GEMC  2.3
Geant4 Monte-Carlo Framework
material_factory.cc
Go to the documentation of this file.
1 // c++ headers
2 #include <set>
3 
4 // gemc headers
5 #include "material_factory.h"
6 #include "cpp_materials.h"
7 #include "gdml_materials.h"
8 #include "mysql_materials.h"
9 #include "text_materials.h"
10 #include "string_utilities.h"
11 
12 // G4 headers
13 #include "G4NistManager.hh"
14 
15 // CLHEP units
16 #include "CLHEP/Units/PhysicalConstants.h"
17 using namespace CLHEP;
18 
19 materials *getMaterialFactory(map<string, materialFactory> *factory, string materialsMethod)
20 {
21 
22  if(factory->find(materialsMethod) == factory->end())
23  {
24  cout << endl << endl << " >>> WARNING: " << materialsMethod << " NOT FOUND IN Material Factory Map." << endl;
25  return NULL;
26  }
27 
28  return (*factory)[materialsMethod]();
29 }
30 
31 map<string, materialFactory> registerMaterialFactories()
32 {
33 
34  map<string, materialFactory> materialMethodMap;
35 
36  // CPP initialization
37  materialMethodMap["CPP"] = &cpp_materials::createMaterials;
38 
39  // MYSQL initialization
40  materialMethodMap["MYSQL"] = &mysql_materials::createMaterials;
41 
42  // TEXT initialization
43  materialMethodMap["TEXT"] = &text_materials::createMaterials;
44 
45  // GDML initialization
46  materialMethodMap["GDML"] = &gdml_materials::createMaterials;
47 
48  return materialMethodMap;
49 }
50 
51 void printMaterials(map<string, G4Material*> matMap)
52 {
53  for(map<string, G4Material*>::iterator it = matMap.begin(); it != matMap.end(); it++)
54  {
55  cout << " - material: " << it->first << " " << it->second << endl;
56  if(it->second->GetMaterialPropertiesTable())
57  {
58  cout << " - Optical Properties for " << it->first << ":" << endl;
59  it->second->GetMaterialPropertiesTable()->DumpTable();
60  cout << endl << endl;
61  }
62  }
63 }
64 
66 {
67  stringstream comps(s);
68 
69  for(int e=0; e<ncomponents; e++)
70  {
71  string thisComp;
72  double thisFrac;
73  comps >> thisComp >> thisFrac;
74  components.push_back(thisComp);
75  fracs.push_back(thisFrac);
76  }
77 }
78 
79 void material::opticalsFromString(string property, string what)
80 {
81 
82  string checkProperty = TrimSpaces(property);
83  if(checkProperty == "none") return;
84  else
85  {
86  stringstream comps(property);
87 
88  while(!comps.eof())
89  {
90  string c;
91  comps >> c ;
92  string trimmedC = TrimSpaces(c);
93 
94  if(what == "photonEnergy")
95  photonEnergy.push_back(get_number(trimmedC));
96 
97  if(what == "indexOfRefraction")
98  indexOfRefraction.push_back(get_number(trimmedC));
99 
100  if(what == "absorptionLength")
101  absorptionLength.push_back(get_number(trimmedC));
102 
103  if(what == "reflectivity")
104  reflectivity.push_back(get_number(trimmedC));
105 
106  if(what == "efficiency")
107  efficiency.push_back(get_number(trimmedC));
108 
109  // scintillation
110  if(what == "fastcomponent")
111  fastcomponent.push_back(get_number(trimmedC));
112 
113  if(what == "slowcomponent")
114  slowcomponent.push_back(get_number(trimmedC));
115 
116  if(what == "scintillationyield")
117  scintillationyield = get_number(trimmedC);
118 
119  if(what == "resolutionscale")
120  resolutionscale = get_number(trimmedC);
121 
122  if(what == "fasttimeconstant")
123  fasttimeconstant = get_number(trimmedC);
124 
125  if(what == "slowtimeconstant")
126  slowtimeconstant = get_number(trimmedC);
127 
128  if(what == "yieldratio")
129  yieldratio = get_number(trimmedC);
130 
131  if(what == "rayleigh")
132  rayleigh.push_back(get_number(trimmedC));
133  }
134 
135  if(what == "rayleigh")
136  {
137  // yieldratio is the last quantity to be loaded
138  // now we can check the vector sizes for comparison
139  // if no match, resetting quantities
140  if(indexOfRefraction.size() != photonEnergy.size()) indexOfRefraction.clear();
141  if(absorptionLength.size() != photonEnergy.size()) absorptionLength.clear();
142  if(reflectivity.size() != photonEnergy.size()) reflectivity.clear();
143  if(efficiency.size() != photonEnergy.size()) efficiency.clear();
144  if(fastcomponent.size() != photonEnergy.size()) fastcomponent.clear();
145  if(slowcomponent.size() != photonEnergy.size()) slowcomponent.clear();
146  if(rayleigh.size() != photonEnergy.size()) rayleigh.clear();
147  }
148 
149  }
150 }
151 
152 
153 
154 
155 // We start with the CPP definitions
156 // Then load the MYSQL, TEXT and GDML
157 // When all the detectors materials are moved to TEXT/MYSQL/GDML
158 // the CPP factory should be empty
159 map<string, G4Material*> buildMaterials(map<string, materialFactory> materialFactoryMap, goptions go, runConditions rc)
160 {
161  // Loading CPP def
162  materials *materialSelectedFactory = getMaterialFactory(&materialFactoryMap, "CPP");
163  map<string, G4Material*> mats = materialSelectedFactory->initMaterials(rc, go);
164 
165  // adding GDML
166  materials *gdmlFactory = getMaterialFactory(&materialFactoryMap, "GDML");
167  map<string, G4Material*> gdmlMats = gdmlFactory->initMaterials(rc, go);
168  for(map<string, G4Material*>::iterator it = gdmlMats.begin(); it != gdmlMats.end(); it++)
169  mats[it->first] = it->second;
170 
171  // adding MYSQL
172  materials *mysqlFactory = getMaterialFactory(&materialFactoryMap, "MYSQL");
173  map<string, G4Material*> mysqlMats = mysqlFactory->initMaterials(rc, go);
174  for(map<string, G4Material*>::iterator it = mysqlMats.begin(); it != mysqlMats.end(); it++)
175  mats[it->first] = it->second;
176 
177  // adding TEXT
178  materials *textFactory = getMaterialFactory(&materialFactoryMap, "TEXT");
179  map<string, G4Material*> textMats = textFactory->initMaterials(rc, go);
180  for(map<string, G4Material*>::iterator it = textMats.begin(); it != textMats.end(); it++)
181  mats[it->first] = it->second;
182 
183  return mats;
184 }
185 
186 map<string, G4Material*> materials::materialsFromMap(map<string, material> mmap)
187 {
188  G4NistManager* matman = G4NistManager::Instance(); // material G4 Manager
189  set<string> nistMap;
190 
191  // building STL map of existing material names
192  // so I can use "find" later
193  vector<G4String> allMats = matman->GetNistMaterialNames();
194  for(unsigned int j=0; j<allMats.size(); j++)
195  nistMap.insert(allMats[j]);
196 
197  vector<G4String> allEls = matman->GetNistElementNames();
198  for(unsigned int j=0; j<allEls.size(); j++)
199  {
200  nistMap.insert(allEls[j]);
201  // cout << allEls[j] << " element " << endl;
202  }
203  map<string, G4Material*> mats = materialsWithIsotopes();
204 
205  // vector of Optical Properties
206  vector<G4MaterialPropertiesTable*> optTable;
207 
208 
224 
225  // if all the materials / elements exist, adding it to the material list.
226  // otherwise continue until the map is empty
227 
228 
229  // doing maxMapSize max iterations.
230  int maxMapSize = 10000;
231  int maxMapIndex = 0;
232 
233  // removing materials already built from the map
234  // can't remove materials while in the map loop, so bookkeeping them
235  // in a list to be deleted outside the loop
236  vector<string> toDelete;
237 
238  while (mmap.size() && maxMapIndex < maxMapSize)
239  {
240  maxMapIndex++;
241 
242  // this is the outside loop - deleting all materials added in the inside loop
243  // then clearing the map again
244  for(unsigned i=0; i<toDelete.size(); i++)
245  mmap.erase(toDelete[i]);
246  toDelete.clear();
247 
248 
249  for(map<string, material>::iterator it = mmap.begin(); it != mmap.end() && mmap.size(); it++)
250  {
251  // first check if the components are available
252  // if not continue, they may be build later
253  bool allExist = 1;
254  for(unsigned int i=0; i<it->second.components.size(); i++)
255  {
256  string compName = it->second.components[i];
257  // first check if it's mats
258  if(mats.find(compName) == mats.end())
259  {
260  // not in mats, check if it's the Nist Manager
261  if(nistMap.find(compName) == nistMap.end())
262  {
263  // cout << " Material " << compName << " does not exist yet. Continuing..." << endl;
264  allExist = 0;
265  }
266  }
267  }
268 
269  // material elements do not exist yet - continue
270  if(!allExist) continue;
271 
272  else
273  // elements exist, build material and remove it from from mmap
274  {
275  mats[it->first] = new G4Material(it->first, it->second.density*g/cm3, it->second.ncomponents);
276 
277  // now check if the components are elements or material
278  // They will either sum to exactly 1 or > 1
279  double totComps = 0;
280  for(unsigned int i=0; i<it->second.fracs.size(); i++)
281  totComps += it->second.fracs[i];
282 
283 
284  // fractional components - must add to one exactly
285  if(fabs(totComps-1) < 0.00001)
286  {
287  for(unsigned int i=0; i<it->second.fracs.size(); i++)
288  {
289  string compName = it->second.components[i];
290 
291  // existing material
292  if(mats.find(compName) != mats.end())
293  mats[it->first]->AddMaterial(mats[compName], it->second.fracs[i]);
294  else
295  // G4 Material DB
296  mats[it->first]->AddMaterial(matman->FindOrBuildMaterial(compName), it->second.fracs[i]);
297  }
298  }
299  // molecular composition
300  else if(totComps > 1)
301  {
302  for(unsigned int i=0; i<it->second.fracs.size(); i++)
303  {
304 
305  string compName = it->second.components[i];
306  if(it->second.fracs[i] < 1)
307  {
308  cout << " The number of atoms of " << compName << " is " << it->second.fracs[i] << " but it should be an integer. Exiting" << endl;
309  exit(0);
310  }
311  mats[it->first]->AddElement(matman->FindOrBuildElement(compName), (int) it->second.fracs[i]);
312  }
313  }
314  else
315  {
316  cout << " Warning: the sum of all components for >" << it->first << "< does not add to one." << endl;
317  }
318 
319  // check for optical properties
320  unsigned nopts = it->second.photonEnergy.size();
321  if(nopts)
322  {
323  optTable.push_back(new G4MaterialPropertiesTable());
324 
325  double penergy[nopts];
326  for(unsigned i=0; i<nopts; i++)
327  penergy[i] = it->second.photonEnergy[i];
328 
329  // index of refraction
330  if(it->second.indexOfRefraction.size() == nopts)
331  {
332  double ior[nopts];
333  for(unsigned i=0; i<nopts; i++)
334  {
335  ior[i] = it->second.indexOfRefraction[i];
336  }
337  optTable.back()->AddProperty("RINDEX", penergy, ior, nopts );
338  }
339 
340  // absorption length
341  if(it->second.absorptionLength.size() == nopts)
342  {
343  double abs[nopts];
344  for(unsigned i=0; i<nopts; i++)
345  abs[i] = it->second.absorptionLength[i];
346  optTable.back()->AddProperty("ABSLENGTH", penergy, abs, nopts );
347  }
348 
349  // reflectivity
350  if(it->second.reflectivity.size() == nopts)
351  {
352  double ref[nopts];
353  for(unsigned i=0; i<nopts; i++)
354  ref[i] = it->second.reflectivity[i];
355 
356  optTable.back()->AddProperty("REFLECTIVITY", penergy, ref, nopts );
357  }
358 
359  // efficiency
360  if(it->second.efficiency.size() == nopts)
361  {
362  double eff[nopts];
363  for(unsigned i=0; i<nopts; i++)
364  eff[i] = it->second.efficiency[i];
365 
366  optTable.back()->AddProperty("EFFICIENCY", penergy, eff, nopts );
367  }
368 
369  // fastcomponent
370  if(it->second.fastcomponent.size() == nopts)
371  {
372  double fastc[nopts];
373  for(unsigned i=0; i<nopts; i++)
374  fastc[i] = it->second.fastcomponent[i];
375 
376  optTable.back()->AddProperty("FASTCOMPONENT", penergy, fastc, nopts );
377  }
378 
379  // slowcomponent
380  if(it->second.slowcomponent.size() == nopts)
381  {
382  double slowc[nopts];
383  for(unsigned i=0; i<nopts; i++)
384  slowc[i] = it->second.slowcomponent[i];
385 
386  optTable.back()->AddProperty("SLOWCOMPONENT", penergy, slowc, nopts );
387  }
388 
389  // rayleigh scattering
390  if(it->second.rayleigh.size() == nopts)
391  {
392  double ray[nopts];
393  for(unsigned i=0; i<nopts; i++)
394  ray[i] = it->second.rayleigh[i];
395 
396  optTable.back()->AddProperty("RAYLEIGH", penergy, ray, nopts);
397  }
398 
399 
400 
401  // scintillationyield
402  if(it->second.scintillationyield != -1)
403  optTable.back()->AddConstProperty("SCINTILLATIONYIELD", it->second.scintillationyield);
404 
405  // resolutionscale
406  if(it->second.resolutionscale != -1)
407  optTable.back()->AddConstProperty("RESOLUTIONSCALE", it->second.resolutionscale);
408 
409  // fasttimeconstant
410  if(it->second.fasttimeconstant != -1)
411  optTable.back()->AddConstProperty("FASTTIMECONSTANT", it->second.fasttimeconstant*ns);
412 
413  // slowtimeconstant
414  if(it->second.slowtimeconstant != -1)
415  optTable.back()->AddConstProperty("SLOWTIMECONSTANT", it->second.slowtimeconstant*ns);
416 
417  // yieldratio
418  if(it->second.yieldratio != -1)
419  optTable.back()->AddConstProperty("YIELDRATIO", it->second.yieldratio);
420 
421  mats[it->first]->SetMaterialPropertiesTable(optTable.back());
422  }
423 
424  // tagging material to be removed from map
425  toDelete.push_back(it->first);
426  }
427  }
428  }
429 
430  return mats;
431 }
432 
433 
434 // build materials with standard isotopes
435 map<string, G4Material*> materialsWithIsotopes()
436 {
437  map<string, G4Material*> mats;
438 
439  G4MaterialTable* matTable = (G4MaterialTable*) G4Material::GetMaterialTable();
440 
441  bool already_defined = 0;
442  for(unsigned i=0; i<matTable->size(); ++i)
443  {
444  G4Material* thisMat = (*(matTable))[i];
445 
446  if(thisMat->GetName() == "LD2")
447  {
448  // LD2 already defined, so we can add the isotopes in our map here
449  mats["LD2"] = thisMat;
450  already_defined = 1;
451  }
452  if(thisMat->GetName() == "helium3Gas")
453  {
454  // LD2 already defined, so we can add the isotopes in our map here
455  mats["helium3Gas"] = thisMat;
456  }
457  if(thisMat->GetName() == "deuteriumGas")
458  {
459  // LD2 already defined, so we can add the isotopes in our map here
460  mats["deuteriumGas"] = thisMat;
461  }
462  if(thisMat->GetName() == "ND3")
463  {
464  // LD2 already defined, so we can add the isotopes in our map here
465  mats["ND3"] = thisMat;
466  }
467 
468  }
469 
470  if(already_defined)
471  return mats;
472 
473  // isotopes not yet defined, defining them for the first time
474 
475  int Z, N;
476  double a;
477 
478 
479  // ---- gas and liquid deuterium
480 
481  // Deuteron isotope
482  G4Isotope* deuteron = new G4Isotope("deuteron", Z=1, N=2, a=2.0141018*g/mole);
483 
484  // Deuterium element
485  G4Element* deuterium = new G4Element("deuterium", "deuterium", 1);
486  deuterium->AddIsotope(deuteron, 1);
487 
488  // Deuterium gas
489  mats["deuteriumGas"] = new G4Material("deuteriumGas", 0.000452*g/cm3, 1, kStateGas, 294.25*kelvin);
490  mats["deuteriumGas"]->AddElement(deuterium, 1);
491 
492  // Liquid Deuterium
493  mats["LD2"] = new G4Material("LD2", 0.169*g/cm3, 1, kStateLiquid, 22.0*kelvin);
494  mats["LD2"]->AddElement(deuterium, 2);
495 
496 
497  // ---- helium 3 gas
498 
499  // helion isotope
500  G4Isotope* helion = new G4Isotope("helion", Z=2, N=3, a=3.0160293*g/mole);
501 
502  // helium 3 element
503  G4Element* helium3 = new G4Element("helium3", "helium3", 1);
504  helium3->AddIsotope(helion, 1);
505 
506  // helium 3 material gas
507  // Density at 21.1°C (70°F) : 0.1650 kg/m3
508  mats["helium3Gas"] = new G4Material("helium3Gas", 0.1650*mg/cm3, 1, kStateGas, 294.25*kelvin);
509  mats["helium3Gas"]->AddElement(helium3, 1);
510 
511 
512 
513  // ammonia
514  G4Element* Nitro = new G4Element("Nitro", "N", Z=7, a=14.01*g/mole);
515  mats["ND3"] = new G4Material("ND3", 1.007*g/cm3, 2, kStateLiquid, 1.0*kelvin);
516  mats["ND3"]->AddElement(Nitro, 1);
517  mats["ND3"]->AddElement(deuterium, 3);
518 
519 
520 
521  return mats;
522 }
523 
524 
materials * getMaterialFactory(map< string, materialFactory > *factory, string materialsMethod)
static materials * createMaterials()
static materials * createMaterials()
Definition: cpp_materials.h:13
map< string, G4Material * > materialsFromMap(map< string, material >)
map< string, materialFactory > registerMaterialFactories()
double get_number(string v, int warn_no_unit)
Returns number with dimension from string, i.e. 100*cm.
void printMaterials(map< string, G4Material * > matMap)
virtual map< string, G4Material * > initMaterials(runConditions, goptions)=0
map< string, G4Material * > materialsWithIsotopes()
void componentsFromString(string)
string TrimSpaces(string in)
Removes leading and trailing spaces.
static materials * createMaterials()
static materials * createMaterials()
void opticalsFromString(string, string)
map< string, G4Material * > buildMaterials(map< string, materialFactory > materialFactoryMap, goptions go, runConditions rc)