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 = 0;
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);
139 if (!dict) dict =
new G4EnergyLossTables::helper_map;
140 helper_map::iterator it;
141 if((it=dict->find(p))==dict->end())
return 0;
142 return (*it).second.theDEDXTable;
150 if (!dict) dict =
new G4EnergyLossTables::helper_map;
151 helper_map::iterator it;
152 if((it=dict->find(p))==dict->end())
return 0;
153 return (*it).second.theRangeTable;
161 if (!dict) dict =
new G4EnergyLossTables::helper_map;
162 helper_map::iterator it;
163 if((it=dict->find(p))==dict->end())
return 0;
164 return (*it).second.theInverseRangeTable;
172 if (!dict) dict =
new G4EnergyLossTables::helper_map;
173 helper_map::iterator it;
174 if((it=dict->find(p))==dict->end())
return 0;
175 return (*it).second.theLabTimeTable;
183 if (!dict) dict =
new G4EnergyLossTables::helper_map;
184 helper_map::iterator it;
185 if((it=dict->find(p))==dict->end())
return 0;
186 return (*it).second.theProperTimeTable;
194 if (!dict) dict =
new G4EnergyLossTables::helper_map;
197 helper_map::iterator it;
198 if ((it=dict->find(p))==dict->end()) {
216 *t= GetTables(aParticle);
225 ParticleHaveNoLoss(aParticle,
"dEdx");
230 G4double scaledKineticEnergy = KineticEnergy*t->theMassRatio;
234 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
236 dEdx =(*dEdxTable)(materialIndex)->GetValue(
237 t->theLowestKineticEnergy,isOut)
238 *std::sqrt(scaledKineticEnergy/t->theLowestKineticEnergy);
240 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
242 dEdx = (*dEdxTable)(materialIndex)->GetValue(
243 t->theHighestKineticEnergy,isOut);
247 dEdx = (*dEdxTable)(materialIndex)->GetValue(
248 scaledKineticEnergy,isOut);
252 return dEdx*Chargesquare;
267 *t= GetTables(aParticle);
273 ParticleHaveNoLoss(aParticle,
"LabTime");
277 const G4double parlowen=0.4 , ppar=0.5-parlowen ;
279 G4double scaledKineticEnergy = KineticEnergy*t->theMassRatio;
283 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
285 time = std::exp(ppar*std::log(scaledKineticEnergy/t->theLowestKineticEnergy))*
286 (*labtimeTable)(materialIndex)->GetValue(
287 t->theLowestKineticEnergy,isOut);
290 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
292 time = (*labtimeTable)(materialIndex)->GetValue(
293 t->theHighestKineticEnergy,isOut);
297 time = (*labtimeTable)(materialIndex)->GetValue(
298 scaledKineticEnergy,isOut);
302 return time/t->theMassRatio ;
318 *t= GetTables(aParticle);
324 ParticleHaveNoLoss(aParticle,
"LabTime");
328 const G4double parlowen=0.4 , ppar=0.5-parlowen ;
329 const G4double dToverT = 0.05 , facT = 1. -dToverT ;
330 G4double timestart,timeend,deltatime,dTT;
334 G4double scaledKineticEnergy = KineticEnergyStart*t->theMassRatio;
336 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
338 timestart = std::exp(ppar*std::log(scaledKineticEnergy/t->theLowestKineticEnergy))*
339 (*labtimeTable)(materialIndex)->GetValue(
340 t->theLowestKineticEnergy,isOut);
343 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
345 timestart = (*labtimeTable)(materialIndex)->GetValue(
346 t->theHighestKineticEnergy,isOut);
350 timestart = (*labtimeTable)(materialIndex)->GetValue(
351 scaledKineticEnergy,isOut);
355 dTT = (KineticEnergyStart - KineticEnergyEnd)/KineticEnergyStart ;
358 scaledKineticEnergy = facT*KineticEnergyStart*t->theMassRatio;
360 scaledKineticEnergy = KineticEnergyEnd*t->theMassRatio;
362 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
364 timeend = std::exp(ppar*std::log(scaledKineticEnergy/t->theLowestKineticEnergy))*
365 (*labtimeTable)(materialIndex)->GetValue(
366 t->theLowestKineticEnergy,isOut);
369 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
371 timeend = (*labtimeTable)(materialIndex)->GetValue(
372 t->theHighestKineticEnergy,isOut);
376 timeend = (*labtimeTable)(materialIndex)->GetValue(
377 scaledKineticEnergy,isOut);
381 deltatime = timestart - timeend ;
384 deltatime *= dTT/dToverT;
386 return deltatime/t->theMassRatio ;
401 *t= GetTables(aParticle);
406 if (!propertimeTable) {
407 ParticleHaveNoLoss(aParticle,
"ProperTime");
411 const G4double parlowen=0.4 , ppar=0.5-parlowen ;
413 G4double scaledKineticEnergy = KineticEnergy*t->theMassRatio;
417 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
419 time = std::exp(ppar*std::log(scaledKineticEnergy/t->theLowestKineticEnergy))*
420 (*propertimeTable)(materialIndex)->GetValue(
421 t->theLowestKineticEnergy,isOut);
424 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
426 time = (*propertimeTable)(materialIndex)->GetValue(
427 t->theHighestKineticEnergy,isOut);
431 time = (*propertimeTable)(materialIndex)->GetValue(
432 scaledKineticEnergy,isOut);
436 return time/t->theMassRatio ;
452 *t= GetTables(aParticle);
457 if (!propertimeTable) {
458 ParticleHaveNoLoss(aParticle,
"ProperTime");
462 const G4double parlowen=0.4 , ppar=0.5-parlowen ;
463 const G4double dToverT = 0.05 , facT = 1. -dToverT ;
464 G4double timestart,timeend,deltatime,dTT;
468 G4double scaledKineticEnergy = KineticEnergyStart*t->theMassRatio;
470 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
472 timestart = std::exp(ppar*std::log(scaledKineticEnergy/t->theLowestKineticEnergy))*
473 (*propertimeTable)(materialIndex)->GetValue(
474 t->theLowestKineticEnergy,isOut);
477 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
479 timestart = (*propertimeTable)(materialIndex)->GetValue(
480 t->theHighestKineticEnergy,isOut);
484 timestart = (*propertimeTable)(materialIndex)->GetValue(
485 scaledKineticEnergy,isOut);
489 dTT = (KineticEnergyStart - KineticEnergyEnd)/KineticEnergyStart ;
492 scaledKineticEnergy = facT*KineticEnergyStart*t->theMassRatio;
494 scaledKineticEnergy = KineticEnergyEnd*t->theMassRatio;
496 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
498 timeend = std::exp(ppar*std::log(scaledKineticEnergy/t->theLowestKineticEnergy))*
499 (*propertimeTable)(materialIndex)->GetValue(
500 t->theLowestKineticEnergy,isOut);
503 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
505 timeend = (*propertimeTable)(materialIndex)->GetValue(
506 t->theHighestKineticEnergy,isOut);
510 timeend = (*propertimeTable)(materialIndex)->GetValue(
511 scaledKineticEnergy,isOut);
515 deltatime = timestart - timeend ;
518 deltatime *= dTT/dToverT ;
520 return deltatime/t->theMassRatio ;
535 *t= GetTables(aParticle);
545 ParticleHaveNoLoss(aParticle,
"Range");
550 G4double scaledKineticEnergy = KineticEnergy*t->theMassRatio;
554 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
556 Range = std::sqrt(scaledKineticEnergy/t->theLowestKineticEnergy)*
557 (*rangeTable)(materialIndex)->GetValue(
558 t->theLowestKineticEnergy,isOut);
560 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
562 Range = (*rangeTable)(materialIndex)->GetValue(
563 t->theHighestKineticEnergy,isOut)+
564 (scaledKineticEnergy-t->theHighestKineticEnergy)/
565 (*dEdxTable)(materialIndex)->GetValue(
566 t->theHighestKineticEnergy,isOut);
570 Range = (*rangeTable)(materialIndex)->GetValue(
571 scaledKineticEnergy,isOut);
575 return Range/(Chargesquare*t->theMassRatio);
591 *t= GetTables(aParticle);
600 if (!inverseRangeTable) {
601 ParticleHaveNoLoss(aParticle,
"InverseRange");
605 G4double scaledrange,scaledKineticEnergy ;
610 if(materialIndex != oldIndex)
612 oldIndex = materialIndex ;
613 rmin = (*inverseRangeTable)(materialIndex)->
614 GetLowEdgeEnergy(0) ;
615 rmax = (*inverseRangeTable)(materialIndex)->
616 GetLowEdgeEnergy(t->theNumberOfBins-2) ;
617 Thigh = (*inverseRangeTable)(materialIndex)->
618 GetValue(rmax,isOut) ;
621 scaledrange = range*Chargesquare*t->theMassRatio ;
623 if(scaledrange < rmin)
625 scaledKineticEnergy = t->theLowestKineticEnergy*
626 scaledrange*scaledrange/(rmin*rmin) ;
630 if(scaledrange < rmax)
632 scaledKineticEnergy = (*inverseRangeTable)(materialIndex)->
633 GetValue( scaledrange,isOut) ;
637 scaledKineticEnergy = Thigh +
639 (*dEdxTable)(materialIndex)->
640 GetValue(Thigh,isOut) ;
644 return scaledKineticEnergy/t->theMassRatio ;
659 *t= GetTables(aParticle);
668 ParticleHaveNoLoss(aParticle,
"dEdx");
673 G4double scaledKineticEnergy = KineticEnergy*t->theMassRatio;
677 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
679 dEdx = std::sqrt(scaledKineticEnergy/t->theLowestKineticEnergy)
680 *(*dEdxTable)(materialIndex)->GetValue(
681 t->theLowestKineticEnergy,isOut);
683 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
685 dEdx = (*dEdxTable)(materialIndex)->GetValue(
686 t->theHighestKineticEnergy,isOut);
690 dEdx = (*dEdxTable)(materialIndex)->GetValue(
691 scaledKineticEnergy,isOut) ;
695 return dEdx*Chargesquare;
710 *t= GetTables(aParticle);
720 ParticleHaveNoLoss(aParticle,
"Range");
725 G4double Thighr = t->theHighestKineticEnergy*t->theLowestKineticEnergy/
726 (*rangeTable)(materialIndex)->
727 GetLowEdgeEnergy(1) ;
729 G4double scaledKineticEnergy = KineticEnergy*t->theMassRatio;
733 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
735 Range = std::sqrt(scaledKineticEnergy/t->theLowestKineticEnergy)*
736 (*rangeTable)(materialIndex)->GetValue(
737 t->theLowestKineticEnergy,isOut);
739 }
else if (scaledKineticEnergy>Thighr) {
741 Range = (*rangeTable)(materialIndex)->GetValue(
743 (scaledKineticEnergy-Thighr)/
744 (*dEdxTable)(materialIndex)->GetValue(
749 Range = (*rangeTable)(materialIndex)->GetValue(
750 scaledKineticEnergy,isOut) ;
754 return Range/(Chargesquare*t->theMassRatio);
769 *t= GetTables(aParticle);
780 else ParticleHaveNoLoss(aParticle,
"dEdx");
785 G4double scaledKineticEnergy = KineticEnergy*t->theMassRatio;
789 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
791 dEdx =(*dEdxTable)(materialIndex)->GetValue(
792 t->theLowestKineticEnergy,isOut)
793 *std::sqrt(scaledKineticEnergy/t->theLowestKineticEnergy);
795 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
797 dEdx = (*dEdxTable)(materialIndex)->GetValue(
798 t->theHighestKineticEnergy,isOut);
802 dEdx = (*dEdxTable)(materialIndex)->GetValue(
803 scaledKineticEnergy,isOut);
807 return dEdx*Chargesquare;
822 *t= GetTables(aParticle);
838 G4double scaledKineticEnergy = KineticEnergy*t->theMassRatio;
842 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
844 Range = std::sqrt(scaledKineticEnergy/t->theLowestKineticEnergy)*
845 (*rangeTable)(materialIndex)->GetValue(
846 t->theLowestKineticEnergy,isOut);
848 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
850 Range = (*rangeTable)(materialIndex)->GetValue(
851 t->theHighestKineticEnergy,isOut)+
852 (scaledKineticEnergy-t->theHighestKineticEnergy)/
853 (*dEdxTable)(materialIndex)->GetValue(
854 t->theHighestKineticEnergy,isOut);
858 Range = (*rangeTable)(materialIndex)->GetValue(
859 scaledKineticEnergy,isOut);
863 return Range/(Chargesquare*t->theMassRatio);
879 *t= GetTables(aParticle);
889 if (!inverseRangeTable) {
895 G4double scaledrange,scaledKineticEnergy ;
900 if(materialIndex != oldIndex)
902 oldIndex = materialIndex ;
903 rmin = (*inverseRangeTable)(materialIndex)->
904 GetLowEdgeEnergy(0) ;
905 rmax = (*inverseRangeTable)(materialIndex)->
906 GetLowEdgeEnergy(t->theNumberOfBins-2) ;
907 Thigh = (*inverseRangeTable)(materialIndex)->
908 GetValue(rmax,isOut) ;
911 scaledrange = range*Chargesquare*t->theMassRatio ;
913 if(scaledrange < rmin)
915 scaledKineticEnergy = t->theLowestKineticEnergy*
916 scaledrange*scaledrange/(rmin*rmin) ;
920 if(scaledrange < rmax)
922 scaledKineticEnergy = (*inverseRangeTable)(materialIndex)->
923 GetValue( scaledrange,isOut) ;
927 scaledKineticEnergy = Thigh +
929 (*dEdxTable)(materialIndex)->
930 GetValue(Thigh,isOut) ;
934 return scaledKineticEnergy/t->theMassRatio ;
948 *t= GetTables(aParticle);
960 G4double scaledKineticEnergy = KineticEnergy*t->theMassRatio;
964 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
966 dEdx = std::sqrt(scaledKineticEnergy/t->theLowestKineticEnergy)
967 *(*dEdxTable)(materialIndex)->GetValue(
968 t->theLowestKineticEnergy,isOut);
970 }
else if (scaledKineticEnergy>t->theHighestKineticEnergy) {
972 dEdx = (*dEdxTable)(materialIndex)->GetValue(
973 t->theHighestKineticEnergy,isOut);
977 dEdx = (*dEdxTable)(materialIndex)->GetValue(
978 scaledKineticEnergy,isOut) ;
982 return dEdx*Chargesquare;
996 *t= GetTables(aParticle);
1005 if ( !dEdxTable || !rangeTable)
1010 G4double Thighr = t->theHighestKineticEnergy*t->theLowestKineticEnergy/
1011 (*rangeTable)(materialIndex)->
1012 GetLowEdgeEnergy(1) ;
1014 G4double scaledKineticEnergy = KineticEnergy*t->theMassRatio;
1018 if (scaledKineticEnergy<t->theLowestKineticEnergy) {
1020 Range = std::sqrt(scaledKineticEnergy/t->theLowestKineticEnergy)*
1021 (*rangeTable)(materialIndex)->GetValue(
1022 t->theLowestKineticEnergy,isOut);
1024 }
else if (scaledKineticEnergy>Thighr) {
1026 Range = (*rangeTable)(materialIndex)->GetValue(
1028 (scaledKineticEnergy-Thighr)/
1029 (*dEdxTable)(materialIndex)->GetValue(
1034 Range = (*rangeTable)(materialIndex)->GetValue(
1035 scaledKineticEnergy,isOut) ;
1039 return Range/(Chargesquare*t->theMassRatio);
1044void G4EnergyLossTables::CPRWarning()
1046 if (let_counter < let_max_num_warnings) {
1049 G4cout <<
"##### G4EnergyLossTable WARNING: The obsolete interface is used!" <<
G4endl;
1050 G4cout <<
"##### RESULTS ARE NOT GARANTEED!" <<
G4endl;
1051 G4cout <<
"##### Please, substitute G4Material by G4MaterialCutsCouple" <<
G4endl;
1052 G4cout <<
"##### Obsolete interface will be removed soon" <<
G4endl;
1056 }
else if (let_counter == let_max_num_warnings) {
1058 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)
G4double GetPDGCharge() const