KaliVeda
Toolkit for HIC analysis
Loading...
Searching...
No Matches
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 "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
33using 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;
65 fTemp = 19.0;
66 // create default range table singleton if not already done
68 fAbsorberVolume = nullptr;
69}
70
71
72//
73
76
78{
79 //default ctor
80 init();
81}
82
83
84
87
88KVMaterial::KVMaterial(const Char_t* type, const Double_t thick)
89{
90 // Create material with given type and linear thickness in cm.
91
92 init();
94 SetThickness(thick);
95}
96
97
98
101
102KVMaterial::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();
108 SetAreaDensity(area_density);
109}
110
111
112
123
124KVMaterial::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
225void 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[50];
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
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();
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
523void 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
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
601 fPressure = p;
602 // change area density to keep linear dimension constant
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
666 fTemp = t;
667 // change area density to keep linear dimension constant
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
1260#else
1261void 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
1412 gmat->SetPressure(GetPressure());
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
#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:142
virtual void SetType(const Char_t *str)
Definition KVBase.h:173
virtual void Copy(TObject &) const
Make a copy of this object.
Definition KVBase.cpp:394
virtual const Char_t * GetType() const
Definition KVBase.h:177
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:94
Double_t GetZ() const
virtual Double_t GetPressure() const
virtual void SetPressure(Double_t)
virtual void Copy(TObject &obj) const
Make a copy of this material object.
virtual void SetTemperature(Double_t)
Double_t GetEffectiveAreaDensity(TVector3 &norm, TVector3 &direction)
virtual void SetThickness(Double_t thick)
virtual Double_t GetThickness() const
Double_t GetDensity() const
Double_t fThick
area density of absorber in g/cm**2
Definition KVMaterial.h:105
virtual KVMaterial * GetActiveLayer() const
Definition KVMaterial.h:185
Bool_t IsGas() const
virtual TGeoMedium * GetGeoMedium(const Char_t *="")
static KVIonRangeTable * GetRangeTable()
virtual Double_t GetEnergyLoss() const
Definition KVMaterial.h:144
virtual void Print(Option_t *option="") const
Show information on this material.
Int_t fAmasr
isotopic mass of element
Definition KVMaterial.h:104
Double_t GetEmaxValid(Int_t Z, Int_t A)
TGeoVolume * fAbsorberVolume
pointer to corresponding volume in ROOT geometry
Definition KVMaterial.h:99
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:108
virtual Double_t GetEIncOfMaxDeltaE(Int_t Z, Int_t A)
virtual Double_t GetPunchThroughEnergy(Int_t Z, Int_t A)
Bool_t IsNat() const
void SetMass(Int_t a)
void init()
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)
void SetAreaDensity(Double_t dens)
Double_t GetAreaDensity() const
virtual Double_t GetParticleEIncFromERes(KVNucleus *, TVector3 *norm=nullptr)
Double_t fTemp
gas temperature in degrees celsius
Definition KVMaterial.h:107
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:106
virtual void DetectParticle(KVNucleus *, TVector3 *norm=nullptr)
virtual Double_t GetTemperature() const
virtual Double_t GetIncidentEnergyFromERes(Int_t Z, Int_t A, Double_t Eres)
virtual void SetMaterial(const Char_t *type)
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:97
virtual Double_t GetERes(Int_t Z, Int_t A, Double_t Einc)
virtual Double_t GetELostByParticle(KVNucleus *, TVector3 *norm=nullptr)
virtual Double_t GetDeltaE(Int_t Z, Int_t A, Double_t Einc)
virtual void Clear(Option_t *opt="")
Reset absorber - set stored energy lost by particles in absorber to zero.
KVMaterial()
default ctor
virtual ~KVMaterial()
Destructor.
virtual Double_t GetRange(Int_t Z, Int_t A, Double_t Einc)
Bool_t IsIsotopic() const
Double_t GetEffectiveThickness(TVector3 &norm, TVector3 &direction)
virtual Double_t GetLinearRange(Int_t Z, Int_t A, Double_t Einc)
Double_t GetMass() const
Description of properties and kinematics of atomic nuclei.
Definition KVNucleus.h:126
Int_t GetA() const
Int_t GetZ() const
Return the number of proton / atomic number.
TVector3 * GetPInitial() const
Definition KVParticle.h:726
TVector3 GetMomentum() const
Definition KVParticle.h:604
void SetKE(Double_t ecin)
void SetE0(TVector3 *e=0)
Definition KVParticle.h:715
void SetIsDetected()
Definition KVParticle.h:730
Double_t GetKE() const
Definition KVParticle.h:614
Range of values specified by minimum, maximum.
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
void Form(const char *fmt,...)
TVector3 Unit() const
const Int_t n
const long double atm
Definition KVUnits.h:79
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)
TArc a
ClassImp(TPyArg)