Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-23 09:22:47

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