source: trunk/source/geometry/navigation/src/G4PathFinder.cc @ 1342

Last change on this file since 1342 was 1058, checked in by garnier, 15 years ago

file release beta

File size: 46.7 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: G4PathFinder.cc,v 1.62 2009/05/13 23:20:54 japost Exp $
28// GEANT4 tag $ Name:  $
29//
30// class G4PathFinder Implementation
31//
32// Original author:  John Apostolakis,  April 2006
33//
34// --------------------------------------------------------------------
35
36#include "G4PathFinder.hh"
37
38#include <iomanip>
39
40#include "G4GeometryTolerance.hh"
41#include "G4Navigator.hh"
42#include "G4PropagatorInField.hh"
43#include "G4TransportationManager.hh"
44#include "G4MultiNavigator.hh"
45#include "G4SafetyHelper.hh"
46
47// Initialise the static instance of the singleton
48//
49G4PathFinder* G4PathFinder::fpPathFinder=0;
50
51// ----------------------------------------------------------------------------
52// GetInstance()
53//
54// Retrieve the static instance of the singleton
55//
56G4PathFinder* G4PathFinder::GetInstance()
57{
58   static G4PathFinder theInstance; 
59   if( ! fpPathFinder )
60   {
61     fpPathFinder = &theInstance; 
62   }
63   return fpPathFinder;
64}
65
66// ----------------------------------------------------------------------------
67// Constructor
68//
69G4PathFinder::G4PathFinder() 
70  : fEndState( G4ThreeVector(), G4ThreeVector(), 0., 0., 0., 0., 0.),
71    fRelocatedPoint(true),
72    fLastStepNo(-1), 
73    fVerboseLevel(0)
74{
75   fpMultiNavigator= new G4MultiNavigator(); 
76
77   fpTransportManager= G4TransportationManager::GetTransportationManager();
78   fpFieldPropagator = fpTransportManager->GetPropagatorInField();
79
80   kCarTolerance = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
81
82   fNoActiveNavigators= 0; 
83   G4ThreeVector  Big3Vector( kInfinity, kInfinity, kInfinity );
84   fLastLocatedPosition= Big3Vector;
85   fSafetyLocation= Big3Vector; 
86   fPreSafetyLocation= Big3Vector;
87   fPreStepLocation= Big3Vector;
88
89   fPreSafetyMinValue=  -1.0; 
90   fMinSafety_PreStepPt= -1.0; 
91   fMinSafety_atSafLocation= -1.0; 
92   fMinStep=   -1.0;
93   fNewTrack= false; 
94   fNoGeometriesLimiting= 0; 
95
96   for( register int num=0; num<= fMaxNav; ++num )
97   {
98      fpNavigator[num] =  0;   
99      fLimitTruth[num] = false;
100      fLimitedStep[num] = kUndefLimited;
101      fCurrentStepSize[num] = -1.0; 
102      fLocatedVolume[num] = 0;
103      fPreSafetyValues[num]= -1.0; 
104      fCurrentPreStepSafety[num] = -1.0;
105      fNewSafetyComputed[num]= -1.0; 
106   }
107}
108
109// ----------------------------------------------------------------------------
110// Destructor
111//
112G4PathFinder::~G4PathFinder() 
113{
114   delete fpMultiNavigator; 
115}
116
117// ----------------------------------------------------------------------------
118//
119void
120G4PathFinder::EnableParallelNavigation(G4bool enableChoice)
121{
122   G4Navigator *navigatorForPropagation=0, *massNavigator=0;
123
124   massNavigator= fpTransportManager->GetNavigatorForTracking(); 
125   if( enableChoice )
126   {
127      navigatorForPropagation= fpMultiNavigator;
128
129      // Enable SafetyHelper to use PF
130      //
131      fpTransportManager->GetSafetyHelper()->EnableParallelNavigation(true);
132   }
133   else
134   {
135      navigatorForPropagation= massNavigator;
136       
137      // Disable SafetyHelper to use PF
138      //
139      fpTransportManager->GetSafetyHelper()->EnableParallelNavigation(false);
140   }
141   fpFieldPropagator->SetNavigatorForPropagating(navigatorForPropagation);
142}
143
144// ----------------------------------------------------------------------------
145//
146G4double
147G4PathFinder::ComputeStep( const G4FieldTrack &InitialFieldTrack, 
148                                 G4double     proposedStepLength,
149                                 G4int        navigatorNo, 
150                                 G4int        stepNo,       // find next step
151                                 G4double     &pNewSafety,  // for this geom
152                                 ELimited     &limitedStep, 
153                                 G4FieldTrack &EndState,
154                                 G4VPhysicalVolume* currentVolume)
155{
156  G4double  possibleStep= -1.0; 
157
158#ifdef G4DEBUG_PATHFINDER
159  if( fVerboseLevel > 2 )
160  { 
161    G4cout << " -------------------------" <<  G4endl;
162    G4cout << " G4PathFinder::ComputeStep - entered " << G4endl;
163    G4cout << "   - stepNo = "  << std::setw(4) << stepNo  << " "
164           << " navigatorId = " << std::setw(2) << navigatorNo  << " "
165           << " proposed step len = " << proposedStepLength << " " << G4endl;
166    G4cout << " PF::ComputeStep requested step " 
167           << " from " << InitialFieldTrack.GetPosition()
168           << " dir  " << InitialFieldTrack.GetMomentumDirection() << G4endl;
169  }
170#endif
171#ifdef G4VERBOSE
172  if( navigatorNo >= fNoActiveNavigators )
173  {
174    G4cerr << "ERROR - G4PathFinder::ComputeStep()" << G4endl
175           << "        Requested Navigator ID = " << navigatorNo << G4endl
176           << "        Number of active navigators = " << fNoActiveNavigators
177           << G4endl;
178    G4Exception("G4PathFinder::ComputeStep()", "InvalidSetup",
179                FatalException, "Bad Navigator ID !"); 
180  }
181#endif
182
183  if( fNewTrack || (stepNo != fLastStepNo)  )
184  {
185    // This is a new track or a new step, so we must make the step
186    // ( else we can simply retrieve its results for this Navigator Id )   
187
188    G4FieldTrack currentState= InitialFieldTrack;
189
190    fCurrentStepNo = stepNo; 
191
192    // Check whether a process shifted the position
193    // since the last step -- by physics processes
194    //
195    G4ThreeVector newPosition = InitialFieldTrack.GetPosition();   
196    G4ThreeVector moveVector= newPosition - fLastLocatedPosition; 
197    G4double moveLenSq= moveVector.mag2(); 
198    if( moveLenSq > kCarTolerance * kCarTolerance )
199    { 
200       G4ThreeVector newDirection = InitialFieldTrack.GetMomentumDirection();   
201#ifdef G4DEBUG_PATHFINDER
202       if( fVerboseLevel > 2 )
203       { 
204          G4double moveLen= std::sqrt( moveLenSq ); 
205          G4cout << " G4PathFinder::ComputeStep : Point moved since last step " 
206                 << " -- at step # = " << stepNo << G4endl
207                 << " by " << moveLen  << " to " << newPosition << G4endl;     
208       } 
209#endif
210       MovePoint();  // Unintentional changed -- ????
211
212       // Relocate to cope with this move -- else could abort !?
213       //
214       Locate( newPosition, newDirection ); 
215    }
216
217    // Check whether the particle have an (EM) field force exerting upon it
218    //
219    G4double particleCharge=  currentState.GetCharge(); 
220
221    G4FieldManager* fieldMgr=0;
222    G4bool          fieldExertsForce = false ;
223    if( (particleCharge != 0.0) )
224    {
225        fieldMgr= fpFieldPropagator->FindAndSetFieldManager( currentVolume );
226
227        // Protect for case where field manager has no field (= field is zero)
228        //
229        fieldExertsForce = (fieldMgr != 0) 
230                        && (fieldMgr->GetDetectorField() != 0);
231    }
232    fFieldExertedForce = fieldExertsForce;  // Store for use in later calls
233                                            // referring to this 'step'.
234
235    fNoGeometriesLimiting= -1;  // At start of track, no process limited step
236    if( fieldExertsForce )
237    {
238       DoNextCurvedStep( currentState, proposedStepLength, currentVolume ); 
239       //--------------
240    }else{
241       DoNextLinearStep( currentState, proposedStepLength ); 
242       //--------------
243    }
244    fLastStepNo= stepNo; 
245
246    if ( (fNoGeometriesLimiting < 0)
247      || (fNoGeometriesLimiting > fNoActiveNavigators) )
248    {
249      G4cout << "ERROR - G4PathFinder::ComputeStep()" << G4endl
250             << "        Number of geometries limiting step = "
251             << fNoGeometriesLimiting << G4endl;
252      G4Exception("G4PathFinder::ComputeStep()", 
253                  "NumGeometriesOutOfRange", FatalException, 
254                  "Number of geometries limiting the step not set."); 
255    }
256  }
257#ifdef G4DEBUG_PATHFINDER     
258  else
259  {
260     if( proposedStepLength < fTrueMinStep )  // For 2nd+ geometry
261     { 
262        G4cout << "ERROR - G4PathFinder::ComputeStep()" << G4endl
263               << "        Problem in step size request." << G4endl
264               << "        Being requested to make a step which is shorter"
265               << " than the minimum Step " << G4endl
266               << "        already computed for any Navigator/geometry during"
267               << " this tracking-step: " << G4endl; 
268        G4cout << "        This can happen due to an error in process ordering."
269               << G4endl;
270        G4cout << "        Check that all physics processes are registered"
271               << G4endl
272               << "        before all processes with a navigator/geometry."
273               << G4endl;
274        G4cout << "        If using pre-packaged physics list and/or"
275               << G4endl
276               << "        functionality, please report this error."
277               << G4endl << G4endl;
278        G4cout << "        Additional information for problem: "  << G4endl
279               << "        Steps request/proposed = " << proposedStepLength
280               << G4endl
281               << "        MinimumStep (true) = " << fTrueMinStep
282               << G4endl
283               << "        MinimumStep (navraw)  = " << fMinStep
284               << G4endl
285               << "        Navigator raw return value" << G4endl
286               << "        Requested step now = " << proposedStepLength
287               << G4endl
288               << "        Difference min-req = "
289               << fTrueMinStep-proposedStepLength << G4endl; 
290        G4cout << "     -- Step info> stepNo= " << stepNo
291               << " last= " << fLastStepNo
292               << " newTr= " << fNewTrack << G4endl; 
293        G4cerr << "ERROR - G4PathFinder::ComputeStep()" << G4endl
294               << "        Problem in step size request. " << G4endl
295               << "        Error can be caused by incorrect process ordering."
296               << G4endl
297               << "        Please see more information in standard output."
298               << G4endl;
299        G4Exception("G4PathFinder::ComputeStep()", 
300                    "ReductionOfRequestedStepSizeBelowMinimum",
301                    FatalException, 
302                    "Not part of specification - not implemented.");
303     }
304     else
305     { 
306        // This is neither a new track nor a new step -- just another
307        // client accessing information for the current track, step
308        // We will simply retrieve the results of the synchronous
309        // stepping for this Navigator Id below.
310        //
311        if( fVerboseLevel > 1 )
312        { 
313           G4cout << " G4P::CS -> Not calling DoNextLinearStep: " 
314                  << " stepNo= " << stepNo << " last= " << fLastStepNo
315                  << " new= " << fNewTrack << " Step already done" << G4endl; 
316        }
317     } 
318  }
319#endif
320
321  fNewTrack= false; 
322
323  // Prepare the information to return
324
325  pNewSafety  = fCurrentPreStepSafety[ navigatorNo ]; 
326  limitedStep = fLimitedStep[ navigatorNo ];
327  fRelocatedPoint= false;
328
329  possibleStep= std::min(proposedStepLength, fCurrentStepSize[ navigatorNo ]);
330  EndState = fEndState;  //  now corrected for smaller step, if needed
331
332#ifdef G4DEBUG_PATHFINDER
333  if( fVerboseLevel > 0 )
334  { 
335    G4cout << " G4PathFinder::ComputeStep returns "
336           << fCurrentStepSize[ navigatorNo ]
337           << " for Navigator " << navigatorNo
338           << " Limited step = " << limitedStep
339           << " Safety(mm) = " << pNewSafety / mm
340           << G4endl; 
341  }
342#endif
343
344  return possibleStep;
345}
346
347// ----------------------------------------------------------------------
348
349void
350G4PathFinder::PrepareNewTrack( const G4ThreeVector& position, 
351                               const G4ThreeVector& direction,
352                               G4VPhysicalVolume*  massStartVol)
353{
354  // Key purposes:
355  //   - Check and cache set of active navigators
356  //   - Reset state for new track
357
358  G4int num=0; 
359
360  EnableParallelNavigation(true); 
361    // Switch PropagatorInField to use MultiNavigator
362
363  fpTransportManager->GetSafetyHelper()->InitialiseHelper(); 
364    // Reinitialise state of safety helper -- avoid problems with overlaps
365
366  fNewTrack= true; 
367  this->MovePoint();   // Signal further that the last status is wiped
368
369  // Message the G4NavigatorPanel / Dispatcher to find active navigators
370  //
371  std::vector<G4Navigator*>::iterator pNavigatorIter; 
372
373  fNoActiveNavigators=  fpTransportManager-> GetNoActiveNavigators();
374  if( fNoActiveNavigators > fMaxNav )
375  {
376    G4cerr << "ERROR - G4PathFinder::PrepareNewTrack()" << G4endl
377           << "        Too many active Navigators. G4PathFinder fails."
378           << G4endl
379           << "        Transportation Manager has "
380           << fNoActiveNavigators << " active navigators." << G4endl
381           << "        This is more than the number allowed = "
382           << fMaxNav << " !" << G4endl;
383    G4Exception("G4PathFinder::PrepareNewTrack()", "TooManyNavigators", 
384                FatalException, "Too many active Navigators / worlds"); 
385  }
386
387  fpMultiNavigator->PrepareNavigators(); 
388  //------------------------------------
389
390  pNavigatorIter= fpTransportManager->GetActiveNavigatorsIterator();
391  for( num=0; num< fNoActiveNavigators; ++pNavigatorIter,++num )
392  {
393     // Keep information in C-array ... for creating touchables - at least
394
395     fpNavigator[num] =  *pNavigatorIter;   
396     fLimitTruth[num] = false;
397     fLimitedStep[num] = kDoNot;
398     fCurrentStepSize[num] = 0.0; 
399     fLocatedVolume[num] = 0; 
400  }
401  fNoGeometriesLimiting= 0;  // At start of track, no process limited step
402
403  // In case of one geometry, the tracking will have done the locating!!
404
405  if( fNoActiveNavigators > 1 )
406  {
407     Locate( position, direction, false );   
408  }
409  else
410  {
411     // Update state -- depending on the tracking's call to Mass Navigator
412
413     fLastLocatedPosition= position; 
414     fLocatedVolume[0]= massStartVol; // This information must be given
415                                      // by transportation
416     fLimitedStep[0]   = kDoNot; 
417     fCurrentStepSize[0] = 0.0;
418  }
419
420  // Reset Safety Information -- as in case of overlaps this can cause
421  // inconsistencies ...
422  //
423  fMinSafety_PreStepPt= fPreSafetyMinValue= fMinSafety_atSafLocation= 0.0; 
424 
425  for( num=0; num< fNoActiveNavigators; ++num )
426  {
427     fPreSafetyValues[num]= 0.0; 
428     fNewSafetyComputed[num]= 0.0; 
429     fCurrentPreStepSafety[num] = 0.0;
430  }
431
432  // The first location for each Navigator must be non-relative
433  // or else call ResetStackAndState() for each Navigator
434
435  fRelocatedPoint= false; 
436}
437
438void G4PathFinder::ReportMove( const G4ThreeVector& OldVector, 
439                               const G4ThreeVector& NewVector, 
440                               const G4String& Quantity ) const
441{
442    G4ThreeVector moveVec = ( NewVector - OldVector );
443
444    G4int prc= G4cerr.precision(12); 
445    G4cerr << G4endl
446           << "WARNING - G4PathFinder::ReportMove()" << G4endl
447           << "          Endpoint moved between value returned by ComputeStep()"
448           << " and call to Locate(). " << G4endl
449           << "          Change of " << Quantity << " is "
450           << moveVec.mag() / mm << " mm long" << G4endl
451           << "          and its vector is "
452           << (1.0/mm) * moveVec << " mm " << G4endl
453           << "          Endpoint of ComputeStep() was " << OldVector << G4endl
454           << "          and current position to locate is " << NewVector
455           << G4endl;
456    G4cerr.precision(prc); 
457}
458
459void
460G4PathFinder::Locate( const   G4ThreeVector& position, 
461                      const   G4ThreeVector& direction,
462                      G4bool  relative)
463{
464  // Locate the point in each geometry
465
466  std::vector<G4Navigator*>::iterator pNavIter=
467     fpTransportManager->GetActiveNavigatorsIterator(); 
468
469  G4ThreeVector lastEndPosition= fEndState.GetPosition(); 
470  G4ThreeVector moveVec = (position - lastEndPosition );
471  G4double      moveLenSq= moveVec.mag2();
472  if( (!fNewTrack) && (!fRelocatedPoint)
473   && ( moveLenSq> kCarTolerance*kCarTolerance ) )
474  {
475     ReportMove( position, lastEndPosition, "Position" ); 
476     G4Exception("G4PathFinder::Locate", "201-LocateUnexpectedPoint", 
477                 JustWarning,
478                 "Location is not where last ComputeStep() ended."); 
479  }
480  fLastLocatedPosition= position; 
481
482#ifdef G4DEBUG_PATHFINDER
483  if( fVerboseLevel > 2 )
484  {
485    G4cout << G4endl; 
486    G4cout << " G4PathFinder::Locate : entered " << G4endl;
487    G4cout << " --------------------   -------" <<  G4endl;
488    G4cout << "   Locating at position " << position
489           << "  with direction " << direction
490           << "  relative= " << relative << G4endl;
491    if ( (fVerboseLevel > 1) || ( moveLenSq > 0.0) )
492    { 
493       G4cout << "  lastEndPosition = " << lastEndPosition
494              << "  moveVec = " << moveVec
495              << "  newTr = " << fNewTrack
496              << "  relocated = " << fRelocatedPoint << G4endl;
497    }
498
499    G4cout << " Located at " << position ; 
500    if( fNoActiveNavigators > 1 )  { G4cout << G4endl; }
501  }
502#endif
503
504  for ( register G4int num=0; num< fNoActiveNavigators ; ++pNavIter,++num )
505  {
506     //  ... who limited the step ....
507
508     if( fLimitTruth[num] ) { (*pNavIter)->SetGeometricallyLimitedStep(); }
509
510     G4VPhysicalVolume *pLocated= 
511     (*pNavIter)->LocateGlobalPointAndSetup( position, &direction,
512                                             relative, 
513                                             false);   
514     // Set the state related to the location
515     //
516     fLocatedVolume[num] = pLocated; 
517
518     // Clear state related to the step
519     //
520     fLimitedStep[num]   = kDoNot; 
521     fCurrentStepSize[num] = 0.0;     
522   
523#ifdef G4DEBUG_PATHFINDER
524     if( fVerboseLevel > 2 )
525     {
526       G4cout << " - In world " << num << " geomLimStep= " << fLimitTruth[num]
527              << "  gives volume= " << pLocated ; 
528       if( pLocated )
529       { 
530         G4cout << "  name = '" << pLocated->GetName() << "'"; 
531         G4cout << " - CopyNo= " << pLocated->GetCopyNo(); 
532       } 
533       G4cout  << G4endl; 
534     }
535#endif
536  }
537
538  fRelocatedPoint= false;
539}
540
541void G4PathFinder::ReLocate( const G4ThreeVector& position )
542{
543  // Locate the point in each geometry
544
545  std::vector<G4Navigator*>::iterator pNavIter=
546    fpTransportManager->GetActiveNavigatorsIterator(); 
547
548  // Check that this relocation does not violate safety
549  //   - at endpoint (computed from start point) AND
550  //   - at last safety location  (likely just called)
551
552  G4ThreeVector lastEndPosition= fEndState.GetPosition();
553
554  // Calculate end-point safety ...
555  //
556  G4double      DistanceStartEnd= (lastEndPosition - fPreStepLocation).mag();
557  G4double      endPointSafety_raw = fMinSafety_PreStepPt - DistanceStartEnd; 
558  G4double      endPointSafety_Est1 = std::max( 0.0, endPointSafety_raw ); 
559
560  // ... and check move from endpoint against this endpoint safety
561  //
562  G4ThreeVector moveVecEndPos  = position - lastEndPosition;
563  G4double      moveLenEndPosSq = moveVecEndPos.mag2(); 
564
565  // Check that move from endpoint of last step is within safety
566  // -- or check against last location or relocation ??
567  //
568  G4ThreeVector moveVecSafety=  position - fSafetyLocation; 
569  G4double      moveLenSafSq=   moveVecSafety.mag2();
570
571  G4double distCheckEnd_sq= ( moveLenEndPosSq - endPointSafety_Est1
572                                               *endPointSafety_Est1 ); 
573  G4double distCheckSaf_sq=   ( moveLenSafSq -  fMinSafety_atSafLocation
574                                               *fMinSafety_atSafLocation ); 
575
576  G4bool longMoveEnd = distCheckEnd_sq > 0.0; 
577  G4bool longMoveSaf = distCheckSaf_sq > 0.0; 
578
579  G4double revisedSafety= 0.0;
580
581  if( (!fNewTrack) && ( longMoveEnd && longMoveSaf ) )
582  { 
583     // Recompute ComputeSafety for end position
584     //
585     revisedSafety= ComputeSafety(lastEndPosition); 
586
587#ifdef G4DEBUG_PATHFINDER
588
589     const G4double kRadTolerance =
590       G4GeometryTolerance::GetInstance()->GetRadialTolerance();
591     const G4double cErrorTolerance=1e-12;   
592       // Maximum relative error from roundoff of arithmetic
593
594     G4double  distCheckRevisedEnd= moveLenEndPosSq-revisedSafety*revisedSafety;
595
596     G4bool  longMoveRevisedEnd=  ( distCheckRevisedEnd > 0. ) ; 
597
598     G4double  moveMinusSafety= 0.0; 
599     G4double  moveLenEndPosition= std::sqrt( moveLenEndPosSq );
600     moveMinusSafety = moveLenEndPosition - revisedSafety; 
601
602     if ( longMoveRevisedEnd && (moveMinusSafety > 0.0 )
603       && ( revisedSafety > 0.0 ) )
604     {
605        // Take into account possibility of roundoff error causing
606        // this apparent move further than safety
607
608        if( fVerboseLevel > 0 )
609        {
610           G4cout << " G4PF:Relocate> Ratio to revised safety is " 
611                  << std::fabs(moveMinusSafety)/revisedSafety << G4endl;
612        }
613
614        G4double  absMoveMinusSafety= std::fabs(moveMinusSafety);
615        G4bool smallRatio= absMoveMinusSafety < kRadTolerance * revisedSafety ; 
616        G4double maxCoordPos = std::max( 
617                                      std::max( std::fabs(position.x()), 
618                                                std::fabs(position.y())), 
619                                      std::fabs(position.z()) );
620        G4bool smallValue= absMoveMinusSafety < cErrorTolerance * maxCoordPos;
621        if( ! (smallRatio || smallValue) )
622        {
623           G4cout << " G4PF:Relocate> Ratio to revised safety is " 
624                  << std::fabs(moveMinusSafety)/revisedSafety << G4endl;
625           G4cout << " Difference of move and safety is not very small."
626                  << G4endl;
627        }
628        else
629        {
630          moveMinusSafety = 0.0; 
631          longMoveRevisedEnd = false;   // Numerical issue -- not too long!
632
633          G4cout << " Difference of move & safety is very small in magnitude, "
634                 << absMoveMinusSafety << G4endl;
635          if( smallRatio )
636          {
637            G4cout << " ratio to safety " << revisedSafety
638                   << " is " <<  absMoveMinusSafety / revisedSafety
639                   << "smaller than " << kRadTolerance << " of safety ";
640          }
641          else
642          {
643            G4cout << " as fraction " << absMoveMinusSafety / maxCoordPos
644                   << " of position vector max-coord " << maxCoordPos
645                   << " smaller than " << cErrorTolerance ;
646          }
647          G4cout << " -- reset moveMinusSafety to "
648                 << moveMinusSafety << G4endl;
649        }
650     }
651
652     if ( longMoveEnd && longMoveSaf
653       && longMoveRevisedEnd && (moveMinusSafety>0.0) )
654     { 
655        G4int oldPrec= G4cout.precision(9); 
656        G4cout << " Problem in G4PathFinder::Relocate() " << G4endl;
657        G4cout << " Moved from last endpoint by " << moveLenEndPosition
658               << " compared to end safety (from preStep point) = " 
659               << endPointSafety_Est1 << G4endl; 
660
661        G4cout << "  --> last PreSafety Location was " << fPreSafetyLocation
662               << G4endl;
663        G4cout << "       safety value =  " << fPreSafetyMinValue << G4endl;
664        G4cout << "  --> last PreStep Location was " << fPreStepLocation
665               << G4endl;
666        G4cout << "       safety value =  " << fMinSafety_PreStepPt << G4endl;
667        G4cout << "  --> last EndStep Location was " << lastEndPosition
668               << G4endl;
669        G4cout << "       safety value =  " << endPointSafety_Est1
670               << " raw-value = " << endPointSafety_raw << G4endl;
671        G4cout << "  --> Calling again at this endpoint, we get "
672               <<  revisedSafety << " as safety value."  << G4endl;
673        G4cout << "  --> last position for safety " << fSafetyLocation
674               << G4endl;
675        G4cout << "       its safety value =  " << fMinSafety_atSafLocation
676               << G4endl;
677        G4cout << "       move from safety location = "
678               << std::sqrt(moveLenSafSq) << G4endl
679               << "         again= " << moveVecSafety.mag() << G4endl;
680        G4cout << "       safety - Move-from-end= " 
681               << revisedSafety - moveLenEndPosition
682               << " (negative is Bad.)" << G4endl;
683
684        G4cout << " Debug:  distCheckRevisedEnd = "
685               << distCheckRevisedEnd << G4endl;
686
687        ReportMove( lastEndPosition, position, "Position" ); 
688        G4Exception( "G4PathFinder::ReLocate", "205-RelocatePointTooFar", 
689                    FatalException, 
690                   "ReLocation is further than end-safety value."); 
691        G4cout.precision(oldPrec); 
692    }
693
694#endif
695  }
696
697#ifdef G4DEBUG_PATHFINDER
698  if( fVerboseLevel > 2 )
699  {
700    G4cout << G4endl; 
701    G4cout << " G4PathFinder::ReLocate : entered " << G4endl;
702    G4cout << " ----------------------   -------" <<  G4endl;
703    G4cout << "  *Re*Locating at position " << position  << G4endl; 
704      // << "  with direction " << direction
705      // << "  relative= " << relative << G4endl;
706    if ( (fVerboseLevel > -1) || ( moveLenEndPosSq > 0.0) )
707    {
708       G4cout << "  lastEndPosition = " << lastEndPosition
709              << "  moveVec from step-end = " << moveVecEndPos
710              << "  is new Track = " << fNewTrack
711              << "  relocated = " << fRelocatedPoint << G4endl;
712    }
713  }
714#endif
715
716  for ( register G4int num=0; num< fNoActiveNavigators ; ++pNavIter,++num )
717  {
718     //  ... none limited the step
719
720     (*pNavIter)->LocateGlobalPointWithinVolume( position ); 
721
722     // Clear state related to the step
723     //
724     fLimitedStep[num]   = kDoNot; 
725     fCurrentStepSize[num] = 0.0;     
726     fLimitTruth[num] = false;   
727  }
728
729  fLastLocatedPosition= position; 
730  fRelocatedPoint= false;
731
732#ifdef G4DEBUG_PATHFINDER
733  if( fVerboseLevel > 2 )
734  {
735    G4cout << " G4PathFinder::ReLocate : exiting " 
736           << "  at position " << fLastLocatedPosition << G4endl << G4endl;
737  }
738#endif
739}
740
741// -----------------------------------------------------------------------------
742
743G4double  G4PathFinder::ComputeSafety( const G4ThreeVector& position )
744{
745    // Recompute safety for the relevant point
746
747   G4double minSafety= kInfinity; 
748 
749   std::vector<G4Navigator*>::iterator pNavigatorIter;
750   pNavigatorIter= fpTransportManager->GetActiveNavigatorsIterator();
751
752   for( register G4int num=0; num<fNoActiveNavigators; ++pNavigatorIter,++num )
753   {
754      G4double safety = (*pNavigatorIter)->ComputeSafety( position,true );
755      if( safety < minSafety ) { minSafety = safety; } 
756      fNewSafetyComputed[num]= safety;
757   } 
758
759   fSafetyLocation= position;
760   fMinSafety_atSafLocation = minSafety;
761
762#ifdef G4DEBUG_PATHFINDER
763   if( fVerboseLevel > 1 )
764   { 
765     G4cout << " G4PathFinder::ComputeSafety - returns " 
766            << minSafety << " at location " << position << G4endl;
767   }
768#endif
769   return minSafety; 
770}
771
772
773// -----------------------------------------------------------------------------
774
775G4TouchableHandle
776G4PathFinder::CreateTouchableHandle( G4int navId ) const
777{
778#ifdef G4DEBUG_PATHFINDER
779  if( fVerboseLevel > 2 )
780  {
781    G4cout << "G4PathFinder::CreateTouchableHandle : navId = "
782           << navId << " -- " << GetNavigator(navId) << G4endl;
783  }
784#endif
785
786  G4TouchableHistory* touchHist;
787  touchHist= GetNavigator(navId) -> CreateTouchableHistory(); 
788
789  G4VPhysicalVolume* locatedVolume= fLocatedVolume[navId]; 
790  if( locatedVolume == 0 )
791  {
792     // Workaround to ensure that the touchable is fixed !! // TODO: fix
793
794     touchHist->UpdateYourself( locatedVolume, touchHist->GetHistory() );
795  }
796 
797#ifdef G4DEBUG_PATHFINDER
798  if( fVerboseLevel > 2 )
799  {   
800    G4String VolumeName("None"); 
801    if( locatedVolume ) { VolumeName= locatedVolume->GetName(); }
802    G4cout << " Touchable History created at address " << touchHist
803           << "  volume = " << locatedVolume << " name= " << VolumeName
804           << G4endl;
805  }
806#endif
807
808  return G4TouchableHandle(touchHist); 
809}
810
811G4double
812G4PathFinder::DoNextLinearStep( const G4FieldTrack &initialState,
813                                      G4double      proposedStepLength )
814{
815  std::vector<G4Navigator*>::iterator pNavigatorIter;
816  G4double safety= 0.0, step=0.0;
817  G4double minSafety= kInfinity, minStep;
818
819  const G4int IdTransport= 0;  // Id of Mass Navigator !!
820  register G4int num=0; 
821
822#ifdef G4DEBUG_PATHFINDER
823  if( fVerboseLevel > 2 )
824  {
825    G4cout << " G4PathFinder::DoNextLinearStep : entered " << G4endl;
826    G4cout << "   Input field track= " << initialState << G4endl;
827    G4cout << "   Requested step= " << proposedStepLength << G4endl;
828  }
829#endif
830
831  G4ThreeVector initialPosition= initialState.GetPosition(); 
832  G4ThreeVector initialDirection= initialState.GetMomentumDirection();
833 
834  G4ThreeVector OriginShift = initialPosition - fPreSafetyLocation;
835  G4double      MagSqShift  = OriginShift.mag2() ;
836  G4double      MagShift;  // Only given value if it larger than minimum safety
837
838  G4double fullSafety;  // For all geometries, for prestep point
839
840  // Potential optimisation using Maximum Value of safety!
841  // if( MagSqShift >= sqr(fPreSafetyMaxValue ) ){
842  //   MagShift= kInfinity;   // Not a useful value -- all will not use/ignore
843  // else
844  //  MagShift= std::sqrt(MagSqShift) ;
845
846  MagShift= std::sqrt(MagSqShift) ;
847  if( MagSqShift >= sqr(fPreSafetyMinValue ) )
848  {
849     fullSafety = 0.0 ;     
850  }
851  else
852  {
853     fullSafety = fPreSafetyMinValue - MagShift;
854  }
855
856#ifdef G4PATHFINDER_OPTIMISATION
857
858  if( proposedStepLength < fullSafety ) 
859  {
860     // Move is smaller than all safeties
861     //  -> so we do not have to move the safety center
862
863     fPreStepCenterRenewed= false;
864
865     for( num=0; num< fNoActiveNavigators; ++num )
866     {
867        fCurrentStepSize[num]= kInfinity; 
868        safety = std::max( 0.0,  fPreSafetyValues[num] - MagShift); 
869        minSafety= std::min( safety, minSafety ); 
870        fCurrentPreStepSafety[num]= safety; 
871     }
872     minStep= kInfinity;
873
874#ifdef G4DEBUG_PATHFINDER
875     if( fVerboseLevel > 2 )
876     {
877       G4cout << "G4PathFinder::DoNextLinearStep : Quick Stepping. " << G4endl
878               << " proposedStepLength " <<  proposedStepLength
879               << " < (full) safety = " << fullSafety
880               << " at " << initialPosition
881               << G4endl;
882     }
883#endif
884  }
885  else
886#endif   // End of G4PATHFINDER_OPTIMISATION 1
887  {
888     // Move is larger than at least one of the safeties
889     //  -> so we must move the safety center!
890
891     fPreStepCenterRenewed= true;
892     pNavigatorIter= fpTransportManager-> GetActiveNavigatorsIterator();
893
894     minStep= kInfinity;  // Not proposedStepLength;
895
896     for( num=0; num< fNoActiveNavigators; ++pNavigatorIter,++num ) 
897     {
898        safety = std::max( 0.0,  fPreSafetyValues[num] - MagShift); 
899
900#ifdef G4PATHFINDER_OPTIMISATION
901        if( proposedStepLength <= safety )  // Should be just < safety ?
902        {
903           // The Step is guaranteed to be taken
904
905           step= kInfinity;    //  ComputeStep Would return this
906
907#ifdef G4DEBUG_PATHFINDER
908           G4cout.precision(8); 
909           G4cout << "PathFinder::ComputeStep> small proposed step = "
910                  << proposedStepLength
911                  << " <=  safety = " << safety << " for nav " << num
912                  << " Step fully taken. " << G4endl;
913#endif
914        }
915        else
916#endif   // End of G4PATHFINDER_OPTIMISATION 2
917        {
918#ifdef G4DEBUG_PATHFINDER
919           G4double previousSafety= safety; 
920#endif
921           step= (*pNavigatorIter)->ComputeStep( initialPosition, 
922                                                 initialDirection,
923                                                 proposedStepLength,
924                                                 safety ); 
925           minStep  = std::min( step,  minStep);
926
927           //  TODO: consider whether/how to reduce the proposed step
928           //        to the latest minStep value - to reduce calculations
929
930#ifdef G4DEBUG_PATHFINDER
931           if( fVerboseLevel > 0)
932           {
933             G4cout.precision(8); 
934             G4cout << "PathFinder::ComputeStep> long  proposed step = "
935                    << proposedStepLength
936                    << "  >  safety = " << previousSafety
937                    << " for nav " << num
938                    << " .  New safety = " << safety << " step= " << step
939                    << G4endl;     
940           } 
941#endif
942        }
943        fCurrentStepSize[num] = step; 
944
945        // Save safety value, must be done for all geometries "together"
946        // (even if not recomputed using call to ComputeStep)
947        // since they share the fPreSafetyLocation
948
949        fPreSafetyValues[num]= safety; 
950        fCurrentPreStepSafety[num]= safety; 
951
952        minSafety= std::min( safety, minSafety ); 
953           
954#ifdef G4DEBUG_PATHFINDER
955        if( fVerboseLevel > 2 )
956        {
957          G4cout << "G4PathFinder::DoNextLinearStep : Navigator ["
958                 << num << "] -- step size " << step << G4endl;
959        }
960#endif
961     }
962
963     // Only change these when safety is recalculated
964     // it is good/relevant only for safety calculations
965
966     fPreSafetyLocation=  initialPosition; 
967     fPreSafetyMinValue=  minSafety;
968  } // end of else for  if( proposedStepLength <= fullSafety)
969
970  // For use in Relocation, need PreStep point location, min-safety
971  //
972  fPreStepLocation= initialPosition; 
973  fMinSafety_PreStepPt= minSafety; 
974
975  fMinStep=   minStep; 
976
977  if( fMinStep == kInfinity )
978  {
979     minStep = proposedStepLength;   //  Use this below for endpoint !!
980  }
981  fTrueMinStep = minStep;
982
983  // Set the EndState
984
985  G4ThreeVector endPosition;
986
987  fEndState= initialState; 
988  endPosition= initialPosition + minStep * initialDirection ; 
989
990#ifdef G4DEBUG_PATHFINDER
991  if( fVerboseLevel > 1 )
992  {
993    G4cout << "G4PathFinder::DoNextLinearStep : "
994           << " initialPosition = " << initialPosition
995           << " and endPosition = " << endPosition<< G4endl;
996  }
997#endif
998
999  fEndState.SetPosition( endPosition ); 
1000  fEndState.SetProperTimeOfFlight( -1.000 );   // Not defined YET
1001
1002  if( fNoActiveNavigators == 1 )
1003  { 
1004     G4bool transportLimited = (fMinStep!= kInfinity); 
1005     fLimitTruth[IdTransport] = transportLimited; 
1006     fLimitedStep[IdTransport] = transportLimited ? kUnique : kDoNot;
1007
1008     // Set fNoGeometriesLimiting - as WhichLimited does
1009     fNoGeometriesLimiting = transportLimited ? 1 : 0; 
1010  }
1011  else
1012  {
1013     WhichLimited(); 
1014  }
1015
1016#ifdef G4DEBUG_PATHFINDER
1017  if( fVerboseLevel > 2 )
1018  {
1019    G4cout << " G4PathFinder::DoNextLinearStep : exits returning "
1020           << minStep << G4endl;
1021    G4cout << "   Endpoint values = " << fEndState << G4endl;
1022    G4cout << G4endl;
1023  }
1024#endif
1025
1026  return minStep;
1027}
1028
1029void G4PathFinder::WhichLimited()
1030{
1031  // Flag which processes limited the step
1032
1033  G4int num=-1, last=-1; 
1034  G4int noLimited=0; 
1035  ELimited shared= kSharedOther; 
1036
1037  const G4int IdTransport= 0;  // Id of Mass Navigator !!
1038
1039  // Assume that [IdTransport] is Mass / Transport
1040  //
1041  G4bool transportLimited = (fCurrentStepSize[IdTransport] == fMinStep)
1042                           && ( fMinStep!= kInfinity) ; 
1043
1044  if( transportLimited )  { 
1045     shared= kSharedTransport;
1046  }
1047
1048  for ( num= 0; num < fNoActiveNavigators; num++ )
1049  { 
1050    G4bool limitedStep;
1051
1052    G4double step= fCurrentStepSize[num]; 
1053
1054    limitedStep = ( std::fabs(step - fMinStep) < kCarTolerance ) 
1055                 && ( step != kInfinity); 
1056
1057    fLimitTruth[ num ] = limitedStep; 
1058    if( limitedStep )
1059    {
1060      noLimited++; 
1061      fLimitedStep[num] = shared;
1062      last= num; 
1063    }
1064    else
1065    {
1066      fLimitedStep[num] = kDoNot;
1067    }
1068  }
1069  fNoGeometriesLimiting= noLimited;  // Save # processes limiting step
1070
1071  if( (last > -1) && (noLimited == 1 ) )
1072  {
1073    fLimitedStep[ last ] = kUnique; 
1074  }
1075
1076#ifdef G4DEBUG_PATHFINDER
1077  if( fVerboseLevel > 1 )
1078  {
1079    PrintLimited();   // --> for tracing
1080    if( fVerboseLevel > 4 ) {
1081      G4cout << " G4PathFinder::WhichLimited - exiting. " << G4endl;
1082    }
1083  }
1084#endif
1085}
1086
1087void G4PathFinder::PrintLimited()
1088{
1089  // Report results -- for checking   
1090
1091  G4cout << "G4PathFinder::PrintLimited reports: " ; 
1092  G4cout << "  Minimum step (true)= " << fTrueMinStep
1093         << "  reported min = " << fMinStep
1094         << G4endl; 
1095  if(  (fCurrentStepNo <= 2) || (fVerboseLevel>=2) )
1096  {
1097    G4cout << std::setw(5) << " Step#"  << " "
1098           << std::setw(5) << " NavId"  << " "
1099           << std::setw(12) << " step-size " << " "
1100           << std::setw(12) << " raw-size "  << " "
1101           << std::setw(12) << " pre-safety " << " " 
1102           << std::setw(15) << " Limited / flag"  << " "
1103           << std::setw(15) << "  World "  << " "
1104           << G4endl; 
1105  }
1106  G4int num;
1107  for ( num= 0; num < fNoActiveNavigators; num++ )
1108  { 
1109    G4double rawStep = fCurrentStepSize[num]; 
1110    G4double stepLen = fCurrentStepSize[num]; 
1111    if( stepLen > fTrueMinStep )
1112    { 
1113      stepLen = fTrueMinStep;     // did not limit (went as far as asked)
1114    }
1115    G4int oldPrec= G4cout.precision(9); 
1116
1117    G4cout << std::setw(5) << fCurrentStepNo  << " " 
1118           << std::setw(5) << num  << " "
1119           << std::setw(12) << stepLen << " "
1120           << std::setw(12) << rawStep << " "
1121           << std::setw(12) << fCurrentPreStepSafety[num] << " "
1122           << std::setw(5) << (fLimitTruth[num] ? "YES" : " NO") << " ";
1123    G4String limitedStr= LimitedString(fLimitedStep[num]); 
1124    G4cout << " " << std::setw(15) << limitedStr << " "; 
1125    G4cout.precision(oldPrec); 
1126
1127    G4Navigator *pNav= GetNavigator( num ); 
1128    G4String  WorldName( "Not-Set" ); 
1129    if (pNav)
1130    {
1131       G4VPhysicalVolume *pWorld= pNav->GetWorldVolume(); 
1132       if( pWorld )
1133       {
1134           WorldName = pWorld->GetName(); 
1135       }
1136    }
1137    G4cout << " " << WorldName ; 
1138    G4cout << G4endl;
1139  }
1140
1141  if( fVerboseLevel > 4 )
1142  {
1143    G4cout << " G4PathFinder::PrintLimited - exiting. " << G4endl;
1144  }
1145}
1146
1147G4double
1148G4PathFinder::DoNextCurvedStep( const G4FieldTrack &initialState,
1149                                G4double      proposedStepLength,
1150                                G4VPhysicalVolume* pCurrentPhysicalVolume )
1151{
1152  const G4double toleratedRelativeError= 1.0e-10; 
1153  G4double minStep= kInfinity, newSafety=0.0;
1154  G4int numNav; 
1155  G4FieldTrack  fieldTrack= initialState;
1156  G4ThreeVector startPoint= initialState.GetPosition(); 
1157
1158#ifdef G4DEBUG_PATHFINDER
1159  G4int prc= G4cout.precision(9);
1160  if( fVerboseLevel > 2 )
1161  {
1162    G4cout << " G4PathFinder::DoNextCurvedStep ****** " << G4endl;
1163    G4cout << " Initial value of field track is " << fieldTrack
1164           << " and proposed step= " << proposedStepLength  << G4endl;
1165  }
1166#endif
1167
1168  fPreStepCenterRenewed= true; // Always update PreSafety with PreStep point
1169
1170  if( fNoActiveNavigators > 1 )
1171  { 
1172     // Calculate the safety values before making the step
1173
1174     G4double minSafety= kInfinity, safety; 
1175     for( numNav=0; numNav < fNoActiveNavigators; ++numNav )
1176     {
1177        safety= fpNavigator[numNav]->ComputeSafety( startPoint, false );
1178        fPreSafetyValues[numNav]= safety; 
1179        fCurrentPreStepSafety[numNav]= safety; 
1180        minSafety = std::min( safety, minSafety ); 
1181     }
1182
1183     // Save safety value, related position
1184
1185     fPreSafetyLocation=  startPoint;   
1186     fPreSafetyMinValue=  minSafety;
1187     fPreStepLocation=    startPoint;
1188     fMinSafety_PreStepPt= minSafety;
1189  }
1190
1191  // Allow Propagator In Field to do the hard work, calling G4MultiNavigator
1192  //
1193  minStep=  fpFieldPropagator->ComputeStep( fieldTrack,
1194                                            proposedStepLength,
1195                                            newSafety, 
1196                                            pCurrentPhysicalVolume );
1197
1198  // fieldTrack now contains the endpoint information
1199  //
1200  fEndState= fieldTrack; 
1201  fMinStep=   minStep; 
1202  fTrueMinStep = std::min( minStep, proposedStepLength );
1203
1204  if( fNoActiveNavigators== 1 )
1205  { 
1206     // Update the 'PreSafety' sphere - as any ComputeStep was called
1207     // (must be done anyway in field)
1208
1209     fPreSafetyValues[0]=   newSafety;
1210     fPreSafetyLocation= startPoint;   
1211     fPreSafetyMinValue= newSafety;
1212
1213     // Update the current 'PreStep' point's values - mandatory
1214     //
1215     fCurrentPreStepSafety[0]= newSafety; 
1216     fPreStepLocation=  startPoint;
1217     fMinSafety_PreStepPt= newSafety;
1218  }
1219
1220#ifdef G4DEBUG_PATHFINDER
1221  if( fVerboseLevel > 2 )
1222  {
1223    G4cout << "G4PathFinder::DoNextCurvedStep : " << G4endl
1224           << " initialState = " << initialState << G4endl
1225           << " and endState = " << fEndState << G4endl;
1226    G4cout << "G4PathFinder::DoNextCurvedStep : " 
1227           << " minStep = " << minStep
1228           << " proposedStepLength " << proposedStepLength
1229           << " safety = " << newSafety << G4endl;
1230  }
1231#endif
1232  G4double currentStepSize;   // = 0.0;
1233  if( minStep < proposedStepLength ) // if == , then a boundary found at end ??
1234  {   
1235    // Recover the remaining information from MultiNavigator
1236    // especially regarding which Navigator limited the step
1237
1238    G4int noLimited= 0;  //   No geometries limiting step
1239    for( numNav=0; numNav < fNoActiveNavigators; ++numNav )
1240    {
1241      G4double finalStep, lastPreSafety=0.0, minStepLast;
1242      ELimited didLimit; 
1243      G4bool limited; 
1244
1245      finalStep=  fpMultiNavigator->ObtainFinalStep( numNav, lastPreSafety, 
1246                                                     minStepLast, didLimit );
1247
1248      // Calculate the step for this geometry, using the
1249      // final step (the only one which can differ.)
1250
1251      currentStepSize = fTrueMinStep; 
1252      G4double diffStep= 0.0; 
1253      if( (minStepLast != kInfinity) )
1254      { 
1255        diffStep = (finalStep-minStepLast);
1256        if ( std::abs(diffStep) <= toleratedRelativeError * finalStep ) 
1257        {
1258          diffStep = 0.0;
1259        }
1260        currentStepSize += diffStep; 
1261      }
1262      fCurrentStepSize[numNav] = currentStepSize; 
1263     
1264      // TODO: could refine the way to obtain safeties for > 1 geometries
1265      //     - for pre step safety
1266      //        notify MultiNavigator about new set of sub-steps
1267      //        allow it to return this value in ObtainFinalStep
1268      //        instead of lastPreSafety (or as well?)
1269      //     - for final step start (available)
1270      //        get final Step start from MultiNavigator
1271      //        and corresponding safety values
1272      // and/or ALSO calculate ComputeSafety at endpoint
1273      //     endSafety= fpNavigator[numNav]->ComputeSafety( endPoint );
1274
1275      fLimitedStep[numNav] = didLimit; 
1276      fLimitTruth[numNav] = limited = (didLimit != kDoNot ); 
1277      if( limited ) { noLimited++; }
1278
1279#ifdef G4DEBUG_PATHFINDER
1280      G4bool StepError= (currentStepSize < 0) 
1281                   || ( (minStepLast != kInfinity) && (diffStep < 0) ) ; 
1282      if( StepError || (fVerboseLevel > 2) )
1283      {
1284        G4String  limitedString=  LimitedString( fLimitedStep[numNav] ); 
1285       
1286        G4cout << " G4PathFinder::ComputeStep. Geometry " << numNav
1287               << "  step= " << fCurrentStepSize[numNav] 
1288               << " from final-step= " << finalStep
1289               << " fTrueMinStep= " << fTrueMinStep
1290               << " minStepLast= "  << minStepLast
1291               << "  limited = " << (fLimitTruth[numNav] ? "YES" : " NO")
1292               << " ";
1293        G4cout << "  status = " << limitedString << " #= " << didLimit
1294               << G4endl;
1295       
1296        if( StepError )
1297        { 
1298           G4cerr << " currentStepSize = " << currentStepSize
1299                 << " diffStep= " << diffStep << G4endl;
1300           G4cerr << "ERROR in computing step size for this navigator."
1301                  << G4endl;
1302           G4Exception("G4PathFinder::DoNextCurvedStep",
1303                       "207-StepGoingBackwards", FatalException, 
1304                       "Incorrect calculation of step size for one navigator");
1305        }
1306      }
1307#endif
1308    } // for num Navigators
1309
1310    fNoGeometriesLimiting= noLimited;  // Save # processes limiting step
1311  } 
1312  else if ( (minStep == proposedStepLength) 
1313            || (minStep == kInfinity) 
1314            || ( std::abs(minStep-proposedStepLength)
1315               < toleratedRelativeError * proposedStepLength ) )
1316  { 
1317    // In case the step was not limited, use default responses
1318    //  --> all Navigators
1319    // Also avoid problems in case of PathFinder using safety to optimise
1320    //  - it is possible that the Navigators were not called
1321    //    if the safety was already satisfactory.
1322    //    (In that case calling ObtainFinalStep gives invalid results.)
1323
1324    currentStepSize= minStep;
1325    for( numNav=0; numNav < fNoActiveNavigators; ++numNav )
1326    {
1327      fCurrentStepSize[numNav] = minStep; 
1328      // Safety for endpoint ??  // Can eventuall improve it -- see TODO above
1329      fLimitedStep[numNav] = kDoNot; 
1330      fLimitTruth[numNav] = false; 
1331    }
1332    fNoGeometriesLimiting= 0;  // Save # processes limiting step
1333  } 
1334  else    //  (minStep > proposedStepLength) and not (minStep == kInfinity)
1335  {
1336    G4cerr << G4endl;
1337    G4cerr << "ERROR - G4PathFinder::DoNextCurvedStep()" << G4endl
1338           << "        currentStepSize = " << minStep << " is larger than "
1339           << " proposed StepSize = " << proposedStepLength << "." << G4endl;
1340    G4Exception("G4PathFinder::DoNextCurvedStep()",
1341                "208-StepLongerThanRequested", FatalException, 
1342                "Incorrect calculation of step size for one navigator."); 
1343  }
1344
1345#ifdef G4DEBUG_PATHFINDER
1346  if( fVerboseLevel > 2 )
1347  {
1348    G4cout << " Exiting G4PathFinder::DoNextCurvedStep " << G4endl;
1349    PrintLimited(); 
1350  }
1351  G4cout.precision(prc); 
1352#endif
1353
1354  return minStep; 
1355}
1356
1357G4String& G4PathFinder::LimitedString( ELimited lim )
1358{
1359  static G4String StrDoNot("DoNot"),
1360                  StrUnique("Unique"),
1361                  StrUndefined("Undefined"),
1362                  StrSharedTransport("SharedTransport"), 
1363                  StrSharedOther("SharedOther");
1364
1365  G4String* limitedStr;
1366  switch ( lim )
1367  {
1368     case kDoNot:  limitedStr= &StrDoNot; break;
1369     case kUnique: limitedStr = &StrUnique; break; 
1370     case kSharedTransport:  limitedStr= &StrSharedTransport; break; 
1371     case kSharedOther: limitedStr = &StrSharedOther; break;
1372     default: limitedStr = &StrUndefined; break;
1373  }
1374  return *limitedStr;
1375}
1376
1377void G4PathFinder::PushPostSafetyToPreSafety()
1378{
1379  fPreSafetyLocation= fSafetyLocation;
1380  fPreSafetyMinValue= fMinSafety_atSafLocation;
1381  for( register G4int nav=0; nav < fNoActiveNavigators; ++nav )
1382  {
1383     fPreSafetyValues[nav]= fNewSafetyComputed[nav];
1384  }
1385}
Note: See TracBrowser for help on using the repository browser.