KaliVeda  1.13/01
Heavy-Ion Analysis Toolkit
KVMaterial.cpp
Go to the documentation of this file.
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 "Riostream.h"
19 #include "KVMaterial.h"
20 #include "KVNucleus.h"
21 #include "TMath.h"
22 #include "TSystem.h"
23 #include "TROOT.h"
24 #include "TEnv.h"
25 #include "TGeoMaterial.h"
26 #include "TGeoMedium.h"
27 #include "TGeoManager.h"
28 #include "KVIonRangeTable.h"
29 
30 #include <KVValueRange.h>
31 #include <TGraph.h>
32 
33 using namespace std;
34 
36 
38 
39 //___________________________________________________________________________________
40 
49 
51 {
52  // Default initialisations.
53  //
54  // No properties are set for the material (except standard temperature (19°C) and pressure (1 atm)).
55  //
56  // Default range table is generated if not already done. By default it is the VEDALOSS table implemented in KVedaLoss.
57  // You can change this by changing the value of environment variable `KVMaterial.IonRangeTable` or by calling
58  // static method ChangeRangeTable() before creating any materials.
59 
60  fELoss = 0;
61  SetName("");
62  SetTitle("");
63  fAmasr = 0;
64  fPressure = 1. * KVUnits::atm;
65  fTemp = 19.0;
66  // create default range table singleton if not already done
67  GetRangeTable();
68  fAbsorberVolume = nullptr;
69 }
70 
71 
72 //
73 
76 
78 {
79  //default ctor
80  init();
81 }
82 
83 
84 
87 
88 KVMaterial::KVMaterial(const Char_t* type, const Double_t thick)
89 {
90  // Create material with given type and linear thickness in cm.
91 
92  init();
93  SetMaterial(type);
94  SetThickness(thick);
95 }
96 
97 
98 
101 
102 KVMaterial::KVMaterial(Double_t area_density, const Char_t* type)
103 {
104  // Create material with given area density in \f$g/cm^{2}\f$ and given type
105 
106  init();
107  SetMaterial(type);
108  SetAreaDensity(area_density);
109 }
110 
111 
112 
123 
124 KVMaterial::KVMaterial(const Char_t* gas, const Double_t thick, const Double_t pressure, const Double_t temperature)
125 {
126  // Create gaseous material with given type, linear thickness in cm, pressure in Torr,
127  // and temperature in degrees C (default value 19°C).
128  //
129  // __Examples__
130  //~~~~{.cpp}
131  //KVMaterial("CF4", 15*KVUnits::cm, 1*KVUnits::atm); // 15cm of CF4 gas at 1atm and 19°C
132  //
133  //KVMaterial("C3F8", 50*KVUnits::mm, 30*KVUnits::mbar, 25); // 50mm of C3F8 at 30mbar and 25°C
134  //~~~~
135 
136  init();
137  SetMaterial(gas);
138  fPressure = pressure;
139  fTemp = temperature;
140  SetThickness(thick);
141 }
142 
143 
144 //
145 
148 
150 {
151  //Copy ctor
152  init();
153 #if ROOT_VERSION_CODE >= ROOT_VERSION(3,4,0)
154  obj.Copy(*this);
155 #else
156  ((KVMaterial&) obj).Copy(*this);
157 #endif
158 }
159 
160 
161 
165 
167 {
168  // Static method
169  // \returns pointer to currently used range table
170  if (!fIonRangeTable) {
171  fIonRangeTable = KVIonRangeTable::GetRangeTable(gEnv->GetValue("KVMaterial.IonRangeTable", "VEDALOSS"));
172  }
173  return fIonRangeTable;
174 }
175 
176 
177 
186 
188 {
189  // Changes the default range table used for energy loss calculations.
190  //
191  // The name must correspond to a Plugin defined for class KVIonRangeTable - see list given by
192  //
193  //~~~~{.cpp}
194  //KVBase::GetListOfPlugins("KVIonRangeTable")
195  //~~~~
196 
197  if (fIonRangeTable) delete fIonRangeTable;
199  if (!fIonRangeTable)
200  ::Error("KVMaterial::ChangeRangeTable", "No plugin %s defined for KVIonRangeTable", name);
201  return fIonRangeTable;
202 }
203 
204 
205 
224 
225 void KVMaterial::SetMaterial(const Char_t* mat_type)
226 {
227  // Intialise material of a given type, which must exist in the currently used range table.
228  //
229  // The list of available material types depends on the underlying range table: this list can be obtained or visualised like so:
230  // ~~~~{.cpp}
231  // KVMaterial::GetRangeTable()->Print(); // print infos on range table
232 
233  // KVMaterial::GetRangeTable()->GetListOfMaterials()->ls(); // retrieve pointer to list
234 
235  // OBJ: TObjArray TObjArray An array of objects : 0
236  // OBJ: TNamed Silicon Si : 0 at: 0x55a63a979390
237  // OBJ: TNamed Mylar Myl : 0 at: 0x55a63d6a95f0
238  // OBJ: TNamed Plastic NE102 : 0 at: 0x55a63d64ea90
239  // OBJ: TNamed Nickel Ni : 0 at: 0x55a63d6afb90
240  // OBJ: TNamed Octofluoropropane C3F8 : 0 at: 0x55a63a9f8e00
241  // etc. etc.
242  // ~~~~
243  //
244  // For materials which are elements of the periodic table you can specify
245  // the isotope such as \c "64Ni", \c "13C", \c "natSn", etc. etc.
246 
247  init();
248  //are we dealing with an isotope ?
249  Char_t type[10];
250  Int_t iso_mass = 0;
251  if (sscanf(mat_type, "nat%s", type) != 1) {
252  if (sscanf(mat_type, "%d%s", &iso_mass, type) != 2) {
253  strcpy(type, mat_type);
254  }
255  }
256  if (iso_mass) SetMass(iso_mass);
257  SetType(type);
259  Warning("SetMaterial",
260  "Called for material %s which is unknown in current range table %s. Energy loss & range calculations impossible.",
262  else {
264  SetName(type);
265  }
266 }
267 
268 
269 
272 
273 KVMaterial::~KVMaterial()
274 {
275  //Destructor
276 }
277 
278 
279 
284 
286 {
287  //Define a specific isotopic mass for the material, e.g. for isotopically pure targets.
288  //
289  //For detectors, this changes the mass of the material composing the active layer (see KVDetector).
290 
291  if (GetActiveLayer()) {
293  return;
294  }
295  fAmasr = a;
296 }
297 
298 
299 
304 
306 {
307  //Returns atomic mass of material.
308  //
309  //For detectors, this is the mass of the material composing the active layer (see KVDetector).
310 
311  if (GetActiveLayer())
312  return GetActiveLayer()->GetMass();
314 }
315 
316 
317 
326 
328 {
329  //Returns kTRUE if a specific isotope has been chosen for the material
330  //using SetMass(), e.g.
331  // - for \f${}^{119}Sn\f$ this method returns kTRUE
332  // - for \f${}^{nat}Sn\f$ this method returns kFALSE
333  //
334  //For detectors, the material in question is that of the active layer (see KVDetector).
335  //\sa IsNat()
336  if (GetActiveLayer())
337  return GetActiveLayer()->IsIsotopic();
338  return (fAmasr != 0);
339 }
340 
341 
342 
351 
353 {
354  //Returns kFALSE if a specific isotope has been chosen for the material
355  //using SetMass() e.g.
356  // - for \f${}^{119}Sn\f$ this method returns kFALSE
357  // - for \f${}^{nat}Sn\f$ this method returns kTRUE
358  //
359  //For detectors, the material in question is that of the active layer (see KVDetector).
360  //\sa IsIsotopic()
361  if (GetActiveLayer())
362  return GetActiveLayer()->IsNat();
363  return (!IsIsotopic());
364 }
365 
366 
367 
368 
373 
375 {
376  // Returns kTRUE for gaseous material.
377  //
378  //For detectors, the material in question is that of the active layer (see KVDetector).
379 
380  if (GetActiveLayer())
381  return GetActiveLayer()->IsGas();
383 }
384 
385 
386 
387 
392 
394 {
395  //Returns atomic number of material.
396  //
397  //For detectors, the material in question is that of the active layer (see KVDetector).
398  if (GetActiveLayer())
399  return GetActiveLayer()->GetZ();
400  return fIonRangeTable->GetZ(GetType());
401 }
402 
403 
404 
405 
420 
422 {
423  // Returns density of material in \f$g/cm^{3}\f$.
424  //
425  //~~~~{.cpp}
426  //auto dens = mat.GetDensity()/(KVUnits::kg/KVUnits::litre); // in kg/litre
427  //~~~~
428  //
429  // For a gas, density is calculated from current pressure & temperature according to ideal gas law
430  // \f[
431  // \rho = \frac{pM}{RT}
432  // \f]
433  // with \f$M\f$ the mass of one mole of the gas, and \f$R\f$ the ideal gas constant.
434  //
435  //For detectors, the material in question is that of the active layer (see KVDetector).
436 
437  if (GetActiveLayer())
438  return GetActiveLayer()->GetDensity();
440  return fIonRangeTable->GetDensity(GetType());
441 }
442 
443 
444 
445 
453 
455 {
456  // Set the linear thickness of the material in cm, e.g.
457  //~~~~{.cpp}
458  //SetThickness( 30.*KVUnits::um ); set thickness to 30 microns
459  //~~~~
460  //
461  //For detectors, the material in question is that of the active layer (see KVDetector).
462 
463  if (GetActiveLayer()) {
465  return;
466  }
467  // recalculate area density
468  if (GetDensity() != 0)
469  fThick = t * GetDensity();
470  else
471  fThick = t;
472 
473 }
474 
475 
476 
477 
486 
488 {
489  // Returns the linear thickness of the material in cm.
490  // Use KVUnits to translate from one unit to another, e.g.
491  //~~~~{.cpp}
492  //auto micro_thick = mat.GetThickness()/KVUnits::um; thickness in microns
493  //~~~~
494  //
495  //For detectors, the material in question is that of the active layer (see KVDetector).
496 
497  if (GetActiveLayer())
498  return GetActiveLayer()->GetThickness();
499  if (GetDensity() != 0)
500  return fThick / GetDensity();
501  else
502  return fThick;
503 }
504 
505 
506 
507 
522 
523 void KVMaterial::SetAreaDensity(Double_t dens /* g/cm**2 */)
524 {
525  // Set area density in \f$g/cm^{2}\f$.
526  //
527  // For solids, area density can only be changed by changing the thickness of the material.
528  //
529  // For gases, the density depends on temperature and pressure - see GetDensity(). This method
530  // leaves temperature and pressure unchanged, therefore for gases also this
531  // method will effectively modify the linear dimension of the gas cell.
532  //
533  //~~~~{.cpp}
534  //mat.SetAreaDensity(500*KVUnits::ug); // set density in microgram/cm2
535  //~~~~
536  //
537  //For detectors, the material in question is that of the active layer (see KVDetector).
538 
539  if (GetActiveLayer())
541  fThick = dens;
542 }
543 
544 
545 
546 
555 
557 {
558  // Return area density of material in \f$g/cm^{2}\f$
559  //
560  //~~~~{.cpp}
561  //auto dens_mgcm2 = mat.GetAreaDensity()/KVUnits::mg; // in mg/cm2
562  //~~~~
563  //
564  //For detectors, the material in question is that of the active layer (see KVDetector).
565 
566  if (GetActiveLayer()) return GetActiveLayer()->GetAreaDensity();
567  return fThick;
568 }
569 
570 
571 
572 
582 
584 {
585  // Set the pressure of a gaseous material (in torr).
586  // The linear dimension (thickness) is kept constant, the area density changes.
587  //
588  //~~~~{.cpp}
589  //mat.SetPressure(50*KVUnits::mbar); // set pressure to 50mbar
590  //~~~~
591  //
592  //For detectors, the material in question is that of the active layer (see KVDetector).
593 
594  if (!IsGas()) return;
595  if (GetActiveLayer()) {
597  return;
598  }
599  // get current linear dimension of absorber
600  Double_t e = GetThickness();
601  fPressure = p;
602  // change area density to keep linear dimension constant
603  SetThickness(e);
604 }
605 
606 
607 
608 
609 
619 
621 {
622  // Returns the pressure of a gas (in torr).
623  // If the material is not a gas - see IsGas() - value is zero.
624  //
625  //~~~~{.cpp}
626  //auto press_mbar = mat.GetPressure()/KVUnits::mbar; // pressure in mbar
627  //~~~~
628  //
629  //For detectors, the material in question is that of the active layer (see KVDetector).
630 
631  if (!IsGas()) return 0.0;
632  if (GetActiveLayer())
633  return GetActiveLayer()->GetPressure();
634  return fPressure;
635 }
636 
637 
638 
639 
648 
650 {
651  // Set temperature of material in degrees celsius.
652  //
653  // This only has an effect on gaseous materials, where the resulting change in density
654  // changes the area density of the absorber (for fixed linear dimension).
655  // \sa GetDensity()
656  //
657  //For detectors, the material in question is that of the active layer (see KVDetector).
658 
659  if (!IsGas()) return;
660  if (GetActiveLayer()) {
662  return;
663  }
664  // get current linear dimension of absorber
665  Double_t e = GetThickness();
666  fTemp = t;
667  // change area density to keep linear dimension constant
668  SetThickness(e);
669 }
670 
671 
672 
673 
674 
679 
681 {
682  //Returns temperature of material in degrees celsius (only gaseous materials).
683  //
684  //For detectors, the material in question is that of the active layer (see KVDetector).
685 
686  if (GetActiveLayer())
687  return GetActiveLayer()->GetTemperature();
688  return fTemp;
689 }
690 
691 
692 
693 
699 
701 {
702  //\param[in] norm vector normal to the material, oriented from the origin towards the material
703  //\param[in] direction direction of motion of an ion
704  //\returns effective linear thickness of absorber (in cm) as 'seen' in given direction, taking into
705  // account the arbitrary orientation of the normal to the material's surface
706 
707  TVector3 n = norm.Unit();
708  TVector3 d = direction.Unit();
709  //absolute value of scalar product, in case direction is opposite to normal
710  Double_t prod = TMath::Abs(n * d);
711  return GetThickness() / TMath::Max(prod, 1.e-03);
712 }
713 
714 
715 
716 
722 
724 {
725  //\param[in] norm vector normal to the material, oriented from the origin towards the material
726  //\param[in] direction direction of motion of an ion
727  //\returns effective area density of absorber in \f$g/cm^{2}\f$ as 'seen' in the given direction, taking into
728  // account the arbitrary orientation of the normal to the material's surface
729 
730  TVector3 n = norm.Unit();
731  TVector3 d = direction.Unit();
732  //absolute value of scalar product, in case direction is opposite to normal
733  Double_t prod = TMath::Abs(n * d);
734  return GetAreaDensity() / TMath::Max(prod, 1.e-03);
735 }
736 
737 
738 
741 
743 {
744  //Show information on this material
745  cout << "KVMaterial: " << GetName() << " (" << GetType() << ")" << endl;
747  cout << " Pressure " << GetPressure() << " torr" << endl;
748  cout << " Thickness " << KVMaterial::GetThickness() << " cm" << endl;
749  cout << " Area density " << KVMaterial::GetAreaDensity() << " g/cm**2" << endl;
750  cout << "-----------------------------------------------" << endl;
751  cout << " Z = " << GetZ() << " atomic mass = " << GetMass() << endl;
752  cout << " Density = " << GetDensity() << " g/cm**3" << endl;
753  cout << "-----------------------------------------------" << endl;
754 }
755 
756 
757 
758 
768 
770 {
771  //\param[in] kvp pointer to a KVNucleus object describing a charged ion
772  //\param[in] norm [optional] vector normal to the material, oriented from the origin towards the material
773  //
774  //\returns The energy loss \f$\Delta E\f$ in MeV of a charged particle impinging on the absorber
775  //
776  //If the unit normal vector is given, the effective thickness of the material 'seen' by the particle
777  //depending on the orientation of its direction of motion with respect to the absorber is used for the calculation,
778  //rather than the nominal thickness corresponding to ions impinging perpendicularly.
779 
780  Double_t thickness;
781  if (norm) {
782  TVector3 p = kvn->GetMomentum();
783  thickness = GetEffectiveThickness((*norm), p);
784  }
785  else
786  thickness = GetThickness();
787  Double_t E_loss =
788  fIonRangeTable->GetLinearDeltaEOfIon(GetType(), kvn->GetZ(), kvn->GetA(), kvn->GetKE(),
789  thickness, fAmasr, fTemp, fPressure);
790  return E_loss;
791 }
792 
793 
794 
795 
803 
805 {
806  // \param[in] kvn KVNucleus describing properties of incident ion (\f$Z,A\f$ and with kinetic energy \f$E_{res}\f$)
807  // \param[in] norm [optional] vector normal to the material, oriented from the origin towards the material.
808  // \returns incident energy of ion \f$E_{inc}\f$ [MeV] deduced from residual energy \f$E_{res}=E_{inc}-\Delta E\f$.
809  //
810  //If \a norm is given, the effective thickness of the material 'seen' by the particle
811  //depending on its direction of motion is used for the calculation.
812 
813  Double_t thickness;
814  if (norm) {
815  TVector3 p = kvn->GetMomentum();
816  thickness = GetEffectiveThickness((*norm), p);
817  }
818  else
819  thickness = GetThickness();
820  Double_t E_inc = fIonRangeTable->
821  GetLinearEIncFromEResOfIon(GetType(), kvn->GetZ(), kvn->GetA(), kvn->GetKE(),
822  thickness, fAmasr, fTemp, fPressure);
823  return E_inc;
824 }
825 
826 
827 
828 
834 
836 {
837  // \param[in] Z atomic number of incident ion
838  // \param[in] A mass number of incident ion
839  // \param[in] Einc kinetic energy of incident ion
840  // \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]
841 
842  if (Z < 1) return 0.;
843  Double_t E_loss =
845 
846  return TMath::Max(E_loss, 0.);
847 }
848 
849 
850 
851 
864 
866 {
867  // \param[in] Z atomic number of incident ion
868  // \param[in] A mass number of incident ion
869  // \param[in] Einc kinetic energy of incident ion
870  // \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]
871  //
872  // Different units can be used with KVUnits:
873  //~~~~{.cpp}
874  // KVMaterial si("Si");
875  // si.GetRange(2,4,13)/KVUnits::mg;
876  //(long double) 25.190011L // range in silicon in mg/cm2 of 13 MeV 4He particles
877  //~~~~
878 
879  if (Z < 1) return 0.;
880  Double_t R =
882  return R;
883 }
884 
885 
886 
887 
901 
903 {
904  // \param[in] Z atomic number of incident ion
905  // \param[in] A mass number of incident ion
906  // \param[in] Einc kinetic energy of incident ion
907  // \returns linear range in [cm] in absorber for incident nucleus \f$Z,A\f$
908  // with kinetic energy \f$E_{inc}\f$ [MeV]
909  //
910  // Different units can be used with KVUnits:
911  //~~~~{.cpp}
912  // KVMaterial si("Si");
913  // si.GetLinearRange(2,4,13)/KVUnits::um;
914  //(long double) 108.11164L // range in silicon in microns of 13 MeV 4He particles
915  //~~~~
916 
917  if (Z < 1) return 0.;
918  Double_t R =
920  return R;
921 }
922 
923 
924 
925 
948 
950 {
951  // \param[in] Z atomic number of incident ion
952  // \param[in] A mass number of incident ion
953  // \param[in] Eres residual kinetic energy of ion after impinging on the absorber
954  // \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
955  //
956  //\b Example of use:
957  //~~~~{.cpp}
958  //KVMaterial si("Si", 300*KVUnits::um); // 300um silicon absorber
959  //KVNucleus alpha("4He",30); // 30MeV/u alpha particle
960  //
961  //si.DetectParticle(&alpha); // particle is slowed by silicon
962  //
963  //si.GetEnergyLoss();
964  //(double) 4.1371801 // energy lost by particle in silicon
965  //
966  //alpha.GetEnergy();
967  //(double) 115.86282 // residual energy of alpha after silicon
968  //
969  //si.GetDeltaEFromERes(2,4,115.86282);
970  //(double) 4.1371801 // energy loss calculated from residual energy
971  //~~~~
972 
973  if (Z < 1) return 0.;
974  Double_t E_loss = fIonRangeTable->
975  GetLinearDeltaEFromEResOfIon(
976  GetType(), Z, A, Eres, GetThickness(), fAmasr, fTemp, fPressure);
977  return E_loss;
978 }
979 
980 
981 
1018 
1020 {
1021  // \returns Calculated residual kinetic energy \f$E_{res}\f$ [MeV] of a nucleus \f$Z,A\f$ after the absorber from
1022  // the energy loss \f$\Delta E\f$ in the absorber. If \a dE is given, it is used instead of the current energy loss.
1023  //
1024  // \param[in] Z,A atomic and mass number of nucleus
1025  // \param[in] dE [optional] energy loss of nucleus in absorber
1026  // \param[in] type
1027  // \parblock
1028  // Determine the type of solution to use. Possible values are:
1029  // \arg SolType::kEmax [default]: solution corresponding to the highest incident energy is returned.
1030  // This is the solution found for \f$E_{inc}\f$ above that of the maximum of the \f$\Delta E(E_{inc})\f$ curve.
1031  // \arg SolType::kEmin : low energy solution (\f$E_{inc}\f$ below maximum of the \f$\Delta E(E_{inc})\f$ curve).
1032  // \endparblock
1033  //
1034  //\b Example of use:
1035  //~~~~{.cpp}
1036  //KVMaterial si("Si", 300*KVUnits::um); // 300um silicon absorber
1037  //KVNucleus alpha("4He",30); // 30MeV/u alpha particle
1038  //
1039  //si.DetectParticle(&alpha); // particle is slowed by silicon
1040  //
1041  //si.GetEnergyLoss();
1042  //(double) 4.1371801 // energy lost by particle in silicon
1043  //
1044  //alpha.GetEnergy();
1045  //(double) 115.86282 // residual energy of alpha after silicon
1046  //
1047  //si.GetEResFromDeltaE(2,4);
1048  //(double) 115.86282 // residual energy calculated from energy loss
1049  //~~~~
1050  //
1051  // \note If the energy loss in the absorber is greater than the maximum theoretical \f$\Delta E\f$ - given by GetMaxDeltaE() - then we return
1052  // the residual energy corresponding to the maximum - given by GetEIncOfMaxDeltaE().
1053  //
1054  // \note For detectors (see KVDetector), \a dE is the energy loss \f$\Delta E\f$ only in the \b active layer, not the total
1055  // energy lost by the particle crossing the detector; because for detectors with inactive layers \f$E_{inc}\geq \Delta E + E_{res}\f$.
1056 
1057  Double_t EINC = GetIncidentEnergy(Z, A, dE, type);
1058  return GetERes(Z, A, EINC);
1059 }
1060 
1061 
1062 
1063 
1094 
1096 {
1097  //\returns Calculated incident energy [MeV] of nucleus \f$Z,A\f$ corresponding to energy loss \f$\Delta E\f$
1098  //in this absorber. If \a delta_e is given, it is used instead of the current energy loss in this absorber.
1099  //
1100  //\param[in] Z,A atomic and mass number of nucleus
1101  //\param[in] delta_e [optional] energy loss of nucleus in absorber \f$\Delta E\f$ [MeV]
1102  //\param[in] type
1103  //\parblock
1104  //Determine the type of solution to use. Possible values are:
1105  // \arg SolType::kEmax [default]: solution corresponding to the highest incident energy is returned.
1106  //This is the solution found for \f$E_{inc}\f$ above that of the maximum of the \f$\Delta E(E_{inc})\f$ curve.
1107  // \arg SolType::kEmin : low energy solution (\f$E_{inc}\f$ below maximum of the \f$\Delta E(E_{inc})\f$ curve).
1108  //\endparblock
1109  //
1110  //\b Example of use:
1111  //~~~~{.cpp}
1112  //KVMaterial si("Si", 300*KVUnits::um); // 300um silicon absorber
1113  //KVNucleus alpha("4He",30); // 30MeV/u alpha particle
1114  //
1115  //si.DetectParticle(&alpha); // particle is slowed by silicon
1116  //
1117  //si.GetEnergyLoss();
1118  //(double) 4.1371801 // energy lost by particle in silicon
1119  //
1120  //si.GetIncidentEnergy(2,4);
1121  //(double) 120.00000 // incident energy of alpha calculated from energy loss
1122  //~~~~
1123  //
1124  //\note If the energy loss in the absorber is greater than the maximum theoretical \f$\Delta E\f$ - given by GetMaxDeltaE() - then we return
1125  //the incident energy corresponding to the maximum - given by GetEIncOfMaxDeltaE().
1126 
1127  if (Z < 1) return 0.;
1128 
1129  Double_t DE = (delta_e > 0 ? delta_e : GetEnergyLoss());
1130 
1133 }
1134 
1135 
1136 
1137 
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  // \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$
1167  //
1168  //\b Example of use:
1169  //~~~~{.cpp}
1170  //KVMaterial si("Si", 300*KVUnits::um); // 300um silicon absorber
1171  //KVNucleus alpha("4He",30); // 30MeV/u alpha particle
1172  //
1173  //si.DetectParticle(&alpha); // particle is slowed by silicon
1174  //
1175  //si.GetEnergyLoss();
1176  //(double) 4.1371801 // energy lost by particle in silicon
1177  //
1178  //alpha.GetEnergy();
1179  //(double) 115.86282 // residual energy of alpha after silicon
1180  //
1181  //si.GetERes(2,4,120.0);
1182  //(double) 115.86282 // residual energy calculated from incident energy
1183  //~~~~
1184 
1185  if (Z < 1) return 0.;
1186  if (IsGas() && GetPressure() == 0)
1187  return Einc;
1188 
1189  Double_t E_res =
1191 
1192  return E_res;
1193 }
1194 
1195 
1196 
1197 
1209 
1211 {
1212  //\param[in] kvp pointer to a KVNucleus object describing a charged ion
1213  //\param[in] norm [optional] vector normal to the material, oriented from the origin towards the material
1214  //
1215  //The energy loss \f$\Delta E\f$ of a charged particle traversing the absorber is calculated,
1216  //and the particle is slowed down by a corresponding amount
1217  //(the kinetic energy of the KVNucleus object passed as argument will be reduced by \f$\Delta E\f$, possibly to zero).
1218  //
1219  //If the unit normal vector is given, the effective thickness of the material 'seen' by the particle
1220  //depending on the orientation of its direction of motion with respect to the absorber is used for the calculation,
1221  //rather than the nominal thickness corresponding to ions impinging perpendicularly.
1222 
1223  kvp->SetIsDetected();//set flag to say that particle has been slowed down
1224  //If this is the first absorber that the particle crosses, we set a "reminder" of its
1225  //initial energy
1226  if (!kvp->GetPInitial())
1227  kvp->SetE0();
1228 
1229 #ifdef DBG_TRGT
1230  cout << "detectparticle in material " << GetType() << " of thickness "
1231  << GetThickness() << endl;
1232 #endif
1233  Double_t el = GetELostByParticle(kvp, norm);
1234  // set particle residual energy
1235  Double_t Eres = kvp->GetKE() - el;
1236  kvp->SetKE(Eres);
1237  // add to total of energy losses in absorber
1238  fELoss += el;
1239 }
1240 
1241 
1242 
1243 
1246 
1248 {
1249  // Reset absorber - set stored energy lost by particles in absorber to zero
1250  fELoss = 0.0;
1251 }
1252 
1253 
1254 #if ROOT_VERSION_CODE >= ROOT_VERSION(3,4,0)
1255 
1258 
1259 void KVMaterial::Copy(TObject& obj) const
1260 #else
1261 void KVMaterial::Copy(TObject& obj)
1262 #endif
1263 {
1264  // Make a copy of this material object
1265  KVBase::Copy(obj);
1266  ((KVMaterial&) obj).SetMaterial(GetType());
1267  ((KVMaterial&) obj).SetMass(GetMass());
1268  ((KVMaterial&) obj).SetPressure(GetPressure());
1269  ((KVMaterial&) obj).SetTemperature(GetTemperature());
1270  ((KVMaterial&) obj).SetThickness(GetThickness());
1271 }
1272 
1273 
1274 
1275 
1280 
1282 {
1283  // \param[in] Z,A atomic & mass numbers of incident ion
1284  // \param[in] Eres residual energy of ion after absorber
1285  // \returns incident energy of ion \f$E_{inc}\f$ [MeV] deduced from residual energy \f$E_{res}=E_{inc}-\Delta E\f$.
1286  if (Z < 1) return 0.;
1287 
1288  return fIonRangeTable->
1289  GetLinearEIncFromEResOfIon(GetType(), Z, A, Eres, GetThickness(), fAmasr, fTemp, fPressure);
1290 }
1291 
1292 
1293 
1294 
1298 
1300 {
1301  //\param[in] Z,A atomic and mass number of impinging ion
1302  //\returns incident energy in MeV for which the \f$\Delta E\f$-\f$E\f$ curve has a maximum
1303 
1304  if (Z < 1) return 0.;
1305 
1306  return fIonRangeTable->
1307  GetLinearEIncOfMaxDeltaEOfIon(GetType(), Z, A, GetThickness(), fAmasr, fTemp, fPressure);
1308 }
1309 
1310 
1311 
1312 
1320 
1322 {
1323  //\returns The maximum possible energy loss \f$\Delta E\f$ of a nucleus in the absorber
1324  //\param[in] Z,A atomic and mass number of the nucleus
1325  //
1326  //\sa GetEIncOfMaxDeltaE()
1327  //
1328  //\note For detectors, this is the maximum energy loss in the active layer.
1329 
1330  if (GetActiveLayer()) return GetActiveLayer()->GetMaxDeltaE(Z, A);
1331 
1332  if (Z < 1) return 0.;
1333 
1334  return fIonRangeTable->
1335  GetLinearMaxDeltaEOfIon(GetType(), Z, A, GetThickness(), fAmasr, fTemp, fPressure);
1336 }
1337 
1338 
1339 
1340 
1357 
1359 {
1360  // By default, return pointer to TGeoMedium corresponding to this KVMaterial.
1361  //
1362  // \param[in] med_name [optional] if it corresponds to the name of an already existing
1363  // medium, we return a pointer to this medium, or a nullptr if it does not exist.
1364  //
1365  // `med_name = "Vacuum"` is a special case: if the "Vacuum" does not exist, we create it.
1366  //
1367  // Instance of geometry manager class TGeoManager must be created before calling this
1368  // method, otherwise nullptr will be returned.
1369  //
1370  // If the required TGeoMedium is not already available in the TGeoManager, we create
1371  // a new TGeoMedium corresponding to the properties of this KVMaterial.
1372  // The name of the TGeoMedium (and associated TGeoMaterial) is the name of the KVMaterial.
1373  //
1374  // \note For detectors, the material in question is that of the active layer (see KVDetector).
1375 
1376  if (!gGeoManager) return nullptr;
1377 
1378  if (strcmp(med_name, "")) {
1379  TGeoMedium* gmed = gGeoManager->GetMedium(med_name);
1380  if (gmed) return gmed;
1381  else if (!strcmp(med_name, "Vacuum")) {
1382  // create material
1383  TGeoMaterial* gmat = new TGeoMaterial("Vacuum", 0, 0, 0);
1384  gmat->SetTitle("Vacuum");
1385  gmed = new TGeoMedium("Vacuum", 0, gmat);
1386  gmed->SetTitle("Vacuum");
1387  return gmed;
1388  }
1389  return nullptr;
1390  }
1391 
1392  // if object is a KVDetector, we return medium corresponding to the active layer
1393  if (GetActiveLayer()) return GetActiveLayer()->GetGeoMedium();
1394 
1395  // for gaseous materials, the TGeoMedium/Material name is of the form
1396  // gasname_pressure
1397  // e.g. C3F8_37.5 for C3F8 gas at 37.5 torr
1398  // each gas with different pressure has to have a separate TGeoMaterial/Medium
1399  TString medName;
1400  if (IsGas()) medName.Form("%s_%f", GetName(), GetPressure());
1401  else medName = GetName();
1402 
1403  TGeoMedium* gmed = gGeoManager->GetMedium(medName);
1404 
1405  if (gmed) return gmed;
1406 
1407  TGeoMaterial* gmat = gGeoManager->GetMaterial(medName);
1408 
1409  if (!gmat) {
1410  // create material
1411  gmat = GetRangeTable()->GetTGeoMaterial(GetName());
1412  gmat->SetPressure(GetPressure());
1413  gmat->SetTemperature(GetTemperature());
1414  gmat->SetTransparency(0);
1415  gmat->SetName(medName);
1416  gmat->SetTitle(GetName());
1417  }
1418 
1419  // create medium
1420  static Int_t numed = 1; // static counter variable used to number media
1421  gmed = new TGeoMedium(medName, numed, gmat);
1422  numed += 1;
1423 
1424  return gmed;
1425 }
1426 
1427 
1428 
1435 
1437 {
1438  // \param[in] nuc definition of charged particle
1439  // \param[in] npts number of points to use
1440  // \param[in] Emin minimum incident energy \f$E\f$
1441  // \param[in] Emax maximum incident energy \f$E\f$
1442  // \returns TGraph with the \f$\Delta E\f$-\f$E\f$ curve for this material for a given charged particle
1443 
1444  auto g = new TGraph;
1445  KVValueRange<Double_t> R(Emin, Emax);
1446  for (int i = 0; i < npts; ++i) {
1447  auto E = R.ValueIofN(i, npts);
1448  g->SetPoint(i, E, GetDeltaE(nuc.GetZ(), nuc.GetA(), E));
1449  }
1450  return g;
1451 }
1452 
1453 
1454 
1461 
1463 {
1464  //\param[in] Z,A atomic & mass numbers of ion
1465  // \returns maximum incident energy [MeV] for which range tables are valid
1466  // for this material and ion with \f$Z,A\f$.
1467  //
1468  //\note For detectors, the limit of validity for the material composing the active layer is returned (see KVDetector).
1469  if (GetActiveLayer()) return GetActiveLayer()->GetEmaxValid(Z, A);
1470  return fIonRangeTable->GetEmaxValid(GetType(), Z, A);
1471 }
1472 
1473 
1474 
1479 
1481 {
1482  //\param[in] Z,A atomic & mass numbers of ion
1483  // \returns incident energy \f$E_{inc}\f$ [MeV] for which ion \f$Z,A\f$ has a range equal to the
1484  // thickness of this absorber (see GetRange(), GetLinearRange()).
1485 
1487 }
1488 
1489 
int Int_t
ClassImp(KVPartitionList) void KVPartitionList
Initialisation.
#define d(i)
#define e(i)
char Char_t
bool Bool_t
double Double_t
const char Option_t
R__EXTERN TEnv * gEnv
int type
R__EXTERN TGeoManager * gGeoManager
Base class for KaliVeda framework.
Definition: KVBase.h:141
virtual const Char_t * GetType() const
Definition: KVBase.h:176
virtual void SetType(const Char_t *str)
Definition: KVBase.h:172
virtual void Copy(TObject &) const
Make a copy of this object.
Definition: KVBase.cpp:394
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.)
virtual 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.
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.)
virtual Double_t GetEResOfIon(const Char_t *mat, Int_t Z, Int_t A, Double_t E, Double_t r, 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 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:93
Double_t GetZ() const
Definition: KVMaterial.cpp:393
virtual Double_t GetPressure() const
Definition: KVMaterial.cpp:620
virtual void SetPressure(Double_t)
Definition: KVMaterial.cpp:583
virtual void Copy(TObject &obj) const
Make a copy of this material object.
virtual void SetTemperature(Double_t)
Definition: KVMaterial.cpp:649
Double_t GetEffectiveAreaDensity(TVector3 &norm, TVector3 &direction)
Definition: KVMaterial.cpp:723
virtual void SetThickness(Double_t thick)
Definition: KVMaterial.cpp:454
virtual Double_t GetThickness() const
Definition: KVMaterial.cpp:487
Double_t GetDensity() const
Definition: KVMaterial.cpp:421
Double_t fThick
area density of absorber in g/cm**2
Definition: KVMaterial.h:104
Bool_t IsGas() const
Definition: KVMaterial.cpp:374
virtual TGeoMedium * GetGeoMedium(const Char_t *="")
static KVIonRangeTable * GetRangeTable()
Definition: KVMaterial.cpp:166
virtual Double_t GetEnergyLoss() const
Definition: KVMaterial.h:143
virtual void Print(Option_t *option="") const
Show information on this material.
Definition: KVMaterial.cpp:742
Int_t fAmasr
isotopic mass of element
Definition: KVMaterial.h:103
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:107
virtual Double_t GetEIncOfMaxDeltaE(Int_t Z, Int_t A)
virtual Double_t GetPunchThroughEnergy(Int_t Z, Int_t A)
Bool_t IsNat() const
Definition: KVMaterial.cpp:352
void SetMass(Int_t a)
Definition: KVMaterial.cpp:285
void init()
Definition: KVMaterial.cpp:50
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:187
void SetAreaDensity(Double_t dens)
Definition: KVMaterial.cpp:523
Double_t GetAreaDensity() const
Definition: KVMaterial.cpp:556
virtual Double_t GetParticleEIncFromERes(KVNucleus *, TVector3 *norm=nullptr)
Definition: KVMaterial.cpp:804
Double_t fTemp
gas temperature in degrees celsius
Definition: KVMaterial.h:106
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:105
virtual void DetectParticle(KVNucleus *, TVector3 *norm=nullptr)
virtual Double_t GetTemperature() const
Definition: KVMaterial.cpp:680
virtual Double_t GetIncidentEnergyFromERes(Int_t Z, Int_t A, Double_t Eres)
virtual void SetMaterial(const Char_t *type)
Definition: KVMaterial.cpp:225
virtual Double_t GetDeltaEFromERes(Int_t Z, Int_t A, Double_t Eres)
Definition: KVMaterial.cpp:949
static KVIonRangeTable * fIonRangeTable
pointer to class used to calculate charged particle ranges & energy losses
Definition: KVMaterial.h:96
virtual Double_t GetERes(Int_t Z, Int_t A, Double_t Einc)
virtual Double_t GetELostByParticle(KVNucleus *, TVector3 *norm=nullptr)
Definition: KVMaterial.cpp:769
virtual Double_t GetDeltaE(Int_t Z, Int_t A, Double_t Einc)
Definition: KVMaterial.cpp:835
virtual void Clear(Option_t *opt="")
Reset absorber - set stored energy lost by particles in absorber to zero.
KVMaterial()
default ctor
Definition: KVMaterial.cpp:77
virtual Double_t GetRange(Int_t Z, Int_t A, Double_t Einc)
Definition: KVMaterial.cpp:865
Bool_t IsIsotopic() const
Definition: KVMaterial.cpp:327
Double_t GetEffectiveThickness(TVector3 &norm, TVector3 &direction)
Definition: KVMaterial.cpp:700
virtual Double_t GetLinearRange(Int_t Z, Int_t A, Double_t Einc)
Definition: KVMaterial.cpp:902
virtual KVMaterial * GetActiveLayer() const
Definition: KVMaterial.h:184
Double_t GetMass() const
Definition: KVMaterial.cpp:305
Description of properties and kinematics of atomic nuclei.
Definition: KVNucleus.h:125
Int_t GetA() const
Definition: KVNucleus.cpp:799
Int_t GetZ() const
Return the number of proton / atomic number.
Definition: KVNucleus.cpp:770
TVector3 * GetPInitial() const
Definition: KVParticle.h:728
TVector3 GetMomentum() const
Definition: KVParticle.h:606
void SetKE(Double_t ecin)
Definition: KVParticle.cpp:230
void SetE0(TVector3 *e=0)
Definition: KVParticle.h:717
void SetIsDetected()
Definition: KVParticle.h:732
Double_t GetKE() const
Definition: KVParticle.h:616
Range of values specified by minimum, maximum.
Definition: KVValueRange.h:17
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 const char * GetName() const
virtual void SetTitle(const char *title="")
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
void Form(const char *fmt,...)
TVector3 Unit() const
const Int_t n
gr SetName("gr")
const long double atm
Definition: KVUnits.h:79
const long double g
masses
Definition: KVUnits.h:72
Type GetType(const std::string &Name)
constexpr Double_t E()
constexpr Double_t R()
Double_t Abs(Double_t d)
Double_t Max(Double_t a, Double_t b)
auto * a