Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-21 07:54:05

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 
0033 #include "G4Box.hh"
0034 #include "G4LogicalVolume.hh"
0035 #include "G4Material.hh"
0036 #include "G4NistManager.hh"
0037 #include "G4PVPlacement.hh"
0038 #include "G4PVReplica.hh"
0039 #include "G4PhysicalConstants.hh"
0040 #include "G4ProductionCutsTable.hh"
0041 #include "G4Region.hh"
0042 #include "G4RunManager.hh"
0043 #include "G4SystemOfUnits.hh"
0044 #include "G4UnitsTable.hh"
0045 
0046 #include <iomanip>
0047 
0048 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0049 
0050 DetectorConstruction::DetectorConstruction()
0051   : fWorldMaterial(nullptr),
0052     fLogicWorld(nullptr),
0053     fPhysiWorld(nullptr),
0054     fLogicLayerFront(nullptr),
0055     fLogicLayerBack(nullptr)
0056 {
0057   for (G4int i = 0; i < kMaxAbsor; ++i) {
0058     fAbsorMaterial[i] = nullptr;
0059     fAbsorThickness[i] = 0.0;
0060     fLogicAbsorFront[i] = nullptr;
0061     fLogicAbsorBack[i] = nullptr;
0062   }
0063 
0064   // default parameter values of the calorimeter
0065   fNbOfAbsor = 2;
0066   fAbsorThickness[1] = 2.3 * mm;
0067   fAbsorThickness[2] = 5.7 * mm;
0068   fNbOfLayers = 50;
0069   fCalorSizeYZ = 40. * cm;
0070   ComputeCalorParameters();
0071 
0072   // materials
0073   SetWorldMaterial("G4_Galactic");
0074   SetAbsorMaterial(1, "G4_Pb");
0075   SetAbsorMaterial(2, "G4_lAr");
0076 
0077   // create commands for interactive definition of the calorimeter
0078   fDetectorMessenger.reset(new DetectorMessenger(this));
0079 }
0080 
0081 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0082 
0083 void DetectorConstruction::ComputeCalorParameters()
0084 {
0085   // Compute derived parameters of the calorimeter
0086   fLayerThickness = 0.;
0087   for (G4int iAbs = 1; iAbs <= fNbOfAbsor; iAbs++) {
0088     fLayerThickness += fAbsorThickness[iAbs];
0089   }
0090   fCalorThickness = fNbOfLayers * fLayerThickness;
0091   fWorldSizeX = 1.2 * fCalorThickness;
0092   fWorldSizeYZ = 1.2 * fCalorSizeYZ;
0093 }
0094 
0095 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0096 
0097 G4VPhysicalVolume* DetectorConstruction::Construct()
0098 {
0099   if (fPhysiWorld) {
0100     return fPhysiWorld;
0101   }
0102   // complete the Calor parameters definition
0103   ComputeCalorParameters();
0104 
0105   //
0106   // World
0107   //
0108   auto* solidWorld = new G4Box("World",  // its name
0109                                fWorldSizeX / 2, fWorldSizeYZ / 2,
0110                                fWorldSizeYZ / 2);  // its size
0111 
0112   fLogicWorld = new G4LogicalVolume(solidWorld,  // its solid
0113                                     fWorldMaterial,  // its material
0114                                     "World");  // its name
0115 
0116   fPhysiWorld = new G4PVPlacement(0,  // no rotation
0117                                   G4ThreeVector(),  // at (0,0,0)
0118                                   fLogicWorld,  // its fLogical volume
0119                                   "World",  // its name
0120                                   0,  // its mother  volume
0121                                   false,  // no boolean operation
0122                                   0);  // copy number
0123   //
0124   // Calorimeter
0125   //
0126 
0127   auto* solidCalor =
0128     new G4Box("Calorimeter", fCalorThickness / 2, fCalorSizeYZ / 2, fCalorSizeYZ / 2);
0129 
0130   auto* logicCalor = new G4LogicalVolume(solidCalor, fWorldMaterial, "Calorimeter");
0131 
0132   new G4PVPlacement(0,  // no rotation
0133                     G4ThreeVector(),  // at (0,0,0)
0134                     logicCalor,  // its fLogical volume
0135                     "Calorimeter",  // its name
0136                     fLogicWorld,  // its mother  volume
0137                     false,  // no boolean operation
0138                     0);  // copy number
0139 
0140   //
0141   // Layers
0142   //
0143 
0144   auto* solidLayer = new G4Box("Layer", fLayerThickness / 2, fCalorSizeYZ / 2, fCalorSizeYZ / 2);
0145 
0146   fLogicLayerFront = new G4LogicalVolume(solidLayer, fWorldMaterial, "Layer-front");
0147   fLogicLayerBack = new G4LogicalVolume(solidLayer, fWorldMaterial, "Layer-back");
0148   G4double xfront = -0.5 * fCalorThickness;
0149   for (G4int l = 0; l < fNbOfLayers; ++l) {
0150     G4double xcenter = xfront + 0.5 * fLayerThickness;
0151     xfront += fLayerThickness;
0152     G4LogicalVolume* logicLayer = fLogicLayerFront;
0153     if (xcenter > 0) {
0154       logicLayer = fLogicLayerBack;
0155     }
0156 
0157     new G4PVPlacement(0, G4ThreeVector(xcenter, 0, 0), logicLayer, "Layer", logicCalor, false, l);
0158   }
0159 
0160   //
0161   // Regions
0162   //
0163 
0164   auto* regionFront = new G4Region("Front");
0165   regionFront->SetProductionCuts(
0166     G4ProductionCutsTable::GetProductionCutsTable()->GetDefaultProductionCuts());
0167   regionFront->AddRootLogicalVolume(fLogicLayerFront);
0168   auto* regionBack = new G4Region("Back");
0169   regionBack->SetProductionCuts(
0170     G4ProductionCutsTable::GetProductionCutsTable()->GetDefaultProductionCuts());
0171   regionBack->AddRootLogicalVolume(fLogicLayerBack);
0172 
0173   //
0174   // Absorbers
0175   //
0176 
0177   xfront = -0.5 * fLayerThickness;
0178   for (G4int k = 1; k <= fNbOfAbsor; ++k) {
0179     auto* solidAbsor = new G4Box("Absorber",  // its name
0180                                  fAbsorThickness[k] / 2, fCalorSizeYZ / 2, fCalorSizeYZ / 2);
0181 
0182     fLogicAbsorFront[k] = new G4LogicalVolume(solidAbsor,  // its solid
0183                                               fAbsorMaterial[k],  // its material
0184                                               fAbsorMaterial[k]->GetName());
0185     fLogicAbsorBack[k] = new G4LogicalVolume(solidAbsor,  // its solid
0186                                              fAbsorMaterial[k],  // its material
0187                                              fAbsorMaterial[k]->GetName());
0188 
0189     G4double xcenter = xfront + 0.5 * fAbsorThickness[k];
0190     xfront += fAbsorThickness[k];
0191     new G4PVPlacement(0, G4ThreeVector(xcenter, 0., 0.), fLogicAbsorFront[k],
0192                       fAbsorMaterial[k]->GetName(), fLogicLayerFront, false,
0193                       k);  // copy number
0194     new G4PVPlacement(0, G4ThreeVector(xcenter, 0., 0.), fLogicAbsorBack[k],
0195                       fAbsorMaterial[k]->GetName(), fLogicLayerBack, false,
0196                       k);  // copy number
0197   }
0198 
0199   PrintCalorParameters();
0200 
0201   // always return the fPhysical World
0202   //
0203   return fPhysiWorld;
0204 }
0205 
0206 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0207 
0208 void DetectorConstruction::PrintCalorParameters()
0209 {
0210   G4cout << "\n-------------------------------------------------------------"
0211          << "\n ---> The calorimeter is " << fNbOfLayers << " layers of:";
0212   for (G4int i = 1; i <= fNbOfAbsor; ++i) {
0213     G4cout << "\n \t" << std::setw(12) << fAbsorMaterial[i]->GetName() << ": " << std::setw(6)
0214            << G4BestUnit(fAbsorThickness[i], "Length");
0215   }
0216   G4cout << "\n-------------------------------------------------------------\n";
0217 
0218   G4cout << "\n" << fWorldMaterial << G4endl;
0219   for (G4int j = 1; j <= fNbOfAbsor; ++j) {
0220     G4cout << "\n" << fAbsorMaterial[j] << G4endl;
0221   }
0222   G4cout << "\n-------------------------------------------------------------\n";
0223 }
0224 
0225 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0226 
0227 void DetectorConstruction::SetWorldMaterial(const G4String& material)
0228 {
0229   // search the material by its name
0230   G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(material);
0231   if (pttoMaterial) {
0232     fWorldMaterial = pttoMaterial;
0233     if (fLogicWorld) {
0234       fLogicWorld->SetMaterial(fWorldMaterial);
0235       fLogicLayerFront->SetMaterial(fWorldMaterial);
0236       fLogicLayerBack->SetMaterial(fWorldMaterial);
0237       G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0238     }
0239   }
0240 }
0241 
0242 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0243 
0244 void DetectorConstruction::SetNbOfLayers(G4int ival)
0245 {
0246   // set the number of Layers
0247   //
0248   if (ival < 2) {
0249     G4cout << "\n --->warning from SetfNbOfLayers: " << ival
0250            << " must be at least 2. Command refused" << G4endl;
0251     return;
0252   }
0253   fNbOfLayers = ival;
0254 }
0255 
0256 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0257 
0258 void DetectorConstruction::SetNbOfAbsor(G4int ival)
0259 {
0260   // set the number of Absorbers
0261   //
0262   if (ival < 1 || ival > (kMaxAbsor - 1)) {
0263     G4cout << "\n ---> warning from SetfNbOfAbsor: " << ival << " must be at least 1 and and most "
0264            << kMaxAbsor - 1 << ". Command refused" << G4endl;
0265     return;
0266   }
0267   fNbOfAbsor = ival;
0268 }
0269 
0270 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0271 
0272 void DetectorConstruction::SetAbsorMaterial(G4int ival, const G4String& material)
0273 {
0274   // search the material by its name
0275   //
0276   if (ival > fNbOfAbsor || ival <= 0) {
0277     G4cout << "\n --->warning from SetAbsorMaterial: absor number " << ival
0278            << " out of range. Command refused" << G4endl;
0279     return;
0280   }
0281 
0282   G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(material);
0283   if (pttoMaterial) {
0284     fAbsorMaterial[ival] = pttoMaterial;
0285     if (fLogicAbsorFront[ival]) {
0286       fLogicAbsorFront[ival]->SetMaterial(pttoMaterial);
0287       fLogicAbsorBack[ival]->SetMaterial(pttoMaterial);
0288       G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0289     }
0290   }
0291 }
0292 
0293 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0294 
0295 void DetectorConstruction::SetAbsorThickness(G4int ival, G4double val)
0296 {
0297   // change Absorber thickness
0298   //
0299   if (ival > fNbOfAbsor || ival <= 0) {
0300     G4cout << "\n --->warning from SetAbsorThickness: absor number " << ival
0301            << " out of range. Command refused" << G4endl;
0302     return;
0303   }
0304   if (val <= DBL_MIN) {
0305     G4cout << "\n --->warning from SetAbsorThickness: thickness " << val
0306            << " out of range. Command refused" << G4endl;
0307     return;
0308   }
0309   fAbsorThickness[ival] = val;
0310 }
0311 
0312 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0313 
0314 void DetectorConstruction::SetCalorSizeYZ(G4double val)
0315 {
0316   // change the transverse size
0317   //
0318   if (val <= DBL_MIN) {
0319     G4cout << "\n --->warning from SetfCalorSizeYZ: thickness " << val
0320            << " out of range. Command refused" << G4endl;
0321     return;
0322   }
0323   fCalorSizeYZ = val;
0324 }
0325 
0326 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0327 
0328 #include "G4AutoDelete.hh"
0329 #include "G4GlobalMagFieldMessenger.hh"
0330 
0331 void DetectorConstruction::ConstructSDandField()
0332 {
0333   if (fFieldMessenger.Get() == nullptr) {
0334     // Create global magnetic field messenger.
0335     // Uniform magnetic field is then created automatically if
0336     // the field value is not zero.
0337     G4ThreeVector fieldValue = G4ThreeVector();
0338     G4GlobalMagFieldMessenger* msg = new G4GlobalMagFieldMessenger(fieldValue);
0339     // msg->SetVerboseLevel(1);
0340     G4AutoDelete::Register(msg);
0341     fFieldMessenger.Put(msg);
0342   }
0343 }
0344 
0345 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......