Back to home page

EIC code displayed by LXR

 
 

    


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

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 #include "Par04DetectorConstruction.hh"
0027 
0028 #include "Par04DefineMeshModel.hh"  // for Par04DefineMeshModel
0029 #include "Par04DetectorMessenger.hh"  // for Par04DetectorMessenger
0030 #include "Par04SensitiveDetector.hh"  // for Par04SensitiveDetector
0031 
0032 #include "G4Box.hh"  // for G4Box
0033 #include "G4LogicalVolume.hh"  // for G4LogicalVolume
0034 #include "G4Material.hh"  // for G4Material
0035 #include "G4NistManager.hh"  // for G4NistManager
0036 #include "G4PVPlacement.hh"  // for G4PVPlacement
0037 #include "G4Region.hh"  // for G4Region
0038 #include "G4RegionStore.hh"  // for G4RegionStore
0039 #include "G4RunManager.hh"  // for G4RunManager
0040 #include "G4SDManager.hh"  // for G4SDManager
0041 #include "G4Tubs.hh"  // for G4Tubs
0042 #include "G4UnitsTable.hh"  // for operator<<, G4BestUnit
0043 #include "G4VisAttributes.hh"  // for G4VisAttributes
0044 
0045 #include <G4Colour.hh>  // for G4Colour
0046 #include <G4Exception.hh>  // for G4Exception
0047 #include <G4ExceptionSeverity.hh>  // for FatalException
0048 #include <G4SystemOfUnits.hh>  // for rad
0049 #include <G4ThreeVector.hh>  // for G4ThreeVector
0050 #include <G4VUserDetectorConstruction.hh>  // for G4VUserDetectorConstruction
0051 #include <G4ios.hh>  // for G4endl, G4cout
0052 #include <algorithm>  // for max
0053 #include <numeric>  // for accumulate
0054 #include <ostream>  // for operator<<, basic_ostream
0055 #include <string>  // for allocator, char_traits
0056 class G4VPhysicalVolume;
0057 #ifdef USE_INFERENCE
0058 #  include "Par04MLFastSimModel.hh"
0059 #endif
0060 
0061 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0062 
0063 Par04DetectorConstruction::Par04DetectorConstruction() : G4VUserDetectorConstruction()
0064 {
0065   fDetectorMessenger = new Par04DetectorMessenger(this);
0066   G4NistManager* nistManager = G4NistManager::Instance();
0067   fAbsorberMaterial[0] = nistManager->FindOrBuildMaterial("G4_PbWO4");
0068 }
0069 
0070 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0071 
0072 Par04DetectorConstruction::~Par04DetectorConstruction() = default;
0073 
0074 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0075 
0076 G4VPhysicalVolume* Par04DetectorConstruction::Construct()
0077 {
0078   //--------- Material definition ---------
0079   G4NistManager* nistManager = G4NistManager::Instance();
0080   G4Material* air = nistManager->FindOrBuildMaterial("G4_AIR");
0081 
0082   //--------- Derived dimensions ---------
0083   G4double full2Pi = 2. * CLHEP::pi * rad;
0084   G4double layerThickness =
0085     std::accumulate(fAbsorberThickness.begin(), fAbsorberThickness.end(), 0.);
0086   G4double detectorOuterRadius = fDetectorInnerRadius + fNbOfLayers * layerThickness;
0087   G4double worldSizeXY = detectorOuterRadius * 4.;
0088   G4double worldSizeZ = fDetectorLength * 2;
0089   // check number of materials: (1 = homogeneous calo, 2 = sampling calo)
0090   G4int nbOfMaterials = 0;
0091   for (const auto material : fAbsorberMaterial) {
0092     if (material != nullptr) nbOfMaterials++;
0093   }
0094 
0095   //--------- World ---------
0096   auto fSolidWorld = new G4Box("World",  // name
0097                                worldSizeXY / 2.,  // half-width in X
0098                                worldSizeXY / 2.,  // half-width in Y
0099                                worldSizeZ / 2.);  // half-width in Z
0100   auto fLogicWorld = new G4LogicalVolume(fSolidWorld,  // solid
0101                                          air,  // material
0102                                          "World");  // name
0103   auto fPhysicWorld = new G4PVPlacement(0,  // no rotation
0104                                         G4ThreeVector(),  // at (0,0,0)
0105                                         fLogicWorld,  // logical volume
0106                                         "World",  // name
0107                                         0,  // mother volume
0108                                         false,  // not used
0109                                         99999,  // copy number
0110                                         false);  // check overlaps
0111   fLogicWorld->SetVisAttributes(G4VisAttributes::GetInvisible());
0112 
0113   //--------- Detector envelope ---------
0114   auto fSolidDetector = new G4Tubs("Detector",  // name
0115                                    fDetectorInnerRadius,  // inner radius
0116                                    detectorOuterRadius,  // outer radius
0117                                    fDetectorLength / 2.,  // half-width in Z
0118                                    0,  // start angle
0119                                    full2Pi);  // delta angle
0120   auto fLogicDetector = new G4LogicalVolume(fSolidDetector,  // solid
0121                                             air,  // material
0122                                             "Detector");  // name
0123   new G4PVPlacement(0,  // no rotation
0124                     G4ThreeVector(0, 0, 0),  // detector centre at (0,0,0)
0125                     fLogicDetector,  // logical volume
0126                     "Detector",  // name
0127                     fLogicWorld,  // mother volume
0128                     false,  // not used
0129                     999,  // copy number
0130                     false);  // check overlaps
0131 
0132   // Region for fast simulation
0133   auto detectorRegion = new G4Region("DetectorRegion");
0134   detectorRegion->AddRootLogicalVolume(fLogicDetector);
0135 
0136   //--------- Detector layers: material ---------
0137   std::array<G4VisAttributes, 2> attribs;
0138   attribs[0].SetColour(G4Colour(0, 0, 1, 0.1));
0139   attribs[0].SetForceSolid(true);
0140   attribs[1].SetColour(G4Colour(1, 0, 0, 0.1));
0141   attribs[1].SetForceSolid(true);
0142   /// useful variable
0143   G4double innerRadius = fDetectorInnerRadius;
0144   for (G4int iLayer = 0; iLayer < fNbOfLayers; iLayer++) {
0145     for (G4int iMaterial = 0; iMaterial < nbOfMaterials; iMaterial++) {
0146       auto fSolidLayer = new G4Tubs("Layer",  // name
0147                                     innerRadius,  // inner radius
0148                                     innerRadius + fAbsorberThickness[iMaterial],  // outer radius
0149                                     fDetectorLength / 2.,  // half-width in Z
0150                                     0,  // start angle
0151                                     full2Pi);  // delta angle
0152       G4LogicalVolume* logical = new G4LogicalVolume(fSolidLayer,  // solid
0153                                                      fAbsorberMaterial[iMaterial],  // material
0154                                                      "Layer");  // name
0155       new G4PVPlacement(0,  // no rotation
0156                         G4ThreeVector(),  // place at centre of mother volume
0157                         logical,  // logical volume
0158                         "Layer",  // name
0159                         fLogicDetector,  // mother volume
0160                         false,  // not used
0161                         iLayer * nbOfMaterials + iMaterial,  // copy number
0162                         false);  // check overlaps
0163       logical->SetVisAttributes(attribs[iMaterial]);
0164       innerRadius += fAbsorberThickness[iMaterial];
0165       if (fAbsorberSensitivity[iMaterial]) {
0166         fLayerLogical.push_back(logical);
0167       }
0168     }
0169   }
0170 
0171   Print();
0172   return fPhysicWorld;
0173 }
0174 
0175 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0176 
0177 void Par04DetectorConstruction::ConstructSDandField()
0178 {
0179   Par04SensitiveDetector* caloSD =
0180     new Par04SensitiveDetector("sensitiveDetector", fMeshNbOfCells, fMeshSizeOfCells);
0181   G4SDManager::GetSDMpointer()->AddNewDetector(caloSD);
0182   for (const auto logical : fLayerLogical) {
0183     SetSensitiveDetector(logical, caloSD);
0184   }
0185 
0186   auto detectorRegion = G4RegionStore::GetInstance()->GetRegion("DetectorRegion");
0187   // Par04DefineMeshModel needs to be first model to call
0188   new Par04DefineMeshModel("defineMesh", detectorRegion);
0189 #ifdef USE_INFERENCE
0190   new Par04MLFastSimModel("inferenceModel", detectorRegion);
0191 #endif
0192 }
0193 
0194 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0195 
0196 void Par04DetectorConstruction::Print() const
0197 {
0198   G4cout << "\n------------------------------------------------------"
0199          << "\n--- Detector length:\t" << G4BestUnit(fDetectorLength, "Length")
0200          << "\n--- Detector inner radius:\t" << G4BestUnit(fDetectorInnerRadius, "Length")
0201          << "\n--- Number of layers:\t" << fNbOfLayers << G4endl << "\n--- 1st layer: \t"
0202          << G4BestUnit(fAbsorberThickness[0], "Length") << " of "
0203          << (fAbsorberSensitivity[0] ? "active " : "passive ") << fAbsorberMaterial[0]->GetName()
0204          << G4endl;
0205   if (fAbsorberMaterial[1] != nullptr)
0206     G4cout << "--- 2nd layer: \t" << G4BestUnit(fAbsorberThickness[1], "Length") << " of "
0207            << (fAbsorberSensitivity[1] ? "active " : "passive ") << fAbsorberMaterial[1]->GetName()
0208            << G4endl;
0209   G4cout << "-----------------------------------------------------" << G4endl;
0210 }
0211 
0212 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0213 
0214 void Par04DetectorConstruction::SetAbsorberMaterial(const std::size_t aLayer, const G4String& aName)
0215 {
0216   // search material by its name
0217   G4Material* material = G4NistManager::Instance()->FindOrBuildMaterial(aName);
0218   if (material)
0219     fAbsorberMaterial[aLayer] = material;
0220   else
0221     G4Exception("Par04DetectorConstruction::SetAbsorberMaterial()", "InvalidSetup", FatalException,
0222                 ("Unknown material name: " + aName).c_str());
0223   G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0224 }
0225 
0226 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0227 
0228 void Par04DetectorConstruction::SetAbsorberThickness(const std::size_t aLayer,
0229                                                      const G4double aThickness)
0230 {
0231   if (aLayer < fAbsorberThickness.size())
0232     fAbsorberThickness[aLayer] = aThickness;
0233   else
0234     G4Exception("Par04DetectorConstruction::SetAbsorberThickness()", "InvalidSetup", FatalException,
0235                 ("Requested layer " + std::to_string(aLayer)
0236                  + " is larger than number of available layers ("
0237                  + std::to_string(fAbsorberThickness.size()) + ").")
0238                   .c_str());
0239   G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0240 }
0241 
0242 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0243 
0244 void Par04DetectorConstruction::SetAbsorberSensitivity(const std::size_t aLayer,
0245                                                        const G4bool aSensitivity)
0246 {
0247   if (aLayer < fAbsorberSensitivity.size())
0248     fAbsorberSensitivity[aLayer] = aSensitivity;
0249   else
0250     G4Exception(
0251       "Par04DetectorConstruction::SetAbsorberSensitivity()", "InvalidSetup", FatalException,
0252       ("Requested layer " + std::to_string(aLayer) + " is larger than number of available layers ("
0253        + std::to_string(fAbsorberSensitivity.size()) + ").")
0254         .c_str());
0255   G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0256 }
0257 
0258 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0259 
0260 void Par04DetectorConstruction::SetInnerRadius(G4double aRadius)
0261 {
0262   fDetectorInnerRadius = aRadius;
0263 }
0264 
0265 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0266 
0267 void Par04DetectorConstruction::SetLength(G4double aLength)
0268 {
0269   fDetectorLength = aLength;
0270 }