Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-12-03 23:52:25

0001 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0002 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0003 //
0004 // This class is a process responsible for the transportation of
0005 // magnetic monopoles, ie the geometrical propagation that encounters the
0006 // geometrical sub-volumes of the detectors.
0007 //
0008 // =======================================================================
0009 // Created:  3 May 2010, J. Apostolakis, B. Bozsogi
0010 //                       G4MonopoleTransportation class for
0011 //                       Geant4 extended example "monopole"
0012 //
0013 // Adopted for CMSSW by V.Ivanchenko 30 April 2018
0014 //
0015 // =======================================================================
0016 
0017 #include "SimG4Core/PhysicsLists/interface/MonopoleTransportation.h"
0018 #include "SimG4Core/Physics/interface/Monopole.h"
0019 #include "SimG4Core/MagneticField/interface/CMSFieldManager.h"
0020 
0021 #include "G4ProductionCutsTable.hh"
0022 #include "G4ParticleTable.hh"
0023 #include "G4ChordFinder.hh"
0024 #include "G4SafetyHelper.hh"
0025 #include "G4FieldManagerStore.hh"
0026 #include "G4TransportationProcessType.hh"
0027 #include "G4SystemOfUnits.hh"
0028 
0029 class G4VSensitiveDetector;
0030 
0031 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0032 
0033 MonopoleTransportation::MonopoleTransportation(const Monopole* mpl, G4int verb)
0034     : G4VProcess(G4String("MonopoleTransportation"), fTransportation),
0035       fParticleDef(mpl),
0036       fieldMgrCMS(nullptr),
0037       fLinearNavigator(nullptr),
0038       fFieldPropagator(nullptr),
0039       fParticleIsLooping(false),
0040       fPreviousSftOrigin(0., 0., 0.),
0041       fPreviousSafety(0.0),
0042       fThreshold_Warning_Energy(100 * MeV),
0043       fThreshold_Important_Energy(250 * MeV),
0044       fThresholdTrials(10),
0045       fNoLooperTrials(0),
0046       fSumEnergyKilled(0.0),
0047       fMaxEnergyKilled(0.0),
0048       fShortStepOptimisation(false),  // Old default: true (=fast short steps)
0049       fpSafetyHelper(nullptr) {
0050   verboseLevel = verb;
0051 
0052   // set Process Sub Type
0053   SetProcessSubType(TRANSPORTATION);
0054 
0055 #ifdef G4MULTITHREADED
0056   // Do not finalize the MonopoleTransportation class
0057   if (G4Threading::IsMasterThread()) {
0058     return;
0059   }
0060 #endif
0061 
0062   G4TransportationManager* transportMgr = G4TransportationManager::GetTransportationManager();
0063 
0064   fLinearNavigator = transportMgr->GetNavigatorForTracking();
0065 
0066   fFieldPropagator = transportMgr->GetPropagatorInField();
0067   fpSafetyHelper = transportMgr->GetSafetyHelper();
0068 
0069   // Cannot determine whether a field exists here,
0070   //  because it would only work if the field manager has informed
0071   //  about the detector's field before this transportation process
0072   //  is constructed.
0073   // Instead later the method DoesGlobalFieldExist() is called
0074 
0075   fCurrentTouchableHandle = nullptr;
0076 
0077   fEndGlobalTimeComputed = false;
0078   fCandidateEndGlobalTime = 0;
0079 }
0080 
0081 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0082 
0083 MonopoleTransportation::~MonopoleTransportation() {
0084   if ((verboseLevel > 0) && (fSumEnergyKilled > 0.0)) {
0085     /*
0086     G4cout << " MonopoleTransportation: Statistics for looping particles " 
0087            << G4endl;
0088     G4cout << "   Sum of energy of loopers killed: " <<  fSumEnergyKilled << G4endl;
0089     G4cout << "   Max energy of loopers killed: " <<  fMaxEnergyKilled << G4endl;
0090     */
0091   }
0092 }
0093 
0094 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0095 //
0096 // Responsibilities:
0097 //    Find whether the geometry limits the Step, and to what length
0098 //    Calculate the new value of the safety and return it.
0099 //    Store the final time, position and momentum.
0100 
0101 G4double MonopoleTransportation::AlongStepGetPhysicalInteractionLength(const G4Track& track,
0102                                                                        G4double,  //  previousStepSize
0103                                                                        G4double currentMinimumStep,
0104                                                                        G4double& currentSafety,
0105                                                                        G4GPILSelection* selection) {
0106   // change to monopole equation
0107   fieldMgrCMS->setMonopoleTracking(true);
0108 
0109   G4double geometryStepLength, newSafety;
0110   fParticleIsLooping = false;
0111 
0112   // Initial actions moved to  StartTrack()
0113   // --------------------------------------
0114   // Note: in case another process changes touchable handle
0115   //    it will be necessary to add here (for all steps)
0116   // fCurrentTouchableHandle = aTrack->GetTouchableHandle();
0117 
0118   // GPILSelection is set to defaule value of CandidateForSelection
0119   // It is a return value
0120   //
0121   *selection = CandidateForSelection;
0122 
0123   // Get initial Energy/Momentum of the track
0124   //
0125   const G4DynamicParticle* pParticle = track.GetDynamicParticle();
0126   const G4ThreeVector& startMomentumDir = pParticle->GetMomentumDirection();
0127   G4ThreeVector startPosition = track.GetPosition();
0128 
0129   // The Step Point safety can be limited by other geometries and/or the
0130   // assumptions of any process - it's not always the geometrical safety.
0131   // We calculate the starting point's isotropic safety here.
0132   //
0133   G4ThreeVector OriginShift = startPosition - fPreviousSftOrigin;
0134   G4double MagSqShift = OriginShift.mag2();
0135   if (MagSqShift >= sqr(fPreviousSafety)) {
0136     currentSafety = 0.0;
0137   } else {
0138     currentSafety = fPreviousSafety - std::sqrt(MagSqShift);
0139   }
0140 
0141   // Is the monopole charged ?
0142   //
0143   G4double particleMagneticCharge = fParticleDef->MagneticCharge();
0144   G4double particleElectricCharge = pParticle->GetCharge();
0145 
0146   fGeometryLimitedStep = false;
0147 
0148   // There is no need to locate the current volume. It is Done elsewhere:
0149   //   On track construction
0150   //   By the tracking, after all AlongStepDoIts, in "Relocation"
0151 
0152   // Check whether the particle have an (EM) field force exerting upon it
0153   G4bool fieldExertsForce = false;
0154 
0155   if (particleMagneticCharge != 0.0 && fieldMgrCMS) {
0156     // Message the field Manager, to configure it for this track
0157     fieldMgrCMS->ConfigureForTrack(&track);
0158     // Moved here, in order to allow a transition
0159     //   from a zero-field  status (with fieldMgr->(field)0
0160     //   to a finite field  status
0161 
0162     // If the field manager has no field, there is no field !
0163     fieldExertsForce = (fieldMgrCMS->GetDetectorField() != nullptr);
0164   }
0165 
0166   // G4cout << " G4Transport:  field exerts force= " << fieldExertsForce
0167   //          << "  fieldMgr= " << fieldMgr << G4endl;
0168 
0169   // Choose the calculation of the transportation: Field or not
0170   //
0171   if (!fieldExertsForce) {
0172     G4double linearStepLength;
0173     if (fShortStepOptimisation && (currentMinimumStep <= currentSafety)) {
0174       // The Step is guaranteed to be taken
0175       //
0176       geometryStepLength = currentMinimumStep;
0177       fGeometryLimitedStep = false;
0178     } else {
0179       //  Find whether the straight path intersects a volume
0180       //
0181       linearStepLength = fLinearNavigator->ComputeStep(startPosition, startMomentumDir, currentMinimumStep, newSafety);
0182       // Remember last safety origin & value.
0183       //
0184       fPreviousSftOrigin = startPosition;
0185       fPreviousSafety = newSafety;
0186       // fpSafetyHelper->SetCurrentSafety( newSafety, startPosition);
0187 
0188       // The safety at the initial point has been re-calculated:
0189       //
0190       currentSafety = newSafety;
0191 
0192       fGeometryLimitedStep = (linearStepLength <= currentMinimumStep);
0193       if (fGeometryLimitedStep) {
0194         // The geometry limits the Step size (an intersection was found.)
0195         geometryStepLength = linearStepLength;
0196       } else {
0197         // The full Step is taken.
0198         geometryStepLength = currentMinimumStep;
0199       }
0200     }
0201     endpointDistance = geometryStepLength;
0202 
0203     // Calculate final position
0204     //
0205     fTransportEndPosition = startPosition + geometryStepLength * startMomentumDir;
0206 
0207     // Momentum direction, energy and polarisation are unchanged by transport
0208     //
0209     fTransportEndMomentumDir = startMomentumDir;
0210     fTransportEndKineticEnergy = track.GetKineticEnergy();
0211     fTransportEndSpin = track.GetPolarization();
0212     fParticleIsLooping = false;
0213     fMomentumChanged = false;
0214     fEndGlobalTimeComputed = false;
0215   } else  //  A field exerts force
0216   {
0217     G4double momentumMagnitude = pParticle->GetTotalMomentum();
0218     G4ThreeVector EndUnitMomentum;
0219     G4double lengthAlongCurve;
0220     G4double restMass = fParticleDef->GetPDGMass();
0221 
0222     G4ChargeState chargeState(particleElectricCharge,  // The charge can change (dynamic)
0223                               fParticleDef->GetPDGSpin(),
0224                               0,                        //  Magnetic moment:  pParticleDef->GetMagneticMoment(),
0225                               0,                        //  Electric Dipole moment - not in Particle Definition
0226                               particleMagneticCharge);  // in Mev/c
0227 
0228     G4EquationOfMotion* equationOfMotion =
0229         fFieldPropagator->GetChordFinder()->GetIntegrationDriver()->GetEquationOfMotion();
0230 
0231     equationOfMotion->SetChargeMomentumMass(chargeState,        //  Was particleMagneticCharge - in Mev/c
0232                                             momentumMagnitude,  //  Was particleElectricCharge
0233                                             restMass);
0234     // SetChargeMomentumMass now passes both the electric and magnetic charge - in chargeState
0235 
0236     G4ThreeVector spin = track.GetPolarization();
0237     G4FieldTrack aFieldTrack = G4FieldTrack(startPosition,
0238                                             track.GetMomentumDirection(),
0239                                             0.0,
0240                                             track.GetKineticEnergy(),
0241                                             restMass,
0242                                             track.GetVelocity(),
0243                                             track.GetGlobalTime(),  // Lab.
0244                                             track.GetProperTime(),  // Part.
0245                                             &spin);
0246     if (currentMinimumStep > 0) {
0247       // Do the Transport in the field (non recti-linear)
0248       //
0249       lengthAlongCurve =
0250           fFieldPropagator->ComputeStep(aFieldTrack, currentMinimumStep, currentSafety, track.GetVolume());
0251       fGeometryLimitedStep = lengthAlongCurve < currentMinimumStep;
0252       if (fGeometryLimitedStep) {
0253         geometryStepLength = lengthAlongCurve;
0254       } else {
0255         geometryStepLength = currentMinimumStep;
0256       }
0257     } else {
0258       geometryStepLength = 0.0;
0259       fGeometryLimitedStep = false;
0260     }
0261 
0262     // Remember last safety origin & value.
0263     //
0264     fPreviousSftOrigin = startPosition;
0265     fPreviousSafety = currentSafety;
0266     // fpSafetyHelper->SetCurrentSafety( newSafety, startPosition);
0267 
0268     // Get the End-Position and End-Momentum (Dir-ection)
0269     //
0270     fTransportEndPosition = aFieldTrack.GetPosition();
0271 
0272     // Momentum:  Magnitude and direction can be changed too now ...
0273     //
0274     fMomentumChanged = true;
0275     fTransportEndMomentumDir = aFieldTrack.GetMomentumDir();
0276 
0277     fTransportEndKineticEnergy = aFieldTrack.GetKineticEnergy();
0278 
0279     fCandidateEndGlobalTime = aFieldTrack.GetLabTimeOfFlight();
0280     fEndGlobalTimeComputed = true;
0281 
0282     fTransportEndSpin = aFieldTrack.GetSpin();
0283     fParticleIsLooping = fFieldPropagator->IsParticleLooping();
0284     endpointDistance = (fTransportEndPosition - startPosition).mag();
0285   }
0286 
0287   // If we are asked to go a step length of 0, and we are on a boundary
0288   // then a boundary will also limit the step -> we must flag this.
0289   //
0290   if (currentMinimumStep == 0.0) {
0291     if (currentSafety == 0.0)
0292       fGeometryLimitedStep = true;
0293   }
0294 
0295   // Update the safety starting from the end-point,
0296   // if it will become negative at the end-point.
0297   //
0298   if (currentSafety < endpointDistance) {
0299     if (particleMagneticCharge != 0.0) {
0300       G4double endSafety = fLinearNavigator->ComputeSafety(fTransportEndPosition);
0301       currentSafety = endSafety;
0302       fPreviousSftOrigin = fTransportEndPosition;
0303       fPreviousSafety = currentSafety;
0304       fpSafetyHelper->SetCurrentSafety(currentSafety, fTransportEndPosition);
0305 
0306       // Because the Stepping Manager assumes it is from the start point,
0307       //  add the StepLength
0308       //
0309       currentSafety += endpointDistance;
0310 
0311 #ifdef G4DEBUG_TRANSPORT
0312       G4cout.precision(12);
0313       G4cout << "***MonopoleTransportation::AlongStepGPIL ** " << G4endl;
0314       G4cout << "  Called Navigator->ComputeSafety at " << fTransportEndPosition
0315              << "    and it returned safety= " << endSafety << G4endl;
0316       G4cout << "  Adding endpoint distance " << endpointDistance << "   to obtain pseudo-safety= " << currentSafety
0317              << G4endl;
0318 #endif
0319     }
0320   }
0321 
0322   fParticleChange.ProposeTrueStepLength(geometryStepLength);
0323 
0324   return geometryStepLength;
0325 }
0326 
0327 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0328 //
0329 //   Initialize ParticleChange  (by setting all its members equal
0330 //                               to corresponding members in G4Track)
0331 
0332 G4VParticleChange* MonopoleTransportation::AlongStepDoIt(const G4Track& track, const G4Step& stepData) {
0333   fParticleChange.Initialize(track);
0334 
0335   //  Code for specific process
0336   //
0337   fParticleChange.ProposePosition(fTransportEndPosition);
0338   fParticleChange.ProposeMomentumDirection(fTransportEndMomentumDir);
0339   fParticleChange.ProposeEnergy(fTransportEndKineticEnergy);
0340   fParticleChange.SetMomentumChanged(fMomentumChanged);
0341 
0342   fParticleChange.ProposePolarization(fTransportEndSpin);
0343 
0344   G4double deltaTime = 0.0;
0345 
0346   // Calculate  Lab Time of Flight (ONLY if field Equations used it!)
0347   G4double startTime = track.GetGlobalTime();
0348 
0349   if (!fEndGlobalTimeComputed) {
0350     // The time was not integrated .. make the best estimate possible
0351     //
0352     G4double finalVelocity = track.GetVelocity();
0353     G4double initialVelocity = stepData.GetPreStepPoint()->GetVelocity();
0354     G4double stepLength = track.GetStepLength();
0355 
0356     deltaTime = 0.0;  // in case initialVelocity = 0
0357     if (finalVelocity > 0.0) {
0358       G4double meanInverseVelocity;
0359       meanInverseVelocity = 0.5 * (1.0 / initialVelocity + 1.0 / finalVelocity);
0360       deltaTime = stepLength * meanInverseVelocity;
0361     } else if (initialVelocity > 0.0) {
0362       deltaTime = stepLength / initialVelocity;
0363     }
0364     fCandidateEndGlobalTime = startTime + deltaTime;
0365   } else {
0366     deltaTime = fCandidateEndGlobalTime - startTime;
0367   }
0368 
0369   fParticleChange.ProposeGlobalTime(fCandidateEndGlobalTime);
0370 
0371   // Now Correct by Lorentz factor to get "proper" deltaTime
0372 
0373   G4double restMass = track.GetDynamicParticle()->GetMass();
0374   G4double deltaProperTime = deltaTime * (restMass / track.GetTotalEnergy());
0375 
0376   fParticleChange.ProposeProperTime(track.GetProperTime() + deltaProperTime);
0377   //fParticleChange. ProposeTrueStepLength( track.GetStepLength() ) ;
0378 
0379   // If the particle is caught looping or is stuck (in very difficult
0380   // boundaries) in a magnetic field (doing many steps)
0381   //   THEN this kills it ...
0382   //
0383   if (fParticleIsLooping) {
0384     G4double endEnergy = fTransportEndKineticEnergy;
0385 
0386     if ((endEnergy < fThreshold_Important_Energy) || (fNoLooperTrials >= fThresholdTrials)) {
0387       // Kill the looping particle
0388       //
0389       fParticleChange.ProposeTrackStatus(fStopAndKill);
0390 
0391       // 'Bare' statistics
0392       fSumEnergyKilled += endEnergy;
0393       if (endEnergy > fMaxEnergyKilled) {
0394         fMaxEnergyKilled = endEnergy;
0395       }
0396 
0397 #ifdef G4VERBOSE
0398       if ((verboseLevel > 1) || (endEnergy > fThreshold_Warning_Energy)) {
0399         G4cout << " MonopoleTransportation is killing track that is looping or stuck " << G4endl << "   This track has "
0400                << track.GetKineticEnergy() / MeV << " MeV energy." << G4endl;
0401         G4cout << "   Number of trials = " << fNoLooperTrials << G4endl;
0402       }
0403 #endif
0404       fNoLooperTrials = 0;
0405     } else {
0406       fNoLooperTrials++;
0407 #ifdef G4VERBOSE
0408       if ((verboseLevel > 2)) {
0409         G4cout << "   MonopoleTransportation::AlongStepDoIt(): Particle looping -  "
0410                << "   Number of trials = " << fNoLooperTrials << G4endl;
0411       }
0412 #endif
0413     }
0414   } else {
0415     fNoLooperTrials = 0;
0416   }
0417 
0418   // Another (sometimes better way) is to use a user-limit maximum Step size
0419   // to alleviate this problem ..
0420 
0421   // Introduce smooth curved trajectories to particle-change
0422   //
0423   fParticleChange.SetPointerToVectorOfAuxiliaryPoints(fFieldPropagator->GimmeTrajectoryVectorAndForgetIt());
0424 
0425   return &fParticleChange;
0426 }
0427 
0428 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0429 //
0430 //  This ensures that the PostStep action is always called,
0431 //  so that it can do the relocation if it is needed.
0432 //
0433 
0434 G4double MonopoleTransportation::PostStepGetPhysicalInteractionLength(const G4Track&,
0435                                                                       G4double,  // previousStepSize
0436                                                                       G4ForceCondition* pForceCond) {
0437   *pForceCond = Forced;
0438   return DBL_MAX;  // was kInfinity ; but convention now is DBL_MAX
0439 }
0440 
0441 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0442 
0443 G4VParticleChange* MonopoleTransportation::PostStepDoIt(const G4Track& track, const G4Step&) {
0444   G4TouchableHandle retCurrentTouchable;  // The one to return
0445 
0446   fParticleChange.ProposeTrackStatus(track.GetTrackStatus());
0447 
0448   // If the Step was determined by the volume boundary,
0449   // logically relocate the particle
0450 
0451   if (fGeometryLimitedStep) {
0452     // fCurrentTouchable will now become the previous touchable,
0453     // and what was the previous will be freed.
0454     // (Needed because the preStepPoint can point to the previous touchable)
0455 
0456     fLinearNavigator->SetGeometricallyLimitedStep();
0457     fLinearNavigator->LocateGlobalPointAndUpdateTouchableHandle(
0458         track.GetPosition(), track.GetMomentumDirection(), fCurrentTouchableHandle, true);
0459     // Check whether the particle is out of the world volume
0460     // If so it has exited and must be killed.
0461     //
0462     if (fCurrentTouchableHandle->GetVolume() == nullptr) {
0463       fParticleChange.ProposeTrackStatus(fStopAndKill);
0464     }
0465     retCurrentTouchable = fCurrentTouchableHandle;
0466     fParticleChange.SetTouchableHandle(fCurrentTouchableHandle);
0467   } else  // fGeometryLimitedStep  is false
0468   {
0469     // This serves only to move the Navigator's location
0470     //
0471     fLinearNavigator->LocateGlobalPointWithinVolume(track.GetPosition());
0472 
0473     // The value of the track's current Touchable is retained.
0474     // (and it must be correct because we must use it below to
0475     // overwrite the (unset) one in particle change)
0476     //  It must be fCurrentTouchable too ??
0477     //
0478     fParticleChange.SetTouchableHandle(track.GetTouchableHandle());
0479     retCurrentTouchable = track.GetTouchableHandle();
0480   }  // endif ( fGeometryLimitedStep )
0481 
0482   const G4VPhysicalVolume* pNewVol = retCurrentTouchable->GetVolume();
0483   const G4Material* pNewMaterial = nullptr;
0484   G4VSensitiveDetector* pNewSensitiveDetector = nullptr;
0485 
0486   if (pNewVol != nullptr) {
0487     pNewMaterial = pNewVol->GetLogicalVolume()->GetMaterial();
0488     pNewSensitiveDetector = pNewVol->GetLogicalVolume()->GetSensitiveDetector();
0489   }
0490 
0491   fParticleChange.SetMaterialInTouchable((G4Material*)pNewMaterial);
0492   fParticleChange.SetSensitiveDetectorInTouchable((G4VSensitiveDetector*)pNewSensitiveDetector);
0493 
0494   const G4MaterialCutsCouple* pNewMaterialCutsCouple = nullptr;
0495   if (pNewVol != nullptr) {
0496     pNewMaterialCutsCouple = pNewVol->GetLogicalVolume()->GetMaterialCutsCouple();
0497   }
0498 
0499   if (pNewVol != nullptr && pNewMaterialCutsCouple != nullptr &&
0500       pNewMaterialCutsCouple->GetMaterial() != pNewMaterial) {
0501     // for parametrized volume
0502     //
0503     pNewMaterialCutsCouple = G4ProductionCutsTable::GetProductionCutsTable()->GetMaterialCutsCouple(
0504         pNewMaterial, pNewMaterialCutsCouple->GetProductionCuts());
0505   }
0506   fParticleChange.SetMaterialCutsCoupleInTouchable(pNewMaterialCutsCouple);
0507 
0508   // temporarily until Get/Set Material of ParticleChange,
0509   // and StepPoint can be made const.
0510   // Set the touchable in ParticleChange
0511   // this must always be done because the particle change always
0512   // uses this value to overwrite the current touchable pointer.
0513   //
0514   fParticleChange.SetTouchableHandle(retCurrentTouchable);
0515 
0516   // change to normal equation
0517   fieldMgrCMS->setMonopoleTracking(false);
0518 
0519   return &fParticleChange;
0520 }
0521 
0522 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0523 
0524 // New method takes over the responsibility to reset the state
0525 // of MonopoleTransportation object at the start of a new track
0526 // or the resumption of a suspended track.
0527 
0528 void MonopoleTransportation::StartTracking(G4Track* aTrack) {
0529   // initialise pointer
0530   if (!fieldMgrCMS) {
0531     G4FieldManager* fieldMgr = fFieldPropagator->FindAndSetFieldManager(aTrack->GetVolume());
0532     fieldMgrCMS = static_cast<CMSFieldManager*>(fieldMgr);
0533   }
0534 
0535   G4VProcess::StartTracking(aTrack);
0536 
0537   // The actions here are those that were taken in AlongStepGPIL
0538   //   when track.GetCurrentStepNumber()==1
0539 
0540   // reset safety value and center
0541   //
0542   fPreviousSafety = 0.0;
0543   fPreviousSftOrigin = G4ThreeVector(0., 0., 0.);
0544 
0545   // reset looping counter -- for motion in field
0546   fNoLooperTrials = 0;
0547   // Must clear this state .. else it depends on last track's value
0548 
0549   // ChordFinder reset internal state
0550   //
0551   if (DoesGlobalFieldExist()) {
0552     fFieldPropagator->ClearPropagatorState();
0553     // Resets all state of field propagator class (ONLY)
0554     //  including safety values (in case of overlaps and to wipe for first track).
0555 
0556     G4ChordFinder* chordF = fFieldPropagator->GetChordFinder();
0557     if (chordF)
0558       chordF->ResetStepEstimate();
0559   }
0560 
0561   // Make sure to clear the chord finders of all fields (ie managers)
0562   G4FieldManagerStore* fieldMgrStore = G4FieldManagerStore::GetInstance();
0563   fieldMgrStore->ClearAllChordFindersState();
0564 
0565   // Update the current touchable handle  (from the track's)
0566   //
0567   fCurrentTouchableHandle = aTrack->GetTouchableHandle();
0568 }
0569 
0570 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0571 
0572 G4double MonopoleTransportation::AtRestGetPhysicalInteractionLength(const G4Track&, G4ForceCondition*) { return -1.0; }
0573 
0574 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0575 
0576 G4VParticleChange* MonopoleTransportation::AtRestDoIt(const G4Track&, const G4Step&) { return nullptr; }
0577 
0578 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0579 
0580 void MonopoleTransportation::ResetKilledStatistics(G4int report)
0581 // Statistics for tracks killed (currently due to looping in field)
0582 {
0583   if (report) {
0584     G4cout << " MonopoleTransportation: Statistics for looping particles " << G4endl;
0585     G4cout << "   Sum of energy of loopers killed: " << fSumEnergyKilled << G4endl;
0586     G4cout << "   Max energy of loopers killed: " << fMaxEnergyKilled << G4endl;
0587   }
0588 
0589   fSumEnergyKilled = 0;
0590   fMaxEnergyKilled = -1.0 * CLHEP::GeV;
0591 }
0592 
0593 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......