281{
283
284 const G4double physStepLimit = currentMinimumStep;
285
286 switch (fType) {
288
293 if (physStepLimit > kGeomMin) {
295 G4double pdgMass = particleDefinition->GetPDGMass();
296 if (pdgMass > CLHEP::GeV) {
297 ekinForSelection *= proton_mass_c2 / pdgMass;
298 }
299
300 if (ekinForSelection >= kLowestKinEnergy) {
302 fModelManager->
SelectModel(ekinForSelection, couple->GetIndex()));
303 if (mscModel == nullptr) {
305 "no MSC model found");
306 }
307 if (!mscModel->
IsActive(ekinForSelection)) {
308 mscModel = nullptr;
309 }
310 }
311 }
312
313
314
315 if (mscModel != nullptr) {
317
318
319 const G4Track* currentTrackPtr = &track;
320
321 G4double currentSafety = proposedSafety;
323
324 G4double stepLimitLeft = physStepLimit;
325 G4double totalGeometryStepLength = 0, totalTruePathLength = 0;
326 G4bool firstStep =
true, continueStepping = fMultipleSteps;
327
328 do {
329 G4double gPathLength = stepLimitLeft;
332 G4bool mscLimitsStep = (tPathLength < stepLimitLeft);
333 if (!fMultipleSteps && mscLimitsStep) {
334
336 }
337
338 if (!firstStep) {
339
341 }
342
345 *currentTrackPtr, previousStepSize, gPathLength, currentSafety, &transportSelection);
346 if (geometryStepLength < gPathLength) {
347
349 continueStepping = false;
350 }
352
353
354 continueStepping = false;
355 }
356
357 if (firstStep) {
358 proposedSafety = currentSafety;
359 }
360 totalGeometryStepLength += geometryStepLength;
361
362
363 const G4double range = mscModel->
GetRange(particleDefinition, currentEnergy, couple);
364
366
367
368 tPathLength = std::min(tPathLength, stepLimitLeft);
369
370 totalTruePathLength += tPathLength;
372
373
374 continueStepping = false;
375 }
376 else if (tPathLength >= range) {
377
378 continueStepping = false;
379 }
380 else {
381 stepLimitLeft -= tPathLength;
382 }
383
384
385 if (tPathLength < range && tPathLength > kGeomMin) {
386 static constexpr G4double minSafety = 1.20 * CLHEP::nm;
387 static constexpr G4double sFact = 0.99;
388
389
390
391
393
396
398
400 if (r2 > kMinDisplacement2) {
401 G4bool positionChanged =
true;
405
406
407 if (postSafety > 0.0 && dispR <= postSafety) {
409
410
411 }
412 else {
413
414 if (dispR < postSafety) {
416
417
418 }
419 else if (postSafety > kGeomMin) {
421
422
423 }
424 else {
425 positionChanged = false;
426 }
427 }
428 if (positionChanged) {
430 }
431 }
432 }
433
434 if (continueStepping) {
435
437 currentSafety = 0;
438 }
439 else {
441 }
442
443
444 currentEnergy = mscModel->
GetEnergy(particleDefinition, range - tPathLength, couple);
445
446
447 currentTrackPtr = fSubStepTrack;
448
452
456 subPreStepPoint.
SetSafety(currentSafety);
458 }
459 firstStep = false;
460 } while (continueStepping);
461
462
463
464
465
466 if (currentEnergy != ekin) {
467
468
469
471
472
473
474 (void)mscModel->
GetRange(particleDefinition, ekin, couple);
475 }
476
478
479
480
481
482
484
485 return totalGeometryStepLength;
486 }
487 break;
488 }
489
491
495
498 if (pdgMass > CLHEP::GeV) {
499 ekinForSelection *= proton_mass_c2 / pdgMass;
500 }
501
503 if (currentModel == nullptr) {
505 "no scattering model found");
506 }
507 if (!currentModel->
IsActive(ekinForSelection)) {
508 currentModel = nullptr;
509 }
510
511 if (currentModel != nullptr) {
513 G4int coupleIndex = couple->GetIndex();
514
515
517 G4double lambda = ((*fLambdaTable)[coupleIndex])->LogVectorValue(ekin, logEkin);
518 if (lambda > 0.0) {
519
520
523
524 G4double currentSafety = proposedSafety;
526
527
528 const G4Track* currentTrackPtr = &track;
529
530 G4double stepLimitLeft = physStepLimit;
532 G4bool firstStep =
true, continueStepping = fMultipleSteps;
533
534 do {
536
537 G4bool ssLimitsStep = (interactionLength < stepLimitLeft);
538 G4double gPathLength = stepLimitLeft;
539 if (ssLimitsStep) {
540 if (!fMultipleSteps) {
541
543 }
544 gPathLength = interactionLength;
545 }
546
547 if (!firstStep) {
548
550 }
551
554 *currentTrackPtr, previousStepSize, gPathLength, currentSafety, &transportSelection);
555 if (geometryStepLength < gPathLength) {
556
558 ssLimitsStep = false;
559 continueStepping = false;
560 }
562
563
564 continueStepping = false;
565 }
566
567 if (firstStep) {
568 proposedSafety = currentSafety;
569 }
570 totalStepLength += geometryStepLength;
571
573
574
575 continueStepping = false;
576 }
577 else {
578 stepLimitLeft -= geometryStepLength;
579 }
580
581
584
585 if (ssLimitsStep) {
587
588
589
590
592
594 (*fCuts)[coupleIndex]);
595
597
598
599
600
601 if (fSecondariesSS->size() > 0) {
603 "scattering model created secondaries");
604 }
607 "scattering model proposed energy deposit");
608 }
609 }
610
611 if (continueStepping) {
612
614 currentSafety = 0;
615 }
616 else {
618 }
619
620
621 currentEnergy = energyAfterLinearLoss;
622
623
624 currentTrackPtr = fSubStepTrack;
625
629
633 subPreStepPoint.
SetSafety(currentSafety);
635 }
636 firstStep = false;
637 } while (continueStepping);
638
639
640
641
642
643 if (currentEnergy != ekin) {
644
645
646
648 }
649
651
652
653
655
656 return totalStepLength;
657 }
658 }
659 break;
660 }
661 }
662
663
665 track, previousStepSize, currentMinimumStep, proposedSafety, selection);
666}
@ NotCandidateForSelection
G4double G4Log(G4double x)
void SetMomentumDirection(const G4ThreeVector &aDirection)
G4double GetLogKineticEnergy() const
void SetKineticEnergy(G4double aEnergy)
G4VEmModel * SelectModel(G4double energy, std::size_t index)
virtual void LocateGlobalPointWithinVolume(const G4ThreeVector &position)
const G4ThreeVector & GetProposedMomentumDirection() const
const G4ThreeVector * GetProposedMomentumDirection() const
void ProposeMomentumDirection(const G4ThreeVector &Pfinal)
G4double GetPDGMass() const
G4double ComputeSafety(const G4ThreeVector &pGlobalPoint, G4double maxRadius=DBL_MAX)
void ReLocateWithinVolume(const G4ThreeVector &pGlobalPoint)
void SetSafety(const G4double aValue)
void SetStepStatus(const G4StepStatus aValue)
void SetMaterialCutsCouple(const G4MaterialCutsCouple *)
void SetPosition(const G4ThreeVector &aValue)
G4StepPoint * GetPreStepPoint() const
void SetPosition(const G4ThreeVector &aValue)
const G4ParticleDefinition * GetParticleDefinition() const
const G4DynamicParticle * GetDynamicParticle() const
G4double GetKineticEnergy() const
const G4MaterialCutsCouple * GetMaterialCutsCouple() const
G4double AlongStepGetPhysicalInteractionLength(const G4Track &track, G4double previousStepSize, G4double currentMinimumStep, G4double ¤tSafety, G4GPILSelection *selection)
G4double fTransportEndKineticEnergy
G4ThreeVector fTransportEndPosition
G4ParticleChangeForTransport fParticleChange
G4double fEndPointDistance
G4Navigator * fLinearNavigator
G4ThreeVector fTransportEndMomentumDir
G4SafetyHelper * fpSafetyHelper
void SetCurrentCouple(const G4MaterialCutsCouple *)
G4bool IsActive(G4double kinEnergy) const
virtual void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin=0.0, G4double tmax=DBL_MAX)=0
G4double GetDEDX(G4double kineticEnergy, const G4MaterialCutsCouple *)
virtual G4double ComputeTruePathLengthLimit(const G4Track &track, G4double &stepLimit)=0
virtual G4double ComputeTrueStepLength(G4double geomPathLength)=0
G4double GetEnergy(const G4ParticleDefinition *part, G4double range, const G4MaterialCutsCouple *couple)
G4double GetRange(const G4ParticleDefinition *part, G4double kineticEnergy, const G4MaterialCutsCouple *couple)
virtual G4ThreeVector & SampleScattering(const G4ThreeVector &, G4double safety)=0
G4double GetLocalEnergyDeposit() const
void ProposeTrueStepLength(G4double truePathLength)