Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-04-10 08:06:16

0001 //
0002 // ********************************************************************
0003 // * License and Disclaimer                                           *
0004 // *                                                                  *
0005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
0006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
0007 // * conditions of the Geant4 Software License,  included in the file *
0008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
0009 // * include a list of copyright holders.                             *
0010 // *                                                                  *
0011 // * Neither the authors of this software system, nor their employing *
0012 // * institutes,nor the agencies providing financial support for this *
0013 // * work  make  any representation or  warranty, express or implied, *
0014 // * regarding  this  software system or assume any liability for its *
0015 // * use.  Please see the license in the file  LICENSE  and URL above *
0016 // * for the full disclaimer and the limitation of liability.         *
0017 // *                                                                  *
0018 // * This  code  implementation is the result of  the  scientific and *
0019 // * technical work of the GEANT4 collaboration.                      *
0020 // * By using,  copying,  modifying or  distributing the software (or *
0021 // * any work based  on the software)  you  agree  to acknowledge its *
0022 // * use  in  resulting  scientific  publications,  and indicate your *
0023 // * acceptance of all terms of the Geant4 Software license.          *
0024 // ********************************************************************
0025 //
0026 /// \file DetectorConstruction.hh
0027 /// \brief Definition of the DetectorConstruction class
0028 //
0029 //
0030 
0031 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0032 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0033 
0034 #include "DetectorConstruction.hh"
0035 
0036 #include "DetectorMessenger.hh"
0037 #include "PrimaryGeneratorAction.hh"
0038 
0039 #include "G4Box.hh"
0040 #include "G4Cons.hh"
0041 #include "G4FieldManager.hh"
0042 #include "G4GeometryManager.hh"
0043 #include "G4LogicalVolume.hh"
0044 #include "G4LogicalVolumeStore.hh"
0045 #include "G4Material.hh"
0046 #include "G4PVPlacement.hh"
0047 #include "G4PVReplica.hh"
0048 #include "G4PhysicalConstants.hh"
0049 #include "G4PhysicalVolumeStore.hh"
0050 #include "G4RotationMatrix.hh"
0051 #include "G4RunManager.hh"
0052 #include "G4SDManager.hh"
0053 #include "G4SolidStore.hh"
0054 #include "G4SystemOfUnits.hh"
0055 #include "G4ThreeVector.hh"
0056 #include "G4TransportationManager.hh"
0057 #include "G4Tubs.hh"
0058 #include "G4UniformMagField.hh"
0059 #include "globals.hh"
0060 
0061 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0062 
0063 DetectorConstruction::DetectorConstruction()
0064   : fVacuum(nullptr),
0065     fIron(nullptr),
0066     fCopper(nullptr),
0067     fTungsten(nullptr),
0068     fLead(nullptr),
0069     fUranium(nullptr),
0070     fPbWO4(nullptr),
0071     fPolystyrene(nullptr),
0072     fLiquidArgon(nullptr),
0073     fSilicon(nullptr),
0074     fQuartz(nullptr),
0075     fBrass(nullptr),
0076     fAluminium(nullptr),
0077     fGraphite(nullptr),
0078     fAbsorberMaterial(nullptr),
0079     fActiveMaterial(nullptr),
0080     fExperimentalHall_log(nullptr),
0081     fExperimentalHall_phys(nullptr),
0082     fLogicCalo(nullptr),
0083     fPhysiCalo(nullptr),
0084     fLogicModule(nullptr),
0085     fPhysiModule(nullptr),
0086     fLogicAbsorber(nullptr),
0087     fPhysiAbsorber(nullptr),
0088     fLogicActive(nullptr),
0089     fPhysiActive(nullptr),
0090     fFieldMgr(nullptr),
0091     fUniformMagField(nullptr),
0092     fDetectorMessenger(nullptr),
0093     // Default values.  ***LOOKHERE***
0094     fIsCalHomogeneous(false),  // Sampling calorimeter.
0095     fIsUnitInLambda(false),  // Unit of length for the absorber total length.
0096     fAbsorberTotalLength(2.0 * CLHEP::m),
0097     fCalorimeterRadius(1.0 * CLHEP::m),
0098     fActiveLayerNumber(50),
0099     fActiveLayerSize(4.0 * CLHEP::mm),
0100     fIsRadiusUnitInLambda(false),  // Unit of length for the radius bin size.
0101     // Extra
0102     fCaloLength(2.0 * CLHEP::m),
0103     // Scoring part
0104     fLogicScoringUpDown(nullptr),
0105     fPhysiScoringUpstream(nullptr),
0106     fPhysiScoringDownstream(nullptr),
0107     fLogicScoringSide(nullptr),
0108     fPhysiScoringSide(nullptr)
0109 {
0110   fFieldMgr = G4TransportationManager::GetTransportationManager()->GetFieldManager();
0111   DefineMaterials();
0112   fAbsorberMaterial = fIron;
0113   fActiveMaterial = fPolystyrene;
0114   fDetectorMessenger = new DetectorMessenger(this);
0115 }
0116 
0117 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0118 
0119 DetectorConstruction::~DetectorConstruction()
0120 {
0121   delete fDetectorMessenger;
0122   delete fUniformMagField;
0123 }
0124 
0125 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0126 
0127 G4VPhysicalVolume* DetectorConstruction::Construct()
0128 {
0129   return ConstructCalorimeter();
0130 }
0131 
0132 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0133 
0134 void DetectorConstruction::ConstructSDandField() {}
0135 
0136 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0137 
0138 void DetectorConstruction::DefineMaterials()
0139 {
0140   G4double a;  // atomic mass
0141   G4double z;  // atomic number
0142   G4double density, pressure, temperature, fractionmass;
0143   G4String name, symbol;
0144   G4int nel, natoms;
0145 
0146   //--- elements
0147 
0148   a = 1.01 * g / mole;
0149   G4Element* elH = new G4Element(name = "Hydrogen", symbol = "H2", z = 1., a);
0150 
0151   a = 2.01 * g / mole;
0152   // G4Element* elD = new G4Element( name="Deuterium", symbol="D", z=1., a );
0153 
0154   a = 4. * g / mole;
0155   // G4Element* elHe = new G4Element( name="Helium", symbol="He", z=2., a );
0156 
0157   a = 6.94 * g / mole;
0158   // G4Element* elLi = new G4Element( name="Lithium", symbol="Li", z=3., a );
0159 
0160   a = 9.01 * g / mole;
0161   // G4Element* elBe = new G4Element( name="Berillium", symbol="Be", z=4., a );
0162 
0163   a = 12.01 * g / mole;
0164   G4Element* elC = new G4Element(name = "Carbon", symbol = "C", z = 6., a);
0165 
0166   a = 14.01 * g / mole;
0167   G4Element* elN = new G4Element(name = "Nitrogen", symbol = "N2", z = 7., a);
0168 
0169   a = 16. * g / mole;
0170   G4Element* elO = new G4Element(name = "Oxygen", symbol = "O2", z = 8., a);
0171 
0172   a = 20.18 * g / mole;
0173   // G4Element* elNe = new G4Element( name="Neon", symbol="Ne", z=10., a );
0174 
0175   a = 22.99 * g / mole;
0176   // G4Element* elNa = new G4Element( name="Sodium", symbol="Na", z=11., a );
0177 
0178   a = 26.98 * g / mole;
0179   // G4Element* elAl = new G4Element( name="Aluminium", symbol="Al", z=13., a );
0180 
0181   a = 28.085 * g / mole;
0182   G4Element* elSi = new G4Element(name = "Silicon", symbol = "Si", z = 14., a);
0183 
0184   a = 40.08 * g / mole;
0185   // G4Element* elCa = new G4Element( name="Calcium", symbol="Ca", z=20., a );
0186 
0187   a = 55.850 * g / mole;
0188   // G4Element* elFe = new G4Element( name="Iron", symbol="Fe", z=26., a );
0189 
0190   a = 63.54 * g / mole;
0191   G4Element* elCu = new G4Element(name = "Copper", symbol = "Cu", z = 29., a);
0192 
0193   a = 65.41 * g / mole;
0194   G4Element* elZn = new G4Element(name = "Zinc", symbol = "Zn", z = 30., a);
0195 
0196   a = 183.85 * g / mole;
0197   G4Element* elW = new G4Element(name = "Tungstenm", symbol = "W", z = 74., a);
0198 
0199   a = 207.19 * g / mole;
0200   G4Element* elPb = new G4Element(name = "Lead", symbol = "Pb", z = 82., a);
0201 
0202   a = 238.03 * g / mole;
0203   // G4Element* elU = new G4Element(name="Uranium", symbol="U", z=92., a);
0204 
0205   //--- simple materials
0206 
0207   // Iron has a  X0 = 1.7585 cm  and  lambda_I = 16.760 cm.
0208   density = 7.87 * g / cm3;
0209   a = 55.85 * g / mole;
0210   fIron = new G4Material(name = "Iron", z = 26., a, density);
0211 
0212   // Copper has a  X0 = 1.4353 cm  and  lambda_I = 15.056 cm.
0213   density = 8.96 * g / cm3;
0214   a = 63.54 * g / mole;
0215   fCopper = new G4Material(name = "Copper", z = 29., a, density);
0216 
0217   // Tungsten has a  X0 = 0.35 cm  and  lambda_I = 9.5855 cm.
0218   density = 19.3 * g / cm3;
0219   a = 183.85 * g / mole;
0220   fTungsten = new G4Material(name = "Tungsten", z = 74., a, density);
0221 
0222   // Lead has a  X0 = 0.56120 cm  and  lambda_I = 17.092 cm.
0223   density = 11.35 * g / cm3;
0224   a = 207.19 * g / mole;
0225   fLead = new G4Material(name = "Lead", z = 82., a, density);
0226 
0227   // Uranium has a  X0 = 0.31662 cm  and  lambda_I = 10.501 cm.
0228   density = 18.95 * g / cm3;
0229   a = 238.03 * g / mole;
0230   fUranium = new G4Material(name = "Uranium", z = 92., a, density);
0231 
0232   // Liquid Argon has a  X0 = 10.971 cm  and  lambda_I = 65.769 cm.
0233   density = 1.4 * g / cm3;
0234   a = 39.95 * g / mole;
0235   fLiquidArgon = new G4Material(name = "LiquidArgon", z = 18., a, density);
0236 
0237   density = 0.002 * g / cm3;
0238   a = 39.95 * g / mole;
0239   // G4Material* ArgonGas = new G4Material( name="ArgonGas", z=18., a, density );
0240 
0241   // Silicon has a  X0 = 9.3688 cm  and  lambda_I = 46.5436 cm
0242   density = 2.33 * g / cm3;
0243   a = 28.085 * g / mole;
0244   fSilicon = new G4Material(name = "Silicon", z = 14., a, density);
0245 
0246   // Aluminium has a  X0 = 8.8959 cm  and  lambda_I = 39.7184 cm
0247   density = 2.7 * g / cm3;
0248   a = 26.98 * g / mole;
0249   fAluminium = new G4Material(name = "Aluminium", z = 13., a, density);
0250 
0251   // Graphite has a  X0 = 19.3213 cm  and  lambda_I = 38.8235 cm
0252   density = 2.210 * g / cm3;
0253   a = 12.0107 * g / mole;
0254   fGraphite = new G4Material(name = "Graphite", z = 6., a, density);
0255 
0256   density = 8.96 * g / cm3;
0257   a = 58.69 * g / mole;
0258   // G4Material* Nickel = new G4Material( name="Nickel", z=28., a, density );
0259 
0260   //--- mixtures
0261 
0262   density = 1.290 * mg / cm3;
0263   G4Material* Air = new G4Material(name = "Air", density, nel = 2);
0264   Air->AddElement(elN, 0.7);
0265   Air->AddElement(elO, 0.3);
0266 
0267   density = 1.e-5 * g / cm3;
0268   pressure = 2.e-2 * bar;
0269   temperature = STP_Temperature;  // From PhysicalConstants.h .
0270   fVacuum = new G4Material(name = "Vacuum", density, nel = 1, kStateGas, temperature, pressure);
0271   fVacuum->AddMaterial(Air, fractionmass = 1.);
0272 
0273   // Plastic scintillator tiles (used both in CMS hadron calorimeter
0274   // and ATLAS hadron barrel calorimeter):
0275   //     X0 = 42.4 cm  and  lambda_I = 79.360 cm.
0276   density = 1.032 * g / cm3;
0277   fPolystyrene = new G4Material(name = "Polystyrene", density, nel = 2);
0278   fPolystyrene->AddElement(elC, natoms = 19);
0279   fPolystyrene->AddElement(elH, natoms = 21);
0280 
0281   // PbWO4 CMS crystals. It has a  X0 = 0.89 cm  and  lambda_I = 22.4 cm.
0282   density = 8.28 * g / cm3;
0283   fPbWO4 = new G4Material(name = "PbWO4", density, nel = 3);
0284   fPbWO4->AddElement(elPb, natoms = 1);
0285   fPbWO4->AddElement(elW, natoms = 1);
0286   fPbWO4->AddElement(elO, natoms = 4);
0287 
0288   fQuartz = new G4Material(name = "Quartz", density = 2.200 * g / cm3, nel = 2);
0289   fQuartz->AddElement(elSi, 1);
0290   fQuartz->AddElement(elO, 2);
0291 
0292   fBrass = new G4Material(name = "Brass", density = 8.6 * g / cm3, nel = 2);
0293   fBrass->AddElement(elCu, 0.7);
0294   fBrass->AddElement(elZn, 0.3);
0295 }
0296 
0297 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0298 
0299 G4VPhysicalVolume* DetectorConstruction::ConstructCalorimeter()
0300 {
0301   if (!AreParametersOK()) {
0302     G4cout << " DetectorConstruction::ConstructCalorimeter() : ***ERROR*** " << G4endl
0303            << "\t PARAMETERS NOT WELL-DEFINED! GEOMETRY UNCHANGED." << G4endl;
0304     return fExperimentalHall_phys;
0305   }
0306 
0307   // Clean old geometry, if any.
0308   G4GeometryManager::GetInstance()->OpenGeometry();
0309   G4PhysicalVolumeStore::GetInstance()->Clean();
0310   G4LogicalVolumeStore::GetInstance()->Clean();
0311   G4SolidStore::GetInstance()->Clean();
0312 
0313   G4double lambda = 0.0;  // G4double X0 = 0.0;
0314   if (fIsUnitInLambda) {
0315     if (fAbsorberMaterial == fIron) {
0316       lambda = 16.760 * cm;  // X0     = 1.7585*cm;
0317     }
0318     else if (fAbsorberMaterial == fCopper) {
0319       lambda = 15.056 * cm;  // X0     = 1.4353*cm;
0320     }
0321     else if (fAbsorberMaterial == fBrass) {
0322       lambda = 15.056 * cm;  // Lack of PDG data: I am assuming the same as Copper.  // X0=1.4353*cm
0323     }
0324     else if (fAbsorberMaterial == fTungsten) {
0325       lambda = 9.5855 * cm;  // X0     = 0.35*cm;
0326     }
0327     else if (fAbsorberMaterial == fLead) {
0328       lambda = 17.092 * cm;  // X0     = 0.56120*cm;
0329     }
0330     else if (fAbsorberMaterial == fPbWO4) {
0331       lambda = 22.4 * cm;  // X0     = 0.89*cm;
0332     }
0333     else if (fAbsorberMaterial == fUranium) {
0334       lambda = 10.501 * cm;  // X0     = 0.31662*cm;
0335     }
0336     else if (fAbsorberMaterial == fGraphite) {
0337       lambda = 38.82 * cm;  // X0     = 19.32*cm;
0338     }
0339     else {
0340       std::cout << "ERROR: absorber material not recognized" << std::endl;
0341     }
0342   }
0343 
0344   //------------------- volumes --------------------------
0345 
0346   G4double absorberTotalLength = fAbsorberTotalLength;
0347   G4double calorimeterRadius = fCalorimeterRadius;
0348   if (fIsUnitInLambda) {
0349     absorberTotalLength *= lambda;
0350     calorimeterRadius *= lambda;
0351   }
0352 
0353   // --- experimental hall (world volume)    ***LOOKHERE***
0354   //     beam line along the Z-axis
0355   G4double expHall_x = 10.0 * m;  // half dimension along x
0356   G4double expHall_y = 10.0 * m;  // half dimension along y
0357   G4double expHall_z = 10.0 * m;  // half dimension along z
0358 
0359   G4Box* experimentalHall_box = new G4Box("expHall_box", expHall_x, expHall_y, expHall_z);
0360   fExperimentalHall_log = new G4LogicalVolume(experimentalHall_box,  // solid
0361                                               fVacuum,  // material
0362                                               "expHall_log",  // name
0363                                               0,  // field manager
0364                                               0,  // sensitive detector
0365                                               0);  // user limits
0366   fExperimentalHall_phys = new G4PVPlacement(0,  // rotation
0367                                              G4ThreeVector(),  // translation
0368                                              "expHall",  // name
0369                                              fExperimentalHall_log,  // logical volume
0370                                              0,  // mother physical volume
0371                                              false,  // boolean operation
0372                                              0);  // copy number
0373 
0374   // --- Detector
0375   // The idea is to use Replica placement.
0376   // To do that, we have to define two extra volumes: the "calorimeter" volume
0377   // and the "module". The former, which has the world as its mother volume,
0378   // is the mother of the module volume. The calorimeter volume is completely
0379   // filled by a number (theActiveLayerNumber) of replicas of the module volume.
0380   // A module volume, in its turn, is the mother volume of the absorber layer +
0381   // active layer.
0382 
0383   //            --- absorber layer : logical
0384   G4double zAbsorber = absorberTotalLength / static_cast<double>(fActiveLayerNumber);
0385   // In the case of homogenous calorimeter the "active" part must be
0386   // subtracted because it is made of the same material
0387   // (the material of the "active" part is set to be the same as
0388   //  the aborber).
0389   if (fIsCalHomogeneous) {
0390     fActiveMaterial = fAbsorberMaterial;
0391     zAbsorber -= fActiveLayerSize;
0392   }
0393   zAbsorber /= 2.0;  // half dimension along z
0394   G4Tubs* solidAbsorber = new G4Tubs("solidAbsorber",  // name
0395                                      0.0,  // inner radius
0396                                      calorimeterRadius,  // outer radius
0397                                      zAbsorber,  // half cylinder length in z
0398                                      0.0,  // starting phi angle in rad
0399                                      2.0 * pi);  // final phi angle in rad
0400   fLogicAbsorber = new G4LogicalVolume(solidAbsorber,  // solid
0401                                        fAbsorberMaterial,  // material
0402                                        "logicAbsorber",  // name
0403                                        0,  // field manager
0404                                        0,  // sensitive detector
0405                                        0);  // user limits
0406 
0407   //            --- active layer : logical
0408   G4double zActive = fActiveLayerSize / 2.0;  // half dimension along z
0409   G4Tubs* solidActive = new G4Tubs("solidActive",  // name
0410                                    0.0,  // inner radius
0411                                    calorimeterRadius,  // outer radius
0412                                    zActive,  // half cylinder length in z
0413                                    0.0,  // starting phi angle in rad
0414                                    2.0 * pi);  // final phi angle in rad
0415   fLogicActive = new G4LogicalVolume(solidActive,  // solid
0416                                      fActiveMaterial,  // material
0417                                      "logicActive",  // name
0418                                      0,  // field manager
0419                                      0,  // sensitive detector
0420                                      0);  // user limits
0421 
0422   //        --- module : logical
0423   G4double zModule = zAbsorber + zActive;  // half dimension along z
0424   G4Tubs* solidModule = new G4Tubs("solidModule",  // name
0425                                    0.0,  // inner radius
0426                                    calorimeterRadius,  // outer radius
0427                                    zModule,  // half cylinder length in z
0428                                    0.0,  // starting phi angle in rad
0429                                    2.0 * pi);  // final phi angle in rad
0430   fLogicModule = new G4LogicalVolume(solidModule,  // solid
0431                                      fLead,  // material, it does NOT matter
0432                                      "logicModule",  // name
0433                                      0,  // field manager
0434                                      0,  // sensitive detector
0435                                      0);  // user limits
0436 
0437   //    --- calorimeter : logical
0438   G4int numberOfModules = fActiveLayerNumber;
0439   G4double zCalo = numberOfModules * zModule;  // half dimension along z
0440   fCaloLength = 2.0 * zCalo;
0441   G4Tubs* solidCalo = new G4Tubs("solidCalo",  // name
0442                                  0.0,  // inner radius
0443                                  calorimeterRadius,  // outer radius
0444                                  zCalo,  // half cylinder length in z
0445                                  0.0,  // starting phi angle in rad
0446                                  2.0 * pi);  // final phi angle in rad
0447   fLogicCalo = new G4LogicalVolume(solidCalo,  // solid
0448                                    fLead,  // material, it does NOT matter
0449                                    "logicCalo",  // name
0450                                    0,  // field manager
0451                                    0,  // sensitive detector
0452                                    0);  // user limits
0453 
0454   //            --- absorber layer : physical
0455   G4double zpos = -zActive;
0456   fPhysiAbsorber = new G4PVPlacement(0,  // rotation
0457                                      G4ThreeVector(0, 0, zpos),  // translation
0458                                      fLogicAbsorber,  // logical volume
0459                                      "physiAbsorber",  // name
0460                                      fLogicModule,  // mother logical volume
0461                                      false,  // boolean operation
0462                                      1000);  // copy number
0463 
0464   //            --- active layer : physical
0465   zpos += zAbsorber + zActive;
0466   fPhysiActive = new G4PVPlacement(0,  // rotation
0467                                    G4ThreeVector(0, 0, zpos),  // translation
0468                                    fLogicActive,  // logical volume
0469                                    "physiActive",  // name
0470                                    fLogicModule,  // mother logical volume
0471                                    false,  // boolean operation
0472                                    2000);  // copy number
0473 
0474   //        --- module : physical (using replica)
0475   fPhysiModule = new G4PVReplica("Calo",  // name
0476                                  fLogicModule,  // logical volume
0477                                  fLogicCalo,  // mother logical volume
0478                                  kZAxis,  // axis of replication
0479                                  numberOfModules,  // number of replica
0480                                  2 * (zAbsorber + zActive));  // (full) width of replica
0481 
0482   //    --- calorimeter : physical
0483   fPhysiCalo = new G4PVPlacement(0,  // rotation
0484                                  G4ThreeVector(),  // translation
0485                                  "physiCalo",  // its name
0486                                  fLogicCalo,  // logical volume
0487                                  fExperimentalHall_phys,  // mother physical volume
0488                                  false,  // boolean operation
0489                                  100);  // copy number
0490 
0491   // Three scoring volumes: one thin layer downstream of the calorimeter ("down")
0492   //                        one thin layer surrounding (lateral) of the calorimeter ("side")
0493   //                        one thin layer upstream of the calorimeter ("up")
0494   G4Tubs* solidScoringUpDown = new G4Tubs("solidScoringUpDown",  // name
0495                                           0.0,  // inner radius
0496                                           calorimeterRadius,  // outer radius
0497                                           0.5 * fScoringThickness,  // half cylinder length in z
0498                                           0.0,  // starting phi angle in rad
0499                                           2.0 * pi);  // final phi angle in rad
0500   fLogicScoringUpDown = new G4LogicalVolume(solidScoringUpDown,  // solid
0501                                             fVacuum,  // material
0502                                             "logicScoringUpDown",  // name
0503                                             0,  // field manager
0504                                             0,  // sensitive detector
0505                                             0);  // user limits
0506   G4double zScoringUpDown = 0.5 * (fCaloLength + fScoringThickness);
0507   fPhysiScoringUpstream = new G4PVPlacement(0,  // rotation
0508                                             G4ThreeVector(0.0, 0.0, -zScoringUpDown),
0509                                             // translation
0510                                             "physiScoringUpstream",  // name
0511                                             fLogicScoringUpDown,  // logical volume
0512                                             fExperimentalHall_phys,  // mother physical volume
0513                                             false,  // boolean operation
0514                                             0);  // copy number
0515   fPhysiScoringDownstream = new G4PVPlacement(0,  // rotation
0516                                               G4ThreeVector(0.0, 0.0, zScoringUpDown),
0517                                               // translation
0518                                               "physiScoringDownstream",  // name
0519                                               fLogicScoringUpDown,  // logical volume
0520                                               fExperimentalHall_phys,  // mother physical volume
0521                                               false,  // boolean operation
0522                                               0);  // copy number
0523 
0524   G4Tubs* solidScoringSide = new G4Tubs("solidScoringSide",  // name
0525                                         calorimeterRadius,  // inner radius
0526                                         calorimeterRadius + fScoringThickness,  // outer radius
0527                                         0.5 * fCaloLength,  // half cylinder length in z
0528                                         0.0,  // starting phi angle in rad
0529                                         2.0 * pi);  // final phi angle in rad
0530   fLogicScoringSide = new G4LogicalVolume(solidScoringSide,  // solid
0531                                           fVacuum,  // material
0532                                           "logicScoringSide",  // name
0533                                           0,  // field manager
0534                                           0,  // sensitive detector
0535                                           0);  // user limits
0536   fPhysiScoringSide = new G4PVPlacement(0,  // rotation
0537                                         G4ThreeVector(0.0, 0.0, 0.0),  // translation
0538                                         "physiScoringSide",  // name
0539                                         fLogicScoringSide,  // logical volume
0540                                         fExperimentalHall_phys,  // mother physical volume
0541                                         false,  // boolean operation
0542                                         0);  // copy number
0543 
0544   return fExperimentalHall_phys;
0545 }
0546 
0547 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0548 
0549 G4bool DetectorConstruction::AreParametersOK()
0550 {
0551   bool isOk = true;
0552   if (!fAbsorberMaterial) {
0553     isOk = false;
0554     G4cout << " DetectorConstruction::AreParametersOK() : UNDEFINED absorber material" << G4endl;
0555   }
0556   if (!fActiveMaterial) {
0557     isOk = false;
0558     G4cout << " DetectorConstruction::AreParametersOK() : UNDEFINED active material" << G4endl;
0559   }
0560   if (fAbsorberTotalLength <= 0.0) {
0561     isOk = false;
0562     G4cout << " DetectorConstruction::AreParametersOK() : fAbsorberTotalLength = "
0563            << fAbsorberTotalLength << G4endl;
0564   }
0565   if (fCalorimeterRadius <= 0.0) {
0566     isOk = false;
0567     G4cout << " DetectorConstruction::AreParametersOK() : fCalorimeterRadius = "
0568            << fCalorimeterRadius << G4endl;
0569   }
0570   if (fActiveLayerNumber <= 0) {
0571     isOk = false;
0572     G4cout << " DetectorConstruction::AreParametersOK() : fActiveLayerNumber = "
0573            << fActiveLayerNumber << G4endl;
0574   }
0575   if (fActiveLayerSize <= 0.0) {
0576     isOk = false;
0577     G4cout << " DetectorConstruction::AreParametersOK() : fActiveLayerSize = " << fActiveLayerSize
0578            << G4endl;
0579   }
0580   return isOk;
0581 }
0582 
0583 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0584 
0585 void DetectorConstruction::SetMagField(const G4double fieldValue)
0586 {
0587   if (fUniformMagField) {
0588     delete fUniformMagField;
0589   }
0590   if (std::abs(fieldValue) > 0.0) {
0591     // Apply a global uniform magnetic field along the Y axis.
0592     // Notice that only if the magnetic field is not zero, the Geant4
0593     // transportion in field gets activated.
0594     fUniformMagField = new G4UniformMagField(G4ThreeVector(0.0, fieldValue, 0.0));
0595     fFieldMgr->SetDetectorField(fUniformMagField);
0596     fFieldMgr->CreateChordFinder(fUniformMagField);
0597   }
0598 }
0599 
0600 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0601 
0602 void DetectorConstruction::SetAbsorberMaterial(const G4String name)
0603 {
0604   if (name == "Fe" || name == "Iron" || name == "iron") {
0605     fAbsorberMaterial = fIron;
0606   }
0607   else if (name == "Cu" || name == "Copper" || name == "copper") {
0608     fAbsorberMaterial = fCopper;
0609   }
0610   else if (name == "Brass" || name == "brass") {
0611     fAbsorberMaterial = fBrass;
0612   }
0613   else if (name == "Pb" || name == "Lead" || name == "lead") {
0614     fAbsorberMaterial = fLead;
0615   }
0616   else if (name == "PbWO4") {
0617     fAbsorberMaterial = fPbWO4;
0618   }
0619   else if (name == "W" || name == "Tungsten" || name == "tungsten") {
0620     fAbsorberMaterial = fTungsten;
0621   }
0622   else if (name == "U" || name == "Uranium" || name == "uranium") {
0623     fAbsorberMaterial = fUranium;
0624   }
0625   else if (name == "C" || name == "Graphite" || name == "graphite") {
0626     fAbsorberMaterial = fGraphite;
0627   }
0628   else {
0629     G4cout << G4endl << G4endl << "WARNING: the name of the material has not been recognized!"
0630            << G4endl << "     ===> the default  * Iron *  will be used." << G4endl << G4endl;
0631     fAbsorberMaterial = fIron;
0632   }
0633   fLogicAbsorber->SetMaterial(fAbsorberMaterial);
0634 }
0635 
0636 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0637 
0638 void DetectorConstruction::SetActiveMaterial(const G4String name)
0639 {
0640   if (name == "Scintillator" || name == "scintillator") {
0641     fActiveMaterial = fPolystyrene;
0642   }
0643   else if (name == "LAr" || name == "LiquidArgon" || name == "liquidArgon") {
0644     fActiveMaterial = fLiquidArgon;
0645   }
0646   else if (name == "PbWO4") {
0647     fActiveMaterial = fPbWO4;
0648   }
0649   else if (name == "Si" || name == "Silicon" || name == "silicon") {
0650     fActiveMaterial = fSilicon;
0651   }
0652   else if (name == "Quartz" || name == "quartz") {
0653     fActiveMaterial = fQuartz;
0654   }
0655   else if (name == "C" || name == "Graphite" || name == "graphite") {
0656     fActiveMaterial = fGraphite;
0657   }
0658   else {
0659     G4cout << G4endl << G4endl << "WARNING: the name of the material has not been recognized!"
0660            << G4endl << "     ===> the default  * Scintillator *  will be used." << G4endl
0661            << G4endl;
0662     fActiveMaterial = fPolystyrene;
0663   }
0664   fLogicActive->SetMaterial(fActiveMaterial);
0665 }
0666 
0667 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0668 
0669 void DetectorConstruction::UpdateGeometry()
0670 {
0671   // G4RunManager::GetRunManager()->DefineWorldVolume( ConstructCalorimeter() );
0672   G4RunManager::GetRunManager()->ReinitializeGeometry();
0673   PrintParameters();
0674   // Update also the position of the gun
0675   const PrimaryGeneratorAction* pPrimaryAction = dynamic_cast<const PrimaryGeneratorAction*>(
0676     G4RunManager::GetRunManager()->GetUserPrimaryGeneratorAction());
0677   if (pPrimaryAction) pPrimaryAction->SetGunPosition();
0678 }
0679 
0680 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0681 
0682 void DetectorConstruction::PrintParameters()
0683 {
0684   G4cout << G4endl << G4endl << " ------  DetectorConstruction::PrintParameters() ------ " << G4endl
0685          << " Absorber Material = ";
0686   if (fAbsorberMaterial) {
0687     G4cout << fAbsorberMaterial->GetName();
0688   }
0689   else {
0690     G4cout << " UNDEFINED ";
0691   }
0692   G4cout << G4endl << " Active Material   = ";
0693   if (fActiveMaterial) {
0694     G4cout << fActiveMaterial->GetName();
0695   }
0696   else {
0697     G4cout << " UNDEFINED ";
0698   }
0699   G4cout << G4endl << " Is the Calorimeter Homogeneous ? " << fIsCalHomogeneous;
0700   G4cout << G4endl << " Is the Unit in Lambda ? " << fIsUnitInLambda;
0701   G4cout << G4endl << " Absorber Total Length = ";
0702   if (fIsUnitInLambda) {
0703     G4cout << fAbsorberTotalLength << "  lambdas";
0704   }
0705   else {
0706     G4cout << fAbsorberTotalLength / m << " m";
0707   }
0708   G4cout << G4endl << " Calorimeter Radius = ";
0709   if (fIsUnitInLambda) {
0710     G4cout << fCalorimeterRadius << "  lambdas";
0711   }
0712   else {
0713     G4cout << fCalorimeterRadius / m << " m";
0714   }
0715   G4cout << G4endl << " Active Layer Number   = " << fActiveLayerNumber;
0716   G4cout << G4endl << " Active Layer Size     = " << fActiveLayerSize / mm << " mm";
0717   G4cout << G4endl << " Is the Radius Unit in Lambda ? " << fIsRadiusUnitInLambda;
0718   G4cout << G4endl << " Radius Bin Size       = ";
0719   G4cout << G4endl << " Magnetic field [T]    = ";
0720   if (fUniformMagField) {
0721     G4cout << fUniformMagField->GetConstantFieldValue() / tesla;
0722   }
0723   else {
0724     G4cout << "(0,0,0)";
0725   }
0726 
0727   G4cout << G4endl << " -------------------------------------------------------- " << G4endl
0728          << G4endl;
0729 }
0730 
0731 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......