109 particleChangeLoss(0),
111 energyLossLimit(0.01),
158 LossTableList::iterator iterTables_end =
lossTableList.end();
160 for(;iterTables != iterTables_end; ++iterTables) {
delete *iterTables; }
164 RangeEnergyTable::iterator itr =
r.begin();
165 RangeEnergyTable::iterator itr_end =
r.end();
166 for(;itr != itr_end; ++itr) {
delete itr->second; }
170 EnergyRangeTable::iterator ite =
E.begin();
171 EnergyRangeTable::iterator ite_end =
E.end();
172 for(;ite != ite_end; ++ite) {
delete ite->second; }
222 EffectiveChargeSquareRatio(particle,
279 LossTableList::iterator iterTables_end =
lossTableList.end();
281 for(;iterTables != iterTables_end; ++iterTables) {
282 (*iterTables) -> ClearCache();
287 RangeEnergyTable::iterator iterRange =
r.begin();
288 RangeEnergyTable::iterator iterRange_end =
r.end();
290 for(;iterRange != iterRange_end; ++iterRange) {
291 delete iterRange->second;
295 EnergyRangeTable::iterator iterEnergy =
E.begin();
296 EnergyRangeTable::iterator iterEnergy_end =
E.end();
298 for(;iterEnergy != iterEnergy_end; iterEnergy++) {
299 delete iterEnergy->second;
311#ifdef PRINT_TABLE_BUILT
312 G4cout <<
"G4IonParametrisedLossModel::Initialise():"
313 <<
" Building dE/dx vectors:"
317 for (
size_t i = 0; i < nmbCouples; ++i) {
322 for(
G4int atomicNumberIon = 3; atomicNumberIon < 102; ++atomicNumberIon) {
327 for(;iter != iter_end; ++iter) {
330 G4cout <<
"G4IonParametrisedLossModel::Initialise():"
331 <<
" Skipping illegal table."
335 if((*iter)->BuildDEDXTable(atomicNumberIon,
material)) {
337#ifdef PRINT_TABLE_BUILT
338 G4cout <<
" Atomic Number Ion = " << atomicNumberIon
340 <<
", Table = " << (*iter) ->
GetName()
386 if(cutEnergy < tmax) {
389 G4double betaSquared = kineticEnergy *
392 crosssection = 1.0 / cutEnergy - 1.0 / maxEnergy -
393 betaSquared * std::log(maxEnergy / cutEnergy) / tmax;
399 G4cout <<
"########################################################"
401 <<
"# G4IonParametrisedLossModel::ComputeCrossSectionPerAtom"
403 <<
"# particle =" << particle -> GetParticleName()
405 <<
"# cut(MeV) = " << cutEnergy/
MeV
409 << std::setw(13) << std::right <<
"E(MeV)"
410 << std::setw(14) <<
"CS(um)"
411 << std::setw(14) <<
"E_max_sec(MeV)"
413 <<
"# ------------------------------------------------------"
416 G4cout << std::setw(14) << std::right << kineticEnergy /
MeV
417 << std::setw(14) << crosssection / (
um *
um)
418 << std::setw(14) << tmax /
MeV
422 crosssection *= atomicNumber;
490 if(transitionEnergy > kineticEnergy) {
492 dEdx = (*iter) -> GetDEDX(particle,
material, kineticEnergy);
498 dEdx -= dEdxDeltaRays;
506 G4double scaledKineticEnergy = kineticEnergy * massRatio;
507 G4double scaledTransitionEnergy = transitionEnergy * massRatio;
511 if(scaledTransitionEnergy >= lowEnergyLimit) {
515 scaledKineticEnergy, cutEnergy);
517 dEdx *= chargeSquare;
519 dEdx +=
corrections -> ComputeIonCorrections(particle,
539 G4double scaledKineticEnergy = kineticEnergy * massRatio;
542 if(scaledKineticEnergy < lowEnergyLimit) {
545 scaledKineticEnergy, cutEnergy);
547 dEdx *= chargeSquare;
552 lowEnergyLimit, cutEnergy);
556 lowEnergyLimit, cutEnergy);
559 G4double chargeSquareLowEnergyLimit =
561 lowEnergyLimit / massRatio);
563 dEdxLimitParam *= chargeSquareLowEnergyLimit;
564 dEdxLimitBetheBloch *= chargeSquareLowEnergyLimit;
566 dEdxLimitBetheBloch +=
568 material, lowEnergyLimit / massRatio);
571 G4double factor = (1.0 + (dEdxLimitParam/dEdxLimitBetheBloch - 1.0)
572 * lowEnergyLimit / scaledKineticEnergy);
576 scaledKineticEnergy, cutEnergy);
578 dEdx *= chargeSquare;
581 dEdx +=
corrections -> ComputeIonCorrections(particle,
590 if (dEdx < 0.0) dEdx = 0.0;
605 G4double atomicMassNumber = particle -> GetAtomicMass();
608 G4cout <<
"# dE/dx table for " << particle -> GetParticleName()
610 <<
" of density " << materialDensity /
g *
cm3
613 <<
"# Projectile mass number A1 = " << atomicMassNumber
615 <<
"# ------------------------------------------------------"
618 << std::setw(13) << std::right <<
"E"
619 << std::setw(14) <<
"E/A1"
620 << std::setw(14) <<
"dE/dx"
621 << std::setw(14) <<
"1/rho*dE/dx"
624 << std::setw(13) << std::right <<
"(MeV)"
625 << std::setw(14) <<
"(MeV)"
626 << std::setw(14) <<
"(MeV/cm)"
627 << std::setw(14) <<
"(MeV*cm2/mg)"
629 <<
"# ------------------------------------------------------"
632 G4double energyLowerBoundary = lowerBoundary * atomicMassNumber;
633 G4double energyUpperBoundary = upperBoundary * atomicMassNumber;
637 energyLowerBoundary = std::log(energyLowerBoundary);
638 energyUpperBoundary = std::log(energyUpperBoundary);
641 G4double deltaEnergy = (energyUpperBoundary - energyLowerBoundary) /
644 for(
int i = 0; i < numBins + 1; i++) {
652 << std::setw(14) <<
energy / atomicMassNumber /
MeV
653 << std::setw(14) << dedx /
MeV *
cm
654 << std::setw(14) << dedx / materialDensity / (
MeV*
cm2/(0.001*
g))
672 for(;iter != iter_end; iter++) {
676 lowerBoundary, upperBoundary,
677 numBins,logScaleEnergy);
686 std::vector<G4DynamicParticle*>* secondaries,
718 std::min(rossiMaxKinEnergySec, userMaxKinEnergySec);
720 if(cutKinEnergySec >= maxKinEnergySec)
return;
722 G4double kineticEnergy = particle -> GetKineticEnergy();
735 kinEnergySec = cutKinEnergySec * maxKinEnergySec /
736 (maxKinEnergySec * (1.0 - xi) + cutKinEnergySec * xi);
740 grej = 1.0 - betaSquared * kinEnergySec / rossiMaxKinEnergySec;
743 G4cout <<
"G4IonParametrisedLossModel::SampleSecondary Warning: "
745 << grej <<
" for e= " << kinEnergySec
761 secondaries->push_back(delta);
768 finalP = finalP.
unit();
770 kineticEnergy -= kinEnergySec;
800 IonMatCouple ionMatCouple = std::make_pair(particle, matCutsCouple);
801 RangeEnergyTable::iterator iterRange =
r.find(ionMatCouple);
851 (*iter) -> GetUpperEnergyEdge(particle,
material);
863 dEdxParam -= dEdxDeltaRays;
870 G4double scaledTransitionEnergy = transitionEnergy * massRatio;
875 scaledTransitionEnergy, cutEnergy);
876 dEdxBetheBloch *= transitionChargeSquare;
885 (dEdxParam - dEdxBetheBloch)/dEdxBetheBloch
926 G4double kineticEnergy = dynamicParticle -> GetKineticEnergy();
928 if(kineticEnergy == eloss) {
return; }
931 size_t cutIndex = couple -> GetIndex();
947 kineticEnergy, cutEnergy);
951 G4cout <<
"########################################################"
953 <<
"# G4IonParametrisedLossModel::CorrectionsAlongStep"
955 <<
"# cut(MeV) = " << cutEnergy/
MeV
959 << std::setw(13) << std::right <<
"E(MeV)"
960 << std::setw(14) <<
"l(um)"
961 << std::setw(14) <<
"l*dE/dx(MeV)"
962 << std::setw(14) <<
"(l*dE/dx)/E"
964 <<
"# ------------------------------------------------------"
967 G4cout << std::setw(14) << std::right << kineticEnergy /
MeV
968 << std::setw(14) << length /
um
969 << std::setw(14) << eloss /
MeV
970 << std::setw(14) << eloss / kineticEnergy * 100.0
981 kineticEnergy,length);
984 G4cout <<
"# Correction applied:"
987 G4cout << std::setw(14) << std::right << kineticEnergy /
MeV
988 << std::setw(14) << length /
um
989 << std::setw(14) << eloss /
MeV
990 << std::setw(14) << eloss / kineticEnergy * 100.0
1003 EffectiveChargeSquareRatio(particle,
1016 if(iter !=
lossTableList.end() && transitionEnergy < kineticEnergy) {
1017 chargeSquareRatio *=
corrections -> EffectiveChargeCorrection(particle,
1022 eloss *= chargeSquareRatioCorr;
1026 chargeSquareRatio *=
corrections -> EffectiveChargeCorrection(particle,
1031 eloss *= chargeSquareRatioCorr;
1043 if(scaledKineticEnergy > lowEnergyLimit)
1056 size_t cutIndex = matCutsCouple -> GetIndex();
1066 G4double logLowerEnergyEdge = std::log(lowerEnergy);
1067 G4double logUpperEnergyEdge = std::log(upperEnergy);
1069 G4double logDeltaEnergy = (logUpperEnergyEdge - logLowerEnergyEdge) /
1085 G4double range = 2.0 * lowerEnergy / dedxLow;
1087 energyRangeVector -> PutValues(0, lowerEnergy, range);
1089 G4double logEnergy = std::log(lowerEnergy);
1090 for(
size_t i = 1; i <
nmbBins+1; i++) {
1092 G4double logEnergyIntegr = logEnergy;
1097 logEnergyIntegr += logDeltaIntegr;
1100 G4double deltaIntegr = binUpperBoundary - binLowerBoundary;
1102 G4double energyIntegr = binLowerBoundary + 0.5 * deltaIntegr;
1109 if(dedxValue > 0.0) range += deltaIntegr / dedxValue;
1111#ifdef PRINT_DEBUG_DETAILS
1113 <<
" MeV -> dE = " << deltaIntegr/
MeV
1114 <<
" MeV -> dE/dx = " << dedxValue/
MeV*
mm
1115 <<
" MeV/mm -> dE/(dE/dx) = " << deltaIntegr /
1117 <<
" mm -> range = " << range /
mm
1122 logEnergy += logDeltaEnergy;
1126 energyRangeVector -> PutValues(i,
energy, range);
1128#ifdef PRINT_DEBUG_DETAILS
1129 G4cout <<
"G4IonParametrisedLossModel::BuildRangeVector() bin = "
1132 << range /
mm <<
" mm"
1138 energyRangeVector -> FillSecondDerivatives();
1141 energyRangeVector ->
Value(lowerEnergy);
1143 energyRangeVector ->
Value(upperEnergy);
1151 for(
size_t i = 0; i <
nmbBins+1; i++) {
1153 rangeEnergyVector ->
1157 rangeEnergyVector -> FillSecondDerivatives();
1159#ifdef PRINT_DEBUG_TABLES
1160 G4cout << *energyLossVector
1161 << *energyRangeVector
1162 << *rangeEnergyVector <<
G4endl;
1165 IonMatCouple ionMatCouple = std::make_pair(particle, matCutsCouple);
1167 E[ionMatCouple] = energyRangeVector;
1168 r[ionMatCouple] = rangeEnergyVector;
1186 if(energyRange != 0 && rangeEnergy != 0) {
1188 G4double lowerEnEdge = energyRange -> Energy( 0 );
1189 G4double lowerRangeEdge = rangeEnergy -> Energy( 0 );
1195 if(kineticEnergy < lowerEnEdge) {
1197 range = energyRange ->
Value(lowerEnEdge);
1198 range *= std::sqrt(kineticEnergy / lowerEnEdge);
1202 G4cout <<
"G4IonParametrisedLossModel::ComputeLossForStep() range = "
1203 << range /
mm <<
" mm, step = " << stepLength /
mm <<
" mm"
1208 G4double remRange = range - stepLength;
1212 if(remRange < 0.0) loss = kineticEnergy;
1213 else if(remRange < lowerRangeEdge) {
1215 G4double ratio = remRange / lowerRangeEdge;
1216 loss = kineticEnergy - ratio * ratio * lowerEnEdge;
1221 loss = kineticEnergy -
energy;
1225 if(loss < 0.0) loss = 0.0;
1238 G4cout <<
"G4IonParametrisedLossModel::AddDEDXTable() Cannot "
1239 <<
" add table: Invalid pointer."
1249 for(;iter != iter_end; ++iter) {
1250 const G4String& tableName = (*iter)->GetName();
1252 if(tableName == nam) {
1253 G4cout <<
"G4IonParametrisedLossModel::AddDEDXTable() Cannot "
1254 <<
" add table: Name already exists."
1262 if(scalingAlgorithm == 0)
1281 for(;iter != iter_end; iter++) {
1284 if(tableName == nam) {
1291 RangeEnergyTable::iterator iterRange =
r.begin();
1292 RangeEnergyTable::iterator iterRange_end =
r.end();
1294 for(;iterRange != iterRange_end; iterRange++)
1295 delete iterRange ->
second;
1298 EnergyRangeTable::iterator iterEnergy =
E.begin();
1299 EnergyRangeTable::iterator iterEnergy_end =
E.end();
1301 for(;iterEnergy != iterEnergy_end; iterEnergy++)
1302 delete iterEnergy ->
second;
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
std::pair< const G4ParticleDefinition *, const G4MaterialCutsCouple * > IonMatCouple
static constexpr double cm3
static constexpr double cm2
static constexpr double mm
static constexpr double second
static constexpr double g
static constexpr double um
static constexpr double MeV
static constexpr double cm
G4GLOB_DLL std::ostream G4cout
const G4ThreeVector & GetMomentumDirection() const
G4ThreeVector GetMomentum() const
static G4Electron * Electron()
static G4EmParameters * Instance()
G4bool UseICRU90Data() const
static G4GenericIon * Definition()
G4BetheBlochModel * betheBlochModel
G4double dedxCacheEnergyCut
G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *, G4double, G4double, G4double, G4double, G4double) override
G4double dedxCacheTransitionEnergy
G4double cacheChargeSquare
G4double lowerEnergyEdgeIntegr
void BuildRangeVector(const G4ParticleDefinition *, const G4MaterialCutsCouple *)
const G4ParticleDefinition * cacheParticle
G4double MinEnergyCut(const G4ParticleDefinition *, const G4MaterialCutsCouple *) override
virtual ~G4IonParametrisedLossModel()
G4double MaxSecondaryEnergy(const G4ParticleDefinition *, G4double) override
const G4ParticleDefinition * rangeCacheParticle
G4double dedxCacheTransitionFactor
void UpdateRangeCache(const G4ParticleDefinition *, const G4MaterialCutsCouple *)
const G4MaterialCutsCouple * rangeCacheMatCutsCouple
void UpdateCache(const G4ParticleDefinition *)
G4double genericIonPDGMass
void CorrectionsAlongStep(const G4MaterialCutsCouple *, const G4DynamicParticle *, const G4double &, G4double &) override
LossTableList::iterator IsApplicable(const G4ParticleDefinition *, const G4Material *)
G4double GetChargeSquareRatio(const G4ParticleDefinition *, const G4Material *, G4double) override
G4BraggIonModel * braggIonModel
G4bool AddDEDXTable(const G4String &name, G4VIonDEDXTable *table, G4VIonDEDXScalingAlgorithm *algorithm=nullptr)
const G4ParticleDefinition * genericIon
void Initialise(const G4ParticleDefinition *, const G4DataVector &) override
G4IonParametrisedLossModel(const G4ParticleDefinition *particle=nullptr, const G4String &name="ParamICRU73")
G4double cacheElecMassRatio
const G4Material * dedxCacheMaterial
void PrintDEDXTableHandlers(const G4ParticleDefinition *, const G4Material *, G4double, G4double, G4int, G4bool)
G4double DeltaRayMeanEnergyTransferRate(const G4Material *, const G4ParticleDefinition *, G4double, G4double)
G4EmCorrections * corrections
G4double ComputeDEDXPerVolume(const G4Material *, const G4ParticleDefinition *, G4double, G4double) override
LossTableList lossTableList
const G4ParticleDefinition * dedxCacheParticle
G4double dedxCacheGenIonMassRatio
void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double, G4double) override
LossTableList::iterator dedxCacheIter
G4bool RemoveDEDXTable(const G4String &name)
G4PhysicsVector * rangeCacheRangeEnergy
G4ParticleChangeForLoss * particleChangeLoss
G4double ComputeLossForStep(const G4MaterialCutsCouple *, const G4ParticleDefinition *, G4double, G4double)
G4double CrossSectionPerVolume(const G4Material *, const G4ParticleDefinition *, G4double, G4double, G4double) override
G4double GetParticleCharge(const G4ParticleDefinition *, const G4Material *, G4double) override
G4PhysicsVector * rangeCacheEnergyRange
void UpdateDEDXCache(const G4ParticleDefinition *, const G4Material *, G4double cutEnergy)
G4double upperEnergyEdgeIntegr
void PrintDEDXTable(const G4ParticleDefinition *, const G4Material *, G4double, G4double, G4int, G4bool)
G4double GetMeanExcitationEnergy() const
static G4LossTableManager * Instance()
G4EmCorrections * EmCorrections()
const G4Material * GetMaterial() const
G4IonisParamMat * GetIonisation() const
void SetProposedKineticEnergy(G4double proposedKinEnergy)
void SetProposedMomentumDirection(const G4ThreeVector &dir)
G4double GetPDGMass() const
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
std::size_t GetTableSize() const
static G4ProductionCutsTable * GetProductionCutsTable()
G4VEmFluctuationModel * GetModelOfFluctuations()
G4VEmAngularDistribution * GetAngularDistribution()
G4double LowEnergyLimit() const
void SetParticleChange(G4VParticleChange *, G4VEmFluctuationModel *f=nullptr)
G4int SelectRandomAtomNumber(const G4Material *)
virtual G4double Value(const G4MaterialCutsCouple *, const G4ParticleDefinition *, G4double kineticEnergy)
G4double HighEnergyLimit() const
void SetAngularDistribution(G4VEmAngularDistribution *)
const G4String & GetName() const
G4double MaxSecondaryKinEnergy(const G4DynamicParticle *dynParticle)
G4ParticleChangeForLoss * GetParticleChangeForLoss()
G4double energy(const ThreeVector &p, const G4double m)
T min(const T t1, const T t2)
brief Return the smallest of the two arguments