109 particleChangeLoss(0),
110 chargeSquareRatio(1.0),
111 energyLossLimit(0.01),
116 genericIonPDGMass = genericIon->GetPDGMass();
124 lowerEnergyEdgeIntegr = 0.025 * MeV;
130 cacheElecMassRatio = 0;
131 cacheChargeSquare = 0;
134 rangeCacheParticle = 0;
135 rangeCacheMatCutsCouple = 0;
136 rangeCacheEnergyRange = 0;
137 rangeCacheRangeEnergy = 0;
140 dedxCacheParticle = 0;
141 dedxCacheMaterial = 0;
142 dedxCacheEnergyCut = 0;
143 dedxCacheIter = lossTableList.end();
144 dedxCacheTransitionEnergy = 0.0;
145 dedxCacheTransitionFactor = 0.0;
146 dedxCacheGenIonMassRatio = 0.0;
157 LossTableList::iterator iterTables = lossTableList.begin();
158 LossTableList::iterator iterTables_end = lossTableList.end();
160 for(;iterTables != iterTables_end; ++iterTables) {
delete *iterTables; }
161 lossTableList.clear();
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; }
204 if(particle != cacheParticle) UpdateCache(particle);
206 G4double tau = kineticEnergy/cacheMass;
207 G4double tmax = 2.0 * electron_mass_c2 * tau * (tau + 2.) /
208 (1. + 2.0 * (tau + 1.) * cacheElecMassRatio +
209 cacheElecMassRatio * cacheElecMassRatio);
222 corrections->EffectiveChargeSquareRatio(particle, material, kinEnergy);
223 return chargeSquareRatio;
245 cacheElecMassRatio = 0;
246 cacheChargeSquare = 0;
249 rangeCacheParticle = 0;
250 rangeCacheMatCutsCouple = 0;
251 rangeCacheEnergyRange = 0;
252 rangeCacheRangeEnergy = 0;
255 dedxCacheParticle = 0;
256 dedxCacheMaterial = 0;
257 dedxCacheEnergyCut = 0;
258 dedxCacheIter = lossTableList.end();
259 dedxCacheTransitionEnergy = 0.0;
260 dedxCacheTransitionFactor = 0.0;
261 dedxCacheGenIonMassRatio = 0.0;
266 isInitialised =
true;
272 LossTableList::iterator iterTables = lossTableList.begin();
273 LossTableList::iterator iterTables_end = lossTableList.end();
275 for(;iterTables != iterTables_end; ++iterTables) {
276 (*iterTables) -> ClearCache();
281 RangeEnergyTable::iterator iterRange = r.begin();
282 RangeEnergyTable::iterator iterRange_end = r.end();
284 for(;iterRange != iterRange_end; ++iterRange) {
285 delete iterRange->second;
289 EnergyRangeTable::iterator iterEnergy = E.begin();
290 EnergyRangeTable::iterator iterEnergy_end = E.end();
292 for(;iterEnergy != iterEnergy_end; ++iterEnergy) {
293 delete iterEnergy->second;
305#ifdef PRINT_TABLE_BUILT
306 G4cout <<
"G4IonParametrisedLossModel::Initialise():"
307 <<
" Building dE/dx vectors:"
311 for (
G4int i = 0; i < nmbCouples; ++i) {
316 for(
G4int atomicNumberIon = 3; atomicNumberIon < 102; ++atomicNumberIon) {
318 LossTableList::iterator iter = lossTableList.begin();
319 LossTableList::iterator iter_end = lossTableList.end();
321 for(;iter != iter_end; ++iter) {
324 G4cout <<
"G4IonParametrisedLossModel::Initialise():"
325 <<
" Skipping illegal table."
329 if((*iter)->BuildDEDXTable(atomicNumberIon, material)) {
331#ifdef PRINT_TABLE_BUILT
332 G4cout <<
" Atomic Number Ion = " << atomicNumberIon
333 <<
", Material = " << material ->
GetName()
334 <<
", Table = " << (*iter) ->
GetName()
344 if(! particleChangeLoss) {
346 braggIonModel->SetParticleChange(particleChangeLoss, 0);
347 betheBlochModel->SetParticleChange(particleChangeLoss, 0);
353 betheBlochModel ->
Initialise(particle, cuts);
378 G4double maxEnergy = std::min(tmax, maxKinEnergy);
380 if(cutEnergy < tmax) {
382 G4double energy = kineticEnergy + cacheMass;
383 G4double betaSquared = kineticEnergy *
384 (energy + cacheMass) / (energy * energy);
386 crosssection = 1.0 / cutEnergy - 1.0 / maxEnergy -
387 betaSquared * std::log(maxEnergy / cutEnergy) / tmax;
389 crosssection *= twopi_mc2_rcl2 * cacheChargeSquare / betaSquared;
393 G4cout <<
"########################################################"
395 <<
"# G4IonParametrisedLossModel::ComputeCrossSectionPerAtom"
397 <<
"# particle =" << particle -> GetParticleName()
399 <<
"# cut(MeV) = " << cutEnergy/MeV
403 << std::setw(13) << std::right <<
"E(MeV)"
404 << std::setw(14) <<
"CS(um)"
405 << std::setw(14) <<
"E_max_sec(MeV)"
407 <<
"# ------------------------------------------------------"
410 G4cout << std::setw(14) << std::right << kineticEnergy / MeV
411 << std::setw(14) << crosssection / (um * um)
412 << std::setw(14) << tmax / MeV
416 crosssection *= atomicNumber;
430 G4double nbElecPerVolume = material -> GetTotNbOfElectPerVolume();
476 UpdateDEDXCache(particle, material, cutEnergy);
478 LossTableList::iterator iter = dedxCacheIter;
480 if(iter != lossTableList.end()) {
482 G4double transitionEnergy = dedxCacheTransitionEnergy;
484 if(transitionEnergy > kineticEnergy) {
486 dEdx = (*iter) -> GetDEDX(particle, material, kineticEnergy);
492 dEdx -= dEdxDeltaRays;
495 G4double massRatio = dedxCacheGenIonMassRatio;
500 G4double scaledKineticEnergy = kineticEnergy * massRatio;
501 G4double scaledTransitionEnergy = transitionEnergy * massRatio;
505 if(scaledTransitionEnergy >= lowEnergyLimit) {
508 material, genericIon,
509 scaledKineticEnergy, cutEnergy);
511 dEdx *= chargeSquare;
513 dEdx += corrections -> ComputeIonCorrections(particle,
514 material, kineticEnergy);
516 G4double factor = 1.0 + dedxCacheTransitionFactor /
527 if(particle != genericIon) {
530 massRatio = genericIonPDGMass / particle -> GetPDGMass();
533 G4double scaledKineticEnergy = kineticEnergy * massRatio;
536 if(scaledKineticEnergy < lowEnergyLimit) {
538 material, genericIon,
539 scaledKineticEnergy, cutEnergy);
541 dEdx *= chargeSquare;
545 material, genericIon,
546 lowEnergyLimit, cutEnergy);
549 material, genericIon,
550 lowEnergyLimit, cutEnergy);
552 if(particle != genericIon) {
553 G4double chargeSquareLowEnergyLimit =
555 lowEnergyLimit / massRatio);
557 dEdxLimitParam *= chargeSquareLowEnergyLimit;
558 dEdxLimitBetheBloch *= chargeSquareLowEnergyLimit;
560 dEdxLimitBetheBloch +=
561 corrections -> ComputeIonCorrections(particle,
562 material, lowEnergyLimit / massRatio);
565 G4double factor = (1.0 + (dEdxLimitParam/dEdxLimitBetheBloch - 1.0)
566 * lowEnergyLimit / scaledKineticEnergy);
569 material, genericIon,
570 scaledKineticEnergy, cutEnergy);
572 dEdx *= chargeSquare;
574 if(particle != genericIon) {
575 dEdx += corrections -> ComputeIonCorrections(particle,
576 material, kineticEnergy);
581 if (dEdx < 0.0) dEdx = 0.0;
595 G4double atomicMassNumber = particle -> GetAtomicMass();
596 G4double materialDensity = material -> GetDensity();
598 G4cout <<
"# dE/dx table for " << particle -> GetParticleName()
599 <<
" in material " << material ->
GetName()
600 <<
" of density " << materialDensity / g * cm3
603 <<
"# Projectile mass number A1 = " << atomicMassNumber
605 <<
"# ------------------------------------------------------"
608 << std::setw(13) << std::right <<
"E"
609 << std::setw(14) <<
"E/A1"
610 << std::setw(14) <<
"dE/dx"
611 << std::setw(14) <<
"1/rho*dE/dx"
614 << std::setw(13) << std::right <<
"(MeV)"
615 << std::setw(14) <<
"(MeV)"
616 << std::setw(14) <<
"(MeV/cm)"
617 << std::setw(14) <<
"(MeV*cm2/mg)"
619 <<
"# ------------------------------------------------------"
622 G4double energyLowerBoundary = lowerBoundary * atomicMassNumber;
623 G4double energyUpperBoundary = upperBoundary * atomicMassNumber;
627 energyLowerBoundary = std::log(energyLowerBoundary);
628 energyUpperBoundary = std::log(energyUpperBoundary);
631 G4double deltaEnergy = (energyUpperBoundary - energyLowerBoundary) /
634 for(
int i = 0; i < numBins + 1; i++) {
636 G4double energy = energyLowerBoundary + i * deltaEnergy;
637 if(logScaleEnergy) energy =
G4Exp(energy);
641 G4cout << std::setw(14) << std::right << energy / MeV
642 << std::setw(14) << energy / atomicMassNumber / MeV
643 << std::setw(14) << dedx / MeV * cm
644 << std::setw(14) << dedx / materialDensity / (MeV*cm2/(0.001*g))
659 LossTableList::iterator iter = lossTableList.begin();
660 LossTableList::iterator iter_end = lossTableList.end();
662 for(;iter != iter_end; iter++) {
666 lowerBoundary, upperBoundary,
667 numBins,logScaleEnergy);
676 std::vector<G4DynamicParticle*>* secondaries,
708 std::min(rossiMaxKinEnergySec, userMaxKinEnergySec);
710 if(cutKinEnergySec >= maxKinEnergySec)
return;
712 G4double kineticEnergy = particle -> GetKineticEnergy();
714 G4double energy = kineticEnergy + cacheMass;
715 G4double betaSquared = kineticEnergy * (energy + cacheMass)
725 kinEnergySec = cutKinEnergySec * maxKinEnergySec /
726 (maxKinEnergySec * (1.0 - xi) + cutKinEnergySec * xi);
730 grej = 1.0 - betaSquared * kinEnergySec / rossiMaxKinEnergySec;
733 G4cout <<
"G4IonParametrisedLossModel::SampleSecondary Warning: "
735 << grej <<
" for e= " << kinEnergySec
751 secondaries->push_back(delta);
755 G4double totalMomentum = std::sqrt(kineticEnergy*(energy + cacheMass));
758 finalP = finalP.
unit();
760 kineticEnergy -= kinEnergySec;
762 particleChangeLoss->SetProposedKineticEnergy(kineticEnergy);
763 particleChangeLoss->SetProposedMomentumDirection(finalP);
768void G4IonParametrisedLossModel::UpdateRangeCache(
776 if(particle == rangeCacheParticle &&
777 matCutsCouple == rangeCacheMatCutsCouple) {
780 rangeCacheParticle = particle;
781 rangeCacheMatCutsCouple = matCutsCouple;
783 const G4Material* material = matCutsCouple -> GetMaterial();
784 LossTableList::iterator iter =
IsApplicable(particle, material);
787 if(iter != lossTableList.end()) {
790 IonMatCouple ionMatCouple = std::make_pair(particle, matCutsCouple);
791 RangeEnergyTable::iterator iterRange = r.find(ionMatCouple);
793 if(iterRange == r.end()) BuildRangeVector(particle, matCutsCouple);
795 rangeCacheEnergyRange = E[ionMatCouple];
796 rangeCacheRangeEnergy = r[ionMatCouple];
799 rangeCacheEnergyRange = 0;
800 rangeCacheRangeEnergy = 0;
807void G4IonParametrisedLossModel::UpdateDEDXCache(
820 if(particle == dedxCacheParticle &&
821 material == dedxCacheMaterial &&
822 cutEnergy == dedxCacheEnergyCut) {
826 dedxCacheParticle = particle;
827 dedxCacheMaterial = material;
828 dedxCacheEnergyCut = cutEnergy;
830 G4double massRatio = genericIonPDGMass / particle -> GetPDGMass();
831 dedxCacheGenIonMassRatio = massRatio;
833 LossTableList::iterator iter =
IsApplicable(particle, material);
834 dedxCacheIter = iter;
837 if(iter != lossTableList.end()) {
841 (*iter) -> GetUpperEnergyEdge(particle, material);
842 dedxCacheTransitionEnergy = transitionEnergy;
846 G4double dEdxParam = (*iter) -> GetDEDX(particle, material,
853 dEdxParam -= dEdxDeltaRays;
860 G4double scaledTransitionEnergy = transitionEnergy * massRatio;
864 material, genericIon,
865 scaledTransitionEnergy, cutEnergy);
866 dEdxBetheBloch *= transitionChargeSquare;
870 corrections -> ComputeIonCorrections(particle,
871 material, transitionEnergy);
874 dedxCacheTransitionFactor =
875 (dEdxParam - dEdxBetheBloch)/dEdxBetheBloch
880 dedxCacheParticle = particle;
881 dedxCacheMaterial = material;
882 dedxCacheEnergyCut = cutEnergy;
884 dedxCacheGenIonMassRatio =
885 genericIonPDGMass / particle -> GetPDGMass();
887 dedxCacheTransitionEnergy = 0.0;
888 dedxCacheTransitionFactor = 0.0;
915 UpdateDEDXCache(particle, material, cutEnergy);
917 LossTableList::iterator iter = dedxCacheIter;
921 if (iter != lossTableList.end()) {
926 kineticEnergy, cutEnergy);
930 G4cout <<
"########################################################" <<
G4endl
931 <<
"# G4IonParametrisedLossModel::CorrectionsAlongStep" <<
G4endl
932 <<
"# cut(MeV) = " << cutEnergy/MeV <<
G4endl;
934 << std::setw(13) << std::right <<
"E(MeV)"
935 << std::setw(14) <<
"l(um)"
936 << std::setw(14) <<
"l*dE/dx(MeV)"
937 << std::setw(14) <<
"(l*dE/dx)/E"
939 <<
"# ------------------------------------------------------" <<
G4endl;
940 G4cout << std::setw(14) << std::right << kineticEnergy / MeV
941 << std::setw(14) << length / um
942 << std::setw(14) << eloss / MeV
943 << std::setw(14) << eloss / kineticEnergy * 100.0
951 if (eloss > energyLossLimit * kineticEnergy) {
953 kineticEnergy,length);
957 G4cout << std::setw(14) << std::right << kineticEnergy / MeV
958 << std::setw(14) << length / um
959 << std::setw(14) << eloss / MeV
960 << std::setw(14) << eloss / kineticEnergy * 100.0
968 G4double energy = kineticEnergy - eloss * 0.5;
969 if (energy < 0.0) energy = kineticEnergy * 0.5;
971 G4double q2 = corrections->EffectiveChargeSquareRatio(particle, material,
980 eloss *= q2/chargeSquareRatio;
985void G4IonParametrisedLossModel::BuildRangeVector(
990 std::size_t cutIndex = matCutsCouple -> GetIndex();
991 cutEnergy = cutEnergies[cutIndex];
993 const G4Material* material = matCutsCouple -> GetMaterial();
995 G4double massRatio = genericIonPDGMass / particle -> GetPDGMass();
997 G4double lowerEnergy = lowerEnergyEdgeIntegr / massRatio;
998 G4double upperEnergy = upperEnergyEdgeIntegr / massRatio;
1000 G4double logLowerEnergyEdge = std::log(lowerEnergy);
1001 G4double logUpperEnergyEdge = std::log(upperEnergy);
1003 G4double logDeltaEnergy = (logUpperEnergyEdge - logLowerEnergyEdge) /
1019 G4double range = 2.0 * lowerEnergy / dedxLow;
1021 energyRangeVector -> PutValues(0, lowerEnergy, range);
1023 G4double logEnergy = std::log(lowerEnergy);
1024 for(std::size_t i = 1; i < nmbBins+1; ++i) {
1026 G4double logEnergyIntegr = logEnergy;
1028 for(std::size_t j = 0; j < nmbSubBins; ++j) {
1031 logEnergyIntegr += logDeltaIntegr;
1034 G4double deltaIntegr = binUpperBoundary - binLowerBoundary;
1036 G4double energyIntegr = binLowerBoundary + 0.5 * deltaIntegr;
1043 if(dedxValue > 0.0) range += deltaIntegr / dedxValue;
1045#ifdef PRINT_DEBUG_DETAILS
1046 G4cout <<
" E = "<< energyIntegr/MeV
1047 <<
" MeV -> dE = " << deltaIntegr/MeV
1048 <<
" MeV -> dE/dx = " << dedxValue/MeV*mm
1049 <<
" MeV/mm -> dE/(dE/dx) = " << deltaIntegr /
1051 <<
" mm -> range = " << range / mm
1056 logEnergy += logDeltaEnergy;
1060 energyRangeVector -> PutValues(i, energy, range);
1062#ifdef PRINT_DEBUG_DETAILS
1063 G4cout <<
"G4IonParametrisedLossModel::BuildRangeVector() bin = "
1065 <<
energy / MeV <<
" MeV, R = "
1066 << range / mm <<
" mm"
1072 energyRangeVector -> FillSecondDerivatives();
1075 energyRangeVector ->
Value(lowerEnergy);
1077 energyRangeVector ->
Value(upperEnergy);
1079 G4PhysicsFreeVector* rangeEnergyVector
1080 =
new G4PhysicsFreeVector(nmbBins+1,
1085 for(std::size_t i = 0; i < nmbBins+1; ++i) {
1087 rangeEnergyVector ->
1088 PutValues(i, energyRangeVector ->
Value(energy), energy);
1091 rangeEnergyVector -> FillSecondDerivatives();
1093#ifdef PRINT_DEBUG_TABLES
1094 G4cout << *energyLossVector
1095 << *energyRangeVector
1096 << *rangeEnergyVector <<
G4endl;
1099 IonMatCouple ionMatCouple = std::make_pair(particle, matCutsCouple);
1101 E[ionMatCouple] = energyRangeVector;
1102 r[ionMatCouple] = rangeEnergyVector;
1115 UpdateRangeCache(particle, matCutsCouple);
1120 if(energyRange != 0 && rangeEnergy != 0) {
1122 G4double lowerEnEdge = energyRange -> Energy( 0 );
1123 G4double lowerRangeEdge = rangeEnergy -> Energy( 0 );
1129 if(kineticEnergy < lowerEnEdge) {
1131 range = energyRange ->
Value(lowerEnEdge);
1132 range *= std::sqrt(kineticEnergy / lowerEnEdge);
1136 G4cout <<
"G4IonParametrisedLossModel::ComputeLossForStep() range = "
1137 << range / mm <<
" mm, step = " << stepLength / mm <<
" mm"
1142 G4double remRange = range - stepLength;
1146 if(remRange < 0.0) loss = kineticEnergy;
1147 else if(remRange < lowerRangeEdge) {
1149 G4double ratio = remRange / lowerRangeEdge;
1150 loss = kineticEnergy - ratio * ratio * lowerEnEdge;
1155 loss = kineticEnergy - energy;
1159 if(loss < 0.0) loss = 0.0;
1172 G4cout <<
"G4IonParametrisedLossModel::AddDEDXTable() Cannot "
1173 <<
" add table: Invalid pointer."
1180 LossTableList::iterator iter = lossTableList.begin();
1181 LossTableList::iterator iter_end = lossTableList.end();
1183 for(;iter != iter_end; ++iter) {
1184 const G4String& tableName = (*iter)->GetName();
1186 if(tableName == nam) {
1187 G4cout <<
"G4IonParametrisedLossModel::AddDEDXTable() Cannot "
1188 <<
" add table: Name already exists."
1196 if(scalingAlgorithm == 0)
1202 lossTableList.push_front(handler);
1212 LossTableList::iterator iter = lossTableList.begin();
1213 LossTableList::iterator iter_end = lossTableList.end();
1215 for(;iter != iter_end; iter++) {
1218 if(tableName == nam) {
1222 lossTableList.erase(iter);
1225 RangeEnergyTable::iterator iterRange = r.begin();
1226 RangeEnergyTable::iterator iterRange_end = r.end();
1228 for(;iterRange != iterRange_end; iterRange++)
1229 delete iterRange -> second;
1232 EnergyRangeTable::iterator iterEnergy = E.begin();
1233 EnergyRangeTable::iterator iterEnergy_end = E.end();
1235 for(;iterEnergy != iterEnergy_end; iterEnergy++)
1236 delete iterEnergy -> second;
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
std::pair< const G4ParticleDefinition *, const G4MaterialCutsCouple * > IonMatCouple
CLHEP::Hep3Vector G4ThreeVector
G4GLOB_DLL std::ostream G4cout
const G4ThreeVector & GetMomentumDirection() const
G4ThreeVector GetMomentum() const
static G4Electron * Electron()
static G4EmParameters * Instance()
G4bool UseICRU90Data() const
static G4GenericIon * Definition()
G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *, G4double, G4double, G4double, G4double, G4double) override
G4double MinEnergyCut(const G4ParticleDefinition *, const G4MaterialCutsCouple *) override
virtual ~G4IonParametrisedLossModel()
G4double MaxSecondaryEnergy(const G4ParticleDefinition *, G4double) override
LossTableList::iterator IsApplicable(const G4ParticleDefinition *, const G4Material *)
G4double GetChargeSquareRatio(const G4ParticleDefinition *, const G4Material *, G4double) override
G4bool AddDEDXTable(const G4String &name, G4VIonDEDXTable *table, G4VIonDEDXScalingAlgorithm *algorithm=nullptr)
void Initialise(const G4ParticleDefinition *, const G4DataVector &) override
G4IonParametrisedLossModel(const G4ParticleDefinition *particle=nullptr, const G4String &name="ParamICRU73")
void PrintDEDXTableHandlers(const G4ParticleDefinition *, const G4Material *, G4double, G4double, G4int, G4bool)
G4double DeltaRayMeanEnergyTransferRate(const G4Material *, const G4ParticleDefinition *, G4double, G4double)
G4double ComputeDEDXPerVolume(const G4Material *, const G4ParticleDefinition *, G4double, G4double) override
void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double, G4double) override
G4bool RemoveDEDXTable(const G4String &name)
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
void CorrectionsAlongStep(const G4Material *, const G4ParticleDefinition *, const G4double kinEnergy, const G4double cutEnergy, const G4double &length, G4double &eloss) override
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
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
std::size_t GetTableSize() const
static G4ProductionCutsTable * GetProductionCutsTable()
virtual void SetParticleAndCharge(const G4ParticleDefinition *, G4double q2)
G4VEmFluctuationModel * GetModelOfFluctuations()
G4VEmAngularDistribution * GetAngularDistribution()
G4double LowEnergyLimit() const
G4int SelectRandomAtomNumber(const G4Material *) const
virtual G4double Value(const G4MaterialCutsCouple *, const G4ParticleDefinition *, G4double kineticEnergy)
G4double HighEnergyLimit() const
G4VEmModel(const G4String &nam)
void SetAngularDistribution(G4VEmAngularDistribution *)
const G4MaterialCutsCouple * CurrentCouple() const
const G4String & GetName() const
G4double MaxSecondaryKinEnergy(const G4DynamicParticle *dynParticle)
G4ParticleChangeForLoss * GetParticleChangeForLoss()
G4double energy(const ThreeVector &p, const G4double m)