82 cutenergy[0] = cutenergy[1] = cutenergy[2] =
DBL_MAX;
95 for (
G4int i=0; i<nLocalMaterials; ++i) {
96 delete localCouples[i];
109 if(
nullptr != couple && UpdateParticle(p, kinEnergy) ) {
110 res = manager->
GetDEDX(p, kinEnergy, couple);
113 if(FindEmModel(p, currentProcessName, kinEnergy)) {
128 G4cout <<
"G4EmCalculator::GetDEDX: E(MeV)= " << kinEnergy/MeV
129 <<
" DEDX(MeV/mm)= " << res*mm/MeV
130 <<
" DEDX(MeV*cm^2/g)= " << res*gram/(MeV*cm2*mat->
GetDensity())
133 <<
" isIon= " << isIon
149 if(couple && UpdateParticle(p, kinEnergy)) {
152 G4cout <<
" G4EmCalculator::GetRangeFromRestrictedDEDX: E(MeV)= "
154 <<
" range(mm)= " << res/mm
173 ed <<
"G4EmCalculator::GetCSDARange: CSDA table is not built; "
174 <<
" use UI command: /process/eLoss/CSDARange true";
175 G4Exception(
"G4EmCalculator::GetCSDARange",
"em0077",
181 if(
nullptr != couple && UpdateParticle(p, kinEnergy)) {
184 G4cout <<
" G4EmCalculator::GetCSDARange: E(MeV)= " << kinEnergy/MeV
185 <<
" range(mm)= " << res/mm
219 if(
nullptr != couple && UpdateParticle(p, 1.0*GeV)) {
220 res = manager->
GetEnergy(p, range, couple);
222 G4cout <<
"G4EmCalculator::GetKinEnergy: Range(mm)= " << range/mm
223 <<
" KinE(MeV)= " << res/MeV
243 if(
nullptr != couple && UpdateParticle(p, kinEnergy)) {
244 if(FindEmModel(p, processName, kinEnergy)) {
247 FindLambdaTable(p, processName, kinEnergy, procType);
249 G4VEmProcess* emproc = FindDiscreteProcess(p, processName);
250 if(
nullptr != emproc) {
252 }
else if(currentLambda) {
256 auto mscM =
static_cast<G4VMscModel*
>(currentModel);
258 G4double tr1Mfp = mscM->GetTransportMeanFreePath(p, kinEnergy);
264 res = (((*currentLambda)[idx])->Value(e))*chargeSquare;
270 G4cout <<
"G4EmCalculator::GetXSPerVolume: E(MeV)= " << kinEnergy/MeV
271 <<
" cross(cm-1)= " << res*cm
275 G4cout <<
" idx= " << idx <<
" Escaled((MeV)= "
276 << kinEnergy*massRatio
277 <<
" q2= " << chargeSquare;
296 if(
nullptr != p &&
nullptr != ad) {
312 if(x > 0.0) { res = 1.0/x; }
314 G4cout <<
"G4EmCalculator::GetMeanFreePath: E(MeV)= " << kinEnergy/MeV
315 <<
" MFP(mm)= " << res/mm
346 G4cout <<
"### G4EmCalculator: Inverse Range Table for "
363 <<
" in " << currentMaterialName
364 <<
" e(MeV)= " << kinEnergy/MeV <<
" cut(MeV)= " << cut/MeV
367 if(UpdateParticle(p, kinEnergy)) {
368 if(FindEmModel(p, processName, kinEnergy)) {
369 G4double escaled = kinEnergy*massRatio;
370 if(
nullptr != baseParticle) {
372 escaled, cut) * chargeSquare;
375 <<
" E(MeV)=" << kinEnergy
377 <<
" Escaled(MeV)= " << escaled
378 <<
" q2=" << chargeSquare <<
G4endl;
384 <<
" E(MeV)=" << kinEnergy <<
G4endl;
388 G4cout << currentModel->
GetName() <<
": DEDX(MeV/mm)= " << res*mm/MeV
389 <<
" DEDX(MeV*cm^2/g)= "
394 if(applySmoothing &&
nullptr != loweModel) {
398 if(
nullptr != baseParticle) {
407 if(res1 > 0.0 && escaled > 0.0) {
408 res *= (1.0 + (res0/res1 - 1.0)*eth/escaled);
411 G4cout <<
"At boundary energy(MeV)= " << eth/MeV
412 <<
" DEDX(MeV/mm)= " << res0*mm/MeV <<
" " << res1*mm/MeV
413 <<
" after correction DEDX(MeV/mm)=" << res*mm/MeV <<
G4endl;
419 if(UpdateCouple(mat, cut)) {
427 G4cout <<
"After Corrections: DEDX(MeV/mm)= " << res*mm/MeV
428 <<
" DEDX(MeV*cm^2/g)= "
434 G4cout <<
"## E(MeV)= " << kinEnergy/MeV
435 <<
" DEDX(MeV/mm)= " << res*mm/MeV
436 <<
" DEDX(MeV*cm^2/g)= " << res*gram/(MeV*cm2*mat->
GetDensity())
437 <<
" cut(MeV)= " << cut/MeV
439 <<
" in " << currentMaterialName
440 <<
" Zi^2= " << chargeSquare
441 <<
" isIon=" << isIon
458 if(UpdateParticle(part, kinEnergy)) {
461 const std::vector<G4VEnergyLossProcess*> vel =
463 std::size_t n = vel.size();
468 for(std::size_t i=0; i<n; ++i) {
471 if(ActiveForParticle(part, p)) {
474 dedx +=
ComputeDEDX(kinEnergy,part,(vel[i])->GetProcessName(),mat,cut);
492 if(UpdateParticle(part, kinEnergy)) {
495 const std::vector<G4VEnergyLossProcess*> vel =
497 std::size_t n = vel.size();
499 if(mat != cutMaterial) {
512 for(std::size_t i=0; i<n; ++i) {
515 if(ActiveForParticle(part, p)) {
523 dedx +=
ComputeDEDX(kinEnergy,part,(vel[i])->GetProcessName(),
551 G4VEmProcess* nucst = FindDiscreteProcess(p,
"nuclearStopping");
562 <<
" NuclearDEDX(MeV/mm)= " << res*mm/MeV
563 <<
" NuclearDEDX(MeV*cm^2/g)= "
581 if(UpdateParticle(p, kinEnergy)) {
582 if(FindEmModel(p, processName, kinEnergy)) {
586 e *= kinEnergy*massRatio;
588 mat, baseParticle, e, aCut, e) * chargeSquare;
593 G4cout <<
"G4EmCalculator::ComputeXSPerVolume: E(MeV)= "
595 <<
" cross(cm-1)= " << res*cm
596 <<
" cut(keV)= " << aCut/keV
616 if(UpdateParticle(p, kinEnergy)) {
619 if(FindEmModel(p, processName, kinEnergy)) {
623 e *= kinEnergy*massRatio;
626 baseParticle, e, Z,
A, aCut) * chargeSquare;
632 G4cout <<
"E(MeV)= " << kinEnergy/MeV
633 <<
" cross(barn)= " << res/barn
635 <<
" Z= " << Z <<
" A= " <<
A/(g/mole) <<
" g/mole"
636 <<
" cut(keV)= " << aCut/keV
654 if(UpdateParticle(p, kinEnergy)) {
656 if(FindEmModel(p, processName, kinEnergy)) {
659 if(
nullptr != baseParticle) {
660 e *= kinEnergy*massRatio;
664 e, aCut) * chargeSquare;
670 G4cout <<
"E(MeV)= " << kinEnergy/MeV
671 <<
" cross(barn)= " << res/barn
673 <<
" Z= " << Z <<
" shellIdx= " << shellIdx
674 <<
" cut(keV)= " << aCut/keV
694 if(res > 0.0) { res = 1.0/res; }
728 if(x > 0.0) { mfp = 1.0/x; }
730 G4cout <<
"E(MeV)= " << kinEnergy/MeV
731 <<
" MFP(mm)= " << mfp/mm
747 ConvertRangeToEnergy(part, mat, range);
755 if(p != currentParticle) {
761 baseParticle =
nullptr;
767 currentProcessName =
"";
771 if(
nullptr != currentProcess) {
774 if(currentProcessName ==
"ionIoni" && p->
GetParticleName() !=
"alpha") {
775 baseParticle = theGenericIon;
780 if(
nullptr != baseParticle) {
788 if(isIon &&
nullptr != currentProcess) {
793 G4cout <<
"\n NewIon: massR= "<< massRatio <<
" q2= "
794 << chargeSquare <<
" " << currentProcess <<
G4endl;
805 if(name != currentParticleName) {
808 G4cout <<
"### WARNING: G4EmCalculator::FindParticle fails to find "
829 if(name != currentMaterialName) {
831 if(
nullptr == currentMaterial) {
832 G4cout <<
"### WARNING: G4EmCalculator::FindMaterial fails to find "
836 return currentMaterial;
854 if(
nullptr != currentMaterial) {
864 std::size_t nr = store->size();
866 for(std::size_t i=0; i<nr; ++i) {
868 material, ((*store)[i])->GetProductionCuts());
869 if(
nullptr != couple) {
break; }
874 if(
nullptr == couple) {
876 ed <<
"G4EmCalculator::FindCouple: fail for material <"
877 << currentMaterialName <<
">";
878 if(region) { ed <<
" and region " << region->
GetName(); }
879 G4Exception(
"G4EmCalculator::FindCouple",
"em0078",
890 if(!currentMaterial) {
return false; }
891 for (
G4int i=0; i<nLocalMaterials; ++i) {
892 if(material == localMaterials[i] && cut == localCuts[i]) {
893 currentCouple = localCouples[i];
894 currentCoupleIndex = currentCouple->
GetIndex();
900 localMaterials.push_back(material);
901 localCouples.push_back(cc);
902 localCuts.push_back(cut);
905 currentCoupleIndex = currentCouple->
GetIndex();
917 if (!currentLambda || p != lambdaParticle || processName != lambdaName) {
918 lambdaName = processName;
919 currentLambda =
nullptr;
921 isApplicable =
false;
926 currentName = processName;
927 currentModel =
nullptr;
931 if(
nullptr != elproc) {
934 if(
nullptr != currentLambda) {
937 G4cout <<
"G4VEnergyLossProcess is found out: " << currentName
946 G4VEmProcess* proc = FindDiscreteProcess(part, processName);
947 if(
nullptr != proc) {
950 if(
nullptr != currentLambda) {
953 G4cout <<
"G4VEmProcess is found out: " << currentName <<
G4endl;
965 if(
nullptr != currentModel) {
967 if(
nullptr != currentLambda) {
970 G4cout <<
"G4VMultipleScattering is found out: " << currentName
986 isApplicable =
false;
987 if(
nullptr == p ||
nullptr == currentMaterial) {
988 G4cout <<
"G4EmCalculator::FindEmModel WARNING: no particle"
989 <<
" or materail defined; particle: " << p <<
G4endl;
993 G4double scaledEnergy = kinEnergy*massRatio;
997 G4cout <<
"## G4EmCalculator::FindEmModel for " << partname
999 <<
") and " << processName <<
" at E(MeV)= " << scaledEnergy
1001 if(p != part) {
G4cout <<
" GenericIon is the base particle" <<
G4endl; }
1005 currentName = processName;
1006 currentModel =
nullptr;
1007 loweModel =
nullptr;
1008 std::size_t idx = 0;
1011 if(
nullptr != elproc) {
1018 if(loweModel == currentModel) { loweModel =
nullptr; }
1027 if(
nullptr == currentModel) {
1028 G4VEmProcess* proc = FindDiscreteProcess(part, processName);
1029 if(
nullptr != proc) {
1036 if(loweModel == currentModel) { loweModel =
nullptr; }
1046 if(
nullptr == currentModel) {
1048 if(
nullptr != proc) {
1050 loweModel =
nullptr;
1053 if(
nullptr != currentModel) {
1054 if(loweModel == currentModel) { loweModel =
nullptr; }
1055 isApplicable =
true;
1064 if(
nullptr != elproc) {
1068 if(
nullptr != loweModel) {
1069 G4cout <<
" LowEnergy model <" << loweModel->
GetName() <<
">";
1074 return isApplicable;
1084 const std::vector<G4VEnergyLossProcess*> v =
1086 std::size_t
n = v.size();
1087 for(std::size_t i=0; i<
n; ++i) {
1088 if((v[i])->GetProcessName() == processName) {
1090 if(ActiveForParticle(part, p)) {
1107 std::size_t
n = v.size();
1108 for(std::size_t i=0; i<
n; ++i) {
1109 auto pName = v[i]->GetProcessName();
1110 if(pName ==
"GammaGeneralProc") {
1111 proc = v[i]->GetEmProcess(processName);
1113 }
else if(pName == processName) {
1115 if(ActiveForParticle(part, p)) {
1131 const std::vector<G4VMultipleScattering*> v =
1133 std::size_t
n = v.size();
1134 for(std::size_t i=0; i<
n; ++i) {
1135 if((v[i])->GetProcessName() == processName) {
1137 if(ActiveForParticle(part, p)) {
1155 for(
G4int i=0; i<nproc; ++i) {
1156 if(processName == (*pv)[i]->GetProcessName()) {
1173 for(
G4int i=0; i<n; ++i) {
1174 if((*pv)[i] == proc) {
1187 currentMaterial = mat;
1188 currentMaterialName = mat->
GetName();
1190 currentMaterial =
nullptr;
1191 currentMaterialName =
"";
1204void G4EmCalculator::CheckMaterial(
G4int Z)
1207 if(
nullptr != currentMaterial) {
1209 for(
G4int i=0; i<nn; ++i) {
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
G4GLOB_DLL std::ostream G4cout
void SetDefinition(const G4ParticleDefinition *aParticleDefinition)
void SetKineticEnergy(G4double aEnergy)
static G4Electron * Electron()
const G4ParticleDefinition * FindParticle(const G4String &)
G4double ComputeMeanFreePath(G4double kinEnergy, const G4ParticleDefinition *, const G4String &processName, const G4Material *, G4double cut=0.0)
G4double GetShellIonisationCrossSectionPerAtom(const G4String &part, G4int Z, G4AtomicShellEnumerator shell, G4double kinEnergy)
G4double GetDEDX(G4double kinEnergy, const G4ParticleDefinition *, const G4Material *, const G4Region *r=nullptr)
G4double ComputeTotalDEDX(G4double kinEnergy, const G4ParticleDefinition *, const G4Material *, G4double cut=DBL_MAX)
G4double GetCSDARange(G4double kinEnergy, const G4ParticleDefinition *, const G4Material *, const G4Region *r=nullptr)
G4double GetRange(G4double kinEnergy, const G4ParticleDefinition *, const G4Material *, const G4Region *r=nullptr)
G4double ComputeNuclearDEDX(G4double kinEnergy, const G4ParticleDefinition *, const G4Material *)
const G4ParticleDefinition * FindIon(G4int Z, G4int A)
G4double ComputeGammaAttenuationLength(G4double kinEnergy, const G4Material *)
G4double ComputeDEDX(G4double kinEnergy, const G4ParticleDefinition *, const G4String &processName, const G4Material *, G4double cut=DBL_MAX)
void SetVerbose(G4int val)
G4double ComputeEnergyCutFromRangeCut(G4double range, const G4ParticleDefinition *, const G4Material *)
G4double GetKinEnergy(G4double range, const G4ParticleDefinition *, const G4Material *, const G4Region *r=nullptr)
G4double GetRangeFromRestricteDEDX(G4double kinEnergy, const G4ParticleDefinition *, const G4Material *, const G4Region *r=nullptr)
G4double ComputeCrossSectionPerVolume(G4double kinEnergy, const G4ParticleDefinition *, const G4String &processName, const G4Material *, G4double cut=0.0)
G4double ComputeCrossSectionPerAtom(G4double kinEnergy, const G4ParticleDefinition *, const G4String &processName, G4double Z, G4double A, G4double cut=0.0)
void PrintDEDXTable(const G4ParticleDefinition *)
const G4Region * FindRegion(const G4String &)
G4VProcess * FindProcess(const G4ParticleDefinition *part, const G4String &processName)
G4double GetCrossSectionPerVolume(G4double kinEnergy, const G4ParticleDefinition *, const G4String &processName, const G4Material *, const G4Region *r=nullptr)
G4double ComputeCrossSectionPerShell(G4double kinEnergy, const G4ParticleDefinition *, const G4String &processName, G4int Z, G4int shellIdx, G4double cut=0.0)
G4double ComputeShellIonisationCrossSectionPerAtom(const G4String &part, G4int Z, G4AtomicShellEnumerator shell, G4double kinEnergy, const G4Material *mat=nullptr)
const G4MaterialCutsCouple * FindCouple(const G4Material *, const G4Region *r=nullptr)
void SetupMaterial(const G4Material *)
void PrintRangeTable(const G4ParticleDefinition *)
void PrintInverseRangeTable(const G4ParticleDefinition *)
G4double ComputeDEDXForCutInRange(G4double kinEnergy, const G4ParticleDefinition *, const G4Material *mat, G4double rangecut=DBL_MAX)
G4double GetMeanFreePath(G4double kinEnergy, const G4ParticleDefinition *, const G4String &processName, const G4Material *, const G4Region *r=nullptr)
G4double ComputeElectronicDEDX(G4double kinEnergy, const G4ParticleDefinition *, const G4Material *mat, G4double cut=DBL_MAX)
const G4Material * FindMaterial(const G4String &)
G4double EffectiveChargeSquareRatio(const G4ParticleDefinition *, const G4Material *, const G4double kineticEnergy)
static G4EmParameters * Instance()
G4bool BuildCSDARange() const
G4double LowestElectronEnergy() const
static const G4Region * FindRegion(const G4String ®ionName, const G4int verbose=0)
static G4GenericIon * GenericIon()
G4ParticleDefinition * GetIon(G4int Z, G4int A, G4int lvl=0)
static G4LossTableManager * Instance()
const std::vector< G4VEmProcess * > & GetEmProcessVector()
G4double GetCSDARange(const G4ParticleDefinition *aParticle, G4double kineticEnergy, const G4MaterialCutsCouple *couple)
G4VEnergyLossProcess * GetEnergyLossProcess(const G4ParticleDefinition *)
G4double GetEnergy(const G4ParticleDefinition *aParticle, G4double range, const G4MaterialCutsCouple *couple)
const std::vector< G4VMultipleScattering * > & GetMultipleScatteringVector()
const std::vector< G4VEnergyLossProcess * > & GetEnergyLossProcessVector()
G4VAtomDeexcitation * AtomDeexcitation()
G4double GetRangeFromRestricteDEDX(const G4ParticleDefinition *aParticle, G4double kineticEnergy, const G4MaterialCutsCouple *couple)
G4EmCorrections * EmCorrections()
G4double GetDEDX(const G4ParticleDefinition *aParticle, G4double kineticEnergy, const G4MaterialCutsCouple *couple)
G4double GetDensity() const
const G4Element * GetElement(G4int iel) const
std::size_t GetNumberOfElements() const
const G4String & GetName() const
static G4Material * GetMaterial(const G4String &name, G4bool warning=true)
G4Material * FindOrBuildSimpleMaterial(G4int Z, G4bool warning=false)
G4Material * FindOrBuildMaterial(const G4String &name, G4bool isotopes=true, G4bool warning=false)
static G4NistManager * Instance()
G4ProcessManager * GetProcessManager() const
const G4String & GetParticleType() const
G4double GetPDGMass() const
G4double GetPDGCharge() const
const G4String & GetParticleName() const
G4IonTable * GetIonTable() const
G4ParticleDefinition * FindParticle(G4int PDGEncoding)
static G4ParticleTable * GetParticleTable()
static G4Positron * Positron()
G4bool GetProcessActivation(G4VProcess *aProcess) const
G4ProcessVector * GetProcessList() const
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
static G4ProductionCutsTable * GetProductionCutsTable()
static G4RegionStore * GetInstance()
G4ProductionCuts * GetProductionCuts() const
const G4String & GetName() const
virtual G4double ComputeShellIonisationCrossSectionPerAtom(const G4ParticleDefinition *, G4int Z, G4AtomicShellEnumerator shell, G4double kinE, const G4Material *mat=nullptr)=0
virtual G4double GetShellIonisationCrossSectionPerAtom(const G4ParticleDefinition *, G4int Z, G4AtomicShellEnumerator shell, G4double kinE, const G4Material *mat=nullptr)=0
virtual G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *, G4double kinEnergy, G4double Z, G4double A=0., G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
virtual void InitialiseForMaterial(const G4ParticleDefinition *, const G4Material *)
G4double LowEnergyLimit() const
virtual G4double CrossSectionPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
void SetCurrentCouple(const G4MaterialCutsCouple *)
void SetFluctuationFlag(G4bool val)
virtual void InitialiseForElement(const G4ParticleDefinition *, G4int Z)
virtual void SetupForMaterial(const G4ParticleDefinition *, const G4Material *, G4double kineticEnergy)
virtual G4double ComputeCrossSectionPerShell(const G4ParticleDefinition *, G4int Z, G4int shellIdx, G4double kinEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
virtual void CorrectionsAlongStep(const G4MaterialCutsCouple *, const G4DynamicParticle *, const G4double &length, G4double &eloss)
virtual G4double GetChargeSquareRatio(const G4ParticleDefinition *, const G4Material *, G4double kineticEnergy)
const G4String & GetName() const
virtual G4double ComputeDEDXPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=DBL_MAX)
G4PhysicsTable * GetCrossSectionTable()
G4VEmModel * EmModel(size_t index=0) const
G4PhysicsTable * LambdaTable() const
G4double GetCrossSection(const G4double kinEnergy, const G4MaterialCutsCouple *couple) override
G4VEmModel * SelectModelForMaterial(G4double kinEnergy, size_t idxCouple) const
const G4ParticleDefinition * BaseParticle() const
G4PhysicsTable * RangeTableForLoss() const
G4PhysicsTable * InverseRangeTable() const
void SetDynamicMassCharge(G4double massratio, G4double charge2ratio)
G4VEmModel * SelectModelForMaterial(G4double kinEnergy, std::size_t &idxCouple) const
G4PhysicsTable * LambdaTable() const
G4PhysicsTable * DEDXTable() const
G4VEmModel * SelectModel(G4double kinEnergy, size_t idx)
const G4String & GetProcessName() const