Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-23 09:20:38

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