Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer << 3 // * DISCLAIMER * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th << 5 // * The following disclaimer summarizes all the specific disclaimers * 6 // * the Geant4 Collaboration. It is provided << 6 // * of contributors to this software. The specific disclaimers,which * 7 // * conditions of the Geant4 Software License << 7 // * govern, are listed with their locations in: * 8 // * LICENSE and available at http://cern.ch/ << 8 // * http://cern.ch/geant4/license * 9 // * include a list of copyright holders. << 10 // * 9 // * * 11 // * Neither the authors of this software syst 10 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 11 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 12 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 13 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file << 14 // * use. * 16 // * for the full disclaimer and the limitatio << 17 // * 15 // * * 18 // * This code implementation is the result << 16 // * This code implementation is the intellectual property of the * 19 // * technical work of the GEANT4 collaboratio << 17 // * GEANT4 collaboration. * 20 // * By using, copying, modifying or distri << 18 // * By copying, distributing or modifying the Program (or any work * 21 // * any work based on the software) you ag << 19 // * based on the Program) you indicate your acceptance of this * 22 // * use in resulting scientific publicati << 20 // * statement, and all its terms. * 23 // * acceptance of all terms of the Geant4 Sof << 24 // ******************************************* 21 // ******************************************************************** 25 // 22 // 26 // class G4PropagatorInField Implementation << 23 // >> 24 // $Id: G4PropagatorInField.cc,v 1.20 2004/12/02 09:31:23 gcosmo Exp $ >> 25 // GEANT4 tag $Name: geant4-07-00-cand-03 $ >> 26 // 27 // 27 // 28 // This class implements an algorithm to trac 28 // This class implements an algorithm to track a particle in a 29 // non-uniform magnetic field. It utilises an 29 // non-uniform magnetic field. It utilises an ODE solver (with 30 // the Runge - Kutta method) to evolve the pa 30 // the Runge - Kutta method) to evolve the particle, and drives it 31 // until the particle has traveled a set dist 31 // until the particle has traveled a set distance or it enters a new 32 // volume. 32 // volume. 33 // 33 // 34 // 14.10.96 John Apostolakis, design and imple << 34 // 14.10.96 John Apostolakis, design and implementation 35 // 17.03.97 John Apostolakis, renaming new set << 35 // 17.03.97 John Apostolakis, renaming new set functions being added >> 36 // 36 // ------------------------------------------- 37 // --------------------------------------------------------------------------- 37 38 38 #include <iomanip> << 39 << 40 #include "G4PropagatorInField.hh" 39 #include "G4PropagatorInField.hh" 41 #include "G4ios.hh" 40 #include "G4ios.hh" 42 #include "G4SystemOfUnits.hh" << 41 #include <iomanip> >> 42 43 #include "G4ThreeVector.hh" 43 #include "G4ThreeVector.hh" 44 #include "G4Material.hh" << 45 #include "G4VPhysicalVolume.hh" 44 #include "G4VPhysicalVolume.hh" 46 #include "G4Navigator.hh" 45 #include "G4Navigator.hh" 47 #include "G4GeometryTolerance.hh" << 48 #include "G4VCurvedTrajectoryFilter.hh" 46 #include "G4VCurvedTrajectoryFilter.hh" 49 #include "G4ChordFinder.hh" 47 #include "G4ChordFinder.hh" 50 #include "G4MultiLevelLocator.hh" << 51 << 52 48 53 // ------------------------------------------- << 49 /////////////////////////////////////////////////////////////////////////// 54 // Constructors and destructor << 55 // 50 // 56 G4PropagatorInField::G4PropagatorInField( G4Na << 51 // Constructors and destructor 57 G4Fi << 52 58 G4VI << 53 G4PropagatorInField::G4PropagatorInField( G4Navigator *theNavigator, >> 54 G4FieldManager *detectorFieldMgr ) 59 : fDetectorFieldMgr(detectorFieldMgr), 55 : fDetectorFieldMgr(detectorFieldMgr), >> 56 fCurrentFieldMgr(detectorFieldMgr), 60 fNavigator(theNavigator), 57 fNavigator(theNavigator), 61 fCurrentFieldMgr(detectorFieldMgr), << 62 End_PointAndTangent(G4ThreeVector(0.,0.,0. 58 End_PointAndTangent(G4ThreeVector(0.,0.,0.), 63 G4ThreeVector(0.,0.,0. << 59 G4ThreeVector(0.,0.,0.),0.0,0.0,0.0,0.0,0.0), >> 60 fParticleIsLooping(false), >> 61 fVerboseLevel(0), >> 62 fMax_loop_count(1000), >> 63 fNoZeroStep(0), >> 64 fCharge(0.0), fInitialMomentumModulus(0.0), fMass(0.0), >> 65 fUseSafetyForOptimisation(true), // (false) is less sensitive to incorrect safety >> 66 fSetFieldMgr(false), >> 67 fpTrajectoryFilter( 0 ) 64 { 68 { 65 fEpsilonStep = (fDetectorFieldMgr != nullptr << 69 if(fDetectorFieldMgr) { fEpsilonStep = fDetectorFieldMgr->GetMaximumEpsilonStep();} 66 ? fDetectorFieldMgr->GetMaximum << 70 else { fEpsilonStep= 1.0e-5; } 67 << 71 fActionThreshold_NoZeroSteps = 2; 68 << 72 fSevereActionThreshold_NoZeroSteps = 10; 69 fPreviousSftOrigin = G4ThreeVector(0.,0.,0.) << 73 fAbandonThreshold_NoZeroSteps = 50; 70 kCarTolerance = G4GeometryTolerance::GetInst << 74 fFull_CurveLen_of_LastAttempt = -1; 71 fZeroStepThreshold = std::max( 1.0e5 * kCarT << 75 fLast_ProposedStepLength = -1; 72 << 76 fLargestAcceptableStep = 1000.0 * meter; 73 fLargestAcceptableStep = 100.0 * meter; // << 74 fMaxStepSizeMultiplier= 0.1 ; // 0.1 in << 75 fMinBigDistance= 100. * CLHEP::mm; << 76 #ifdef G4DEBUG_FIELD << 77 G4cout << " PiF: Zero Step Threshold set to << 78 << fZeroStepThreshold / millimeter << 79 << " mm." << G4endl; << 80 G4cout << " PiF: Value of kCarTolerance = << 81 << kCarTolerance / millimeter << 82 << " mm. " << G4endl; << 83 fVerboseLevel = 2; << 84 fVerbTracePiF = true; << 85 #endif << 86 77 87 // Defining Intersection Locator and his par << 78 fPreviousSftOrigin= G4ThreeVector(0.,0.,0.); 88 if ( vLocator == nullptr ) << 79 fPreviousSafety= 0.0; 89 { << 90 fIntersectionLocator = new G4MultiLevelLoc << 91 fAllocatedLocator = true; << 92 } << 93 else << 94 { << 95 fIntersectionLocator = vLocator; << 96 fAllocatedLocator = false; << 97 } << 98 RefreshIntersectionLocator(); // Copy all << 99 } 80 } 100 81 101 // ------------------------------------------- << 102 // << 103 G4PropagatorInField::~G4PropagatorInField() 82 G4PropagatorInField::~G4PropagatorInField() 104 { 83 { 105 if(fAllocatedLocator) { delete fIntersecti << 106 } 84 } 107 85 108 // ------------------------------------------- << 86 /////////////////////////////////////////////////////////////////////////// 109 // Update the IntersectionLocator with current << 110 // 87 // 111 void G4PropagatorInField::RefreshIntersectionL << 112 { << 113 fIntersectionLocator->SetEpsilonStepFor(fEps << 114 fIntersectionLocator->SetDeltaIntersectionFo << 115 fIntersectionLocator->SetChordFinderFor(GetC << 116 fIntersectionLocator->SetSafetyParametersFor << 117 } << 118 << 119 // ------------------------------------------- << 120 // Compute the next geometric Step 88 // Compute the next geometric Step 121 // << 89 122 G4double G4PropagatorInField::ComputeStep( << 90 G4double >> 91 G4PropagatorInField::ComputeStep( 123 G4FieldTrack& pFieldTrack 92 G4FieldTrack& pFieldTrack, 124 G4double CurrentProp 93 G4double CurrentProposedStepLength, 125 G4double& currentSafe 94 G4double& currentSafety, // IN/OUT 126 G4VPhysicalVolume* pPhysVol, << 95 G4VPhysicalVolume* pPhysVol) 127 G4bool canRelaxDel << 96 { 128 { << 129 GetChordFinder()->OnComputeStep(&pFieldTrack << 130 const G4double deltaChord = GetChordFinder() << 131 << 132 // If CurrentProposedStepLength is too small 97 // If CurrentProposedStepLength is too small for finding Chords 133 // then return with no action (for now - TOD << 98 // just forget. 134 // << 99 if(CurrentProposedStepLength<kCarTolerance) return DBL_MAX; 135 const char* methodName = "G4PropagatorInFiel << 136 if (CurrentProposedStepLength<kCarTolerance) << 137 { << 138 return kInfinity; << 139 } << 140 100 141 // Introducing smooth trajectory display (ja 101 // Introducing smooth trajectory display (jacek 01/11/2002) 142 // << 102 if (fpTrajectoryFilter) { 143 if (fpTrajectoryFilter != nullptr) << 144 { << 145 fpTrajectoryFilter->CreateNewTrajectorySeg 103 fpTrajectoryFilter->CreateNewTrajectorySegment(); 146 } 104 } 147 105 148 fFirstStepInVolume = fNewTrack ? true : fLas << 149 fLastStepInVolume = false; << 150 fNewTrack = false; << 151 << 152 if( fVerboseLevel > 2 ) << 153 { << 154 G4cout << methodName << " called" << G4end << 155 G4cout << " Starting FT: " << pFieldTrac << 156 G4cout << " Requested length = " << Curr << 157 G4cout << " PhysVol = "; << 158 if( pPhysVol != nullptr ) << 159 { << 160 G4cout << pPhysVol->GetName() << G4endl << 161 } << 162 else << 163 { << 164 G4cout << " N/A "; << 165 } << 166 G4cout << G4endl; << 167 } << 168 << 169 // Parameters for adaptive Runge-Kutta integ 106 // Parameters for adaptive Runge-Kutta integration 170 107 171 G4double h_TrialStepSize; // 1st Step << 108 G4double h_TrialStepSize; // 1st Step Size 172 G4double TruePathLength = CurrentProposedSte << 109 G4double TruePathLength = CurrentProposedStepLength; 173 G4double StepTaken = 0.0; << 110 G4double StepTaken = 0.0; 174 G4double s_length_taken, epsilon; << 111 G4double s_length_taken, epsilon ; 175 G4bool intersects; << 112 G4bool intersects; 176 G4bool first_substep = true; << 113 G4bool first_substep = true; 177 114 178 G4double NewSafety; << 115 G4double NewSafety; 179 fParticleIsLooping = false; 116 fParticleIsLooping = false; 180 117 181 // If not yet done, 118 // If not yet done, 182 // Set the field manager to the local one 119 // Set the field manager to the local one if the volume has one, 183 // or to the global one 120 // or to the global one if not 184 // 121 // 185 if( !fSetFieldMgr ) << 122 if( !fSetFieldMgr ) fCurrentFieldMgr= FindAndSetFieldManager( pPhysVol ); 186 { << 123 // For the next call, the field manager must again be set 187 fCurrentFieldMgr = FindAndSetFieldManager( << 124 fSetFieldMgr= false; 188 } << 189 fSetFieldMgr = false; // For next call, the << 190 125 191 G4FieldTrack CurrentState(pFieldTrack); << 126 GetChordFinder()->SetChargeMomentumMass(fCharge, fInitialMomentumModulus, fMass); 192 G4FieldTrack OriginalState = CurrentState; << 127 >> 128 G4FieldTrack CurrentState(pFieldTrack); >> 129 G4FieldTrack OriginalState = CurrentState; 193 130 194 // If the Step length is "infinite", then an 131 // If the Step length is "infinite", then an approximate-maximum Step 195 // length (used to calculate the relative ac << 132 // length (used to calculate the relative accuracy) must be guessed. 196 // 133 // 197 if( CurrentProposedStepLength >= fLargestAcc 134 if( CurrentProposedStepLength >= fLargestAcceptableStep ) 198 { 135 { 199 G4ThreeVector StartPointA, VelocityUnit; 136 G4ThreeVector StartPointA, VelocityUnit; 200 StartPointA = pFieldTrack.GetPosition(); 137 StartPointA = pFieldTrack.GetPosition(); 201 VelocityUnit = pFieldTrack.GetMomentumDir( 138 VelocityUnit = pFieldTrack.GetMomentumDir(); 202 139 203 G4double trialProposedStep = fMaxStepSizeM << 140 G4double trialProposedStep = 1.e2 * ( 10.0 * cm + 204 fNavigator->GetWorldVolume()->GetLogical 141 fNavigator->GetWorldVolume()->GetLogicalVolume()-> 205 GetSolid()->DistanceToOut(St 142 GetSolid()->DistanceToOut(StartPointA, VelocityUnit) ); 206 CurrentProposedStepLength = std::min( tria << 143 CurrentProposedStepLength= std::min( trialProposedStep, 207 fLar << 144 fLargestAcceptableStep ); 208 } 145 } 209 epsilon = fCurrentFieldMgr->GetDeltaOneStep( << 146 epsilon = GetDeltaOneStep() / CurrentProposedStepLength; >> 147 // G4double raw_epsilon= epsilon; 210 G4double epsilonMin= fCurrentFieldMgr->GetMi 148 G4double epsilonMin= fCurrentFieldMgr->GetMinimumEpsilonStep(); 211 G4double epsilonMax= fCurrentFieldMgr->GetMa << 149 G4double epsilonMax= fCurrentFieldMgr->GetMaximumEpsilonStep();; 212 if( epsilon < epsilonMin ) { epsilon = epsi << 150 if( epsilon < epsilonMin ) epsilon = epsilonMin; 213 if( epsilon > epsilonMax ) { epsilon = epsi << 151 if( epsilon > epsilonMax ) epsilon = epsilonMax; 214 SetEpsilonStep( epsilon ); 152 SetEpsilonStep( epsilon ); 215 153 216 // Values for Intersection Locator has to be << 154 // G4cout << "G4PiF: Epsilon of current step - raw= " << raw_epsilon 217 // case that CurrentFieldManager has changed << 155 // << " final= " << epsilon << G4endl; 218 // << 219 RefreshIntersectionLocator(); << 220 156 221 // Shorten the proposed step in case of earl << 157 // Shorten the proposed step in case of earlier problems (zero steps) 222 // 158 // 223 if( fNoZeroStep > fActionThreshold_NoZeroSte 159 if( fNoZeroStep > fActionThreshold_NoZeroSteps ) 224 { 160 { 225 G4double stepTrial; 161 G4double stepTrial; 226 162 227 stepTrial = fFull_CurveLen_of_LastAttempt; << 163 stepTrial= fFull_CurveLen_of_LastAttempt; 228 if( (stepTrial <= 0.0) && (fLast_ProposedS << 164 if( (stepTrial <= 0.0) && (fLast_ProposedStepLength > 0.0) ) 229 { << 165 stepTrial= fLast_ProposedStepLength; 230 stepTrial = fLast_ProposedStepLength; << 231 } << 232 166 233 G4double decreaseFactor = 0.9; // Unused d 167 G4double decreaseFactor = 0.9; // Unused default 234 if( (fNoZeroStep < fSevereActionThreshol 168 if( (fNoZeroStep < fSevereActionThreshold_NoZeroSteps) 235 && (stepTrial > 100.0*fZeroStepThreshol << 169 && (stepTrial > 1000.0*kCarTolerance) ) 236 { 170 { 237 // Attempt quick convergence << 171 // Ensure quicker convergence 238 // 172 // 239 decreaseFactor= 0.25; << 173 decreaseFactor= 0.1; 240 } 174 } 241 else 175 else 242 { 176 { 243 // We are in significant difficulties, p 177 // We are in significant difficulties, probably at a boundary that 244 // is either geometrically sharp or betw 178 // is either geometrically sharp or between very different materials. 245 // Careful decreases to cope with tolera << 179 // Careful decreases to cope with tolerance are required. 246 // 180 // 247 if( stepTrial > 100.0*fZeroStepThreshold << 181 if( stepTrial > 1000.0*kCarTolerance ) 248 decreaseFactor = 0.35; // Try decr << 182 decreaseFactor = 0.25; // Try slow decreases 249 } else if( stepTrial > 30.0*fZeroStepThr << 183 else if( stepTrial > 100.0*kCarTolerance ) 250 decreaseFactor= 0.5; // Try yet << 184 decreaseFactor= 0.5; // Try slower decreases 251 } else if( stepTrial > 10.0*fZeroStepThr << 185 else if( stepTrial > 10.0*kCarTolerance ) 252 decreaseFactor= 0.75; // Try even 186 decreaseFactor= 0.75; // Try even slower decreases 253 } else { << 187 else 254 decreaseFactor= 0.9; // Try very 188 decreaseFactor= 0.9; // Try very slow decreases 255 } << 256 } 189 } 257 stepTrial *= decreaseFactor; 190 stepTrial *= decreaseFactor; 258 191 259 #ifdef G4DEBUG_FIELD 192 #ifdef G4DEBUG_FIELD 260 if( fVerboseLevel > 2 << 193 PrintStepLengthDiagnostic(CurrentProposedStepLength, decreaseFactor, 261 || (fNoZeroStep >= fSevereActionThreshol << 194 stepTrial, pFieldTrack); 262 { << 263 G4cerr << " " << methodName << 264 << " Decreasing step after " < << 265 << " - in volume " << pPhysVol; << 266 if( pPhysVol ) << 267 G4cerr << " with name " << pPhysVol << 268 else << 269 G4cerr << " i.e. *unknown* volume." << 270 G4cerr << G4endl; << 271 PrintStepLengthDiagnostic(CurrentPropo << 272 stepTrial, p << 273 } << 274 #endif 195 #endif 275 if( stepTrial == 0.0 ) // Change to mak << 196 if( stepTrial == 0.0 ) 276 { 197 { 277 std::ostringstream message; << 198 G4cout << " G4PropagatorInField::ComputeStep " 278 message << "Particle abandoned due to l << 199 << " Particle abandoned due to lack of progress in field." 279 << G4endl << 200 << G4endl 280 << " Properties : " << pFieldT << 201 << " Properties : " << pFieldTrack << " " 281 << " Attempting a zero step = << 202 << G4endl; 282 << " while attempting to progr << 203 G4cerr << " G4PropagatorInField::ComputeStep " 283 << " trial steps. Will abandon << 204 << " ERROR : attempting a zero step= " << stepTrial << G4endl 284 G4Exception(methodName, "GeomNav1002", << 205 << " while attempting to progress after " << fNoZeroStep 285 fParticleIsLooping = true; << 206 << " trial steps. Will abandon step." << G4endl; 286 return 0; // = stepTrial; << 207 fParticleIsLooping= true; >> 208 return 0; // = stepTrial; 287 } 209 } 288 if( stepTrial < CurrentProposedStepLength 210 if( stepTrial < CurrentProposedStepLength ) 289 { << 290 CurrentProposedStepLength = stepTrial; 211 CurrentProposedStepLength = stepTrial; 291 } << 292 } 212 } 293 fLast_ProposedStepLength = CurrentProposedSt 213 fLast_ProposedStepLength = CurrentProposedStepLength; 294 214 295 G4int do_loop_count = 0; 215 G4int do_loop_count = 0; 296 do // Loop checking, 07.10.2016, JA << 216 do 297 { 217 { 298 G4FieldTrack SubStepStartState = CurrentSt 218 G4FieldTrack SubStepStartState = CurrentState; 299 G4ThreeVector SubStartPoint = CurrentState 219 G4ThreeVector SubStartPoint = CurrentState.GetPosition(); 300 << 220 301 if(!first_substep) << 221 if( !first_substep) { 302 { << 303 if( fVerboseLevel > 4 ) << 304 { << 305 G4cout << " PiF: Calling Nav/Locate Gl << 306 << G4endl; << 307 } << 308 fNavigator->LocateGlobalPointWithinVolum 222 fNavigator->LocateGlobalPointWithinVolume( SubStartPoint ); 309 } 223 } 310 224 311 // How far to attempt to move the particle 225 // How far to attempt to move the particle ! 312 // 226 // 313 h_TrialStepSize = CurrentProposedStepLengt 227 h_TrialStepSize = CurrentProposedStepLength - StepTaken; 314 228 315 if (canRelaxDeltaChord && << 316 fIncreaseChordDistanceThreshold > 0 & << 317 do_loop_count > fIncreaseChordDistance << 318 do_loop_count % fIncreaseChordDistance << 319 { << 320 GetChordFinder()->SetDeltaChord( << 321 GetChordFinder()->GetDeltaChord() * << 322 ); << 323 } << 324 << 325 // Integrate as far as "chord miss" rule a 229 // Integrate as far as "chord miss" rule allows. 326 // 230 // 327 s_length_taken = GetChordFinder()->Advance 231 s_length_taken = GetChordFinder()->AdvanceChordLimited( 328 CurrentState, 232 CurrentState, // Position & velocity 329 h_TrialStepSize, 233 h_TrialStepSize, 330 fEpsilonStep, 234 fEpsilonStep, 331 fPreviousSftOrigi 235 fPreviousSftOrigin, 332 fPreviousSafety ) << 236 fPreviousSafety 333 // CurrentState is now updated with the << 237 ); >> 238 // CurrentState is now updated with the final position and velocity. 334 239 335 fFull_CurveLen_of_LastAttempt = s_length_t 240 fFull_CurveLen_of_LastAttempt = s_length_taken; 336 241 337 G4ThreeVector EndPointB = CurrentState.Get << 242 G4ThreeVector EndPointB = CurrentState.GetPosition(); 338 G4ThreeVector InterSectionPointE; << 243 G4ThreeVector InterSectionPointE; 339 G4double LinearStepLength; << 244 G4double LinearStepLength; 340 245 341 // Intersect chord AB with geometry 246 // Intersect chord AB with geometry 342 // << 343 intersects= IntersectChord( SubStartPoint, 247 intersects= IntersectChord( SubStartPoint, EndPointB, 344 NewSafety, Lin << 248 NewSafety, LinearStepLength, 345 InterSectionPo << 249 InterSectionPointE ); 346 // E <- Intersection Point of chord AB a << 250 // E <- Intersection Point of chord AB and either volume A's surface 347 // or a << 251 // or a daughter volume's surface .. 348 252 349 if( first_substep ) << 253 if( first_substep ) { 350 { << 351 currentSafety = NewSafety; 254 currentSafety = NewSafety; 352 } // Updating safety in other steps is pot 255 } // Updating safety in other steps is potential future extention 353 256 354 if( intersects ) 257 if( intersects ) 355 { 258 { 356 G4FieldTrack IntersectPointVelct_G(Curr 259 G4FieldTrack IntersectPointVelct_G(CurrentState); // FT-Def-Construct 357 260 358 // Find the intersection point of AB tr 261 // Find the intersection point of AB true path with the surface 359 // of vol(A), if it exists. Start wit 262 // of vol(A), if it exists. Start with point E as first "estimate". 360 G4bool recalculatedEndPt = false; << 263 G4bool recalculatedEndPt= false; 361 << 264 G4bool found_intersection = 362 G4bool found_intersection = fIntersecti << 265 LocateIntersectionPoint( SubStepStartState, CurrentState, 363 EstimateIntersectionPoint( SubStepSta << 266 InterSectionPointE, IntersectPointVelct_G, 364 InterSecti << 267 recalculatedEndPt); 365 recalculat << 268 intersects = intersects && found_intersection; 366 fPreviousS << 269 if( found_intersection ) { 367 intersects = found_intersection; << 368 if( found_intersection ) << 369 { << 370 End_PointAndTangent= IntersectPointV 270 End_PointAndTangent= IntersectPointVelct_G; // G is our EndPoint ... 371 StepTaken = TruePathLength = Interse 271 StepTaken = TruePathLength = IntersectPointVelct_G.GetCurveLength() 372 - Origina << 272 - OriginalState.GetCurveLength(); 373 } << 273 } else { 374 else << 274 // intersects= false; // "Minor" chords do not intersect 375 { << 275 if( recalculatedEndPt ){ 376 // Either "minor" chords do not inte << 276 CurrentState= IntersectPointVelct_G; 377 // or else stopped (due to too many << 277 } 378 // << 379 if( recalculatedEndPt ) << 380 { << 381 G4double endAchieved = IntersectP << 382 G4double endExpected = CurrentSta << 383 << 384 // Detect failure - due to too ma << 385 G4bool shortEnd = endAchieved << 386 < (endExpected*(1 << 387 << 388 G4double stepAchieved = endAchiev << 389 - SubStepSt << 390 << 391 // Update remaining state - must << 392 // abandonned intersection << 393 // << 394 CurrentState = IntersectPointVelc << 395 s_length_taken = stepAchieved; << 396 if( shortEnd ) << 397 { << 398 fParticleIsLooping = true; << 399 } << 400 } << 401 } 278 } 402 } 279 } 403 if( !intersects ) 280 if( !intersects ) 404 { 281 { 405 StepTaken += s_length_taken; << 282 StepTaken += s_length_taken; 406 << 283 // For smooth trajectory display (jacek 01/11/2002) 407 if (fpTrajectoryFilter != nullptr) // Fo << 284 if (fpTrajectoryFilter) { 408 { << 409 fpTrajectoryFilter->TakeIntermediatePo 285 fpTrajectoryFilter->TakeIntermediatePoint(CurrentState.GetPosition()); 410 } 286 } 411 } 287 } 412 first_substep = false; 288 first_substep = false; 413 289 414 #ifdef G4DEBUG_FIELD 290 #ifdef G4DEBUG_FIELD 415 if( fNoZeroStep > fActionThreshold_NoZeroS << 291 if( fNoZeroStep > fActionThreshold_NoZeroSteps ) { 416 { << 417 if( fNoZeroStep > fSevereActionThreshold << 418 G4cout << " Above 'Severe Action' thre << 419 else << 420 G4cout << " Above 'action' threshold - << 421 G4cout << " Number of zero steps = " << << 422 printStatus( SubStepStartState, // or O 292 printStatus( SubStepStartState, // or OriginalState, 423 CurrentState, CurrentPropos << 293 CurrentState, CurrentProposedStepLength, 424 NewSafety, do_loop_count, p << 294 NewSafety, do_loop_count, pPhysVol ); 425 } 295 } 426 if( (fVerboseLevel > 1) && (do_loop_count << 296 #endif 427 { << 297 #ifdef G4VERBOSE 428 if( do_loop_count == fMax_loop_count-9 ) << 298 if( (fVerboseLevel > 1) && (do_loop_count > fMax_loop_count-10 )) { 429 { << 299 if( do_loop_count == fMax_loop_count-9 ){ 430 G4cout << " G4PropagatorInField::Compu << 300 G4cout << "G4PropagatorInField::ComputeStep " 431 << " Difficult track - taking << 301 << " Difficult track - taking many sub steps." << G4endl; 432 printStatus( SubStepStartState, SubSte << 433 NewSafety, 0, pPhysVol ); << 434 } 302 } 435 printStatus( SubStepStartState, CurrentS 303 printStatus( SubStepStartState, CurrentState, CurrentProposedStepLength, 436 NewSafety, do_loop_count, p << 304 NewSafety, do_loop_count, pPhysVol ); 437 } 305 } 438 #endif 306 #endif 439 307 440 ++do_loop_count; << 308 do_loop_count++; 441 309 442 } while( (!intersects ) 310 } while( (!intersects ) 443 && (!fParticleIsLooping) << 444 && (StepTaken + kCarTolerance < Curren 311 && (StepTaken + kCarTolerance < CurrentProposedStepLength) 445 && ( do_loop_count < fMax_loop_count ) 312 && ( do_loop_count < fMax_loop_count ) ); 446 313 447 if( do_loop_count >= fMax_loop_count << 314 if( do_loop_count >= fMax_loop_count ) 448 && (StepTaken + kCarTolerance < CurrentPro << 449 { 315 { 450 fParticleIsLooping = true; 316 fParticleIsLooping = true; >> 317 >> 318 if ( fVerboseLevel > 0 ){ >> 319 G4cout << "G4PropagateInField: Killing looping particle " >> 320 // << " of " << energy << " energy " >> 321 << " after " << do_loop_count << " field substeps " >> 322 << " totaling " << StepTaken / mm << " mm " ; >> 323 if( pPhysVol ) >> 324 G4cout << " in the volume " << pPhysVol->GetName() ; >> 325 else >> 326 G4cout << " in unknown or null volume. " ; >> 327 G4cout << G4endl; >> 328 } 451 } 329 } 452 if ( ( fParticleIsLooping ) && (fVerboseLeve << 330 453 { << 454 ReportLoopingParticle( do_loop_count, Step << 455 CurrentProposedStep << 456 CurrentState.GetMom << 457 } << 458 << 459 if( !intersects ) 331 if( !intersects ) 460 { 332 { 461 // Chord AB or "minor chords" do not inter 333 // Chord AB or "minor chords" do not intersect 462 // B is the endpoint Step of the current S 334 // B is the endpoint Step of the current Step. 463 // 335 // 464 End_PointAndTangent = CurrentState; 336 End_PointAndTangent = CurrentState; 465 TruePathLength = StepTaken; // Original << 337 TruePathLength = StepTaken; 466 << 467 // Tried the following to avoid potential << 468 // - but has issues... Suppressing this ch << 469 // TruePathLength = CurrentProposedStepLen << 470 } 338 } 471 fLastStepInVolume = intersects; << 472 339 473 // Set pFieldTrack to the return value 340 // Set pFieldTrack to the return value 474 // 341 // 475 pFieldTrack = End_PointAndTangent; 342 pFieldTrack = End_PointAndTangent; 476 343 477 #ifdef G4VERBOSE 344 #ifdef G4VERBOSE 478 // Check that "s" is correct 345 // Check that "s" is correct 479 // 346 // 480 if( std::fabs(OriginalState.GetCurveLength() 347 if( std::fabs(OriginalState.GetCurveLength() + TruePathLength 481 - End_PointAndTangent.GetCurveLength()) 348 - End_PointAndTangent.GetCurveLength()) > 3.e-4 * TruePathLength ) 482 { 349 { 483 std::ostringstream message; << 350 G4cerr << " ERROR - G4PropagatorInField::ComputeStep():" << G4endl 484 message << "Curve length mis-match between << 351 << " Curve length mis-match, is advancement wrong ? " << G4endl; 485 << "and proposed endpoint of propa << 352 G4cerr << " The curve length of the endpoint should be: " 486 << " The curve length of the endp << 353 << OriginalState.GetCurveLength() + TruePathLength << G4endl 487 << OriginalState.GetCurveLength() << 354 << " and it is instead: " 488 << " and it is instead: " << 355 << End_PointAndTangent.GetCurveLength() << "." << G4endl 489 << End_PointAndTangent.GetCurveLen << 356 << " A difference of: " 490 << " A difference of: " << 357 << OriginalState.GetCurveLength() + TruePathLength 491 << OriginalState.GetCurveLength() << 358 - End_PointAndTangent.GetCurveLength() << G4endl; 492 - End_PointAndTangent.GetCurveL << 359 G4cerr << " Original state= " << OriginalState << G4endl 493 << " Original state = " << Origin << 360 << " Proposed state= " << End_PointAndTangent << G4endl; 494 << " Proposed state = " << End_Po << 361 G4Exception("G4PropagatorInField::ComputeStep()", "IncorrectProposedEndPoint", 495 G4Exception(methodName, "GeomNav0003", Fat << 362 FatalException, >> 363 "Curve length mis-match between original state and proposed endpoint of propagation."); 496 } 364 } 497 #endif 365 #endif 498 366 499 if( TruePathLength+kCarTolerance >= CurrentP << 367 #ifdef G4DEBUG_FIELD 500 { << 368 // static G4std::vector<G4int> ZeroStepNumberHist(fAbandonThreshold+1); 501 fNoZeroStep = 0; << 369 if( fNoZeroStep ){ 502 } << 370 // ZeroStepNumberHist[fNoZeroStep]++; 503 else << 371 if( fNoZeroStep > fActionThreshold_NoZeroSteps ){ 504 { << 372 G4cout << " PiF: Step returning=" << StepTaken << G4endl; 505 // In particular anomalous cases, we can << 373 G4cout << " ------------------------------------------------------- " 506 // We identify these cases and take corre << 374 << G4endl; 507 // << 508 if( TruePathLength < std::max( fZeroStepT << 509 { << 510 ++fNoZeroStep; << 511 } << 512 else << 513 { << 514 fNoZeroStep = 0; << 515 } 375 } 516 } 376 } 517 if( fNoZeroStep > fAbandonThreshold_NoZeroSt << 377 #endif 518 { << 378 >> 379 // In particular anomalous cases, we can get repeated zero steps >> 380 // In order to correct this efficiently, we identify these cases >> 381 // and only take corrective action when they occur. >> 382 // >> 383 if( TruePathLength < 0.5*kCarTolerance ) >> 384 fNoZeroStep++; >> 385 else >> 386 fNoZeroStep = 0; >> 387 >> 388 if( fNoZeroStep > fAbandonThreshold_NoZeroSteps ) { 519 fParticleIsLooping = true; 389 fParticleIsLooping = true; 520 ReportStuckParticle( fNoZeroStep, Current << 390 G4cout << " WARNING - G4PropagatorInField::ComputeStep():" << G4endl 521 fFull_CurveLen_of_La << 391 << " Zero progress for " << fNoZeroStep << " attempted steps." >> 392 << G4endl; >> 393 #ifdef G4VERBOSE >> 394 if ( fVerboseLevel > 2 ) >> 395 G4cout << " Particle that is stuck will be killed." << G4endl; >> 396 #endif 522 fNoZeroStep = 0; 397 fNoZeroStep = 0; 523 } 398 } 524 << 399 525 GetChordFinder()->SetDeltaChord(deltaChord); << 400 #ifdef G4VERBOSE >> 401 if ( fVerboseLevel > 3 ){ >> 402 G4cout << "G4PropagatorInField returns " << TruePathLength << G4endl; >> 403 } >> 404 #endif >> 405 526 return TruePathLength; 406 return TruePathLength; 527 } 407 } 528 408 529 // ------------------------------------------- << 409 // -------------------------------------------------------------------------- 530 // Dumps status of propagator << 410 // G4bool >> 411 // G4PropagatorInField::LocateIntersectionPoint( >> 412 // const G4FieldTrack& CurveStartPointVelocity, // A >> 413 // const G4FieldTrack& CurveEndPointVelocity, // B >> 414 // const G4ThreeVector& TrialPoint, // E >> 415 // G4FieldTrack& IntersectedOrRecalculated // Output >> 416 // G4bool& recalculated) // Out >> 417 // -------------------------------------------------------------------------- >> 418 // >> 419 // Function that returns the intersection of the true path with the surface >> 420 // of the current volume (either the external one or the inner one with one >> 421 // of the daughters >> 422 // >> 423 // A = Initial point >> 424 // B = another point >> 425 // >> 426 // Both A and B are assumed to be on the true path. >> 427 // >> 428 // E is the first point of intersection of the chord AB with >> 429 // a volume other than A (on the surface of A or of a daughter) >> 430 // >> 431 // Convention of Use : >> 432 // i) If it returns "true", then IntersectionPointVelocity is set >> 433 // to the approximate intersection point. >> 434 // ii) If it returns "false", no intersection was found. >> 435 // The validity of IntersectedOrRecalculated depends on 'recalculated' >> 436 // a) if latter is false, then IntersectedOrRecalculated is invalid. >> 437 // b) if latter is true, then IntersectedOrRecalculated is >> 438 // the new endpoint, due to a re-integration. >> 439 // -------------------------------------------------------------------------- >> 440 >> 441 G4bool >> 442 G4PropagatorInField::LocateIntersectionPoint( >> 443 const G4FieldTrack& CurveStartPointVelocity, // A >> 444 const G4FieldTrack& CurveEndPointVelocity, // B >> 445 const G4ThreeVector& TrialPoint, // E >> 446 G4FieldTrack& IntersectedOrRecalculatedFT, // Out: point found >> 447 G4bool& recalculatedEndPoint) // Out: >> 448 { >> 449 // Find Intersection Point ( A, B, E ) of true path AB - start at E. >> 450 >> 451 G4bool found_approximate_intersection = false; >> 452 G4bool there_is_no_intersection = false; >> 453 >> 454 G4FieldTrack CurrentA_PointVelocity = CurveStartPointVelocity; >> 455 G4FieldTrack CurrentB_PointVelocity = CurveEndPointVelocity; >> 456 G4ThreeVector CurrentE_Point = TrialPoint; >> 457 >> 458 G4FieldTrack ApproxIntersecPointV(CurveEndPointVelocity); // FT-Def-Construct >> 459 G4double NewSafety= -0.0; >> 460 G4bool final_section= true; // Shows whether current section is last (ie B=full end) >> 461 >> 462 recalculatedEndPoint= false; >> 463 >> 464 G4bool restoredFullEndpoint= false; >> 465 >> 466 G4int substep_no = 0; >> 467 const G4int max_substeps= 100; >> 468 >> 469 do{ // REPEAT >> 470 >> 471 G4ThreeVector Point_A = CurrentA_PointVelocity.GetPosition(); >> 472 G4ThreeVector Point_B = CurrentB_PointVelocity.GetPosition(); >> 473 >> 474 // F = a point on true AB path close to point E (the closest if possible) >> 475 // >> 476 ApproxIntersecPointV = >> 477 GetChordFinder()->ApproxCurvePointV( CurrentA_PointVelocity, >> 478 CurrentB_PointVelocity, >> 479 CurrentE_Point, >> 480 fEpsilonStep ); >> 481 // The above method is the key & most intuitive part ... >> 482 >> 483 #ifdef G4DEBUG_FIELD >> 484 if( ApproxIntersecPointV.GetCurveLength() > >> 485 CurrentB_PointVelocity.GetCurveLength() * (1.0 + kAngTolerance) ) { >> 486 G4cerr << "Error - Intermediate F point is more advanced than endpoint B." >> 487 << G4endl; >> 488 G4Exception("G4PropagatorInField::LocateIntersectionPoint()", >> 489 "IntermediatePointConfusion", >> 490 FatalException, "Intermediate F point is past end B point" ); >> 491 } >> 492 #endif >> 493 >> 494 G4ThreeVector CurrentF_Point= ApproxIntersecPointV.GetPosition(); >> 495 >> 496 // First check whether EF is small - then F is a good approx. point >> 497 // Calculate the length and direction of the chord AF >> 498 // >> 499 G4ThreeVector ChordEF_Vector = CurrentF_Point - CurrentE_Point; >> 500 >> 501 if ( ChordEF_Vector.mag2() <= sqr(GetDeltaIntersection()) ) >> 502 { >> 503 found_approximate_intersection = true; >> 504 >> 505 // Create the "point" return value >> 506 // >> 507 IntersectedOrRecalculatedFT = ApproxIntersecPointV; >> 508 IntersectedOrRecalculatedFT.SetPosition( CurrentE_Point ); >> 509 >> 510 // Note: in order to return a point on the boundary, >> 511 // we must return E. But it is F on the curve. >> 512 // So we must "cheat": we are using the position at point E >> 513 // and the velocity at point F !!! >> 514 // >> 515 // This must limit the length we can allow for displacement! >> 516 >> 517 } >> 518 else // E is NOT close enough to the curve (ie point F) >> 519 { >> 520 // Check whether any volumes are encountered by the chord AF >> 521 // --------------------------------------------------------- >> 522 // First relocate to restore any Voxel etc information in the Navigator >> 523 // before calling ComputeStep >> 524 fNavigator->LocateGlobalPointWithinVolume( Point_A ); >> 525 >> 526 G4ThreeVector PointG; // Candidate intersection point >> 527 G4double stepLengthAF; >> 528 G4bool Intersects_AF = IntersectChord( Point_A, CurrentF_Point, >> 529 NewSafety, stepLengthAF, >> 530 PointG >> 531 ); >> 532 if( Intersects_AF ) >> 533 { >> 534 // G is our new Candidate for the intersection point. >> 535 // It replaces "E" and we will repeat the test to see if >> 536 // it is a good enough approximate point for us. >> 537 // B <- F >> 538 // E <- G >> 539 CurrentB_PointVelocity = ApproxIntersecPointV; >> 540 CurrentE_Point = PointG; >> 541 >> 542 // By moving point B, must take care if current AF has no intersection >> 543 // to try current FB!! >> 544 final_section= false; >> 545 >> 546 #ifdef G4VERBOSE >> 547 if( fVerboseLevel > 3 ){ >> 548 G4cout << "G4PiF::LI> Investigating intermediate point" >> 549 << " at s=" << ApproxIntersecPointV.GetCurveLength() >> 550 << " on way to full s=" << CurveEndPointVelocity.GetCurveLength() >> 551 << G4endl; >> 552 } >> 553 #endif >> 554 } >> 555 else // not Intersects_AF >> 556 { >> 557 // In this case: >> 558 // There is NO intersection of AF with a volume boundary. >> 559 // We must continue the search in the segment FB! >> 560 fNavigator->LocateGlobalPointWithinVolume( CurrentF_Point ); >> 561 >> 562 G4double stepLengthFB; >> 563 G4ThreeVector PointH; >> 564 // Check whether any volumes are encountered by the chord FB >> 565 // --------------------------------------------------------- >> 566 G4bool Intersects_FB = >> 567 IntersectChord( CurrentF_Point, Point_B, >> 568 NewSafety, stepLengthFB, PointH ); >> 569 if( Intersects_FB ) >> 570 { >> 571 // There is an intersection of FB with a volume boundary >> 572 // H <- First Intersection of Chord FB >> 573 >> 574 // H is our new Candidate for the intersection point. >> 575 // It replaces "E" and we will repeat the test to see if >> 576 // it is a good enough approximate point for us. >> 577 >> 578 // Note that F must be in volume volA (the same as A) >> 579 // (otherwise AF would meet a volume boundary!) >> 580 // A <- F >> 581 // E <- H >> 582 CurrentA_PointVelocity = ApproxIntersecPointV; >> 583 CurrentE_Point = PointH; >> 584 } >> 585 else // not Intersects_FB >> 586 { >> 587 // There is NO intersection of FB with a volume boundary >> 588 if( final_section ){ >> 589 // If B is the original endpoint, this means that whatever volume(s) >> 590 // intersected the original chord, none touch the smaller chords >> 591 // we have used. >> 592 // The value of IntersectedOrRecalculatedFT returned is likely not valid >> 593 // >> 594 there_is_no_intersection = true; >> 595 }else{ >> 596 // We must restore the original endpoint >> 597 CurrentA_PointVelocity= CurrentB_PointVelocity; // We have got to B >> 598 CurrentB_PointVelocity= CurveEndPointVelocity; >> 599 restoredFullEndpoint = true; >> 600 } >> 601 >> 602 } // Endif (Intersects_FB) >> 603 } // Endif (Intersects_AF) >> 604 >> 605 // Ensure that the new endpoints are not further apart in space >> 606 // than on the curve due to different errors in the integration >> 607 // >> 608 G4double linDistSq, curveDist; >> 609 linDistSq = ( CurrentB_PointVelocity.GetPosition() >> 610 - CurrentA_PointVelocity.GetPosition() ).mag2(); >> 611 curveDist = CurrentB_PointVelocity.GetCurveLength() >> 612 - CurrentA_PointVelocity.GetCurveLength(); >> 613 if( curveDist*(curveDist+2*perMillion ) < linDistSq ) >> 614 { >> 615 // Re-integrate to obtain a new B >> 616 // >> 617 G4FieldTrack newEndPointFT= >> 618 ReEstimateEndpoint( CurrentA_PointVelocity, >> 619 CurrentB_PointVelocity, >> 620 linDistSq, // to avoid recalculation >> 621 curveDist ); >> 622 G4FieldTrack oldPointVelB = CurrentB_PointVelocity; >> 623 CurrentB_PointVelocity = newEndPointFT; >> 624 >> 625 if( final_section ){ >> 626 recalculatedEndPoint= true; >> 627 IntersectedOrRecalculatedFT= newEndPointFT; // So that we can return it, >> 628 // if it is the endpoint! >> 629 } >> 630 } >> 631 if( curveDist < 0.0 ) >> 632 { >> 633 G4cerr << "G4PropagatorInField::LocateIntersectionPoint():" << G4endl >> 634 << "Error in advancing propagation." << G4endl; >> 635 fVerboseLevel= 5; // Print out a maximum of information >> 636 printStatus( CurrentA_PointVelocity, CurrentB_PointVelocity, >> 637 -1.0, NewSafety, substep_no, 0); >> 638 G4cerr << " Point A (start) is " << CurrentA_PointVelocity << G4endl; >> 639 G4cerr << " Point B (end) is " << CurrentB_PointVelocity << G4endl; >> 640 G4cerr << " curveDist is " << curveDist << G4endl; >> 641 G4cerr << G4endl >> 642 << "The final curve point is not further along" >> 643 << " than the original!" << G4endl; >> 644 G4Exception("G4PropagatorInField::LocateIntersectionPoint()", "FatalError", >> 645 FatalException, "Error in advancing propagation."); >> 646 } >> 647 >> 648 if(restoredFullEndpoint) { >> 649 final_section= restoredFullEndpoint; >> 650 restoredFullEndpoint=false; >> 651 } >> 652 >> 653 } // EndIf ( E is close enough to the curve, ie point F. ) >> 654 // tests ChordAF_Vector.mag() <= maximum_lateral_displacement >> 655 >> 656 } while ( ( ! found_approximate_intersection ) >> 657 && ( ! there_is_no_intersection ) >> 658 && ( substep_no++ < max_substeps) ); // UNTIL found or failed >> 659 >> 660 #ifdef G4VERBOSE >> 661 if( substep_no >= max_substeps ) { >> 662 G4cerr << "Problem in G4PropagatorInField::LocateIntersectionPoint:" >> 663 << " Convergence is requiring too many substeps: " << substep_no; >> 664 G4cerr << " Will abandon effort to intersect. " << G4endl; >> 665 G4cerr << " Information on start & current step follows in cout: " << G4endl; >> 666 printStatus( CurrentA_PointVelocity, CurrentA_PointVelocity, >> 667 -1.0, NewSafety, 0, 0); >> 668 printStatus( CurrentA_PointVelocity, CurrentB_PointVelocity, >> 669 -1.0, NewSafety, substep_no, 0); >> 670 } >> 671 #endif >> 672 >> 673 return !there_is_no_intersection; // Success or failure >> 674 } >> 675 >> 676 /////////////////////////////////////////////////////////////////////////// 531 // 677 // >> 678 // Dumps status of propagator. >> 679 532 void 680 void 533 G4PropagatorInField::printStatus( const G4Fiel << 681 G4PropagatorInField::printStatus( const G4FieldTrack& StartFT, 534 const G4Fiel << 682 const G4FieldTrack& CurrentFT, 535 G4doub << 683 G4double requestStep, 536 G4doub << 684 G4double safety, 537 G4int << 685 G4int stepNo, 538 G4VPhy << 686 G4VPhysicalVolume* startVolume) 539 { 687 { 540 const G4int verboseLevel = fVerboseLevel; << 688 const G4int verboseLevel= fVerboseLevel; 541 const G4ThreeVector StartPosition = St 689 const G4ThreeVector StartPosition = StartFT.GetPosition(); 542 const G4ThreeVector StartUnitVelocity = St 690 const G4ThreeVector StartUnitVelocity = StartFT.GetMomentumDir(); 543 const G4ThreeVector CurrentPosition = Cu 691 const G4ThreeVector CurrentPosition = CurrentFT.GetPosition(); 544 const G4ThreeVector CurrentUnitVelocity = Cu 692 const G4ThreeVector CurrentUnitVelocity = CurrentFT.GetMomentumDir(); 545 693 546 G4double step_len = CurrentFT.GetCurveLength 694 G4double step_len = CurrentFT.GetCurveLength() - StartFT.GetCurveLength(); 547 << 548 G4long oldprec; // cout/cerr precision set << 549 695 550 if( ((stepNo == 0) && (verboseLevel <3)) || << 696 if( ((stepNo == 0) && (verboseLevel <3)) >> 697 || (verboseLevel == 3) ) 551 { 698 { 552 oldprec = G4cout.precision(4); << 699 static G4int noPrecision= 4; 553 G4cout << std::setw( 5) << "Step#" << 700 G4cout.precision(noPrecision); 554 << std::setw(10) << " s " << " " << 701 // G4cout.setf(ios_base::fixed,ios_base::floatfield); >> 702 G4cout << std::setw( 6) << " " >> 703 << std::setw( 25) << " Current Position and Direction" << " " >> 704 << G4endl; >> 705 G4cout << std::setw( 5) << "Step#" << " " 555 << std::setw(10) << "X(mm)" << " " 706 << std::setw(10) << "X(mm)" << " " 556 << std::setw(10) << "Y(mm)" << " " 707 << std::setw(10) << "Y(mm)" << " " 557 << std::setw(10) << "Z(mm)" << " " 708 << std::setw(10) << "Z(mm)" << " " 558 << std::setw( 7) << " N_x " << " " 709 << std::setw( 7) << " N_x " << " " 559 << std::setw( 7) << " N_y " << " " 710 << std::setw( 7) << " N_y " << " " 560 << std::setw( 7) << " N_z " << " " << 711 << std::setw( 7) << " N_z " << " " 561 G4cout << std::setw( 7) << " Delta|N|" << << 712 << std::setw( 7) << " Delta|N|" << " " >> 713 // << std::setw( 7) << " Delta(N_z) " << " " 562 << std::setw( 9) << "StepLen" << " 714 << std::setw( 9) << "StepLen" << " " 563 << std::setw(12) << "StartSafety" < 715 << std::setw(12) << "StartSafety" << " " 564 << std::setw( 9) << "PhsStep" << " << 716 << std::setw( 9) << "PhsStep" << " " 565 if( startVolume != nullptr ) << 717 << std::setw(18) << "NextVolume" << " " 566 { G4cout << std::setw(18) << "NextVolume << 567 G4cout.precision(oldprec); << 568 G4cout << G4endl; << 569 } << 570 if((stepNo == 0) && (verboseLevel <=3)) << 571 { << 572 // Recurse to print the start values << 573 // << 574 printStatus( StartFT, StartFT, -1.0, safet << 575 } << 576 if( verboseLevel <= 3 ) << 577 { << 578 if( stepNo >= 0) << 579 { G4cout << std::setw( 4) << stepNo << " << 580 else << 581 { G4cout << std::setw( 5) << "Start" ; } << 582 oldprec = G4cout.precision(8); << 583 G4cout << std::setw(10) << CurrentFT.GetCu << 584 G4cout.precision(8); << 585 G4cout << std::setw(10) << CurrentPosition << 586 << std::setw(10) << CurrentPosition << 587 << std::setw(10) << CurrentPosition << 588 G4cout.precision(4); << 589 G4cout << std::setw( 7) << CurrentUnitVelo << 590 << std::setw( 7) << CurrentUnitVelo << 591 << std::setw( 7) << CurrentUnitVelo << 592 G4cout.precision(3); << 593 G4cout << std::setw( 7) << 594 << CurrentFT.GetMomentum().mag()-St << 595 G4cout << std::setw( 9) << step_len << " " << 596 G4cout << std::setw(12) << safety << " "; << 597 if( requestStep != -1.0 ) << 598 { G4cout << std::setw( 9) << requestStep << 599 else << 600 { G4cout << std::setw( 9) << "Init/NotKn << 601 if( startVolume != nullptr) << 602 { G4cout << std::setw(12) << startVolume << 603 G4cout.precision(oldprec); << 604 G4cout << G4endl; << 605 } << 606 else // if( verboseLevel > 3 ) << 607 { << 608 // Multi-line output << 609 << 610 G4cout << "Step taken was " << step_len << 611 << " out of PhysicalStep = " << re << 612 G4cout << "Final safety is: " << safety << << 613 G4cout << "Chord length = " << (CurrentPos << 614 << G4endl; 718 << G4endl; 615 G4cout << G4endl; << 616 } 719 } >> 720 if((stepNo == 0) && (verboseLevel <=3)){ >> 721 // Recurse to print the start values >> 722 // >> 723 printStatus( StartFT, StartFT, -1.0, safety, -1, startVolume); >> 724 } >> 725 if( verboseLevel <= 3 ) >> 726 { >> 727 G4cout.precision(8); >> 728 if( stepNo >= 0) >> 729 G4cout << std::setw( 5) << stepNo << " "; >> 730 else >> 731 G4cout << std::setw( 5) << "Start" << " "; >> 732 G4cout << std::setw(10) << CurrentPosition.x() << " " >> 733 << std::setw(10) << CurrentPosition.y() << " " >> 734 << std::setw(10) << CurrentPosition.z() << " " >> 735 << std::setw( 7) << CurrentUnitVelocity.x() << " " >> 736 << std::setw( 7) << CurrentUnitVelocity.y() << " " >> 737 << std::setw( 7) << CurrentUnitVelocity.z() << " "; >> 738 G4cout.precision(2); >> 739 G4cout << std::setw( 7) << CurrentFT.GetMomentum().mag()- StartFT.GetMomentum().mag() << " "; >> 740 // << std::setw( 7) << CurrentUnitVelocity.z() - InitialUnitVelocity.z() << " "; >> 741 G4cout << std::setw( 9) << step_len << " "; >> 742 G4cout << std::setw(12) << safety << " "; >> 743 if( requestStep != -1.0 ) >> 744 G4cout << std::setw( 9) << requestStep << " "; >> 745 else >> 746 G4cout << std::setw( 9) << "Init/NotKnown" << " "; >> 747 >> 748 if( startVolume != 0) >> 749 { >> 750 G4cout << std::setw(12) << startVolume->GetName() << " "; >> 751 } >> 752 else >> 753 { >> 754 if( step_len != -1 ) >> 755 G4cout << std::setw(12) << "OutOfWorld" << " "; >> 756 else >> 757 G4cout << std::setw(12) << "NotGiven" << " "; >> 758 } >> 759 >> 760 G4cout << G4endl; >> 761 } >> 762 else // if( verboseLevel > 3 ) >> 763 { >> 764 // Multi-line output >> 765 >> 766 G4cout << "Step taken was " << step_len >> 767 << " out of PhysicalStep= " << requestStep << G4endl; >> 768 G4cout << "Final safety is: " << safety << G4endl; >> 769 >> 770 G4cout << "Chord length = " << (CurrentPosition-StartPosition).mag() >> 771 << G4endl; >> 772 G4cout << G4endl; >> 773 } 617 } 774 } 618 775 619 // ------------------------------------------- << 776 /////////////////////////////////////////////////////////////////////////// 620 // Prints Step diagnostics << 621 // 777 // >> 778 // Prints Step diagnostics >> 779 622 void 780 void 623 G4PropagatorInField::PrintStepLengthDiagnostic 781 G4PropagatorInField::PrintStepLengthDiagnostic( 624 G4double CurrentProp 782 G4double CurrentProposedStepLength, 625 G4double decreaseFac 783 G4double decreaseFactor, 626 G4double stepTrial, 784 G4double stepTrial, 627 const G4FieldTrack& ) 785 const G4FieldTrack& ) 628 { 786 { 629 G4long iprec= G4cout.precision(8); << 787 G4cout << " PiF: NoZeroStep= " << fNoZeroStep 630 G4cout << " " << std::setw(12) << " PiF: NoZ << 788 << " CurrentProposedStepLength= " << CurrentProposedStepLength 631 << " " << std::setw(20) << " CurrentP << 789 << " Full_curvelen_last=" << fFull_CurveLen_of_LastAttempt 632 << " " << std::setw(18) << " Full_cur << 790 << " last proposed step-length= " << fLast_ProposedStepLength 633 << " " << std::setw(18) << " last pro << 791 << " decreate factor = " << decreaseFactor 634 << " " << std::setw(18) << " decrease << 792 << " step trial = " << stepTrial 635 << " " << std::setw(15) << " step tri << 636 << G4endl; 793 << G4endl; >> 794 } 637 795 638 G4cout << " " << std::setw(10) << fNoZeroSte << 796 G4bool 639 << " " << std::setw(20) << CurrentPro << 797 G4PropagatorInField::IntersectChord( G4ThreeVector StartPointA, 640 << " " << std::setw(18) << fFull_Curv << 798 G4ThreeVector EndPointB, 641 << " " << std::setw(18) << fLast_Prop << 799 G4double &NewSafety, 642 << " " << std::setw(18) << decreaseFa << 800 G4double &LinearStepLength, 643 << " " << std::setw(15) << stepTrial << 801 G4ThreeVector &IntersectionPoint 644 << G4endl; << 802 ) 645 G4cout.precision( iprec ); << 803 { >> 804 // Calculate the direction and length of the chord AB >> 805 G4ThreeVector ChordAB_Vector = EndPointB - StartPointA; >> 806 G4double ChordAB_Length = ChordAB_Vector.mag(); // Magnitude (norm) >> 807 G4ThreeVector ChordAB_Dir = ChordAB_Vector.unit(); >> 808 G4bool intersects; >> 809 >> 810 G4ThreeVector OriginShift = StartPointA - fPreviousSftOrigin ; >> 811 G4double MagSqShift = OriginShift.mag2() ; >> 812 G4double currentSafety; >> 813 G4bool doCallNav= false; >> 814 >> 815 if( MagSqShift >= sqr(fPreviousSafety) ) >> 816 { >> 817 currentSafety = 0.0 ; >> 818 }else{ >> 819 currentSafety = fPreviousSafety - std::sqrt(MagSqShift) ; >> 820 } >> 821 >> 822 if( fUseSafetyForOptimisation && (ChordAB_Length <= currentSafety) ) >> 823 { >> 824 // The Step is guaranteed to be taken >> 825 >> 826 LinearStepLength = ChordAB_Length; >> 827 intersects = false; >> 828 >> 829 NewSafety= currentSafety; >> 830 } >> 831 else >> 832 { >> 833 doCallNav= true; >> 834 // Check whether any volumes are encountered by the chord AB >> 835 LinearStepLength = >> 836 fNavigator->ComputeStep( StartPointA, ChordAB_Dir, >> 837 ChordAB_Length, NewSafety ); >> 838 intersects = (LinearStepLength <= ChordAB_Length); >> 839 // G4Navigator contracts to return k_infinity if len==asked >> 840 // and it did not find a surface boundary at that length >> 841 LinearStepLength = std::min( LinearStepLength, ChordAB_Length); >> 842 >> 843 // Save the last calculated safety! >> 844 fPreviousSftOrigin = StartPointA; >> 845 fPreviousSafety= NewSafety; >> 846 >> 847 if( intersects ){ >> 848 // Intersection Point of chord AB and either volume A's surface >> 849 // or a daughter volume's surface .. >> 850 IntersectionPoint = StartPointA + LinearStepLength * ChordAB_Dir; >> 851 } >> 852 } >> 853 >> 854 #ifdef DEBUG_INTERSECTS_CHORD >> 855 // printIntersection( >> 856 // StartPointA, EndPointB, LinearStepLength, IntersectionPoint, NewSafety >> 857 >> 858 G4cout << "Start=" << std::setw(12) << StartPointA << " " >> 859 << "End= " << std::setw(8) << EndPointB << " " >> 860 << "StepIn=" << std::setw(8) << LinearStepLength << " " >> 861 << "NewSft=" << std::setw(8) << NewSafety >> 862 << "NavCall" << doCallNav << " " >> 863 << "In T/F " << intersects << " " >> 864 << "IntrPt=" << std::setw(8) << IntersectionPoint << " " >> 865 << G4endl; >> 866 #endif >> 867 >> 868 return intersects; >> 869 } >> 870 >> 871 // --------------------- oooo000000000000oooo ---------------------------- >> 872 >> 873 G4FieldTrack G4PropagatorInField:: >> 874 ReEstimateEndpoint( const G4FieldTrack &CurrentStateA, >> 875 const G4FieldTrack &EstimatedEndStateB, >> 876 G4double linearDistSq, >> 877 G4double curveDist >> 878 ) >> 879 { >> 880 // G4double checkCurveDist= EstimatedEndStateB.GetCurveLength() >> 881 // - CurrentStateA.GetCurveLength(); >> 882 // G4double checkLinDistSq= (EstimatedEndStateB.GetPosition() >> 883 // - CurrentStateA.GetPosition() ).mag2(); >> 884 >> 885 G4FieldTrack newEndPoint( CurrentStateA ); >> 886 G4MagInt_Driver* integrDriver= GetChordFinder()->GetIntegrationDriver(); >> 887 >> 888 G4FieldTrack retEndPoint( CurrentStateA ); >> 889 G4bool goodAdvance; >> 890 G4int itrial=0; >> 891 const G4int no_trials= 20; >> 892 >> 893 G4double endCurveLen= EstimatedEndStateB.GetCurveLength(); >> 894 do >> 895 { >> 896 G4double currentCurveLen= newEndPoint.GetCurveLength(); >> 897 G4double advanceLength= endCurveLen - currentCurveLen ; >> 898 >> 899 goodAdvance= >> 900 integrDriver->AccurateAdvance(newEndPoint, advanceLength, fEpsilonStep); >> 901 // *************** >> 902 } >> 903 while( !goodAdvance && (++itrial < no_trials) ); >> 904 >> 905 if( goodAdvance ) { >> 906 retEndPoint= newEndPoint; >> 907 }else{ >> 908 retEndPoint= EstimatedEndStateB; // Could not improve without major work !! >> 909 } >> 910 >> 911 // All the work is done >> 912 // below are some diagnostics only -- before the return! >> 913 // >> 914 static const G4String MethodName("G4PropagatorInField::ReEstimateEndpoint"); >> 915 #ifdef G4VERBOSE >> 916 G4int latest_good_trials=0; >> 917 if( itrial > 1) { >> 918 if( fVerboseLevel > 0 ) { >> 919 G4cout << MethodName << " called - goodAdv= " << goodAdvance >> 920 << " trials = " << itrial << " previous good= " << latest_good_trials >> 921 << G4endl; >> 922 } >> 923 latest_good_trials=0; >> 924 }else{ >> 925 latest_good_trials++; >> 926 } >> 927 #endif >> 928 >> 929 #ifdef G4DEBUG_FIELD >> 930 G4double lengthDone= newEndPoint.GetCurveLength() >> 931 - CurrentStateA.GetCurveLength(); >> 932 if( !goodAdvance ) { >> 933 if( fVerboseLevel >= 3 ){ >> 934 G4cout << MethodName << "> AccurateAdvance failed " ; >> 935 G4cout << " in " << itrial << " integration trials/steps. " << G4endl >> 936 G4cout << " It went only " << lengthDone << " instead of " << curveDist >> 937 << " -- a difference of " << curveDist - lengthDone << G4endl; >> 938 G4cout << " ReEstimateEndpoint> Reset endPoint to original value!" << G4endl; >> 939 } >> 940 } >> 941 >> 942 static G4int noInaccuracyWarnings = 0; >> 943 G4int maxNoWarnings = 10; >> 944 if ( (noInaccuracyWarnings < maxNoWarnings ) >> 945 || (fVerboseLevel > 1) ) >> 946 { >> 947 G4cerr << "G4PropagatorInField::LocateIntersectionPoint():" >> 948 << G4endl >> 949 << " Warning: Integration inaccuracy requires" >> 950 << " an adjustment in the step's endpoint." << G4endl >> 951 << " Two mid-points are further apart than their" >> 952 << " curve length difference" << G4endl >> 953 << " Dist = " << std::sqrt(linearDistSq) >> 954 << " curve length = " << curveDist << G4endl; >> 955 G4cerr << " Correction applied is " >> 956 << (newEndPoint.GetPosition()-EstimatedEndStateB.GetPosition()).mag() >> 957 << G4endl; >> 958 } >> 959 #else >> 960 // Statistics on the RMS value of the corrections >> 961 static G4int noCorrections=0; >> 962 static G4double sumCorrectionsSq = 0; >> 963 noCorrections++; >> 964 if( goodAdvance ){ >> 965 sumCorrectionsSq += (EstimatedEndStateB.GetPosition() - >> 966 newEndPoint.GetPosition()).mag2(); >> 967 } >> 968 linearDistSq -= curveDist; // To use linearDistSq ... ! >> 969 #endif >> 970 >> 971 return retEndPoint; 646 } 972 } 647 973 648 // Access the points which have passed through 974 // Access the points which have passed through the filter. The 649 // points are stored as ThreeVectors for the i 975 // points are stored as ThreeVectors for the initial impelmentation 650 // only (jacek 30/10/2002) 976 // only (jacek 30/10/2002) 651 // Responsibility for deleting the points lies 977 // Responsibility for deleting the points lies with 652 // SmoothTrajectoryPoint, which is the points' 978 // SmoothTrajectoryPoint, which is the points' final 653 // destination. The points pointer is set to N 979 // destination. The points pointer is set to NULL, to ensure that 654 // the points are not re-used in subsequent st 980 // the points are not re-used in subsequent steps, therefore THIS 655 // METHOD MUST BE CALLED EXACTLY ONCE PER STEP 981 // METHOD MUST BE CALLED EXACTLY ONCE PER STEP. (jacek 08/11/2002) 656 982 >> 983 657 std::vector<G4ThreeVector>* 984 std::vector<G4ThreeVector>* 658 G4PropagatorInField::GimmeTrajectoryVectorAndF << 985 G4PropagatorInField::GimmeTrajectoryVectorAndForgetIt() const { 659 { << 660 // NB, GimmeThePointsAndForgetThem really fo 986 // NB, GimmeThePointsAndForgetThem really forgets them, so it can 661 // only be called (exactly) once for each st 987 // only be called (exactly) once for each step. 662 << 988 if (fpTrajectoryFilter) { 663 if (fpTrajectoryFilter != nullptr) << 664 { << 665 return fpTrajectoryFilter->GimmeThePointsA 989 return fpTrajectoryFilter->GimmeThePointsAndForgetThem(); >> 990 } else { >> 991 return NULL; 666 } 992 } 667 return nullptr; << 668 } 993 } 669 994 670 // ------------------------------------------- << 671 // << 672 void 995 void 673 G4PropagatorInField::SetTrajectoryFilter(G4VCu << 996 G4PropagatorInField::SetTrajectoryFilter(G4VCurvedTrajectoryFilter* filter) { 674 { << 675 fpTrajectoryFilter = filter; 997 fpTrajectoryFilter = filter; 676 } 998 } 677 999 678 // ------------------------------------------- << 1000 679 // << 680 void G4PropagatorInField::ClearPropagatorState 1001 void G4PropagatorInField::ClearPropagatorState() 681 { 1002 { 682 // Goal: Clear all memory of previous steps, << 1003 G4Exception("G4PropagatorInField::ClearPropagatorState()", "NotImplemented", 683 << 1004 FatalException, "Functionality not yet implemented."); 684 fParticleIsLooping = false; << 685 fNoZeroStep = 0; << 686 << 687 fSetFieldMgr = false; // Has field-manager << 688 fEpsilonStep= 1.0e-5; // Relative accuracy << 689 << 690 End_PointAndTangent= G4FieldTrack( G4ThreeVe << 691 G4ThreeVe << 692 0.0,0.0,0 << 693 fFull_CurveLen_of_LastAttempt = -1; << 694 fLast_ProposedStepLength = -1; << 695 << 696 fPreviousSftOrigin= G4ThreeVector(0.,0.,0.); << 697 fPreviousSafety= 0.0; << 698 << 699 fNewTrack = true; << 700 } 1005 } 701 1006 702 // ------------------------------------------- << 1007 G4FieldManager* 703 // << 1008 G4PropagatorInField::FindAndSetFieldManager( G4VPhysicalVolume* pCurrentPhysicalVolume) 704 G4FieldManager* G4PropagatorInField:: << 705 FindAndSetFieldManager( G4VPhysicalVolume* pCu << 706 { 1009 { 707 G4FieldManager* currentFieldMgr; 1010 G4FieldManager* currentFieldMgr; 708 1011 709 currentFieldMgr = fDetectorFieldMgr; 1012 currentFieldMgr = fDetectorFieldMgr; 710 if( pCurrentPhysicalVolume != nullptr ) << 1013 if( pCurrentPhysicalVolume) 711 { 1014 { 712 G4FieldManager *pRegionFieldMgr = nullptr << 1015 G4FieldManager *newFieldMgr = 0; 713 G4LogicalVolume* pLogicalVol = pCurrentPh << 1016 newFieldMgr= pCurrentPhysicalVolume->GetLogicalVolume()->GetFieldManager(); 714 << 1017 if ( newFieldMgr ) 715 if( pLogicalVol != nullptr ) << 1018 currentFieldMgr = newFieldMgr; 716 { << 717 // Value for Region, if any, overrides << 718 // << 719 G4Region* pRegion = pLogicalVol->GetR << 720 if( pRegion != nullptr ) << 721 { << 722 pRegionFieldMgr = pRegion->GetField << 723 if( pRegionFieldMgr != nullptr ) << 724 { << 725 currentFieldMgr= pRegionFieldMgr << 726 } << 727 } << 728 << 729 // 'Local' Value from logical volume, << 730 // << 731 localFieldMgr = pLogicalVol->GetFieldM << 732 if ( localFieldMgr != nullptr ) << 733 { << 734 currentFieldMgr = localFieldMgr; << 735 } << 736 } << 737 } 1019 } 738 fCurrentFieldMgr = currentFieldMgr; << 1020 fCurrentFieldMgr= currentFieldMgr; 739 1021 740 // Flag that field manager has been set << 1022 // Flag that field manager has been set. 741 // << 1023 fSetFieldMgr= true; 742 fSetFieldMgr = true; << 743 1024 744 return currentFieldMgr; 1025 return currentFieldMgr; 745 } 1026 } 746 1027 747 // ------------------------------------------- << 1028 G4int G4PropagatorInField::SetVerboseLevel( G4int Verbose ) 748 // << 749 G4int G4PropagatorInField::SetVerboseLevel( G4 << 750 { 1029 { 751 G4int oldval = fVerboseLevel; << 1030 G4int oldval= fVerboseLevel; 752 fVerboseLevel = level; << 1031 fVerboseLevel= Verbose; 753 1032 754 // Forward the verbose level 'reduced' to Ch << 1033 // Forward the verbose level 'reduced' to ChordFinder, MagIntegratorDriver ... ? 755 // MagIntegratorDriver ... ? << 1034 G4MagInt_Driver* integrDriver= GetChordFinder()->GetIntegrationDriver(); 756 // << 1035 integrDriver->SetVerboseLevel( Verbose - 2 ); 757 auto integrDriver = GetChordFinder()->GetInt << 1036 G4cout << "Set Driver verbosity to " << Verbose - 2 << G4endl; 758 integrDriver->SetVerboseLevel( fVerboseLevel << 759 G4cout << "Set Driver verbosity to " << fVer << 760 1037 761 return oldval; 1038 return oldval; 762 } << 763 << 764 // ------------------------------------------- << 765 // << 766 void G4PropagatorInField::ReportLoopingParticl << 767 << 768 << 769 << 770 << 771 << 772 { << 773 std::ostringstream message; << 774 G4double fraction = StepTaken / StepRequest << 775 message << " Unfinished integration of trac << 776 << " of momentum " << momentumVec < << 777 << momentumVec.mag() << " ) " << G4 << 778 << " after " << count << " field su << 779 << " totaling " << std::setprecisio << 780 << " out of requested step " << std << 781 << StepRequested / mm << " mm "; << 782 message << " a fraction of "; << 783 G4int prec = 4; << 784 if( fraction > 0.99 ) << 785 { << 786 prec = 7; << 787 } << 788 else << 789 { << 790 if (fraction > 0.97 ) { prec = 5; } << 791 } << 792 message << std::setprecision(prec) << 793 << 100. * StepTaken / StepRequested << 794 if( pPhysVol != nullptr ) << 795 { << 796 message << " in volume " << pPhysVol->Get << 797 auto material = pPhysVol->GetLogicalVolum << 798 if( material != nullptr ) << 799 { << 800 message << " with material " << materia << 801 << " ( density = " << 802 << material->GetDensity() / ( g << 803 } << 804 } << 805 else << 806 { << 807 message << " in unknown (null) volume. " << 808 } << 809 G4Exception(methodName, "GeomNav1002", Just << 810 } << 811 << 812 // ------------------------------------------- << 813 // << 814 void G4PropagatorInField::ReportStuckParticle( << 815 << 816 << 817 << 818 { << 819 std::ostringstream message; << 820 message << "Particle is stuck; it will be k << 821 << " Zero progress for " << noZero << 822 << G4endl << 823 << " Proposed Step is " << propose << 824 << " but Step Taken is "<< lastTrie << 825 if( physVol != nullptr ) << 826 { << 827 message << " in volume " << physVol->Get << 828 } << 829 else << 830 { << 831 message << " in unknown or null volume. << 832 } << 833 G4Exception("G4PropagatorInField::ComputeSt << 834 "GeomNav1002", JustWarning, mes << 835 } << 836 << 837 // ------------------------------------------- << 838 << 839 // ------------------------------------------- << 840 // Methods to alter Parameters << 841 // ------------------------------------------- << 842 << 843 // Was a data member (of an object) -- now mov << 844 G4double G4PropagatorInField::GetLargestAccep << 845 { << 846 return fLargestAcceptableStep; << 847 } << 848 << 849 // ------------------------------------------- << 850 // << 851 void G4PropagatorInField::SetLargestAcceptable << 852 { << 853 if( fLargestAcceptableStep>0.0 ) << 854 { << 855 fLargestAcceptableStep = newBigDist; << 856 } << 857 } << 858 << 859 // ------------------------------------------- << 860 << 861 G4double G4PropagatorInField::GetMaxStepSizeMu << 862 { << 863 return fMaxStepSizeMultiplier; << 864 } << 865 << 866 // ------------------------------------------- << 867 << 868 void G4PropagatorInField::SetMaxStepSizeMu << 869 { << 870 fMaxStepSizeMultiplier=vm; << 871 } << 872 << 873 // ------------------------------------------- << 874 << 875 G4double G4PropagatorInField::GetMinBigDistanc << 876 { << 877 return fMinBigDistance; << 878 } << 879 << 880 // ------------------------------------------- << 881 << 882 void G4PropagatorInField::SetMinBigDistanc << 883 { << 884 fMinBigDistance= val; << 885 } 1039 } 886 1040