Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-23 09:20:58

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 electromagnetic/TestEm3/src/DetectorConstruction.cc
0027 /// \brief Implementation of the DetectorConstruction class
0028 //
0029 //
0030 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0031 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0032 
0033 #include "DetectorConstruction.hh"
0034 
0035 #include "DetectorMessenger.hh"
0036 
0037 #include "G4Box.hh"
0038 #include "G4GeometryManager.hh"
0039 #include "G4LogicalVolume.hh"
0040 #include "G4LogicalVolumeStore.hh"
0041 #include "G4Material.hh"
0042 #include "G4NistManager.hh"
0043 #include "G4PVPlacement.hh"
0044 #include "G4PVReplica.hh"
0045 #include "G4PhysicalConstants.hh"
0046 #include "G4PhysicalVolumeStore.hh"
0047 #include "G4RunManager.hh"
0048 #include "G4SolidStore.hh"
0049 #include "G4SystemOfUnits.hh"
0050 #include "G4UnitsTable.hh"
0051 
0052 #include <iomanip>
0053 
0054 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0055 
0056 DetectorConstruction::DetectorConstruction()
0057 {
0058   for (G4int i = 0; i < kMaxAbsor; ++i) {
0059     fAbsorMaterial[i] = nullptr;
0060     fAbsorThickness[i] = 0.0;
0061     fSolidAbsor[i] = nullptr;
0062     fLogicAbsor[i] = nullptr;
0063     fPhysiAbsor[i] = nullptr;
0064   }
0065 
0066   // default parameter values of the calorimeter
0067   fNbOfAbsor = 2;
0068   fAbsorThickness[1] = 2.3 * mm;
0069   fAbsorThickness[2] = 5.7 * mm;
0070   fNbOfLayers = 50;
0071   fCalorSizeYZ = 40. * cm;
0072   ComputeCalorParameters();
0073 
0074   // materials
0075   DefineMaterials();
0076   SetWorldMaterial("Galactic");
0077   SetAbsorMaterial(1, "G4_Pb");
0078   SetAbsorMaterial(2, "G4_lAr");
0079 
0080   // create commands for interactive definition of the calorimeter
0081   fDetectorMessenger = new DetectorMessenger(this);
0082 }
0083 
0084 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0085 
0086 DetectorConstruction::~DetectorConstruction()
0087 {
0088   delete fDetectorMessenger;
0089 }
0090 
0091 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0092 
0093 void DetectorConstruction::DefineMaterials()
0094 {
0095   // This function illustrates the possible ways to define materials using
0096   // G4 database on G4Elements
0097   G4NistManager* manager = G4NistManager::Instance();
0098   manager->SetVerbose(0);
0099   //
0100   // define Elements
0101   //
0102   G4double z, a;
0103 
0104   G4Element* H = manager->FindOrBuildElement(1);
0105   G4Element* C = manager->FindOrBuildElement(6);
0106   G4Element* N = manager->FindOrBuildElement(7);
0107   G4Element* O = manager->FindOrBuildElement(8);
0108   G4Element* Si = manager->FindOrBuildElement(14);
0109   G4Element* Ge = manager->FindOrBuildElement(32);
0110   G4Element* Sb = manager->FindOrBuildElement(51);
0111   G4Element* I = manager->FindOrBuildElement(53);
0112   G4Element* Cs = manager->FindOrBuildElement(55);
0113   G4Element* Pb = manager->FindOrBuildElement(82);
0114   G4Element* Bi = manager->FindOrBuildElement(83);
0115 
0116   //
0117   // define an Element from isotopes, by relative abundance
0118   //
0119   G4int iz, n;  // iz=number of protons  in an isotope;
0120                 //  n=number of nucleons in an isotope;
0121   G4int ncomponents;
0122   G4double abundance;
0123 
0124   G4Isotope* U5 = new G4Isotope("U235", iz = 92, n = 235, a = 235.01 * g / mole);
0125   G4Isotope* U8 = new G4Isotope("U238", iz = 92, n = 238, a = 238.03 * g / mole);
0126 
0127   G4Element* U = new G4Element("enriched Uranium", "U", ncomponents = 2);
0128   U->AddIsotope(U5, abundance = 90. * perCent);
0129   U->AddIsotope(U8, abundance = 10. * perCent);
0130 
0131   //
0132   // define simple materials
0133   //
0134   G4double density;
0135 
0136   new G4Material("liquidH2", z = 1., a = 1.008 * g / mole, density = 70.8 * mg / cm3);
0137   new G4Material("Aluminium", z = 13., a = 26.98 * g / mole, density = 2.700 * g / cm3);
0138   new G4Material("Titanium", z = 22., a = 47.867 * g / mole, density = 4.54 * g / cm3);
0139   new G4Material("Iron", z = 26., a = 55.85 * g / mole, density = 7.870 * g / cm3);
0140   new G4Material("Copper", z = 29., a = 63.55 * g / mole, density = 8.960 * g / cm3);
0141   new G4Material("Tungsten", z = 74., a = 183.85 * g / mole, density = 19.30 * g / cm3);
0142   new G4Material("Gold", z = 79., a = 196.97 * g / mole, density = 19.32 * g / cm3);
0143   new G4Material("Uranium", z = 92., a = 238.03 * g / mole, density = 18.95 * g / cm3);
0144 
0145   //
0146   // define a material from elements.   case 1: chemical molecule
0147   //
0148   G4int natoms;
0149 
0150   G4Material* H2O = new G4Material("Water", density = 1.000 * g / cm3, ncomponents = 2);
0151   H2O->AddElement(H, natoms = 2);
0152   H2O->AddElement(O, natoms = 1);
0153   H2O->GetIonisation()->SetMeanExcitationEnergy(78.0 * eV);
0154   H2O->SetChemicalFormula("H_2O");
0155 
0156   G4Material* CH = new G4Material("Polystyrene", density = 1.032 * g / cm3, ncomponents = 2);
0157   CH->AddElement(C, natoms = 1);
0158   CH->AddElement(H, natoms = 1);
0159 
0160   G4Material* Sci = new G4Material("Scintillator", density = 1.032 * g / cm3, ncomponents = 2);
0161   Sci->AddElement(C, natoms = 9);
0162   Sci->AddElement(H, natoms = 10);
0163 
0164   Sci->GetIonisation()->SetBirksConstant(0.126 * mm / MeV);
0165 
0166   G4Material* Lct = new G4Material("Lucite", density = 1.185 * g / cm3, ncomponents = 3);
0167   Lct->AddElement(C, 59.97 * perCent);
0168   Lct->AddElement(H, 8.07 * perCent);
0169   Lct->AddElement(O, 31.96 * perCent);
0170 
0171   G4Material* Sili = new G4Material("Silicon", density = 2.330 * g / cm3, ncomponents = 1);
0172   Sili->AddElement(Si, natoms = 1);
0173 
0174   G4Material* SiO2 = new G4Material("quartz", density = 2.200 * g / cm3, ncomponents = 2);
0175   SiO2->AddElement(Si, natoms = 1);
0176   SiO2->AddElement(O, natoms = 2);
0177 
0178   G4Material* G10 = new G4Material("NemaG10", density = 1.700 * g / cm3, ncomponents = 4);
0179   G10->AddElement(Si, natoms = 1);
0180   G10->AddElement(O, natoms = 2);
0181   G10->AddElement(C, natoms = 3);
0182   G10->AddElement(H, natoms = 3);
0183 
0184   G4Material* CsI = new G4Material("CsI", density = 4.534 * g / cm3, ncomponents = 2);
0185   CsI->AddElement(Cs, natoms = 1);
0186   CsI->AddElement(I, natoms = 1);
0187   CsI->GetIonisation()->SetMeanExcitationEnergy(553.1 * eV);
0188 
0189   G4Material* BGO = new G4Material("BGO", density = 7.10 * g / cm3, ncomponents = 3);
0190   BGO->AddElement(O, natoms = 12);
0191   BGO->AddElement(Ge, natoms = 3);
0192   BGO->AddElement(Bi, natoms = 4);
0193 
0194   // SiNx
0195   density = 3.1 * g / cm3;
0196   G4Material* SiNx = new G4Material("SiNx", density, ncomponents = 3);
0197   SiNx->AddElement(Si, 300);
0198   SiNx->AddElement(N, 310);
0199   SiNx->AddElement(H, 6);
0200 
0201   //
0202   // define gaseous materials using G4 NIST database
0203   //
0204   G4double fractionmass;
0205 
0206   G4Material* Air = manager->FindOrBuildMaterial("G4_AIR");
0207   manager->ConstructNewGasMaterial("Air20", "G4_AIR", 293. * kelvin, 1. * atmosphere);
0208 
0209   G4Material* lAr = manager->FindOrBuildMaterial("G4_lAr");
0210   G4Material* lArEm3 = new G4Material("liquidArgon", density = 1.390 * g / cm3, ncomponents = 1);
0211   lArEm3->AddMaterial(lAr, fractionmass = 1.0);
0212 
0213   //
0214   // define a material from elements and others materials (mixture of mixtures)
0215   //
0216 
0217   G4Material* Lead = new G4Material("Lead", density = 11.35 * g / cm3, ncomponents = 1);
0218   Lead->AddElement(Pb, fractionmass = 1.0);
0219 
0220   G4Material* LeadSb = new G4Material("LeadSb", density = 11.35 * g / cm3, ncomponents = 2);
0221   LeadSb->AddElement(Sb, fractionmass = 4. * perCent);
0222   LeadSb->AddElement(Pb, fractionmass = 96. * perCent);
0223 
0224   G4Material* Aerog = new G4Material("Aerogel", density = 0.200 * g / cm3, ncomponents = 3);
0225   Aerog->AddMaterial(SiO2, fractionmass = 62.5 * perCent);
0226   Aerog->AddMaterial(H2O, fractionmass = 37.4 * perCent);
0227   Aerog->AddElement(C, fractionmass = 0.1 * perCent);
0228 
0229   //
0230   // examples of gas in non STP conditions
0231   //
0232   G4double temperature, pressure;
0233 
0234   G4Material* CO2 =
0235     new G4Material("CarbonicGas", density = 27. * mg / cm3, ncomponents = 2, kStateGas,
0236                    temperature = 325. * kelvin, pressure = 50. * atmosphere);
0237   CO2->AddElement(C, natoms = 1);
0238   CO2->AddElement(O, natoms = 2);
0239 
0240   G4Material* steam =
0241     new G4Material("WaterSteam", density = 1.0 * mg / cm3, ncomponents = 1, kStateGas,
0242                    temperature = 273 * kelvin, pressure = 1 * atmosphere);
0243   steam->AddMaterial(H2O, fractionmass = 1.);
0244 
0245   new G4Material("ArgonGas", z = 18, a = 39.948 * g / mole, density = 1.782 * mg / cm3, kStateGas,
0246                  273.15 * kelvin, 1 * atmosphere);
0247   //
0248   // examples of vacuum
0249   //
0250 
0251   density = universe_mean_density;  // from PhysicalConstants.h
0252   pressure = 3.e-18 * pascal;
0253   temperature = 2.73 * kelvin;
0254   new G4Material("Galactic", z = 1., a = 1.008 * g / mole, density, kStateGas, temperature,
0255                  pressure);
0256 
0257   density = 1.e-5 * g / cm3;
0258   pressure = 2.e-2 * bar;
0259   temperature = STP_Temperature;  // from PhysicalConstants.h
0260   G4Material* beam =
0261     new G4Material("Beam", density, ncomponents = 1, kStateGas, temperature, pressure);
0262   beam->AddMaterial(Air, fractionmass = 1.);
0263 
0264   //  G4cout << *(G4Material::GetMaterialTable()) << G4endl;
0265 }
0266 
0267 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0268 
0269 void DetectorConstruction::ComputeCalorParameters()
0270 {
0271   // Compute derived parameters of the calorimeter
0272   fLayerThickness = 0.;
0273   for (G4int iAbs = 1; iAbs <= fNbOfAbsor; iAbs++) {
0274     fLayerThickness += fAbsorThickness[iAbs];
0275   }
0276   fCalorThickness = fNbOfLayers * fLayerThickness;
0277   fWorldSizeX = 1.2 * fCalorThickness;
0278   fWorldSizeYZ = 1.2 * fCalorSizeYZ;
0279 }
0280 
0281 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0282 
0283 G4VPhysicalVolume* DetectorConstruction::Construct()
0284 {
0285   if (fPhysiWorld) {
0286     return fPhysiWorld;
0287   }
0288   // complete the Calor parameters definition
0289   ComputeCalorParameters();
0290 
0291   //
0292   // World
0293   //
0294   fSolidWorld = new G4Box("World",  // its name
0295                           fWorldSizeX / 2, fWorldSizeYZ / 2, fWorldSizeYZ / 2);  // its size
0296 
0297   fLogicWorld = new G4LogicalVolume(fSolidWorld,  // its solid
0298                                     fWorldMaterial,  // its material
0299                                     "World");  // its name
0300 
0301   fPhysiWorld = new G4PVPlacement(0,  // no rotation
0302                                   G4ThreeVector(),  // at (0,0,0)
0303                                   fLogicWorld,  // its fLogical volume
0304                                   "World",  // its name
0305                                   0,  // its mother  volume
0306                                   false,  // no boolean operation
0307                                   0);  // copy number
0308   //
0309   // Calorimeter
0310   //
0311 
0312   fSolidCalor = new G4Box("Calorimeter", fCalorThickness / 2, fCalorSizeYZ / 2, fCalorSizeYZ / 2);
0313 
0314   fLogicCalor = new G4LogicalVolume(fSolidCalor, fWorldMaterial, "Calorimeter");
0315 
0316   fPhysiCalor = new G4PVPlacement(0,  // no rotation
0317                                   G4ThreeVector(),  // at (0,0,0)
0318                                   fLogicCalor,  // its fLogical volume
0319                                   "Calorimeter",  // its name
0320                                   fLogicWorld,  // its mother  volume
0321                                   false,  // no boolean operation
0322                                   0);  // copy number
0323 
0324   //
0325   // Layers
0326   //
0327 
0328   fSolidLayer = new G4Box("Layer", fLayerThickness / 2, fCalorSizeYZ / 2, fCalorSizeYZ / 2);
0329 
0330   fLogicLayer = new G4LogicalVolume(fSolidLayer, fWorldMaterial, "Layer");
0331   if (fNbOfLayers > 1) {
0332     fPhysiLayer =
0333       new G4PVReplica("Layer", fLogicLayer, fLogicCalor, kXAxis, fNbOfLayers, fLayerThickness);
0334   }
0335   else {
0336     fPhysiLayer =
0337       new G4PVPlacement(0, G4ThreeVector(), fLogicLayer, "Layer", fLogicCalor, false, 0);
0338   }
0339   //
0340   // Absorbers
0341   //
0342 
0343   G4double xfront = -0.5 * fLayerThickness;
0344   for (G4int k = 1; k <= fNbOfAbsor; ++k) {
0345     fSolidAbsor[k] = new G4Box("Absorber",  // its name
0346                                fAbsorThickness[k] / 2, fCalorSizeYZ / 2, fCalorSizeYZ / 2);
0347 
0348     fLogicAbsor[k] = new G4LogicalVolume(fSolidAbsor[k],  // its solid
0349                                          fAbsorMaterial[k],  // its material
0350                                          fAbsorMaterial[k]->GetName());
0351 
0352     G4double xcenter = xfront + 0.5 * fAbsorThickness[k];
0353     xfront += fAbsorThickness[k];
0354     fPhysiAbsor[k] = new G4PVPlacement(0, G4ThreeVector(xcenter, 0., 0.), fLogicAbsor[k],
0355                                        fAbsorMaterial[k]->GetName(), fLogicLayer, false,
0356                                        k);  // copy number
0357   }
0358 
0359   PrintCalorParameters();
0360 
0361   // always return the fPhysical World
0362   //
0363   return fPhysiWorld;
0364 }
0365 
0366 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0367 
0368 void DetectorConstruction::PrintCalorParameters()
0369 {
0370   G4cout << "\n-------------------------------------------------------------"
0371          << "\n ---> The calorimeter is " << fNbOfLayers << " layers of:";
0372   for (G4int i = 1; i <= fNbOfAbsor; ++i) {
0373     G4cout << "\n \t" << std::setw(12) << fAbsorMaterial[i]->GetName() << ": " << std::setw(6)
0374            << G4BestUnit(fAbsorThickness[i], "Length");
0375   }
0376   G4cout << "\n-------------------------------------------------------------\n";
0377 
0378   G4cout << "\n" << fWorldMaterial << G4endl;
0379   for (G4int j = 1; j <= fNbOfAbsor; ++j) {
0380     G4cout << "\n" << fAbsorMaterial[j] << G4endl;
0381   }
0382   G4cout << "\n-------------------------------------------------------------\n";
0383 }
0384 
0385 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0386 
0387 void DetectorConstruction::SetWorldMaterial(const G4String& material)
0388 {
0389   // search the material by its name
0390   G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(material);
0391   if (pttoMaterial) {
0392     fWorldMaterial = pttoMaterial;
0393     if (fLogicWorld) {
0394       fLogicWorld->SetMaterial(fWorldMaterial);
0395       fLogicLayer->SetMaterial(fWorldMaterial);
0396       G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0397     }
0398   }
0399 }
0400 
0401 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0402 
0403 void DetectorConstruction::SetNbOfLayers(G4int ival)
0404 {
0405   // set the number of Layers
0406   //
0407   if (ival < 1) {
0408     G4cout << "\n --->warning from SetfNbOfLayers: " << ival
0409            << " must be at least 1. Command refused" << G4endl;
0410     return;
0411   }
0412   fNbOfLayers = ival;
0413 }
0414 
0415 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0416 
0417 void DetectorConstruction::SetNbOfAbsor(G4int ival)
0418 {
0419   // set the number of Absorbers
0420   //
0421   if (ival < 1 || ival > (kMaxAbsor - 1)) {
0422     G4cout << "\n ---> warning from SetfNbOfAbsor: " << ival << " must be at least 1 and and most "
0423            << kMaxAbsor - 1 << ". Command refused" << G4endl;
0424     return;
0425   }
0426   fNbOfAbsor = ival;
0427 }
0428 
0429 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0430 
0431 void DetectorConstruction::SetAbsorMaterial(G4int ival, const G4String& material)
0432 {
0433   // search the material by its name
0434   //
0435   if (ival > fNbOfAbsor || ival <= 0) {
0436     G4cout << "\n --->warning from SetAbsorMaterial: absor number " << ival
0437            << " out of range. Command refused" << G4endl;
0438     return;
0439   }
0440 
0441   G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(material);
0442   if (pttoMaterial) {
0443     fAbsorMaterial[ival] = pttoMaterial;
0444     if (fLogicAbsor[ival]) {
0445       fLogicAbsor[ival]->SetMaterial(pttoMaterial);
0446       G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0447     }
0448   }
0449 }
0450 
0451 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0452 
0453 void DetectorConstruction::SetAbsorThickness(G4int ival, G4double val)
0454 {
0455   // change Absorber thickness
0456   //
0457   if (ival > fNbOfAbsor || ival <= 0) {
0458     G4cout << "\n --->warning from SetAbsorThickness: absor number " << ival
0459            << " out of range. Command refused" << G4endl;
0460     return;
0461   }
0462   if (val <= DBL_MIN) {
0463     G4cout << "\n --->warning from SetAbsorThickness: thickness " << val
0464            << " out of range. Command refused" << G4endl;
0465     return;
0466   }
0467   fAbsorThickness[ival] = val;
0468 }
0469 
0470 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0471 
0472 void DetectorConstruction::SetCalorSizeYZ(G4double val)
0473 {
0474   // change the transverse size
0475   //
0476   if (val <= DBL_MIN) {
0477     G4cout << "\n --->warning from SetfCalorSizeYZ: thickness " << val
0478            << " out of range. Command refused" << G4endl;
0479     return;
0480   }
0481   fCalorSizeYZ = val;
0482 }
0483 
0484 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0485 
0486 #include "G4AutoDelete.hh"
0487 #include "G4GlobalMagFieldMessenger.hh"
0488 
0489 void DetectorConstruction::ConstructSDandField()
0490 {
0491   if (fFieldMessenger.Get() == nullptr) {
0492     // Create global magnetic field messenger.
0493     // Uniform magnetic field is then created automatically if
0494     // the field value is not zero.
0495     G4ThreeVector fieldValue = G4ThreeVector();
0496     G4GlobalMagFieldMessenger* msg = new G4GlobalMagFieldMessenger(fieldValue);
0497     // msg->SetVerboseLevel(1);
0498     G4AutoDelete::Register(msg);
0499     fFieldMessenger.Put(msg);
0500   }
0501 }
0502 
0503 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......