GEMC  1.8
Geant4 Monte-Carlo Framework
mysql_materials.cc
Go to the documentation of this file.
1 // %%%%%%%%%%
2 // Qt headers
3 // %%%%%%%%%%
4 #include <QtSql>
5 
6 // %%%%%%%%%%%%%
7 // gemc headers
8 // %%%%%%%%%%%%%
9 #include "material_factory.h"
10 #include "mysql_materials.h"
11 #include "detector.h" // just for TrimSpaces
12 #include "string_utilities.h"
13 
14 // %%%%%%%%%%
15 // G4 headers
16 // %%%%%%%%%%
17 #include "G4Element.hh"
18 #include "G4NistManager.hh"
19 #include "G4OpBoundaryProcess.hh"
20 
21 
22 map<string, G4Material*> mysql_materials::initMaterials(run_conditions runConditions, gemc_opts opts)
23 {
24  // DB settings
25  string database = opts.args["DATABASE"].args;
26  string dbhost = opts.args["DBHOST"].args;
27  string dbUser = opts.args["DBUSER"].args;
28  string dbPswd = opts.args["DBPSWD"].args;
29  string hd_msg = opts.args["LOG_MSG"].args + " MYSQL Materials: >> ";
30  double verbos = opts.args["MATERIAL_VERBOSITY"].arg;
31 
32 
33  // connection to the DB
34  QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
35  db.setHostName(dbhost.c_str());
36  db.setDatabaseName(database.c_str());
37  db.setUserName( dbUser.c_str() );
38  db.setPassword( dbPswd.c_str() );
39  bool ok = db.open();
40 
41  if(!ok)
42  {
43  cout << hd_msg << " Cannot connect to database " << database << ". Exiting." << endl;
44  exit(-1);
45  }
46 
47 
48  map<string, G4Material*> mats; // material maps
49  map<string, G4MaterialPropertiesTable*> optP; // optical properties maps
50 
51  G4NistManager* matman = G4NistManager::Instance(); // material G4 Manager
52 
53 
54  // loading elements material from table "materials__elements"
55  map<string, G4Element*> elementsMap;
56  QSqlQuery q, q2, q3;
57  string dbexecute = "select name, symbol, atomic_number, molar_mass from materials__elements" ;
58 
59  // will exit if table cannot be accessed.
60  if(!q.exec(dbexecute.c_str()))
61  {
62  cout << hd_msg << " Failed to access DB for table: materials__elements. Maybe the table doesn't exist? Exiting." << endl;
63  exit(0);
64  }
65 
66 
67  while (q.next())
68  {
69  string ename = TrimSpaces(gemc_tostring(q.value(0).toString()));
70  string esymbol = TrimSpaces(gemc_tostring(q.value(1).toString()));
71  int atomic_number = q.value(2).toInt();
72  double molar_mass = q.value(3).toDouble();
73 
74  elementsMap[ename] = new G4Element(ename, esymbol, atomic_number, molar_mass*g/mole);
75 
76  }
77 
78 
79  string dbtable = opts.args["GT"].args;
80 
81  if(runConditions.gTab_Vec.size() == 0 && dbtable != "no")
82  runConditions.gTab_Vec.push_back(dbtable);
83 
84 
85 
86  // at this point RunConditions should have something inside
87  for(unsigned int sql_t=0; sql_t< runConditions.gTab_Vec.size(); sql_t++)
88  {
89  string material_table = runConditions.gTab_Vec[sql_t] + "__materials";
90  dbexecute = "select name, density, nelements, elements from " + material_table;
91 
92  // will exit if table cannot be accessed.
93  if(!q.exec(dbexecute.c_str()))
94  {
95  cout << hd_msg << " Failed to access DB for table: " << material_table << ". Maybe the table doesn't exist? Exiting." << endl;
96  exit(0);
97  }
98 
99  while (q.next())
100  {
101  string mname = TrimSpaces(gemc_tostring(q.value(0).toString()));
102  double density = q.value(1).toDouble();
103  int nelements = q.value(2).toInt();
104  mats[mname] = new G4Material(mname, density*mg/cm3, nelements);
105 
106 
107  stringstream elements(gemc_tostring(q.value(3).toString()));
108  string *enamelist= new string[nelements]; // Have to use new, since string is a class (non-POD = not "plain old data") and clang complains.
109  // Also, maybe cause the string operator "[]" ?
110  double eperc[nelements];
111  for(int e=0; e<nelements; e++)
112  {
113  elements >> enamelist[e] >> eperc[e];
114  }
115 
116  // checking that all components exists
117  // if not, will build non-existing components first
118  // TODO: adding elements by molecular components:
119  //
120  // Example for Water:
121  // H2O->AddElement(elH, natoms=2);
122  // H2O->AddElement(elO, natoms=1);
123  // should be done by modifying percentage so it's always < 1
124  // so if it's > 1 it's molecular constructor
125 
126  for(int e=0; e<nelements; e++)
127  {
128  if(elementsMap.find(enamelist[e]) != elementsMap.end())
129  {
130  mats[mname]->AddElement(elementsMap[enamelist[e]], eperc[e]*perCent);
131  }
132  // checking if geant4 provides this material. In case,
133  // add it to the materials
134  else if(matman->FindOrBuildMaterial(enamelist[e]) != 0)
135  mats[mname]->AddMaterial(matman->FindOrBuildMaterial(enamelist[e]), eperc[e]*perCent);
136 
137  else
138  cout << hd_msg << " WARNING: Component " << enamelist[e] << " NOT FOUND!!" << endl;
139  }
140 
141  // checking that percentages add to 100
142  double sum = 0;
143  for(int e=0; e<nelements; e++)
144  sum += eperc[e]*perCent;
145 
146  if(fabs(sum-1)>0.01)
147  cout << hd_msg << " WARNING: Material " << mname << " components percentages add to " << sum*100 << " instead of 100." << endl;
148 
149 
150  // Check if there are material properties associated with the material
151  // First check if there's photon energy
152  // If yes then load it, and proceed to the rest of the properties
153  string opt_properties_table = runConditions.gTab_Vec[sql_t] + "__opt_properties";
154  dbexecute = "select property, plist from " + opt_properties_table + " where mat_name='" + mname + "' and property='PhotonEnergy'";
155 
156  if(q2.exec(dbexecute.c_str()))
157  {
158  int non_zero = 0; // switch to one for any properties so we can associate it to the material
159  optP[mname] = new G4MaterialPropertiesTable();
160  vector<string> pvalues;
161 
162  while(q2.next())
163  {
164  string property = TrimSpaces(gemc_tostring(q2.value(0).toString()));
165  pvalues = get_strings(gemc_tostring(q2.value(1).toString()));
166  // last entry in pvalues is empty. Removing it
167  pvalues.pop_back();
168  }
169 
170  unsigned int nentries = pvalues.size();
171  double penergy[nentries];
172  for(unsigned int i=0; i<nentries; i++)
173  penergy[i] = get_number(pvalues[i]);
174 
175  // now can fill the other properties
176  dbexecute = "select property, plist from " + opt_properties_table + " where mat_name='" + mname + "' and property!='PhotonEnergy'";
177  if(q3.exec(dbexecute.c_str()))
178  {
179  while(q3.next())
180  {
181  string property = TrimSpaces( gemc_tostring(q3.value(0).toString()));
182  vector<string> dvalues = get_strings(gemc_tostring(q3.value(1).toString()));
183  // last entry in dvalues is empty. Removing it
184  dvalues.pop_back();
185 
186  if(dvalues.size() != nentries)
187  {
188  cout << hd_msg << " Number of entries for property " << property
189  << " of material " << mname
190  << " is " << dvalues.size() << " and does not match the photon energy entries of " << nentries << endl;
191  exit(0);
192  }
193  else
194  {
195  double this_values[nentries];
196  for(unsigned int i=0; i<nentries; i++)
197  this_values[i] = get_number(dvalues[i]);
198 
199  if(property == "IndexOfRefraction")
200  optP[mname]->AddProperty("RINDEX", penergy, this_values, nentries);
201 
202  if(property == "AbsorptionLength")
203  optP[mname]->AddProperty("ABSLENGTH", penergy, this_values, nentries);
204 
205  if(property == "Reflectivity")
206  optP[mname]->AddProperty("REFLECTIVITY", penergy, this_values, nentries);
207 
208  if(property == "Efficiency")
209  optP[mname]->AddProperty("EFFICIENCY", penergy, this_values, nentries);
210 
211  non_zero = 1;
212  }
213  }
214  }
215 
216  if(non_zero)
217  {
218  mats[mname]->SetMaterialPropertiesTable(optP[mname]);
219  if(verbos > 1)
220  {
221  cout << hd_msg << " Optical Properties for " << mname << ":" << endl;
222  optP[mname]->DumpTable();
223  }
224  }
225  }
226 
227  if(verbos > 1)
228  {
229  cout << hd_msg << " Material: " << mname << " with density " << density << " mg/cm3 loaded with " << nelements << " components: " << endl;
230  for(int e=0; e<nelements; e++)
231  cout << " (" << e+1 << ") " << enamelist[e] << " " << eperc[e] << "%" << endl;
232  }
233 
234  delete[] enamelist;
235  }
236  }
237 
238 
239  // closing DB connection
240  db.close();
241  // need to create empty db before removing the connection
242  db = QSqlDatabase();
243  db.removeDatabase("qt_sql_default_connection");
244  cout << endl;
245 
246 
247 
248  return mats;
249 }
vector< string > get_strings(string input)
returns a vector of strings from a stringstream
vector< string > gTab_Vec
Vector of SQL tables names.
map< string, G4Material * > initMaterials(run_conditions, gemc_opts)
Definition: usage.h:43
string gemc_tostring(QString input)
map< string, opts > args
Options map.
Definition: usage.h:68
string TrimSpaces(string in)
Removes leading and trailing spaces.
double get_number(string)
Returns dimension from string, i.e. 100*cm.