Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-21 08:30:08

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 // -------------------------------------------------------------
0030 //      GEANT4 ibrem test
0031 //
0032 // Authors: V.Grichine, V.Ivanchenko
0033 //
0034 // Modified:
0035 //
0036 // 18-02-03 V.Ivanchenko create
0037 //
0038 // -------------------------------------------------------------
0039 
0040 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0041 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0042 
0043 #include "DetectorConstruction.hh"
0044 
0045 #include "CheckVolumeSD.hh"
0046 #include "DetectorMessenger.hh"
0047 #include "PhantomSD.hh"
0048 #include "TargetSD.hh"
0049 
0050 #include "G4Box.hh"
0051 #include "G4Colour.hh"
0052 #include "G4GeometryManager.hh"
0053 #include "G4LogicalVolume.hh"
0054 #include "G4LogicalVolumeStore.hh"
0055 #include "G4Material.hh"
0056 #include "G4NistManager.hh"
0057 #include "G4PVPlacement.hh"
0058 #include "G4PhysicalConstants.hh"
0059 #include "G4PhysicalVolumeStore.hh"
0060 #include "G4RunManager.hh"
0061 #include "G4SDManager.hh"
0062 #include "G4SolidStore.hh"
0063 #include "G4SystemOfUnits.hh"
0064 #include "G4Tubs.hh"
0065 #include "G4VPhysicalVolume.hh"
0066 #include "G4VisAttributes.hh"
0067 #include "G4ios.hh"
0068 #include "globals.hh"
0069 
0070 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0071 
0072 DetectorConstruction::DetectorConstruction()
0073 {
0074   fLogicTarget1 = 0;
0075   fLogicTarget2 = 0;
0076 
0077   fMessenger = new DetectorMessenger(this);
0078   fVerbose = false;
0079 
0080   fNumZ = 60;
0081   fNumR = 80;
0082 
0083   fNumE = 200;
0084   fMaxEnergy = 50.0 * MeV;
0085 
0086   fDistanceVacuumTarget = 30. * mm,
0087 
0088   fDelta = 0.001 * mm;
0089 
0090   fTargetRadius = 100. * mm;
0091   fTarget1Z = 9. * mm;
0092   fTarget2Z = 6. * mm;
0093 
0094   fGasVolumeRadius = 210. * mm;
0095   fGasVolumeZ = 690. * mm;
0096   fMylarVolumeZ = 0.02 * mm;
0097 
0098   fCheckVolumeZ = 0.1 * mm;
0099   fCheckShiftZ = 200. * mm;
0100 
0101   fAbsorberRadius = 200. * mm;
0102   fPhantomRadius = 300. * mm;
0103   fPhantomZ = 300. * mm;
0104 
0105   fAirZ = 210. * mm;
0106   fAbsorberShiftZ = 70. * mm;
0107   fWindowZ = 0.05 * mm;
0108 
0109   G4NistManager* man = G4NistManager::Instance();
0110   // man->SetVerbose(1);
0111 
0112   fTarget1Material = man->FindOrBuildMaterial("G4_Be");
0113   fWindowMaterial = fTarget1Material;
0114   fTarget2Material = man->FindOrBuildMaterial("G4_W");
0115   fLightMaterial = man->FindOrBuildMaterial("G4_He");
0116   fAbsorberMaterial = man->FindOrBuildMaterial("G4_WATER");
0117   fWorldMaterial = man->FindOrBuildMaterial("G4_AIR");
0118   fMylar = man->FindOrBuildMaterial("G4_MYLAR");
0119 
0120   G4cout << *(G4Material::GetMaterialTable()) << G4endl;
0121 }
0122 
0123 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0124 
0125 DetectorConstruction::~DetectorConstruction()
0126 {
0127   delete fMessenger;
0128 }
0129 
0130 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0131 
0132 void DetectorConstruction::InitialiseGeometryParameters()
0133 {
0134   // Volumee sizes
0135 
0136   G4double factor = 1.2;
0137 
0138   fWorldXY = factor * std::max(fPhantomRadius, fGasVolumeRadius);
0139   fAbsorberZ = fPhantomZ / fNumZ;
0140   fGasVolumeZ = 1000. * mm - fAbsorberShiftZ - fAirZ - fTarget1Z - fTarget2Z;
0141 
0142   G4double ztot = fGasVolumeZ + fAirZ + fPhantomZ + fDistanceVacuumTarget;
0143   fTargetVolumeZ = fDistanceVacuumTarget + fTarget2Z + fTarget1Z + fDelta;
0144   fWorldZ = factor * ztot * 0.5;
0145 
0146   if (fCheckShiftZ < fDelta) {
0147     fCheckShiftZ = fDelta;
0148   }
0149   if (fCheckShiftZ > fAirZ - fCheckVolumeZ - fDelta) {
0150     fCheckShiftZ = fAirZ - fCheckVolumeZ - fDelta;
0151   }
0152 
0153   // Z position of volumes from upstream to downstream
0154 
0155   fWindowPosZ = -(ztot + fWindowZ) * 0.5;
0156   fGeneratorPosZ = fWindowPosZ - 0.5 * fWindowZ - fDelta;
0157 
0158   fTargetVolumePosZ = -0.5 * (ztot - fTargetVolumeZ);
0159   fTarget1PosZ = -0.5 * (fTargetVolumeZ - fTarget1Z) + fDistanceVacuumTarget;
0160   fTarget2PosZ = fTarget1PosZ + 0.5 * (fTarget2Z + fTarget1Z);
0161 
0162   fGasVolumePosZ = fTargetVolumePosZ + 0.5 * (fTargetVolumeZ + fGasVolumeZ);
0163   fCheckVolumePosZ = fGasVolumePosZ + 0.5 * (fGasVolumeZ + fCheckVolumeZ) + fCheckShiftZ;
0164   fMylarPosZ = fGasVolumePosZ + 0.5 * (fGasVolumeZ + fMylarVolumeZ) + fDelta;
0165 
0166   fPhantomPosZ = fGasVolumePosZ + 0.5 * (fGasVolumeZ + fPhantomZ) + fAirZ;
0167   fAbsorberPosZ = fAbsorberShiftZ - 0.5 * (fPhantomZ - fAbsorberZ);
0168 
0169   fShiftZPh = fPhantomPosZ - 0.5 * fPhantomZ;
0170 
0171   DumpGeometryParameters();
0172 }
0173 
0174 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0175 
0176 G4VPhysicalVolume* DetectorConstruction::Construct()
0177 {
0178   InitialiseGeometryParameters();
0179 
0180   G4GeometryManager::GetInstance()->OpenGeometry();
0181   G4PhysicalVolumeStore::GetInstance()->Clean();
0182   G4LogicalVolumeStore::GetInstance()->Clean();
0183   G4SolidStore::GetInstance()->Clean();
0184   //
0185   // World
0186   //
0187 
0188   G4Box* solidWorld = new G4Box("World", fWorldXY, fWorldXY, fWorldZ);
0189   G4LogicalVolume* logicWorld = new G4LogicalVolume(solidWorld, fWorldMaterial, "World");
0190   G4VPhysicalVolume* physWorld =
0191     new G4PVPlacement(0, G4ThreeVector(), "World", logicWorld, 0, false, 0);
0192 
0193   // Be Vacuum window
0194   G4Tubs* solidWin = new G4Tubs("Window", 0., fTargetRadius * 0.25, 0.5 * fWindowZ, 0., twopi);
0195   G4LogicalVolume* logicWin = new G4LogicalVolume(solidWin, fWindowMaterial, "Window");
0196   new G4PVPlacement(0, G4ThreeVector(0., 0., fWindowPosZ), "Window", logicWin, physWorld, false, 0);
0197 
0198   // Target Volume
0199   G4Tubs* solidTGVolume =
0200     new G4Tubs("TargetVolume", 0., fTargetRadius, 0.5 * fTargetVolumeZ, 0., twopi);
0201   G4LogicalVolume* logicTGVolume =
0202     new G4LogicalVolume(solidTGVolume, fLightMaterial, "TargetVolume");
0203   new G4PVPlacement(0, G4ThreeVector(0., 0., fTargetVolumePosZ), logicTGVolume, "TargetVolume",
0204                     logicWorld, false, 0);
0205 
0206   // Target 1
0207   G4Tubs* solidTarget1 = new G4Tubs("Target1", 0., fTargetRadius * 0.5, 0.5 * fTarget1Z, 0., twopi);
0208   fLogicTarget1 = new G4LogicalVolume(solidTarget1, fTarget1Material, "Target1");
0209   fTarget1 = new G4PVPlacement(0, G4ThreeVector(0., 0., fTarget1PosZ), fLogicTarget1, "Target1",
0210                                logicTGVolume, false, 0);
0211   //  fLogicTarget1->SetSensitiveDetector(fTargetSD);
0212 
0213   // Target 2 (for combined targets)
0214   G4Tubs* solidTarget2 = new G4Tubs("Target2", 0., fTargetRadius * 0.5, 0.5 * fTarget2Z, 0., twopi);
0215   fLogicTarget2 = new G4LogicalVolume(solidTarget2, fTarget2Material, "Target2");
0216   fTarget2 = new G4PVPlacement(0, G4ThreeVector(0., 0., fTarget2PosZ), fLogicTarget2, "Target2",
0217                                logicTGVolume, false, 0);
0218 
0219   //  fLogicTarget2->SetSensitiveDetector(fTargetSD);
0220 
0221   // Gas Volume
0222   G4Tubs* solidGasVolume =
0223     new G4Tubs("GasVolume", 0., fGasVolumeRadius, 0.5 * fGasVolumeZ, 0., twopi);
0224   G4LogicalVolume* logicGasVolume =
0225     new G4LogicalVolume(solidGasVolume, fLightMaterial, "GasVolume");
0226   fGasVolume = new G4PVPlacement(0, G4ThreeVector(0., 0., fGasVolumePosZ), "GasVolume",
0227                                  logicGasVolume, physWorld, false, 0);
0228 
0229   // Mylar window
0230   G4Tubs* sMylarVolume = new G4Tubs("Mylar", 0., fGasVolumeRadius, 0.5 * fMylarVolumeZ, 0., twopi);
0231   G4LogicalVolume* lMylarVolume = new G4LogicalVolume(sMylarVolume, fMylar, "Mylar");
0232   new G4PVPlacement(0, G4ThreeVector(0., 0., fMylarPosZ), "Mylar", lMylarVolume, physWorld, false,
0233                     0);
0234 
0235   // Check Volume
0236   G4Tubs* solidCheckVolume =
0237     new G4Tubs("CheckVolume", 0., fGasVolumeRadius, 0.5 * fCheckVolumeZ, 0., twopi);
0238   fLogicCheckVolume = new G4LogicalVolume(solidCheckVolume, fWorldMaterial, "CheckVolume");
0239   fCheckVolume = new G4PVPlacement(0, G4ThreeVector(0., 0., fCheckVolumePosZ), "CheckVolume",
0240                                    fLogicCheckVolume, physWorld, false, 0);
0241   //  logicCheckVolume->SetSensitiveDetector(fCheckSD);
0242 
0243   // Phantom
0244   G4Box* solidPhantom = new G4Box("Phantom", fPhantomRadius, fPhantomRadius, 0.5 * fPhantomZ);
0245   G4LogicalVolume* logicPhantom = new G4LogicalVolume(solidPhantom, fAbsorberMaterial, "Phantom");
0246   G4VPhysicalVolume* physPhantom = new G4PVPlacement(0, G4ThreeVector(0., 0., fPhantomPosZ),
0247                                                      "Phantom", logicPhantom, physWorld, false, 0);
0248 
0249   G4Tubs* solidPh = new G4Tubs("PhantomSD", 0., fAbsorberRadius, 0.5 * fPhantomZ, 0., twopi);
0250   fLogicPh = new G4LogicalVolume(solidPh, fAbsorberMaterial, "PhantomSD");
0251   fPhantom =
0252     new G4PVPlacement(0, G4ThreeVector(0., 0., 0.), "Phantom", fLogicPh, physPhantom, false, 0);
0253   G4cout << "Phantom R= " << fAbsorberRadius << " dz= " << 0.5 * fPhantomZ << G4endl;
0254 
0255   // Sensitive Absorber
0256   G4double absWidth = 0.5 * fAbsorberZ;
0257   G4Tubs* solidAbsorber = new G4Tubs("Absorber", 0., fAbsorberRadius, absWidth, 0., twopi);
0258   fLogicAbsorber = new G4LogicalVolume(solidAbsorber, fAbsorberMaterial, "Absorber");
0259   G4cout << "Absorber R= " << fAbsorberRadius << " dz= " << absWidth << " posZ= " << fAbsorberPosZ
0260          << G4endl;
0261 
0262   new G4PVPlacement(0, G4ThreeVector(0., 0., fAbsorberPosZ), "Absorber", fLogicAbsorber, fPhantom,
0263                     false, 0);
0264 
0265   G4double stepR = fAbsorberRadius / (G4double)fNumR;
0266 
0267   G4double r1 = 0.0;
0268   G4double r2 = 0.0;
0269   G4Tubs* solidRing;
0270 
0271   G4VisAttributes* VisAtt_ring = new G4VisAttributes(G4VisAttributes::GetInvisible());
0272   for (G4int k = 0; k < fNumR; k++) {
0273     r2 = r1 + stepR;
0274     if (k == fNumR - 1) r2 = fAbsorberRadius;
0275     //    G4cout << "New ring r1= " << r1 << " r2= " << r2
0276     //  << " dz= " << absWidth << G4endl;
0277     solidRing = new G4Tubs("Ring", r1, r2, absWidth, 0., twopi);
0278     G4LogicalVolume* logicRing = new G4LogicalVolume(solidRing, fAbsorberMaterial, "Ring");
0279     //    logicRing->SetSensitiveDetector(fPhantomSD);
0280     logicRing->SetVisAttributes(VisAtt_ring);
0281     fLogicRing.push_back(logicRing);
0282     new G4PVPlacement(0, G4ThreeVector(0., 0., 0.), logicRing, "Ring", fLogicAbsorber, false, k);
0283     r1 = r2;
0284   }
0285 
0286   //
0287   // Visualization attributes
0288   //
0289   G4VisAttributes* VisAtt = 0;
0290   VisAtt = new G4VisAttributes(G4Colour(1.0, 1.0, 1.0));
0291   VisAtt->SetVisibility(true);
0292   fLogicAbsorber->SetVisAttributes(VisAtt);
0293 
0294   VisAtt = new G4VisAttributes(G4Colour(1.0, 1.0, 2.0));
0295   VisAtt->SetVisibility(true);
0296   logicPhantom->SetVisAttributes(VisAtt);
0297 
0298   VisAtt = new G4VisAttributes(G4Colour(1.0, 0.0, 2.0));
0299   VisAtt->SetVisibility(true);
0300   fLogicPh->SetVisAttributes(VisAtt);
0301 
0302   VisAtt = new G4VisAttributes(G4Colour(1.0, 1.0, 0.0));
0303   VisAtt->SetVisibility(true);
0304   fLogicAbsorber->SetVisAttributes(VisAtt);
0305 
0306   VisAtt = new G4VisAttributes(G4Colour(0.1, 1.0, 2.0));
0307   VisAtt->SetVisibility(true);
0308   logicWorld->SetVisAttributes(VisAtt);
0309 
0310   VisAtt = new G4VisAttributes(G4Colour(1.0, 1.0, 0.0));
0311   VisAtt->SetVisibility(true);
0312   logicGasVolume->SetVisAttributes(VisAtt);
0313 
0314   VisAtt = new G4VisAttributes(G4Colour(0.0, 0.5, 1.0));
0315   VisAtt->SetVisibility(true);
0316   fLogicTarget1->SetVisAttributes(VisAtt);
0317   fLogicTarget2->SetVisAttributes(VisAtt);
0318   logicTGVolume->SetVisAttributes(VisAtt);
0319 
0320   return physWorld;
0321 }
0322 
0323 void DetectorConstruction::ConstructSDandField()
0324 {
0325   static G4ThreadLocal G4bool initialized = false;
0326   if (!initialized) {
0327     // Prepare sensitive detectors
0328     CheckVolumeSD* fCheckSD = new CheckVolumeSD("checkSD");
0329     (G4SDManager::GetSDMpointer())->AddNewDetector(fCheckSD);
0330     fLogicCheckVolume->SetSensitiveDetector(fCheckSD);
0331 
0332     TargetSD* fTargetSD = new TargetSD("targetSD");
0333     (G4SDManager::GetSDMpointer())->AddNewDetector(fTargetSD);
0334     fLogicTarget1->SetSensitiveDetector(fTargetSD);
0335     fLogicTarget2->SetSensitiveDetector(fTargetSD);
0336 
0337     PhantomSD* fPhantomSD = new PhantomSD("phantomSD");
0338     (G4SDManager::GetSDMpointer())->AddNewDetector(fPhantomSD);
0339     fPhantomSD->SetShiftZ(fShiftZPh);
0340     for (auto& v : fLogicRing)
0341       v->SetSensitiveDetector(fPhantomSD);
0342     fLogicPh->SetSensitiveDetector(fPhantomSD);
0343     fLogicAbsorber->SetSensitiveDetector(fPhantomSD);
0344     initialized = true;
0345   }
0346 }
0347 
0348 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0349 
0350 void DetectorConstruction::SetTarget1Material(const G4String& mat)
0351 {
0352   // search the material by its name
0353   G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(mat);
0354   if (!pttoMaterial) {
0355     G4cout << "Material " << mat << " is not found out!" << G4endl;
0356   }
0357   else if (pttoMaterial != fTarget1Material) {
0358     G4cout << "New target1 material " << mat << G4endl;
0359     if (fLogicTarget1) {
0360       fLogicTarget1->SetMaterial(fTarget1Material);
0361     }
0362     G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0363   }
0364 }
0365 
0366 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0367 
0368 void DetectorConstruction::SetTarget2Material(const G4String& mat)
0369 {
0370   // search the material by its name
0371   G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(mat);
0372 
0373   if (!pttoMaterial) {
0374     G4cout << "Material " << mat << " is not found out!" << G4endl;
0375   }
0376   else if (pttoMaterial != fTarget2Material) {
0377     fTarget2Material = pttoMaterial;
0378     G4cout << "New target2 material " << mat << G4endl;
0379     if (fLogicTarget2) {
0380       fLogicTarget2->SetMaterial(fTarget2Material);
0381     }
0382     G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0383   }
0384 }
0385 
0386 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0387 
0388 void DetectorConstruction::DumpGeometryParameters()
0389 {
0390   G4cout << "===================================================" << G4endl;
0391   G4cout << "#           GammaTherapy Geometry                 #" << G4endl;
0392   G4cout << "===================================================" << G4endl;
0393   G4cout << "  World   width= " << fWorldZ / mm << " mm " << G4endl;
0394   G4cout << "  Window  width= " << fWindowZ / mm << " mm    position = " << fWindowPosZ / mm
0395          << " mm:" << G4endl;
0396   G4cout << "  TargetV width= " << fTargetVolumeZ / mm
0397          << " mm  position = " << fTargetVolumePosZ / mm << " mm:" << G4endl;
0398   G4cout << "  Target1 width= " << fTarget1Z / mm << " mm       position = " << fTarget1PosZ / mm
0399          << " mm:" << G4endl;
0400   G4cout << "  Target2 width= " << fTarget2Z / mm << " mm       position = " << fTarget2PosZ / mm
0401          << " mm:" << G4endl;
0402   G4cout << "  Gas     width= " << fGasVolumeZ / mm << " mm     position = " << fGasVolumePosZ / mm
0403          << " mm:" << G4endl;
0404   G4cout << "  Mylar   width= " << fMylarVolumeZ / mm << " mm    position = " << fMylarPosZ / mm
0405          << " mm:" << G4endl;
0406   G4cout << "  Check   width= " << fCheckVolumeZ / mm
0407          << " mm     position = " << fCheckVolumePosZ / mm << " mm:" << G4endl;
0408   G4cout << "  Air     width= " << fAirZ / mm << " mm " << G4endl;
0409   G4cout << "  Phantom width= " << fPhantomZ / mm << " mm     position = " << fPhantomPosZ / mm
0410          << " mm:" << G4endl;
0411   G4cout << "  Absorb  width= " << fAbsorberZ / mm << " mm       position = " << fAbsorberPosZ / mm
0412          << " mm:" << G4endl;
0413   G4cout << "  Absorb  shift= " << fShiftZPh / mm << " mm " << G4endl;
0414   G4cout << "  Target1        " << fTarget1Material->GetName() << G4endl;
0415   G4cout << "  Target2        " << fTarget2Material->GetName() << G4endl;
0416   G4cout << "  Phantom        " << fAbsorberMaterial->GetName() << G4endl;
0417   G4cout << "===================================================" << G4endl;
0418 }