KaliVeda
Toolkit for HIC analysis
KVRangeYanez.cpp
1 //Created by KVClassFactory on Thu Sep 27 14:48:55 2012
2 //Author: John Frankland,,,
3 
4 #include "KVRangeYanez.h"
5 #include "KVRangeYanezMaterial.h"
6 #include "TString.h"
7 #include "KVNucleus.h"
8 #include "KVNumberList.h"
9 #include <KVSystemDirectory.h>
10 #include <KVSystemFile.h>
11 #include <Riostream.h>
12 using namespace std;
13 
15 
16 KVHashList* KVRangeYanez::fMaterials = 0x0;
17 
18 
37 
39  : KVIonRangeTable("RANGE",
40  "Interface to Range dE/dx and range library (Ricardo Yanez)")
41 {
42  // Default constructor
43  //
44  // Predefined materials are created based on the contents of the file(s) whose
45  // names are given as values of the variable `RANGE.PredefMaterials`
46  //
47  // A default file is specified in the main `.kvrootrc` file.
48  //
49  // If you want to add your own definitions, just put in your `.kvrootrc` file:
50  //~~~~~~~~~~~
51  //+RANGE.PredefMaterials: myfile1.dat
52  //+RANGE.PredefMaterials: myfile2.dat
53  //~~~~~~~~~~~
54  // If you want to override the default definitions:
55  //~~~~~~~~~~~
56  //RANGE.PredefMaterials: myfile1.dat
57  //+RANGE.PredefMaterials: myfile2.dat
58  //~~~~~~~~~~~
59 
60  KVString DataFilePaths = gEnv->GetValue("RANGE.PredefMaterials", "");
61  DataFilePaths.Begin(" ");
62  KVString nextPath;
63  KVString lastPath;
64  while (!DataFilePaths.End()) {
65  nextPath = DataFilePaths.Next();
66  if (nextPath == lastPath) break; //check for double occurrence of last file : TEnv bug?
67  lastPath = nextPath;
68  ReadMaterials(nextPath);
69  }
70 
71  // directory where any materials defined by user are stored
72  fLocalMaterialsDirectory = GetWORKDIRFilePath("RANGE");
73  if (!gSystem->AccessPathName(fLocalMaterialsDirectory)) {
74  // read all materials in directory if it exists
75  KVSystemDirectory matDir("matDir", fLocalMaterialsDirectory);
76  TIter nxtfil(matDir.GetListOfFiles());
77  KVSystemFile* fil;
78  while ((fil = (KVSystemFile*)nxtfil())) {
79  if (TString(fil->GetName()).EndsWith(".dat")) ReadMaterials(fil->GetFullPath());
80  }
81  }
82  fDoNotSaveMaterials = kFALSE;
83 }
84 
85 
86 
87 
89 
91 {
92  obj.Copy(*this);
93 }
94 
95 
96 
97 
99 
100 void KVRangeYanez::Copy(TObject& obj) const
101 {
103  KVRangeYanez& CastedObj = (KVRangeYanez&)obj;
104  CastedObj.fLocalMaterialsDirectory = fLocalMaterialsDirectory;
105  CastedObj.fDoNotSaveMaterials = fDoNotSaveMaterials;
106 }
107 
108 
109 
114 
115 KVIonRangeTableMaterial* KVRangeYanez::GetMaterialWithNameOrType(const Char_t* material) const
116 {
117  // Returns pointer to material of given name or type if it has been defined.
118  //
119  // \param[in] material name or type of material to retrieve
120 
121  CheckMaterialsList();
122  KVIonRangeTableMaterial* M = (KVIonRangeTableMaterial*)fMaterials->FindObject(material);
123  if (!M) {
124  M = (KVIonRangeTableMaterial*)fMaterials->FindObjectByType(material);
125  }
126  return M;
127 }
128 
129 
130 
132 
134 {
135  printf("KVRangeYanez::%s\n%s\n", GetName(), GetTitle());
136  Int_t n = (fMaterials ? fMaterials->GetEntries() : 0);
137  if (n) {
138  printf("\nEnergy loss & range tables loaded for %d materials:\n\n", fMaterials->GetEntries());
139  fMaterials->Print();
140  }
141  else
142  printf("\nEnergy loss & range tables loaded for 0 materials.\n");
143 }
144 
145 
146 
153 
155 {
156  // Create and fill a list of all materials for which range tables exist.
157  //
158  // Each entry is a TNamed with the name and type (title) of the material.
159  //
160  // User's responsibility to delete list after use (it owns its objects).
161 
162  TObjArray* list = new TObjArray(fMaterials->GetEntries());
163  list->SetOwner(kTRUE);
164  TIter next(fMaterials);
166  while ((mat = (KVIonRangeTableMaterial*)next())) {
167  list->Add(new TNamed(mat->GetName(), mat->GetType()));
168  }
169  return list;
170 }
171 
172 
174 
175 void KVRangeYanez::CheckMaterialsList() const
176 {
177  if (!fMaterials) {
178  fMaterials = new KVHashList;
179  fMaterials->SetName("RANGE materials list");
180  fMaterials->SetOwner();
181  }
182 }
183 
184 
199 
201 {
202  // Adds a material composed of a single chemical element.
203  //
204  // \param[in] z atomic number \f$Z\f$ of element
205  // \param[in] a [optional] mass number \f$A\f$ of isotope
206  //
207  // If the mass number of the isotope \f$A\f$ is not specified, we create a material containing the naturally
208  // occuring isotopes of the given element, weighted according to natural abundance.
209  //
210  // If the mass is given, the material name will be `"Xxx-A"` where `Xxx` is the name of the element
211  // - e.g. `"Calcium-48"`, `"Tin-124"`, etc.
212  //
213  // Otherwise, we just use the element symbol and name for naturally-occurring
214  // mixtures of atomic elements (`"Ca"`, `"Calcium"`, etc.).
215 
217  if (!a) mat = MakeNaturallyOccuringElementMixture(z, a); // this may set a!=0 if only one isotope exists in nature
218  if (a) {
219  auto d = get_element_density(z);
220  TString state = "solid";
221  if (is_gas(z)) state = "gas";
222  mat = new KVRangeYanezMaterial(this, Form("%s-%d", get_element_name(z).c_str(), a),
223  get_element_symbol(z).c_str(),
224  state, d ? *d : 0., z, a);
225  mat->Initialize();
226  }
227  CheckMaterialsList();
228  fMaterials->Add(mat);
229  if (!fDoNotSaveMaterials) SaveMaterial(mat);
230  return mat;
231 }
232 
233 
234 
250 
252  const std::vector<CompoundFormulaElement>& elements, Double_t density) const
253 {
254  // Adds a compound material with a simple formula composed of different elements
255  //
256  // \param[in] name name for the new compound (no spaces)
257  // \param[in] symbol chemical symbol for compound
258  // \param[in] elements vector of elemental components
259  // \param[in] density in \f$g/cm^{3}\f$, only required if compound is a solid
260  //
261  // Example of use:
262  //
263  //~~~{.cpp}
264  // KVRangeYanez irt;
265  // irt.AddCompoundMaterial("polyethylene", "CH2", {{6,12,1},{1,1,2}}, 0.940);
266  //~~~
267  //
268 
269  TString state = "gas";
270  if (density > 0) state = "solid";
271  KVRangeYanezMaterial* mat =
272  new KVRangeYanezMaterial(this, name, symbol, state, density);
273  for (auto& el : elements) {
274  mat->AddCompoundElement(el.Z, el.A, el.natoms);
275  }
276  mat->Initialize();
277  CheckMaterialsList();
278  fMaterials->Add(mat);
279  if (!fDoNotSaveMaterials) SaveMaterial(mat);
280  return mat;
281 }
282 
283 
284 
298 
300  const std::vector<MixtureFormulaElement>& elements, Double_t density) const
301 {
302  // Adds a material which is a mixture of either elements or compounds:
303  //
304  // \param[in] name name for the new mixture (no spaces)
305  // \param[in] symbol chemical symbol for mixture
306  // \param[in] elements vector of elemental components
307  // \param[in] density in \f$g/cm^{3}\f$, if mixture is a solid
308  // Example of use:
309  //
310  //~~~{.cpp}
311  // KVRangeYanez irt;
312  // irt.AddMixedMaterial("Air", "Air", {{7,14,2,0.78},{8,16,2,0.21},{18,40,1,0.01}});
313  //~~~
314 
315  TString state = "gas";
316  if (density > 0) state = "solid";
317  KVRangeYanezMaterial* mat =
318  new KVRangeYanezMaterial(this, name, symbol, state, density);
319  for (auto& el : elements) {
320  mat->AddMixtureElement(el.Z, el.A, el.natoms, el.proportion);
321  }
322  mat->Initialize();
323  CheckMaterialsList();
324  fMaterials->Add(mat);
325  if (!fDoNotSaveMaterials) SaveMaterial(mat);
326  return mat;
327 }
328 
329 
330 
340 
342 {
343  // Create a material containing the naturally occuring isotopes of the given element,
344  // weighted according to their abundance.
345  //
346  // \param[in] z atomic number of element
347  // \param[out] a mass number of unique isotope, if 100% abundance
348  //
349  // if there is only one naturally occurring isotope of the element we set `a` to this isotope
350  // and don't create any material
351 
352  KVNucleus nuc(z);
353  KVNumberList isotopes = nuc.GetKnownARange();
354  isotopes.Begin();
355  while (!isotopes.End()) {
356  nuc.SetA(isotopes.Next());
357  if (nuc.GetAbundance() == 100.) {
358  a = nuc.GetA();
359  return nullptr;
360  }
361  }
362 
363  TString state = "solid";
364  if (is_gas(z)) state = "gas";
365  KVRangeYanezMaterial* mat =
366  new KVRangeYanezMaterial(this,
367  get_element_name(z).c_str(), get_element_symbol(z).c_str(),
368  state, get_element_density(z).value_or(0.));
369  isotopes.Begin();
370  while (!isotopes.End()) {
371  nuc.SetA(isotopes.Next());
372  auto abundance = nuc.GetAbundance();
373  if (abundance) mat->AddMixtureElement(z, nuc.GetA(), 1, *abundance/100);
374  }
375  mat->Initialize();
376  return (KVIonRangeTableMaterial*)mat;
377 }
378 
379 
380 
383 
385 {
386  // Read materials from file whose name is given
387 
388  TString DataFilePath = filename;
389 
390  ifstream filestream;
391  if (!SearchAndOpenKVFile(DataFilePath, filestream, "data")) {
392  KVError::Error(this, "ReadPredefinedMaterials", "Cannot open %s for reading", DataFilePath.Data());
393  return kFALSE;
394  }
395  Info("ReadPredefinedMaterials", "Reading materials in file : %s", filename);
396 
397  fDoNotSaveMaterials = kTRUE; //don't write what we just read!!
398 
399  Bool_t compound, mixture;
400  compound = mixture = kFALSE;
401 
402  KVString line;
403  while (filestream.good()) {
404  line.ReadLine(filestream);
405  if (filestream.good()) {
406  if (line.BeginsWith("//")) continue;
407  if (line.BeginsWith("COMPOUND")) {
408  compound = kTRUE;
409  mixture = kFALSE;
410  }
411  else if (line.BeginsWith("MIXTURE")) {
412  compound = kFALSE;
413  mixture = kTRUE;
414  }
415  else if (line.BeginsWith("ELEMENT")) {
416  compound = mixture = kFALSE;
417  }
418  if (compound || mixture) {
419  // new compound or mixed material
420  KVString name, symbol, state;
421  Double_t density = -1;
422  KVString element;
423  std::vector<CompoundFormulaElement> compound_elements;
424  std::vector<MixtureFormulaElement> mixture_elements;
425  Int_t nelem = 0;
426  line.ReadLine(filestream);
427  while (filestream.good() && !line.IsWhitespace() && line != "\n") {
428  line.Begin("=");
429  KVString next = line.Next();
430  if (next == "name") name = line.Next();
431  else if (next == "symbol") symbol = line.Next();
432  else if (next == "state") state = line.Next();
433  else if (next == "density") density = line.Next().Atof();
434  else if (next == "nelem") {
435  nelem = line.Next().Atoi();
436  for (int i = 0; i < nelem; i++) {
437  line.ReadLine(filestream);
438  line.Begin(" ");
439  element = line.Next();
440  auto a = KVNucleus::IsMassGiven(element);
441  KVNucleus n(element);
442  auto z = n.GetZ();
443  if (!a) a = TMath::Nint(n.GetNaturalA());
444  auto natoms = line.Next().Atoi();
445  if (mixture) {
446  auto proportion = line.Next().Atof();
447  mixture_elements.push_back({z, a, natoms, proportion});
448  }
449  else {
450  compound_elements.push_back({z, a, natoms});
451  }
452  }
453  }
454  line.ReadLine(filestream, kFALSE); //do not skip 'whitespace'
455  }
456  if (compound) AddCompoundMaterial(name, symbol, compound_elements, density);
457  else if (mixture) AddMixedMaterial(name, symbol, mixture_elements, density);
458  compound = mixture = kFALSE;
459  }
460  else {
461  // new isotopically pure material
462  KVString name, symbol, state;
463  line.ReadLine(filestream);
464  while (filestream.good() && !line.IsWhitespace() && line != "\n") {
465  line.Begin("=");
466  KVString next = line.Next();
467  if (next == "name") name = line.Next();
468  else if (next == "symbol") symbol = line.Next();
469  else if (next == "state") state = line.Next();
470  line.ReadLine(filestream, kFALSE); //do not skip 'whitespace'
471  }
472  KVNucleus nuc(symbol);
473  AddElementalMaterial(nuc.GetZ(), nuc.GetA());
474  }
475  }
476  }
477  fDoNotSaveMaterials = kFALSE;
478  return kTRUE;
479 }
480 
481 
482 
490 
491 void KVRangeYanez::SaveMaterial(KVIonRangeTableMaterial* mat) const
492 {
493  // Write definition of material in a file in the directory
494  //
495  // $(WORKING_DIR)/RANGE
496  //
497  // All files in this directory are read when the table is initialised
498 
499  // make directory if needed
500  if (gSystem->AccessPathName(fLocalMaterialsDirectory)) {
501  gSystem->mkdir(fLocalMaterialsDirectory, true);
502  gSystem->Chmod(fLocalMaterialsDirectory, 0755);
503  }
504  TString matfilename(mat->GetName());
505  matfilename.ReplaceAll(" ", "_"); // no spaces in filenames
506  matfilename += ".dat";
507  ofstream matfil;
508  if (SearchAndOpenKVFile(matfilename, matfil, fLocalMaterialsDirectory)) {
509  dynamic_cast<KVRangeYanezMaterial*>(mat)->SaveMaterial(matfil);
510  matfil.close();
511  }
512 }
513 
514 
int Int_t
#define d(i)
bool Bool_t
char Char_t
constexpr Bool_t kFALSE
double Double_t
constexpr Bool_t kTRUE
const char Option_t
R__EXTERN TEnv * gEnv
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 filename
char name[80]
char * Form(const char *fmt,...)
R__EXTERN TSystem * gSystem
virtual const Char_t * GetType() const
Definition: KVBase.h:177
static const Char_t * GetWORKDIRFilePath(const Char_t *namefile="")
Definition: KVBase.cpp:120
void Copy(TObject &) const override
Make a copy of this object.
Definition: KVBase.cpp:396
static Bool_t SearchAndOpenKVFile(const Char_t *name, KVSQLite::database &dbfile, const Char_t *kvsubdir="")
Definition: KVBase.cpp:651
Extended version of ROOT THashList.
Definition: KVHashList.h:29
Material for use in energy loss & range calculations.
void AddCompoundElement(Int_t Z, Int_t A, Int_t Natoms)
void AddMixtureElement(Int_t Z, Int_t A, Int_t Natoms, Double_t Proportion)
Abstract base class for calculation of range & energy loss of charged particles in matter.
std::string get_element_name(int z) const
bool is_gas(int z) const
std::string get_element_symbol(int z) const
std::optional< double > get_element_density(int z) const
Description of properties and kinematics of atomic nuclei.
Definition: KVNucleus.h:108
std::optional< double > GetAbundance(std::optional< int > z={}, std::optional< int > a={}) const
Definition: KVNucleus.cpp:1179
Int_t GetA() const
Definition: KVNucleus.cpp:805
static Int_t IsMassGiven(const Char_t *)
Definition: KVNucleus.cpp:149
void SetA(Int_t a)
Definition: KVNucleus.cpp:658
KVNumberList GetKnownARange(std::optional< int > z={}, std::optional< double > tmin={}) const
Definition: KVNucleus.cpp:1342
Int_t GetZ() const
Return the number of proton / atomic number.
Definition: KVNucleus.cpp:776
Strings used to represent a set of ranges of values.
Definition: KVNumberList.h:86
Bool_t End(void) const
Definition: KVNumberList.h:200
void Begin(void) const
Int_t Next(void) const
Description of absorber for the Range dE/dx and range library.
Interface to Range dE/dx and range library.
Definition: KVRangeYanez.h:26
void Copy(TObject &) const override
Bool_t ReadMaterials(const Char_t *filename) const override
Read materials from file whose name is given.
void Print(Option_t *="") const override
TObjArray * GetListOfMaterials() override
KVIonRangeTableMaterial * AddElementalMaterial(Int_t z, Int_t a=0) const override
virtual KVIonRangeTableMaterial * AddMixedMaterial(const Char_t *name, const Char_t *symbol, const std::vector< MixtureFormulaElement > &elements, Double_t density=-1.0) const override
virtual KVIonRangeTableMaterial * AddCompoundMaterial(const Char_t *name, const Char_t *symbol, const std::vector< CompoundFormulaElement > &elements, Double_t density=-1.0) const override
KVIonRangeTableMaterial * MakeNaturallyOccuringElementMixture(Int_t z, Int_t &a) const
void Add(TObject *obj) override
TObject * FindObject(const char *name) const override
void SetOwner(Bool_t enable=kTRUE) override
virtual TObject * FindObjectByType(const Char_t *) const
Extension of ROOT TString class which allows backwards compatibility with ROOT v3....
Definition: KVString.h:73
void Begin(TString delim) const
Definition: KVString.cpp:565
Bool_t End() const
Definition: KVString.cpp:634
KVString Next(Bool_t strip_whitespace=kFALSE) const
Definition: KVString.cpp:695
Extension of ROOT TSystemDirectory class, handling browsing directories on disk.
TList * GetListOfFiles() const override
Extended ROOT TSystemFile with added info on file size etc.
Definition: KVSystemFile.h:18
const Char_t * GetFullPath() const
Definition: KVSystemFile.h:49
virtual void Print(Option_t *option, const char *wildcard, Int_t recurse=1) const
void SetName(const char *name)
virtual Int_t GetEntries() const
virtual void SetOwner(Bool_t enable=kTRUE)
virtual const char * GetValue(const char *name, const char *dflt) const
const char * GetName() const override
const char * GetTitle() const override
void Add(TObject *obj) override
virtual void Info(const char *method, const char *msgfmt,...) const
const char * Data() const
virtual int Chmod(const char *file, UInt_t mode)
virtual int mkdir(const char *name, Bool_t recursive=kFALSE)
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
TLine * line
void compound()
const Int_t n
void Error(UserClass p, const char *location, const char *va_(fmt),...)
Definition: KVError.h:116
Int_t Nint(T x)
TArc a
ClassImp(TPyArg)