11#include " AtELossCATIMA.h"
22
33#include < FairLogger.h>
4+ namespace AtTools {
45
5- AtTools:: AtELossCATIMA::AtELossCATIMA (double density, std::vector<std::tuple<int , int , int >> materialComponents)
6+ AtELossCATIMA::AtELossCATIMA (double density, std::vector<std::tuple<int , int , int >> materialComponents)
67 : AtELossModel(density)
78{
8- fMaterial = std::make_unique<catima::Material>();
9-
10- for (auto materialComponent : materialComponents)
11- fMaterial ->add_element (std::get<0 >(materialComponent), std::get<1 >(materialComponent),
12- std::get<2 >(materialComponent));
9+ SetMaterial (materialComponents);
1310}
1411
15- double AtTools:: AtELossCATIMA::GetdEdx (double energy) const
12+ double AtELossCATIMA::GetdEdx (double energy) const
1613{
1714 if (fProjectile == nullptr ) {
1815 LOG (warning)
1916 << " Warning in AtTools::AtELossCATIMA::GetdEdx : The projectile was not set! GetdEdx will return 0!" ;
2017 return 0 ;
2118 }
2219
23- if (fProjectileMassUma <= 0 ) {
20+ if (fProjectileMassAmu <= 0 ) {
2421 LOG (error) << " Error in AtTools::AtELossCATIMA::GetdEdx : The projectile's mass in umas can not be <= 0! "
2522 " GetdEdx will return 0!" ;
2623 return 0 ;
2724 }
2825
29- catima::Result result = catima::calculate (*fProjectile , *fMaterial , energy / fProjectileMassUma );
30- double dEdx = result.dEdxi * fDensity ;
31- return dEdx;
26+ catima::Result result = catima::calculate (*fProjectile , *fMaterial , energy / fProjectileMassAmu );
27+ double dEdx = result.dEdxi * fDensity ; // MeV/cm
28+ return dEdx / 10.0 ; // convert to MeV/mm
3229}
3330
34- double AtTools:: AtELossCATIMA::GetRange (double energyIni, double energyFin) const
31+ double AtELossCATIMA::GetRange (double energyIni, double energyFin) const
3532{
3633 if (energyFin < 0 ) {
3734 LOG (warning) << " Warning in AtTools::AtELossCATIMA::GetRange : The final energy was set to a negative value! "
@@ -40,14 +37,14 @@ double AtTools::AtELossCATIMA::GetRange(double energyIni, double energyFin) cons
4037 }
4138
4239 if (energyFin == 0 ) {
43- fProjectile ->T = energyIni / fProjectileMassUma ;
40+ fProjectile ->T = energyIni / fProjectileMassAmu ;
4441 return catima::range (*fProjectile , *fMaterial ) / fDensity * 10 .;
4542 }
4643
4744 double remainingEnergy{energyIni};
4845 double range{0 };
4946 while (remainingEnergy > energyFin) {
50- catima::Result result = catima::calculate (*fProjectile , *fMaterial , remainingEnergy / fProjectileMassUma );
47+ catima::Result result = catima::calculate (*fProjectile , *fMaterial , remainingEnergy / fProjectileMassAmu );
5148 double dEdx = result.dEdxi * fDensity ;
5249 double DE = dEdx * fRangeStepSize / 10 .;
5350
@@ -63,12 +60,12 @@ double AtTools::AtELossCATIMA::GetRange(double energyIni, double energyFin) cons
6360 return range;
6461}
6562
66- double AtTools:: AtELossCATIMA::GetEnergy (double energyIni, double distance) const
63+ double AtELossCATIMA::GetEnergy (double energyIni, double distance) const
6764{
6865 double remainingEnergy{energyIni};
6966 double range{0 };
7067 while (range < distance) {
71- catima::Result result = catima::calculate (*fProjectile , *fMaterial , remainingEnergy / fProjectileMassUma );
68+ catima::Result result = catima::calculate (*fProjectile , *fMaterial , remainingEnergy / fProjectileMassAmu );
7269 double dEdx = result.dEdxi * fDensity ;
7370 double DE{};
7471
@@ -86,9 +83,55 @@ double AtTools::AtELossCATIMA::GetEnergy(double energyIni, double distance) cons
8683
8784 return remainingEnergy;
8885}
86+ double AtELossCATIMA::GetRangeVariance (double energy) const
87+ {
88+ if (fProjectile == nullptr || fMaterial == nullptr ) {
89+ LOG (error) << " Projectile or material not set. Range variance is 0." ;
90+ return 0 ;
91+ }
92+ auto range_var =
93+ catima::range_variance (*fProjectile , energy / fProjectileMassAmu , *fMaterial ); // range var in (g/cm^2)^2
94+ LOG (debug) << " Range variance in (g/cm^2)^2: " << range_var << " for energy: " << energy / fProjectileMassAmu
95+ << " MeV/u" ;
96+ range_var /= fDensity * fDensity ; // convert to (cm)^2
97+ LOG (debug) << " Range variance in (cm)^2: " << range_var << " for energy: " << energy / fProjectileMassAmu
98+ << " MeV/u" ;
99+ return range_var * 100 ; // convert to mm^2
100+ }
101+
102+ double AtELossCATIMA::GetElossStraggling (double energyIni, double energyFin) const
103+ {
104+ if (fProjectile == nullptr || fMaterial == nullptr ) {
105+ LOG (error) << " Projectile or material not set." ;
106+ return 0 ;
107+ }
108+ if (energyFin > energyIni) {
109+ LOG (error) << " Final energy must be less than initial energy!" ;
110+ return 0 ;
111+ }
112+ auto energy_strag = catima::energy_straggling_from_E (*fProjectile , energyIni / fProjectileMassAmu ,
113+ energyFin / fProjectileMassAmu , *fMaterial );
114+ return energy_strag;
115+ }
116+ double AtELossCATIMA::GetdEdxStraggling (double energyIni, double energyFin) const
117+ {
118+ if (fProjectile == nullptr || fMaterial == nullptr ) {
119+ LOG (error) << " Projectile or material not set. dEdx straggling is 0." ;
120+ return 0 ;
121+ }
122+ auto dedx_min = GetdEdx (energyIni);
123+ auto dedx_max = GetdEdx (energyFin);
124+ if (std::abs (dedx_min - dedx_max) / dedx_min > 0.01 ) {
125+ LOG (warning) << " From " << energyIni << " to " << energyFin
126+ << " MeV the dEdx is not constant. dEdx straggling calculation is unreliable." ;
127+ }
128+ auto dE_st = GetElossStraggling (energyIni, energyFin);
129+ auto factor = dE_st / (energyIni - energyFin);
130+ return factor * dedx_min;
131+ }
89132
90133std::vector<std::pair<double , double >>
91- AtTools:: AtELossCATIMA::GetBraggCurve (double energy, double rangeStepSize, double totalFractionELoss) const
134+ AtELossCATIMA::GetBraggCurve (double energy, double rangeStepSize, double totalFractionELoss) const
92135{
93136 if (rangeStepSize == 0 )
94137 return GetBraggCurve (energy, fRangeStepSize , totalFractionELoss);
@@ -99,7 +142,7 @@ AtTools::AtELossCATIMA::GetBraggCurve(double energy, double rangeStepSize, doubl
99142 double range{};
100143 while (remainingEnergy / energy > totalFractionELoss) {
101144
102- catima::Result result = catima::calculate (*fProjectile , *fMaterial , remainingEnergy / fProjectileMassUma );
145+ catima::Result result = catima::calculate (*fProjectile , *fMaterial , remainingEnergy / fProjectileMassAmu );
103146 double dEdx = result.dEdxi * fDensity ;
104147 braggCurve.push_back (std::make_pair (dEdx, range));
105148
@@ -113,3 +156,14 @@ AtTools::AtELossCATIMA::GetBraggCurve(double energy, double rangeStepSize, doubl
113156
114157 return braggCurve;
115158}
159+
160+ void AtELossCATIMA::SetMaterial (std::vector<std::tuple<int , int , int >> materialComponents)
161+ {
162+ fMaterial = std::make_unique<catima::Material>();
163+ for (const auto &materialComponent : materialComponents) {
164+ fMaterial ->add_element (std::get<0 >(materialComponent), std::get<1 >(materialComponent),
165+ std::get<2 >(materialComponent));
166+ }
167+ }
168+
169+ } // namespace AtTools
0 commit comments