Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-03-31 07:50:49

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 Par03DetectorConstruction.cc
0027 /// \brief Implementation of the Par03DetectorConstruction class
0028 
0029 #include "Par03DetectorConstruction.hh"
0030 
0031 #include "Par03DetectorMessenger.hh"
0032 #include "Par03EMShowerModel.hh"
0033 #include "Par03SensitiveDetector.hh"
0034 
0035 #include "G4Box.hh"
0036 #include "G4LogicalVolume.hh"
0037 #include "G4Material.hh"
0038 #include "G4NistManager.hh"
0039 #include "G4PVPlacement.hh"
0040 #include "G4PVReplica.hh"
0041 #include "G4Region.hh"
0042 #include "G4RegionStore.hh"
0043 #include "G4RunManager.hh"
0044 #include "G4SDManager.hh"
0045 #include "G4Tubs.hh"
0046 #include "G4UnitsTable.hh"
0047 #include "G4VisAttributes.hh"
0048 
0049 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0050 
0051 Par03DetectorConstruction::Par03DetectorConstruction() : G4VUserDetectorConstruction()
0052 {
0053   fDetectorMessenger = new Par03DetectorMessenger(this);
0054 
0055   G4NistManager* nistManager = G4NistManager::Instance();
0056   fDetectorMaterial = nistManager->FindOrBuildMaterial("G4_Fe");
0057 }
0058 
0059 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0060 
0061 Par03DetectorConstruction::~Par03DetectorConstruction() = default;
0062 
0063 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0064 
0065 G4VPhysicalVolume* Par03DetectorConstruction::Construct()
0066 {
0067   //--------- Material definition ---------
0068   G4NistManager* nistManager = G4NistManager::Instance();
0069   G4Material* air = nistManager->FindOrBuildMaterial("G4_AIR");
0070 
0071   //--------- Derived dimensions ---------
0072   G4double full2Pi = 2. * CLHEP::pi * rad;
0073   G4double layerThickness = fDetectorLength / fNbOfLayers;
0074   G4double cellPhi = full2Pi / fNbOfPhiCells;
0075   G4double cellDR = fDetectorRadius / fNbOfRhoCells;
0076 
0077   //--------- World ---------
0078   auto fSolidWorld = new G4Box("World",  // name
0079                                fWorldSize / 2.,  // half-width in X
0080                                fWorldSize / 2.,  // half-width in Y
0081                                fWorldSize / 2.);  // half-width in Z
0082   auto fLogicWorld = new G4LogicalVolume(fSolidWorld,  // solid
0083                                          air,  // material
0084                                          "World");  // name
0085   auto fPhysicWorld = new G4PVPlacement(0,  // no rotation
0086                                         G4ThreeVector(),  // at (0,0,0)
0087                                         fLogicWorld,  // logical volume
0088                                         "World",  // name
0089                                         0,  // mother volume
0090                                         false,  // not used
0091                                         999,  // copy number
0092                                         true);  // copy number
0093 
0094   //--------- Detector envelope ---------
0095   auto fSolidDetector = new G4Tubs("Detector",  // name
0096                                    0,  // inner radius
0097                                    fDetectorRadius,  // outer radius
0098                                    fDetectorLength / 2.,  // half-width in Z
0099                                    0,  // start angle
0100                                    full2Pi);  // delta angle
0101   auto fLogicDetector = new G4LogicalVolume(fSolidDetector,  // solid
0102                                             fDetectorMaterial,  // material
0103                                             "Detector");  // name
0104   new G4PVPlacement(0,  // no rotation
0105                     G4ThreeVector(0, 0,
0106                                   fDetectorLength / 2),  // detector face starts at (0,0,0)
0107                     fLogicDetector,  // logical volume
0108                     "Detector",  // name
0109                     fLogicWorld,  // mother volume
0110                     false,  // not used
0111                     99,  // copy number
0112                     true);  // check overlaps
0113 
0114   // Region for fast simulation
0115   auto detectorRegion = new G4Region("DetectorRegion");
0116   detectorRegion->AddRootLogicalVolume(fLogicDetector);
0117 
0118   //--------- Readout geometry ---------
0119   // Layers (along z)
0120   auto fSolidLayer = new G4Tubs("Layer",  // name
0121                                 0,  // inner radius
0122                                 fDetectorRadius,  // outer radius
0123                                 layerThickness / 2.,  // half-width in Z
0124                                 0,  // start angle
0125                                 full2Pi);  // delta angle
0126   auto fLogicLayer = new G4LogicalVolume(fSolidLayer,  // solid
0127                                          air,  // material
0128                                          "Layer");  // name
0129   if (fNbOfLayers > 1)
0130     new G4PVReplica("Layer",  // name
0131                     fLogicLayer,  // logical volume
0132                     fLogicDetector,  // mother volume
0133                     kZAxis,  // axis of replication
0134                     fNbOfLayers,  // number of replicas
0135                     layerThickness);  // width of single replica
0136   else
0137     new G4PVPlacement(0,  // no rotation
0138                       G4ThreeVector(),  // place at centre of mother volume
0139                       fLogicLayer,  // logical volume
0140                       "Layer",  // name
0141                       fLogicDetector,  // mother volume
0142                       false,  // not used
0143                       0,  // copy number
0144                       true);  // check overlaps
0145 
0146   // Layer segment (division in phi)
0147   auto fSolidRow = new G4Tubs("Row",  // name
0148                               0,  // inner radius
0149                               fDetectorRadius,  // outer radius
0150                               layerThickness / 2.,  // half-width in Z
0151                               0,  // start angle
0152                               cellPhi);  // delta angle
0153 
0154   auto fLogicRow = new G4LogicalVolume(fSolidRow,  // solid
0155                                        air,  // material
0156                                        "Segment");  // name
0157   if (fNbOfPhiCells > 1)
0158     new G4PVReplica("Segment",  // name
0159                     fLogicRow,  // logical volume
0160                     fLogicLayer,  // mother volume
0161                     kPhi,  // axis of replication
0162                     fNbOfPhiCells,  // number of replicas
0163                     cellPhi);  // width of single replica
0164   else
0165     new G4PVPlacement(0,  // no rotation
0166                       G4ThreeVector(),  // place at centre of mother volume
0167                       fLogicRow,  // logical volume
0168                       "Row",  // name
0169                       fLogicLayer,  // mother volume
0170                       false,  // not used
0171                       0,  // copy number
0172                       true);  // check overlaps
0173 
0174   // Final cells (segment slices in radius)
0175   // No volume can be placed inside a radial replication
0176   auto fSolidCell = new G4Tubs("Cell",  // name
0177                                0,  // inner radius
0178                                cellDR,  // outer radius
0179                                layerThickness / 2.,  // half-width in Z
0180                                0,  // start angle
0181                                cellPhi);  // delta angle
0182 
0183   fLogicCell = new G4LogicalVolume(fSolidCell,  // solid
0184                                    fDetectorMaterial,  // material
0185                                    "Cell");  // name
0186   if (fNbOfRhoCells > 1)
0187     new G4PVReplica("Cell",  // name
0188                     fLogicCell,  // logical volume
0189                     fLogicRow,  // mother volume
0190                     kRho,  // axis of replication
0191                     fNbOfRhoCells,  // number of replicas
0192                     cellDR);  // width of single replica
0193   else
0194     new G4PVPlacement(0,  // no rotation
0195                       G4ThreeVector(),  // place at centre of mother volume
0196                       fLogicCell,  // logical volume
0197                       "Cell",  // name
0198                       fLogicRow,  // mother volume
0199                       false,  // not used
0200                       0,  // copy number
0201                       true);  // check overlaps
0202 
0203   //--------- Visualisation settings ---------
0204   fLogicWorld->SetVisAttributes(G4VisAttributes::GetInvisible());
0205   fLogicLayer->SetVisAttributes(G4VisAttributes::GetInvisible());
0206   fLogicRow->SetVisAttributes(G4VisAttributes::GetInvisible());
0207   G4VisAttributes attribs;
0208   attribs.SetColour(G4Colour(0, 0, 1, 0.3));
0209   attribs.SetForceSolid(true);
0210   fLogicCell->SetVisAttributes(attribs);
0211 
0212   Print();
0213   return fPhysicWorld;
0214 }
0215 
0216 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0217 
0218 void Par03DetectorConstruction::ConstructSDandField()
0219 {
0220   Par03SensitiveDetector* caloSD =
0221     new Par03SensitiveDetector("sensitiveDetector", fNbOfLayers, fNbOfPhiCells, fNbOfRhoCells);
0222   G4SDManager::GetSDMpointer()->AddNewDetector(caloSD);
0223   SetSensitiveDetector(fLogicCell, caloSD);
0224 
0225   auto detectorRegion = G4RegionStore::GetInstance()->GetRegion("DetectorRegion");
0226   new Par03EMShowerModel("model", detectorRegion);
0227 }
0228 
0229 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0230 
0231 void Par03DetectorConstruction::Print() const
0232 {
0233   G4cout << "\n------------------------------------------------------"
0234          << "\n--- Detector material:\t" << fDetectorMaterial->GetName()
0235          << "\n--- Detector length:\t" << G4BestUnit(fDetectorLength, "Length")
0236          << "\n--- Detector radius:\t" << G4BestUnit(fDetectorRadius, "Length")
0237          << "\n--- Number of layers:\t" << fNbOfLayers << "\n--- Number of R-cells:\t"
0238          << fNbOfRhoCells << "\n--- Number of phi-cells:\t" << fNbOfPhiCells << G4endl;
0239   G4cout << "-----------------------------------------------------" << G4endl;
0240 }
0241 
0242 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0243 
0244 void Par03DetectorConstruction::SetMaterial(const G4String& aName)
0245 {
0246   // search material by its name
0247   G4Material* material = G4NistManager::Instance()->FindOrBuildMaterial(aName);
0248   if (material)
0249     fDetectorMaterial = material;
0250   else
0251     G4Exception("Par03DetectorConstruction::SetMaterial()", "InvalidSetup", FatalException,
0252                 ("Unknown material name: " + aName).c_str());
0253   G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0254 }
0255 
0256 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0257 
0258 void Par03DetectorConstruction::SetRadius(G4double aRadius)
0259 {
0260   // check if fits within world volume
0261   if (aRadius >= fWorldSize / 2.)
0262     G4Exception("Par03DetectorConstruction::SetRadius()", "InvalidSetup", FatalException,
0263                 ("Detector radius cannot be larger than the world size ("
0264                  + G4String(G4BestUnit(fWorldSize / 2., "Length")) + ")")
0265                   .c_str());
0266   fDetectorRadius = aRadius;
0267 }
0268 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0269 
0270 void Par03DetectorConstruction::SetLength(G4double aLength)
0271 {
0272   // check if fits within world volume
0273   if (aLength >= fWorldSize / 2.)
0274     G4Exception("Par03DetectorConstruction::SetLength()", "InvalidSetup", FatalException,
0275                 ("Detector length cannot be larger than the world size ("
0276                  + G4String(G4BestUnit(fWorldSize / 2., "Length")) + ")")
0277                   .c_str());
0278   fDetectorLength = aLength;
0279 }