Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-18 07:42:19

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 "G4Box.hh"
0032 #include "G4Exception.hh"
0033 #include "G4GeometryManager.hh"
0034 #include "G4Material.hh"
0035 #include "G4NistManager.hh"
0036 #include "G4PVPlacement.hh"
0037 #include "G4Region.hh"
0038 #include "G4RunManager.hh"
0039 #include "G4SDManager.hh"
0040 #include "G4StateManager.hh"
0041 #include "G4SystemOfUnits.hh"
0042 #include "globals.hh"
0043 
0044 #include "DetectorMessenger.hh"
0045 #include "TrackerSD.hh"
0046 
0047 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0048 
0049 DetectorConstruction::DetectorConstruction() : G4VUserDetectorConstruction()
0050 {
0051   // Create commands for interactive definition of the detector
0052   fDetectorMessenger = std::make_unique<DetectorMessenger>(this);
0053 }
0054 
0055 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0056 
0057 DetectorConstruction::~DetectorConstruction() = default;
0058 
0059 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0060 
0061 G4VPhysicalVolume* DetectorConstruction::Construct()
0062 {
0063   // Define the materials
0064   DefineMaterials();
0065 
0066   // Define volumes
0067   G4VPhysicalVolume* World = DefineWorld();
0068   DefineSD(World);  // SD is placed inside the world volume
0069   return World;
0070 }
0071 
0072 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0073 
0074 void DetectorConstruction::DefineMaterials()
0075 {
0076   // Taking water from the NIST database
0077   G4NistManager* nist = G4NistManager::Instance();
0078   if (!fMat) {
0079     fMat = nist->FindOrBuildMaterial("G4_WATER");
0080   }
0081 
0082   // Print the material information
0083   G4cout << "Material: " << fMat->GetName() << G4endl;
0084   G4cout << *(G4Material::GetMaterialTable()) << G4endl;
0085 }
0086 
0087 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0088 
0089 void DetectorConstruction::CheckConsistency()
0090 {
0091   if (!(fMaxRange > 0.)) {
0092     G4ExceptionDescription msg;
0093     msg << "fMaxRange must be > 0.\n"
0094         << "Please consider using the formula by Tabata for the calculation "
0095         << "of the maximum range of secondary electrons:\n"
0096         << "\t https://doi.org/10.1016/0029-554X(72)90463-6" << G4endl
0097         << "Note: This parameter affects the world volume size only along "
0098         << "the z-axis.\n"
0099         << "Sizes along x- and y-axes are set by fHitSelRegXY and the "
0100         << "site radius." << G4endl;
0101     G4Exception("DetectorConstruction::CheckConsistency()", "DetCons0001",
0102                 FatalException, msg);
0103   }
0104   if (!(fHitSelRegZ > 0.)) {
0105     G4ExceptionDescription msg;
0106     msg << "fHitSelRegZ must be > 0.\n"
0107         << "Otherwise, no hits are eligible to set randomly the site "
0108         << "position using the weighted method.\n"
0109         << G4endl;
0110     G4Exception("DetectorConstruction::CheckConsistency()", "DetCons0002",
0111                 FatalException, msg);
0112   }
0113   if (!(fHitSelRegXY > 0.)) {
0114     G4ExceptionDescription msg;
0115     msg << "fHitSelRegXY must be > 0.\n"
0116         << "Otherwise, no hits are eligible to set randomly the site "
0117         << "position using the weighted method." << G4endl
0118         << "Note: This parameter, together with the site radius, sets the "
0119         << "world volume size along the xy-axes." << G4endl;
0120     G4Exception("DetectorConstruction::CheckConsistency()", "DetCons0003",
0121                 FatalException, msg);
0122   }
0123 }
0124 
0125 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0126 
0127 G4VPhysicalVolume* DetectorConstruction::DefineWorld()
0128 {
0129   // Ensure geometry consistency
0130   CheckConsistency();
0131 
0132   // Define the world volume
0133 
0134   G4double WorldZ = fHitSelRegZ + 4. * fSiteRadius + 2. * fMaxRange;
0135   G4double WorldXY = fHitSelRegXY + 4. * fSiteRadius;
0136 
0137   auto* sWorld = new G4Box("World", WorldXY / 2., WorldXY / 2., WorldZ / 2.);
0138   auto* lWorld = new G4LogicalVolume(sWorld, fMat, "World", 0, 0, 0);
0139   G4VPhysicalVolume* World =
0140     new G4PVPlacement(0, G4ThreeVector(), lWorld, "World", nullptr, false, 0);
0141 
0142   // Print the world volume information
0143   PrintParameters(World);
0144 
0145   return World;
0146 }
0147 
0148 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0149 
0150 G4VPhysicalVolume*
0151 DetectorConstruction::DefineSD(G4VPhysicalVolume* mother) const
0152 {
0153   // Define the sensitive detector volume
0154 
0155   G4double SensDetZ = fHitSelRegZ + 4. * fSiteRadius;
0156   G4double SensDetXY = fHitSelRegXY + 4. * fSiteRadius;
0157 
0158   auto* sSDbox =
0159     new G4Box("SDbox", SensDetXY / 2., SensDetXY / 2., SensDetZ / 2.);
0160   auto* lSDbox = new G4LogicalVolume(sSDbox, fMat, "SDbox", 0, 0, 0);
0161   G4VPhysicalVolume* SDbox = new G4PVPlacement(
0162     0, G4ThreeVector(), lSDbox, "SDbox", mother->GetLogicalVolume(), false, 0);
0163   // Print the sensitive detector volume information
0164   PrintParameters(SDbox);
0165 
0166   return SDbox;
0167 }
0168 
0169 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0170 
0171 void DetectorConstruction::ConstructSDandField()
0172 {
0173   // Sensitive Detector
0174   G4String SDname = "SDbox";
0175 
0176   auto* aSD = new TrackerSD(SDname, "TrackerHitColl");
0177 
0178   // Register the SD with the SD manager
0179   G4SDManager* SDMan = G4SDManager::GetSDMpointer();
0180   SDMan->AddNewDetector(aSD);
0181 
0182   // Set the SD to the logical volume
0183   SetSensitiveDetector("SDbox", aSD, true);
0184 }
0185 
0186 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0187 
0188 void DetectorConstruction::SetMaterial(const G4String& name)
0189 {
0190   auto* nist = G4NistManager::Instance();
0191 
0192   G4Material* mat = nist->FindOrBuildMaterial(name);
0193 
0194   if (!mat) {
0195     G4ExceptionDescription ed;
0196     ed << "Material '" << name << "' not found. Falling back to G4_WATER.";
0197     G4Exception("DetectorConstruction::SetMaterial", "MTK001", JustWarning, ed);
0198     mat = nist->FindOrBuildMaterial("G4_WATER");
0199   }
0200 
0201   if (fMat != mat) {
0202     fMat = mat;
0203   }
0204 }
0205 
0206 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0207 
0208 void DetectorConstruction::PrintParameters(G4VPhysicalVolume* physVol) const
0209 {
0210   if (!physVol) {
0211     G4cerr << "Error: Physical volume is null!" << G4endl;
0212     return;
0213   }
0214 
0215   G4ThreeVector pos = physVol->GetObjectTranslation();
0216   G4LogicalVolume* logVol = physVol->GetLogicalVolume();
0217   G4VSolid* solid = logVol->GetSolid();
0218   G4Material* material = logVol->GetMaterial();
0219 
0220   G4cout << "\n================ Volume Parameters ================" << G4endl;
0221   G4cout << "Physical Volume Name: " << physVol->GetName() << G4endl;
0222   G4cout << "Position: " << pos / mm << " mm" << G4endl;
0223   G4cout << "Material: " << material->GetName() << G4endl;
0224 
0225   // Detect shape and print dimensions accordingly
0226   if (auto box = dynamic_cast<G4Box*>(solid)) {
0227     G4cout << "Shape: Box" << G4endl;
0228     G4cout << "Dimensions (full): " << 2 * box->GetXHalfLength() / mm << " x "
0229            << 2 * box->GetYHalfLength() / mm << " x "
0230            << 2 * box->GetZHalfLength() / mm << " mm" << G4endl;
0231   }
0232   else {
0233     G4cout << "Shape: Unknown or not handled yet." << G4endl;
0234   }
0235 
0236   G4cout << "===================================================\n" << G4endl;
0237 }
0238 
0239 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......