Geant4-11
G4CoupledTransportation.cc
Go to the documentation of this file.
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//
28// ------------------------------------------------------------
29// GEANT 4 class implementation
30//
31// =======================================================================
32// Created: 19 March 1997, J. Apostolakis
33// =======================================================================
34
38
40#include "G4SystemOfUnits.hh"
42#include "G4ParticleTable.hh"
43#include "G4ChordFinder.hh"
44#include "G4Field.hh"
45#include "G4FieldTrack.hh"
47
48#include "G4Transportation.hh" // In order to use fUseMagneticMoment
49
51
53// This mode must apply to all threads
54
59//
60// Constructor
61
63 : G4VProcess( G4String("CoupledTransportation"), fTransportation ),
64 fTransportEndPosition(0.0, 0.0, 0.0),
65 fTransportEndMomentumDir(0.0, 0.0, 0.0),
66 fTransportEndKineticEnergy(0.0),
67 fTransportEndSpin(0.0, 0.0, 0.0),
68 fMomentumChanged(false),
69 fEndGlobalTimeComputed(false),
70 fCandidateEndGlobalTime(0.0),
71 fParticleIsLooping( false ),
72 fNewTrack( true ),
73 fPreviousSftOrigin( 0.,0.,0. ),
74 fPreviousMassSafety( 0.0 ),
75 fPreviousFullSafety( 0.0 ),
76 fMassGeometryLimitedStep( false ),
77 fAnyGeometryLimitedStep( false ),
78 fEndpointDistance( -1.0 ),
79 fSumEnergyKilled( 0.0 ), fMaxEnergyKilled( 0.0 ),
80 fFirstStepInMassVolume( true ),
81 fFirstStepInAnyVolume( true )
82{
84 SetVerboseLevel(verbosity);
85
86 G4TransportationManager* transportMgr ;
87
89
90 fMassNavigator = transportMgr->GetNavigatorForTracking() ;
91 fFieldPropagator = transportMgr->GetPropagatorInField() ;
92 // fGlobalFieldMgr = transportMgr->GetFieldManager() ;
94 if( verboseLevel > 0 )
95 {
96 G4cout << " G4CoupledTransportation constructor: ----- " << G4endl;
97 G4cout << " Verbose level is " << verboseLevel << G4endl;
98 G4cout << " Navigator Id obtained in G4CoupledTransportation constructor "
99 << fNavigatorId << G4endl;
100 G4cout << " Reports First/Last in "
101 << (fSignifyStepInAnyVolume ? " any " : " mass " )
102 << " geometry " << G4endl;
103 }
105 fpSafetyHelper = transportMgr->GetSafetyHelper(); // New
106
107 fpLogger = new G4TransportationLogger("G4Transportation", verbosity);
108
110 // Use the old defaults: Warning = 100 MeV, Important = 250 MeV, No Trials = 10;
111
113 // Should be done by Set methods in SetHighLooperThresholds -- making sure
114
115 static G4ThreadLocal G4TouchableHandle* pNullTouchableHandle = 0;
116 if ( !pNullTouchableHandle) { pNullTouchableHandle = new G4TouchableHandle; }
117 fCurrentTouchableHandle = *pNullTouchableHandle;
118 // Points to (G4VTouchable*) 0
119
121}
122
124
126{
127 if( fSumEnergyKilled > 0.0 )
128 {
130 }
131 delete fpLogger;
132}
133
135
136void
138{
139 if( fSumEnergyKilled > 0.0 )
140 {
141 outStr << " G4CoupledTransportation: Statistics for looping particles "
142 << G4endl;
143 outStr << " Sum of energy of loopers killed: "
144 << fSumEnergyKilled / MeV << " MeV " << G4endl;
145 outStr << " Max energy of loopers killed: "
146 << fMaxEnergyKilled / MeV << " MeV " << G4endl;
147
148
149 outStr << " Max energy of loopers 'saved': " << fMaxEnergySaved << G4endl;
150 outStr << " Sum of energy of loopers 'saved': "
152 outStr << " Sum of energy of unstable loopers 'saved': "
154 }
155}
156
158//
159// Responsibilities:
160// Find whether the geometry limits the Step, and to what length
161// Calculate the new value of the safety and return it.
162// Store the final time, position and momentum.
163
166 G4double, // previousStepSize
167 G4double currentMinimumStep,
168 G4double& proposedSafetyForStart,
169 G4GPILSelection* selection )
170{
171 G4double geometryStepLength;
172 G4double startMassSafety= 0.0; // estimated safety for start point (mass geometry)
173 G4double startFullSafety= 0.0; // estimated safety for start point (all geometries)
174 G4double safetyProposal= -1.0; // local copy of proposal
175
176 G4ThreeVector EndUnitMomentum ;
177 G4double lengthAlongCurve = 0.0 ;
178
179 fParticleIsLooping = false ;
180
181 // Initial actions moved to StartTrack()
182 // --------------------------------------
183 // Note: in case another process changes touchable handle
184 // it will be necessary to add here (for all steps)
185 // fCurrentTouchableHandle = aTrack->GetTouchableHandle();
186
187 // GPILSelection is set to defaule value of CandidateForSelection
188 // It is a return value
189 //
190 *selection = CandidateForSelection ;
191
194
195#ifdef G4DEBUG_TRANSPORT
196 G4cout << " CoupledTransport::AlongStep GPIL: "
197 << " 1st-step: any= " <<fFirstStepInAnyVolume << " ( geom= "
198 << fAnyGeometryLimitedStep << " ) "
199 << " mass= " << fFirstStepInMassVolume << " ( geom= "
200 << fMassGeometryLimitedStep << " ) "
201 << " newTrack= " << fNewTrack << G4endl;
202#endif
203
204 // fLastStepInVolume= false;
205 fNewTrack = false;
206
207 // Get initial Energy/Momentum of the track
208 //
209 const G4DynamicParticle* pParticle = track.GetDynamicParticle() ;
210 const G4ParticleDefinition* pParticleDef = pParticle->GetDefinition() ;
211 G4ThreeVector startMomentumDir = pParticle->GetMomentumDirection() ;
212 G4ThreeVector startPosition = track.GetPosition() ;
213 G4VPhysicalVolume* currentVolume= track.GetVolume();
214
215#ifdef G4DEBUG_TRANSPORT
216 if( verboseLevel > 1 )
217 {
218 G4cout << "G4CoupledTransportation::AlongStepGPIL> called in volume "
219 << currentVolume->GetName() << G4endl;
220 }
221#endif
222 // G4double theTime = track.GetGlobalTime() ;
223
224 // The Step Point safety can be limited by other geometries and/or the
225 // assumptions of any process - it's not always the geometrical safety.
226 // We calculate the starting point's isotropic safety here.
227 //
228 G4ThreeVector OriginShift = startPosition - fPreviousSftOrigin ;
229 G4double MagSqShift = OriginShift.mag2() ;
230 startMassSafety = 0.0;
231 startFullSafety= 0.0;
232
233 // Recall that FullSafety <= MassSafety
234 // Original: if( MagSqShift < sqr(fPreviousMassSafety) ) {
235 if( MagSqShift < sqr(fPreviousFullSafety) )
236 {
237 G4double mag_shift= std::sqrt(MagSqShift);
238 startMassSafety = std::max( (fPreviousMassSafety - mag_shift), 0.0);
239 startFullSafety = std::max( (fPreviousFullSafety - mag_shift), 0.0);
240 // Need to be consistent between full safety with Mass safety
241 // in order reproduce results in simple case
242 // --> use same calculation method
243
244 // Only compute full safety if massSafety > 0. Else it remains 0
245 // startFullSafety = fPathFinder->ComputeSafety( startPosition );
246 }
247
248 // Is the particle charged or has it a magnetic moment?
249 //
250 G4double particleCharge = pParticle->GetCharge() ;
251 G4double magneticMoment = pParticle->GetMagneticMoment() ;
252 G4double restMass = pParticle->GetMass() ;
253
254 fMassGeometryLimitedStep = false ; // Set default - alex
256
257 // There is no need to locate the current volume. It is Done elsewhere:
258 // On track construction
259 // By the tracking, after all AlongStepDoIts, in "Relocation"
260
261 // Check if the particle has a force, EM or gravitational, exerted on it
262 //
263 G4FieldManager* fieldMgr= nullptr;
264 G4bool fieldExertsForce = false ;
265
266 const G4Field* ptrField= nullptr;
267
269 G4bool eligibleEM = (particleCharge != 0.0)
270 || ( fUseMagneticMoment && (magneticMoment != 0.0) );
271 G4bool eligibleGrav = fUseGravity && (restMass != 0.0) ;
272
273 if( (fieldMgr!=nullptr) && (eligibleEM||eligibleGrav) )
274 {
275 // Message the field Manager, to configure it for this track
276 //
277 fieldMgr->ConfigureForTrack( &track );
278
279 // The above call can transition from a null field-ptr oto a finite field.
280 // If the field manager has no field ptr, the field is zero
281 // by definition ( = there is no field ! )
282 //
283 ptrField= fieldMgr->GetDetectorField();
284
285 if( ptrField != nullptr)
286 {
287 fieldExertsForce = eligibleEM
288 || ( eligibleGrav && ptrField->IsGravityActive() );
289 }
290 }
291 G4double momentumMagnitude = pParticle->GetTotalMomentum() ;
292
293 if( fieldExertsForce )
294 {
295 auto equationOfMotion= fFieldPropagator->GetCurrentEquationOfMotion();
296
297 G4ChargeState chargeState(particleCharge, // Charge can change (dynamic)
298 magneticMoment,
299 pParticleDef->GetPDGSpin() );
300 if( equationOfMotion )
301 {
302 equationOfMotion->SetChargeMomentumMass( chargeState,
303 momentumMagnitude,
304 restMass );
305 }
306#ifdef G4DEBUG_TRANSPORT
307 else
308 {
309 G4cerr << " ERROR in G4CoupledTransportation> "
310 << "Cannot find valid Equation of motion: " << G4endl;
311 << " Unable to pass Charge, Momentum and Mass " << G4endl;
312 }
313#endif
314 }
315
316 G4ThreeVector polarizationVec = track.GetPolarization() ;
317 G4FieldTrack aFieldTrack = G4FieldTrack(startPosition,
318 track.GetGlobalTime(), // Lab.
319 track.GetMomentumDirection(),
320 track.GetKineticEnergy(),
321 restMass,
322 particleCharge,
323 polarizationVec,
324 pParticleDef->GetPDGMagneticMoment(),
325 0.0, // Length along track
326 pParticleDef->GetPDGSpin() ) ;
327 G4int stepNo= track.GetCurrentStepNumber();
328
329 ELimited limitedStep;
330 G4FieldTrack endTrackState('a'); // Default values
331
332 fMassGeometryLimitedStep = false ; // default
334 if( currentMinimumStep > 0 )
335 {
336 G4double newMassSafety= 0.0; // temp. for recalculation
337
338 // Do the Transport in the field (non recti-linear)
339 //
340 lengthAlongCurve = fPathFinder->ComputeStep( aFieldTrack,
341 currentMinimumStep,
343 stepNo,
344 newMassSafety,
345 limitedStep,
346 endTrackState,
347 currentVolume ) ;
348
349 G4double newFullSafety= fPathFinder->GetCurrentSafety();
350 // this was estimated already in step above
351
352 if( limitedStep == kUnique || limitedStep == kSharedTransport )
353 {
355 }
356
358
359#ifdef G4DEBUG_TRANSPORT
361 {
362 std::ostringstream message;
363 message << " ERROR in determining geometries limiting the step" << G4endl;
364 message << " Limiting: mass=" << fMassGeometryLimitedStep
365 << " any= " << fAnyGeometryLimitedStep << G4endl;
366 message << "Incompatible conditions - by which geometries was it limited ?";
367 G4Exception("G4CoupledTransportation::AlongStepGetPhysicalInteractionLength()",
368 "PathFinderConfused", FatalException, message);
369 }
370#endif
371
372 geometryStepLength = std::min( lengthAlongCurve, currentMinimumStep);
373
374 // Momentum: Magnitude and direction can be changed too now ...
375 //
376 fMomentumChanged = true ;
377 fTransportEndMomentumDir = endTrackState.GetMomentumDir() ;
378
379 // Remember last safety origin & value.
380 fPreviousSftOrigin = startPosition ;
381 fPreviousMassSafety = newMassSafety ;
382 fPreviousFullSafety = newFullSafety ;
383 // fpSafetyHelper->SetCurrentSafety( newFullSafety, startPosition);
384
385#ifdef G4DEBUG_TRANSPORT
386 if( verboseLevel > 1 )
387 {
388 G4cout << "G4Transport:CompStep> "
389 << " called the pathfinder for a new step at " << startPosition
390 << " and obtained step = " << lengthAlongCurve << G4endl;
391 G4cout << " New safety (preStep) = " << newMassSafety
392 << " versus precalculated = " << startMassSafety << G4endl;
393 }
394#endif
395
396 // Store as best estimate value
397 startMassSafety = newMassSafety ;
398 startFullSafety = newFullSafety ;
399
400 // Get the End-Position and End-Momentum (Dir-ection)
401 fTransportEndPosition = endTrackState.GetPosition() ;
403 }
404 else
405 {
406 geometryStepLength = lengthAlongCurve= 0.0 ;
407 fMomentumChanged = false ;
408 // fMassGeometryLimitedStep = false ; // --- ???
409 // fAnyGeometryLimitedStep = true;
412
413 fTransportEndPosition = startPosition;
414
415 endTrackState= aFieldTrack; // Ensures that time is updated
416
417 // If the step length requested is 0, and we are on a boundary
418 // then a boundary will also limit the step.
419 if( startMassSafety == 0.0 )
420 {
423 }
424 // TODO: Add explicit logical status for being at a boundary
425 }
426 // G4FieldTrack aTrackState(endTrackState);
427
428 if( !fieldExertsForce )
429 {
430 fParticleIsLooping = false ;
431 fMomentumChanged = false ;
432 fEndGlobalTimeComputed = false ;
433 }
434 else
435 {
437
438#ifdef G4DEBUG_TRANSPORT
439 if( verboseLevel > 1 )
440 {
441 G4cout << " G4CT::CS End Position = "
443 G4cout << " G4CT::CS End Direction = "
445 }
446#endif
448 {
449 // If the field can change energy, then the time must be integrated
450 // - so this should have been updated
451 //
454
455 // was ( fCandidateEndGlobalTime != track.GetGlobalTime() );
456 // a cleaner way is to have FieldTrack knowing whether time
457 // is updated
458 }
459 else
460 {
461 // The energy should be unchanged by field transport,
462 // - so the time changed will be calculated elsewhere
463 //
465
466 // Check that the integration preserved the energy
467 // - and if not correct this!
468 G4double startEnergy= track.GetKineticEnergy();
470
471 static G4ThreadLocal G4int no_inexact_steps=0; // , no_large_ediff;
472 G4double absEdiff = std::fabs(startEnergy- endEnergy);
473 if( absEdiff > perMillion * endEnergy )
474 {
475 no_inexact_steps++;
476 // Possible statistics keeping here ...
477 }
478#ifdef G4VERBOSE
479 if( (verboseLevel > 1) && ( absEdiff > perThousand * endEnergy) )
480 {
481 ReportInexactEnergy(startEnergy, endEnergy);
482 } // end of if (verboseLevel)
483#endif
484 // Correct the energy for fields that conserve it
485 // This - hides the integration error
486 // - but gives a better physical answer
488 }
489 }
490
491 fEndpointDistance = (fTransportEndPosition - startPosition).mag() ;
492 fTransportEndSpin = endTrackState.GetSpin();
493
494 // Calculate the safety
495
496 safetyProposal= startFullSafety; // used to be startMassSafety
497 // Changed to accomodate processes that cannot update the safety
498
499 // Update safety for the end-point, if becomes negative at the end-point.
500
501 if( (startFullSafety < fEndpointDistance )
502 && ( particleCharge != 0.0 ) ) // Only needed to prepare for MSC
503 // && !fAnyGeometryLimitedStep ) // To-Try: No safety update if at boundary
504 {
505 G4double endFullSafety =
507 // Expected mission -- only mass geometry's safety
508 // fMassNavigator->ComputeSafety( fTransportEndPosition) ;
509 // Yet discrete processes only have poststep -- and this cannot
510 // currently revise the safety
511 // ==> so we use the all-geometry safety as a precaution
512
514 // Pushing safety to Helper avoids recalculation at this point
515
516 G4ThreeVector centerPt= G4ThreeVector(0.0, 0.0, 0.0); // Used for return value
517 G4double endMassSafety= fPathFinder->ObtainSafety( fNavigatorId, centerPt);
518 // Retrieves the mass value from PathFinder (it calculated it)
519
520 fPreviousMassSafety = endMassSafety ;
521 fPreviousFullSafety = endFullSafety;
523
524 // The convention (Stepping Manager's) is safety from the start point
525 //
526 safetyProposal = endFullSafety + fEndpointDistance;
527 // --> was endMassSafety
528 // Changed to accomodate processes that cannot update the safety
529
530#ifdef G4DEBUG_TRANSPORT
531 G4int prec= G4cout.precision(12) ;
532 G4cout << "***CoupledTransportation::AlongStepGPIL ** " << G4endl ;
533 G4cout << " Revised Safety at endpoint " << fTransportEndPosition
534 << " give safety values: Mass= " << endMassSafety
535 << " All= " << endFullSafety << G4endl ;
536 G4cout << " Adding endpoint distance " << fEndpointDistance
537 << " to obtain pseudo-safety= " << safetyProposal << G4endl ;
538 G4cout.precision(prec);
539 }
540 else
541 {
542 G4int prec= G4cout.precision(12) ;
543 G4cout << "***CoupledTransportation::AlongStepGPIL ** " << G4endl ;
544 G4cout << " Quick Safety estimate at endpoint "
546 << " gives safety endpoint value = "
547 << startFullSafety - fEndpointDistance
548 << " using start-point value " << startFullSafety
549 << " and endpointDistance " << fEndpointDistance << G4endl;
550 G4cout.precision(prec);
551#endif
552 }
553
554 proposedSafetyForStart= safetyProposal;
555 fParticleChange.ProposeTrueStepLength(geometryStepLength) ;
556
557 return geometryStepLength ;
558}
559
561
564 const G4Step& stepData )
565{
566 static G4ThreadLocal G4long noCallsCT_ASDI=0;
567 const char *methodName= "AlongStepDoIt";
568
569 noCallsCT_ASDI++;
570
572 // sets all its members to the value of corresponding members in G4Track
573
574 // Code specific for Transport
575 //
580
582
583 G4double deltaTime = 0.0 ;
584
585 // Calculate Lab Time of Flight (ONLY if field Equations used it!)
586 // G4double endTime = fCandidateEndGlobalTime;
587 // G4double delta_time = endTime - startTime;
588
589 G4double startTime = track.GetGlobalTime() ;
590
592 {
593 G4double finalInverseVel= DBL_MAX, initialInverseVel=DBL_MAX;
594
595 // The time was not integrated .. make the best estimate possible
596 //
597 G4double finalVelocity = track.GetVelocity() ;
598 if( finalVelocity > 0.0 ) { finalInverseVel= 1.0 / finalVelocity; }
599 G4double initialVelocity = stepData.GetPreStepPoint()->GetVelocity() ;
600 if( initialVelocity > 0.0 ) { initialInverseVel= 1.0 / initialVelocity; }
601 G4double stepLength = track.GetStepLength() ;
602
603 if (finalVelocity > 0.0)
604 {
605 // deltaTime = stepLength/finalVelocity ;
606 G4double meanInverseVelocity = 0.5
607 * (initialInverseVel + finalInverseVel);
608 deltaTime = stepLength * meanInverseVelocity ;
609 }
610 else
611 {
612 deltaTime = stepLength * initialInverseVel ;
613 } // Could do with better estimate for final step (finalVelocity = 0) ?
614
615 fCandidateEndGlobalTime = startTime + deltaTime ;
616 fParticleChange.ProposeLocalTime( track.GetLocalTime() + deltaTime) ;
617 }
618 else
619 {
620 deltaTime = fCandidateEndGlobalTime - startTime ;
622 }
623
624 // Now Correct by Lorentz factor to get "proper" deltaTime
625
626 G4double restMass = track.GetDynamicParticle()->GetMass() ;
627 G4double deltaProperTime = deltaTime*( restMass/track.GetTotalEnergy() ) ;
628
629 fParticleChange.ProposeProperTime(track.GetProperTime() + deltaProperTime) ;
630 // fParticleChange. ProposeTrueStepLength( track.GetStepLength() ) ;
631
632 // If the particle is caught looping or is stuck (in very difficult
633 // boundaries) in a magnetic field (doing many steps) THEN this kills it ...
634 //
635 if ( fParticleIsLooping )
636 {
638
639 const G4ParticleDefinition* particleType=
640 track.GetDynamicParticle() -> GetParticleDefinition();
641 G4bool stable = particleType->GetPDGStable();
642
643 G4bool candidateForEnd = (endEnergy < fThreshold_Important_Energy)
645
646 if( candidateForEnd && stable )
647 {
648 const G4int electronPDG= 11; // G4Electron::G4Electron()->GetPDGEncoding();
649 G4int particlePDG= particleType->GetPDGEncoding();
650
651 // Kill the looping particle
652 //
654
655 // Simple statistics
656 fSumEnergyKilled += endEnergy;
657 fSumEnerSqKilled = endEnergy * endEnergy;
659
660 if( endEnergy > fMaxEnergyKilled ) {
661 fMaxEnergyKilled = endEnergy;
662 fMaxEnergyKilledPDG = particlePDG;
663 }
664
665 if( particleType->GetPDGEncoding() != electronPDG )
666 {
667 fSumEnergyKilled_NonElectron += endEnergy;
668 fSumEnerSqKilled_NonElectron += endEnergy * endEnergy;
670
671 if( endEnergy > fMaxEnergyKilled_NonElectron )
672 {
674 fMaxEnergyKilled_NonElecPDG = particlePDG;
675 }
676 }
677
679 {
681 noCallsCT_ASDI, methodName );
682 }
683
685 }
686 else
687 {
689
691 if( fNoLooperTrials == 1 ) {
692 fSumEnergySaved += endEnergy;
693 if ( !stable )
694 fSumEnergyUnstableSaved += endEnergy;
695 }
696#ifdef G4VERBOSE
698 {
699 G4cout << " ** G4CoupledTransportation::AlongStepDoIt():"
700 << " Particle is looping but is saved ..." << G4endl
701 << " Number of trials (this track) = " << fNoLooperTrials
702 << G4endl
703 << " Steps by this track: " << track.GetCurrentStepNumber()
704 << G4endl
705 << " Total no of calls to this method (all tracks) = "
706 << noCallsCT_ASDI << G4endl;
707 }
708#endif
709 }
710 }
711 else
712 {
714 }
715
716 // Another (sometimes better way) is to use a user-limit maximum Step size
717 // to alleviate this problem ..
718
719 // Introduce smooth curved trajectories to particle-change
720 //
723
724 return &fParticleChange ;
725}
726
728//
729// This ensures that the PostStep action is always called,
730// so that it can do the relocation if it is needed.
731//
732
735 G4double, // previousStepSize
736 G4ForceCondition* pForceCond )
737{
738 // Must act as PostStep action -- to relocate particle
739 *pForceCond = Forced ;
740 return DBL_MAX ;
741}
742
744
746ReportMove( G4ThreeVector OldVector, G4ThreeVector NewVector,
747 const G4String& Quantity )
748{
749 G4ThreeVector moveVec = ( NewVector - OldVector );
750
751 G4cerr << G4endl
752 << "**************************************************************"
753 << G4endl;
754 G4cerr << "Endpoint has moved between value expected from TransportEndPosition "
755 << " and value from Track in PostStepDoIt. " << G4endl
756 << "Change of " << Quantity << " is " << moveVec.mag() / mm
757 << " mm long, "
758 << " and its vector is " << (1.0/mm) * moveVec << " mm " << G4endl
759 << "Endpoint of ComputeStep was " << OldVector
760 << " and current position to locate is " << NewVector << G4endl;
761}
762
764
766 const G4Step& )
767{
768 G4TouchableHandle retCurrentTouchable ; // The one to return
769
770 // Initialize ParticleChange (by setting all its members equal
771 // to corresponding members in G4Track)
772 // fParticleChange.Initialize(track) ; // To initialise TouchableChange
773
775
777 {
779 }
780 else
781 {
783 }
784
785 // Check that the end position and direction are preserved
786 // since call to AlongStepDoIt
787
788#ifdef G4DEBUG_TRANSPORT
789 if( ( verboseLevel > 0 )
790 && ((fTransportEndPosition - track.GetPosition()).mag2() >= 1.0e-16) )
791 {
793 "End of Step Position" );
794 G4cerr << " Problem in G4CoupledTransportation::PostStepDoIt " << G4endl;
795 }
796
797 // If the Step was determined by the volume boundary, relocate the particle
798 // The pathFinder will know that the geometry limited the step (!?)
799
800 if( verboseLevel > 0 )
801 {
802 G4cout << " Calling PathFinder::Locate() from "
803 << " G4CoupledTransportation::PostStepDoIt " << G4endl;
804 G4cout << " fAnyGeometryLimitedStep is " << fAnyGeometryLimitedStep
805 << G4endl;
806
807 }
808#endif
809
811 {
812 fPathFinder->Locate( track.GetPosition(),
813 track.GetMomentumDirection(),
814 true);
815
816 // fCurrentTouchable will now become the previous touchable,
817 // and what was the previous will be freed.
818 // (Needed because the preStepPoint can point to the previous touchable)
819
822
823#ifdef G4DEBUG_TRANSPORT
824 if( verboseLevel > 0 )
825 {
826 G4cout << "G4CoupledTransportation::PostStepDoIt --- fNavigatorId = "
827 << fNavigatorId << G4endl;
828 }
829 if( verboseLevel > 1 )
830 {
832 G4cout << "CHECK !!!!!!!!!!! fCurrentTouchableHandle->GetVolume() = "
833 << vol;
834 if( vol ) { G4cout << "Name=" << vol->GetName(); }
835 G4cout << G4endl;
836 }
837#endif
838
839 // Check whether the particle is out of the world volume
840 // If so it has exited and must be killed.
841 //
843 {
845 }
846 retCurrentTouchable = fCurrentTouchableHandle ;
847 // fParticleChange.SetTouchableHandle( fCurrentTouchableHandle ) ;
848 }
849 else // fAnyGeometryLimitedStep is false
850 {
851#ifdef G4DEBUG_TRANSPORT
852 if( verboseLevel > 1 )
853 {
854 G4cout << "G4CoupledTransportation::PostStepDoIt -- "
855 << " fAnyGeometryLimitedStep = " << fAnyGeometryLimitedStep
856 << " must be false " << G4endl;
857 }
858#endif
859 // This serves only to move each of the Navigator's location
860 //
861 // fLinearNavigator->LocateGlobalPointWithinVolume( track.GetPosition() ) ;
862
863 fPathFinder->ReLocate( track.GetPosition() );
864 // track.GetMomentumDirection() );
865
866 // Keep the value of the track's current Touchable is retained,
867 // and use it to overwrite the (unset) one in particle change.
868 // Expect this must be fCurrentTouchable too
869 // - could it be different, eg at the start of a step ?
870 //
871 retCurrentTouchable = track.GetTouchableHandle() ;
872 // fParticleChange.SetTouchableHandle( track.GetTouchableHandle() ) ;
873 } // endif ( fAnyGeometryLimitedStep )
874
875#ifdef G4DEBUG_NAVIGATION
876 G4cout << " CoupledTransport::AlongStep GPIL: "
877 << " last-step: any= " << fAnyGeometryLimitedStep
878 << " . ..... x . "
879 << " mass= " << fMassGeometryLimitedStep
880 << G4endl;
881#endif
882
885 else
887
888 const G4VPhysicalVolume* pNewVol = retCurrentTouchable->GetVolume() ;
889 const G4Material* pNewMaterial = 0 ;
890 const G4VSensitiveDetector* pNewSensitiveDetector = 0 ;
891
892 if( pNewVol != 0 )
893 {
894 pNewMaterial= pNewVol->GetLogicalVolume()->GetMaterial();
895 pNewSensitiveDetector= pNewVol->GetLogicalVolume()->GetSensitiveDetector();
896 }
897
898 // ( const_cast<G4Material *> pNewMaterial ) ;
899 // ( const_cast<G4VSensitiveDetetor *> pNewSensitiveDetector) ;
900
903 // "temporarily" until Get/Set Material of ParticleChange,
904 // and StepPoint can be made const.
905
906 const G4MaterialCutsCouple* pNewMaterialCutsCouple = 0;
907 if( pNewVol != 0 )
908 {
909 pNewMaterialCutsCouple=pNewVol->GetLogicalVolume()->GetMaterialCutsCouple();
910 if( pNewMaterialCutsCouple!=0
911 && pNewMaterialCutsCouple->GetMaterial()!=pNewMaterial )
912 {
913 // for parametrized volume
914 //
915 pNewMaterialCutsCouple = G4ProductionCutsTable::GetProductionCutsTable()
916 ->GetMaterialCutsCouple(pNewMaterial,
917 pNewMaterialCutsCouple->GetProductionCuts());
918 }
919 }
920 fParticleChange.SetMaterialCutsCoupleInTouchable( pNewMaterialCutsCouple );
921
922 // Must always set the touchable in ParticleChange, whether relocated or not
923 //
924 fParticleChange.SetTouchableHandle(retCurrentTouchable) ;
925
926 return &fParticleChange ;
927}
928
930// New method takes over the responsibility to reset the state of
931// G4CoupledTransportation object:
932// - at the start of a new track, and
933// - on the resumption of a suspended track.
934//
935void
937{
938
939 G4TransportationManager* transportMgr =
941
942 // G4VProcess::StartTracking(aTrack);
943 fNewTrack= true;
944
945 // The 'initialising' actions
946 // once taken in AlongStepGPIL -- if ( track.GetCurrentStepNumber()==1 )
947
948 // fStartedNewTrack= true;
949
950 fMassNavigator = transportMgr->GetNavigatorForTracking() ;
952
954 G4ThreeVector direction = aTrack->GetMomentumDirection();
955
956 fPathFinder->PrepareNewTrack( position, direction);
957 // This implies a call to fPathFinder->Locate( position, direction );
958
959 // Whether field exists should be determined at run level -- TODO
961
962 // reset safety value and center
963 //
964 fPreviousMassSafety = 0.0 ;
965 fPreviousFullSafety = 0.0 ;
967
968 // reset looping counter -- for motion in field
969 fNoLooperTrials= 0;
970
971 // Must clear this state .. else it depends on last track's value
972 // --> a better solution would set this from state of suspended track TODO ?
973 // Was if( aTrack->GetCurrentStepNumber()==1 ) { .. }
974
975 // ChordFinder reset internal state
976 //
978 {
980 // Resets safety values, in case of overlaps.
981
983 if( chordF ) { chordF->ResetStepEstimate(); }
984 }
985
986 // Clear the chord finders of all fields (ie managers) derived objects
987 //
989 fieldMgrStore->ClearAllChordFindersState();
990
991#ifdef G4DEBUG_TRANSPORT
992 if( verboseLevel > 1 )
993 {
994 G4cout << " Returning touchable handle " << fCurrentTouchableHandle
995 << G4endl;
996 }
997#endif
998
999 // Update the current touchable handle (from the track's)
1000 //
1002}
1003
1005
1006void
1008{
1011 // Resets TransportationManager to use ordinary Navigator
1012}
1013
1015
1016void
1018ReportInexactEnergy(G4double startEnergy, G4double endEnergy)
1019{
1020 static G4ThreadLocal G4int no_warnings= 0, warnModulo=1,
1021 moduloFactor= 10, no_large_ediff= 0;
1022
1023 if( std::fabs(startEnergy- endEnergy) > perThousand * endEnergy )
1024 {
1025 no_large_ediff ++;
1026 if( (no_large_ediff% warnModulo) == 0 )
1027 {
1028 no_warnings++;
1029 std::ostringstream message;
1030 message << "Energy change in Step is above 1^-3 relative value. "
1031 << G4endl
1032 << " Relative change in 'tracking' step = "
1033 << std::setw(15) << (endEnergy-startEnergy)/startEnergy
1034 << G4endl
1035 << " Starting E= " << std::setw(12) << startEnergy / MeV
1036 << " MeV " << G4endl
1037 << " Ending E= " << std::setw(12) << endEnergy / MeV
1038 << " MeV " << G4endl
1039 << "Energy has been corrected -- however, review"
1040 << " field propagation parameters for accuracy." << G4endl;
1041 if ( (verboseLevel > 2 ) || (no_warnings<4)
1042 || (no_large_ediff == warnModulo * moduloFactor) )
1043 {
1044 message << "These include EpsilonStepMax(/Min) in G4FieldManager,"
1045 << G4endl
1046 << "which determine fractional error per step for integrated quantities."
1047 << G4endl
1048 << "Note also the influence of the permitted number of integration steps."
1049 << G4endl;
1050 }
1051 message << "Bad 'endpoint'. Energy change detected and corrected."
1052 << G4endl
1053 << "Has occurred already " << no_large_ediff << " times.";
1054 G4Exception("G4CoupledTransportation::AlongStepGetPIL()",
1055 "EnergyChange", JustWarning, message);
1056 if( no_large_ediff == warnModulo * moduloFactor )
1057 {
1058 warnModulo *= moduloFactor;
1059 }
1060 }
1061 }
1062}
1063
1065
1067{
1068 G4bool lastValue= fUseMagneticMoment;
1069 fUseMagneticMoment= useMoment;
1071 return lastValue;
1072}
1073
1075//
1076
1078{
1079 G4bool lastValue= fUseGravity;
1080 fUseGravity= useGravity;
1082 return lastValue;
1083}
1084
1086//
1087// Supress (or not) warnings about 'looping' particles
1088
1090{
1091 fSilenceLooperWarnings= val; // Flag to *Supress* all 'looper' warnings
1092 // G4CoupledTransportation::fSilenceLooperWarnings= val;
1093}
1094
1096//
1098{
1099 return fSilenceLooperWarnings;
1100}
1101
1103//
1105{
1106 // Setting old 'high' values for thresholds - old values, potentially appropriate
1107 // for the energy frontier HEP experiments
1108 SetThresholdWarningEnergy( 100.0 * CLHEP::MeV ); // Warn above this energy
1109 SetThresholdImportantEnergy( 250.0 * CLHEP::MeV ); // Give a few trial above this E);
1110
1111 G4int maxTrials = 10;
1112 SetThresholdTrials( maxTrials );
1113
1115}
1116
1118void G4CoupledTransportation::SetLowLooperThresholds() // Values for low-E applications
1119{
1120 // These values were the default in Geant4 10.5 - beta
1121 SetThresholdWarningEnergy( 1.0 * CLHEP::keV ); // Warn above this En
1122 SetThresholdImportantEnergy( 1.0 * CLHEP::MeV ); // Extra trials above it
1123
1124 G4int maxTrials = 30; // A new value - was 10
1125 SetThresholdTrials( maxTrials );
1126
1128}
1129
1131//
1132void
1134{
1135 const char* message= "Logger object missing from G4CoupledTransportation";
1136 G4String classAndMethod= G4String("G4CoupledTransportation") + G4String( methodName );
1137 G4Exception(classAndMethod, "Missing Logger", JustWarning, message);
1138
1140}
1141
1143//
1144void
1146{
1147 PushThresholdsToLogger(); // To be absolutely certain they are in sync
1148 fpLogger->ReportLooperThresholds("G4CoupledTransportation");
1149}
@ JustWarning
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
G4ForceCondition
@ Forced
G4GPILSelection
@ CandidateForSelection
#define fPreviousSftOrigin
#define fNewTrack
ELimited
@ kUnique
@ kSharedTransport
@ fTransportation
static constexpr double perMillion
Definition: G4SIunits.hh:327
static constexpr double mm
Definition: G4SIunits.hh:95
static constexpr double MeV
Definition: G4SIunits.hh:200
static constexpr double perThousand
Definition: G4SIunits.hh:326
CLHEP::Hep3Vector G4ThreeVector
G4ReferenceCountedHandle< G4VTouchable > G4TouchableHandle
@ fStopAndKill
double G4double
Definition: G4Types.hh:83
long G4long
Definition: G4Types.hh:87
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
G4GLOB_DLL std::ostream G4cerr
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
double mag2() const
double mag() const
void ResetStepEstimate()
G4VParticleChange * AlongStepDoIt(const G4Track &track, const G4Step &stepData)
G4VParticleChange * PostStepDoIt(const G4Track &track, const G4Step &stepData)
void SetThresholdTrials(G4int newMaxTrials)
G4TransportationLogger * fpLogger
static G4bool EnableGravity(G4bool useGravity)
void ReportMove(G4ThreeVector OldVector, G4ThreeVector NewVector, const G4String &Quantity)
static void SetSilenceLooperWarnings(G4bool val)
void ReportInexactEnergy(G4double startEnergy, G4double endEnergy)
static G4bool EnableMagneticMoment(G4bool useMoment=true)
void PrintStatistics(std::ostream &outStr) const
G4TouchableHandle fCurrentTouchableHandle
G4CoupledTransportation(G4int verbosityLevel=0)
G4double PostStepGetPhysicalInteractionLength(const G4Track &, G4double previousStepSize, G4ForceCondition *pForceCond)
G4PropagatorInField * fFieldPropagator
void SetThresholdImportantEnergy(G4double newEnImp)
void SetThresholdWarningEnergy(G4double newEnWarn)
void StartTracking(G4Track *aTrack)
G4double AlongStepGetPhysicalInteractionLength(const G4Track &track, G4double previousStepSize, G4double currentMinimumStep, G4double &currentSafety, G4GPILSelection *selection)
void ReportMissingLogger(const char *methodName)
G4ParticleChangeForTransport fParticleChange
G4double GetMass() const
const G4ThreeVector & GetMomentumDirection() const
G4double GetCharge() const
G4ParticleDefinition * GetDefinition() const
G4double GetMagneticMoment() const
G4double GetTotalMomentum() const
static G4FieldManagerStore * GetInstance()
G4bool DoesFieldChangeEnergy() const
virtual void ConfigureForTrack(const G4Track *)
const G4Field * GetDetectorField() const
const G4ThreeVector & GetMomentumDir() const
G4double GetKineticEnergy() const
G4ThreeVector GetPosition() const
G4ThreeVector GetSpin() const
G4double GetLabTimeOfFlight() const
G4bool IsGravityActive() const
Definition: G4Field.hh:101
G4VSensitiveDetector * GetSensitiveDetector() const
G4Material * GetMaterial() const
const G4MaterialCutsCouple * GetMaterialCutsCouple() const
const G4Material * GetMaterial() const
G4ProductionCuts * GetProductionCuts() const
void SetPointerToVectorOfAuxiliaryPoints(std::vector< G4ThreeVector > *vec)
void SetMaterialInTouchable(G4Material *fMaterial)
void SetTouchableHandle(const G4TouchableHandle &fTouchable)
void SetMaterialCutsCoupleInTouchable(const G4MaterialCutsCouple *fMaterialCutsCouple)
virtual void Initialize(const G4Track &)
void SetSensitiveDetectorInTouchable(G4VSensitiveDetector *fSensitiveDetector)
void SetMomentumChanged(G4bool b)
void ProposePolarization(G4double Px, G4double Py, G4double Pz)
void ProposePosition(G4double x, G4double y, G4double z)
void ProposeLocalTime(G4double t)
void ProposeProperTime(G4double finalProperTime)
void ProposeEnergy(G4double finalEnergy)
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
void ProposeGlobalTime(G4double t)
G4double GetPDGMagneticMoment() const
G4bool GetPDGStable() const
G4double ComputeSafety(const G4ThreeVector &globalPoint)
void ReLocate(const G4ThreeVector &position)
unsigned int GetNumberGeometriesLimitingStep() const
G4double ObtainSafety(G4int navId, G4ThreeVector &globalCenterPoint)
G4double ComputeStep(const G4FieldTrack &pFieldTrack, G4double pCurrentProposedStepLength, G4int navigatorId, G4int stepNo, G4double &pNewSafety, ELimited &limitedStep, G4FieldTrack &EndState, G4VPhysicalVolume *currentVolume)
void Locate(const G4ThreeVector &position, const G4ThreeVector &direction, G4bool relativeSearch=true)
G4double GetCurrentSafety() const
void PrepareNewTrack(const G4ThreeVector &position, const G4ThreeVector &direction, G4VPhysicalVolume *massStartVol=nullptr)
static G4PathFinder * GetInstance()
Definition: G4PathFinder.cc:52
G4TouchableHandle CreateTouchableHandle(G4int navId) const
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
static G4ProductionCutsTable * GetProductionCutsTable()
G4FieldManager * FindAndSetFieldManager(G4VPhysicalVolume *pCurrentPhysVol)
G4FieldManager * GetCurrentFieldManager()
G4bool IsParticleLooping() const
G4ChordFinder * GetChordFinder()
G4EquationOfMotion * GetCurrentEquationOfMotion()
std::vector< G4ThreeVector > * GimmeTrajectoryVectorAndForgetIt() const
void SetCurrentSafety(G4double val, const G4ThreeVector &pos)
G4double GetVelocity() const
Definition: G4Step.hh:62
G4StepPoint * GetPreStepPoint() const
G4TrackStatus GetTrackStatus() const
G4double GetVelocity() const
G4VPhysicalVolume * GetVolume() const
const G4ThreeVector & GetPosition() const
G4double GetGlobalTime() const
G4double GetProperTime() const
G4int GetCurrentStepNumber() const
G4double GetLocalTime() const
const G4DynamicParticle * GetDynamicParticle() const
const G4TouchableHandle & GetTouchableHandle() const
const G4ThreeVector & GetMomentumDirection() const
G4double GetKineticEnergy() const
const G4ThreeVector & GetPolarization() const
G4double GetStepLength() const
G4double GetTotalEnergy() const
void ReportLoopingTrack(const G4Track &track, const G4Step &stepInfo, G4int numTrials, G4long noCalls, const char *methodName) const
void ReportLooperThresholds(const char *className)
static G4TransportationManager * GetTransportationManager()
G4PropagatorInField * GetPropagatorInField() const
G4SafetyHelper * GetSafetyHelper() const
G4Navigator * GetNavigatorForTracking() const
G4int ActivateNavigator(G4Navigator *aNavigator)
static G4bool fUseGravity
static G4bool fUseMagneticMoment
void ProposeTrackStatus(G4TrackStatus status)
void ProposeLastStepInVolume(G4bool flag)
void ProposeFirstStepInVolume(G4bool flag)
void ProposeTrueStepLength(G4double truePathLength)
G4LogicalVolume * GetLogicalVolume() const
const G4String & GetName() const
void SetVerboseLevel(G4int value)
Definition: G4VProcess.hh:412
G4int verboseLevel
Definition: G4VProcess.hh:356
void SetProcessSubType(G4int)
Definition: G4VProcess.hh:406
virtual G4VPhysicalVolume * GetVolume(G4int depth=0) const
Definition: G4VTouchable.cc:34
static const double prec
Definition: RanecuEngine.cc:61
static constexpr double keV
static constexpr double MeV
T max(const T t1, const T t2)
brief Return the largest of the two arguments
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
T sqr(const T &x)
Definition: templates.hh:128
#define DBL_MAX
Definition: templates.hh:62
#define G4ThreadLocal
Definition: tls.hh:77