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  Warning("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  // 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 
450 
452 {
453  // Set the linear thickness of the material in cm, e.g.
454  //~~~~{.cpp}
455  //SetThickness( 30.*KVUnits::um ); set thickness to 30 microns
456  //~~~~
457  //
458  //For detectors, the material in question is that of the active layer (see KVDetector).
459 
460  if (GetActiveLayer()) {
462  return;
463  }
464  // recalculate area density
465  if (GetDensity() != 0)
466  fThick = t * GetDensity();
467  else
468  fThick = t;
469 
470 }
471 
472 
473 
474 
483 
485 {
486  // Returns the linear thickness of the material in cm.
487  // Use KVUnits to translate from one unit to another, e.g.
488  //~~~~{.cpp}
489  //auto micro_thick = mat.GetThickness()/KVUnits::um; thickness in microns
490  //~~~~
491  //
492  //For detectors, the material in question is that of the active layer (see KVDetector).
493 
494  if (GetActiveLayer())
495  return GetActiveLayer()->GetThickness();
496  if (GetDensity() != 0)
497  return fThick / GetDensity();
498  else
499  return fThick;
500 }
501 
502 
503 
504 
519 
520 void KVMaterial::SetAreaDensity(Double_t dens /* g/cm**2 */)
521 {
522  // Set area density in \f$g/cm^{2}\f$.
523  //
524  // For solids, area density can only be changed by changing the thickness of the material.
525  //
526  // For gases, the density depends on temperature and pressure - see GetDensity(). This method
527  // leaves temperature and pressure unchanged, therefore for gases also this
528  // method will effectively modify the linear dimension of the gas cell.
529  //
530  //~~~~{.cpp}
531  //mat.SetAreaDensity(500*KVUnits::ug); // set density in microgram/cm2
532  //~~~~
533  //
534  //For detectors, the material in question is that of the active layer (see KVDetector).
535 
536  if (GetActiveLayer())
538  fThick = dens;
539 }
540 
541 
542 
543 
552 
554 {
555  // Return area density of material in \f$g/cm^{2}\f$
556  //
557  //~~~~{.cpp}
558  //auto dens_mgcm2 = mat.GetAreaDensity()/KVUnits::mg; // in mg/cm2
559  //~~~~
560  //
561  //For detectors, the material in question is that of the active layer (see KVDetector).
562 
563  if (GetActiveLayer()) return GetActiveLayer()->GetAreaDensity();
564  return fThick;
565 }
566 
567 
568 
569 
579 
581 {
582  // Set the pressure of a gaseous material (in torr).
583  // The linear dimension (thickness) is kept constant, the area density changes.
584  //
585  //~~~~{.cpp}
586  //mat.SetPressure(50*KVUnits::mbar); // set pressure to 50mbar
587  //~~~~
588  //
589  //For detectors, the material in question is that of the active layer (see KVDetector).
590 
591  if (!IsGas()) return;
592  if (GetActiveLayer()) {
594  return;
595  }
596  // get current linear dimension of absorber
597  Double_t e = GetThickness();
598  fPressure = p;
599  // change area density to keep linear dimension constant
600  SetThickness(e);
601 }
602 
603 
604 
605 
606 
616 
618 {
619  // Returns the pressure of a gas (in torr).
620  // If the material is not a gas - see IsGas() - value is zero.
621  //
622  //~~~~{.cpp}
623  //auto press_mbar = mat.GetPressure()/KVUnits::mbar; // pressure in mbar
624  //~~~~
625  //
626  //For detectors, the material in question is that of the active layer (see KVDetector).
627 
628  if (!IsGas()) return 0.0;
629  if (GetActiveLayer())
630  return GetActiveLayer()->GetPressure();
631  return fPressure;
632 }
633 
634 
635 
636 
645 
647 {
648  // Set temperature of material in degrees celsius.
649  //
650  // This only has an effect on gaseous materials, where the resulting change in density
651  // changes the area density of the absorber (for fixed linear dimension).
652  // \sa GetDensity()
653  //
654  //For detectors, the material in question is that of the active layer (see KVDetector).
655 
656  if (!IsGas()) return;
657  if (GetActiveLayer()) {
659  return;
660  }
661  // get current linear dimension of absorber
662  Double_t e = GetThickness();
663  fTemp = t;
664  // change area density to keep linear dimension constant
665  SetThickness(e);
666 }
667 
668 
669 
670 
671 
676 
678 {
679  //Returns temperature of material in degrees celsius (only gaseous materials).
680  //
681  //For detectors, the material in question is that of the active layer (see KVDetector).
682 
683  if (GetActiveLayer())
684  return GetActiveLayer()->GetTemperature();
685  return fTemp;
686 }
687 
688 
689 
690 
696 
698 {
699  //\param[in] norm vector normal to the material, oriented from the origin towards the material
700  //\param[in] direction direction of motion of an ion
701  //\returns effective linear thickness of absorber (in cm) as 'seen' in given direction, taking into
702  // account the arbitrary orientation of the normal to the material's surface
703 
704  TVector3 n = norm.Unit();
705  TVector3 d = direction.Unit();
706  //absolute value of scalar product, in case direction is opposite to normal
707  Double_t prod = TMath::Abs(n * d);
708  return GetThickness() / TMath::Max(prod, 1.e-03);
709 }
710 
711 
712 
713 
719 
721 {
722  //\param[in] norm vector normal to the material, oriented from the origin towards the material
723  //\param[in] direction direction of motion of an ion
724  //\returns effective area density of absorber in \f$g/cm^{2}\f$ as 'seen' in the given direction, taking into
725  // account the arbitrary orientation of the normal to the material's surface
726 
727  TVector3 n = norm.Unit();
728  TVector3 d = direction.Unit();
729  //absolute value of scalar product, in case direction is opposite to normal
730  Double_t prod = TMath::Abs(n * d);
731  return GetAreaDensity() / TMath::Max(prod, 1.e-03);
732 }
733 
734 
735 
738 
740 {
741  //Show information on this material
742  cout << "KVMaterial: " << GetName() << " (" << GetType() << ")" << endl;
744  cout << " Pressure " << GetPressure() << " torr" << endl;
745  cout << " Thickness " << KVMaterial::GetThickness() << " cm" << endl;
746  cout << " Area density " << KVMaterial::GetAreaDensity() << " g/cm**2" << endl;
747  cout << "-----------------------------------------------" << endl;
748  cout << " Z = " << GetZ() << " atomic mass = " << GetMass() << endl;
749  cout << " Density = " << GetDensity() << " g/cm**3" << endl;
750  cout << "-----------------------------------------------" << endl;
751 }
752 
753 
754 
755 
765 
767 {
768  //\param[in] kvp pointer to a KVNucleus object describing a charged ion
769  //\param[in] norm [optional] vector normal to the material, oriented from the origin towards the material
770  //
771  //\returns The energy loss \f$\Delta E\f$ in MeV of a charged particle impinging on the absorber
772  //
773  //If the unit normal vector is given, the effective thickness of the material 'seen' by the particle
774  //depending on the orientation of its direction of motion with respect to the absorber is used for the calculation,
775  //rather than the nominal thickness corresponding to ions impinging perpendicularly.
776 
777  Double_t thickness;
778  if (norm) {
779  TVector3 p = kvn->GetMomentum();
780  thickness = GetEffectiveThickness((*norm), p);
781  }
782  else
783  thickness = GetThickness();
784  Double_t E_loss =
785  fIonRangeTable->GetLinearDeltaEOfIon(GetType(), kvn->GetZ(), kvn->GetA(), kvn->GetKE(),
786  thickness, fAmasr, fTemp, fPressure);
787  return E_loss;
788 }
789 
790 
791 
792 
800 
802 {
803  // \param[in] kvn KVNucleus describing properties of incident ion (\f$Z,A\f$ and with kinetic energy \f$E_{res}\f$)
804  // \param[in] norm [optional] vector normal to the material, oriented from the origin towards the material.
805  // \returns incident energy of ion \f$E_{inc}\f$ [MeV] deduced from residual energy \f$E_{res}=E_{inc}-\Delta E\f$.
806  //
807  //If \a norm is given, the effective thickness of the material 'seen' by the particle
808  //depending on its direction of motion is used for the calculation.
809 
810  Double_t thickness;
811  if (norm) {
812  TVector3 p = kvn->GetMomentum();
813  thickness = GetEffectiveThickness((*norm), p);
814  }
815  else
816  thickness = GetThickness();
817  Double_t E_inc = fIonRangeTable->
818  GetLinearEIncFromEResOfIon(GetType(), kvn->GetZ(), kvn->GetA(), kvn->GetKE(),
819  thickness, fAmasr, fTemp, fPressure);
820  return E_inc;
821 }
822 
823 
824 
825 
832 
834 {
835  // \param[in] Z atomic number of incident ion
836  // \param[in] A mass number of incident ion
837  // \param[in] Einc kinetic energy of incident ion
838  // \param[in] dx if given, used as thickness (in cm) of absorber instead of current thickness
839  // \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]
840 
841  if (Z < 1) return 0.;
842  Double_t E_loss =
843  fIonRangeTable->GetLinearDeltaEOfIon(GetType(), Z, A, Einc, (dx > 0 ? dx : GetThickness()), fAmasr, fTemp, fPressure);
844 
845  return TMath::Max(E_loss, 0.);
846 }
847 
848 
849 
850 
863 
865 {
866  // \param[in] Z atomic number of incident ion
867  // \param[in] A mass number of incident ion
868  // \param[in] Einc kinetic energy of incident ion
869  // \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]
870  //
871  // Different units can be used with KVUnits:
872  //~~~~{.cpp}
873  // KVMaterial si("Si");
874  // si.GetRange(2,4,13)/KVUnits::mg;
875  //(long double) 25.190011L // range in silicon in mg/cm2 of 13 MeV 4He particles
876  //~~~~
877 
878  if (Z < 1) return 0.;
879  Double_t R =
881  return R;
882 }
883 
884 
885 
886 
900 
902 {
903  // \param[in] Z atomic number of incident ion
904  // \param[in] A mass number of incident ion
905  // \param[in] Einc kinetic energy of incident ion
906  // \returns linear range in [cm] in absorber for incident nucleus \f$Z,A\f$
907  // with kinetic energy \f$E_{inc}\f$ [MeV]
908  //
909  // Different units can be used with KVUnits:
910  //~~~~{.cpp}
911  // KVMaterial si("Si");
912  // si.GetLinearRange(2,4,13)/KVUnits::um;
913  //(long double) 108.11164L // range in silicon in microns of 13 MeV 4He particles
914  //~~~~
915 
916  if (Z < 1) return 0.;
917  Double_t R =
919  return R;
920 }
921 
922 
923 
924 
947 
949 {
950  // \param[in] Z atomic number of incident ion
951  // \param[in] A mass number of incident ion
952  // \param[in] Eres residual kinetic energy of ion after impinging on the absorber
953  // \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
954  //
955  //\b Example of use:
956  //~~~~{.cpp}
957  //KVMaterial si("Si", 300*KVUnits::um); // 300um silicon absorber
958  //KVNucleus alpha("4He",30); // 30MeV/u alpha particle
959  //
960  //si.DetectParticle(&alpha); // particle is slowed by silicon
961  //
962  //si.GetEnergyLoss();
963  //(double) 4.1371801 // energy lost by particle in silicon
964  //
965  //alpha.GetEnergy();
966  //(double) 115.86282 // residual energy of alpha after silicon
967  //
968  //si.GetDeltaEFromERes(2,4,115.86282);
969  //(double) 4.1371801 // energy loss calculated from residual energy
970  //~~~~
971 
972  if (Z < 1) return 0.;
973  Double_t E_loss = fIonRangeTable->
974  GetLinearDeltaEFromEResOfIon(
975  GetType(), Z, A, Eres, GetThickness(), fAmasr, fTemp, fPressure);
976  return E_loss;
977 }
978 
979 
980 
1017 
1019 {
1020  // \returns Calculated residual kinetic energy \f$E_{res}\f$ [MeV] of a nucleus \f$Z,A\f$ after the absorber from
1021  // the energy loss \f$\Delta E\f$ in the absorber. If \a dE is given, it is used instead of the current energy loss.
1022  //
1023  // \param[in] Z,A atomic and mass number of nucleus
1024  // \param[in] dE [optional] energy loss of nucleus in absorber
1025  // \param[in] type
1026  // \parblock
1027  // Determine the type of solution to use. Possible values are:
1028  // \arg SolType::kEmax [default]: solution corresponding to the highest incident energy is returned.
1029  // This is the solution found for \f$E_{inc}\f$ above that of the maximum of the \f$\Delta E(E_{inc})\f$ curve.
1030  // \arg SolType::kEmin : low energy solution (\f$E_{inc}\f$ below maximum of the \f$\Delta E(E_{inc})\f$ curve).
1031  // \endparblock
1032  //
1033  //\b Example of use:
1034  //~~~~{.cpp}
1035  //KVMaterial si("Si", 300*KVUnits::um); // 300um silicon absorber
1036  //KVNucleus alpha("4He",30); // 30MeV/u alpha particle
1037  //
1038  //si.DetectParticle(&alpha); // particle is slowed by silicon
1039  //
1040  //si.GetEnergyLoss();
1041  //(double) 4.1371801 // energy lost by particle in silicon
1042  //
1043  //alpha.GetEnergy();
1044  //(double) 115.86282 // residual energy of alpha after silicon
1045  //
1046  //si.GetEResFromDeltaE(2,4);
1047  //(double) 115.86282 // residual energy calculated from energy loss
1048  //~~~~
1049  //
1050  // \note If the energy loss in the absorber is greater than the maximum theoretical \f$\Delta E\f$ - given by GetMaxDeltaE() - then we return
1051  // the residual energy corresponding to the maximum - given by GetEIncOfMaxDeltaE().
1052  //
1053  // \note For detectors (see KVDetector), \a dE is the energy loss \f$\Delta E\f$ only in the \b active layer, not the total
1054  // energy lost by the particle crossing the detector; because for detectors with inactive layers \f$E_{inc}\geq \Delta E + E_{res}\f$.
1055 
1056  Double_t EINC = GetIncidentEnergy(Z, A, dE, type);
1057  return GetERes(Z, A, EINC);
1058 }
1059 
1060 
1061 
1062 
1093 
1095 {
1096  //\returns Calculated incident energy [MeV] of nucleus \f$Z,A\f$ corresponding to energy loss \f$\Delta E\f$
1097  //in this absorber. If \a delta_e is given, it is used instead of the current energy loss in this absorber.
1098  //
1099  //\param[in] Z,A atomic and mass number of nucleus
1100  //\param[in] delta_e [optional] energy loss of nucleus in absorber \f$\Delta E\f$ [MeV]
1101  //\param[in] type
1102  //\parblock
1103  //Determine the type of solution to use. Possible values are:
1104  // \arg SolType::kEmax [default]: solution corresponding to the highest incident energy is returned.
1105  //This is the solution found for \f$E_{inc}\f$ above that of the maximum of the \f$\Delta E(E_{inc})\f$ curve.
1106  // \arg SolType::kEmin : low energy solution (\f$E_{inc}\f$ below maximum of the \f$\Delta E(E_{inc})\f$ curve).
1107  //\endparblock
1108  //
1109  //\b Example of use:
1110  //~~~~{.cpp}
1111  //KVMaterial si("Si", 300*KVUnits::um); // 300um silicon absorber
1112  //KVNucleus alpha("4He",30); // 30MeV/u alpha particle
1113  //
1114  //si.DetectParticle(&alpha); // particle is slowed by silicon
1115  //
1116  //si.GetEnergyLoss();
1117  //(double) 4.1371801 // energy lost by particle in silicon
1118  //
1119  //si.GetIncidentEnergy(2,4);
1120  //(double) 120.00000 // incident energy of alpha calculated from energy loss
1121  //~~~~
1122  //
1123  //\note If the energy loss in the absorber is greater than the maximum theoretical \f$\Delta E\f$ - given by GetMaxDeltaE() - then we return
1124  //the incident energy corresponding to the maximum - given by GetEIncOfMaxDeltaE().
1125 
1126  if (Z < 1) return 0.;
1127 
1128  Double_t DE = (delta_e > 0 ? delta_e : GetEnergyLoss());
1129 
1132 }
1133 
1134 
1135 
1136 
1160 
1162 {
1163  // \param[in] Z atomic number of incident ion
1164  // \param[in] A mass number of incident ion
1165  // \param[in] Einc kinetic energy of incident ion
1166  // \param[in] dx if given, used as thickness (in cm) of absorber instead of current thickness
1167  // \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$
1168  //
1169  //\b Example of use:
1170  //~~~~{.cpp}
1171  //KVMaterial si("Si", 300*KVUnits::um); // 300um silicon absorber
1172  //KVNucleus alpha("4He",30); // 30MeV/u alpha particle
1173  //
1174  //si.DetectParticle(&alpha); // particle is slowed by silicon
1175  //
1176  //si.GetEnergyLoss();
1177  //(double) 4.1371801 // energy lost by particle in silicon
1178  //
1179  //alpha.GetEnergy();
1180  //(double) 115.86282 // residual energy of alpha after silicon
1181  //
1182  //si.GetERes(2,4,120.0);
1183  //(double) 115.86282 // residual energy calculated from incident energy
1184  //~~~~
1185 
1186  if (Z < 1) return 0.;
1187  if (IsGas() && GetPressure() == 0)
1188  return Einc;
1189 
1190  Double_t E_res =
1191  fIonRangeTable->GetLinearEResOfIon(GetType(), Z, A, Einc, (dx > 0 ? dx : GetThickness()), fAmasr, fTemp, fPressure);
1192 
1193  return E_res;
1194 }
1195 
1196 
1197 
1198 
1210 
1212 {
1213  //\param[in] kvp pointer to a KVNucleus object describing a charged ion
1214  //\param[in] norm [optional] vector normal to the material, oriented from the origin towards the material
1215  //
1216  //The energy loss \f$\Delta E\f$ of a charged particle traversing the absorber is calculated,
1217  //and the particle is slowed down by a corresponding amount
1218  //(the kinetic energy of the KVNucleus object passed as argument will be reduced by \f$\Delta E\f$, possibly to zero).
1219  //
1220  //If the unit normal vector is given, the effective thickness of the material 'seen' by the particle
1221  //depending on the orientation of its direction of motion with respect to the absorber is used for the calculation,
1222  //rather than the nominal thickness corresponding to ions impinging perpendicularly.
1223 
1224  kvp->SetIsDetected();//set flag to say that particle has been slowed down
1225  //If this is the first absorber that the particle crosses, we set a "reminder" of its
1226  //initial energy
1227  if (!kvp->GetPInitial())
1228  kvp->SetE0();
1229 
1230 #ifdef DBG_TRGT
1231  cout << "detectparticle in material " << GetType() << " of thickness "
1232  << GetThickness() << endl;
1233 #endif
1234  Double_t el = GetELostByParticle(kvp, norm);
1235  // set particle residual energy
1236  Double_t Eres = kvp->GetKE() - el;
1237  kvp->SetKE(Eres);
1238  // add to total of energy losses in absorber
1239  fELoss += el;
1240 }
1241 
1242 
1243 
1244 
1247 
1249 {
1250  // Reset absorber - set stored energy lost by particles in absorber to zero
1251  fELoss = 0.0;
1252 }
1253 
1254 
1255 
1258 
1259 void KVMaterial::Copy(TObject& obj) const
1260 {
1261  // Make a copy of this material object
1262  KVBase::Copy(obj);
1263  ((KVMaterial&) obj).SetMaterial(GetType());
1264  if (IsIsotopic())((KVMaterial&) obj).SetMass(fAmasr);
1265  ((KVMaterial&) obj).SetPressure(GetPressure());
1266  ((KVMaterial&) obj).SetTemperature(GetTemperature());
1267  ((KVMaterial&) obj).SetThickness(GetThickness());
1268 }
1269 
1270 
1271 
1272 
1277 
1279 {
1280  // \param[in] Z,A atomic & mass numbers of incident ion
1281  // \param[in] Eres residual energy of ion after absorber
1282  // \returns incident energy of ion \f$E_{inc}\f$ [MeV] deduced from residual energy \f$E_{res}=E_{inc}-\Delta E\f$.
1283  if (Z < 1) return 0.;
1284 
1285  return fIonRangeTable->
1286  GetLinearEIncFromEResOfIon(GetType(), Z, A, Eres, GetThickness(), fAmasr, fTemp, fPressure);
1287 }
1288 
1289 
1290 
1291 
1295 
1297 {
1298  //\param[in] Z,A atomic and mass number of impinging ion
1299  //\returns incident energy in MeV for which the \f$\Delta E\f$-\f$E\f$ curve has a maximum
1300 
1301  if (Z < 1) return 0.;
1302 
1303  return fIonRangeTable->
1304  GetLinearEIncOfMaxDeltaEOfIon(GetType(), Z, A, GetThickness(), fAmasr, fTemp, fPressure);
1305 }
1306 
1307 
1308 
1309 
1317 
1319 {
1320  //\returns The maximum possible energy loss \f$\Delta E\f$ of a nucleus in the absorber
1321  //\param[in] Z,A atomic and mass number of the nucleus
1322  //
1323  //\sa GetEIncOfMaxDeltaE()
1324  //
1325  //\note For detectors, this is the maximum energy loss in the active layer.
1326 
1327  if (GetActiveLayer()) return GetActiveLayer()->GetMaxDeltaE(Z, A);
1328 
1329  if (Z < 1) return 0.;
1330 
1331  return fIonRangeTable->
1332  GetLinearMaxDeltaEOfIon(GetType(), Z, A, GetThickness(), fAmasr, fTemp, fPressure);
1333 }
1334 
1335 
1336 
1337 
1358 
1360 {
1361  // By default, return pointer to TGeoMedium corresponding to this KVMaterial.
1362  //
1363  // \param[in] med_name [optional] if it corresponds to the name of an already existing
1364  // medium, we return a pointer to this medium, or a nullptr if it does not exist.
1365  //
1366  // `med_name = "Vacuum"` is a special case: if the "Vacuum" does not exist, we create it.
1367  //
1368  // Instance of geometry manager class TGeoManager must be created before calling this
1369  // method, otherwise nullptr will be returned.
1370  //
1371  // If the required TGeoMedium is not already available in the TGeoManager, we create
1372  // a new TGeoMedium corresponding to the properties of this KVMaterial.
1373  // The name of the TGeoMedium (and associated TGeoMaterial) is the name of the KVMaterial.
1374  //
1375  // \note For detectors, the material in question is that of the active layer (see KVDetector).
1376  //
1377  // \note for gaseous materials, the TGeoMedium/Material name is of the form gasname_pressure_temperature
1378  // e.g. C3F8_37.5_20.0 for C3F8 gas at 37.5 torr 20 degrees Celsius.
1379  // Each gas with different pressure/temperature has to have a separate TGeoMaterial/Medium (with different density).
1380 
1381  if (!gGeoManager) return nullptr;
1382 
1383  if (strcmp(med_name, "")) {
1384  TGeoMedium* gmed = gGeoManager->GetMedium(med_name);
1385  if (gmed) return gmed;
1386  else if (!strcmp(med_name, "Vacuum")) {
1387  // create material
1388  TGeoMaterial* gmat = new TGeoMaterial("Vacuum", 0, 0, 0);
1389  gmat->SetTitle("Vacuum");
1390  gmed = new TGeoMedium("Vacuum", 0, gmat);
1391  gmed->SetTitle("Vacuum");
1392  return gmed;
1393  }
1394  return nullptr;
1395  }
1396 
1397  // if object is a KVDetector, we return medium corresponding to the active layer
1398  if (GetActiveLayer()) return GetActiveLayer()->GetGeoMedium();
1399 
1400  // for gaseous materials, the TGeoMedium/Material name is of the form
1401  // gasname_pressure
1402  // e.g. C3F8_37.5 for C3F8 gas at 37.5 torr
1403  // each gas with different pressure has to have a separate TGeoMaterial/Medium
1404  TString medName;
1405  if (IsGas()) medName.Form("%s_%f_%f", GetName(), GetPressure(), GetTemperature());
1406  else medName = GetName();
1407 
1408  TGeoMedium* gmed = gGeoManager->GetMedium(medName);
1409 
1410  if (gmed) return gmed;
1411 
1412  TGeoMaterial* gmat = gGeoManager->GetMaterial(medName);
1413 
1414  if (!gmat) {
1415  // create material
1416  gmat = GetRangeTable()->GetTGeoMaterial(GetName());
1417  gmat->SetPressure(GetPressure());
1418  gmat->SetTemperature(GetTemperature());
1419  gmat->SetTransparency(0);
1420  gmat->SetName(medName);
1421  gmat->SetTitle(GetName());
1422  }
1423 
1424  // create medium
1425  static Int_t numed = 1; // static counter variable used to number media
1426  gmed = new TGeoMedium(medName, numed, gmat);
1427  numed += 1;
1428 
1429  return gmed;
1430 }
1431 
1432 
1433 
1440 
1442 {
1443  // \param[in] nuc definition of charged particle
1444  // \param[in] npts number of points to use
1445  // \param[in] Emin minimum incident energy \f$E\f$
1446  // \param[in] Emax maximum incident energy \f$E\f$
1447  // \returns TGraph with the \f$\Delta E\f$-\f$E\f$ curve for this material for a given charged particle
1448 
1449  auto g = new TGraph;
1450  KVValueRange<Double_t> R(Emin, Emax);
1451  for (int i = 0; i < npts; ++i) {
1452  auto E = R.ValueIofN(i, npts);
1453  g->SetPoint(i, E, GetDeltaE(nuc.GetZ(), nuc.GetA(), E));
1454  }
1455  return g;
1456 }
1457 
1458 
1459 
1466 
1468 {
1469  //\param[in] Z,A atomic & mass numbers of ion
1470  // \returns maximum incident energy [MeV] for which range tables are valid
1471  // for this material and ion with \f$Z,A\f$.
1472  //
1473  //\note For detectors, the limit of validity for the material composing the active layer is returned (see KVDetector).
1474  if (GetActiveLayer()) return GetActiveLayer()->GetEmaxValid(Z, A);
1475  return fIonRangeTable->GetEmaxValid(GetType(), Z, A);
1476 }
1477 
1478 
1479 
1484 
1486 {
1487  //\param[in] Z,A atomic & mass numbers of ion
1488  // \returns incident energy \f$E_{inc}\f$ [MeV] for which ion \f$Z,A\f$ has a range equal to the
1489  // thickness of this absorber (see GetRange(), GetLinearRange()).
1490 
1492 }
1493 
1494 
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:139
virtual const Char_t * GetType() const
Definition: KVBase.h:176
void Copy(TObject &) const override
Make a copy of this object.
Definition: KVBase.cpp:373
virtual void SetType(const Char_t *str)
Definition: KVBase.h:172
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 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:89
Double_t GetZ() const
Definition: KVMaterial.cpp:390
virtual Double_t GetPressure() const
Definition: KVMaterial.cpp:617
virtual void SetPressure(Double_t)
Definition: KVMaterial.cpp:580
virtual void SetTemperature(Double_t)
Definition: KVMaterial.cpp:646
Double_t GetEffectiveAreaDensity(TVector3 &norm, TVector3 &direction)
Definition: KVMaterial.cpp:720
virtual void SetThickness(Double_t thick)
Definition: KVMaterial.cpp:451
virtual Double_t GetThickness() const
Definition: KVMaterial.cpp:484
Double_t GetDensity() const
Definition: KVMaterial.cpp:418
Double_t fThick
area density of absorber in g/cm**2
Definition: KVMaterial.h:100
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:139
Int_t fAmasr
isotopic mass of element
Definition: KVMaterial.h:99
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:103
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 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:520
Double_t GetAreaDensity() const
Definition: KVMaterial.cpp:553
virtual Double_t GetParticleEIncFromERes(KVNucleus *, TVector3 *norm=nullptr)
Definition: KVMaterial.cpp:801
Double_t fTemp
gas temperature in degrees celsius
Definition: KVMaterial.h:102
virtual TGraph * GetGraphOfDeltaEVsE(const KVNucleus &nuc, Int_t npts, Double_t Emin, Double_t Emax)
Double_t fPressure
gas pressure in torr
Definition: KVMaterial.h:101
virtual void DetectParticle(KVNucleus *, TVector3 *norm=nullptr)
virtual Double_t GetTemperature() const
Definition: KVMaterial.cpp:677
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)
Definition: KVMaterial.cpp:948
static KVIonRangeTable * fIonRangeTable
pointer to class used to calculate charged particle ranges & energy losses
Definition: KVMaterial.h:92
virtual Double_t GetELostByParticle(KVNucleus *, TVector3 *norm=nullptr)
Definition: KVMaterial.cpp:766
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:864
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:739
Double_t GetEffectiveThickness(TVector3 &norm, TVector3 &direction)
Definition: KVMaterial.cpp:697
virtual Double_t GetDeltaE(Int_t Z, Int_t A, Double_t Einc, Double_t dx=0.)
Definition: KVMaterial.cpp:833
virtual Double_t GetLinearRange(Int_t Z, Int_t A, Double_t Einc)
Definition: KVMaterial.cpp:901
virtual KVMaterial * GetActiveLayer() const
Definition: KVMaterial.h:176
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:792
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:763
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 Warning(const char *method, const char *msgfmt,...) const
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
const long double atm
Definition: KVUnits.h:79
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)