Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-09 08:28:49

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