EDepSimUserDetectorConstruction.cc
Go to the documentation of this file.
4 #include "EDepSimSDFactory.hh"
5 #include "EDepSimUniformField.hh"
6 #include "EDepSimEMFieldSetup.hh"
7 #include "EDepSimArbEMField.hh"
8 #include "EDepSimArbElecField.hh"
9 #include "EDepSimArbMagField.hh"
10 
11 #define BUILD_CAPTAIN
12 #ifdef BUILD_CAPTAIN
14 #endif
15 
16 #include "EDepSimLog.hh"
17 
18 #include <G4ios.hh>
19 #include <G4NistManager.hh>
20 #include <G4StableIsotopes.hh>
21 
22 #include <G4Isotope.hh>
23 #include <G4Material.hh>
24 #include <G4UnitsTable.hh>
25 #include <G4Box.hh>
26 #include <G4LogicalVolume.hh>
27 #include <G4PVPlacement.hh>
28 #include <G4RunManager.hh>
29 #include <G4VPersistencyManager.hh>
30 #include <G4GDMLParser.hh>
31 #include <G4UserLimits.hh>
32 
33 #include <G4SolidStore.hh>
34 #include <G4LogicalVolumeStore.hh>
35 #include <G4PhysicalVolumeStore.hh>
36 
37 #include <G4FieldManager.hh>
38 
39 #include <G4UnitsTable.hh>
40 #include <G4SystemOfUnits.hh>
41 #include <G4PhysicalConstants.hh>
42 
43 #include <G4RegionStore.hh>
44 
45 #include <queue>
46 
49  fWorldBuilder = NULL;
50 #define BUILD_CAPTAIN
51 #ifdef BUILD_CAPTAIN
52  fWorldBuilder = new CaptWorldBuilder("/Captain",this);
53 #endif
54  fDefaultMaterial = NULL;
55  fValidateGeometry = false;
56  fGDMLParser = NULL;
57  fPhysicalWorld = NULL;
58  new G4UnitDefinition("volt/cm","V/cm","Electric field",volt/cm);
59 }
60 
63  if (fWorldBuilder) delete fWorldBuilder;
64  if (fGDMLParser) delete fGDMLParser;
65 }
66 
67 namespace {
68  double ParseFloat(std::string value) {
69  std::istringstream theStream(value);
70  double val;
71  theStream >> val;
72  return val;
73  }
74 
75  // Parse a string containing an RGBA color.
76  G4Color ParseColor(std::string value) {
77 
78  std::size_t pos = value.find("(");
79  if (pos == std::string::npos) return G4Color(0.5,0.5,0.5,1.0);
80 
81  value = value.substr(pos+1);
82  pos = value.find(",");
83  if (pos == std::string::npos) return G4Color(0.5,0.5,0.5,1.0);
84  std::string elem = value.substr(0,pos);
85  double r = ParseFloat(elem);
86 
87  value = value.substr(pos+1);
88  pos = value.find(",");
89  if (pos == std::string::npos) return G4Color(0.5,0.5,0.5,1.0);
90  elem = value.substr(0,pos);
91  double g = ParseFloat(elem);
92 
93  value = value.substr(pos+1);
94  pos = value.find(",");
95  if (pos == std::string::npos) {
96  double b = ParseFloat(value);
97  return G4Color(r,g,b,1.0);
98  }
99  elem = value.substr(0,pos);
100  double b = ParseFloat(elem);
101 
102  value = value.substr(pos+1);
103  double a = ParseFloat(value);
104 
105  return G4Color(r,g,b,a);
106  }
107 }
108 
109 
110 namespace {
111  double ParseUnit(std::string value, std::string unit) {
112  double val = 0.0;
113  std::istringstream theStream(value);
114  theStream >> val >> unit;
115  val *= G4UnitDefinition::GetValueOf(unit);
116  return val;
117  }
118 
119  // Parse a string containing the electric field vector.
120  G4ThreeVector ParseEField(std::string value) {
121  G4ThreeVector field(0,0,0);
122  value = value.substr(value.find("(")+1);
123  std::string elem = value.substr(0,value.find(","));
124  field.setX(ParseUnit(elem,"V/cm"));
125  value = value.substr(value.find(",")+1);
126  elem = value.substr(0,value.find(","));
127  field.setY(ParseUnit(elem,"V/cm"));
128  value = value.substr(value.find(",")+1);
129  elem = value.substr(0,value.find(")"));
130  field.setZ(ParseUnit(elem,"V/cm"));
131  return field;
132  }
133 
134  G4ThreeVector ParseBField(std::string value) {
135  G4ThreeVector field(0,0,0);
136  value = value.substr(value.find("(")+1);
137  std::string elem = value.substr(0,value.find(","));
138  field.setX(ParseUnit(elem,"tesla"));
139  value = value.substr(value.find(",")+1);
140  elem = value.substr(0,value.find(","));
141  field.setY(ParseUnit(elem,"tesla"));
142  value = value.substr(value.find(",")+1);
143  elem = value.substr(0,value.find(")"));
144  field.setZ(ParseUnit(elem,"tesla"));
145  return field;
146  }
147 }
148 
150  if (fGDMLParser) {
151  EDepSimLog("Using a GDML Geometry");
152 
153  fPhysicalWorld = fGDMLParser->GetWorldVolume();
154 
155  // Use auxilliary information to set the visual attributes for logical
156  // volumes.
158  aux = fGDMLParser->GetAuxMap()->begin();
159  aux != fGDMLParser->GetAuxMap()->end();
160  ++aux) {
161  G4Color color(0.5,0.5,0.5,0.5);
163  = aux->second.begin();
164  auxItem != aux->second.end();
165  ++auxItem) {
166  if (auxItem->type == "Color") {
167  // Set the color while keeping the original alpha.
168  EDepSimInfo("Set volume " << aux->first->GetName()
169  << " color to " << auxItem->value);
170  G4Color tmp;
171  if (G4Color::GetColour(auxItem->value,tmp)) {
172  color = G4Color(tmp.GetRed(),
173  tmp.GetGreen(),
174  tmp.GetBlue(),
175  color.GetAlpha());
176  }
177  else {
178  color = ParseColor(auxItem->value);
179  }
180  }
181  if (auxItem->type == "Opacity") {
182  // Set the alpha while keeping the original color.
183  EDepSimInfo("Set volume " << aux->first->GetName()
184  << " opacity to " << auxItem->value);
185  double opacity = ParseFloat(auxItem->value);
186  color = G4Color(color.GetRed(),
187  color.GetGreen(),
188  color.GetBlue(),
189  opacity);
190 
191  }
192  }
193  aux->first->SetVisAttributes(new G4VisAttributes(color));
194  }
195 
196  // Check for step limits
198  aux = fGDMLParser->GetAuxMap()->begin();
199  aux != fGDMLParser->GetAuxMap()->end();
200  ++aux) {
202  = aux->second.begin();
203  auxItem != aux->second.end();
204  ++auxItem) {
205  if (auxItem->type == "StepLimit") {
206  double stepLimit = ParseUnit(auxItem->value,"mm");
207  EDepSimLog("Set volume " << aux->first->GetName()
208  << " step limit to " << stepLimit
209  << " from " << auxItem->value);
210  aux->first->SetUserLimits(new G4UserLimits(stepLimit));
211  break;
212  }
213  }
214  }
215  }
216 
217  if (!fPhysicalWorld) {
218  EDepSimLog("Try to construct a custom geometry");
220  }
221 
222  if (!fPhysicalWorld) {
223  EDepSimError("Physical world not built");
224  EDepSimThrow("Physical world not built");
225  }
226 
229 
230  G4RunManager::GetRunManager()->DefineWorldVolume(fPhysicalWorld);
231 
232  G4VPersistencyManager *pMan
233  = G4VPersistencyManager::GetPersistencyManager();
234  if (pMan) pMan->Store(fPhysicalWorld);
235 
236  return fPhysicalWorld;
237 }
238 
240  // The parser didn't get created.
241  if (!fGDMLParser) return;
242  // There isn't an auxillary map associated with the parser.
243  if (!fGDMLParser->GetAuxMap()) return;
244 
245  // Construct the sensitive detectors for the logical volumes. This can be
246  // done in any order so leave it outside of the traversal below.
248  aux = fGDMLParser->GetAuxMap()->begin();
249  aux != fGDMLParser->GetAuxMap()->end();
250  ++aux) {
251  for (G4GDMLAuxListType::const_iterator auxItem = aux->second.begin();
252  auxItem != aux->second.end();
253  ++auxItem) {
254  if (auxItem->type != "SensDet") continue;
255  std::string logName(aux->first->GetName());
256  bool exclude = false;
258  = fExcludeAsSensitiveDetector.begin();
259  e != fExcludeAsSensitiveDetector.end(); ++e) {
260  if (logName.find((*e)) != std::string::npos) {
261  exclude = true;
262  break;
263  }
264  }
265  if (exclude) {
266  EDepSimLog("Volume " << logName << "marked as sensitive, but"
267  << " excluded");
268  }
269  EDepSimLog("Collect energy deposition for " << aux->first->GetName()
270  << " in " << auxItem->value);
271  EDepSim::SDFactory factory("segment");
272  aux->first->SetSensitiveDetector(factory.MakeSD(auxItem->value));
273  }
274  }
275 
276  // Add the EM field using a breadth first traversal of the geometry. This
277  // means that the field from parent volumes are applied to children, but
278  // that the children can override the local field.
279  std::queue<G4LogicalVolume*> remainingVolumes;
280  remainingVolumes.push(fPhysicalWorld->GetLogicalVolume());
281  while (!remainingVolumes.empty()) {
282  // Get the next logical volume and put it's daughters onto queue to be
283  // handled later.
284  G4LogicalVolume* logVolume = remainingVolumes.front();
285  remainingVolumes.pop();
286  for (std::size_t i = 0; i<logVolume->GetNoDaughters(); ++i) {
287  G4VPhysicalVolume* daughter = logVolume->GetDaughter(i);
288  remainingVolumes.push(daughter->GetLogicalVolume());
289  }
290 
291  // Check to see if there are any auxillary values for this volume. If
292  // not, then we are done.
294  = fGDMLParser->GetAuxMap()->find(logVolume);
295  if (aux == fGDMLParser->GetAuxMap()->end()) continue;
296 
297 
298  // Check the auxilliary items and add the field if necessary.
299  const G4GDMLAuxListType& auxItems = aux->second;
300 
301  // Find the electric field for the volume.
302  bool HasEField = false;
303  std::string eField_fname;
304  G4ThreeVector eField(0,0,0);
305  for (G4GDMLAuxListType::const_iterator auxItem = auxItems.begin();
306  auxItem != auxItems.end();
307  ++auxItem) {
308  if (auxItem->type != "EField" && auxItem->type != "ArbEField") {
309  continue;
310  }
311 
312  if (auxItem->type == "EField") {
313  eField = ParseEField(auxItem->value);
314  HasEField = true;
315 
316  EDepSimInfo("Set the electric field for "
317  << logVolume->GetName()
318  << " to "
319  << " X=" << eField.x()/(volt/cm) << " V/cm"
320  << ", Y=" << eField.y()/(volt/cm) << " V/cm"
321  << ", Z=" << eField.z()/(volt/cm) << " V/cm");
322  }
323 
324  if (auxItem->type == "ArbEField") {
325  eField_fname = auxItem->value;
326  HasEField = true;
327 
328  EDepSimInfo("Set the electric field for "
329  << logVolume->GetName()
330  << " to " << eField_fname);
331  }
332  }
333 
334  // Find the magnetic field for the volume.
335  bool HasBField = false;
336  std::string bField_fname;
337  G4ThreeVector bField(0,0,0);
338  for (G4GDMLAuxListType::const_iterator auxItem = auxItems.begin();
339  auxItem != auxItems.end();
340  ++auxItem) {
341  if (auxItem->type != "BField" && auxItem->type != "ArbBField") {
342  continue;
343  }
344 
345  if (auxItem->type == "BField") {
346  bField = ParseBField(auxItem->value);
347  HasBField = true;
348 
349  EDepSimInfo("Set the magnetic field for "
350  << logVolume->GetName()
351  << " to "
352  << " X=" << bField.x()/(tesla) << " T"
353  << ", Y=" << bField.y()/(tesla) << " T"
354  << ", Z=" << bField.z()/(tesla) << " T");
355  }
356 
357  if (auxItem->type == "ArbBField") {
358  bField_fname = auxItem->value;
359  HasBField = true;
360 
361  EDepSimInfo("Set the magnetic field for "
362  << logVolume->GetName()
363  << " to " << bField_fname);
364  }
365  }
366 
367  // Set the electromagnetic field. But first check if there is one to
368  // set.
369  if (!HasEField && !HasBField) continue;
370 
371  // The electric field can't be exactly zero, or the equation of
372  // motion fails.
373  if (eField.mag() < 0.01 * volt/cm) {
374  eField.setY(0.01 * volt/cm);
375  }
376 
377  // Create new field manager and an arbitrary EM field. The ArbEMField
378  // can store fields that inherits from G4ElectroMagneticField.
379  G4FieldManager* manager = new G4FieldManager();
380  EDepSim::ArbEMField* arbField = new EDepSim::ArbEMField();
381 
382  if (!eField_fname.empty()) {
383  EDepSim::ArbElecField* eFieldPtr = new EDepSim::ArbElecField();
384  eFieldPtr->ReadFile(eField_fname);
385  eFieldPtr->PrintInfo();
386 
387  arbField->SetEField(eFieldPtr);
388  }
389  else {
390  EDepSim::UniformField* eFieldPtr = new EDepSim::UniformField();
391  eFieldPtr->SetEField(eField);
392 
393  arbField->SetEField(eFieldPtr);
394  }
395 
396  if (!bField_fname.empty()) {
397  EDepSim::ArbMagField* bFieldPtr = new EDepSim::ArbMagField();
398  bFieldPtr->ReadFile(bField_fname);
399  bFieldPtr->PrintInfo();
400 
401  arbField->SetBField(bFieldPtr);
402  }
403  else {
404  EDepSim::UniformField* bFieldPtr = new EDepSim::UniformField();
405  bFieldPtr->SetBField(bField);
406 
407  arbField->SetBField(bFieldPtr);
408  }
409 
410  EDepSim::EMFieldSetup* fieldSetup
411  = new EDepSim::EMFieldSetup(arbField, manager);
412  if (!fieldSetup) {
413  EDepSimError("Field not created");
414  throw std::runtime_error("Field not created");
415  }
416  logVolume->SetFieldManager(manager,true);
417  }
418 }
419 
422  G4double density;
423  G4String name, symbol;
424  G4double temperature, pressure;
425  G4int nel, natoms;
426  G4double fractionmass;
427 
428  G4NistManager* nistMan = G4NistManager::Instance();
429 
430  G4Element* elH = nistMan->FindOrBuildElement(1);
431 
432  G4Element* elB = nistMan->FindOrBuildElement(5);
433 
434  G4Element* elC = nistMan->FindOrBuildElement(6);
435 
436  G4Element* elN = nistMan->FindOrBuildElement(7);
437 
438  G4Element* elO = nistMan->FindOrBuildElement(8);
439 
440  // G4Element* elF = nistMan->FindOrBuildElement(9);
441 
442  G4Element* elNa = nistMan->FindOrBuildElement(11);
443 
444  // G4Element* elAl = nistMan->FindOrBuildElement(13);
445 
446  G4Element* elSi = nistMan->FindOrBuildElement(14);
447 
448  // G4Element* elCl = nistMan->FindOrBuildElement(17);
449 
450  G4Element* elAr = nistMan->FindOrBuildElement(18);
451 
452  // G4Element* elTi = nistMan->FindOrBuildElement(22);
453 
454  G4Element* elFe = nistMan->FindOrBuildElement(26);
455 
456  G4Element* elCo = nistMan->FindOrBuildElement(27);
457 
458  G4Element* elCu = nistMan->FindOrBuildElement(29);
459 
460  // G4Element* elZn = nistMan->FindOrBuildElement(30);
461 
462  // G4Element* elSn = nistMan->FindOrBuildElement(50);
463 
464  // G4Element* elPb = nistMan->FindOrBuildElement(82);
465 
466  //Air
467  G4Material* air
468  = new G4Material(name="Air",
469  density = 1.29*CLHEP::mg/CLHEP::cm3,
470  nel=2,
471  kStateGas,
472  temperature = 293.15*CLHEP::kelvin,
473  pressure=1*CLHEP::atmosphere);
474  air->AddElement(elN, fractionmass = 70*CLHEP::perCent);
475  air->AddElement(elO, fractionmass = 30*CLHEP::perCent);
476  geoMan->SetDrawAtt(air,kGray+3,0.01);
477 
478  // This is the default material.
479  fDefaultMaterial = air;
480 
481  //Earth
482  density = 2.15*CLHEP::g/CLHEP::cm3;
483  G4Material* earth
484  = new G4Material(name="Earth",
485  density = 2.15*CLHEP::g/CLHEP::cm3,
486  nel=2,
487  kStateSolid,
488  temperature = 293.15*CLHEP::kelvin,
489  pressure=1*CLHEP::atmosphere);
490  earth->AddElement(elSi, natoms=1);
491  earth->AddElement(elO, natoms=2);
492  geoMan->SetDrawAtt(earth,49,0.2);
493 
494  //Cement
495  G4Material* cement
496  = new G4Material(name="Cement",
497  density = 2.5*CLHEP::g/CLHEP::cm3,
498  nel=2,
499  kStateSolid,
500  temperature = 293.15*CLHEP::kelvin,
501  pressure=1*CLHEP::atmosphere);
502  cement->AddElement(elSi, natoms=1);
503  cement->AddElement(elO, natoms=2);
504  geoMan->SetDrawAtt(cement,kGray,0.2);
505 
506  // The usual stainless steel (SS_304).
507  density = 8.0*CLHEP::g/CLHEP::cm3;
508  G4Material* SS_304 = new G4Material(name="SS_304",
509  density = 8.0*CLHEP::g/CLHEP::cm3,
510  nel=3,
511  kStateSolid,
512  temperature = 293.15*CLHEP::kelvin,
513  pressure=1*CLHEP::atmosphere);
514  SS_304->AddElement(elC, fractionmass = 4*CLHEP::perCent);
515  SS_304->AddElement(elFe, fractionmass = 88*CLHEP::perCent);
516  SS_304->AddElement(elCo, fractionmass = 8*CLHEP::perCent);
517  geoMan->SetDrawAtt(SS_304,kBlue-10,0.05);
518 
519  // Argon Gas
520  G4Material* argon = new G4Material(name="Argon_Gas",
521  density = 1.66*CLHEP::mg/CLHEP::cm3,
522  nel=1,
523  kStateGas,
524  temperature = 87.3*CLHEP::kelvin,
525  pressure=1*CLHEP::atmosphere);
526  argon->AddElement(elAr, natoms=1);
527  geoMan->SetDrawAtt(argon,kMagenta-10,0.1);
528 
529  // Liquid Argon
530  G4Material* LAr = new G4Material(name="Argon_Liquid",
531  density = 1.3954*CLHEP::g/CLHEP::cm3,
532  nel=1,
533  kStateLiquid,
534  temperature = 87.3*CLHEP::kelvin,
535  pressure=1*CLHEP::atmosphere);
536  LAr->AddElement(elAr, natoms=1);
537 
538  // Set up liquid argon for NEST.
539  G4MaterialPropertiesTable *LArMatProps = new G4MaterialPropertiesTable();
540  LArMatProps->AddConstProperty("ELECTRICFIELD",500*CLHEP::volt/CLHEP::cm);
541  LArMatProps->AddConstProperty("TOTALNUM_INT_SITES",-1);
542  LAr->SetMaterialPropertiesTable(LArMatProps);
543 
544  geoMan->SetDrawAtt(LAr,kCyan-9,0.1);
545 
546  // The CAPTAIN TPC wire.
547  G4Material *wire = new G4Material(name="Captain_Wire",
548  density = 8.96*CLHEP::g/CLHEP::cm3,
549  nel=1,
550  kStateSolid,
551  temperature = 87.3*CLHEP::kelvin,
552  pressure=1*CLHEP::atmosphere);
553  wire->AddElement(elCu, natoms=1);
554  geoMan->SetDrawAtt(wire,kOrange+1,1.0);
555 
556  // Glass -
557  G4Material* glass
558  = new G4Material(name="Glass",
559  density = 2.70*CLHEP::g/CLHEP::cm3,
560  nel=4);
561  glass->AddElement(elO,53.9*CLHEP::perCent);
562  glass->AddElement(elSi,38.4*CLHEP::perCent);
563  glass->AddElement(elB,3.8*CLHEP::perCent);
564  glass->AddElement(elNa,3.8*CLHEP::perCent);
565  geoMan->SetDrawAtt(glass,kBlue+1,0.3);
566 
567  // G10 - by volume 57% glass, 43% epoxy (CH2)
568  G4Material* g10
569  = new G4Material(name="G10",
570  density = 1.70*CLHEP::g/CLHEP::cm3,
571  nel=6);
572  g10->AddElement(elH,6.2*CLHEP::perCent);
573  g10->AddElement(elC,36.8*CLHEP::perCent);
574  g10->AddElement(elO,30.7*CLHEP::perCent);
575  g10->AddElement(elSi,21.9*CLHEP::perCent);
576  g10->AddElement(elB,2.2*CLHEP::perCent);
577  g10->AddElement(elNa,2.2*CLHEP::perCent);
578  geoMan->SetDrawAtt(g10,kGreen+1,0.75);
579 
580  // FR4 - Approximated by the composition of G10. The density is from
581  // Wikipedia.
582  G4Material* fr4
583  = new G4Material(name="FR4",
584  density = 1850*CLHEP::kg/CLHEP::m3,
585  nel=6);
586  fr4->AddElement(elH,6.2*CLHEP::perCent);
587  fr4->AddElement(elC,36.8*CLHEP::perCent);
588  fr4->AddElement(elO,30.7*CLHEP::perCent);
589  fr4->AddElement(elSi,21.9*CLHEP::perCent);
590  fr4->AddElement(elB,2.2*CLHEP::perCent);
591  fr4->AddElement(elNa,2.2*CLHEP::perCent);
592  geoMan->SetDrawAtt(fr4,kGreen+1,1.0);
593 
594  // FR4_Copper - Approximated by the composition of G10 plus copper. The
595  // copper is from the cladding, but is approximated as spread through the
596  // FR4. The density is from Wikipedia.
597  G4Material* fr4Copper
598  = new G4Material(name="FR4_Copper",
599  density = 1850*CLHEP::kg/CLHEP::m3,
600  nel=7);
601  double cuFrac = 3*CLHEP::perCent;
602  double fr4Frac = 1.0 - cuFrac;
603  fr4Copper->AddElement(elH,6.2*CLHEP::perCent*fr4Frac);
604  fr4Copper->AddElement(elC,36.8*CLHEP::perCent*fr4Frac);
605  fr4Copper->AddElement(elO,30.7*CLHEP::perCent*fr4Frac);
606  fr4Copper->AddElement(elSi,21.9*CLHEP::perCent*fr4Frac);
607  fr4Copper->AddElement(elB,2.2*CLHEP::perCent*fr4Frac);
608  fr4Copper->AddElement(elNa,2.2*CLHEP::perCent*fr4Frac);
609  fr4Copper->AddElement(elCu,cuFrac);
610  geoMan->SetDrawAtt(fr4Copper,kYellow-6,1.0);
611 
612  // Acrylic - Approximated by the composition of the Acrylic used to hold
613  // the TPB.. The density is from Wikipedia.
614  G4Material* acrylic
615  = new G4Material(name="Acrylic",
616  density = 1189*CLHEP::kg/CLHEP::m3,
617  nel=3);
618  acrylic->AddElement(elH,53.4*CLHEP::perCent);
619  acrylic->AddElement(elO,13.3*CLHEP::perCent);
620  acrylic->AddElement(elC,33.3*CLHEP::perCent);
621  geoMan->SetDrawAtt(acrylic,kAzure+6,0.75);
622 
623  // Print all the materials defined.
624  EDepSimLog(*(G4Material::GetMaterialTable()));
625 }
626 
628  G4String symbol,
629  G4double z) {
630  // Keep track of existing isotopes. This prevents them from being created
631  // twice when the geometry is regenerated.
632  static G4StableIsotopes theDefaultIsotopes;
633 
634  G4int Z = G4int(z);
635  G4int ncomponents = theDefaultIsotopes.GetNumberOfIsotopes(Z);
636  G4Element* el = new G4Element(name, symbol, ncomponents);
637  G4int first = theDefaultIsotopes.GetFirstIsotope(Z);
638  for (G4int i=0; i<ncomponents; i++) {
639  G4int A = theDefaultIsotopes.GetIsotopeNucleonCount(first+i);
640  std::ostringstream os; os << symbol << A;
641  G4Isotope* is = new G4Isotope(name=os.str(), Z, A,
643  G4double abundance = theDefaultIsotopes.GetAbundance(first+i);
644  el->AddIsotope(is, abundance*CLHEP::perCent);
645  }
646  return el;
647 }
648 
650 
651  if (!fWorldBuilder) return NULL;
652 
653  DefineMaterials();
654 
655  // Create a region outside of the detector to define cuts.
656  G4RegionStore::GetInstance()->FindOrCreateRegion("hallRegion");
657 
658  G4String name = fWorldBuilder->GetName();
659  G4LogicalVolume *vol = fWorldBuilder->GetPiece();
660 
661  //------------------------------
662  // World
663  //------------------------------
664  // Must place the World Physical volume unrotated at (0,0,0).
665  G4VPhysicalVolume* physWorld
666  = new G4PVPlacement(0, // no rotation
667  G4ThreeVector(), // position (0,0,0)
668  name, // name
669  vol,// logical volume
670  0, // mother volume
671  false, // no boolean operations
672  0);
673 
674  return physWorld;
675 }
676 
678  // Initialize the run manager. This sets everything in motion.
679  G4RunManager::GetRunManager()->Initialize();
680 }
static constexpr double cm
Definition: Units.h:68
static QCString name
Definition: declinfo.cpp:673
#define EDepSimLog(outStream)
Definition: EDepSimLog.hh:717
intermediate_table::iterator iterator
G4String GetName(void)
Return the base name of the object that this builds.
static constexpr double g
Definition: Units.h:144
void Update(const G4VPhysicalVolume *aWorld, bool validate)
Update the root geometry to match the g4 geometry.
std::string string
Definition: nybbler.cc:12
static constexpr double cm3
Definition: Units.h:70
int kelvin
Definition: units.py:217
float perCent
Definition: units.py:268
static constexpr double kg
Definition: Units.h:143
intermediate_table::const_iterator const_iterator
#define EDepSimThrow(message)
Print an error message, and then throw an exception.
#define EDepSimInfo(outStream)
Definition: EDepSimLog.hh:752
virtual G4LogicalVolume * GetPiece(void)=0
static constexpr double mg
Definition: Units.h:145
void SetBField(G4Field *bfield_in)
int atmosphere
Definition: units.py:162
EDepSim::Builder * fWorldBuilder
A constructor to create the world.
void SetEField(G4Field *efield_in)
const double e
G4Element * DefineElement(G4String name, G4String symbol, G4double z)
Define the natural isotope abundance.
const double a
virtual void SetBField(const G4ThreeVector bField)
bool ReadFile(const std::string &fname)
G4VPhysicalVolume * fPhysicalWorld
The constructed world volume.
volt_as<> volt
Type of potential stored in volts, in double precision.
EDepSim::DetectorMessenger * fDetectorMessenger
A messenger to for the DetectorConstruction object.
string tmp
Definition: languages.py:63
static constexpr double m3
Definition: Units.h:73
void SetDrawAtt(G4Material *material, int color, double opacity=1.0)
Set material color.
virtual void SetEField(const G4ThreeVector eField)
std::size_t color(std::string const &procname)
void DefineMaterials(void)
Define the materials used in the detector.
#define EDepSimError(outStream)
Definition: EDepSimLog.hh:503
G4GDMLParser * fGDMLParser
A GDML Parser if one has been defined.
#define A
Definition: memgrp.cpp:38
static bool * b
Definition: config.cpp:1043
bool ReadFile(const std::string &fname)
std::vector< std::string > fExcludeAsSensitiveDetector
Vector of logical volumes to exclude being sensitive detectors.
static EDepSim::RootGeometryManager * Get(void)
If a persistency manager has not been created, create one.
G4Material * fDefaultMaterial
The default material.