Class Reference for E1039 Core & Analysis Software
DetectorConstruction.cc
Go to the documentation of this file.
1 // DetectorConstruction.cc
2 // need help with this code? jumper1@illinois.edu
3 //
4 // This file performs the main fucntion of constructing and configuring
5 // the physical model of the experiment used in the GMC. Even though it
6 // is called DetectorConstruction it constructs all of the geometry, detectors,
7 // magnets, magnetic fields, concrete barriers, target, etc. It uses SQL
8 // databases to construct the shapes, sizes, positions and materials of the
9 // experiment components, sets up magnetic fields, sets display attributes of
10 // the physical componets, and assigns which components will be detectors.
11 
12 #include "DetectorConstruction.hh"
13 
14 #include "GlobalConsts.h"
15 
17 {
18  mySettings = settings;
19  G4cout << "detector constructor" << G4endl;
20 }
21 
23 {
24 }
25 
26 G4VPhysicalVolume* DetectorConstruction::Construct()
27 {
28  con = mysql_init(NULL);
29 
30  mysql_real_connect(con,mySettings->sqlServer, mySettings->login, mySettings->password, mySettings->geometrySchema, mySettings->sqlPort, NULL, 0);
31 
32  G4cout << "begin Construct routine..." << endl;
33 
34  /* The entire geometry, with the exception of the fields, are built from 5 different Geant Objects.
35 
36  Elements (G4Element) are things like carbon and oxygen, but you can define seperate elements
37  for seperate isotopes of the same element if you wish. The database has a liquid deuterium and
38  a hydrogen entry, for example. To define an element you need an atomic number (z), and its
39  mass per mole, and a name.
40 
41  Materials (G4Material) are built from combinations of one or more elements. To define a material,
42  the number of elements in the material, the pointers to those elements, and the fraction by mass
43  for each element. You also need to give a density and a name for the material.
44 
45  Solids (G4VSolid) are the shapes that make up your geometry. To define one you give the shape
46  (i.e. cylinder, box) and the spatial dimensions. More complex solids can be made by combining
47  simpler ones, either by adding them together or by using one solid to define a hole in another
48  solid.
49 
50  Logical Volumes (G4LogicalVolume) are the combination of a Solid with a Material. Multiple
51  Logical Volumes can use the same Solid.
52 
53  Physical Volumes (G4VPhysicalVolume) are what are actually placed within the geometry. They are
54  made from a logical volume, placed within a different logical volume(called its mother volume), and
55  given a position within its mother volume. Multiple Physical Volumes can use the same Logical Volume.
56  The World Volume is a special Physical Volume; its Logical Volume contains all the other Physical
57  Volumes and it does not have a mother volume. The World Volume is what this routine returns.
58 
59  This routine downloads the Elements info from MySQL and loads it into a vector. Then it downloads
60  the Materials information, builds those using the Elements, and loads it into a different vector.
61  It similarly builds up to Physical Volumes.
62 
63  At various points certain variables like target length are stored to send to PrimaryGeneratorAction.
64  Pointers to the target material and magnet material are also stored so their materials can be changed
65  through the UI if desired.
66  */
67 
68  MYSQL_RES* res;
69 
70  MYSQL_ROW row;
71 
72  double z, n, a;
73  int id;
74  G4String name, symbol;
75 
76  mysql_query(con, "SELECT eID, eName, symbol, z, n FROM Elements");
77  if (mysql_errno(con) != 0)
78  cout << mysql_error(con) << endl;
79  res = mysql_store_result(con);
80  int nElement = mysql_num_rows(res);
81  elementVec.resize(nElement+1);
82 
83  while ((row = mysql_fetch_row(res)))
84  {
85  id = atoi(row[0]);
86  if (id >= (int)elementVec.size())
87  elementVec.resize(id+10);
88  name = row[1];
89  symbol = row[2];
90  z = atof(row[3]);
91  n = atof(row[4]);
92  a = n * gram;
93  elementVec[id] = new G4Element(name, symbol, z, a);
94  }
95 
96  mysql_free_result(res);
97 
98  double density;
99  int numEle;
100  vector<double> perAbundance;
101  perAbundance.resize(11);
102  vector<G4String> eleName;
103  eleName.resize(11);
104  vector<int> eID;
105  eID.resize(11);
106 
107  // This query might have to be expanded if materials with more elements are made.
108  // This is inelegant, most of the fields are usually NULL, but I don't know a better way to do it.
109  // Perhaps have all the eIDs and percents in a MySQL VarChar or blob field and parse the string?
110  // It works fine, so not a priority.
111 
112  mysql_query(con, "SELECT mID, mName, density, numElements, eID1, eID2, eID3, eID4, eID5, "
113  "eID6, eID7, eID8, eID9, eID10, elementPercent1, elementPercent2, "
114  "elementPercent3, elementPercent4, elementPercent5, elementPercent6, "
115  "elementPercent7, elementPercent8, elementPercent9, elementPercent10 FROM Materials");
116  if (mysql_errno(con) != 0)
117  cout << mysql_error(con) << endl;
118  res = mysql_store_result(con);
119  int nMaterial = mysql_num_rows(res);
120  materialVec.resize(nMaterial+1);
121 
122  while ((row = mysql_fetch_row(res)))
123  {
124  id = atoi(row[0]);
125  if (id >= (int)materialVec.size())
126  materialVec.resize(id+10);
127  name = row[1];
128  density = atof(row[2])*g/(cm*cm*cm);
129  numEle = atoi(row[3]);
130  for (int i = 1; i <= numEle; i++)
131  {
132  eID[i] = atoi(row[3+i]);
133  perAbundance[i] = atof(row[13+i]);
134  }
135 
136  materialVec[id] = new G4Material(name, density, numEle);
137 
138  for (int j = 1; j <= numEle; j++)
139  materialVec[id]->AddElement(elementVec[eID[j]],perAbundance[j]/100.0);
140  }
141 
142  mysql_free_result(res);
143 
144  double xLength, yLength, zLength, radiusMin, radiusMax;
145  int shellID, holeID;
146 
147  // For any row at least three of the fields will be NULL. If statements on the shapes are used to define
148  // the shapes properly. More fields might have to be added if one wishes to add new shapes.
149  // Compound Solids have to be skipped on the first loop through, then defined in a second loop when all
150  // the simple Solids have been defined.
151 
152  int nSolid = 3000;
153  solidVec.resize(nSolid);
154 
155  mysql_query(con, "SELECT sID, sName, xLength, yLength, zLength FROM SolidBoxes");
156  if (mysql_errno(con) != 0)
157  cout << mysql_error(con) << endl;
158  res = mysql_store_result(con);
159 
160  while ((row = mysql_fetch_row(res)))
161  {
162  id = atoi(row[0]);
163  if (id >= (int)solidVec.size())
164  solidVec.resize(id+10);
165  name = row[1];
166 
167  xLength = atof(row[2])*cm;
168  yLength = atof(row[3])*cm;
169  zLength = atof(row[4])*cm;
170 
171  solidVec[id] = new G4Box(name, xLength/2.0, yLength/2.0, zLength/2.0);
172  }
173  mysql_free_result(res);
174 
175  mysql_query(con, "SELECT sID, sName, length, radiusMin, radiusMax FROM SolidTubes");
176  if (mysql_errno(con) != 0)
177  cout << mysql_error(con) << endl;
178  res = mysql_store_result(con);
179 
180  while ((row = mysql_fetch_row(res)))
181  {
182  id = atoi(row[0]);
183  if (id >= (int)solidVec.size())
184  solidVec.resize(id+10);
185  name = row[1];
186 
187  zLength = atof(row[2])*cm;
188  radiusMin = atof(row[3])*cm;
189  radiusMax = atof(row[4])*cm;
190 
191  solidVec[id] = new G4Tubs(name, radiusMin, radiusMax, zLength/2.0, 0, 360*deg);
192  }
193  mysql_free_result(res);
194 
195  mysql_query(con, "SELECT sID, sName, shellID, holeID, rotX, rotY, rotZ, posX, posY, posZ FROM SubtractionSolids");
196  if (mysql_errno(con) != 0)
197  cout << mysql_error(con) << endl;
198  res = mysql_store_result(con);
199 
200  while ((row = mysql_fetch_row(res)))
201  {
202  id = atoi(row[0]);
203  if (id >= (int)solidVec.size())
204  solidVec.resize(id+10);
205  name = row[1];
206 
207  shellID = atoi(row[2]);
208  holeID = atoi(row[3]);
209 
210  G4RotationMatrix ra;
211  ra.rotateX(atof(row[4]));
212  ra.rotateY(atof(row[5]));
213  ra.rotateZ(atof(row[6]));
214  G4ThreeVector ta;
215  ta.setX(atof(row[7]));
216  ta.setY(atof(row[8]));
217  ta.setZ(atof(row[9]));
218  G4Transform3D rata;
219  rata = G4Transform3D(ra,ta);
220 
221  solidVec[id] = new G4SubtractionSolid(name, solidVec[shellID], solidVec[holeID], rata);
222  }
223  mysql_free_result(res);
224 
225  int sID, mID;
226 
227  mysql_query(con, "SELECT lvID, lvName, sID, mID FROM LogicalVolumes");
228  if (mysql_errno(con) != 0)
229  cout << mysql_error(con) << endl;
230  res = mysql_store_result(con);
231  int nLogicalVolume = mysql_num_rows(res);
232  logicalVolumeVec.resize(nLogicalVolume);
233 
234  while ((row = mysql_fetch_row(res)))
235  {
236  id = atoi(row[0]);
237  if (id >= (int)logicalVolumeVec.size())
238  logicalVolumeVec.resize(id+10);
239  name = row[1];
240  sID = atoi(row[2]);
241  mID = atoi(row[3]);
242  logicalVolumeVec[id] = new G4LogicalVolume(solidVec[sID], materialVec[mID], name);
243  }
244  mysql_free_result(res);
245 
246  int logicalID, motherID;
247  G4ThreeVector pos;
248 
249  vector<int> copy;
250  copy.resize((int)logicalVolumeVec.size());
251 
252  for (int i = 0; i<(int)copy.size(); i++)
253  copy[i] = 0;
254 
255  mysql_query(con, "SELECT MAX(depth) FROM PhysicalVolumes");
256  if (mysql_errno(con) != 0)
257  cout << mysql_error(con) << endl;
258  res = mysql_store_result(con);
259  row = mysql_fetch_row(res);
260  int depth = atoi(row[0]);
261 
262  rotationMatrixVec.resize(0);
263 
264  mysql_query(con, "SELECT lvID FROM PhysicalVolumes WHERE depth = 0");
265  if (mysql_errno(con) != 0)
266  cout << mysql_error(con) << endl;
267  res = mysql_store_result(con);
268 
269  if ((row = mysql_fetch_row(res)))
270  {
271  logicalID = atoi(row[0]);
272  physiWorld = new G4PVPlacement(0, G4ThreeVector(), "World", logicalVolumeVec[logicalID], 0, false, 0);
273  copy[logicalID]++;
274  }
275  mysql_free_result(res);
276 
277  char qry[500];
278 
279  for (int i = 1; i <= depth; i++)
280  {
281  sprintf(qry, "SELECT pvID, pvName, lvID, motherID, xRel, yRel, zRel, rotX, rotY, rotZ "
282  "FROM PhysicalVolumes WHERE depth = %i", i);
283  mysql_query(con, qry);
284  if (mysql_errno(con) != 0)
285  cout << mysql_error(con) << endl;
286  res = mysql_store_result(con);
287 
288  while ((row = mysql_fetch_row(res)))
289  {
290  id = atoi(row[0]);
291  name = row[1];
292  logicalID = atoi(row[2]);
293  motherID = atoi(row[3]);
294  pos(0) = atof(row[4])*cm;
295  pos(1) = atof(row[5])*cm;
296  pos(2) = atof(row[6])*cm;
297 
298  rotationMatrixVec.push_back(new G4RotationMatrix());
299  rotationMatrixVec.back()->rotateZ(atof(row[9]));
300  rotationMatrixVec.back()->rotateY(atof(row[8]));
301  rotationMatrixVec.back()->rotateX(atof(row[7]));
302 
303  new G4PVPlacement(rotationMatrixVec.back(), pos, logicalVolumeVec[logicalID], name,
304  logicalVolumeVec[motherID], 0, copy[logicalID]);
305 
306  copy[logicalID]++;
307  }
308  mysql_free_result(res);
309  }
310 
311  mysql_query(con, "SELECT * FROM ConstantsDerived");
312  if (mysql_errno(con) != 0)
313  cout << mysql_error(con) << endl;
314  res = mysql_store_result(con);
315 
316  char constant[30];
317  while ((row = mysql_fetch_row(res)))
318  {
319  sprintf(constant, row[0]);
320  if (!strcmp(constant, "targetLength"))
321  targetLength = atof(row[1])*cm;
322  else if (!strcmp(constant, "targetCenter"))
323  targetCenter = atof(row[1])*cm;
324  else if (!strcmp(constant, "targetRadius"))
325  targetRadius = atof(row[1])*cm;
326  else if (!strcmp(constant, "fmagLength"))
327  fmagLength = atof(row[1])*cm;
328  else if (!strcmp(constant, "fmagCenter"))
329  fmagCenter = atof(row[1])*cm;
330  else if (!strcmp(constant, "targetMaterialID"))
331  targetMat = materialVec[atoi(row[1])];
332  else if (!strcmp(constant, "targetVolumeID"))
333  targetVolume = logicalVolumeVec[atoi(row[1])];
334  else if (!strcmp(constant, "fmagMaterialID"))
335  defaultMagnetMat = materialVec[atoi(row[1])];
336  else if (!strcmp(constant, "fmagVolumeID"))
337  magnetVolume = logicalVolumeVec[atoi(row[1])];
338  }
339  mysql_free_result(res);
340 
341  mysql_close(con);
342 
343  // This manages the physical volumes that are sensitive detectors (particle passing through triggers a hit)
344 
345  G4cout << "Initializing sensitive detector manager...\n";
346  G4SDManager* SDman = G4SDManager::GetSDMpointer();
347  G4String sta_SDname = "E906/StationSD";
348  staSD = new GenericSD(sta_SDname);
349  SDman->AddNewDetector(staSD);
350  G4cout << "Finished initializing sensitive detector manager!\n";
351 
352  // Execute a function to recursively sort through all Volumes and assign proper display and sensitive detector attributes to each component
353  G4cout << "Setting attributes...\n";
354  AssignAttributes(physiWorld);
355  G4cout << "Finished setting attributes!\n";
356 
357  // Magnetic Field
358  // For details see Field and TabulatedField3D .cc and .hh
359 
360  G4cout << "Setting up physical magnetic field..." << G4endl;
361 
362  Field* myField = new Field(mySettings);
363  G4FieldManager* fieldMgr = G4TransportationManager::GetTransportationManager()->GetFieldManager();
364  fieldMgr->SetDetectorField(myField);
365 
366  G4Mag_UsualEqRhs* fEquation = new G4Mag_UsualEqRhs(myField);
367  G4MagIntegratorStepper* pStepper = new G4ClassicalRK4(fEquation);
368  G4ChordFinder* pChordFinder = new G4ChordFinder(myField,0.01*mm, pStepper);
369  fieldMgr->SetChordFinder(pChordFinder);
370 
371  G4cout << "******************" << fieldMgr->DoesFieldExist() << "*******************" << G4endl;
372 
373  // Prints the material table to screen, for debugging purposes
374 
375  G4cout << "here comes the material tables" << endl;
376  G4cout << *(G4Element::GetElementTable()) << endl;
377  G4cout << *(G4Material::GetMaterialTable()) << endl;
378  G4cout << "Geometry complete!!!" << G4endl;
379 
380  return physiWorld;
381 }
382 
383 int DetectorConstruction::AssignAttributes(G4VPhysicalVolume* mother_phy)
384 {
385  // set all possible display attributes
386  G4VisAttributes* targetVisAtt = new G4VisAttributes(G4Colour(0.8,0.8,0.8));
387  targetVisAtt->SetForceSolid(true);
388  G4VisAttributes* polyVisAtt = new G4VisAttributes(G4Colour(0.7,0.0,0.3,0.3));
389  G4VisAttributes* magVisAtt = new G4VisAttributes(G4Colour(0.0,0.6,0.0,0.2));
390  G4VisAttributes* coilVisAtt = new G4VisAttributes(G4Colour(0.65,0.83,0.95,0.60));
391  G4VisAttributes* concreteVisAtt = new G4VisAttributes(G4Colour(0.45,0.44,0.35,0.8));
392  G4VisAttributes* detVisAtt = new G4VisAttributes(G4Colour(0.3,0.5,1.0));
393  G4VisAttributes* absWallVisAtt = new G4VisAttributes(G4Colour(0.9,0.88,0.7));
394  absWallVisAtt->SetForceSolid(true);
395 
396  // check for daughter volumes
397 
398  G4LogicalVolume *mother_vol = mother_phy->GetLogicalVolume();
399  G4String pName = mother_phy->GetName();
400  G4String lName = mother_vol->GetName();
401  G4int nDaughters = mother_vol->GetNoDaughters();
402  G4Material* mat = mother_vol->GetMaterial();
403  G4String matName = mat->GetName();
404  G4int exit = 0;
405 
406  bool overDet = lName.contains("osta");
407  bool det = ( pName.contains("H1") || pName.contains("H2") || pName.contains("H3") || pName.contains("H4")
408  || pName.contains("C1") || pName.contains("C2") || pName.contains("C3")
409  || pName.contains("P1") || pName.contains("P2"));
410 
411  if (overDet)
412  mother_vol->SetSensitiveDetector(staSD);
413  else if (det)
414  mother_vol->SetSensitiveDetector(staSD);
415 
416  //if no daughters exist, determine which attributes to assign
417  if(nDaughters == 0)
418  {
419  // If naming schemes are changed this part needs to be checked for accuracy, as it assigns attributes based on the names of components.
420  if (overDet)
421  mother_vol->SetVisAttributes(G4VisAttributes::Invisible);
422  else if (det)
423  mother_vol->SetVisAttributes(detVisAtt);
424  else if (matName == "Air" )
425  mother_vol->SetVisAttributes(G4VisAttributes::Invisible);
426  else if (lName.contains("absorber"))
427  mother_vol->SetVisAttributes( absWallVisAtt);
428  else if (lName.contains("targ"))
429  mother_vol->SetVisAttributes(targetVisAtt);
430  else if (lName.contains("poly"))
431  mother_vol->SetVisAttributes( polyVisAtt);
432  else if (lName.contains("block"))
433  mother_vol->SetVisAttributes(concreteVisAtt);
434  else if (lName.contains("coil"))
435  mother_vol->SetVisAttributes(coilVisAtt);
436  else if (lName.contains("concrete"))
437  mother_vol->SetVisAttributes(concreteVisAtt);
438  else if (lName.contains("body"))
439  mother_vol->SetVisAttributes(magVisAtt);
440  else
441  mother_vol->SetVisAttributes(G4VisAttributes::Invisible);
442  }
443  else // if daughters exist, repeat function for each.
444  {
445  mother_vol->SetVisAttributes(G4VisAttributes::Invisible);
446  for(int i=0; i < nDaughters; i++)
447  exit += AssignAttributes( mother_vol->GetDaughter(i));
448  }
449 
450  // 'exit' returns a zero if all componets were assigned attributes or
451  // the number of componets missing assigment if some were not assigned
452  return exit;
453 }
454 
455 // This is called if someone changes the target material through the UI
456 
458 {
459  G4NistManager* man = G4NistManager::Instance();
460  G4Material* targMat = man->FindOrBuildMaterial(material);
461  targetMat = targMat;
462  if (targMat)
463  targetVolume->SetMaterial(targetMat);
464  else
465  cout << material << " not found in material database." << endl;
466 
467  G4RunManager::GetRunManager()->GeometryHasBeenModified();
468 }
469 
470 // This is called if someone changes the magnet material through the UI
471 
473 {
474  G4NistManager* man = G4NistManager::Instance();
475  G4Material* air = man->FindOrBuildMaterial("Air");
476 
477  if (iron == true)
478  magnetVolume->SetMaterial(defaultMagnetMat);
479  else
480  magnetVolume->SetMaterial(air);
481 
482  G4RunManager::GetRunManager()->GeometryHasBeenModified();
483 }
484 
485 // This is called whenever someone changes the asciiFieldMap bool in the settings
486 // It reloads the field from the place specified.
487 
489 {
490  G4cout << "Setting up physical magnetic field..." << G4endl;
491  Field* myField = new Field(mySettings);
492  G4FieldManager* fieldMgr = G4TransportationManager::GetTransportationManager()->GetFieldManager();
493  fieldMgr->SetDetectorField(myField);
494 
495  G4Mag_UsualEqRhs* fEquation = new G4Mag_UsualEqRhs(myField);
496  G4MagIntegratorStepper* pStepper = new G4ClassicalRK4(fEquation);
497  G4ChordFinder* pChordFinder = new G4ChordFinder(myField,1.e-1*mm, pStepper);
498 
499  fieldMgr->SetChordFinder(pChordFinder);
500  G4cout << "******************" << fieldMgr->DoesFieldExist() << "*******************" << G4endl;
501 
502  G4RunManager::GetRunManager()->GeometryHasBeenModified();
503 }
#define NULL
Definition: Pdb.h:9
vector< G4RotationMatrix * > rotationMatrixVec
G4LogicalVolume * magnetVolume
G4LogicalVolume * targetVolume
G4VPhysicalVolume * Construct()
vector< G4LogicalVolume * > logicalVolumeVec
vector< G4Material * > materialVec
vector< G4Element * > elementVec
vector< G4VSolid * > solidVec
void SetTargetMaterial(G4String)
Definition: Field.hh:13
G4String sqlServer
Definition: Settings.hh:40
G4String login
Definition: Settings.hh:35
G4String password
Definition: Settings.hh:37
int sqlPort
Definition: Settings.hh:41
G4String geometrySchema
Definition: Settings.hh:48