113 particleChangeLoss(0),
115 energyLossLimit(0.01),
162 LossTableList::iterator iterTables_end =
lossTableList.end();
164 for(;iterTables != iterTables_end; ++iterTables) {
delete *iterTables; }
168 RangeEnergyTable::iterator itr =
r.begin();
169 RangeEnergyTable::iterator itr_end =
r.end();
170 for(;itr != itr_end; ++itr) {
delete itr->second; }
174 EnergyRangeTable::iterator ite =
E.begin();
175 EnergyRangeTable::iterator ite_end =
E.end();
176 for(;ite != ite_end; ++ite) {
delete ite->second; }
226 EffectiveChargeSquareRatio(particle,
283 LossTableList::iterator iterTables_end =
lossTableList.end();
285 for(;iterTables != iterTables_end; ++iterTables) {
286 (*iterTables) -> ClearCache();
291 RangeEnergyTable::iterator iterRange =
r.begin();
292 RangeEnergyTable::iterator iterRange_end =
r.end();
294 for(;iterRange != iterRange_end; ++iterRange) {
295 delete iterRange->second;
299 EnergyRangeTable::iterator iterEnergy =
E.begin();
300 EnergyRangeTable::iterator iterEnergy_end =
E.end();
302 for(;iterEnergy != iterEnergy_end; iterEnergy++) {
303 delete iterEnergy->second;
315 #ifdef PRINT_TABLE_BUILT
316 G4cout <<
"G4IonParametrisedLossModel::Initialise():"
317 <<
" Building dE/dx vectors:"
321 for (
size_t i = 0; i < nmbCouples; ++i) {
326 for(
G4int atomicNumberIon = 3; atomicNumberIon < 102; ++atomicNumberIon) {
331 for(;iter != iter_end; ++iter) {
334 G4cout <<
"G4IonParametrisedLossModel::Initialise():"
335 <<
" Skipping illegal table."
339 if((*iter)->BuildDEDXTable(atomicNumberIon, material)) {
341 #ifdef PRINT_TABLE_BUILT
342 G4cout <<
" Atomic Number Ion = " << atomicNumberIon
343 <<
", Material = " << material ->
GetName()
344 <<
", Table = " << (*iter) ->
GetName()
390 if(cutEnergy < tmax) {
393 G4double betaSquared = kineticEnergy *
394 (energy +
cacheMass) / (energy * energy);
396 crosssection = 1.0 / cutEnergy - 1.0 / maxEnergy -
397 betaSquared * std::log(maxEnergy / cutEnergy) / tmax;
402 #ifdef PRINT_DEBUG_CS
403 G4cout <<
"########################################################"
405 <<
"# G4IonParametrisedLossModel::ComputeCrossSectionPerAtom"
407 <<
"# particle =" << particle -> GetParticleName()
409 <<
"# cut(MeV) = " << cutEnergy/
MeV
414 << std::setw(14) <<
"CS(um)"
415 << std::setw(14) <<
"E_max_sec(MeV)"
417 <<
"# ------------------------------------------------------"
421 << std::setw(14) << crosssection / (
um *
um)
422 << std::setw(14) << tmax /
MeV
426 crosssection *= atomicNumber;
440 G4double nbElecPerVolume = material -> GetTotNbOfElectPerVolume();
494 if(transitionEnergy > kineticEnergy) {
496 dEdx = (*iter) -> GetDEDX(particle, material, kineticEnergy);
502 dEdx -= dEdxDeltaRays;
510 G4double scaledKineticEnergy = kineticEnergy * massRatio;
511 G4double scaledTransitionEnergy = transitionEnergy * massRatio;
515 if(scaledTransitionEnergy >= lowEnergyLimit) {
519 scaledKineticEnergy, cutEnergy);
521 dEdx *= chargeSquare;
523 dEdx +=
corrections -> ComputeIonCorrections(particle,
524 material, kineticEnergy);
543 G4double scaledKineticEnergy = kineticEnergy * massRatio;
546 if(scaledKineticEnergy < lowEnergyLimit) {
549 scaledKineticEnergy, cutEnergy);
551 dEdx *= chargeSquare;
556 lowEnergyLimit, cutEnergy);
560 lowEnergyLimit, cutEnergy);
563 G4double chargeSquareLowEnergyLimit =
565 lowEnergyLimit / massRatio);
567 dEdxLimitParam *= chargeSquareLowEnergyLimit;
568 dEdxLimitBetheBloch *= chargeSquareLowEnergyLimit;
570 dEdxLimitBetheBloch +=
572 material, lowEnergyLimit / massRatio);
575 G4double factor = (1.0 + (dEdxLimitParam/dEdxLimitBetheBloch - 1.0)
576 * lowEnergyLimit / scaledKineticEnergy);
580 scaledKineticEnergy, cutEnergy);
582 dEdx *= chargeSquare;
585 dEdx +=
corrections -> ComputeIonCorrections(particle,
586 material, kineticEnergy);
594 if (dEdx < 0.0) dEdx = 0.0;
609 G4double atomicMassNumber = particle -> GetAtomicMass();
610 G4double materialDensity = material -> GetDensity();
612 G4cout <<
"# dE/dx table for " << particle -> GetParticleName()
613 <<
" in material " << material ->
GetName()
614 <<
" of density " << materialDensity /
g *
cm3
617 <<
"# Projectile mass number A1 = " << atomicMassNumber
619 <<
"# ------------------------------------------------------"
623 << std::setw(14) <<
"E/A1"
624 << std::setw(14) <<
"dE/dx"
625 << std::setw(14) <<
"1/rho*dE/dx"
629 << std::setw(14) <<
"(MeV)"
630 << std::setw(14) <<
"(MeV/cm)"
631 << std::setw(14) <<
"(MeV*cm2/mg)"
633 <<
"# ------------------------------------------------------"
636 G4double energyLowerBoundary = lowerBoundary * atomicMassNumber;
637 G4double energyUpperBoundary = upperBoundary * atomicMassNumber;
641 energyLowerBoundary = std::log(energyLowerBoundary);
642 energyUpperBoundary = std::log(energyUpperBoundary);
645 G4double deltaEnergy = (energyUpperBoundary - energyLowerBoundary) /
648 for(
int i = 0; i < numBins + 1; i++) {
651 if(logScaleEnergy) energy =
G4Exp(energy);
656 << std::setw(14) << energy / atomicMassNumber /
MeV
657 << std::setw(14) << dedx /
MeV *
cm
658 << std::setw(14) << dedx / materialDensity / (
MeV*
cm2/(0.001*
g))
676 for(;iter != iter_end; iter++) {
680 lowerBoundary, upperBoundary,
681 numBins,logScaleEnergy);
690 std::vector<G4DynamicParticle*>* secondaries,
724 std::min(rossiMaxKinEnergySec, userMaxKinEnergySec);
726 if(cutKinEnergySec >= maxKinEnergySec)
return;
728 G4double kineticEnergy = particle -> GetKineticEnergy();
741 kinEnergySec = cutKinEnergySec * maxKinEnergySec /
742 (maxKinEnergySec * (1.0 - xi) + cutKinEnergySec * xi);
746 grej = 1.0 - betaSquared * kinEnergySec / rossiMaxKinEnergySec;
749 G4cout <<
"G4IonParametrisedLossModel::SampleSecondary Warning: "
751 << grej <<
" for e= " << kinEnergySec
768 secondaries->push_back(delta);
772 G4double totalMomentum = std::sqrt(kineticEnergy*(energy + cacheMass));
775 finalP = finalP.
unit();
777 kineticEnergy -= kinEnergySec;
801 LossTableList::iterator iter =
IsApplicable(particle, material);
807 IonMatCouple ionMatCouple = std::make_pair(particle, matCutsCouple);
808 RangeEnergyTable::iterator iterRange =
r.find(ionMatCouple);
850 LossTableList::iterator iter =
IsApplicable(particle, material);
858 (*iter) -> GetUpperEnergyEdge(particle, material);
863 G4double dEdxParam = (*iter) -> GetDEDX(particle, material,
870 dEdxParam -= dEdxDeltaRays;
877 G4double scaledTransitionEnergy = transitionEnergy * massRatio;
882 scaledTransitionEnergy, cutEnergy);
883 dEdxBetheBloch *= transitionChargeSquare;
888 material, transitionEnergy);
892 (dEdxParam - dEdxBetheBloch)/dEdxBetheBloch
934 G4double kineticEnergy = dynamicParticle -> GetKineticEnergy();
936 if(kineticEnergy == eloss) {
return; }
939 size_t cutIndex = couple -> GetIndex();
955 kineticEnergy, cutEnergy);
959 G4cout <<
"########################################################"
961 <<
"# G4IonParametrisedLossModel::CorrectionsAlongStep"
963 <<
"# cut(MeV) = " << cutEnergy/
MeV
968 << std::setw(14) <<
"l(um)"
969 << std::setw(14) <<
"l*dE/dx(MeV)"
970 << std::setw(14) <<
"(l*dE/dx)/E"
972 <<
"# ------------------------------------------------------"
976 << std::setw(14) << length /
um
977 << std::setw(14) << eloss /
MeV
978 << std::setw(14) << eloss / kineticEnergy * 100.0
989 kineticEnergy,length);
992 G4cout <<
"# Correction applied:"
996 << std::setw(14) << length /
um
997 << std::setw(14) << eloss /
MeV
998 << std::setw(14) << eloss / kineticEnergy * 100.0
1008 if(energy < 0.0) energy = kineticEnergy * 0.5;
1011 EffectiveChargeSquareRatio(particle,
1024 if(iter !=
lossTableList.end() && transitionEnergy < kineticEnergy) {
1025 chargeSquareRatio *=
corrections -> EffectiveChargeCorrection(particle,
1030 eloss *= chargeSquareRatioCorr;
1034 chargeSquareRatio *=
corrections -> EffectiveChargeCorrection(particle,
1039 eloss *= chargeSquareRatioCorr;
1051 if(scaledKineticEnergy > lowEnergyLimit)
1053 corrections -> IonHighOrderCorrections(particle, couple, energy);
1064 size_t cutIndex = matCutsCouple -> GetIndex();
1074 G4double logLowerEnergyEdge = std::log(lowerEnergy);
1075 G4double logUpperEnergyEdge = std::log(upperEnergy);
1077 G4double logDeltaEnergy = (logUpperEnergyEdge - logLowerEnergyEdge) /
1092 G4double range = 2.0 * lowerEnergy / dedxLow;
1094 energyRangeVector -> PutValues(0, lowerEnergy, range);
1096 G4double logEnergy = std::log(lowerEnergy);
1097 for(
size_t i = 1; i <
nmbBins+1; i++) {
1099 G4double logEnergyIntegr = logEnergy;
1104 logEnergyIntegr += logDeltaIntegr;
1107 G4double deltaIntegr = binUpperBoundary - binLowerBoundary;
1109 G4double energyIntegr = binLowerBoundary + 0.5 * deltaIntegr;
1116 if(dedxValue > 0.0) range += deltaIntegr / dedxValue;
1118 #ifdef PRINT_DEBUG_DETAILS
1120 <<
" MeV -> dE = " << deltaIntegr/
MeV
1121 <<
" MeV -> dE/dx = " << dedxValue/
MeV*
mm
1122 <<
" MeV/mm -> dE/(dE/dx) = " << deltaIntegr /
1124 <<
" mm -> range = " << range /
mm
1129 logEnergy += logDeltaEnergy;
1133 energyRangeVector -> PutValues(i, energy, range);
1135 #ifdef PRINT_DEBUG_DETAILS
1136 G4cout <<
"G4IonParametrisedLossModel::BuildRangeVector() bin = "
1138 << energy /
MeV <<
" MeV, R = "
1139 << range /
mm <<
" mm"
1144 energyRangeVector -> SetSpline(
true);
1147 energyRangeVector ->
Value(lowerEnergy);
1149 energyRangeVector ->
Value(upperEnergy);
1156 for(
size_t i = 0; i < nmbBins+1; i++) {
1158 rangeEnergyVector ->
1159 PutValues(i, energyRangeVector ->
Value(energy), energy);
1162 rangeEnergyVector -> SetSpline(
true);
1164 #ifdef PRINT_DEBUG_TABLES
1165 G4cout << *energyLossVector
1166 << *energyRangeVector
1167 << *rangeEnergyVector <<
G4endl;
1170 IonMatCouple ionMatCouple = std::make_pair(particle, matCutsCouple);
1172 E[ionMatCouple] = energyRangeVector;
1173 r[ionMatCouple] = rangeEnergyVector;
1191 if(energyRange != 0 && rangeEnergy != 0) {
1193 G4double lowerEnEdge = energyRange -> Energy( 0 );
1194 G4double lowerRangeEdge = rangeEnergy -> Energy( 0 );
1200 if(kineticEnergy < lowerEnEdge) {
1202 range = energyRange ->
Value(lowerEnEdge);
1203 range *= std::sqrt(kineticEnergy / lowerEnEdge);
1207 G4cout <<
"G4IonParametrisedLossModel::ComputeLossForStep() range = "
1208 << range /
mm <<
" mm, step = " << stepLength /
mm <<
" mm"
1213 G4double remRange = range - stepLength;
1217 if(remRange < 0.0) loss = kineticEnergy;
1218 else if(remRange < lowerRangeEdge) {
1221 loss = kineticEnergy - ratio * ratio * lowerEnEdge;
1226 loss = kineticEnergy -
energy;
1230 if(loss < 0.0) loss = 0.0;
1243 G4cout <<
"G4IonParametrisedLossModel::AddDEDXTable() Cannot "
1244 <<
" add table: Invalid pointer."
1254 for(;iter != iter_end; ++iter) {
1255 const G4String& tableName = (*iter)->GetName();
1257 if(tableName == nam) {
1258 G4cout <<
"G4IonParametrisedLossModel::AddDEDXTable() Cannot "
1259 <<
" add table: Name already exists."
1267 if(scalingAlgorithm == 0)
1286 for(;iter != iter_end; iter++) {
1289 if(tableName == nam) {
1296 RangeEnergyTable::iterator iterRange =
r.begin();
1297 RangeEnergyTable::iterator iterRange_end =
r.end();
1299 for(;iterRange != iterRange_end; iterRange++)
1300 delete iterRange ->
second;
1303 EnergyRangeTable::iterator iterEnergy =
E.begin();
1304 EnergyRangeTable::iterator iterEnergy_end =
E.end();
1306 for(;iterEnergy != iterEnergy_end; iterEnergy++)
1307 delete iterEnergy ->
second;