55G4double G4EnergyLossTables::QQPositron = 1.0;
56G4double G4EnergyLossTables::Chargesquare ;
57G4int G4EnergyLossTables::oldIndex = -1 ;
58G4double G4EnergyLossTables::rmin = 0. ;
59G4double G4EnergyLossTables::rmax = 0. ;
60G4double G4EnergyLossTables::Thigh = 0. ;
61G4int G4EnergyLossTables::let_counter = 0;
62G4int G4EnergyLossTables::let_max_num_warnings = 100;
63G4bool G4EnergyLossTables::first_loss =
true;
65G4EnergyLossTables::helper_map *G4EnergyLossTables::dict =
nullptr;
80 theDEDXTable(aDEDXTable), theRangeTable(aRangeTable),
81 theInverseRangeTable(anInverseRangeTable),
82 theLabTimeTable(aLabTimeTable),
83 theProperTimeTable(aProperTimeTable),
84 theLowestKineticEnergy(aLowestKineticEnergy),
85 theHighestKineticEnergy(aHighestKineticEnergy),
86 theMassRatio(aMassRatio),
87 theNumberOfBins(aNumberOfBins)
94 theLowestKineticEnergy = 0.0;
95 theHighestKineticEnergy= 0.0;
98 theDEDXTable = theRangeTable = theInverseRangeTable = theLabTimeTable
99 = theProperTimeTable =
nullptr;
116 if (!dict) dict =
new G4EnergyLossTables::helper_map;
121 tLabTime,tProperTime,lowestKineticEnergy,
122 highestKineticEnergy, massRatio,NumberOfBins);
130 nullptr,
nullptr,
nullptr,
nullptr,
nullptr, 0.0, 0.0, 0.0, 0);
140 if (!dict) dict =
new G4EnergyLossTables::helper_map;
141 helper_map::iterator it;
142 if((it=dict->find(p))==dict->end())
return nullptr;
143 return (*it).second.theDEDXTable;
151 if (!dict) dict =
new G4EnergyLossTables::helper_map;
152 helper_map::iterator it;
153 if((it=dict->find(p))==dict->end())
return nullptr;
154 return (*it).second.theRangeTable;
162 if (!dict) dict =
new G4EnergyLossTables::helper_map;
163 helper_map::iterator it;
164 if((it=dict->find(p))==dict->end())
return nullptr;
165 return (*it).second.theInverseRangeTable;
173 if (!dict) dict =
new G4EnergyLossTables::helper_map;
174 helper_map::iterator it;
175 if((it=dict->find(p))==dict->end())
return nullptr;
176 return (*it).second.theLabTimeTable;
184 if (!dict) dict =
new G4EnergyLossTables::helper_map;
185 helper_map::iterator it;
186 if((it=dict->find(p))==dict->end())
return nullptr;
187 return (*it).second.theProperTimeTable;
195 if (!dict) dict =
new G4EnergyLossTables::helper_map;
198 helper_map::iterator it;
199 if ((it=dict->find(p))==dict->end()) {
217 *t= GetTables(aParticle);
226 ParticleHaveNoLoss(aParticle,
"dEdx");
231 G4double scaledKineticEnergy = KineticEnergy*t->theMassRatio;
235 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
237 dEdx =(*dEdxTable)(materialIndex)->GetValue(
238 t->theLowestKineticEnergy,isOut)
239 *std::sqrt(scaledKineticEnergy/t->theLowestKineticEnergy);
241 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
243 dEdx = (*dEdxTable)(materialIndex)->GetValue(
244 t->theHighestKineticEnergy,isOut);
248 dEdx = (*dEdxTable)(materialIndex)->GetValue(
249 scaledKineticEnergy,isOut);
253 return dEdx*Chargesquare;
268 *t= GetTables(aParticle);
274 ParticleHaveNoLoss(aParticle,
"LabTime");
278 const G4double parlowen=0.4 , ppar=0.5-parlowen ;
280 G4double scaledKineticEnergy = KineticEnergy*t->theMassRatio;
284 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
286 time = std::exp(ppar*std::log(scaledKineticEnergy/t->theLowestKineticEnergy))*
287 (*labtimeTable)(materialIndex)->GetValue(
288 t->theLowestKineticEnergy,isOut);
291 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
293 time = (*labtimeTable)(materialIndex)->GetValue(
294 t->theHighestKineticEnergy,isOut);
298 time = (*labtimeTable)(materialIndex)->GetValue(
299 scaledKineticEnergy,isOut);
303 return time/t->theMassRatio ;
319 *t= GetTables(aParticle);
325 ParticleHaveNoLoss(aParticle,
"LabTime");
329 const G4double parlowen=0.4 , ppar=0.5-parlowen ;
330 const G4double dToverT = 0.05 , facT = 1. -dToverT ;
331 G4double timestart,timeend,deltatime,dTT;
335 G4double scaledKineticEnergy = KineticEnergyStart*t->theMassRatio;
337 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
339 timestart = std::exp(ppar*std::log(scaledKineticEnergy/t->theLowestKineticEnergy))*
340 (*labtimeTable)(materialIndex)->GetValue(
341 t->theLowestKineticEnergy,isOut);
344 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
346 timestart = (*labtimeTable)(materialIndex)->GetValue(
347 t->theHighestKineticEnergy,isOut);
351 timestart = (*labtimeTable)(materialIndex)->GetValue(
352 scaledKineticEnergy,isOut);
356 dTT = (KineticEnergyStart - KineticEnergyEnd)/KineticEnergyStart ;
359 scaledKineticEnergy = facT*KineticEnergyStart*t->theMassRatio;
361 scaledKineticEnergy = KineticEnergyEnd*t->theMassRatio;
363 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
365 timeend = std::exp(ppar*std::log(scaledKineticEnergy/t->theLowestKineticEnergy))*
366 (*labtimeTable)(materialIndex)->GetValue(
367 t->theLowestKineticEnergy,isOut);
370 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
372 timeend = (*labtimeTable)(materialIndex)->GetValue(
373 t->theHighestKineticEnergy,isOut);
377 timeend = (*labtimeTable)(materialIndex)->GetValue(
378 scaledKineticEnergy,isOut);
382 deltatime = timestart - timeend ;
385 deltatime *= dTT/dToverT;
387 return deltatime/t->theMassRatio ;
402 *t= GetTables(aParticle);
407 if (!propertimeTable) {
408 ParticleHaveNoLoss(aParticle,
"ProperTime");
412 const G4double parlowen=0.4 , ppar=0.5-parlowen ;
414 G4double scaledKineticEnergy = KineticEnergy*t->theMassRatio;
418 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
420 time = std::exp(ppar*std::log(scaledKineticEnergy/t->theLowestKineticEnergy))*
421 (*propertimeTable)(materialIndex)->GetValue(
422 t->theLowestKineticEnergy,isOut);
425 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
427 time = (*propertimeTable)(materialIndex)->GetValue(
428 t->theHighestKineticEnergy,isOut);
432 time = (*propertimeTable)(materialIndex)->GetValue(
433 scaledKineticEnergy,isOut);
437 return time/t->theMassRatio ;
453 *t= GetTables(aParticle);
458 if (!propertimeTable) {
459 ParticleHaveNoLoss(aParticle,
"ProperTime");
463 const G4double parlowen=0.4 , ppar=0.5-parlowen ;
464 const G4double dToverT = 0.05 , facT = 1. -dToverT ;
465 G4double timestart,timeend,deltatime,dTT;
469 G4double scaledKineticEnergy = KineticEnergyStart*t->theMassRatio;
471 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
473 timestart = std::exp(ppar*std::log(scaledKineticEnergy/t->theLowestKineticEnergy))*
474 (*propertimeTable)(materialIndex)->GetValue(
475 t->theLowestKineticEnergy,isOut);
478 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
480 timestart = (*propertimeTable)(materialIndex)->GetValue(
481 t->theHighestKineticEnergy,isOut);
485 timestart = (*propertimeTable)(materialIndex)->GetValue(
486 scaledKineticEnergy,isOut);
490 dTT = (KineticEnergyStart - KineticEnergyEnd)/KineticEnergyStart ;
493 scaledKineticEnergy = facT*KineticEnergyStart*t->theMassRatio;
495 scaledKineticEnergy = KineticEnergyEnd*t->theMassRatio;
497 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
499 timeend = std::exp(ppar*std::log(scaledKineticEnergy/t->theLowestKineticEnergy))*
500 (*propertimeTable)(materialIndex)->GetValue(
501 t->theLowestKineticEnergy,isOut);
504 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
506 timeend = (*propertimeTable)(materialIndex)->GetValue(
507 t->theHighestKineticEnergy,isOut);
511 timeend = (*propertimeTable)(materialIndex)->GetValue(
512 scaledKineticEnergy,isOut);
516 deltatime = timestart - timeend ;
519 deltatime *= dTT/dToverT ;
521 return deltatime/t->theMassRatio ;
536 *t= GetTables(aParticle);
546 ParticleHaveNoLoss(aParticle,
"Range");
551 G4double scaledKineticEnergy = KineticEnergy*t->theMassRatio;
555 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
557 Range = std::sqrt(scaledKineticEnergy/t->theLowestKineticEnergy)*
558 (*rangeTable)(materialIndex)->GetValue(
559 t->theLowestKineticEnergy,isOut);
561 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
563 Range = (*rangeTable)(materialIndex)->GetValue(
564 t->theHighestKineticEnergy,isOut)+
565 (scaledKineticEnergy-t->theHighestKineticEnergy)/
566 (*dEdxTable)(materialIndex)->GetValue(
567 t->theHighestKineticEnergy,isOut);
571 Range = (*rangeTable)(materialIndex)->GetValue(
572 scaledKineticEnergy,isOut);
576 return Range/(Chargesquare*t->theMassRatio);
592 *t= GetTables(aParticle);
601 if (!inverseRangeTable) {
602 ParticleHaveNoLoss(aParticle,
"InverseRange");
606 G4double scaledrange,scaledKineticEnergy ;
611 if(materialIndex != oldIndex)
613 oldIndex = materialIndex ;
614 rmin = (*inverseRangeTable)(materialIndex)->
615 GetLowEdgeEnergy(0) ;
616 rmax = (*inverseRangeTable)(materialIndex)->
617 GetLowEdgeEnergy(t->theNumberOfBins-2) ;
618 Thigh = (*inverseRangeTable)(materialIndex)->
619 GetValue(rmax,isOut) ;
622 scaledrange = range*Chargesquare*t->theMassRatio ;
624 if(scaledrange < rmin)
626 scaledKineticEnergy = t->theLowestKineticEnergy*
627 scaledrange*scaledrange/(rmin*rmin) ;
631 if(scaledrange < rmax)
633 scaledKineticEnergy = (*inverseRangeTable)(materialIndex)->
634 GetValue( scaledrange,isOut) ;
638 scaledKineticEnergy = Thigh +
640 (*dEdxTable)(materialIndex)->
641 GetValue(Thigh,isOut) ;
645 return scaledKineticEnergy/t->theMassRatio ;
660 *t= GetTables(aParticle);
669 ParticleHaveNoLoss(aParticle,
"dEdx");
674 G4double scaledKineticEnergy = KineticEnergy*t->theMassRatio;
678 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
680 dEdx = std::sqrt(scaledKineticEnergy/t->theLowestKineticEnergy)
681 *(*dEdxTable)(materialIndex)->GetValue(
682 t->theLowestKineticEnergy,isOut);
684 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
686 dEdx = (*dEdxTable)(materialIndex)->GetValue(
687 t->theHighestKineticEnergy,isOut);
691 dEdx = (*dEdxTable)(materialIndex)->GetValue(
692 scaledKineticEnergy,isOut) ;
696 return dEdx*Chargesquare;
711 *t= GetTables(aParticle);
721 ParticleHaveNoLoss(aParticle,
"Range");
726 G4double Thighr = t->theHighestKineticEnergy*t->theLowestKineticEnergy/
727 (*rangeTable)(materialIndex)->
728 GetLowEdgeEnergy(1) ;
730 G4double scaledKineticEnergy = KineticEnergy*t->theMassRatio;
734 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
736 Range = std::sqrt(scaledKineticEnergy/t->theLowestKineticEnergy)*
737 (*rangeTable)(materialIndex)->GetValue(
738 t->theLowestKineticEnergy,isOut);
740 }
else if (scaledKineticEnergy>Thighr) {
742 Range = (*rangeTable)(materialIndex)->GetValue(
744 (scaledKineticEnergy-Thighr)/
745 (*dEdxTable)(materialIndex)->GetValue(
750 Range = (*rangeTable)(materialIndex)->GetValue(
751 scaledKineticEnergy,isOut) ;
755 return Range/(Chargesquare*t->theMassRatio);
770 *t= GetTables(aParticle);
781 else ParticleHaveNoLoss(aParticle,
"dEdx");
786 G4double scaledKineticEnergy = KineticEnergy*t->theMassRatio;
790 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
792 dEdx =(*dEdxTable)(materialIndex)->GetValue(
793 t->theLowestKineticEnergy,isOut)
794 *std::sqrt(scaledKineticEnergy/t->theLowestKineticEnergy);
796 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
798 dEdx = (*dEdxTable)(materialIndex)->GetValue(
799 t->theHighestKineticEnergy,isOut);
803 dEdx = (*dEdxTable)(materialIndex)->GetValue(
804 scaledKineticEnergy,isOut);
808 return dEdx*Chargesquare;
823 *t= GetTables(aParticle);
839 G4double scaledKineticEnergy = KineticEnergy*t->theMassRatio;
843 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
845 Range = std::sqrt(scaledKineticEnergy/t->theLowestKineticEnergy)*
846 (*rangeTable)(materialIndex)->GetValue(
847 t->theLowestKineticEnergy,isOut);
849 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
851 Range = (*rangeTable)(materialIndex)->GetValue(
852 t->theHighestKineticEnergy,isOut)+
853 (scaledKineticEnergy-t->theHighestKineticEnergy)/
854 (*dEdxTable)(materialIndex)->GetValue(
855 t->theHighestKineticEnergy,isOut);
859 Range = (*rangeTable)(materialIndex)->GetValue(
860 scaledKineticEnergy,isOut);
864 return Range/(Chargesquare*t->theMassRatio);
880 *t= GetTables(aParticle);
890 if (!inverseRangeTable) {
896 G4double scaledrange,scaledKineticEnergy ;
901 if(materialIndex != oldIndex)
903 oldIndex = materialIndex ;
904 rmin = (*inverseRangeTable)(materialIndex)->
905 GetLowEdgeEnergy(0) ;
906 rmax = (*inverseRangeTable)(materialIndex)->
907 GetLowEdgeEnergy(t->theNumberOfBins-2) ;
908 Thigh = (*inverseRangeTable)(materialIndex)->
909 GetValue(rmax,isOut) ;
912 scaledrange = range*Chargesquare*t->theMassRatio ;
914 if(scaledrange < rmin)
916 scaledKineticEnergy = t->theLowestKineticEnergy*
917 scaledrange*scaledrange/(rmin*rmin) ;
921 if(scaledrange < rmax)
923 scaledKineticEnergy = (*inverseRangeTable)(materialIndex)->
924 GetValue( scaledrange,isOut) ;
928 scaledKineticEnergy = Thigh +
930 (*dEdxTable)(materialIndex)->
931 GetValue(Thigh,isOut) ;
935 return scaledKineticEnergy/t->theMassRatio ;
949 *t= GetTables(aParticle);
961 G4double scaledKineticEnergy = KineticEnergy*t->theMassRatio;
965 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
967 dEdx = std::sqrt(scaledKineticEnergy/t->theLowestKineticEnergy)
968 *(*dEdxTable)(materialIndex)->GetValue(
969 t->theLowestKineticEnergy,isOut);
971 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
973 dEdx = (*dEdxTable)(materialIndex)->GetValue(
974 t->theHighestKineticEnergy,isOut);
978 dEdx = (*dEdxTable)(materialIndex)->GetValue(
979 scaledKineticEnergy,isOut) ;
983 return dEdx*Chargesquare;
997 *t= GetTables(aParticle);
1006 if ( !dEdxTable || !rangeTable)
1011 G4double Thighr = t->theHighestKineticEnergy*t->theLowestKineticEnergy/
1012 (*rangeTable)(materialIndex)->
1013 GetLowEdgeEnergy(1) ;
1015 G4double scaledKineticEnergy = KineticEnergy*t->theMassRatio;
1019 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
1021 Range = std::sqrt(scaledKineticEnergy/t->theLowestKineticEnergy)*
1022 (*rangeTable)(materialIndex)->GetValue(
1023 t->theLowestKineticEnergy,isOut);
1025 }
else if (scaledKineticEnergy>Thighr) {
1027 Range = (*rangeTable)(materialIndex)->GetValue(
1029 (scaledKineticEnergy-Thighr)/
1030 (*dEdxTable)(materialIndex)->GetValue(
1035 Range = (*rangeTable)(materialIndex)->GetValue(
1036 scaledKineticEnergy,isOut) ;
1040 return Range/(Chargesquare*t->theMassRatio);
1045void G4EnergyLossTables::CPRWarning()
1047 if (let_counter < let_max_num_warnings) {
1050 G4cout <<
"##### G4EnergyLossTable WARNING: The obsolete interface is used!" <<
G4endl;
1051 G4cout <<
"##### RESULTS ARE NOT GARANTEED!" <<
G4endl;
1052 G4cout <<
"##### Please, substitute G4Material by G4MaterialCutsCouple" <<
G4endl;
1053 G4cout <<
"##### Obsolete interface will be removed soon" <<
G4endl;
1057 }
else if (let_counter == let_max_num_warnings) {
1059 G4cout <<
"##### G4EnergyLossTable WARNING closed" <<
G4endl;
G4GLOB_DLL std::ostream G4cout
G4EnergyLossTablesHelper()
static G4double GetRange(const G4ParticleDefinition *aParticle, G4double KineticEnergy, const G4Material *aMaterial)
static const G4PhysicsTable * GetLabTimeTable(const G4ParticleDefinition *p)
static void Register(const G4ParticleDefinition *p, const G4PhysicsTable *tDEDX, const G4PhysicsTable *tRange, const G4PhysicsTable *tInverseRange, const G4PhysicsTable *tLabTime, const G4PhysicsTable *tProperTime, G4double lowestKineticEnergy, G4double highestKineticEnergy, G4double massRatio, G4int NumberOfBins)
static G4double GetDEDX(const G4ParticleDefinition *aParticle, G4double KineticEnergy, const G4Material *aMaterial)
static G4double GetDeltaProperTime(const G4ParticleDefinition *aParticle, G4double KineticEnergyStart, G4double KineticEnergyEnd, const G4Material *aMaterial)
static G4double GetLabTime(const G4ParticleDefinition *aParticle, G4double KineticEnergy, const G4Material *aMaterial)
static G4double GetPreciseDEDX(const G4ParticleDefinition *aParticle, G4double KineticEnergy, const G4Material *aMaterial)
static G4double GetPreciseEnergyFromRange(const G4ParticleDefinition *aParticle, G4double range, const G4Material *aMaterial)
static const G4PhysicsTable * GetDEDXTable(const G4ParticleDefinition *p)
static const G4PhysicsTable * GetRangeTable(const G4ParticleDefinition *p)
static const G4PhysicsTable * GetInverseRangeTable(const G4ParticleDefinition *p)
static G4double GetDeltaLabTime(const G4ParticleDefinition *aParticle, G4double KineticEnergyStart, G4double KineticEnergyEnd, const G4Material *aMaterial)
static G4double GetPreciseRangeFromEnergy(const G4ParticleDefinition *aParticle, G4double KineticEnergy, const G4Material *aMaterial)
static G4double GetProperTime(const G4ParticleDefinition *aParticle, G4double KineticEnergy, const G4Material *aMaterial)
static const G4PhysicsTable * GetProperTimeTable(const G4ParticleDefinition *p)
static G4LossTableManager * Instance()
G4double GetEnergy(const G4ParticleDefinition *aParticle, G4double range, const G4MaterialCutsCouple *couple)
G4double GetRange(const G4ParticleDefinition *aParticle, G4double kineticEnergy, const G4MaterialCutsCouple *couple)
G4double GetDEDX(const G4ParticleDefinition *aParticle, G4double kineticEnergy, const G4MaterialCutsCouple *couple)
std::size_t GetIndex() const
G4double GetPDGCharge() const