Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/examples/extended/hadronic/ParticleFluence/Calo/src/DetectorConstruction.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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 /// \file DetectorConstruction.hh
 27 /// \brief Definition of the DetectorConstruction class
 28 //
 29 //
 30 
 31 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 32 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 33 
 34 #include "DetectorConstruction.hh"
 35 
 36 #include "DetectorMessenger.hh"
 37 #include "PrimaryGeneratorAction.hh"
 38 
 39 #include "G4Box.hh"
 40 #include "G4Cons.hh"
 41 #include "G4FieldManager.hh"
 42 #include "G4GeometryManager.hh"
 43 #include "G4LogicalVolume.hh"
 44 #include "G4LogicalVolumeStore.hh"
 45 #include "G4Material.hh"
 46 #include "G4PVPlacement.hh"
 47 #include "G4PVReplica.hh"
 48 #include "G4PhysicalConstants.hh"
 49 #include "G4PhysicalVolumeStore.hh"
 50 #include "G4RotationMatrix.hh"
 51 #include "G4RunManager.hh"
 52 #include "G4SDManager.hh"
 53 #include "G4SolidStore.hh"
 54 #include "G4SystemOfUnits.hh"
 55 #include "G4ThreeVector.hh"
 56 #include "G4TransportationManager.hh"
 57 #include "G4Tubs.hh"
 58 #include "G4UniformMagField.hh"
 59 #include "globals.hh"
 60 
 61 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 62 
 63 DetectorConstruction::DetectorConstruction()
 64   : fVacuum(nullptr),
 65     fIron(nullptr),
 66     fCopper(nullptr),
 67     fTungsten(nullptr),
 68     fLead(nullptr),
 69     fUranium(nullptr),
 70     fPbWO4(nullptr),
 71     fPolystyrene(nullptr),
 72     fLiquidArgon(nullptr),
 73     fSilicon(nullptr),
 74     fQuartz(nullptr),
 75     fBrass(nullptr),
 76     fAluminium(nullptr),
 77     fGraphite(nullptr),
 78     fAbsorberMaterial(nullptr),
 79     fActiveMaterial(nullptr),
 80     fExperimentalHall_log(nullptr),
 81     fExperimentalHall_phys(nullptr),
 82     fLogicCalo(nullptr),
 83     fPhysiCalo(nullptr),
 84     fLogicModule(nullptr),
 85     fPhysiModule(nullptr),
 86     fLogicAbsorber(nullptr),
 87     fPhysiAbsorber(nullptr),
 88     fLogicActive(nullptr),
 89     fPhysiActive(nullptr),
 90     fFieldMgr(nullptr),
 91     fUniformMagField(nullptr),
 92     fDetectorMessenger(nullptr),
 93     // Default values.  ***LOOKHERE***
 94     fIsCalHomogeneous(false),  // Sampling calorimeter.
 95     fIsUnitInLambda(false),  // Unit of length for the absorber total length.
 96     fAbsorberTotalLength(2.0 * CLHEP::m),
 97     fCalorimeterRadius(1.0 * CLHEP::m),
 98     fActiveLayerNumber(50),
 99     fActiveLayerSize(4.0 * CLHEP::mm),
100     fIsRadiusUnitInLambda(false),  // Unit of length for the radius bin size.
101     // Extra
102     fCaloLength(2.0 * CLHEP::m),
103     // Scoring part
104     fLogicScoringUpDown(nullptr),
105     fPhysiScoringUpstream(nullptr),
106     fPhysiScoringDownstream(nullptr),
107     fLogicScoringSide(nullptr),
108     fPhysiScoringSide(nullptr)
109 {
110   fFieldMgr = G4TransportationManager::GetTransportationManager()->GetFieldManager();
111   DefineMaterials();
112   fAbsorberMaterial = fIron;
113   fActiveMaterial = fPolystyrene;
114   fDetectorMessenger = new DetectorMessenger(this);
115 }
116 
117 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
118 
119 DetectorConstruction::~DetectorConstruction()
120 {
121   delete fDetectorMessenger;
122   delete fUniformMagField;
123 }
124 
125 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
126 
127 G4VPhysicalVolume* DetectorConstruction::Construct()
128 {
129   return ConstructCalorimeter();
130 }
131 
132 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
133 
134 void DetectorConstruction::ConstructSDandField() {}
135 
136 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
137 
138 void DetectorConstruction::DefineMaterials()
139 {
140   G4double a;  // atomic mass
141   G4double z;  // atomic number
142   G4double density, pressure, temperature, fractionmass;
143   G4String name, symbol;
144   G4int nel, natoms;
145 
146   //--- elements
147 
148   a = 1.01 * g / mole;
149   G4Element* elH = new G4Element(name = "Hydrogen", symbol = "H2", z = 1., a);
150 
151   a = 2.01 * g / mole;
152   // G4Element* elD = new G4Element( name="Deuterium", symbol="D", z=1., a );
153 
154   a = 4. * g / mole;
155   // G4Element* elHe = new G4Element( name="Helium", symbol="He", z=2., a );
156 
157   a = 6.94 * g / mole;
158   // G4Element* elLi = new G4Element( name="Lithium", symbol="Li", z=3., a );
159 
160   a = 9.01 * g / mole;
161   // G4Element* elBe = new G4Element( name="Berillium", symbol="Be", z=4., a );
162 
163   a = 12.01 * g / mole;
164   G4Element* elC = new G4Element(name = "Carbon", symbol = "C", z = 6., a);
165 
166   a = 14.01 * g / mole;
167   G4Element* elN = new G4Element(name = "Nitrogen", symbol = "N2", z = 7., a);
168 
169   a = 16. * g / mole;
170   G4Element* elO = new G4Element(name = "Oxygen", symbol = "O2", z = 8., a);
171 
172   a = 20.18 * g / mole;
173   // G4Element* elNe = new G4Element( name="Neon", symbol="Ne", z=10., a );
174 
175   a = 22.99 * g / mole;
176   // G4Element* elNa = new G4Element( name="Sodium", symbol="Na", z=11., a );
177 
178   a = 26.98 * g / mole;
179   // G4Element* elAl = new G4Element( name="Aluminium", symbol="Al", z=13., a );
180 
181   a = 28.085 * g / mole;
182   G4Element* elSi = new G4Element(name = "Silicon", symbol = "Si", z = 14., a);
183 
184   a = 40.08 * g / mole;
185   // G4Element* elCa = new G4Element( name="Calcium", symbol="Ca", z=20., a );
186 
187   a = 55.850 * g / mole;
188   // G4Element* elFe = new G4Element( name="Iron", symbol="Fe", z=26., a );
189 
190   a = 63.54 * g / mole;
191   G4Element* elCu = new G4Element(name = "Copper", symbol = "Cu", z = 29., a);
192 
193   a = 65.41 * g / mole;
194   G4Element* elZn = new G4Element(name = "Zinc", symbol = "Zn", z = 30., a);
195 
196   a = 183.85 * g / mole;
197   G4Element* elW = new G4Element(name = "Tungstenm", symbol = "W", z = 74., a);
198 
199   a = 207.19 * g / mole;
200   G4Element* elPb = new G4Element(name = "Lead", symbol = "Pb", z = 82., a);
201 
202   a = 238.03 * g / mole;
203   // G4Element* elU = new G4Element(name="Uranium", symbol="U", z=92., a);
204 
205   //--- simple materials
206 
207   // Iron has a  X0 = 1.7585 cm  and  lambda_I = 16.760 cm.
208   density = 7.87 * g / cm3;
209   a = 55.85 * g / mole;
210   fIron = new G4Material(name = "Iron", z = 26., a, density);
211 
212   // Copper has a  X0 = 1.4353 cm  and  lambda_I = 15.056 cm.
213   density = 8.96 * g / cm3;
214   a = 63.54 * g / mole;
215   fCopper = new G4Material(name = "Copper", z = 29., a, density);
216 
217   // Tungsten has a  X0 = 0.35 cm  and  lambda_I = 9.5855 cm.
218   density = 19.3 * g / cm3;
219   a = 183.85 * g / mole;
220   fTungsten = new G4Material(name = "Tungsten", z = 74., a, density);
221 
222   // Lead has a  X0 = 0.56120 cm  and  lambda_I = 17.092 cm.
223   density = 11.35 * g / cm3;
224   a = 207.19 * g / mole;
225   fLead = new G4Material(name = "Lead", z = 82., a, density);
226 
227   // Uranium has a  X0 = 0.31662 cm  and  lambda_I = 10.501 cm.
228   density = 18.95 * g / cm3;
229   a = 238.03 * g / mole;
230   fUranium = new G4Material(name = "Uranium", z = 92., a, density);
231 
232   // Liquid Argon has a  X0 = 10.971 cm  and  lambda_I = 65.769 cm.
233   density = 1.4 * g / cm3;
234   a = 39.95 * g / mole;
235   fLiquidArgon = new G4Material(name = "LiquidArgon", z = 18., a, density);
236 
237   density = 0.002 * g / cm3;
238   a = 39.95 * g / mole;
239   // G4Material* ArgonGas = new G4Material( name="ArgonGas", z=18., a, density );
240 
241   // Silicon has a  X0 = 9.3688 cm  and  lambda_I = 46.5436 cm
242   density = 2.33 * g / cm3;
243   a = 28.085 * g / mole;
244   fSilicon = new G4Material(name = "Silicon", z = 14., a, density);
245 
246   // Aluminium has a  X0 = 8.8959 cm  and  lambda_I = 39.7184 cm
247   density = 2.7 * g / cm3;
248   a = 26.98 * g / mole;
249   fAluminium = new G4Material(name = "Aluminium", z = 13., a, density);
250 
251   // Graphite has a  X0 = 19.3213 cm  and  lambda_I = 38.8235 cm
252   density = 2.210 * g / cm3;
253   a = 12.0107 * g / mole;
254   fGraphite = new G4Material(name = "Graphite", z = 6., a, density);
255 
256   density = 8.96 * g / cm3;
257   a = 58.69 * g / mole;
258   // G4Material* Nickel = new G4Material( name="Nickel", z=28., a, density );
259 
260   //--- mixtures
261 
262   density = 1.290 * mg / cm3;
263   G4Material* Air = new G4Material(name = "Air", density, nel = 2);
264   Air->AddElement(elN, 0.7);
265   Air->AddElement(elO, 0.3);
266 
267   density = 1.e-5 * g / cm3;
268   pressure = 2.e-2 * bar;
269   temperature = STP_Temperature;  // From PhysicalConstants.h .
270   fVacuum = new G4Material(name = "Vacuum", density, nel = 1, kStateGas, temperature, pressure);
271   fVacuum->AddMaterial(Air, fractionmass = 1.);
272 
273   // Plastic scintillator tiles (used both in CMS hadron calorimeter
274   // and ATLAS hadron barrel calorimeter):
275   //     X0 = 42.4 cm  and  lambda_I = 79.360 cm.
276   density = 1.032 * g / cm3;
277   fPolystyrene = new G4Material(name = "Polystyrene", density, nel = 2);
278   fPolystyrene->AddElement(elC, natoms = 19);
279   fPolystyrene->AddElement(elH, natoms = 21);
280 
281   // PbWO4 CMS crystals. It has a  X0 = 0.89 cm  and  lambda_I = 22.4 cm.
282   density = 8.28 * g / cm3;
283   fPbWO4 = new G4Material(name = "PbWO4", density, nel = 3);
284   fPbWO4->AddElement(elPb, natoms = 1);
285   fPbWO4->AddElement(elW, natoms = 1);
286   fPbWO4->AddElement(elO, natoms = 4);
287 
288   fQuartz = new G4Material(name = "Quartz", density = 2.200 * g / cm3, nel = 2);
289   fQuartz->AddElement(elSi, 1);
290   fQuartz->AddElement(elO, 2);
291 
292   fBrass = new G4Material(name = "Brass", density = 8.6 * g / cm3, nel = 2);
293   fBrass->AddElement(elCu, 0.7);
294   fBrass->AddElement(elZn, 0.3);
295 }
296 
297 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
298 
299 G4VPhysicalVolume* DetectorConstruction::ConstructCalorimeter()
300 {
301   if (!AreParametersOK()) {
302     G4cout << " DetectorConstruction::ConstructCalorimeter() : ***ERROR*** " << G4endl
303            << "\t PARAMETERS NOT WELL-DEFINED! GEOMETRY UNCHANGED." << G4endl;
304     return fExperimentalHall_phys;
305   }
306 
307   // Clean old geometry, if any.
308   G4GeometryManager::GetInstance()->OpenGeometry();
309   G4PhysicalVolumeStore::GetInstance()->Clean();
310   G4LogicalVolumeStore::GetInstance()->Clean();
311   G4SolidStore::GetInstance()->Clean();
312 
313   G4double lambda = 0.0;  // G4double X0 = 0.0;
314   if (fIsUnitInLambda) {
315     if (fAbsorberMaterial == fIron) {
316       lambda = 16.760 * cm;  // X0     = 1.7585*cm;
317     }
318     else if (fAbsorberMaterial == fCopper) {
319       lambda = 15.056 * cm;  // X0     = 1.4353*cm;
320     }
321     else if (fAbsorberMaterial == fBrass) {
322       lambda = 15.056 * cm;  // Lack of PDG data: I am assuming the same as Copper.  // X0=1.4353*cm
323     }
324     else if (fAbsorberMaterial == fTungsten) {
325       lambda = 9.5855 * cm;  // X0     = 0.35*cm;
326     }
327     else if (fAbsorberMaterial == fLead) {
328       lambda = 17.092 * cm;  // X0     = 0.56120*cm;
329     }
330     else if (fAbsorberMaterial == fPbWO4) {
331       lambda = 22.4 * cm;  // X0     = 0.89*cm;
332     }
333     else if (fAbsorberMaterial == fUranium) {
334       lambda = 10.501 * cm;  // X0     = 0.31662*cm;
335     }
336     else if (fAbsorberMaterial == fGraphite) {
337       lambda = 38.82 * cm;  // X0     = 19.32*cm;
338     }
339     else {
340       std::cout << "ERROR: absorber material not recognized" << std::endl;
341     }
342   }
343 
344   //------------------- volumes --------------------------
345 
346   G4double absorberTotalLength = fAbsorberTotalLength;
347   G4double calorimeterRadius = fCalorimeterRadius;
348   if (fIsUnitInLambda) {
349     absorberTotalLength *= lambda;
350     calorimeterRadius *= lambda;
351   }
352 
353   // --- experimental hall (world volume)    ***LOOKHERE***
354   //     beam line along the Z-axis
355   G4double expHall_x = 10.0 * m;  // half dimension along x
356   G4double expHall_y = 10.0 * m;  // half dimension along y
357   G4double expHall_z = 10.0 * m;  // half dimension along z
358 
359   G4Box* experimentalHall_box = new G4Box("expHall_box", expHall_x, expHall_y, expHall_z);
360   fExperimentalHall_log = new G4LogicalVolume(experimentalHall_box,  // solid
361                                               fVacuum,  // material
362                                               "expHall_log",  // name
363                                               0,  // field manager
364                                               0,  // sensitive detector
365                                               0);  // user limits
366   fExperimentalHall_phys = new G4PVPlacement(0,  // rotation
367                                              G4ThreeVector(),  // translation
368                                              "expHall",  // name
369                                              fExperimentalHall_log,  // logical volume
370                                              0,  // mother physical volume
371                                              false,  // boolean operation
372                                              0);  // copy number
373 
374   // --- Detector
375   // The idea is to use Replica placement.
376   // To do that, we have to define two extra volumes: the "calorimeter" volume
377   // and the "module". The former, which has the world as its mother volume,
378   // is the mother of the module volume. The calorimeter volume is completely
379   // filled by a number (theActiveLayerNumber) of replicas of the module volume.
380   // A module volume, in its turn, is the mother volume of the absorber layer +
381   // active layer.
382 
383   //            --- absorber layer : logical
384   G4double zAbsorber = absorberTotalLength / static_cast<double>(fActiveLayerNumber);
385   // In the case of homogenous calorimeter the "active" part must be
386   // subtracted because it is made of the same material
387   // (the material of the "active" part is set to be the same as
388   //  the aborber).
389   if (fIsCalHomogeneous) {
390     fActiveMaterial = fAbsorberMaterial;
391     zAbsorber -= fActiveLayerSize;
392   }
393   zAbsorber /= 2.0;  // half dimension along z
394   G4Tubs* solidAbsorber = new G4Tubs("solidAbsorber",  // name
395                                      0.0,  // inner radius
396                                      calorimeterRadius,  // outer radius
397                                      zAbsorber,  // half cylinder length in z
398                                      0.0,  // starting phi angle in rad
399                                      2.0 * pi);  // final phi angle in rad
400   fLogicAbsorber = new G4LogicalVolume(solidAbsorber,  // solid
401                                        fAbsorberMaterial,  // material
402                                        "logicAbsorber",  // name
403                                        0,  // field manager
404                                        0,  // sensitive detector
405                                        0);  // user limits
406 
407   //            --- active layer : logical
408   G4double zActive = fActiveLayerSize / 2.0;  // half dimension along z
409   G4Tubs* solidActive = new G4Tubs("solidActive",  // name
410                                    0.0,  // inner radius
411                                    calorimeterRadius,  // outer radius
412                                    zActive,  // half cylinder length in z
413                                    0.0,  // starting phi angle in rad
414                                    2.0 * pi);  // final phi angle in rad
415   fLogicActive = new G4LogicalVolume(solidActive,  // solid
416                                      fActiveMaterial,  // material
417                                      "logicActive",  // name
418                                      0,  // field manager
419                                      0,  // sensitive detector
420                                      0);  // user limits
421 
422   //        --- module : logical
423   G4double zModule = zAbsorber + zActive;  // half dimension along z
424   G4Tubs* solidModule = new G4Tubs("solidModule",  // name
425                                    0.0,  // inner radius
426                                    calorimeterRadius,  // outer radius
427                                    zModule,  // half cylinder length in z
428                                    0.0,  // starting phi angle in rad
429                                    2.0 * pi);  // final phi angle in rad
430   fLogicModule = new G4LogicalVolume(solidModule,  // solid
431                                      fLead,  // material, it does NOT matter
432                                      "logicModule",  // name
433                                      0,  // field manager
434                                      0,  // sensitive detector
435                                      0);  // user limits
436 
437   //    --- calorimeter : logical
438   G4int numberOfModules = fActiveLayerNumber;
439   G4double zCalo = numberOfModules * zModule;  // half dimension along z
440   fCaloLength = 2.0 * zCalo;
441   G4Tubs* solidCalo = new G4Tubs("solidCalo",  // name
442                                  0.0,  // inner radius
443                                  calorimeterRadius,  // outer radius
444                                  zCalo,  // half cylinder length in z
445                                  0.0,  // starting phi angle in rad
446                                  2.0 * pi);  // final phi angle in rad
447   fLogicCalo = new G4LogicalVolume(solidCalo,  // solid
448                                    fLead,  // material, it does NOT matter
449                                    "logicCalo",  // name
450                                    0,  // field manager
451                                    0,  // sensitive detector
452                                    0);  // user limits
453 
454   //            --- absorber layer : physical
455   G4double zpos = -zActive;
456   fPhysiAbsorber = new G4PVPlacement(0,  // rotation
457                                      G4ThreeVector(0, 0, zpos),  // translation
458                                      fLogicAbsorber,  // logical volume
459                                      "physiAbsorber",  // name
460                                      fLogicModule,  // mother logical volume
461                                      false,  // boolean operation
462                                      1000);  // copy number
463 
464   //            --- active layer : physical
465   zpos += zAbsorber + zActive;
466   fPhysiActive = new G4PVPlacement(0,  // rotation
467                                    G4ThreeVector(0, 0, zpos),  // translation
468                                    fLogicActive,  // logical volume
469                                    "physiActive",  // name
470                                    fLogicModule,  // mother logical volume
471                                    false,  // boolean operation
472                                    2000);  // copy number
473 
474   //        --- module : physical (using replica)
475   fPhysiModule = new G4PVReplica("Calo",  // name
476                                  fLogicModule,  // logical volume
477                                  fLogicCalo,  // mother logical volume
478                                  kZAxis,  // axis of replication
479                                  numberOfModules,  // number of replica
480                                  2 * (zAbsorber + zActive));  // (full) width of replica
481 
482   //    --- calorimeter : physical
483   fPhysiCalo = new G4PVPlacement(0,  // rotation
484                                  G4ThreeVector(),  // translation
485                                  "physiCalo",  // its name
486                                  fLogicCalo,  // logical volume
487                                  fExperimentalHall_phys,  // mother physical volume
488                                  false,  // boolean operation
489                                  100);  // copy number
490 
491   // Three scoring volumes: one thin layer downstream of the calorimeter ("down")
492   //                        one thin layer surrounding (lateral) of the calorimeter ("side")
493   //                        one thin layer upstream of the calorimeter ("up")
494   G4Tubs* solidScoringUpDown = new G4Tubs("solidScoringUpDown",  // name
495                                           0.0,  // inner radius
496                                           calorimeterRadius,  // outer radius
497                                           0.5 * fScoringThickness,  // half cylinder length in z
498                                           0.0,  // starting phi angle in rad
499                                           2.0 * pi);  // final phi angle in rad
500   fLogicScoringUpDown = new G4LogicalVolume(solidScoringUpDown,  // solid
501                                             fVacuum,  // material
502                                             "logicScoringUpDown",  // name
503                                             0,  // field manager
504                                             0,  // sensitive detector
505                                             0);  // user limits
506   G4double zScoringUpDown = 0.5 * (fCaloLength + fScoringThickness);
507   fPhysiScoringUpstream = new G4PVPlacement(0,  // rotation
508                                             G4ThreeVector(0.0, 0.0, -zScoringUpDown),
509                                             // translation
510                                             "physiScoringUpstream",  // name
511                                             fLogicScoringUpDown,  // logical volume
512                                             fExperimentalHall_phys,  // mother physical volume
513                                             false,  // boolean operation
514                                             0);  // copy number
515   fPhysiScoringDownstream = new G4PVPlacement(0,  // rotation
516                                               G4ThreeVector(0.0, 0.0, zScoringUpDown),
517                                               // translation
518                                               "physiScoringDownstream",  // name
519                                               fLogicScoringUpDown,  // logical volume
520                                               fExperimentalHall_phys,  // mother physical volume
521                                               false,  // boolean operation
522                                               0);  // copy number
523 
524   G4Tubs* solidScoringSide = new G4Tubs("solidScoringSide",  // name
525                                         calorimeterRadius,  // inner radius
526                                         calorimeterRadius + fScoringThickness,  // outer radius
527                                         0.5 * fCaloLength,  // half cylinder length in z
528                                         0.0,  // starting phi angle in rad
529                                         2.0 * pi);  // final phi angle in rad
530   fLogicScoringSide = new G4LogicalVolume(solidScoringSide,  // solid
531                                           fVacuum,  // material
532                                           "logicScoringSide",  // name
533                                           0,  // field manager
534                                           0,  // sensitive detector
535                                           0);  // user limits
536   fPhysiScoringSide = new G4PVPlacement(0,  // rotation
537                                         G4ThreeVector(0.0, 0.0, 0.0),  // translation
538                                         "physiScoringSide",  // name
539                                         fLogicScoringSide,  // logical volume
540                                         fExperimentalHall_phys,  // mother physical volume
541                                         false,  // boolean operation
542                                         0);  // copy number
543 
544   return fExperimentalHall_phys;
545 }
546 
547 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
548 
549 G4bool DetectorConstruction::AreParametersOK()
550 {
551   bool isOk = true;
552   if (!fAbsorberMaterial) {
553     isOk = false;
554     G4cout << " DetectorConstruction::AreParametersOK() : UNDEFINED absorber material" << G4endl;
555   }
556   if (!fActiveMaterial) {
557     isOk = false;
558     G4cout << " DetectorConstruction::AreParametersOK() : UNDEFINED active material" << G4endl;
559   }
560   if (fAbsorberTotalLength <= 0.0) {
561     isOk = false;
562     G4cout << " DetectorConstruction::AreParametersOK() : fAbsorberTotalLength = "
563            << fAbsorberTotalLength << G4endl;
564   }
565   if (fCalorimeterRadius <= 0.0) {
566     isOk = false;
567     G4cout << " DetectorConstruction::AreParametersOK() : fCalorimeterRadius = "
568            << fCalorimeterRadius << G4endl;
569   }
570   if (fActiveLayerNumber <= 0) {
571     isOk = false;
572     G4cout << " DetectorConstruction::AreParametersOK() : fActiveLayerNumber = "
573            << fActiveLayerNumber << G4endl;
574   }
575   if (fActiveLayerSize <= 0.0) {
576     isOk = false;
577     G4cout << " DetectorConstruction::AreParametersOK() : fActiveLayerSize = " << fActiveLayerSize
578            << G4endl;
579   }
580   return isOk;
581 }
582 
583 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
584 
585 void DetectorConstruction::SetMagField(const G4double fieldValue)
586 {
587   if (fUniformMagField) {
588     delete fUniformMagField;
589   }
590   if (std::abs(fieldValue) > 0.0) {
591     // Apply a global uniform magnetic field along the Y axis.
592     // Notice that only if the magnetic field is not zero, the Geant4
593     // transportion in field gets activated.
594     fUniformMagField = new G4UniformMagField(G4ThreeVector(0.0, fieldValue, 0.0));
595     fFieldMgr->SetDetectorField(fUniformMagField);
596     fFieldMgr->CreateChordFinder(fUniformMagField);
597   }
598 }
599 
600 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
601 
602 void DetectorConstruction::SetAbsorberMaterial(const G4String name)
603 {
604   if (name == "Fe" || name == "Iron" || name == "iron") {
605     fAbsorberMaterial = fIron;
606   }
607   else if (name == "Cu" || name == "Copper" || name == "copper") {
608     fAbsorberMaterial = fCopper;
609   }
610   else if (name == "Brass" || name == "brass") {
611     fAbsorberMaterial = fBrass;
612   }
613   else if (name == "Pb" || name == "Lead" || name == "lead") {
614     fAbsorberMaterial = fLead;
615   }
616   else if (name == "PbWO4") {
617     fAbsorberMaterial = fPbWO4;
618   }
619   else if (name == "W" || name == "Tungsten" || name == "tungsten") {
620     fAbsorberMaterial = fTungsten;
621   }
622   else if (name == "U" || name == "Uranium" || name == "uranium") {
623     fAbsorberMaterial = fUranium;
624   }
625   else if (name == "C" || name == "Graphite" || name == "graphite") {
626     fAbsorberMaterial = fGraphite;
627   }
628   else {
629     G4cout << G4endl << G4endl << "WARNING: the name of the material has not been recognized!"
630            << G4endl << "     ===> the default  * Iron *  will be used." << G4endl << G4endl;
631     fAbsorberMaterial = fIron;
632   }
633   fLogicAbsorber->SetMaterial(fAbsorberMaterial);
634 }
635 
636 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
637 
638 void DetectorConstruction::SetActiveMaterial(const G4String name)
639 {
640   if (name == "Scintillator" || name == "scintillator") {
641     fActiveMaterial = fPolystyrene;
642   }
643   else if (name == "LAr" || name == "LiquidArgon" || name == "liquidArgon") {
644     fActiveMaterial = fLiquidArgon;
645   }
646   else if (name == "PbWO4") {
647     fActiveMaterial = fPbWO4;
648   }
649   else if (name == "Si" || name == "Silicon" || name == "silicon") {
650     fActiveMaterial = fSilicon;
651   }
652   else if (name == "Quartz" || name == "quartz") {
653     fActiveMaterial = fQuartz;
654   }
655   else if (name == "C" || name == "Graphite" || name == "graphite") {
656     fActiveMaterial = fGraphite;
657   }
658   else {
659     G4cout << G4endl << G4endl << "WARNING: the name of the material has not been recognized!"
660            << G4endl << "     ===> the default  * Scintillator *  will be used." << G4endl
661            << G4endl;
662     fActiveMaterial = fPolystyrene;
663   }
664   fLogicActive->SetMaterial(fActiveMaterial);
665 }
666 
667 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
668 
669 void DetectorConstruction::UpdateGeometry()
670 {
671   // G4RunManager::GetRunManager()->DefineWorldVolume( ConstructCalorimeter() );
672   G4RunManager::GetRunManager()->ReinitializeGeometry();
673   PrintParameters();
674   // Update also the position of the gun
675   const PrimaryGeneratorAction* pPrimaryAction = dynamic_cast<const PrimaryGeneratorAction*>(
676     G4RunManager::GetRunManager()->GetUserPrimaryGeneratorAction());
677   if (pPrimaryAction) pPrimaryAction->SetGunPosition();
678 }
679 
680 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
681 
682 void DetectorConstruction::PrintParameters()
683 {
684   G4cout << G4endl << G4endl << " ------  DetectorConstruction::PrintParameters() ------ " << G4endl
685          << " Absorber Material = ";
686   if (fAbsorberMaterial) {
687     G4cout << fAbsorberMaterial->GetName();
688   }
689   else {
690     G4cout << " UNDEFINED ";
691   }
692   G4cout << G4endl << " Active Material   = ";
693   if (fActiveMaterial) {
694     G4cout << fActiveMaterial->GetName();
695   }
696   else {
697     G4cout << " UNDEFINED ";
698   }
699   G4cout << G4endl << " Is the Calorimeter Homogeneous ? " << fIsCalHomogeneous;
700   G4cout << G4endl << " Is the Unit in Lambda ? " << fIsUnitInLambda;
701   G4cout << G4endl << " Absorber Total Length = ";
702   if (fIsUnitInLambda) {
703     G4cout << fAbsorberTotalLength << "  lambdas";
704   }
705   else {
706     G4cout << fAbsorberTotalLength / m << " m";
707   }
708   G4cout << G4endl << " Calorimeter Radius = ";
709   if (fIsUnitInLambda) {
710     G4cout << fCalorimeterRadius << "  lambdas";
711   }
712   else {
713     G4cout << fCalorimeterRadius / m << " m";
714   }
715   G4cout << G4endl << " Active Layer Number   = " << fActiveLayerNumber;
716   G4cout << G4endl << " Active Layer Size     = " << fActiveLayerSize / mm << " mm";
717   G4cout << G4endl << " Is the Radius Unit in Lambda ? " << fIsRadiusUnitInLambda;
718   G4cout << G4endl << " Radius Bin Size       = ";
719   G4cout << G4endl << " Magnetic field [T]    = ";
720   if (fUniformMagField) {
721     G4cout << fUniformMagField->GetConstantFieldValue() / tesla;
722   }
723   else {
724     G4cout << "(0,0,0)";
725   }
726 
727   G4cout << G4endl << " -------------------------------------------------------- " << G4endl
728          << G4endl;
729 }
730 
731 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
732