Geant4  10.01.p02
FFDetectorConstruction.cc
Go to the documentation of this file.
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 // -------------------------------------------------------------
27 // =============== Begin Documentation Comments ===============
38 // ================ End Documentation Comments ================
39 //
40 // Modified:
41 //
42 // 23-06-14 BWendt
43 // Fixed issue with the automatic placement of the meat not working. Solution
44 // was to use the correct units "inch" in the y-direction as well.
45 // Coincidentally eliminated the need to using the 'std::abs()" from the
46 // "cmath" library.
47 // Implemented method "PlaceFuelPlates"
48 //
49 // -------------------------------------------------------------
50 
51 #include "globals.hh"
52 
53 #include "G4Box.hh"
54 #include "G4Element.hh"
55 #include "G4Isotope.hh"
56 #include "G4LogicalVolume.hh"
57 #include "G4NistManager.hh"
58 #include "G4PVPlacement.hh"
59 #include "G4SystemOfUnits.hh"
60 #include "G4Tubs.hh"
61 #include "G4VPhysicalVolume.hh"
62 
64 
65 
66 static const G4double inch = 2.54 * cm;
67 
68 
69 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
73 {
75 }
76 
77 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
80 {
82 #ifdef NDEBUG
83  G4bool const overlapChecking = false;
84 #else
85  G4bool const overlapChecking = true;
86 #endif // NDEBUG
87 
88  //
89  // Create the world
90  //
91  const G4double worldSize = 40.0 * inch;
92  G4Box* const solidWorld = new G4Box("World", // the name
93  worldSize, // x size
94  worldSize, // y size
95  worldSize); // z size
96  G4LogicalVolume* const logicalWorld
97  = new G4LogicalVolume(solidWorld, // the solid volume
98  fAir, // the material
99  solidWorld->GetName()); // the name
100  // Center at the origin
101  position.set(0.0, 0.0, 0.0);
102  G4VPhysicalVolume* const physicalWorld
103  = new G4PVPlacement(NULL, // no rotation
104  position, // must be at origin
105  logicalWorld, // the logical volume
106  logicalWorld->GetName(), // the name
107  NULL, // no mother volume
108  false, // no boolean ops
109  0, // copy number
110  overlapChecking); // check for overlaps
111 
112  //
113  // Create the graphite pile that the subcritical assembly rests on.
114  //
115  const G4double floorH = 30.0 * inch;
116  const G4ThreeVector floorPosition(0.0, 0.0, 0.0);
117  G4Box* const solidFloor = new G4Box("Floor", // the name
118  worldSize, // x size
119  worldSize, // y size
120  floorH * 0.5); // z size
121  G4LogicalVolume* const logicalFloor
122  = new G4LogicalVolume(solidFloor, // the solid volume
123  fGraphite, // the material
124  solidFloor->GetName()); // the name
125  // Shift down so the top is at the origin
126  position.set(0.0, 0.0, -floorH * 0.5);
127  new G4PVPlacement(NULL, // no rotation
128  position, // position
129  logicalFloor, // the logical volume
130  logicalFloor->GetName(), // the name
131  logicalWorld, // the mother volume
132  false, // no boolean ops
133  0, // copy number
134  overlapChecking); // check for overlaps
135 
136  //
137  // Create the tank
138  //
139  const G4double tankWallThickness = 0.25 * inch;
140  const G4double tankOR = 18.0 * inch;
141  const G4double tankH = 39.0 * inch;
142  G4Tubs* const solidTank
143  = new G4Tubs("Tank_Wall", // the name
144  0.0, // inner radius
145  tankOR, // outer radius
146  tankH * 0.5, // half height
147  0.0 * deg, // start angle
148  360.0 * deg); // end angle
149  G4LogicalVolume* const logicalTank
150  = new G4LogicalVolume(solidTank, // the solid volume
151  fAluminum, // the material
152  solidTank->GetName()); // the name
153  // Shift up so the base is at the origin
154  position.set(0.0, 0.0, tankH * 0.5);
155  new G4PVPlacement(NULL, // no rotation
156  position, // shift up
157  logicalTank, // the logical volume
158  logicalTank->GetName(), // the name
159  logicalWorld, // the mother volume
160  false, // no boolean ops
161  0, // copy number
162  overlapChecking); // check for overlaps
163  // Top 3 inches are air
164  const G4double tankAirH = 3.0 * inch;
165  G4Tubs* const solidTankAir
166  = new G4Tubs("Tank_Air", // the name
167  0.0, // inner radius
168  tankOR - tankWallThickness, // outer radius
169  tankAirH * 0.5, // half height
170  0.0 * deg, // start angle
171  360.0 * deg); // end angle
172  G4LogicalVolume* const logicalTankAir
173  = new G4LogicalVolume(solidTankAir, // the solid volume
174  fAir, // the material
175  solidTankAir->GetName()); // the name
176  // Shift up so that the top of the air is the same as the top of the tank
177  position.set(0.0, 0.0, (tankH - tankAirH) * 0.5);
178  new G4PVPlacement(NULL, // no rotation
179  position, // shift ip
180  logicalTankAir, // the logical volume
181  logicalTankAir->GetName(), // the name
182  logicalTank, // the mother volume
183  false, // no boolean ops
184  0, // copy number
185  overlapChecking); // check for overlaps
186  // Fill remaining area with water
187  const G4double tankH2OH = (tankH - (tankAirH + tankWallThickness));
188  G4Tubs* const solidTankH2O
189  = new G4Tubs("Tank_H2O", // the name
190  0.0, // inner radius
191  tankOR - tankWallThickness, // outer radius
192  tankH2OH * 0.5, // half height
193  0.0 * deg, // start angle
194  360.0 * deg); // end angle
195  G4LogicalVolume* const logicalTankH2O
196  = new G4LogicalVolume(solidTankH2O, // the solid volume
197  fAluminum, // the material
198  solidTankH2O->GetName()); // the name
199  // Shift up so that the top of the water is at the bottom of the air
200  const G4double centerOfH2O = (tankH - tankH2OH) * 0.5 - tankAirH;
201  position.set(0.0, 0.0, centerOfH2O);
202  new G4PVPlacement(NULL, // no rotation
203  position, // shift to origin
204  logicalTankH2O, // the logical volume
205  logicalTankH2O->GetName(), // the name
206  logicalTank, // the mother volume
207  false, // no boolean ops
208  0, // copy number
209  overlapChecking); // check for overlaps
210 
211  //
212  // Fuel plates
213  //
214  const G4double plateX = 3.0 * inch;
215  const G4double plateY = 0.08 * inch;
216  const G4double plateZ = 26.0 * inch;
217  const G4double meatX = 2.75 * inch;
218  const G4double meatY = 0.04 * inch;
219  const G4double meatZ = 24.0 * inch;
220  const G4double xSpacing = 5.0 * inch;
221  const G4double ySpacing = 0.3 * inch;
222  const G4double plateRadius = 12.0 * inch;
223  // Define the aluminim claddiing
224  G4Box* const solidPlate
225  = new G4Box("Plate_Cladding", // the name
226  plateX * 0.5, // x size
227  plateY * 0.5, // y size
228  plateZ * 0.5); // z size
229  G4LogicalVolume* const logicalPlate
230  = new G4LogicalVolume(solidPlate, // the solid volume
231  fAluminum, // the material
232  solidPlate->GetName()); // the name
233  // Place the meat inside the cladding
234  G4Box* const solidMeat
235  = new G4Box("Plate_Meat", // the name
236  meatX * 0.5, // x size
237  meatY * 0.5, // y size
238  meatZ * 0.5); // z size
239  G4LogicalVolume* const logicalMeat
240  = new G4LogicalVolume(solidMeat, // the solid volume
241  fUO2_20E, // the material
242  solidMeat->GetName()); // the name
243  // The meat goes into the exact center of the plate
244  position.set(0.0, 0.0, 0.0);
245  new G4PVPlacement(NULL, // no rotation
246  position, // position
247  logicalMeat, // the logical volume
248  logicalMeat->GetName(), // the name
249  logicalPlate, // the mother volume
250  false, // no boolean ops
251  0, // copy number
252  overlapChecking); // check for overlaps
253  // The plate will be centered in the z-direction within the water
254  // Simulate a subcritical assembly loading within a radius of 12 inches
255  bool placeMe;
256 
257  position.setZ(0.0);
258  fCopyNumber = 0;
259  for(double x = 0.0;
260  x <= plateRadius;
261  x += xSpacing)
262  {
263  // 5 rows of plates
264  for(double y = 0.0;
265  y <= plateRadius;
266  y += ySpacing)
267  {
268  placeMe = false;
269 
270  // Fuel plate must be completely within the radius to be placed
271  if(std::sqrt(x * x + y * y) < plateRadius)
272  {
273  // Leave a 1 inch radius opening in the middle for the neutron
274  // source
275  if(std::sqrt(x * x + y * y) > 1.0 * inch)
276  {
277  placeMe = true;
278  }
279  }
280 
281  if(placeMe)
282  {
283  PlaceFuelPlate(x,
284  y,
285  logicalPlate,
286  logicalTankH2O);
287  PlaceFuelPlate(x,
288  -y,
289  logicalPlate,
290  logicalTankH2O);
291  if(x > 0.0)
292  {
293  PlaceFuelPlate(-x,
294  y,
295  logicalPlate,
296  logicalTankH2O);
297  PlaceFuelPlate(-x,
298  -y,
299  logicalPlate,
300  logicalTankH2O);
301  }
302  }
303  }
304  }
305  G4cout << fCopyNumber << " plates were added to the subcritical assembly"
306  << G4endl;
307 
308  //
309  // Neutron Source
310  //
311  // TODO create the AmBe material in DefineMaterials() and use it here
312  // For now steel is used, but the logical volume is used in the
313  // PrimaryGeneratorAction to know where to emit the neutrons from
314  const G4double sourceH = 2 * inch;
315  const G4double sourceR = 0.2 * inch;
316  G4Tubs* const solidSource
317  = new G4Tubs("NeutronSource", // the name
318  0.0, // inner radius
319  sourceR, // outer radius
320  sourceH * 0.5, // half height
321  0.0 * deg, // start angle
322  360.0 * deg); // end angle
323  G4LogicalVolume* const logicalSource
324  = new G4LogicalVolume(solidSource, // the solid volume
325  fStainlessSteel, // the material
326  solidSource->GetName()); // the name
327  // Place in the exact center of the water tank
328  position.set(0.0, 0.0, 0.0);
329  new G4PVPlacement(NULL, // no rotation
330  position, // shift to origin
331  logicalSource, // the logical volume
332  logicalSource->GetName(), // the name
333  logicalTankH2O, // the mother volume
334  false, // no boolean ops
335  0, // copy number
336  overlapChecking); // check for overlaps
337 
338  //
339  // Detector Tower
340  //
341  const G4double polyS = 3.0 * inch;
342  const G4double polyH = 18.0 * inch;
343  G4Box* const solidPoly
344  = new G4Box("Poly", // the name
345  polyS, // x size
346  polyS, // y size
347  polyH); // z size
348  G4LogicalVolume* const logicalPoly
349  = new G4LogicalVolume(solidPoly, // the solid volume
350  fPolyethylene, // the material
351  solidPoly->GetName()); // the name
352  // The polyethylene detector tower goes just outside the tank at 45 deg
353  G4double radiusToPolyCenter = (tankOR / std::sqrt(2.0)) + std::sqrt(2.0) * polyS;
354  position.set(-radiusToPolyCenter, radiusToPolyCenter, polyH);
355  new G4PVPlacement(NULL, // no rotation
356  position, // position
357  logicalPoly, // the logical volume
358  logicalPoly->GetName(), // the name
359  logicalWorld, // the mother volume
360  false, // no boolean ops
361  0, // copy number
362  overlapChecking); // check for overlaps
363  // Create the detector shell
364  G4double shellR = 0.3 * inch;
365  G4double shellH = 6.5 * inch;
366  G4Tubs* const solidShell
367  = new G4Tubs("Detector_Shell", // the name
368  0.0, // inner radius
369  shellR, // outer radius
370  shellH * 0.5, // half height
371  0.0 * deg, // start angle
372  360.0 * deg); // end angle
373  G4LogicalVolume* const logicalShell
374  = new G4LogicalVolume(solidShell, // the solid volume
375  fStainlessSteel, // the material
376  solidShell->GetName()); // the name
377  // Place in the exact center of the polyethylene tower
378  position.set(0.0, 0.0, 0.0);
379  new G4PVPlacement(NULL, // no rotation
380  position, // shift to origin
381  logicalShell, // the logical volume
382  logicalShell->GetName(), // the name
383  logicalPoly, // the mother volume
384  false, // no boolean ops
385  0, // copy number
386  overlapChecking); // check for overlaps
387  // Create the BF3 detector
388  G4double BF3R = 0.2 * inch;
389  G4double BF3H = 6.0 * inch;
390  G4Tubs* const solidBF3
391  = new G4Tubs("Detector_BF3_Core", // the name
392  0.0, // inner radius
393  BF3R, // outer radius
394  BF3H * 0.5, // half height
395  0.0 * deg, // start angle
396  360.0 * deg); // end angle
397  G4LogicalVolume* const logicalBF3
398  = new G4LogicalVolume(solidBF3, // the solid volume
399  fBF3_96E, // the material
400  solidBF3->GetName()); // the name
401  // Place in the exact center of the shell
402  position.set(0.0, 0.0, 0.0);
403  new G4PVPlacement(NULL, // no rotation
404  position, // shift to origin
405  logicalBF3, // the logical volume
406  logicalBF3->GetName(), // the name
407  logicalShell, // the mother volume
408  false, // no boolean ops
409  0, // copy number
410  overlapChecking); // check for overlaps
411 
412  return physicalWorld;
413 }
414 
415 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
418 {
419  static G4NistManager* const nist = G4NistManager::Instance();
420 
421  fAir = nist->FindOrBuildMaterial("G4_AIR");
422  fAluminum = nist->FindOrBuildMaterial("G4_Al");
423  fGraphite = nist->FindOrBuildMaterial("G4_GRAPHITE");
424  fPolyethylene = nist->FindOrBuildMaterial("G4_POLYETHYLENE");
425  fStainlessSteel = nist->FindOrBuildMaterial("G4_STAINLESS-STEEL");
426  fWater = nist->FindOrBuildMaterial("G4_WATER");
427 
428  /*// List available materials
429  std::vector< G4String > materials = nist->GetNistMaterialNames();
430  for(unsigned int i = 0;
431  i < materials.size();
432  ++i)
433  {
434  G4cout << materials[i] << G4endl;
435  }*/
436 
437  //
438  // Define the 20% enriched UO2
439  //
440  // First we need to start by creating the isotopes
441  G4double const U235Enrichment = 0.2;
442  G4double const U238Enrichment = 0.8;
443  G4Isotope* const iU235
444  = new G4Isotope("iU235", // name
445  92, // ZZZ
446  235, // AAA
447  235.053930 * (g / mole)); // molecular weight
448  G4Isotope* const iU238
449  = new G4Isotope("iU238", // name
450  92, // ZZZ
451  238, // AAA
452  238.050788 * (g / mole)); // molecular weight
453  // Now create the elements and add the isotopes
454  G4Element* const U235
455  = new G4Element("U235", // name
456  "U235", // symbol
457  1); // number of isotopes
458  U235->AddIsotope(iU235, // isotope
459  1.0); // abundance
460  G4Element* const U238
461  = new G4Element("U238", // name
462  "U238", // symbol
463  1); // number of isotopes
464  U238->AddIsotope(iU238, // isotope
465  1.0); // abundance
466  G4Element* const oxygen = nist->FindOrBuildElement("O");
467  // Calculate the mass fractions
468  const G4double UO2MolecularWeight = U235->GetA() * U235Enrichment
469  + U238->GetA() * U238Enrichment
470  + oxygen->GetA() * 2;
471  const G4double U235MassFraction = (U235->GetA() * U235Enrichment)
472  / UO2MolecularWeight;
473  const G4double U238MassFraction = (U238->GetA() * U238Enrichment)
474  / UO2MolecularWeight;
475  const G4double oxygenMassFraction = (oxygen->GetA() * 2)
476  / UO2MolecularWeight;
477  // create the material and add the elements
478  fUO2_20E = new G4Material("UO2_20E", // name
479  10.97 * (g / cm3), // density
480  3); // number of components
481  fUO2_20E->AddElement(U235, // element
482  U235MassFraction); // mass fraction
483  fUO2_20E->AddElement(U238, // element
484  U238MassFraction); // mass fraction
485  fUO2_20E->AddElement(oxygen, // element
486  oxygenMassFraction); // mass fraction
487 
488  //
489  // Define the BF3
490  //
491  // The BF3 is B-10 enriched
492  // http://www.orau.org/ptp/collection/proportional%20counters/bf3info.htm
493  G4double const B10Enrichment = 0.96;
494  G4double const B11Enrichment = 0.04;
495  G4Isotope* const iB10
496  = new G4Isotope("iB10", // name
497  5, // ZZZ
498  10, // AAA
499  10.0129370 * (g / mole)); // molecular weight
500  G4Isotope* const iB11
501  = new G4Isotope("iB11", // name
502  5, // ZZZ
503  11, // AAA
504  11.0093054 * (g / mole)); // molecular weight
505  // Now create the elements and add the isotopes
506  G4Element* const B10
507  = new G4Element("B10", // name
508  "B10", // symbol
509  1); // number of isotopes
510  B10->AddIsotope(iB10, // isotope
511  1.0); // abundance
512  G4Element* const B11
513  = new G4Element("B11", // name
514  "B11", // symbol
515  1); // number of isotopes
516  B11->AddIsotope(iB11, // isotope
517  1.0); // abundance
518  G4Element* const flouride = nist->FindOrBuildElement("F");
519  // Calculate the mass fractions
520  const G4double BF3MolecularWeight = B10->GetA() * B10Enrichment
521  + B11->GetA() * B11Enrichment
522  + flouride->GetA() * 3;
523  const G4double B10MassFraction = (B10->GetA() * B10Enrichment)
524  / BF3MolecularWeight;
525  const G4double B11MassFraction = (B11->GetA() * B11Enrichment)
526  / BF3MolecularWeight;
527  const G4double flourideMassFraction = (flouride->GetA() * 3)
528  / BF3MolecularWeight;
529  // create the material and add the elements
530  fBF3_96E = new G4Material("BF3_96E", // name
531  2.5 * (kg / m3), // density
532  3); // number of components
533  fBF3_96E->AddElement(B10, // element
534  B10MassFraction); // mass fraction
535  fBF3_96E->AddElement(B11, // element
536  B11MassFraction); // mass fraction
537  fBF3_96E->AddElement(flouride, // element
538  flourideMassFraction); // mass fraction
539 }
540 
541 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
543 PlaceFuelPlate(double x,
544  double y,
545  G4LogicalVolume* const myLogicalVolume,
546  G4LogicalVolume* const parentLogicalVolume)
547 {
548  char copyName[64];
549  G4ThreeVector position(x, y);
550 
551  sprintf(copyName,
552  "Plate@Location X:%.2f Y:%.2f",
553  x / inch,
554  y / inch);
555 
556  new G4PVPlacement(NULL, // no rotation
557  position, // position
558  myLogicalVolume, // the logical volume
559  copyName, // the name
560  parentLogicalVolume, // the mother volume
561  false, // no boolean ops
562  fCopyNumber++, // copy number
563  true); // check for overlaps
564 }
565 
566 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
569 {
570  // Nothing here
571 }
572 
573 
static const double cm
Definition: G4SIunits.hh:106
G4String GetName() const
G4Material * FindOrBuildMaterial(const G4String &name, G4bool isotopes=true, G4bool warning=false)
G4String GetName() const
CLHEP::Hep3Vector G4ThreeVector
static const double m3
Definition: G4SIunits.hh:112
Definition: G4Box.hh:64
const G4String & GetName() const
Definition: G4Material.hh:178
Definition: G4Tubs.hh:85
G4double GetA() const
Definition: G4Element.hh:138
static G4NistManager * Instance()
#define position
Definition: xmlparse.cc:605
G4GLOB_DLL std::ostream G4cout
static const double deg
Definition: G4SIunits.hh:133
bool G4bool
Definition: G4Types.hh:79
void AddIsotope(G4Isotope *isotope, G4double RelativeAbundance)
Definition: G4Element.cc:151
static const double cm3
Definition: G4SIunits.hh:108
static const double kg
Definition: G4SIunits.hh:161
void PlaceFuelPlate(double x, double y, G4LogicalVolume *const myLogicalVolume, G4LogicalVolume *const parentLogicalVolume)
virtual G4VPhysicalVolume * Construct()
static const G4double inch
static const double g
Definition: G4SIunits.hh:162
static const double mole
Definition: G4SIunits.hh:265
#define G4endl
Definition: G4ios.hh:61
void AddElement(G4Element *element, G4int nAtoms)
Definition: G4Material.cc:364
Definition of the FFDetectorConstruction class.
double G4double
Definition: G4Types.hh:76
G4Element * FindOrBuildElement(G4int Z, G4bool isotopes=true)