File indexing completed on 2025-02-23 09:22:46
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 #include "G4EventManager.hh"
0038 #include "G4Field.hh"
0039 #include "G4FieldManager.hh"
0040 #include "G4FieldManagerStore.hh"
0041 #include "G4GeometryTolerance.hh"
0042 #include "G4LogicalVolume.hh"
0043 #include "G4Navigator.hh"
0044 #include "G4PropagatorInField.hh"
0045 #include "G4Region.hh"
0046 #include "G4SafetyHelper.hh"
0047 #include "G4Step.hh"
0048 #include "G4StepPoint.hh"
0049 #include "G4TouchableHandle.hh"
0050 #include "G4TouchableHistory.hh"
0051 #include "G4Track.hh"
0052 #include "G4TrackVector.hh"
0053 #include "G4TransportationManager.hh"
0054 #include "G4UserSteppingAction.hh"
0055 #include "G4UserTrackingAction.hh"
0056 #include "G4VPhysicalVolume.hh"
0057 #include "G4VSensitiveDetector.hh"
0058
0059 template <typename PhysicsImpl, typename NavigationImpl>
0060 void TrackingManagerHelper::TrackParticle(
0061 G4Track* aTrack, PhysicsImpl& physics, NavigationImpl& navigation)
0062 {
0063
0064 auto* evtMgr = G4EventManager::GetEventManager();
0065 auto* userTrackingAction = evtMgr->GetUserTrackingAction();
0066 auto* userSteppingAction = evtMgr->GetUserSteppingAction();
0067
0068
0069 {
0070 auto* transMgr = G4TransportationManager::GetTransportationManager();
0071 auto* linearNavigator = transMgr->GetNavigatorForTracking();
0072
0073 const G4ThreeVector& pos = aTrack->GetPosition();
0074 const G4ThreeVector& dir = aTrack->GetMomentumDirection();
0075
0076
0077 G4TouchableHandle touchableHandle;
0078 if (aTrack->GetTouchableHandle()) {
0079 touchableHandle = aTrack->GetTouchableHandle();
0080
0081 auto* touchableHistory = (G4TouchableHistory*)touchableHandle();
0082 G4VPhysicalVolume* oldTopVolume = touchableHandle->GetVolume();
0083 G4VPhysicalVolume* newTopVolume =
0084 linearNavigator->ResetHierarchyAndLocate(pos, dir, *touchableHistory);
0085
0086 if (newTopVolume != oldTopVolume || oldTopVolume->GetRegularStructureId() == 1) {
0087 touchableHandle = linearNavigator->CreateTouchableHistory();
0088 aTrack->SetTouchableHandle(touchableHandle);
0089 }
0090 }
0091 else {
0092 linearNavigator->LocateGlobalPointAndSetup(pos, &dir, false, false);
0093 touchableHandle = linearNavigator->CreateTouchableHistory();
0094 aTrack->SetTouchableHandle(touchableHandle);
0095 }
0096 aTrack->SetNextTouchableHandle(touchableHandle);
0097 }
0098
0099
0100 G4Step step;
0101 step.NewSecondaryVector();
0102 G4StepPoint& preStepPoint = *step.GetPreStepPoint();
0103 step.InitializeStep(aTrack);
0104 aTrack->SetStep(&step);
0105 G4TrackVector secondaries;
0106
0107
0108 if (userTrackingAction) {
0109 userTrackingAction->PreUserTrackingAction(aTrack);
0110 }
0111
0112 physics.StartTracking(aTrack);
0113
0114 while (aTrack->GetTrackStatus() == fAlive) {
0115
0116 aTrack->IncrementCurrentStepNumber();
0117
0118 step.CopyPostToPreStepPoint();
0119 step.ResetTotalEnergyDeposit();
0120 aTrack->SetTouchableHandle(aTrack->GetNextTouchableHandle());
0121
0122 auto* lvol = aTrack->GetTouchable()->GetVolume()->GetLogicalVolume();
0123 preStepPoint.SetMaterial(lvol->GetMaterial());
0124 preStepPoint.SetMaterialCutsCouple(lvol->GetMaterialCutsCouple());
0125
0126
0127 G4double physicalStep = physics.GetPhysicalInteractionLength(*aTrack);
0128 G4double geometryStep = navigation.MakeStep(*aTrack, step, physicalStep);
0129
0130 bool geometryLimitedStep = geometryStep < physicalStep;
0131 G4double finalStep = geometryLimitedStep ? geometryStep : physicalStep;
0132
0133 step.SetStepLength(finalStep);
0134 aTrack->SetStepLength(finalStep);
0135
0136
0137 physics.AlongStepDoIt(*aTrack, step, secondaries);
0138 step.UpdateTrack();
0139
0140 if (aTrack->GetTrackStatus() == fAlive && aTrack->GetKineticEnergy() < DBL_MIN) {
0141 if (physics.HasAtRestProcesses()) {
0142 aTrack->SetTrackStatus(fStopButAlive);
0143 }
0144 else {
0145 aTrack->SetTrackStatus(fStopAndKill);
0146 }
0147 }
0148
0149 navigation.FinishStep(*aTrack, step);
0150
0151
0152 if (aTrack->GetNextVolume() == nullptr) {
0153 aTrack->SetTrackStatus(fStopAndKill);
0154 }
0155
0156
0157
0158
0159 if (aTrack->GetTrackStatus() != fStopAndKill) {
0160 physics.PostStepDoIt(*aTrack, step, secondaries);
0161 }
0162
0163
0164 aTrack->AddTrackLength(step.GetStepLength());
0165
0166
0167 if (step.GetControlFlag() != AvoidHitInvocation) {
0168 auto* sensitive = lvol->GetSensitiveDetector();
0169 if (sensitive) {
0170 sensitive->Hit(&step);
0171 }
0172 }
0173
0174 if (userSteppingAction) {
0175 userSteppingAction->UserSteppingAction(&step);
0176 }
0177
0178 auto* regionalAction = lvol->GetRegion()->GetRegionalSteppingAction();
0179 if (regionalAction) {
0180 regionalAction->UserSteppingAction(&step);
0181 }
0182 }
0183
0184 if (aTrack->GetTrackStatus() == fStopButAlive && aTrack->GetNextVolume() != nullptr) {
0185
0186 aTrack->IncrementCurrentStepNumber();
0187
0188 step.CopyPostToPreStepPoint();
0189 step.ResetTotalEnergyDeposit();
0190
0191 physics.AtRestDoIt(*aTrack, step, secondaries);
0192
0193
0194 auto* lvol = aTrack->GetTouchable()->GetVolume()->GetLogicalVolume();
0195 if (step.GetControlFlag() != AvoidHitInvocation) {
0196 auto sensitive = lvol->GetSensitiveDetector();
0197 if (sensitive) {
0198 sensitive->Hit(&step);
0199 }
0200 }
0201
0202 if (userSteppingAction) {
0203 userSteppingAction->UserSteppingAction(&step);
0204 }
0205
0206 auto* regionalAction = lvol->GetRegion()->GetRegionalSteppingAction();
0207 if (regionalAction) {
0208 regionalAction->UserSteppingAction(&step);
0209 }
0210 }
0211
0212
0213 physics.EndTracking();
0214
0215 if (userTrackingAction) {
0216 userTrackingAction->PostUserTrackingAction(aTrack);
0217 }
0218
0219 evtMgr->StackTracks(&secondaries);
0220
0221 step.DeleteSecondaryVector();
0222 }
0223
0224 template <typename PhysicsImpl>
0225 void TrackingManagerHelper::TrackChargedParticle(G4Track* aTrack, PhysicsImpl& physics)
0226 {
0227 class ChargedNavigation final : public Navigation
0228 {
0229 public:
0230 ChargedNavigation()
0231 {
0232 auto* transMgr = G4TransportationManager::GetTransportationManager();
0233 fLinearNavigator = transMgr->GetNavigatorForTracking();
0234 fFieldPropagator = transMgr->GetPropagatorInField();
0235 fSafetyHelper = transMgr->GetSafetyHelper();
0236 kCarTolerance = 0.5 * G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
0237
0238
0239 fFieldPropagator->ClearPropagatorState();
0240
0241 auto* fieldMgrStore = G4FieldManagerStore::GetInstance();
0242 fieldMgrStore->ClearAllChordFindersState();
0243 }
0244
0245 G4double MakeStep(G4Track& track, G4Step& step, G4double physicalStep) override
0246 {
0247 G4ThreeVector pos = track.GetPosition();
0248 G4ThreeVector dir = track.GetMomentumDirection();
0249 G4StepPoint& postStepPoint = *step.GetPostStepPoint();
0250
0251 bool fieldExertsForce = false;
0252 if (auto* fieldMgr = fFieldPropagator->FindAndSetFieldManager(track.GetVolume())) {
0253 fieldMgr->ConfigureForTrack(&track);
0254 if (const G4Field* ptrField = fieldMgr->GetDetectorField()) {
0255 fieldExertsForce = true;
0256 }
0257 }
0258
0259 G4double endpointDistance;
0260 G4double safety = 0.0;
0261
0262
0263
0264 const G4double shiftSquare = (pos - fSafetyOrigin).mag2();
0265 if (shiftSquare < sqr(fSafety)) {
0266 safety = fSafety - std::sqrt(shiftSquare);
0267 }
0268
0269 if (fieldExertsForce) {
0270 const G4DynamicParticle* pParticle = track.GetDynamicParticle();
0271 const G4double particleCharge = pParticle->GetCharge();
0272 const G4double particleMass = pParticle->GetMass();
0273 const G4double magneticMoment = pParticle->GetMagneticMoment();
0274 const G4ThreeVector particleSpin = pParticle->GetPolarization();
0275 const G4double kineticEnergy = pParticle->GetKineticEnergy();
0276 const auto pParticleDef = pParticle->GetDefinition();
0277 const auto particlePDGSpin = pParticleDef->GetPDGSpin();
0278 const auto particlePDGMagM = pParticleDef->GetPDGMagneticMoment();
0279
0280 auto equationOfMotion = fFieldPropagator->GetCurrentEquationOfMotion();
0281 equationOfMotion->SetChargeMomentumMass(
0282 G4ChargeState(particleCharge, magneticMoment, particlePDGSpin),
0283 pParticle->GetTotalMomentum(), particleMass);
0284
0285 const G4ThreeVector startPosition = pos;
0286 const G4ThreeVector startDirection = dir;
0287 G4FieldTrack aFieldTrack(startPosition,
0288 track.GetGlobalTime(),
0289 dir, kineticEnergy, particleMass, particleCharge, particleSpin, particlePDGMagM,
0290 0.0,
0291 particlePDGSpin);
0292
0293
0294
0295 fGeometryLimitedStep = false;
0296 const G4double lengthAlongCurve = fFieldPropagator->ComputeStep(
0297 aFieldTrack, physicalStep, safety, track.GetVolume(), kineticEnergy < 250.0);
0298 if (lengthAlongCurve < physicalStep) {
0299 physicalStep = lengthAlongCurve;
0300 fGeometryLimitedStep = true;
0301 }
0302 fSafetyHelper->SetCurrentSafety(safety, pos);
0303 fSafetyOrigin = pos;
0304 fSafety = safety;
0305
0306 if (fFieldPropagator->IsParticleLooping()) {
0307 track.SetTrackStatus(fStopAndKill);
0308 }
0309
0310 pos = aFieldTrack.GetPosition();
0311 dir = aFieldTrack.GetMomentumDir();
0312
0313 postStepPoint.SetPosition(pos);
0314 postStepPoint.SetMomentumDirection(dir);
0315
0316 endpointDistance = (startPosition - pos).mag();
0317 }
0318 else {
0319 fGeometryLimitedStep = false;
0320 G4double linearStepLength = fLinearNavigator->ComputeStep(pos, dir, physicalStep, safety);
0321 if (linearStepLength < physicalStep) {
0322 physicalStep = linearStepLength;
0323 fGeometryLimitedStep = true;
0324 }
0325 fSafetyHelper->SetCurrentSafety(safety, pos);
0326 fSafetyOrigin = pos;
0327 fSafety = safety;
0328
0329
0330 pos += physicalStep * dir;
0331 postStepPoint.SetPosition(pos);
0332
0333 endpointDistance = physicalStep;
0334 }
0335
0336
0337 double velocity = track.GetVelocity();
0338 double deltaTime = 0;
0339 if (velocity > 0) {
0340 deltaTime = physicalStep / velocity;
0341 }
0342
0343 postStepPoint.AddGlobalTime(deltaTime);
0344 postStepPoint.AddLocalTime(deltaTime);
0345
0346 double restMass = track.GetDynamicParticle()->GetMass();
0347 double deltaProperTime = deltaTime * (restMass / track.GetTotalEnergy());
0348 postStepPoint.AddProperTime(deltaProperTime);
0349
0350
0351
0352 if (safety > physicalStep) {
0353 safety -= physicalStep;
0354 }
0355 else if (safety < endpointDistance) {
0356 safety = fLinearNavigator->ComputeSafety(pos);
0357 fSafetyHelper->SetCurrentSafety(safety, pos);
0358 fSafetyOrigin = pos;
0359 fSafety = safety;
0360 }
0361 else {
0362 safety = 0;
0363 }
0364 if (safety < kCarTolerance) {
0365 fPostStepSafety = kCarTolerance;
0366 }
0367 else {
0368 fPostStepSafety = safety;
0369 }
0370
0371 return physicalStep;
0372 }
0373
0374 void FinishStep(G4Track& track, G4Step& step) override
0375 {
0376
0377 G4StepPoint& postStepPoint = *step.GetPostStepPoint();
0378 postStepPoint.SetSafety(fPostStepSafety);
0379
0380 G4TouchableHandle touchableHandle = track.GetTouchableHandle();
0381 const G4ThreeVector& pos = track.GetPosition();
0382 if (fGeometryLimitedStep) {
0383
0384 fLinearNavigator->SetGeometricallyLimitedStep();
0385 fLinearNavigator->LocateGlobalPointAndUpdateTouchableHandle(
0386 pos, track.GetMomentumDirection(), touchableHandle, true);
0387 const G4VPhysicalVolume* newVolume = touchableHandle->GetVolume();
0388 if (newVolume == nullptr) {
0389 postStepPoint.SetStepStatus(fWorldBoundary);
0390 }
0391 else {
0392 postStepPoint.SetStepStatus(fGeomBoundary);
0393 }
0394 }
0395 else {
0396
0397 fLinearNavigator->LocateGlobalPointWithinVolume(pos);
0398 }
0399
0400 postStepPoint.SetTouchableHandle(touchableHandle);
0401 track.SetNextTouchableHandle(touchableHandle);
0402 }
0403
0404 private:
0405 G4Navigator* fLinearNavigator;
0406 G4PropagatorInField* fFieldPropagator;
0407 G4SafetyHelper* fSafetyHelper;
0408 G4ThreeVector fSafetyOrigin;
0409 G4double fSafety = 0;
0410 G4double fPostStepSafety = 0;
0411 G4double kCarTolerance;
0412 G4bool fGeometryLimitedStep;
0413 };
0414
0415 ChargedNavigation navigation;
0416 TrackParticle(aTrack, physics, navigation);
0417 }
0418
0419 template <typename PhysicsImpl>
0420 void TrackingManagerHelper::TrackNeutralParticle(G4Track* aTrack, PhysicsImpl& physics)
0421 {
0422 class NeutralNavigation final : public Navigation
0423 {
0424 public:
0425 NeutralNavigation()
0426 {
0427 auto* transMgr = G4TransportationManager::GetTransportationManager();
0428 fLinearNavigator = transMgr->GetNavigatorForTracking();
0429 fSafetyHelper = transMgr->GetSafetyHelper();
0430 kCarTolerance = 0.5 * G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
0431 }
0432
0433 G4double MakeStep(G4Track& track, G4Step& step, G4double physicalStep) override
0434 {
0435 G4ThreeVector pos = track.GetPosition();
0436 G4ThreeVector dir = track.GetMomentumDirection();
0437 G4StepPoint& postStepPoint = *step.GetPostStepPoint();
0438
0439 G4double safety = 0.0;
0440 const G4double shiftSquare = (pos - fSafetyOrigin).mag2();
0441 if (shiftSquare < sqr(fSafety)) {
0442 safety = fSafety - std::sqrt(shiftSquare);
0443 }
0444
0445 fGeometryLimitedStep = false;
0446 G4double linearStepLength = fLinearNavigator->ComputeStep(pos, dir, physicalStep, safety);
0447 if (linearStepLength < physicalStep) {
0448 physicalStep = linearStepLength;
0449 fGeometryLimitedStep = true;
0450 }
0451 fSafetyHelper->SetCurrentSafety(safety, pos);
0452 fSafetyOrigin = pos;
0453 fSafety = safety;
0454
0455
0456 pos += physicalStep * dir;
0457 postStepPoint.SetPosition(pos);
0458
0459
0460 double velocity = track.GetVelocity();
0461 double deltaTime = 0;
0462 if (velocity > 0) {
0463 deltaTime = physicalStep / velocity;
0464 }
0465 postStepPoint.AddGlobalTime(deltaTime);
0466 postStepPoint.AddLocalTime(deltaTime);
0467
0468 double restMass = track.GetDynamicParticle()->GetMass();
0469 double deltaProperTime = deltaTime * (restMass / track.GetTotalEnergy());
0470 postStepPoint.AddProperTime(deltaProperTime);
0471
0472
0473
0474 if (safety > physicalStep) {
0475 safety -= physicalStep;
0476 }
0477 else {
0478 safety = 0;
0479 }
0480 if (safety < kCarTolerance) {
0481 fPostStepSafety = kCarTolerance;
0482 }
0483 else {
0484 fPostStepSafety = safety;
0485 }
0486
0487 return physicalStep;
0488 }
0489
0490 void FinishStep(G4Track& track, G4Step& step) override
0491 {
0492
0493 G4StepPoint& postStepPoint = *step.GetPostStepPoint();
0494 postStepPoint.SetSafety(fPostStepSafety);
0495
0496 G4TouchableHandle touchableHandle = track.GetTouchableHandle();
0497 const G4ThreeVector& pos = track.GetPosition();
0498 if (fGeometryLimitedStep) {
0499
0500 fLinearNavigator->SetGeometricallyLimitedStep();
0501 fLinearNavigator->LocateGlobalPointAndUpdateTouchableHandle(
0502 pos, track.GetMomentumDirection(), touchableHandle, true);
0503 const G4VPhysicalVolume* newVolume = touchableHandle->GetVolume();
0504 if (newVolume == nullptr) {
0505 postStepPoint.SetStepStatus(fWorldBoundary);
0506 }
0507 else {
0508 postStepPoint.SetStepStatus(fGeomBoundary);
0509 }
0510 }
0511 else {
0512
0513 fLinearNavigator->LocateGlobalPointWithinVolume(pos);
0514 }
0515
0516 postStepPoint.SetTouchableHandle(touchableHandle);
0517 track.SetNextTouchableHandle(touchableHandle);
0518 }
0519
0520 private:
0521 G4Navigator* fLinearNavigator;
0522 G4SafetyHelper* fSafetyHelper;
0523 G4ThreeVector fSafetyOrigin;
0524 G4double fSafety = 0;
0525 G4double fPostStepSafety = 0;
0526 G4double kCarTolerance;
0527 G4bool fGeometryLimitedStep;
0528 };
0529
0530 NeutralNavigation navigation;
0531 TrackParticle(aTrack, physics, navigation);
0532 }