Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-08 07:52:48

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 B3::DetectorConstruction class
0028 
0029 #include "DetectorConstruction.hh"
0030 
0031 #include "G4Box.hh"
0032 #include "G4LogicalVolume.hh"
0033 #include "G4MultiFunctionalDetector.hh"
0034 #include "G4NistManager.hh"
0035 #include "G4PSDoseDeposit.hh"
0036 #include "G4PSEnergyDeposit.hh"
0037 #include "G4PVPlacement.hh"
0038 #include "G4PhysicalConstants.hh"
0039 #include "G4RotationMatrix.hh"
0040 #include "G4SDManager.hh"
0041 #include "G4SystemOfUnits.hh"
0042 #include "G4Transform3D.hh"
0043 #include "G4Tubs.hh"
0044 #include "G4VisAttributes.hh"
0045 
0046 namespace B3
0047 {
0048 
0049 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0050 
0051 DetectorConstruction::DetectorConstruction()
0052 {
0053   DefineMaterials();
0054 }
0055 
0056 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0057 
0058 void DetectorConstruction::DefineMaterials()
0059 {
0060   G4NistManager* man = G4NistManager::Instance();
0061 
0062   G4bool isotopes = false;
0063 
0064   G4Element* O = man->FindOrBuildElement("O", isotopes);
0065   G4Element* Si = man->FindOrBuildElement("Si", isotopes);
0066   G4Element* Lu = man->FindOrBuildElement("Lu", isotopes);
0067 
0068   auto LSO = new G4Material("Lu2SiO5", 7.4 * g / cm3, 3);
0069   LSO->AddElement(Lu, 2);
0070   LSO->AddElement(Si, 1);
0071   LSO->AddElement(O, 5);
0072 }
0073 
0074 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0075 
0076 G4VPhysicalVolume* DetectorConstruction::Construct()
0077 {
0078   // Gamma detector Parameters
0079   //
0080   G4double cryst_dX = 6 * cm, cryst_dY = 6 * cm, cryst_dZ = 3 * cm;
0081   G4int nb_cryst = 32;
0082   G4int nb_rings = 9;
0083   //
0084   G4double dPhi = twopi / nb_cryst, half_dPhi = 0.5 * dPhi;
0085   G4double cosdPhi = std::cos(half_dPhi);
0086   G4double tandPhi = std::tan(half_dPhi);
0087   //
0088   G4double ring_R1 = 0.5 * cryst_dY / tandPhi;
0089   G4double ring_R2 = (ring_R1 + cryst_dZ) / cosdPhi;
0090   //
0091   G4double detector_dZ = nb_rings * cryst_dX;
0092   //
0093   G4NistManager* nist = G4NistManager::Instance();
0094   G4Material* default_mat = nist->FindOrBuildMaterial("G4_AIR");
0095   G4Material* cryst_mat = nist->FindOrBuildMaterial("Lu2SiO5");
0096 
0097   //
0098   // World
0099   //
0100   G4double world_sizeXY = 2.4 * ring_R2;
0101   G4double world_sizeZ = 1.2 * detector_dZ;
0102 
0103   auto solidWorld =
0104     new G4Box("World",  // its name
0105               0.5 * world_sizeXY, 0.5 * world_sizeXY, 0.5 * world_sizeZ);  // its size
0106 
0107   auto logicWorld = new G4LogicalVolume(solidWorld,  // its solid
0108                                         default_mat,  // its material
0109                                         "World");  // its name
0110 
0111   auto physWorld = new G4PVPlacement(nullptr,  // no rotation
0112                                      G4ThreeVector(),  // at (0,0,0)
0113                                      logicWorld,  // its logical volume
0114                                      "World",  // its name
0115                                      nullptr,  // its mother  volume
0116                                      false,  // no boolean operation
0117                                      0,  // copy number
0118                                      fCheckOverlaps);  // checking overlaps
0119 
0120   //
0121   // ring
0122   //
0123   auto solidRing = new G4Tubs("Ring", ring_R1, ring_R2, 0.5 * cryst_dX, 0., twopi);
0124 
0125   auto logicRing = new G4LogicalVolume(solidRing,  // its solid
0126                                        default_mat,  // its material
0127                                        "Ring");  // its name
0128 
0129   //
0130   // define crystal
0131   //
0132   G4double gap = 0.5 * mm;  // a gap for wrapping
0133   G4double dX = cryst_dX - gap, dY = cryst_dY - gap;
0134   auto solidCryst = new G4Box("crystal", dX / 2, dY / 2, cryst_dZ / 2);
0135 
0136   auto logicCryst = new G4LogicalVolume(solidCryst,  // its solid
0137                                         cryst_mat,  // its material
0138                                         "CrystalLV");  // its name
0139 
0140   // place crystals within a ring
0141   //
0142   for (G4int icrys = 0; icrys < nb_cryst; icrys++) {
0143     G4double phi = icrys * dPhi;
0144     G4RotationMatrix rotm = G4RotationMatrix();
0145     rotm.rotateY(90 * deg);
0146     rotm.rotateZ(phi);
0147     G4ThreeVector uz = G4ThreeVector(std::cos(phi), std::sin(phi), 0.);
0148     G4ThreeVector position = (ring_R1 + 0.5 * cryst_dZ) * uz;
0149     G4Transform3D transform = G4Transform3D(rotm, position);
0150 
0151     new G4PVPlacement(transform,  // rotation,position
0152                       logicCryst,  // its logical volume
0153                       "crystal",  // its name
0154                       logicRing,  // its mother  volume
0155                       false,  // no boolean operation
0156                       icrys,  // copy number
0157                       fCheckOverlaps);  // checking overlaps
0158   }
0159 
0160   //
0161   // full detector
0162   //
0163   auto solidDetector = new G4Tubs("Detector", ring_R1, ring_R2, 0.5 * detector_dZ, 0., twopi);
0164 
0165   auto logicDetector = new G4LogicalVolume(solidDetector,  // its solid
0166                                            default_mat,  // its material
0167                                            "Detector");  // its name
0168 
0169   //
0170   // place rings within detector
0171   //
0172   G4double OG = -0.5 * (detector_dZ + cryst_dX);
0173   for (G4int iring = 0; iring < nb_rings; iring++) {
0174     OG += cryst_dX;
0175     new G4PVPlacement(nullptr,  // no rotation
0176                       G4ThreeVector(0, 0, OG),  // position
0177                       logicRing,  // its logical volume
0178                       "ring",  // its name
0179                       logicDetector,  // its mother  volume
0180                       false,  // no boolean operation
0181                       iring,  // copy number
0182                       fCheckOverlaps);  // checking overlaps
0183   }
0184 
0185   //
0186   // place detector in world
0187   //
0188   new G4PVPlacement(nullptr,  // no rotation
0189                     G4ThreeVector(),  // at (0,0,0)
0190                     logicDetector,  // its logical volume
0191                     "Detector",  // its name
0192                     logicWorld,  // its mother  volume
0193                     false,  // no boolean operation
0194                     0,  // copy number
0195                     fCheckOverlaps);  // checking overlaps
0196 
0197   //
0198   // patient
0199   //
0200   G4double patient_radius = 8 * cm;
0201   G4double patient_dZ = 10 * cm;
0202   G4Material* patient_mat = nist->FindOrBuildMaterial("G4_BRAIN_ICRP");
0203 
0204   auto solidPatient = new G4Tubs("Patient", 0., patient_radius, 0.5 * patient_dZ, 0., twopi);
0205 
0206   auto logicPatient = new G4LogicalVolume(solidPatient,  // its solid
0207                                           patient_mat,  // its material
0208                                           "PatientLV");  // its name
0209 
0210   //
0211   // place patient in world
0212   //
0213   new G4PVPlacement(nullptr,  // no rotation
0214                     G4ThreeVector(),  // at (0,0,0)
0215                     logicPatient,  // its logical volume
0216                     "Patient",  // its name
0217                     logicWorld,  // its mother  volume
0218                     false,  // no boolean operation
0219                     0,  // copy number
0220                     fCheckOverlaps);  // checking overlaps
0221 
0222   // Visualization attributes
0223   //
0224   logicRing->SetVisAttributes(G4VisAttributes::GetInvisible());
0225   logicDetector->SetVisAttributes(G4VisAttributes::GetInvisible());
0226 
0227   // Print materials
0228   G4cout << *(G4Material::GetMaterialTable()) << G4endl;
0229 
0230   // always return the physical World
0231   //
0232   return physWorld;
0233 }
0234 
0235 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0236 
0237 void DetectorConstruction::ConstructSDandField()
0238 {
0239   G4SDManager::GetSDMpointer()->SetVerboseLevel(1);
0240 
0241   // declare crystal as a MultiFunctionalDetector scorer
0242   //
0243   auto cryst = new G4MultiFunctionalDetector("crystal");
0244   G4SDManager::GetSDMpointer()->AddNewDetector(cryst);
0245   G4VPrimitiveScorer* primitiv1 = new G4PSEnergyDeposit("edep");
0246   cryst->RegisterPrimitive(primitiv1);
0247   SetSensitiveDetector("CrystalLV", cryst);
0248 
0249   // declare patient as a MultiFunctionalDetector scorer
0250   //
0251   auto patient = new G4MultiFunctionalDetector("patient");
0252   G4SDManager::GetSDMpointer()->AddNewDetector(patient);
0253   G4VPrimitiveScorer* primitiv2 = new G4PSDoseDeposit("dose");
0254   patient->RegisterPrimitive(primitiv2);
0255   SetSensitiveDetector("PatientLV", patient);
0256 }
0257 
0258 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0259 
0260 }  // namespace B3