KaliVeda
Toolkit for HIC analysis
KVMaterial.cpp
1 /***************************************************************************
2  kvmaterial.cpp - description
3  -------------------
4  begin : Thu May 16 2002
5  copyright : (C) 2002 by J.D. Frankland
6  email : frankland@ganil.fr
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "KVMaterial.h"
19 #include "KVNucleus.h"
20 #include "TEnv.h"
21 #include "TGeoMaterial.h"
22 #include "TGeoMedium.h"
23 #include "TGeoManager.h"
24 #include "KVIonRangeTable.h"
25 
26 #include <KVValueRange.h>
27 #include <TGraph.h>
28 
29 using namespace std;
30 
32 
34 
35 //___________________________________________________________________________________
36 
45 
47 {
48  // Default initialisations.
49  //
50  // No properties are set for the material (except standard temperature (19°C) and pressure (1 atm)).
51  //
52  // Default range table is generated if not already done. By default it is the VEDALOSS table implemented in KVedaLoss.
53  // You can change this by changing the value of environment variable `KVMaterial.IonRangeTable` or by calling
54  // static method ChangeRangeTable() before creating any materials.
55 
56  fELoss = 0;
57  SetName("");
58  SetTitle("");
59  fAmasr = 0;
60  fPressure = 1. * KVUnits::atm;
61  fTemp = 19.0;
62  // create default range table singleton if not already done
63  GetRangeTable();
64  fAbsorberVolume = nullptr;
65 }
66 
67 
68 //
69 
72 
74 {
75  //default ctor
76  init();
77 }
78 
79 
80 
83 
84 KVMaterial::KVMaterial(const Char_t* type, const Double_t thick)
85 {
86  // Create material with given type and linear thickness in cm.
87 
88  init();
89  SetMaterial(type);
90  SetThickness(thick);
91 }
92 
93 
94 
97 
98 KVMaterial::KVMaterial(Double_t area_density, const Char_t* type)
99 {
100  // Create material with given area density in \f$g/cm^{2}\f$ and given type
101 
102  init();
103  SetMaterial(type);
104  SetAreaDensity(area_density);
105 }
106 
107 
108 
119 
120 KVMaterial::KVMaterial(const Char_t* gas, const Double_t thick, const Double_t pressure, const Double_t temperature)
121 {
122  // Create gaseous material with given type, linear thickness in cm, pressure in Torr,
123  // and temperature in degrees C (default value 19°C).
124  //
125  // __Examples__
126  //~~~~{.cpp}
127  //KVMaterial("CF4", 15*KVUnits::cm, 1*KVUnits::atm); // 15cm of CF4 gas at 1atm and 19°C
128  //
129  //KVMaterial("C3F8", 50*KVUnits::mm, 30*KVUnits::mbar, 25); // 50mm of C3F8 at 30mbar and 25°C
130  //~~~~
131 
132  init();
133  SetMaterial(gas);
134  fPressure = pressure;
135  fTemp = temperature;
136  SetThickness(thick);
137 }
138 
139 
140 //
141 
144 
146 {
147  //Copy ctor
148  init();
149  obj.Copy(*this);
150 }
151 
152 
153 
157 
159 {
160  // Static method
161  // \returns pointer to currently used range table
162  if (!fIonRangeTable) {
163  fIonRangeTable = KVIonRangeTable::GetRangeTable(gEnv->GetValue("KVMaterial.IonRangeTable", "VEDALOSS"));
164  }
165  return fIonRangeTable;
166 }
167 
168 
169 
178 
180 {
181  // Changes the default range table used for energy loss calculations.
182  //
183  // The name must correspond to a Plugin defined for class KVIonRangeTable - see list given by
184  //
185  //~~~~{.cpp}
186  //KVBase::GetListOfPlugins("KVIonRangeTable")
187  //~~~~
188 
189  if (fIonRangeTable) delete fIonRangeTable;
191  if (!fIonRangeTable)
192  ::Error("KVMaterial::ChangeRangeTable", "No plugin %s defined for KVIonRangeTable", name);
193  return fIonRangeTable;
194 }
195 
196 
197 
216 
217 void KVMaterial::SetMaterial(const Char_t* mat_type)
218 {
219  // Intialise material of a given type, which must exist in the currently used range table.
220  //
221  // The list of available material types depends on the underlying range table: this list can be obtained or visualised like so:
222  // ~~~~{.cpp}
223  // KVMaterial::GetRangeTable()->Print(); // print infos on range table
224 
225  // KVMaterial::GetRangeTable()->GetListOfMaterials()->ls(); // retrieve pointer to list
226 
227  // OBJ: TObjArray TObjArray An array of objects : 0
228  // OBJ: TNamed Silicon Si : 0 at: 0x55a63a979390
229  // OBJ: TNamed Mylar Myl : 0 at: 0x55a63d6a95f0
230  // OBJ: TNamed Plastic NE102 : 0 at: 0x55a63d64ea90
231  // OBJ: TNamed Nickel Ni : 0 at: 0x55a63d6afb90
232  // OBJ: TNamed Octofluoropropane C3F8 : 0 at: 0x55a63a9f8e00
233  // etc. etc.
234  // ~~~~
235  //
236  // For materials which are elements of the periodic table you can specify
237  // the isotope such as \c "64Ni", \c "13C", \c "natSn", etc. etc.
238 
239  init();
240  if (fIonRangeTable->IsMaterialKnown(mat_type)) {
243  return;
244  }
245  // probably dealing with an element with an isotopic or 'natural' mass (i.e. "124Sn" or "natSn")
246  TString iso_name(mat_type);
247  auto iso_mass = KVNucleus::IsMassGiven(iso_name);
248  if (iso_mass < 0) {
249  // Not recognised as an element
250  KVError::Warning(this, "SetMaterial",
251  "Called for material '%s' which is unknown in current range table %s. Energy loss & range calculations impossible.",
252  mat_type, fIonRangeTable->GetName());
253  return;
254  }
255  if (iso_mass == 0) {
256  if (iso_name.BeginsWith("nat")) iso_name.Remove(0, 3);
257  }
258  KVNucleus n(iso_name);
259  TString type = n.GetSymbol("EL");
260  if (iso_mass) SetMass(iso_mass);
263 }
264 
265 
266 
269 
270 KVMaterial::~KVMaterial()
271 {
272  //Destructor
273 }
274 
275 
276 
281 
283 {
284  //Define a specific isotopic mass for the material, e.g. for isotopically pure targets.
285  //
286  //For detectors, this changes the mass of the material composing the active layer (see KVDetector).
287 
288  if (GetActiveLayer()) {
290  return;
291  }
292  fAmasr = a;
293 }
294 
295 
296 
301 
303 {
304  //Returns atomic mass of material.
305  //
306  //For detectors, this is the mass of the material composing the active layer (see KVDetector).
307 
308  if (GetActiveLayer())
309  return GetActiveLayer()->GetMass();
311 }
312 
313 
314 
323 
325 {
326  //Returns kTRUE if a specific isotope has been chosen for the material
327  //using SetMass(), e.g.
328  // - for \f${}^{119}Sn\f$ this method returns kTRUE
329  // - for \f${}^{nat}Sn\f$ this method returns kFALSE
330  //
331  //For detectors, the material in question is that of the active layer (see KVDetector).
332  //\sa IsNat()
333  if (GetActiveLayer())
334  return GetActiveLayer()->IsIsotopic();
335  return (fAmasr != 0);
336 }
337 
338 
339 
348 
350 {
351  //Returns kFALSE if a specific isotope has been chosen for the material
352  //using SetMass() e.g.
353  // - for \f${}^{119}Sn\f$ this method returns kFALSE
354  // - for \f${}^{nat}Sn\f$ this method returns kTRUE
355  //
356  //For detectors, the material in question is that of the active layer (see KVDetector).
357  //\sa IsIsotopic()
358  if (GetActiveLayer())
359  return GetActiveLayer()->IsNat();
360  return (!IsIsotopic());
361 }
362 
363 
364 
365 
370 
372 {
373  // Returns kTRUE for gaseous material.
374  //
375  //For detectors, the material in question is that of the active layer (see KVDetector).
376 
377  if (GetActiveLayer())
378  return GetActiveLayer()->IsGas();
380 }
381 
382 
383 
384 
389 
391 {
392  //Returns atomic number of material.
393  //
394  //For detectors, the material in question is that of the active layer (see KVDetector).
395  if (GetActiveLayer())
396  return GetActiveLayer()->GetZ();
397  return fIonRangeTable->GetZ(GetType());
398 }
399 
400 
401 
402 
417 
419 {
420  // Returns density of material in \f$g/cm^{3}\f$.
421  //
422  //~~~~{.cpp}
423  //auto dens = mat.GetDensity()/(KVUnits::kg/KVUnits::litre); // in kg/litre
424  //~~~~
425  //
426  // \note For a gas, density is calculated from current pressure & temperature according to ideal gas law
427  // \f[
428  // \rho = \frac{pM}{RT}
429  // \f]
430  // with \f$M\f$ the mass of one mole of the gas, and \f$R\f$ the ideal gas constant.
431  //
432  //For detectors, the material in question is that of the active layer (see KVDetector).
433 
434  if (GetActiveLayer())
435  return GetActiveLayer()->GetDensity();
437  return fIonRangeTable->GetDensity(GetType());
438 }
439 
440 
441 
442 
458 
459 void KVMaterial::SetDensity(double dens)
460 {
461  // Change density of material to value given in \f$g/cm^{3}\f$.
462  //
463  // \warning This will change the density of the corresponding material in the energy loss/range
464  // table, it will therefore potentially affect all KVMaterial and KVDetector objects using
465  // the same material
466  //
467  // \note Has no effect for gases, for which density is calculated from current pressure & temperature according
468  // to the ideal gas law
469  //
470  // \note As the density is used primarily to calculate areal density from linear thickness (and vice versa),
471  // changing the density of a material whose area density has already been set will have no effect
472  // except to change the value returned by GetThickness().
473  //
474  //For detectors, the material in question is that of the active layer (see KVDetector).
475 
476  if (GetActiveLayer())
477  GetActiveLayer()->SetDensity(dens);
478  if(IsGas())
479  return;
481 }
482 
483 
484 
485 
498 
500 {
501  // Set the linear thickness of the material in cm, e.g.
502  //
503  //~~~~{.cpp}
504  //SetThickness( 30.*KVUnits::um ); set thickness to 30 microns
505  //~~~~
506  //
507  // \note What this method actually does is modify the areal density of the material,
508  // which is the only parameter that matters for using the energy loss/range tables.
509  // The result therefore depends on the material's density (see GetDensity()).
510  //
511  //For detectors, the material in question is that of the active layer (see KVDetector).
512 
513  if (GetActiveLayer()) {
515  return;
516  }
517  // recalculate area density
518  if (GetDensity() != 0)
519  fThick = t * GetDensity();
520  else
521  fThick = t;
522 
523 }
524 
525 
526 
527 
536 
538 {
539  // Returns the linear thickness of the material in cm.
540  // Use KVUnits to translate from one unit to another, e.g.
541  //~~~~{.cpp}
542  //auto micro_thick = mat.GetThickness()/KVUnits::um; thickness in microns
543  //~~~~
544  //
545  //For detectors, the material in question is that of the active layer (see KVDetector).
546 
547  if (GetActiveLayer())
548  return GetActiveLayer()->GetThickness();
549  if (GetDensity() != 0)
550  return fThick / GetDensity();
551  else
552  return fThick;
553 }
554 
555 
556 
557 
572 
573 void KVMaterial::SetAreaDensity(Double_t dens /* g/cm**2 */)
574 {
575  // Set area density in \f$g/cm^{2}\f$.
576  //
577  // For solids, changing the area density implies also a change in the (linear) thickness of the material.
578  //
579  // For gases, the density depends on temperature and pressure - see GetDensity(). This method
580  // leaves temperature and pressure unchanged, therefore for gases also this
581  // method will effectively modify the linear dimension of the gas cell.
582  //
583  //~~~~{.cpp}
584  //mat.SetAreaDensity(500*KVUnits::ug); // set density in microgram/cm2
585  //~~~~
586  //
587  //For detectors, the material in question is that of the active layer (see KVDetector).
588 
589  if (GetActiveLayer())
591  fThick = dens;
592 }
593 
594 
595 
596 
605 
607 {
608  // Return area density of material in \f$g/cm^{2}\f$
609  //
610  //~~~~{.cpp}
611  //auto dens_mgcm2 = mat.GetAreaDensity()/KVUnits::mg; // in mg/cm2
612  //~~~~
613  //
614  //For detectors, the material in question is that of the active layer (see KVDetector).
615 
616  if (GetActiveLayer()) return GetActiveLayer()->GetAreaDensity();
617  return fThick;
618 }
619 
620 
621 
622 
632 
634 {
635  // Set the pressure of a gaseous material (default unit: torr).
636  // \note The linear dimension (thickness) is kept constant, the density and areal density change.
637  //
638  //~~~~{.cpp}
639  //mat.SetPressure(50*KVUnits::mbar); // set pressure to 50mbar
640  //~~~~
641  //
642  //For detectors, the material in question is that of the active layer (see KVDetector).
643 
644  if (!IsGas()) return;
645  if (GetActiveLayer()) {
647  return;
648  }
649  // get current linear dimension of absorber
650  Double_t e = GetThickness();
651  fPressure = p;
652  // change area density to keep linear dimension constant
653  SetThickness(e);
654 }
655 
656 
657 
658 
659 
669 
671 {
672  // Returns the pressure of a gas (default unit: torr).
673  // \note If the material is not a gas - see IsGas() - value is zero.
674  //
675  //~~~~{.cpp}
676  //auto press_mbar = mat.GetPressure()/KVUnits::mbar; // pressure in mbar
677  //~~~~
678  //
679  //For detectors, the material in question is that of the active layer (see KVDetector).
680 
681  if (!IsGas()) return 0.0;
682  if (GetActiveLayer())
683  return GetActiveLayer()->GetPressure();
684  return fPressure;
685 }
686 
687 
688 
689 
698 
700 {
701  // Set temperature of material in degrees celsius.
702  //
703  // This only has an effect on gaseous materials, and the resulting change in density
704  // changes the areal density of the absorber (because we keep the linear thickness fixed).
705  // \sa GetDensity()
706  //
707  //For detectors, the material in question is that of the active layer (see KVDetector).
708 
709  if (!IsGas()) return;
710  if (GetActiveLayer()) {
712  return;
713  }
714  // get current linear dimension of absorber
715  Double_t e = GetThickness();
716  fTemp = t;
717  // change area density to keep linear dimension constant
718  SetThickness(e);
719 }
720 
721 
722 
723 
724 
729 
731 {
732  //Returns temperature of material in degrees celsius (only gaseous materials).
733  //
734  //For detectors, the material in question is that of the active layer (see KVDetector).
735 
736  if (GetActiveLayer())
737  return GetActiveLayer()->GetTemperature();
738  return fTemp;
739 }
740 
741 
742 
743 
749 
751 {
752  //\param[in] norm vector normal to the material, oriented from the origin towards the material
753  //\param[in] direction direction of motion of an ion
754  //\returns effective linear thickness of absorber (in cm) as 'seen' in given direction, taking into
755  // account the arbitrary orientation of the normal to the material's surface
756 
757  TVector3 n = norm.Unit();
758  TVector3 d = direction.Unit();
759  //absolute value of scalar product, in case direction is opposite to normal
760  Double_t prod = TMath::Abs(n * d);
761  return GetThickness() / TMath::Max(prod, 1.e-03);
762 }
763 
764 
765 
766 
772 
774 {
775  //\param[in] norm vector normal to the material, oriented from the origin towards the material
776  //\param[in] direction direction of motion of an ion
777  //\returns effective area density of absorber in \f$g/cm^{2}\f$ as 'seen' in the given direction, taking into
778  // account the arbitrary orientation of the normal to the material's surface
779 
780  TVector3 n = norm.Unit();
781  TVector3 d = direction.Unit();
782  //absolute value of scalar product, in case direction is opposite to normal
783  Double_t prod = TMath::Abs(n * d);
784  return GetAreaDensity() / TMath::Max(prod, 1.e-03);
785 }
786 
787 
788 
791 
793 {
794  //Show information on this material
795  cout << "KVMaterial: " << GetName() << " (" << GetType() << ")" << endl;
797  cout << " Pressure " << GetPressure() << " torr" << endl;
798  cout << " Thickness " << KVMaterial::GetThickness() << " cm" << endl;
799  cout << " Area density " << KVMaterial::GetAreaDensity() << " g/cm**2" << endl;
800  cout << "-----------------------------------------------" << endl;
801  cout << " Z = " << GetZ() << " atomic mass = " << GetMass() << endl;
802  cout << " Density = " << GetDensity() << " g/cm**3" << endl;
803  cout << "-----------------------------------------------" << endl;
804 }
805 
806 
807 
808 
818 
820 {
821  //\param[in] kvp pointer to a KVNucleus object describing a charged ion
822  //\param[in] norm [optional] vector normal to the material, oriented from the origin towards the material
823  //
824  //\returns The energy loss \f$\Delta E\f$ in MeV of a charged particle impinging on the absorber
825  //
826  //If the unit normal vector is given, the effective thickness of the material 'seen' by the particle
827  //depending on the orientation of its direction of motion with respect to the absorber is used for the calculation,
828  //rather than the nominal thickness corresponding to ions impinging perpendicularly.
829 
830  Double_t thickness;
831  if (norm) {
832  TVector3 p = kvn->GetMomentum();
833  thickness = GetEffectiveThickness((*norm), p);
834  }
835  else
836  thickness = GetThickness();
837  Double_t E_loss =
838  fIonRangeTable->GetLinearDeltaEOfIon(GetType(), kvn->GetZ(), kvn->GetA(), kvn->GetKE(),
839  thickness, fAmasr, fTemp, fPressure);
840  return E_loss;
841 }
842 
843 
844 
845 
853 
855 {
856  // \param[in] kvn KVNucleus describing properties of incident ion (\f$Z,A\f$ and with kinetic energy \f$E_{res}\f$)
857  // \param[in] norm [optional] vector normal to the material, oriented from the origin towards the material.
858  // \returns incident energy of ion \f$E_{inc}\f$ [MeV] deduced from residual energy \f$E_{res}=E_{inc}-\Delta E\f$.
859  //
860  //If \a norm is given, the effective thickness of the material 'seen' by the particle
861  //depending on its direction of motion is used for the calculation.
862 
863  Double_t thickness;
864  if (norm) {
865  TVector3 p = kvn->GetMomentum();
866  thickness = GetEffectiveThickness((*norm), p);
867  }
868  else
869  thickness = GetThickness();
870  Double_t E_inc = fIonRangeTable->
871  GetLinearEIncFromEResOfIon(GetType(), kvn->GetZ(), kvn->GetA(), kvn->GetKE(),
872  thickness, fAmasr, fTemp, fPressure);
873  return E_inc;
874 }
875 
876 
877 
878 
885 
887 {
888  // \param[in] Z atomic number of incident ion
889  // \param[in] A mass number of incident ion
890  // \param[in] Einc kinetic energy of incident ion
891  // \param[in] dx if given, used as thickness (in cm) of absorber instead of current thickness
892  // \returns Energy lost \f$\Delta E\f$ [MeV] by an ion \f$Z, A\f$ impinging on the absorber with kinetic energy \f$E_{inc}\f$ [MeV]
893 
894  if (Z < 1) return 0.;
895  Double_t E_loss =
896  fIonRangeTable->GetLinearDeltaEOfIon(GetType(), Z, A, Einc, (dx > 0 ? dx : GetThickness()), fAmasr, fTemp, fPressure);
897 
898  return TMath::Max(E_loss, 0.);
899 }
900 
901 
902 
903 
916 
918 {
919  // \param[in] Z atomic number of incident ion
920  // \param[in] A mass number of incident ion
921  // \param[in] Einc kinetic energy of incident ion
922  // \returns range in [\f$g/cm^2\f$] in absorber for incident nucleus \f$Z,A\f$ with kinetic energy \f$E_{inc}\f$ [MeV]
923  //
924  // Different units can be used with KVUnits:
925  //~~~~{.cpp}
926  // KVMaterial si("Si");
927  // si.GetRange(2,4,13)/KVUnits::mg;
928  //(long double) 25.190011L // range in silicon in mg/cm2 of 13 MeV 4He particles
929  //~~~~
930 
931  if (Z < 1) return 0.;
932  Double_t R =
934  return R;
935 }
936 
937 
938 
939 
953 
955 {
956  // \param[in] Z atomic number of incident ion
957  // \param[in] A mass number of incident ion
958  // \param[in] Einc kinetic energy of incident ion
959  // \returns linear range in [cm] in absorber for incident nucleus \f$Z,A\f$
960  // with kinetic energy \f$E_{inc}\f$ [MeV]
961  //
962  // Different units can be used with KVUnits:
963  //~~~~{.cpp}
964  // KVMaterial si("Si");
965  // si.GetLinearRange(2,4,13)/KVUnits::um;
966  //(long double) 108.11164L // range in silicon in microns of 13 MeV 4He particles
967  //~~~~
968 
969  if (Z < 1) return 0.;
970  Double_t R =
972  return R;
973 }
974 
975 
976 
977 
1000 
1002 {
1003  // \param[in] Z atomic number of incident ion
1004  // \param[in] A mass number of incident ion
1005  // \param[in] Eres residual kinetic energy of ion after impinging on the absorber
1006  // \returns Incident kinetic energy \f$E_{inc}\f$ of an ion \f$Z, A\f$ with given \f$E_{res}=E_{inc}-\Delta E\f$ residual energy
1007  //
1008  //\b Example of use:
1009  //~~~~{.cpp}
1010  //KVMaterial si("Si", 300*KVUnits::um); // 300um silicon absorber
1011  //KVNucleus alpha("4He",30); // 30MeV/u alpha particle
1012  //
1013  //si.DetectParticle(&alpha); // particle is slowed by silicon
1014  //
1015  //si.GetEnergyLoss();
1016  //(double) 4.1371801 // energy lost by particle in silicon
1017  //
1018  //alpha.GetEnergy();
1019  //(double) 115.86282 // residual energy of alpha after silicon
1020  //
1021  //si.GetDeltaEFromERes(2,4,115.86282);
1022  //(double) 4.1371801 // energy loss calculated from residual energy
1023  //~~~~
1024 
1025  if (Z < 1) return 0.;
1026  Double_t E_loss = fIonRangeTable->
1027  GetLinearDeltaEFromEResOfIon(
1028  GetType(), Z, A, Eres, GetThickness(), fAmasr, fTemp, fPressure);
1029  return E_loss;
1030 }
1031 
1032 
1033 
1070 
1072 {
1073  // \returns Calculated residual kinetic energy \f$E_{res}\f$ [MeV] of a nucleus \f$Z,A\f$ after the absorber from
1074  // the energy loss \f$\Delta E\f$ in the absorber. If \a dE is given, it is used instead of the current energy loss.
1075  //
1076  // \param[in] Z,A atomic and mass number of nucleus
1077  // \param[in] dE [optional] energy loss of nucleus in absorber
1078  // \param[in] type
1079  // \parblock
1080  // Determine the type of solution to use. Possible values are:
1081  // \arg SolType::kEmax [default]: solution corresponding to the highest incident energy is returned.
1082  // This is the solution found for \f$E_{inc}\f$ above that of the maximum of the \f$\Delta E(E_{inc})\f$ curve.
1083  // \arg SolType::kEmin : low energy solution (\f$E_{inc}\f$ below maximum of the \f$\Delta E(E_{inc})\f$ curve).
1084  // \endparblock
1085  //
1086  //\b Example of use:
1087  //~~~~{.cpp}
1088  //KVMaterial si("Si", 300*KVUnits::um); // 300um silicon absorber
1089  //KVNucleus alpha("4He",30); // 30MeV/u alpha particle
1090  //
1091  //si.DetectParticle(&alpha); // particle is slowed by silicon
1092  //
1093  //si.GetEnergyLoss();
1094  //(double) 4.1371801 // energy lost by particle in silicon
1095  //
1096  //alpha.GetEnergy();
1097  //(double) 115.86282 // residual energy of alpha after silicon
1098  //
1099  //si.GetEResFromDeltaE(2,4);
1100  //(double) 115.86282 // residual energy calculated from energy loss
1101  //~~~~
1102  //
1103  // \note If the energy loss in the absorber is greater than the maximum theoretical \f$\Delta E\f$ - given by GetMaxDeltaE() - then we return
1104  // the residual energy corresponding to the maximum - given by GetEIncOfMaxDeltaE().
1105  //
1106  // \note For detectors (see KVDetector), \a dE is the energy loss \f$\Delta E\f$ only in the \b active layer, not the total
1107  // energy lost by the particle crossing the detector; because for detectors with inactive layers \f$E_{inc}\geq \Delta E + E_{res}\f$.
1108 
1109  Double_t EINC = GetIncidentEnergy(Z, A, dE, type);
1110  return GetERes(Z, A, EINC);
1111 }
1112 
1113 
1114 
1115 
1146 
1148 {
1149  //\returns Calculated incident energy [MeV] of nucleus \f$Z,A\f$ corresponding to energy loss \f$\Delta E\f$
1150  //in this absorber. If \a delta_e is given, it is used instead of the current energy loss in this absorber.
1151  //
1152  //\param[in] Z,A atomic and mass number of nucleus
1153  //\param[in] delta_e [optional] energy loss of nucleus in absorber \f$\Delta E\f$ [MeV]
1154  //\param[in] type
1155  //\parblock
1156  //Determine the type of solution to use. Possible values are:
1157  // \arg SolType::kEmax [default]: solution corresponding to the highest incident energy is returned.
1158  //This is the solution found for \f$E_{inc}\f$ above that of the maximum of the \f$\Delta E(E_{inc})\f$ curve.
1159  // \arg SolType::kEmin : low energy solution (\f$E_{inc}\f$ below maximum of the \f$\Delta E(E_{inc})\f$ curve).
1160  //\endparblock
1161  //
1162  //\b Example of use:
1163  //~~~~{.cpp}
1164  //KVMaterial si("Si", 300*KVUnits::um); // 300um silicon absorber
1165  //KVNucleus alpha("4He",30); // 30MeV/u alpha particle
1166  //
1167  //si.DetectParticle(&alpha); // particle is slowed by silicon
1168  //
1169  //si.GetEnergyLoss();
1170  //(double) 4.1371801 // energy lost by particle in silicon
1171  //
1172  //si.GetIncidentEnergy(2,4);
1173  //(double) 120.00000 // incident energy of alpha calculated from energy loss
1174  //~~~~
1175  //
1176  //\note If the energy loss in the absorber is greater than the maximum theoretical \f$\Delta E\f$ - given by GetMaxDeltaE() - then we return
1177  //the incident energy corresponding to the maximum - given by GetEIncOfMaxDeltaE().
1178 
1179  if (Z < 1) return 0.;
1180 
1181  Double_t DE = (delta_e > 0 ? delta_e : GetEnergyLoss());
1182 
1185 }
1186 
1187 
1188 
1189 
1213 
1215 {
1216  // \param[in] Z atomic number of incident ion
1217  // \param[in] A mass number of incident ion
1218  // \param[in] Einc kinetic energy of incident ion
1219  // \param[in] dx if given, used as thickness (in cm) of absorber instead of current thickness
1220  // \returns Residual energy \f$E_{res}=E_{inc}-\Delta E\f$ in MeV of an ion \f$Z, A\f$ after impinging on the absorber with kinetic energy \f$E_{inc}\f$
1221  //
1222  //\b Example of use:
1223  //~~~~{.cpp}
1224  //KVMaterial si("Si", 300*KVUnits::um); // 300um silicon absorber
1225  //KVNucleus alpha("4He",30); // 30MeV/u alpha particle
1226  //
1227  //si.DetectParticle(&alpha); // particle is slowed by silicon
1228  //
1229  //si.GetEnergyLoss();
1230  //(double) 4.1371801 // energy lost by particle in silicon
1231  //
1232  //alpha.GetEnergy();
1233  //(double) 115.86282 // residual energy of alpha after silicon
1234  //
1235  //si.GetERes(2,4,120.0);
1236  //(double) 115.86282 // residual energy calculated from incident energy
1237  //~~~~
1238 
1239  if (Z < 1) return 0.;
1240  if (IsGas() && GetPressure() == 0)
1241  return Einc;
1242 
1243  Double_t E_res =
1244  fIonRangeTable->GetLinearEResOfIon(GetType(), Z, A, Einc, (dx > 0 ? dx : GetThickness()), fAmasr, fTemp, fPressure);
1245 
1246  return E_res;
1247 }
1248 
1249 
1250 
1251 
1263 
1265 {
1266  //\param[in] kvp pointer to a KVNucleus object describing a charged ion
1267  //\param[in] norm [optional] vector normal to the material, oriented from the origin towards the material
1268  //
1269  //The energy loss \f$\Delta E\f$ of a charged particle traversing the absorber is calculated,
1270  //and the particle is slowed down by a corresponding amount
1271  //(the kinetic energy of the KVNucleus object passed as argument will be reduced by \f$\Delta E\f$, possibly to zero).
1272  //
1273  //If the unit normal vector is given, the effective thickness of the material 'seen' by the particle
1274  //depending on the orientation of its direction of motion with respect to the absorber is used for the calculation,
1275  //rather than the nominal thickness corresponding to ions impinging perpendicularly.
1276 
1277  kvp->SetIsDetected();//set flag to say that particle has been slowed down
1278  //If this is the first absorber that the particle crosses, we set a "reminder" of its
1279  //initial energy
1280  if (!kvp->GetPInitial())
1281  kvp->SetE0();
1282 
1283 #ifdef DBG_TRGT
1284  cout << "detectparticle in material " << GetType() << " of thickness "
1285  << GetThickness() << endl;
1286 #endif
1287  Double_t el = GetELostByParticle(kvp, norm);
1288  // set particle residual energy
1289  Double_t Eres = kvp->GetKE() - el;
1290  kvp->SetKE(Eres);
1291  // add to total of energy losses in absorber
1292  fELoss += el;
1293 }
1294 
1295 
1296 
1297 
1300 
1302 {
1303  // Reset absorber - set stored energy lost by particles in absorber to zero
1304  fELoss = 0.0;
1305 }
1306 
1307 
1308 
1311 
1312 void KVMaterial::Copy(TObject& obj) const
1313 {
1314  // Make a copy of this material object
1315  KVBase::Copy(obj);
1316  ((KVMaterial&) obj).SetMaterial(GetType());
1317  if (IsIsotopic())((KVMaterial&) obj).SetMass(fAmasr);
1318  ((KVMaterial&) obj).SetPressure(GetPressure());
1319  ((KVMaterial&) obj).SetTemperature(GetTemperature());
1320  ((KVMaterial&) obj).SetThickness(GetThickness());
1321 }
1322 
1323 
1324 
1325 
1330 
1332 {
1333  // \param[in] Z,A atomic & mass numbers of incident ion
1334  // \param[in] Eres residual energy of ion after absorber
1335  // \returns incident energy of ion \f$E_{inc}\f$ [MeV] deduced from residual energy \f$E_{res}=E_{inc}-\Delta E\f$.
1336  if (Z < 1) return 0.;
1337 
1338  return fIonRangeTable->
1339  GetLinearEIncFromEResOfIon(GetType(), Z, A, Eres, GetThickness(), fAmasr, fTemp, fPressure);
1340 }
1341 
1342 
1343 
1344 
1348 
1350 {
1351  //\param[in] Z,A atomic and mass number of impinging ion
1352  //\returns incident energy in MeV for which the \f$\Delta E\f$-\f$E\f$ curve has a maximum
1353 
1354  if (Z < 1) return 0.;
1355 
1356  return fIonRangeTable->
1357  GetLinearEIncOfMaxDeltaEOfIon(GetType(), Z, A, GetThickness(), fAmasr, fTemp, fPressure);
1358 }
1359 
1360 
1361 
1362 
1370 
1372 {
1373  //\returns The maximum possible energy loss \f$\Delta E\f$ of a nucleus in the absorber
1374  //\param[in] Z,A atomic and mass number of the nucleus
1375  //
1376  //\sa GetEIncOfMaxDeltaE()
1377  //
1378  //\note For detectors, this is the maximum energy loss in the active layer.
1379 
1380  if (GetActiveLayer()) return GetActiveLayer()->GetMaxDeltaE(Z, A);
1381 
1382  if (Z < 1) return 0.;
1383 
1384  return fIonRangeTable->
1385  GetLinearMaxDeltaEOfIon(GetType(), Z, A, GetThickness(), fAmasr, fTemp, fPressure);
1386 }
1387 
1388 
1389 
1390 
1411 
1413 {
1414  // By default, return pointer to TGeoMedium corresponding to this KVMaterial.
1415  //
1416  // \param[in] med_name [optional] if it corresponds to the name of an already existing
1417  // medium, we return a pointer to this medium, or a nullptr if it does not exist.
1418  //
1419  // `med_name = "Vacuum"` is a special case: if the "Vacuum" does not exist, we create it.
1420  //
1421  // Instance of geometry manager class TGeoManager must be created before calling this
1422  // method, otherwise nullptr will be returned.
1423  //
1424  // If the required TGeoMedium is not already available in the TGeoManager, we create
1425  // a new TGeoMedium corresponding to the properties of this KVMaterial.
1426  // The name of the TGeoMedium (and associated TGeoMaterial) is the name of the KVMaterial.
1427  //
1428  // \note For detectors, the material in question is that of the active layer (see KVDetector).
1429  //
1430  // \note for gaseous materials, the TGeoMedium/Material name is of the form gasname_pressure_temperature
1431  // e.g. C3F8_37.5_20.0 for C3F8 gas at 37.5 torr 20 degrees Celsius.
1432  // Each gas with different pressure/temperature has to have a separate TGeoMaterial/Medium (with different density).
1433 
1434  if (!gGeoManager) return nullptr;
1435 
1436  if (strcmp(med_name, "")) {
1437  TGeoMedium* gmed = gGeoManager->GetMedium(med_name);
1438  if (gmed) return gmed;
1439  else if (!strcmp(med_name, "Vacuum")) {
1440  // create material
1441  TGeoMaterial* gmat = new TGeoMaterial("Vacuum", 0, 0, 0);
1442  gmat->SetTitle("Vacuum");
1443  gmed = new TGeoMedium("Vacuum", 0, gmat);
1444  gmed->SetTitle("Vacuum");
1445  return gmed;
1446  }
1447  return nullptr;
1448  }
1449 
1450  // if object is a KVDetector, we return medium corresponding to the active layer
1451  if (GetActiveLayer()) return GetActiveLayer()->GetGeoMedium();
1452 
1453  // for gaseous materials, the TGeoMedium/Material name is of the form
1454  // gasname_pressure
1455  // e.g. C3F8_37.5 for C3F8 gas at 37.5 torr
1456  // each gas with different pressure has to have a separate TGeoMaterial/Medium
1457  TString medName;
1458  if (IsGas()) medName.Form("%s_%f_%f", GetName(), GetPressure(), GetTemperature());
1459  else medName = GetName();
1460 
1461  TGeoMedium* gmed = gGeoManager->GetMedium(medName);
1462 
1463  if (gmed) return gmed;
1464 
1465  TGeoMaterial* gmat = gGeoManager->GetMaterial(medName);
1466 
1467  if (!gmat) {
1468  // create material
1469  gmat = GetRangeTable()->GetTGeoMaterial(GetName());
1470  gmat->SetPressure(GetPressure());
1471  gmat->SetTemperature(GetTemperature());
1472  gmat->SetTransparency(0);
1473  gmat->SetName(medName);
1474  gmat->SetTitle(GetName());
1475  }
1476 
1477  // create medium
1478  static Int_t numed = 1; // static counter variable used to number media
1479  gmed = new TGeoMedium(medName, numed, gmat);
1480  numed += 1;
1481 
1482  return gmed;
1483 }
1484 
1485 
1486 
1493 
1495 {
1496  // \param[in] nuc definition of charged particle
1497  // \param[in] npts number of points to use
1498  // \param[in] Emin minimum incident energy \f$E\f$
1499  // \param[in] Emax maximum incident energy \f$E\f$
1500  // \returns KVDrawable<TGraph> with the \f$\Delta E\f$-\f$E\f$ curve for this material for a given charged particle
1501 
1502  auto g = new TGraph;
1503  KVValueRange<Double_t> R(Emin, Emax);
1504  for (int i = 0; i < npts; ++i) {
1505  auto E = R.ValueIofN(i, npts);
1506  g->SetPoint(i, E, GetDeltaE(nuc.GetZ(), nuc.GetA(), E));
1507  }
1508  return g;
1509 }
1510 
1511 
1512 
1519 
1521 {
1522  //\param[in] Z,A atomic & mass numbers of ion
1523  // \returns maximum incident energy [MeV] for which range tables are valid
1524  // for this material and ion with \f$Z,A\f$.
1525  //
1526  //\note For detectors, the limit of validity for the material composing the active layer is returned (see KVDetector).
1527  if (GetActiveLayer()) return GetActiveLayer()->GetEmaxValid(Z, A);
1528  return fIonRangeTable->GetEmaxValid(GetType(), Z, A);
1529 }
1530 
1531 
1532 
1537 
1539 {
1540  //\param[in] Z,A atomic & mass numbers of ion
1541  // \returns incident energy \f$E_{inc}\f$ [MeV] for which ion \f$Z,A\f$ has a range equal to the
1542  // thickness of this absorber (see GetRange(), GetLinearRange()).
1543 
1545 }
1546 
1547 
int Int_t
#define d(i)
#define e(i)
bool Bool_t
char Char_t
double Double_t
const char Option_t
R__EXTERN TEnv * gEnv
winID h TVirtualViewer3D TVirtualGLPainter p
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 g
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 name[80]
R__EXTERN TGeoManager * gGeoManager
Base class for KaliVeda framework.
Definition: KVBase.h:140
virtual const Char_t * GetType() const
Definition: KVBase.h:177
void Copy(TObject &) const override
Make a copy of this object.
Definition: KVBase.cpp:396
virtual void SetType(const Char_t *str)
Definition: KVBase.h:173
Simple wrapper for objects which can be drawn (graphs, histograms)
Definition: KVDrawable.h:29
Abstract base class for calculation of range & energy loss of charged particles in matter.
virtual Bool_t IsMaterialGas(const Char_t *)
Return kTRUE if material is gaseous.
virtual Double_t GetLinearEIncFromDeltaEOfIon(const Char_t *mat, Int_t Z, Int_t A, Double_t DeltaE, Double_t e, enum SolType type=kEmax, Double_t isoAmat=0., Double_t T=-1., Double_t P=-1.)
const Char_t * GetMaterialName(const Char_t *)
Return name of material of given type or name if it is in range tables.
virtual Double_t GetAtomicMass(const Char_t *)
Returns atomic mass of a material in the range tables.
const Char_t * GetMaterialType(const Char_t *)
Return type of material of given type or name if it is in range tables.
virtual Double_t GetRangeOfIon(const Char_t *mat, Int_t Z, Int_t A, Double_t E, Double_t Amat=0., Double_t T=-1., Double_t P=-1.)
static KVIonRangeTable * GetRangeTable(const Char_t *name)
Generates an instance of the KVIonRangeTable plugin class corresponding to given name.
virtual TGeoMaterial * GetTGeoMaterial(const Char_t *material)
Create and return pointer to TGeoMaterial/Mixture corresponding to material.
virtual Double_t GetZ(const Char_t *)
Returns atomic number of a material in the range tables.
virtual Double_t GetLinearEResOfIon(const Char_t *mat, Int_t Z, Int_t A, Double_t E, Double_t d, Double_t Amat=0., Double_t T=-1., Double_t P=-1.)
virtual void SetDensity(const Char_t *, Double_t)
Changes the density (g/cm**3) of a material in the range tables.
virtual Double_t GetEmaxValid(const Char_t *material, Int_t Z, Int_t A)
virtual Double_t GetLinearPunchThroughEnergy(const Char_t *mat, Int_t Z, Int_t A, Double_t e, Double_t isoAmat=0., Double_t T=-1., Double_t P=-1.)
virtual Bool_t IsMaterialKnown(const Char_t *)
Return kTRUE if material is in range tables.
virtual Double_t GetLinearDeltaEOfIon(const Char_t *mat, Int_t Z, Int_t A, Double_t E, Double_t d, Double_t Amat=0., Double_t T=-1., Double_t P=-1.)
virtual void SetTemperatureAndPressure(const Char_t *, Double_t temperature, Double_t pressure)
virtual Double_t GetDensity(const Char_t *)
Returns density (g/cm**3) of a material in the range tables.
virtual Double_t GetLinearRangeOfIon(const Char_t *mat, Int_t Z, Int_t A, Double_t E, Double_t Amat=0., Double_t T=-1., Double_t P=-1.)
Description of physical materials used to construct detectors & targets; interface to range tables.
Definition: KVMaterial.h:115
Double_t GetZ() const
Definition: KVMaterial.cpp:390
virtual Double_t GetPressure() const
Definition: KVMaterial.cpp:670
virtual void SetPressure(Double_t)
Definition: KVMaterial.cpp:633
virtual void SetTemperature(Double_t)
Definition: KVMaterial.cpp:699
virtual void SetThickness(Double_t thick)
Definition: KVMaterial.cpp:499
virtual Double_t GetThickness() const
Definition: KVMaterial.cpp:537
Double_t GetEffectiveAreaDensity(const TVector3 &norm, const TVector3 &direction)
Definition: KVMaterial.cpp:773
Double_t GetDensity() const
Definition: KVMaterial.cpp:418
Double_t fThick
area density of absorber in g/cm**2
Definition: KVMaterial.h:126
Bool_t IsGas() const
Definition: KVMaterial.cpp:371
virtual TGeoMedium * GetGeoMedium(const Char_t *="")
static KVIonRangeTable * GetRangeTable()
Definition: KVMaterial.cpp:158
virtual Double_t GetEnergyLoss() const
Definition: KVMaterial.h:166
Int_t fAmasr
isotopic mass of element
Definition: KVMaterial.h:125
Double_t GetEmaxValid(Int_t Z, Int_t A)
virtual Double_t GetIncidentEnergy(Int_t Z, Int_t A, Double_t delta_e=-1.0, enum SolType type=kEmax)
Double_t fELoss
total of energy lost by all particles traversing absorber
Definition: KVMaterial.h:129
virtual Double_t GetEIncOfMaxDeltaE(Int_t Z, Int_t A)
void Clear(Option_t *opt="") override
Reset absorber - set stored energy lost by particles in absorber to zero.
virtual Double_t GetPunchThroughEnergy(Int_t Z, Int_t A)
Bool_t IsNat() const
Definition: KVMaterial.cpp:349
void SetMass(Int_t a)
Definition: KVMaterial.cpp:282
void init()
Definition: KVMaterial.cpp:46
virtual Double_t GetEResFromDeltaE(Int_t Z, Int_t A, Double_t dE=-1.0, enum SolType type=kEmax)
virtual KVDrawable< TGraph > GetGraphOfDeltaEVsE(const KVNucleus &nuc, Int_t npts, Double_t Emin, Double_t Emax)
virtual Double_t GetMaxDeltaE(Int_t Z, Int_t A)
static KVIonRangeTable * ChangeRangeTable(const Char_t *name)
Definition: KVMaterial.cpp:179
void SetAreaDensity(Double_t dens)
Definition: KVMaterial.cpp:573
Double_t GetAreaDensity() const
Definition: KVMaterial.cpp:606
virtual Double_t GetParticleEIncFromERes(KVNucleus *, TVector3 *norm=nullptr)
Definition: KVMaterial.cpp:854
Double_t fTemp
gas temperature in degrees celsius
Definition: KVMaterial.h:128
Double_t fPressure
gas pressure in torr
Definition: KVMaterial.h:127
virtual void DetectParticle(KVNucleus *, TVector3 *norm=nullptr)
virtual Double_t GetTemperature() const
Definition: KVMaterial.cpp:730
virtual Double_t GetIncidentEnergyFromERes(Int_t Z, Int_t A, Double_t Eres)
virtual void SetMaterial(const Char_t *type)
Definition: KVMaterial.cpp:217
virtual Double_t GetDeltaEFromERes(Int_t Z, Int_t A, Double_t Eres)
static KVIonRangeTable * fIonRangeTable
pointer to class used to calculate charged particle ranges & energy losses
Definition: KVMaterial.h:118
void SetDensity(Double_t)
Definition: KVMaterial.cpp:459
virtual Double_t GetELostByParticle(KVNucleus *, TVector3 *norm=nullptr)
Definition: KVMaterial.cpp:819
Double_t GetEffectiveThickness(const TVector3 &norm, const TVector3 &direction)
Definition: KVMaterial.cpp:750
virtual Double_t GetERes(Int_t Z, Int_t A, Double_t Einc, Double_t dx=0.)
KVMaterial()
default ctor
Definition: KVMaterial.cpp:73
virtual Double_t GetRange(Int_t Z, Int_t A, Double_t Einc)
Definition: KVMaterial.cpp:917
Bool_t IsIsotopic() const
Definition: KVMaterial.cpp:324
void Copy(TObject &obj) const override
Make a copy of this material object.
void Print(Option_t *option="") const override
Show information on this material.
Definition: KVMaterial.cpp:792
virtual Double_t GetDeltaE(Int_t Z, Int_t A, Double_t Einc, Double_t dx=0.)
Definition: KVMaterial.cpp:886
virtual Double_t GetLinearRange(Int_t Z, Int_t A, Double_t Einc)
Definition: KVMaterial.cpp:954
virtual KVMaterial * GetActiveLayer() const
Definition: KVMaterial.h:203
Double_t GetMass() const
Definition: KVMaterial.cpp:302
Description of properties and kinematics of atomic nuclei.
Definition: KVNucleus.h:123
Int_t GetA() const
Definition: KVNucleus.cpp:796
static Int_t IsMassGiven(const Char_t *)
Definition: KVNucleus.cpp:137
Int_t GetZ() const
Return the number of proton / atomic number.
Definition: KVNucleus.cpp:767
TVector3 * GetPInitial() const
Definition: KVParticle.h:729
TVector3 GetMomentum() const
Definition: KVParticle.h:607
void SetKE(Double_t ecin)
Definition: KVParticle.cpp:246
void SetE0(TVector3 *e=0)
Definition: KVParticle.h:718
void SetIsDetected()
Definition: KVParticle.h:733
Double_t GetKE() const
Definition: KVParticle.h:617
Range of values specified by minimum, maximum.
Definition: KVValueRange.h:19
virtual const char * GetValue(const char *name, const char *dflt) const
TGeoMedium * GetMedium(const char *medium) const
TGeoMaterial * GetMaterial(const char *matname) const
void SetPressure(Double_t pressure)
void SetTransparency(Char_t transparency=0)
void SetTemperature(Double_t temperature)
virtual void SetTitle(const char *title="")
const char * GetName() const override
virtual void SetName(const char *name)
virtual void Error(const char *method, const char *msgfmt,...) const
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
void Form(const char *fmt,...)
TString & Remove(EStripType s, char c)
TVector3 Unit() const
gr SetName("gr")
const Int_t n
void Warning(UserClass p, const char *location, const char *va_(fmt),...)
Definition: KVError.h:125
void init()
constexpr Double_t E()
constexpr Double_t R()
Double_t Abs(Double_t d)
Double_t Max(Double_t a, Double_t b)
TArc a
ClassImp(TPyArg)