KaliVeda
Toolkit for HIC analysis
KVMaterialStack.cpp
1 #include "KVMaterialStack.h"
2 
4 
5 
6 
9 KVMaterialStack::KVMaterialStack(const KVDetector* D, double incidence)
10  : KVBase(),
11  fDetector(D),
12  fELossF("ELossActive", this, &KVMaterialStack::ELossActive, 0., 1.e+04, 2, "KVMaterialStack", "ELossActive", TF1::EAddToList::kNo),
13  fEResF("ERes", this, &KVMaterialStack::EResDet, 0., 1.e+04, 2, "KVMaterialStack", "EResDet", TF1::EAddToList::kNo),
14  fmaxELossF("maxELoss", this, &KVMaterialStack::MaxELossActive, 0., 90., 2, "KVMaterialStack", "MaxELossActive", TF1::EAddToList::kNo)
15 {
16  // Copy all materials to stack, adjust thicknesses according to incidence angle
17 
18  fELossF.SetNpx(500);
19  fEResF.SetNpx(500);
20  fmaxELossF.SetNpx(500);
21 
22  TIter next(D->GetListOfAbsorbers());
23  KVMaterial* mat;
24  auto active = D->GetActiveLayer();
25  int layer = 0;
26  while ((mat = (KVMaterial*)next())) {
27  if (mat == active) fActiveLayer = layer;
28  fAbsorbers.push_back(*mat);
29  fLayThick.push_back(mat->GetThickness());
30  ++layer;
31  }
32 }
33 
34 
35 
37 
39 {
42  fELossF.SetTitle(Form("Energy loss [MeV] in detector %s for Z=%d A=%d", fDetector->GetName(), Z, A));
43  return fELossF;
44 }
45 
46 
47 
49 
51 {
54  fEResF.SetTitle(Form("Residual energy [MeV] after detector %s for Z=%d A=%d", fDetector->GetName(), Z, A));
55  return fEResF;
56 }
57 
58 
59 
61 
63 {
65  return fmaxELossF;
66 }
67 
68 
69 
77 
79 {
80  // Calculates energy loss (in MeV) in active layer of stack,
81  // taking into account preceding layers
82  //
83  // \param[in] x[0] is incident energy in MeV
84  // \param[in] par[0] Z of ion
85  // \param[in] par[1] A of ion
86 
87  Double_t e = x[0];
88  int layer = 0;
89  if (fActiveLayer > 0) {
90  for (auto& mat : fAbsorbers) {
91  e = mat.GetERes(par[0], par[1], e, fLayThick[layer] / fIncAngleCosine);
92  if (e <= 0.)
93  return 0.; // return 0 if particle stops in layers before active layer
94  ++layer;
95  if (layer == fActiveLayer) break;
96  }
97  }
98  //calculate energy loss in active layer
99  return fAbsorbers[fActiveLayer].GetDeltaE(par[0], par[1], e, fLayThick[layer] / fIncAngleCosine);
100 }
101 
102 
103 
111 
113 {
114  // Calculates maximum energy loss (in MeV) in active layer of stack,
115  // taking into account preceding layers
116  //
117  // \param[in] x[0] is incident angle [deg] of particle measured wrt normal to entrance window
118  // \param[in] par[0] Z of ion
119  // \param[in] par[1] A of ion
120 
121  Double_t psi = x[0];
122  auto psi_sav = fIncAngle;
123  SetIncidenceAngle(psi);
124  auto demax = GetELossFunction(par[0], par[1]).GetMaximum();
125  SetIncidenceAngle(psi_sav);
126  return demax;
127 }
128 
129 
130 
139 
141 {
142  // Calculates residual energy (in MeV) of particle after traversing all layers of detector.
143  //
144  // \warning Returned value is -1000 if particle stops in one of the layers of the detector.
145  //
146  // \param[in] x[0] is incident energy in MeV
147  // \param[in] par[0] Z of ion
148  // \param[in] par[1] A of ion
149 
150  Double_t e = x[0];
151  int layer = 0;
152  for (auto& mat : fAbsorbers) {
153  Double_t eres = mat.GetERes(par[0], par[1], e, fLayThick[layer] / fIncAngleCosine); //residual energy after layer
154  if (eres <= 0.)
155  return -1000.; // return -1000 if particle stops in layers before active layer
156  e = eres;
157  ++layer;
158  }
159  return e;
160 }
161 
162 
163 
168 
170 {
171  // Calculate incident energy of nucleus from residual energy.
172  //
173  // \warning Returns -1 if Eres is out of defined range of values
174 
175  if (Z < 1 || Eres <= 0.) return 0.;
176  KVBase::GetX_status status;
177  Double_t einc = KVBase::ProtectedGetX(&GetEResFunction(Z, A), Eres, status);
179  // problem with inversion - value out of defined range of function
180  return -1;
181  }
182  return einc;
183 }
184 
185 
186 
206 
208 {
209  // Returns incident energy corresponding to energy loss delta_e in active layer for a given nucleus.
210  //
211  // By default the solution corresponding to the highest incident energy is returned
212  // This is the solution found for Einc greater than the maximum of the dE(Einc) curve.
213  // If you want the low energy solution set SolType = KVIonRangeTable::kEmin.
214  //
215  // \warning calculating the incident energy of a particle using only the dE in a detector
216  // is ambiguous, as in general (and especially for very heavy ions) the maximum of the dE
217  // curve occurs for Einc greater than the punch-through energy, therefore it is not always
218  // true to assume that if the particle does not stop in the detector the required solution
219  // is that for type=KVIonRangeTable::kEmax. For a range of energies between punch-through
220  // and dE_max, the required solution is still that for type=KVIonRangeTable::kEmin.
221  // If the residual energy of the particle is unknown, there is no way to know which is the
222  // correct solution.
223  //
224  // \warning If the given energy loss in the active layer is greater than the maximum theoretical dE
225  // for given Z & A, (dE > GetMaxDeltaE(Z,A)) then we return a NEGATIVE incident energy
226  // corresponding to the maximum, GetEIncOfMaxDeltaE(Z,A)
227 
228  if (Z < 1) return 0.;
229 
230  Double_t DE = delta_e;
231 
232  // If the given energy loss in the active layer is greater than the maximum theoretical dE
233  // for given Z & A, (dE > GetMaxDeltaE(Z,A)) then we return a NEGATIVE incident energy
234  // corresponding to the maximum, GetEIncOfMaxDeltaE(Z,A)
235  if (DE > GetMaxDeltaE(Z, A)) {
236  return -GetEIncOfMaxDeltaE(Z, A);
237  }
238 
239  TF1* dE = &GetELossFunction(Z, A);
240  Double_t e1, e2;
241  dE->GetRange(e1, e2);
242  switch (type) {
243  case KVMaterial::SolType::kEmin:
244  e2 = GetEIncOfMaxDeltaE(Z, A);
245  break;
246  case KVMaterial::SolType::kEmax:
247  e1 = GetEIncOfMaxDeltaE(Z, A);
248  break;
249  }
250  KVBase::GetX_status status;
251  Double_t EINC = ProtectedGetX(dE, DE, status, e1, e2);
253  return -EINC;
254  }
255  return EINC;
256 }
257 
258 
259 
264 
266 {
267  // Returns residual energy of given nucleus after the detector.
268  //
269  // Returns 0 if Einc<=0
270 
271  if (Einc <= 0.) return 0.;
272  Double_t eres = GetEResFunction(Z, A).Eval(Einc);
273  // Eres function returns -1000 when particle stops in detector,
274  // in order for function inversion (GetEIncFromEres) to work
275  if (eres < 0.) eres = 0.;
276  return eres;
277 }
278 
279 
280 
284 
286 {
287  // Returns calculated total energy loss of ion in ALL layers of the detector.
288  // This is just (Einc - GetERes(Z,A,Einc))
289 
290  return Einc - GetERes(Z, A, Einc);
291 }
292 
293 
294 
297 
299 {
300  // Returns energy loss of given nucleus in the active layer of the detector.
301 
302  return GetELossFunction(Z, A).Eval(Einc);
303 }
304 
305 
int Int_t
#define e(i)
double Double_t
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
char * Form(const char *fmt,...)
Base class for KaliVeda framework.
Definition: KVBase.h:140
GetX_status
Definition: KVBase.h:321
static Double_t ProtectedGetX(const TF1 *func, Double_t val, GetX_status &status, std::optional< Double_t > xmin={}, std::optional< Double_t > xmax={})
Definition: KVBase.cpp:1622
Base class for detector geometry description, interface to energy-loss calculations.
Definition: KVDetector.h:173
virtual Double_t GetSmallestEmaxValid(Int_t Z, Int_t A) const
A stack of materials in which successive energy losses of charged particles can be calculated ,...
Double_t GetIncidentEnergyFromERes(Int_t Z, Int_t A, Double_t Eres)
std::vector< KVMaterial > fAbsorbers
TF1 & GetEResFunction(Int_t Z, Int_t A)
Double_t GetEIncOfMaxDeltaE(Int_t Z, Int_t A)
Double_t GetERes(Int_t Z, Int_t A, Double_t Einc)
Double_t EResDet(Double_t *x, Double_t *par)
Double_t fIncAngleCosine
TF1 & GetELossFunction(Int_t Z, Int_t A)
TF1 & GetMaxELossFunction(Int_t Z, Int_t A)
Double_t ELossActive(Double_t *x, Double_t *par)
Double_t GetIncidentEnergy(Int_t Z, Int_t A, Double_t delta_e, enum KVMaterial::SolType type=KVMaterial::SolType::kEmax)
std::vector< double > fLayThick
layer thicknesses in cm
Double_t GetTotalDeltaE(Int_t Z, Int_t A, Double_t Einc)
Double_t MaxELossActive(Double_t *x, Double_t *par)
void SetIncidenceAngle(double psi)
Double_t GetDeltaE(Int_t Z, Int_t A, Double_t Einc)
Returns energy loss of given nucleus in the active layer of the detector.
const KVDetector * fDetector
Double_t GetMaxDeltaE(Int_t Z, Int_t A)
Description of physical materials used to construct detectors & targets; interface to range tables.
Definition: KVMaterial.h:115
virtual Double_t GetThickness() const
Definition: KVMaterial.cpp:537
virtual KVMaterial * GetActiveLayer() const
Definition: KVMaterial.h:203
virtual void SetRange(Double_t xmin, Double_t xmax)
void SetTitle(const char *title="") override
virtual void GetRange(Double_t &xmin, Double_t &xmax) const
virtual void SetParameters(const Double_t *params)
virtual Double_t Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const
virtual Double_t GetMaximum(Double_t xmin=0, Double_t xmax=0, Double_t epsilon=1.E-10, Int_t maxiter=100, Bool_t logx=false) const
const char * GetName() const override
Double_t x[n]
ClassImp(TPyArg)