62static constexpr G4double kLowestKinEnergy = 10 * CLHEP::eV;
63static constexpr G4double kGeomMin = 0.05 * CLHEP::nm;
64static constexpr G4double kMinDisplacement2 = kGeomMin * kGeomMin;
81 fSecondariesSS =
new std::vector<G4DynamicParticle*>;
86 fSubStepTrack =
new G4Track(fSubStepDynamicParticle, 0, zero);
88 fSubStepTrack->
SetStep(fSubStep);
96 delete fParticleChangeForMSC;
98 delete fParticleChangeForSS;
99 delete fSecondariesSS;
102 delete fSubStepTrack;
113 "not allowed unless type == MultipleScattering");
116 fModelManager->
AddEmModel(order, mscModel,
nullptr, region);
126 "not allowed unless type == SingleScattering");
129 fModelManager->
AddEmModel(order, model,
nullptr, region);
138 if (
nullptr == fFirstParticle) {
139 fFirstParticle = ∂
145 if (fFirstParticle == &part) {
160 for (
G4int i = 0; i < numberOfModels; ++i) {
163 msc->SetPolarAngleLimit(theParameters->MscThetaLimit());
164 G4double emax = std::min(msc->HighEnergyLimit(), theParameters->MaxKinEnergy());
165 msc->SetHighEnergyLimit(emax);
166 msc->SetUseBaseMaterials(baseMat);
171 if (fEmData ==
nullptr) {
188 if (fFirstParticle == &part) {
197 std::size_t numOfCouples = theCoupleTable->
GetTableSize();
199 G4double emin = theParameters->MinKinEnergy();
200 G4double emax = theParameters->MaxKinEnergy();
203 G4int nbin = theParameters->NumberOfBinsPerDecade() *
G4lrint(std::log10(scale));
204 scale = nbin /
G4Log(scale);
207 bin = std::max(bin, 5);
209 for (std::size_t i = 0; i < numOfCouples; ++i) {
210 if (!bld->
GetFlag(i))
continue;
217 aVector->FillSecondDerivatives();
228 for (
G4int i = 0; i < numberOfModels; ++i) {
230 auto msc0 =
static_cast<G4VMscModel*
>(masterProcess->fModelManager->GetModel(i));
232 msc->InitialiseLocal(fFirstParticle, msc0);
236 this->fLambdaTable = masterProcess->fLambdaTable;
244 if (fMultipleSteps) {
245 G4cout <<
" (multipleSteps: 1)";
263 for (
G4int i = 0; i < numberOfModels; ++i) {
266 msc->SetIonisation(fIonisation, currParticle);
284 const G4double physStepLimit = currentMinimumStep;
293 if (physStepLimit > kGeomMin) {
295 G4double pdgMass = particleDefinition->GetPDGMass();
296 if (pdgMass > CLHEP::GeV) {
297 ekinForSelection *= proton_mass_c2 / pdgMass;
300 if (ekinForSelection >= kLowestKinEnergy) {
302 fModelManager->
SelectModel(ekinForSelection, couple->GetIndex()));
303 if (mscModel ==
nullptr) {
305 "no MSC model found");
307 if (!mscModel->
IsActive(ekinForSelection)) {
315 if (mscModel !=
nullptr) {
319 const G4Track* currentTrackPtr = &track;
321 G4double currentSafety = proposedSafety;
324 G4double stepLimitLeft = physStepLimit;
325 G4double totalGeometryStepLength = 0, totalTruePathLength = 0;
326 G4bool firstStep =
true, continueStepping = fMultipleSteps;
329 G4double gPathLength = stepLimitLeft;
332 G4bool mscLimitsStep = (tPathLength < stepLimitLeft);
333 if (!fMultipleSteps && mscLimitsStep) {
345 *currentTrackPtr, previousStepSize, gPathLength, currentSafety, &transportSelection);
346 if (geometryStepLength < gPathLength) {
349 continueStepping =
false;
354 continueStepping =
false;
358 proposedSafety = currentSafety;
360 totalGeometryStepLength += geometryStepLength;
363 const G4double range = mscModel->
GetRange(particleDefinition, currentEnergy, couple);
368 tPathLength = std::min(tPathLength, stepLimitLeft);
370 totalTruePathLength += tPathLength;
374 continueStepping =
false;
376 else if (tPathLength >= range) {
378 continueStepping =
false;
381 stepLimitLeft -= tPathLength;
385 if (tPathLength < range && tPathLength > kGeomMin) {
386 static constexpr G4double minSafety = 1.20 * CLHEP::nm;
387 static constexpr G4double sFact = 0.99;
400 if (r2 > kMinDisplacement2) {
401 G4bool positionChanged =
true;
407 if (postSafety > 0.0 && dispR <= postSafety) {
414 if (dispR < postSafety) {
419 else if (postSafety > kGeomMin) {
425 positionChanged =
false;
428 if (positionChanged) {
434 if (continueStepping) {
444 currentEnergy = mscModel->
GetEnergy(particleDefinition, range - tPathLength, couple);
447 currentTrackPtr = fSubStepTrack;
456 subPreStepPoint.
SetSafety(currentSafety);
460 }
while (continueStepping);
466 if (currentEnergy != ekin) {
474 (void)mscModel->
GetRange(particleDefinition, ekin, couple);
485 return totalGeometryStepLength;
498 if (pdgMass > CLHEP::GeV) {
499 ekinForSelection *= proton_mass_c2 / pdgMass;
503 if (currentModel ==
nullptr) {
505 "no scattering model found");
507 if (!currentModel->
IsActive(ekinForSelection)) {
508 currentModel =
nullptr;
511 if (currentModel !=
nullptr) {
513 G4int coupleIndex = couple->GetIndex();
517 G4double lambda = ((*fLambdaTable)[coupleIndex])->LogVectorValue(ekin, logEkin);
521 G4double meanFreePath = 1.0 / lambda;
524 G4double currentSafety = proposedSafety;
528 const G4Track* currentTrackPtr = &track;
530 G4double stepLimitLeft = physStepLimit;
532 G4bool firstStep =
true, continueStepping = fMultipleSteps;
537 G4bool ssLimitsStep = (interactionLength < stepLimitLeft);
538 G4double gPathLength = stepLimitLeft;
540 if (!fMultipleSteps) {
544 gPathLength = interactionLength;
554 *currentTrackPtr, previousStepSize, gPathLength, currentSafety, &transportSelection);
555 if (geometryStepLength < gPathLength) {
558 ssLimitsStep =
false;
559 continueStepping =
false;
564 continueStepping =
false;
568 proposedSafety = currentSafety;
570 totalStepLength += geometryStepLength;
575 continueStepping =
false;
578 stepLimitLeft -= geometryStepLength;
594 (*fCuts)[coupleIndex]);
601 if (fSecondariesSS->size() > 0) {
603 "scattering model created secondaries");
607 "scattering model proposed energy deposit");
611 if (continueStepping) {
621 currentEnergy = energyAfterLinearLoss;
624 currentTrackPtr = fSubStepTrack;
633 subPreStepPoint.
SetSafety(currentSafety);
637 }
while (continueStepping);
643 if (currentEnergy != ekin) {
656 return totalStepLength;
665 track, previousStepSize, currentMinimumStep, proposedSafety, selection);
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
@ NotCandidateForSelection
G4double G4Log(G4double x)
G4GLOB_DLL std::ostream G4cout
void SetMomentumDirection(const G4ThreeVector &aDirection)
void SetDefinition(const G4ParticleDefinition *aParticleDefinition)
G4double GetLogKineticEnergy() const
void SetKineticEnergy(G4double aEnergy)
static G4Electron * Definition()
static G4Electron * Electron()
void PrepareModels(const G4ParticleDefinition *aParticle, G4VEnergyLossProcess *p)
G4PhysicsTable * MakeTable(size_t idx)
void AddEmModel(G4int, G4VEmModel *, G4VEmFluctuationModel *fm, const G4Region *r)
const G4DataVector * Initialise(const G4ParticleDefinition *part, const G4ParticleDefinition *secPart, G4int verb)
G4VEmModel * SelectModel(G4double energy, std::size_t index)
void DumpModelList(std::ostream &out, G4int verb)
G4int NumberOfModels() const
G4VEmModel * GetModel(G4int idx, G4bool ver=false) const
void FillLambdaVector(G4PhysicsVector *, const G4MaterialCutsCouple *, G4bool startFromNull=true, G4EmTableType t=fRestricted)
static G4EmParameters * Instance()
G4bool GetBaseMaterialFlag()
void InitialiseBaseMaterials(const G4PhysicsTable *table=nullptr)
G4bool GetFlag(size_t idx)
static G4LossTableManager * Instance()
G4VEnergyLossProcess * GetEnergyLossProcess(const G4ParticleDefinition *)
G4LossTableBuilder * GetTableBuilder()
void BuildPhysicsTable(const G4ParticleDefinition *aParticle)
G4EmConfigurator * EmConfigurator()
virtual void LocateGlobalPointWithinVolume(const G4ThreeVector &position)
const G4ThreeVector & GetProposedMomentumDirection() const
const G4ThreeVector * GetProposedMomentumDirection() const
void ProposeMomentumDirection(const G4ThreeVector &Pfinal)
G4double GetPDGMass() const
const G4String & GetParticleName() const
static void SetPhysicsVector(G4PhysicsTable *physTable, std::size_t idx, G4PhysicsVector *vec)
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
std::size_t GetTableSize() const
static G4ProductionCutsTable * GetProductionCutsTable()
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)
void SetStep(const G4Step *aValue)
const G4ParticleDefinition * GetParticleDefinition() const
const G4DynamicParticle * GetDynamicParticle() const
G4double GetKineticEnergy() const
const G4MaterialCutsCouple * GetMaterialCutsCouple() const
void AddMscModel(G4VMscModel *mscModel, G4int order=0, const G4Region *region=nullptr)
void BuildPhysicsTable(const G4ParticleDefinition &part) override
~G4TransportationWithMsc() override
void AddSSModel(G4VEmModel *model, G4int order=0, const G4Region *region=nullptr)
void StartTracking(G4Track *track) override
G4TransportationWithMsc(ScatteringType type, G4int verbosity=0)
G4double AlongStepGetPhysicalInteractionLength(const G4Track &track, G4double previousStepSize, G4double currentMinimumStep, G4double &proposedSafety, G4GPILSelection *selection) override
void PreparePhysicsTable(const G4ParticleDefinition &part) override
G4double AlongStepGetPhysicalInteractionLength(const G4Track &track, G4double previousStepSize, G4double currentMinimumStep, G4double ¤tSafety, G4GPILSelection *selection)
G4double fTransportEndKineticEnergy
G4ThreeVector fTransportEndPosition
G4ParticleChangeForTransport fParticleChange
G4double fEndPointDistance
void StartTracking(G4Track *aTrack)
G4Navigator * fLinearNavigator
G4ThreeVector fTransportEndMomentumDir
G4SafetyHelper * fpSafetyHelper
void SetCrossSectionTable(G4PhysicsTable *, G4bool isLocal)
void SetPolarAngleLimit(G4double)
void SetMasterThread(G4bool val)
void SetCurrentCouple(const G4MaterialCutsCouple *)
void SetParticleChange(G4VParticleChange *, G4VEmFluctuationModel *f=nullptr)
G4bool IsActive(G4double kinEnergy) const
virtual void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin=0.0, G4double tmax=DBL_MAX)=0
virtual void StartTracking(G4Track *)
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)
void SetVerboseLevel(G4int value)
const G4VProcess * GetMasterProcess() const
const G4String & GetProcessName() const