Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-23 09:22:18

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