source: trunk/source/geometry/navigation/src/G4PropagatorInField.cc @ 908

Last change on this file since 908 was 850, checked in by garnier, 16 years ago

geant4.8.2 beta

File size: 57.0 KB
Line 
1//
2// ********************************************************************
3// * License and Disclaimer                                           *
4// *                                                                  *
5// * The  Geant4 software  is  copyright of the Copyright Holders  of *
6// * the Geant4 Collaboration.  It is provided  under  the terms  and *
7// * conditions of the Geant4 Software License,  included in the file *
8// * LICENSE and available at  http://cern.ch/geant4/license .  These *
9// * include a list of copyright holders.                             *
10// *                                                                  *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work  make  any representation or  warranty, express or implied, *
14// * regarding  this  software system or assume any liability for its *
15// * use.  Please see the license in the file  LICENSE  and URL above *
16// * for the full disclaimer and the limitation of liability.         *
17// *                                                                  *
18// * This  code  implementation is the result of  the  scientific and *
19// * technical work of the GEANT4 collaboration.                      *
20// * By using,  copying,  modifying or  distributing the software (or *
21// * any work based  on the software)  you  agree  to acknowledge its *
22// * use  in  resulting  scientific  publications,  and indicate your *
23// * acceptance of all terms of the Geant4 Software license.          *
24// ********************************************************************
25//
26//
27// $Id: G4PropagatorInField.cc,v 1.43 2008/05/28 09:12:23 tnikitin Exp $
28// GEANT4 tag $Name: HEAD $
29//
30//
31//  This class implements an algorithm to track a particle in a
32//  non-uniform magnetic field. It utilises an ODE solver (with
33//  the Runge - Kutta method) to evolve the particle, and drives it
34//  until the particle has traveled a set distance or it enters a new
35//  volume.
36//                                                                     
37// 14.10.96 John Apostolakis,   design and implementation
38// 17.03.97 John Apostolakis,   renaming new set functions being added
39//
40// ---------------------------------------------------------------------------
41
42#include "G4PropagatorInField.hh"
43#include "G4ios.hh"
44#include <iomanip>
45
46#include "G4ThreeVector.hh"
47#include "G4VPhysicalVolume.hh"
48#include "G4Navigator.hh"
49#include "G4GeometryTolerance.hh"
50#include "G4VCurvedTrajectoryFilter.hh"
51#include "G4ChordFinder.hh"
52
53///////////////////////////////////////////////////////////////////////////
54//
55// Constructors and destructor
56
57G4PropagatorInField::G4PropagatorInField( G4Navigator    *theNavigator, 
58                                          G4FieldManager *detectorFieldMgr )
59  : fDetectorFieldMgr(detectorFieldMgr), 
60    fCurrentFieldMgr(detectorFieldMgr), 
61    fNavigator(theNavigator),
62    End_PointAndTangent(G4ThreeVector(0.,0.,0.),
63                        G4ThreeVector(0.,0.,0.),0.0,0.0,0.0,0.0,0.0),
64    fParticleIsLooping(false),
65    fVerboseLevel(0),
66    fMax_loop_count(1000),
67    fNoZeroStep(0), 
68    fCharge(0.0), fInitialMomentumModulus(0.0), fMass(0.0),
69    fUseSafetyForOptimisation(true),   // (false) is less sensitive to incorrect safety
70    fSetFieldMgr(false),
71    fpTrajectoryFilter( 0 )
72{
73  if(fDetectorFieldMgr) { fEpsilonStep = fDetectorFieldMgr->GetMaximumEpsilonStep();}
74  else                  { fEpsilonStep= 1.0e-5; } 
75  fActionThreshold_NoZeroSteps = 2; 
76  fSevereActionThreshold_NoZeroSteps = 10; 
77  fAbandonThreshold_NoZeroSteps = 50; 
78  fFull_CurveLen_of_LastAttempt = -1; 
79  fLast_ProposedStepLength = -1;
80  fLargestAcceptableStep = 1000.0 * meter;
81
82  fPreviousSftOrigin= G4ThreeVector(0.,0.,0.);
83  fPreviousSafety= 0.0;
84  kCarTolerance = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
85  //
86  fUseBrentLocator=true;
87  // In case of too slow progress in finding Intersection Point
88  // intermediates Points on the Track must be stored.
89  // Initialise the array of Pointers [max_depth+1] to do this 
90  G4ThreeVector zeroV(0.0,0.0,0.0);
91  for (G4int idepth=0; idepth<max_depth+1; idepth++ )
92  {
93    ptrInterMedFT[ idepth ] = new G4FieldTrack( zeroV, zeroV, 0., 0., 0., 0.);
94  }
95  // Counter for Maximum Number Of Trial before Intersection Found
96    maxNumberOfStepsForIntersection=0;
97 // Counter for Number Of Calls to ReIntegrationEndPoint Method
98    maxNumberOfCallsToReIntegration=0; 
99    maxNumberOfCallsToReIntegration_depth=0; 
100}
101
102G4PropagatorInField::~G4PropagatorInField()
103{
104  for ( G4int idepth=0; idepth<max_depth+1; idepth++)
105  {
106    delete ptrInterMedFT[idepth];
107  }
108  if(fVerboseLevel>0){
109  G4cout<<"G4PropagatorInField::Location with Max Number of Steps="
110       << maxNumberOfStepsForIntersection<<G4endl;
111  G4cout<<"G4PropagatorInField::ReIntegrateEndPoint was called "<<
112    maxNumberOfCallsToReIntegration<<" times and for depth algorithm "<<
113    maxNumberOfCallsToReIntegration_depth<<" times"<<G4endl;
114  }
115}
116
117///////////////////////////////////////////////////////////////////////////
118//
119// Compute the next geometric Step
120
121G4double
122G4PropagatorInField::ComputeStep(
123                G4FieldTrack&      pFieldTrack,
124                G4double           CurrentProposedStepLength,
125                G4double&          currentSafety,                // IN/OUT
126                G4VPhysicalVolume* pPhysVol)
127{
128 
129  // If CurrentProposedStepLength is too small for finding Chords
130  // then return with no action (for now - TODO: some action)
131  //
132  if(CurrentProposedStepLength<kCarTolerance)
133  {
134    return kInfinity;
135  }
136
137  // Introducing smooth trajectory display (jacek 01/11/2002)
138  //
139  if (fpTrajectoryFilter)
140  {
141    fpTrajectoryFilter->CreateNewTrajectorySegment();
142  }
143
144  // Parameters for adaptive Runge-Kutta integration
145 
146  G4double      h_TrialStepSize;        // 1st Step Size
147  G4double      TruePathLength = CurrentProposedStepLength;
148  G4double      StepTaken = 0.0; 
149  G4double      s_length_taken, epsilon ; 
150  G4bool        intersects;
151  G4bool        first_substep = true;
152
153  G4double      NewSafety;
154  fParticleIsLooping = false;
155
156  // If not yet done,
157  //   Set the field manager to the local  one if the volume has one,
158  //                      or to the global one if not
159  //
160  if( !fSetFieldMgr ) fCurrentFieldMgr= FindAndSetFieldManager( pPhysVol ); 
161  // For the next call, the field manager must again be set
162  fSetFieldMgr= false;
163
164  GetChordFinder()->SetChargeMomentumMass(fCharge, fInitialMomentumModulus, fMass); 
165 
166  G4FieldTrack  CurrentState(pFieldTrack);
167  G4FieldTrack  OriginalState = CurrentState;
168
169  // If the Step length is "infinite", then an approximate-maximum Step
170  // length (used to calculate the relative accuracy) must be guessed.
171  //
172  if( CurrentProposedStepLength >= fLargestAcceptableStep )
173  {
174    G4ThreeVector StartPointA, VelocityUnit;
175    StartPointA  = pFieldTrack.GetPosition();
176    VelocityUnit = pFieldTrack.GetMomentumDir();
177
178    G4double trialProposedStep = 1.e2 * ( 10.0 * cm + 
179      fNavigator->GetWorldVolume()->GetLogicalVolume()->
180                  GetSolid()->DistanceToOut(StartPointA, VelocityUnit) );
181    CurrentProposedStepLength= std::min( trialProposedStep,
182                                           fLargestAcceptableStep ); 
183  }
184  epsilon = GetDeltaOneStep() / CurrentProposedStepLength;
185  // G4double raw_epsilon= epsilon;
186  G4double epsilonMin= fCurrentFieldMgr->GetMinimumEpsilonStep();
187  G4double epsilonMax= fCurrentFieldMgr->GetMaximumEpsilonStep();; 
188  if( epsilon < epsilonMin ) epsilon = epsilonMin;
189  if( epsilon > epsilonMax ) epsilon = epsilonMax;
190  SetEpsilonStep( epsilon );
191
192  // G4cout << "G4PiF: Epsilon of current step - raw= " << raw_epsilon
193  //        << " final= " << epsilon << G4endl;
194
195  //  Shorten the proposed step in case of earlier problems (zero steps)
196  //
197  if( fNoZeroStep > fActionThreshold_NoZeroSteps )
198  {
199    G4double stepTrial;
200
201    stepTrial= fFull_CurveLen_of_LastAttempt; 
202    if( (stepTrial <= 0.0) && (fLast_ProposedStepLength > 0.0) ) 
203      stepTrial= fLast_ProposedStepLength; 
204
205    G4double decreaseFactor = 0.9; // Unused default
206    if(   (fNoZeroStep < fSevereActionThreshold_NoZeroSteps)
207       && (stepTrial > 1000.0*kCarTolerance) )
208    {
209      // Ensure quicker convergence
210      //
211      decreaseFactor= 0.1;
212    } 
213    else
214    {
215      // We are in significant difficulties, probably at a boundary that
216      // is either geometrically sharp or between very different materials.
217      // Careful decreases to cope with tolerance are required.
218      //
219      if( stepTrial > 1000.0*kCarTolerance )
220        decreaseFactor = 0.25;     // Try slow decreases
221      else if( stepTrial > 100.0*kCarTolerance )
222        decreaseFactor= 0.5;       // Try slower decreases
223      else if( stepTrial > 10.0*kCarTolerance )
224        decreaseFactor= 0.75;      // Try even slower decreases
225      else
226        decreaseFactor= 0.9;       // Try very slow decreases
227     }
228     stepTrial *= decreaseFactor;
229
230#ifdef G4DEBUG_FIELD
231     PrintStepLengthDiagnostic(CurrentProposedStepLength, decreaseFactor,
232                               stepTrial, pFieldTrack);
233#endif
234     if( stepTrial == 0.0 )
235     {
236       G4cout << " G4PropagatorInField::ComputeStep "
237              << " Particle abandoned due to lack of progress in field."
238              << G4endl
239              << " Properties : " << pFieldTrack << " "
240              << G4endl;
241       G4cerr << " G4PropagatorInField::ComputeStep "
242              << "  ERROR : attempting a zero step= " << stepTrial << G4endl
243              << " while attempting to progress after " << fNoZeroStep
244              << " trial steps.  Will abandon step." << G4endl;
245         fParticleIsLooping= true;
246         return 0;  // = stepTrial;
247     }
248     if( stepTrial < CurrentProposedStepLength )
249       CurrentProposedStepLength = stepTrial;
250  }
251  fLast_ProposedStepLength = CurrentProposedStepLength;
252
253  G4int do_loop_count = 0; 
254  do
255  { 
256    G4FieldTrack SubStepStartState = CurrentState;
257    G4ThreeVector SubStartPoint = CurrentState.GetPosition(); 
258
259    if( !first_substep) {
260      fNavigator->LocateGlobalPointWithinVolume( SubStartPoint );
261    }
262
263    // How far to attempt to move the particle !
264    //
265    h_TrialStepSize = CurrentProposedStepLength - StepTaken;
266
267    // Integrate as far as "chord miss" rule allows.
268    //
269    s_length_taken = GetChordFinder()->AdvanceChordLimited( 
270                             CurrentState,    // Position & velocity
271                             h_TrialStepSize,
272                             fEpsilonStep,
273                             fPreviousSftOrigin,
274                             fPreviousSafety
275                             );
276    //  CurrentState is now updated with the final position and velocity.
277
278    fFull_CurveLen_of_LastAttempt = s_length_taken;
279
280    G4ThreeVector  EndPointB = CurrentState.GetPosition(); 
281    G4ThreeVector  InterSectionPointE;
282    G4double       LinearStepLength;
283 
284    // Intersect chord AB with geometry
285    intersects= IntersectChord( SubStartPoint, EndPointB, 
286                                NewSafety,     LinearStepLength, 
287                                InterSectionPointE );
288    // E <- Intersection Point of chord AB and either volume A's surface
289    //                                  or a daughter volume's surface ..
290
291    if( first_substep ) { 
292       currentSafety = NewSafety;
293    } // Updating safety in other steps is potential future extention
294
295    if( intersects )
296    {
297       G4FieldTrack IntersectPointVelct_G(CurrentState);  // FT-Def-Construct
298
299       // Find the intersection point of AB true path with the surface
300       //   of vol(A), if it exists. Start with point E as first "estimate".
301       G4bool recalculatedEndPt= false;
302       G4bool found_intersection = 
303         LocateIntersectionPoint( SubStepStartState, CurrentState, 
304                                  InterSectionPointE, IntersectPointVelct_G,
305                                  recalculatedEndPt);
306       // G4cout<<"In Locate"<<recalculatedEndPt<<"  and V"<<IntersectPointVelct_G.GetPosition()<<G4endl;
307       intersects = intersects && found_intersection;
308       if( found_intersection ) {       
309          End_PointAndTangent= IntersectPointVelct_G;  // G is our EndPoint ...
310          StepTaken = TruePathLength = IntersectPointVelct_G.GetCurveLength()
311                                      - OriginalState.GetCurveLength();
312       } else {
313          // intersects= false;          // "Minor" chords do not intersect
314          if( recalculatedEndPt ){
315             CurrentState= IntersectPointVelct_G; 
316          }
317       }
318    }
319    if( !intersects )
320    {
321      StepTaken += s_length_taken; 
322      // For smooth trajectory display (jacek 01/11/2002)
323      if (fpTrajectoryFilter) {
324        fpTrajectoryFilter->TakeIntermediatePoint(CurrentState.GetPosition());
325      }
326    }
327    first_substep = false;
328
329#ifdef G4DEBUG_FIELD
330    if( fNoZeroStep > fActionThreshold_NoZeroSteps ) {
331      printStatus( SubStepStartState,  // or OriginalState,
332                   CurrentState,  CurrentProposedStepLength, 
333                   NewSafety,     do_loop_count,  pPhysVol );
334    }
335#endif
336#ifdef G4VERBOSE
337    if( (fVerboseLevel > 1) && (do_loop_count > fMax_loop_count-10 )) {
338      if( do_loop_count == fMax_loop_count-9 ){
339        G4cout << "G4PropagatorInField::ComputeStep "
340               << " Difficult track - taking many sub steps." << G4endl;
341      }
342      printStatus( SubStepStartState, CurrentState, CurrentProposedStepLength, 
343                   NewSafety, do_loop_count, pPhysVol );
344    }
345#endif
346
347    do_loop_count++;
348
349  } while( (!intersects )
350        && (StepTaken + kCarTolerance < CurrentProposedStepLength) 
351        && ( do_loop_count < fMax_loop_count ) );
352
353  if( do_loop_count >= fMax_loop_count  )
354  {
355    fParticleIsLooping = true;
356
357    if ( fVerboseLevel > 0 ){
358       G4cout << "G4PropagateInField: Killing looping particle " 
359              // << " of " << energy  << " energy "
360              << " after " << do_loop_count << " field substeps "
361              << " totaling " << StepTaken / mm << " mm " ;
362       if( pPhysVol )
363          G4cout << " in the volume " << pPhysVol->GetName() ; 
364       else
365         G4cout << " in unknown or null volume. " ; 
366       G4cout << G4endl;
367    }
368  }
369
370  if( !intersects )
371  {
372    // Chord AB or "minor chords" do not intersect
373    // B is the endpoint Step of the current Step.
374    //
375    End_PointAndTangent = CurrentState; 
376    TruePathLength = StepTaken;
377  }
378 
379  // Set pFieldTrack to the return value
380  //
381  pFieldTrack = End_PointAndTangent;
382
383#ifdef G4VERBOSE
384  // Check that "s" is correct
385  //
386  if( std::fabs(OriginalState.GetCurveLength() + TruePathLength
387      - End_PointAndTangent.GetCurveLength()) > 3.e-4 * TruePathLength )
388  {
389    G4cerr << " ERROR - G4PropagatorInField::ComputeStep():" << G4endl
390           << " Curve length mis-match, is advancement wrong ? " << G4endl;
391    G4cerr << " The curve length of the endpoint should be: " 
392           << OriginalState.GetCurveLength() + TruePathLength << G4endl
393           << " and it is instead: "
394           << End_PointAndTangent.GetCurveLength() << "." << G4endl
395           << " A difference of: "
396           << OriginalState.GetCurveLength() + TruePathLength
397              - End_PointAndTangent.GetCurveLength() << G4endl;
398    G4cerr << " Original state= " << OriginalState   << G4endl
399           << " Proposed state= " << End_PointAndTangent << G4endl;
400    G4Exception("G4PropagatorInField::ComputeStep()", "IncorrectProposedEndPoint",
401                FatalException, 
402                "Curve length mis-match between original state and proposed endpoint of propagation.");
403  }
404#endif
405
406  // In particular anomalous cases, we can get repeated zero steps
407  // In order to correct this efficiently, we identify these cases
408  // and only take corrective action when they occur.
409  //
410  if( TruePathLength < 0.5*kCarTolerance ) 
411    fNoZeroStep++;
412  else
413    fNoZeroStep = 0;
414
415  if( fNoZeroStep > fAbandonThreshold_NoZeroSteps ) { 
416     fParticleIsLooping = true;
417     G4cout << " WARNING - G4PropagatorInField::ComputeStep():" << G4endl
418            << " Zero progress for "  << fNoZeroStep << " attempted steps." 
419            << G4endl;
420     G4cout << "Proposed Step is "<<CurrentProposedStepLength <<" but Step Taken is "<< fFull_CurveLen_of_LastAttempt <<G4endl;
421     G4cout << "For Particle with Charge ="<<fCharge
422            << " Momentum="<< fInitialMomentumModulus<<" Mass="<< fMass<<G4endl;
423       if( pPhysVol )
424          G4cout << " in the volume " << pPhysVol->GetName() ; 
425       else
426         G4cout << " in unknown or null volume. " ; 
427       G4cout << G4endl;
428     if ( fVerboseLevel > 2 )
429       G4cout << " Particle that is stuck will be killed." << G4endl;
430     fNoZeroStep = 0; 
431  }
432 
433  return TruePathLength;
434}
435
436// --------------------------------------------------------------------------
437// G4bool
438// G4PropagatorInField::LocateIntersectionPoint(
439//   const G4FieldTrack&       CurveStartPointVelocity,   //  A
440//   const G4FieldTrack&       CurveEndPointVelocity,     //  B
441//   const G4ThreeVector&      TrialPoint,                //  E
442//         G4FieldTrack&       IntersectedOrRecalculated  // Output
443//         G4bool&             recalculated)              // Out
444// --------------------------------------------------------------------------
445//
446// Function that returns the intersection of the true path with the surface
447// of the current volume (either the external one or the inner one with one
448// of the daughters
449//
450//     A = Initial point
451//     B = another point
452//
453// Both A and B are assumed to be on the true path.
454//
455//     E is the first point of intersection of the chord AB with
456//     a volume other than A  (on the surface of A or of a daughter)
457//
458// Convention of Use :
459//     i) If it returns "true", then IntersectionPointVelocity is set
460//       to the approximate intersection point.
461//    ii) If it returns "false", no intersection was found.
462//          The validity of IntersectedOrRecalculated depends on 'recalculated'
463//        a) if latter is false, then IntersectedOrRecalculated is invalid.
464//        b) if latter is true,  then IntersectedOrRecalculated is
465//             the new endpoint, due to a re-integration.
466// --------------------------------------------------------------------------
467
468G4bool
469G4PropagatorInField::LocateIntersectionPoint( 
470  const   G4FieldTrack&       CurveStartPointVelocity,   //  A
471  const   G4FieldTrack&       CurveEndPointVelocity,     //  B
472  const   G4ThreeVector&      TrialPoint,                //  E
473          G4FieldTrack&       IntersectedOrRecalculatedFT, // Out: point found
474          G4bool&             recalculatedEndPoint)        // Out:
475{
476  // Find Intersection Point ( A, B, E )  of true path AB - start at E.
477
478  G4bool found_approximate_intersection = false;
479  G4bool there_is_no_intersection       = false;
480 
481  G4FieldTrack  CurrentA_PointVelocity = CurveStartPointVelocity; 
482  G4FieldTrack  CurrentB_PointVelocity = CurveEndPointVelocity;
483  G4ThreeVector CurrentE_Point = TrialPoint;
484  G4FieldTrack ApproxIntersecPointV(CurveEndPointVelocity); // FT-Def-Construct
485  G4double    NewSafety= -0.0;
486 
487  G4bool final_section= true;  // Shows whether current section is last
488                               // (i.e. B=full end)
489  G4bool first_section=true;
490  recalculatedEndPoint= false; 
491 
492  G4bool restoredFullEndpoint= false;
493
494  G4int substep_no = 0;
495   
496  // Limits for substep number
497  //
498  const G4int max_substeps=   10000;  // Test 120  (old value 100 )
499  const G4int warn_substeps=   1000;  //      100 
500
501  // Statistics for substeps
502  //
503  static G4int max_no_seen= -1; 
504  static G4int trigger_substepno_print= warn_substeps - 20 ;
505 
506  //-------------------------------------------------------------------------- 
507  //  Algoritm for the case if progress in founding intersection is too slow.
508  //  Process is defined too slow if after N=param_substeps advances on the
509  //  path, it will be only 'fraction_done' of the total length.
510  //  In this case the remaining length is divided in two half and
511  //  the loop is restarted for each half. 
512  //  If progress is still too slow, the division in two halfs continue
513  //  until 'max_depth'.
514  //--------------------------------------------------------------------------
515  G4double count_did_len=0.;
516  G4double count_all_len=0;
517  G4int param_substeps=100;//Test value for the maximum number of substeps
518  if(!fUseBrentLocator)  param_substeps=10;// Reduced value for the maximum number
519
520  const G4double fraction_done=0.3;
521
522  G4bool Second_half=false;      // First half or second half of divided step
523
524  // We need to know this for the 'final_section':
525  // real 'final_section' or first half 'final_section'
526  // In algorithm it is considered that the 'Second_half' is true
527  // and it becomes false only if we are in the first-half of level
528  // depthness or if we are in the first section
529
530  G4int depth=0; // Depth counts how many subdivisions of initial step made
531
532#ifdef G4DEBUG_FIELD
533  static G4double tolerance= 1.0e-8; 
534  G4ThreeVector  StartPosition= CurveStartPointVelocity.GetPosition(); 
535  if( (TrialPoint - StartPosition).mag() < tolerance * mm ) 
536  {
537     G4cerr << "WARNING - G4PropagatorInField::LocateIntersectionPoint()"
538            << G4endl
539            << "          Intermediate F point is on top of starting point A."
540            << G4endl;
541     G4Exception("G4PropagatorInField::LocateIntersectionPoint()", 
542                 "IntersectionPointIsAtStart", JustWarning,
543                 "Intersection point F is exactly at start point A." ); 
544  }
545#endif
546
547  // Intermediates Points on the Track = Subdivided Points must be stored.
548  // Give the initial values to 'InterMedFt'
549  // Important is 'ptrInterMedFT[0]', it saves the 'EndCurvePoint'
550  //
551  *ptrInterMedFT[0] = CurveEndPointVelocity;
552  for (G4int idepth=1; idepth<max_depth+1; idepth++ )
553  {
554    *ptrInterMedFT[idepth]=CurveStartPointVelocity;
555  }
556
557  // 'SubStartPoint' is needed to calculate the length of the divided step
558  //
559  G4FieldTrack SubStart_PointVelocity = CurveStartPointVelocity;
560   
561  do
562  {
563    G4int substep_no_p = 0;
564    G4bool sub_final_section = false; // the same as final_section,
565                                      // but for 'sub_section'
566    do // REPEAT param
567    {
568      G4ThreeVector Point_A = CurrentA_PointVelocity.GetPosition(); 
569      G4ThreeVector Point_B = CurrentB_PointVelocity.GetPosition();
570       
571      // F = a point on true AB path close to point E
572      // (the closest if possible)
573      //
574      if((!fUseBrentLocator)||(substep_no_p==0)){
575       ApproxIntersecPointV = GetChordFinder()
576                             ->ApproxCurvePointV( CurrentA_PointVelocity, 
577                                                  CurrentB_PointVelocity, 
578                                                  CurrentE_Point,
579                                                  fEpsilonStep );
580      //  The above method is the key & most intuitive part ...
581      }
582#ifdef G4DEBUG_FIELD
583      if( ApproxIntersecPointV.GetCurveLength() > 
584          CurrentB_PointVelocity.GetCurveLength() * (1.0 + tolerance) )
585      {
586        G4cerr << "ERROR - G4PropagatorInField::LocateIntersectionPoint()"
587               << G4endl
588               << "        Intermediate F point is more advanced than"
589               << " endpoint B." << G4endl;
590        G4Exception("G4PropagatorInField::LocateIntersectionPoint()", 
591                    "IntermediatePointConfusion", FatalException,
592                    "Intermediate F point is past end B point" ); 
593      }
594#endif
595
596      G4ThreeVector CurrentF_Point= ApproxIntersecPointV.GetPosition();
597      if(substep_no> maxNumberOfStepsForIntersection)maxNumberOfStepsForIntersection=substep_no; 
598      // First check whether EF is small - then F is a good approx. point
599      // Calculate the length and direction of the chord AF
600      //
601      G4ThreeVector  ChordEF_Vector = CurrentF_Point - CurrentE_Point;
602
603      if ( ChordEF_Vector.mag2() <= sqr(GetDeltaIntersection()) )
604      {
605        found_approximate_intersection = true;
606        // Create the "point" return value
607        //
608        IntersectedOrRecalculatedFT = ApproxIntersecPointV;
609        IntersectedOrRecalculatedFT.SetPosition( CurrentE_Point );
610       
611        // Note: in order to return a point on the boundary,
612        //       we must return E. But it is F on the curve.
613        //       So we must "cheat": we are using the position at point E
614        //       and the velocity at point F !!!
615        //
616        // This must limit the length we can allow for displacement!
617      }
618      else  // E is NOT close enough to the curve (ie point F)
619      {
620        // Check whether any volumes are encountered by the chord AF
621        // ---------------------------------------------------------
622        // First relocate to restore any Voxel etc information
623        // in the Navigator before calling ComputeStep()
624        //
625        fNavigator->LocateGlobalPointWithinVolume( Point_A );
626
627        G4ThreeVector PointG;   // Candidate intersection point
628        G4double stepLengthAF; 
629        G4bool Intersects_AF = IntersectChord( Point_A,   CurrentF_Point,
630                                               NewSafety, stepLengthAF,
631                                               PointG );
632        if( Intersects_AF )
633        {
634          if(fUseBrentLocator){
635           
636            G4FieldTrack EndPoint=ApproxIntersecPointV;
637            ApproxIntersecPointV= GetChordFinder()->ApproxCurvePointS(
638                   CurrentA_PointVelocity,CurrentB_PointVelocity,
639                   CurrentE_Point,CurrentF_Point,PointG,true,fEpsilonStep);
640            CurrentB_PointVelocity =  EndPoint;
641            CurrentE_Point = PointG;
642          // By moving point B, must take care if current
643          // AF has no intersection to try current FB!!
644          //
645          final_section= false; 
646
647          }
648          else{
649          // G is our new Candidate for the intersection point.
650          // It replaces  "E" and we will repeat the test to see if
651          // it is a good enough approximate point for us.
652          //       B    <- F
653          //       E    <- G
654
655          CurrentB_PointVelocity = ApproxIntersecPointV;
656          CurrentE_Point = PointG; 
657     
658          // By moving point B, must take care if current
659          // AF has no intersection to try current FB!!
660          //
661          final_section= false; 
662          }
663#ifdef G4VERBOSE
664          if( fVerboseLevel > 3 )
665          {
666            G4cout << "G4PiF::LI> Investigating intermediate point"
667                   << " at s=" << ApproxIntersecPointV.GetCurveLength()
668                   << " on way to full s="
669                   << CurveEndPointVelocity.GetCurveLength() << G4endl;
670          }
671#endif
672        }
673        else  // not Intersects_AF
674        { 
675          // In this case:
676          // There is NO intersection of AF with a volume boundary.
677          // We must continue the search in the segment FB!
678          //
679          fNavigator->LocateGlobalPointWithinVolume( CurrentF_Point );
680
681          G4double stepLengthFB;
682          G4ThreeVector PointH;
683
684          // Check whether any volumes are encountered by the chord FB
685          // ---------------------------------------------------------
686
687          G4bool Intersects_FB = IntersectChord( CurrentF_Point, Point_B, 
688                                                 NewSafety, stepLengthFB,
689                                                 PointH );
690          if( Intersects_FB )
691          {
692            if(fUseBrentLocator){
693               CurrentA_PointVelocity = ApproxIntersecPointV;
694               ApproxIntersecPointV= GetChordFinder()->ApproxCurvePointS(
695                   CurrentA_PointVelocity,CurrentB_PointVelocity,
696                   CurrentE_Point,Point_A,PointH,false,fEpsilonStep);
697               CurrentE_Point = PointH;
698           }
699           else{
700 
701            // There is an intersection of FB with a volume boundary
702            // H <- First Intersection of Chord FB
703
704            // H is our new Candidate for the intersection point.
705            // It replaces  "E" and we will repeat the test to see if
706            // it is a good enough approximate point for us.
707
708            // Note that F must be in volume volA  (the same as A)
709            // (otherwise AF would meet a volume boundary!)
710            //   A    <- F
711            //   E    <- H
712
713            CurrentA_PointVelocity = ApproxIntersecPointV;
714            CurrentE_Point = PointH;
715           }
716          }
717          else  // not Intersects_FB
718          {
719            // There is NO intersection of FB with a volume boundary
720
721            if( final_section  )
722            {
723              // If B is the original endpoint, this means that whatever
724              // volume(s) intersected the original chord, none touch the
725              // smaller chords we have used.
726              // The value of 'IntersectedOrRecalculatedFT' returned is
727              // likely not valid
728
729              // Check on real final_section or SubEndSection
730              //
731              if( ((Second_half)&&(depth==0)) || (first_section) )
732              {
733                there_is_no_intersection = true;   // real final_section
734              }
735              else
736              {
737                // end of subsection, not real final section
738                // exit from the and go to the depth-1 level
739
740                substep_no_p = param_substeps+2;  // exit from the loop
741
742                // but 'Second_half' is still true because we need to find
743                // the 'CurrentE_point' for the next loop
744                //
745                Second_half = true; 
746                sub_final_section = true;
747           
748              }
749            }
750            else
751            {
752              // We must restore the original endpoint
753
754              CurrentA_PointVelocity = CurrentB_PointVelocity;  // Got to B
755              CurrentB_PointVelocity = CurveEndPointVelocity;
756              restoredFullEndpoint = true;
757            }
758          } // Endif (Intersects_FB)
759        } // Endif (Intersects_AF)
760
761        // Ensure that the new endpoints are not further apart in space
762        // than on the curve due to different errors in the integration
763        //
764        G4double linDistSq, curveDist; 
765        linDistSq = ( CurrentB_PointVelocity.GetPosition() 
766                    - CurrentA_PointVelocity.GetPosition() ).mag2(); 
767        curveDist = CurrentB_PointVelocity.GetCurveLength()
768                    - CurrentA_PointVelocity.GetCurveLength();
769         if( curveDist*curveDist*(1+2*fEpsilonStep ) < linDistSq )
770        {
771          // Re-integrate to obtain a new B
772          //
773          G4FieldTrack newEndPointFT=
774                  ReEstimateEndpoint( CurrentA_PointVelocity,
775                                      CurrentB_PointVelocity,
776                                      linDistSq,    // to avoid recalculation
777                                      curveDist );
778          G4FieldTrack oldPointVelB = CurrentB_PointVelocity; 
779          CurrentB_PointVelocity = newEndPointFT;
780          maxNumberOfCallsToReIntegration= maxNumberOfCallsToReIntegration+1;
781          #ifdef G4DEBUG_FIELD
782          G4cout<<"G4PIF::Call ReIntEnd1 linD="<<std::sqrt(linDistSq)<<" curve="<<curveDist<<" n="<<substep_no<<G4endl;
783          G4cout<<"G4PIF::Call ReIntEnd2 IntersectAF="<< Intersects_AF<<" final_section="<<final_section<<G4endl;
784          #endif
785          if( (final_section)&&(Second_half)&&(depth==0) ) // real final section
786          {
787            recalculatedEndPoint = true;
788            IntersectedOrRecalculatedFT = newEndPointFT;
789              // So that we can return it, if it is the endpoint!
790          }
791         
792        }
793   
794        if( curveDist < 0.0 )
795        {
796          G4cerr << "ERROR - G4PropagatorInField::LocateIntersectionPoint()"
797                 << G4endl
798                 << "        Error in advancing propagation." << G4endl;
799          fVerboseLevel = 5; // Print out a maximum of information
800          printStatus( CurrentA_PointVelocity,  CurrentB_PointVelocity,
801                       -1.0, NewSafety,  substep_no, 0 );
802          G4cerr << "        Point A (start) is " << CurrentA_PointVelocity
803                 << G4endl;
804          G4cerr << "        Point B (end)   is " << CurrentB_PointVelocity
805                 << G4endl;
806          G4cerr << "        Curve distance is " << curveDist << G4endl;
807          G4cerr << G4endl
808                 << "The final curve point is not further along"
809                 << " than the original!" << G4endl;
810          if( recalculatedEndPoint )
811          {
812            G4cerr << "Recalculation of EndPoint was called with fEpsStep= "
813                   << fEpsilonStep << G4endl;
814          }
815          G4cerr.precision(20);
816          G4cerr << " Point A (Curve start)   is " << CurveStartPointVelocity
817                 << G4endl;
818          G4cerr << " Point B (Curve   end)   is " << CurveEndPointVelocity
819                 << G4endl;
820          G4cerr << " Point A (Current start) is " << CurrentA_PointVelocity
821                 << G4endl;
822          G4cerr << " Point B (Current end)   is " << CurrentB_PointVelocity
823                 << G4endl;
824          G4cerr << " Point S (Sub start)     is " << SubStart_PointVelocity
825                 << G4endl;
826          G4cerr << " Point E (Trial Point)   is " << CurrentE_Point
827                 << G4endl;
828          G4cerr << " Point F (Intersection)  is " << ApproxIntersecPointV
829                 << G4endl;
830          G4cerr << "        LocateIntersection parameters are : Substep no= "
831                 << substep_no << G4endl;
832          G4cerr << "        Substep depth no= "<< substep_no_p  << " Depth= "
833                 << depth << G4endl;
834          G4cerr << "        did_len= "<< count_did_len  << " all_len= "
835                 << count_all_len << G4endl;
836          G4Exception("G4PropagatorInField::LocateIntersectionPoint()",
837                      "FatalError", FatalException,
838                      "Error in advancing propagation.");
839        }
840       
841        if(restoredFullEndpoint)
842        {
843          final_section = restoredFullEndpoint;
844          restoredFullEndpoint = false;
845        }
846      } // EndIf ( E is close enough to the curve, ie point F. )
847        // tests ChordAF_Vector.mag() <= maximum_lateral_displacement
848
849#ifdef G4DEBUG_LOCATE_INTERSECTION 
850      if( substep_no >= trigger_substepno_print )
851      {
852        G4cout << "Difficulty in converging in "
853               << "G4PropagatorInField::LocateIntersectionPoint():"
854               << G4endl
855               << "    Substep no = " << substep_no << G4endl;
856        if( substep_no == trigger_substepno_print )
857        {
858          printStatus( CurveStartPointVelocity, CurveEndPointVelocity,
859                       -1.0, NewSafety, 0, 0);
860        }
861        G4cout << " State of point A: "; 
862        printStatus( CurrentA_PointVelocity, CurrentA_PointVelocity,
863                     -1.0, NewSafety, substep_no-1, 0);
864        G4cout << " State of point B: "; 
865        printStatus( CurrentA_PointVelocity, CurrentB_PointVelocity,
866                     -1.0, NewSafety, substep_no, 0);
867      }
868#endif
869
870      substep_no++; 
871      substep_no_p++;
872
873    } while (  ( ! found_approximate_intersection )
874            && ( ! there_is_no_intersection )     
875            && ( substep_no_p <= param_substeps) );  // UNTIL found or
876                                                     // failed param substep
877    first_section = false;
878
879    if( (!found_approximate_intersection) && (!there_is_no_intersection) )
880    {
881      G4double did_len = std::abs( CurrentA_PointVelocity.GetCurveLength()
882                       - SubStart_PointVelocity.GetCurveLength()); 
883      G4double all_len = std::abs( CurrentB_PointVelocity.GetCurveLength()
884                       - SubStart_PointVelocity.GetCurveLength());
885      count_did_len=did_len;
886      count_all_len=all_len;   
887      G4double stepLengthAB;
888      G4ThreeVector PointGe;
889
890      // Check if progress is too slow and if it possible to go deeper,
891      // then halve the step if so
892      //
893      if( ( ( did_len )<fraction_done*all_len)
894         && (depth<max_depth) && (!sub_final_section) )
895      {
896
897        Second_half=false;
898        depth++;
899
900        G4double Sub_len = (all_len-did_len)/(2.);
901        G4FieldTrack start = CurrentA_PointVelocity;
902        G4MagInt_Driver* integrDriver=GetChordFinder()->GetIntegrationDriver();
903        integrDriver->AccurateAdvance(start, Sub_len, fEpsilonStep);
904        *ptrInterMedFT[depth] = start;
905        CurrentB_PointVelocity = *ptrInterMedFT[depth];
906 
907        // Adjust 'SubStartPoint' to calculate the 'did_length' in next loop
908        //
909        SubStart_PointVelocity = CurrentA_PointVelocity;
910
911        // Find new trial intersection point needed at start of the loop
912        //
913        G4ThreeVector Point_A = CurrentA_PointVelocity.GetPosition();
914        G4ThreeVector SubE_point = CurrentB_PointVelocity.GetPosition();   
915     
916        fNavigator->LocateGlobalPointWithinVolume(Point_A);
917        G4bool Intersects_AB = IntersectChord(Point_A, SubE_point,
918                                              NewSafety, stepLengthAB, PointGe);
919        if(Intersects_AB)
920        {
921          CurrentE_Point = PointGe;
922        }
923        else
924        {
925          // No intersection found for first part of curve
926          // (CurrentA,InterMedPoint[depth]). Go to the second part
927          //
928          Second_half = true;
929        }
930      } // if did_len
931
932      if( (Second_half)&&(depth!=0) )
933      {
934        // Second part of curve (InterMed[depth],Intermed[depth-1])                       )
935        // On the depth-1 level normally we are on the 'second_half'
936
937        Second_half = true;
938
939        //  Find new trial intersection point needed at start of the loop
940        //
941        SubStart_PointVelocity = *ptrInterMedFT[depth];
942        CurrentA_PointVelocity = *ptrInterMedFT[depth];
943        CurrentB_PointVelocity = *ptrInterMedFT[depth-1];
944        // Ensure that the new endpoints are not further apart in space
945        // than on the curve due to different errors in the integration
946        //
947        G4double linDistSq, curveDist; 
948        linDistSq = ( CurrentB_PointVelocity.GetPosition() 
949                    - CurrentA_PointVelocity.GetPosition() ).mag2(); 
950        curveDist = CurrentB_PointVelocity.GetCurveLength()
951                    - CurrentA_PointVelocity.GetCurveLength();
952        if( curveDist*curveDist*(1+2*fEpsilonStep ) < linDistSq )
953        {
954          // Re-integrate to obtain a new B
955          //
956          G4FieldTrack newEndPointFT=
957                  ReEstimateEndpoint( CurrentA_PointVelocity,
958                                      CurrentB_PointVelocity,
959                                      linDistSq,    // to avoid recalculation
960                                      curveDist );
961          G4FieldTrack oldPointVelB = CurrentB_PointVelocity; 
962          CurrentB_PointVelocity = newEndPointFT;
963          maxNumberOfCallsToReIntegration_depth= maxNumberOfCallsToReIntegration_depth+1;
964        }
965
966        G4ThreeVector Point_A    = CurrentA_PointVelocity.GetPosition();
967        G4ThreeVector SubE_point = CurrentB_PointVelocity.GetPosition();   
968        fNavigator->LocateGlobalPointWithinVolume(Point_A);
969        G4bool Intersects_AB = IntersectChord(Point_A, SubE_point, NewSafety,
970                                              stepLengthAB, PointGe);
971        if(Intersects_AB)
972        {
973          CurrentE_Point = PointGe;
974        }
975        else
976        {
977          final_section = true;
978        }
979        depth--;
980      }
981    }  // if(!found_aproximate_intersection)
982
983  } while ( ( ! found_approximate_intersection )
984            && ( ! there_is_no_intersection )     
985            && ( substep_no <= max_substeps) ); // UNTIL found or failed
986
987  if( substep_no > max_no_seen )
988  {
989    max_no_seen = substep_no; 
990    if( max_no_seen > warn_substeps )
991    {
992      trigger_substepno_print = max_no_seen-20; // Want to see last 20 steps
993    } 
994  }
995
996  if(  ( substep_no >= max_substeps)
997      && !there_is_no_intersection
998      && !found_approximate_intersection )
999  {
1000    G4cerr << "WARNING - G4PropagatorInField::LocateIntersectionPoint()"
1001           << G4endl
1002           << "          Convergence is requiring too many substeps: "
1003           << substep_no << G4endl;
1004    G4cerr << "          Abandoning effort to intersect. " << G4endl;
1005    G4cerr << "          Information on start & current step follows in cout."
1006           << G4endl;
1007    G4cout << "WARNING - G4PropagatorInField::LocateIntersectionPoint()"
1008           << G4endl
1009           << "          Convergence is requiring too many substeps: "
1010           << substep_no << G4endl;
1011    G4cout << "          Found intersection = "
1012           << found_approximate_intersection << G4endl
1013           << "          Intersection exists = "
1014           << !there_is_no_intersection << G4endl;
1015    G4cout << "          Start and Endpoint of Requested Step:" << G4endl;
1016    printStatus( CurveStartPointVelocity, CurveEndPointVelocity,
1017                 -1.0, NewSafety, 0, 0);
1018    G4cout << G4endl;
1019    G4cout << "          'Bracketing' starting and endpoint of current Sub-Step"
1020           << G4endl;
1021    printStatus( CurrentA_PointVelocity, CurrentA_PointVelocity,
1022                 -1.0, NewSafety, substep_no-1, 0);
1023    printStatus( CurrentA_PointVelocity, CurrentB_PointVelocity,
1024                 -1.0, NewSafety, substep_no, 0);
1025    G4cout << G4endl;
1026 
1027#ifdef FUTURE_CORRECTION
1028    // Attempt to correct the results of the method // FIX - TODO
1029
1030    if ( ! found_approximate_intersection )
1031    { 
1032      recalculatedEndPoint = true;
1033      // Return the further valid intersection point -- potentially A ??
1034      // JA/19 Jan 2006
1035      IntersectedOrRecalculatedFT = CurrentA_PointVelocity;
1036
1037      G4cout << "WARNING - G4PropagatorInField::LocateIntersectionPoint()"
1038             << G4endl
1039             << "          Did not convergence after " << substep_no
1040             << " substeps." << G4endl;
1041      G4cout << "          The endpoint was adjused to pointA resulting"
1042             << G4endl
1043             << "          from the last substep: " << CurrentA_PointVelocity
1044             << G4endl;
1045    }
1046#endif
1047
1048    G4cout.precision( 10 ); 
1049    G4double done_len = CurrentA_PointVelocity.GetCurveLength(); 
1050    G4double full_len = CurveEndPointVelocity.GetCurveLength();
1051    G4cout << "ERROR - G4PropagatorInField::LocateIntersectionPoint()"
1052           << G4endl
1053           << "        Undertaken only length: " << done_len
1054           << " out of " << full_len << " required." << G4endl;
1055    G4cout << "        Remaining length = " << full_len - done_len << G4endl; 
1056
1057    G4Exception("G4PropagatorInField::LocateIntersectionPoint()",
1058                "UnableToLocateIntersection", FatalException,
1059                "Too many substeps while trying to locate intersection.");
1060  }
1061  else if( substep_no >= warn_substeps )
1062  { 
1063    int oldprc= G4cout.precision( 10 ); 
1064    G4cout << "WARNING - G4PropagatorInField::LocateIntersectionPoint()"
1065           << G4endl
1066           << "          Undertaken length: " 
1067           << CurrentB_PointVelocity.GetCurveLength(); 
1068    G4cout << " - Needed: "  << substep_no << " substeps." << G4endl
1069           << "          Warning level = " << warn_substeps
1070           << " and maximum substeps = " << max_substeps << G4endl;
1071    G4Exception("G4PropagatorInField::LocateIntersectionPoint()",
1072                "DifficultyToLocateIntersection", JustWarning,
1073                "Many substeps while trying to locate intersection.");
1074    G4cout.precision( oldprc ); 
1075  }
1076 
1077  return  !there_is_no_intersection; //  Success or failure
1078}
1079
1080///////////////////////////////////////////////////////////////////////////
1081//
1082// Dumps status of propagator.
1083
1084void
1085G4PropagatorInField::printStatus( const G4FieldTrack&        StartFT,
1086                                  const G4FieldTrack&        CurrentFT, 
1087                                        G4double             requestStep, 
1088                                        G4double             safety,
1089                                        G4int                stepNo, 
1090                                        G4VPhysicalVolume*   startVolume)
1091{
1092  const G4int verboseLevel= fVerboseLevel;
1093  const G4ThreeVector StartPosition       = StartFT.GetPosition();
1094  const G4ThreeVector StartUnitVelocity   = StartFT.GetMomentumDir();
1095  const G4ThreeVector CurrentPosition     = CurrentFT.GetPosition();
1096  const G4ThreeVector CurrentUnitVelocity = CurrentFT.GetMomentumDir();
1097
1098  G4double step_len = CurrentFT.GetCurveLength() - StartFT.GetCurveLength();
1099     
1100  if( ((stepNo == 0) && (verboseLevel <3))
1101      || (verboseLevel >= 3) )
1102  {
1103    static G4int noPrecision= 4;
1104    G4cout.precision(noPrecision);
1105    // G4cout.setf(ios_base::fixed,ios_base::floatfield);
1106    G4cout << std::setw( 6)  << " " 
1107           << std::setw( 25) << " Current Position  and  Direction" << " "
1108           << G4endl; 
1109    G4cout << std::setw( 5) << "Step#" 
1110           << std::setw(10) << "  s  " << " "
1111           << std::setw(10) << "X(mm)" << " "
1112           << std::setw(10) << "Y(mm)" << " " 
1113           << std::setw(10) << "Z(mm)" << " "
1114           << std::setw( 7) << " N_x " << " "
1115           << std::setw( 7) << " N_y " << " "
1116           << std::setw( 7) << " N_z " << " " ;
1117    //            << G4endl;
1118    G4cout     // << " >>> "
1119           << std::setw( 7) << " Delta|N|" << " "
1120      //   << std::setw( 7) << " Delta(N_z) " << " "
1121           << std::setw( 9) << "StepLen" << " " 
1122           << std::setw(12) << "StartSafety" << " " 
1123           << std::setw( 9) << "PhsStep" << " "; 
1124    if( startVolume ) {
1125      G4cout << std::setw(18) << "NextVolume" << " "; 
1126    }
1127    G4cout << G4endl;
1128  }
1129  if((stepNo == 0) && (verboseLevel <=3)){
1130     // Recurse to print the start values
1131     //
1132     printStatus( StartFT, StartFT, -1.0, safety, -1, startVolume);
1133   }
1134   if( verboseLevel <= 3 )
1135   {
1136     if( stepNo >= 0)
1137       G4cout << std::setw( 4) << stepNo << " ";
1138     else
1139       G4cout << std::setw( 5) << "Start" ;
1140     G4cout.precision(8);
1141     G4cout << std::setw(10) << CurrentFT.GetCurveLength() << " "; 
1142     G4cout.precision(8);
1143     G4cout << std::setw(10) << CurrentPosition.x() << " "
1144            << std::setw(10) << CurrentPosition.y() << " "
1145            << std::setw(10) << CurrentPosition.z() << " ";
1146     G4cout.precision(4);
1147     G4cout << std::setw( 7) << CurrentUnitVelocity.x() << " "
1148            << std::setw( 7) << CurrentUnitVelocity.y() << " "
1149            << std::setw( 7) << CurrentUnitVelocity.z() << " ";
1150     //  G4cout << G4endl;
1151     //     G4cout << " >>> " ;
1152     G4cout.precision(3); 
1153     G4cout << std::setw( 7) << CurrentFT.GetMomentum().mag()- StartFT.GetMomentum().mag() << " "; 
1154     //   << std::setw( 7) << CurrentUnitVelocity.z() - InitialUnitVelocity.z() << " ";
1155     G4cout << std::setw( 9) << step_len << " "; 
1156     G4cout << std::setw(12) << safety << " ";
1157     if( requestStep != -1.0 ) 
1158       G4cout << std::setw( 9) << requestStep << " ";
1159     else
1160       G4cout << std::setw( 9) << "Init/NotKnown" << " "; 
1161
1162     if( startVolume != 0)
1163     {
1164       G4cout << std::setw(12) << startVolume->GetName() << " ";
1165     }
1166#if 0
1167     else
1168     {
1169       if( step_len != -1 )
1170         G4cout << std::setw(12) << "OutOfWorld" << " ";
1171       else
1172         G4cout << std::setw(12) << "NotGiven" << " ";
1173     }
1174#endif
1175
1176     G4cout << G4endl;
1177   }
1178   else // if( verboseLevel > 3 )
1179   {
1180     //  Multi-line output
1181       
1182     G4cout << "Step taken was " << step_len 
1183            << " out of PhysicalStep= " <<  requestStep << G4endl;
1184     G4cout << "Final safety is: " << safety << G4endl;
1185
1186     G4cout << "Chord length = " << (CurrentPosition-StartPosition).mag()
1187            << G4endl;
1188     G4cout << G4endl; 
1189   }
1190}
1191
1192///////////////////////////////////////////////////////////////////////////
1193//
1194// Prints Step diagnostics
1195
1196void 
1197G4PropagatorInField::PrintStepLengthDiagnostic(
1198                          G4double CurrentProposedStepLength,
1199                          G4double decreaseFactor,
1200                          G4double stepTrial,
1201                    const G4FieldTrack& )
1202{
1203  G4cout << " PiF: NoZeroStep= " << fNoZeroStep
1204         << " CurrentProposedStepLength= " << CurrentProposedStepLength
1205         << " Full_curvelen_last=" << fFull_CurveLen_of_LastAttempt
1206         << " last proposed step-length= " << fLast_ProposedStepLength
1207         << " decreate factor = " << decreaseFactor
1208         << " step trial = " << stepTrial
1209         << G4endl;
1210}
1211
1212G4bool
1213G4PropagatorInField::IntersectChord( G4ThreeVector  StartPointA, 
1214                                     G4ThreeVector  EndPointB,
1215                                     G4double      &NewSafety,
1216                                     G4double      &LinearStepLength,
1217                                     G4ThreeVector &IntersectionPoint
1218                                   )
1219{
1220    // Calculate the direction and length of the chord AB
1221    G4ThreeVector  ChordAB_Vector = EndPointB - StartPointA;
1222    G4double       ChordAB_Length = ChordAB_Vector.mag();  // Magnitude (norm)
1223    G4ThreeVector  ChordAB_Dir =    ChordAB_Vector.unit();
1224    G4bool intersects;
1225
1226    G4ThreeVector OriginShift = StartPointA - fPreviousSftOrigin ;
1227    G4double      MagSqShift  = OriginShift.mag2() ;
1228    G4double      currentSafety;
1229    G4bool        doCallNav= false;
1230
1231    if( MagSqShift >= sqr(fPreviousSafety) )
1232    {
1233        currentSafety = 0.0 ;
1234    }else{
1235        currentSafety = fPreviousSafety - std::sqrt(MagSqShift) ;
1236    }
1237
1238    if( fUseSafetyForOptimisation && (ChordAB_Length <= currentSafety) )
1239    {
1240       // The Step is guaranteed to be taken
1241
1242       LinearStepLength = ChordAB_Length;
1243       intersects = false;
1244
1245       NewSafety= currentSafety;
1246
1247#if 0 
1248       G4cout << " G4PropagatorInField does not call Navigator::ComputeStep " << G4endl ;
1249       G4cout << "    step= " << LinearStepLength << " safety= " << NewSafety << G4endl;
1250       G4cout << "    safety: Origin = " << fPreviousSftOrigin << " val= " << fPreviousSafety << G4endl;
1251#endif
1252    }
1253    else
1254    {
1255       doCallNav= true; 
1256       // Check whether any volumes are encountered by the chord AB
1257
1258       // G4cout << " G4PropagatorInField calling Navigator::ComputeStep " << G4endl ;
1259
1260       LinearStepLength = 
1261        fNavigator->ComputeStep( StartPointA, ChordAB_Dir,
1262                                 ChordAB_Length, NewSafety );
1263       intersects = (LinearStepLength <= ChordAB_Length); 
1264       // G4Navigator contracts to return k_infinity if len==asked
1265       // and it did not find a surface boundary at that length
1266       LinearStepLength = std::min( LinearStepLength, ChordAB_Length);
1267
1268       // G4cout << " G4PiF got step= " << LinearStepLength << " safety= " << NewSafety << G4endl;
1269
1270       // Save the last calculated safety!
1271       fPreviousSftOrigin = StartPointA;
1272       fPreviousSafety= NewSafety;
1273
1274       if( intersects ){
1275          // Intersection Point of chord AB and either volume A's surface
1276          //                                or a daughter volume's surface ..
1277          IntersectionPoint = StartPointA + LinearStepLength * ChordAB_Dir;
1278       }
1279    }
1280
1281#ifdef DEBUG_INTERSECTS_CHORD
1282    // printIntersection(
1283    // StartPointA, EndPointB, LinearStepLength, IntersectionPoint, NewSafety
1284
1285    G4cout << " G4PropagatorInField::IntersectChord reports " << G4endl;
1286    G4cout << " PiF-IC> "
1287           << "Start="  << std::setw(12) << StartPointA       << " "
1288           << "End= "   << std::setw(8) << EndPointB         << " "
1289           << "StepIn=" << std::setw(8) << LinearStepLength  << " "
1290           << "NewSft=" << std::setw(8) << NewSafety << " " 
1291           << "CallNav=" << doCallNav      << "  "
1292           << "Intersects " << intersects     << "  "; 
1293    if( intersects ) 
1294      G4cout << "IntrPt=" << std::setw(8) << IntersectionPoint << " " ; 
1295    G4cout << G4endl;
1296#endif
1297
1298    return intersects;
1299}
1300
1301// --------------------- oooo000000000000oooo ----------------------------
1302
1303G4FieldTrack G4PropagatorInField::
1304ReEstimateEndpoint( const G4FieldTrack &CurrentStateA, 
1305                    const G4FieldTrack &EstimatedEndStateB,
1306                          G4double      linearDistSq,
1307                          G4double      curveDist
1308                  )
1309{
1310  // G4double checkCurveDist= EstimatedEndStateB.GetCurveLength()
1311  //   - CurrentStateA.GetCurveLength();
1312  // G4double checkLinDistSq= (EstimatedEndStateB.GetPosition()
1313  //                    - CurrentStateA.GetPosition() ).mag2();
1314
1315  G4FieldTrack newEndPoint( CurrentStateA );
1316  G4MagInt_Driver* integrDriver= GetChordFinder()->GetIntegrationDriver(); 
1317
1318  G4FieldTrack retEndPoint( CurrentStateA );
1319  G4bool goodAdvance;
1320  G4int  itrial=0;
1321  const G4int no_trials= 20;
1322
1323  G4double endCurveLen= EstimatedEndStateB.GetCurveLength();
1324  do
1325  {
1326     G4double currentCurveLen= newEndPoint.GetCurveLength();
1327     G4double advanceLength= endCurveLen - currentCurveLen ; 
1328     if (std::abs(advanceLength)<kCarTolerance)
1329     {
1330       advanceLength=(EstimatedEndStateB.GetPosition()
1331                     -newEndPoint.GetPosition()).mag();
1332     }
1333     goodAdvance= 
1334       integrDriver->AccurateAdvance(newEndPoint, advanceLength, fEpsilonStep);
1335     //              ***************
1336  }
1337  while( !goodAdvance && (++itrial < no_trials) );
1338
1339  if( goodAdvance )
1340  {
1341    retEndPoint= newEndPoint; 
1342  }
1343  else
1344  {
1345    retEndPoint= EstimatedEndStateB; // Could not improve without major work !!
1346  }
1347
1348  //  All the work is done
1349  //   below are some diagnostics only -- before the return!
1350  //
1351  static const G4String MethodName("G4PropagatorInField::ReEstimateEndpoint");
1352
1353#ifdef G4VERBOSE
1354  G4int  latest_good_trials=0;
1355  if( itrial > 1)
1356  {
1357    if( fVerboseLevel > 0 )
1358    {
1359      G4cout << MethodName << " called - goodAdv= " << goodAdvance
1360             << " trials = " << itrial
1361             << " previous good= " << latest_good_trials
1362             << G4endl;
1363    }
1364    latest_good_trials=0; 
1365  }
1366  else
1367  {   
1368    latest_good_trials++; 
1369  }
1370#endif
1371
1372#ifdef G4DEBUG_FIELD
1373  G4double lengthDone = newEndPoint.GetCurveLength() 
1374                      - CurrentStateA.GetCurveLength(); 
1375  if( !goodAdvance )
1376  {
1377    if( fVerboseLevel >= 3 )
1378    {
1379      G4cout << MethodName << "> AccurateAdvance failed " ;
1380      G4cout << " in " << itrial << " integration trials/steps. " << G4endl;
1381      G4cout << " It went only " << lengthDone << " instead of " << curveDist
1382             << " -- a difference of " << curveDist - lengthDone  << G4endl;
1383      G4cout << " ReEstimateEndpoint> Reset endPoint to original value!"
1384             << G4endl;
1385    }
1386  }
1387
1388  static G4int noInaccuracyWarnings = 0; 
1389  G4int maxNoWarnings = 10;
1390  if (  (noInaccuracyWarnings < maxNoWarnings ) 
1391       || (fVerboseLevel > 1) )
1392    {
1393      G4cerr << "G4PropagatorInField::LocateIntersectionPoint():"
1394             << G4endl
1395             << " Warning: Integration inaccuracy requires" 
1396             <<   " an adjustment in the step's endpoint."  << G4endl
1397             << "   Two mid-points are further apart than their"
1398             <<   " curve length difference"                << G4endl
1399             << "   Dist = "       << std::sqrt(linearDistSq)
1400             << " curve length = " << curveDist             << G4endl; 
1401      G4cerr << " Correction applied is " 
1402             << (newEndPoint.GetPosition()-EstimatedEndStateB.GetPosition()).mag()
1403             << G4endl;
1404    }
1405#else
1406  // Statistics on the RMS value of the corrections
1407
1408  static G4int    noCorrections=0;
1409  static G4double sumCorrectionsSq = 0;
1410  noCorrections++; 
1411  if( goodAdvance )
1412  {
1413    sumCorrectionsSq += (EstimatedEndStateB.GetPosition() - 
1414                         newEndPoint.GetPosition()).mag2();
1415  }
1416  linearDistSq -= curveDist; // To use linearDistSq ... !
1417#endif
1418
1419  return retEndPoint;
1420}
1421
1422// Access the points which have passed through the filter. The
1423// points are stored as ThreeVectors for the initial impelmentation
1424// only (jacek 30/10/2002)
1425// Responsibility for deleting the points lies with
1426// SmoothTrajectoryPoint, which is the points' final
1427// destination. The points pointer is set to NULL, to ensure that
1428// the points are not re-used in subsequent steps, therefore THIS
1429// METHOD MUST BE CALLED EXACTLY ONCE PER STEP. (jacek 08/11/2002)
1430
1431std::vector<G4ThreeVector>*
1432G4PropagatorInField::GimmeTrajectoryVectorAndForgetIt() const
1433{
1434  // NB, GimmeThePointsAndForgetThem really forgets them, so it can
1435  // only be called (exactly) once for each step.
1436
1437  if (fpTrajectoryFilter)
1438  {
1439    return fpTrajectoryFilter->GimmeThePointsAndForgetThem();
1440  }
1441  else
1442  {
1443    return 0;
1444  }
1445}
1446
1447void 
1448G4PropagatorInField::SetTrajectoryFilter(G4VCurvedTrajectoryFilter* filter)
1449{
1450  fpTrajectoryFilter = filter;
1451}
1452
1453void G4PropagatorInField::ClearPropagatorState()
1454{
1455  // Goal: Clear all memory of previous steps,  cached information
1456
1457  fParticleIsLooping= false;
1458  fNoZeroStep= 0;
1459
1460  End_PointAndTangent= G4FieldTrack( G4ThreeVector(0.,0.,0.),
1461                                     G4ThreeVector(0.,0.,0.),
1462                                     0.0,0.0,0.0,0.0,0.0); 
1463  fFull_CurveLen_of_LastAttempt = -1; 
1464  fLast_ProposedStepLength = -1;
1465
1466  fPreviousSftOrigin= G4ThreeVector(0.,0.,0.);
1467  fPreviousSafety= 0.0;
1468}
1469
1470G4FieldManager* G4PropagatorInField::
1471FindAndSetFieldManager( G4VPhysicalVolume* pCurrentPhysicalVolume)
1472{
1473  G4FieldManager* currentFieldMgr;
1474
1475  currentFieldMgr = fDetectorFieldMgr;
1476  if( pCurrentPhysicalVolume)
1477  {
1478     G4FieldManager *newFieldMgr = 0;
1479     newFieldMgr= pCurrentPhysicalVolume->GetLogicalVolume()->GetFieldManager();
1480     if ( newFieldMgr ) 
1481        currentFieldMgr = newFieldMgr;
1482  }
1483  fCurrentFieldMgr= currentFieldMgr;
1484
1485  // Flag that field manager has been set.
1486  fSetFieldMgr= true;
1487
1488  return currentFieldMgr;
1489}
1490
1491G4int G4PropagatorInField::SetVerboseLevel( G4int level )
1492{
1493  G4int oldval= fVerboseLevel;
1494  fVerboseLevel= level;
1495
1496  // Forward the verbose level 'reduced' to ChordFinder,
1497  // MagIntegratorDriver ... ?
1498  //
1499  G4MagInt_Driver* integrDriver= GetChordFinder()->GetIntegrationDriver(); 
1500  integrDriver->SetVerboseLevel( fVerboseLevel - 2 ); 
1501  G4cout << "Set Driver verbosity to " << fVerboseLevel - 2 << G4endl;
1502
1503  return oldval;
1504}
Note: See TracBrowser for help on using the repository browser.