Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 // 27 /// \file medical/GammaTherapy/src/DetectorConstruction.cc 28 /// \brief Implementation of the DetectorConstruction class 29 // 30 // 31 // ------------------------------------------------------------- 32 // GEANT4 ibrem test 33 // 34 // Authors: V.Grichine, V.Ivanchenko 35 // 36 // Modified: 37 // 38 // 18-02-03 V.Ivanchenko create 39 // 40 // ------------------------------------------------------------- 41 42 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 43 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 44 45 #include "DetectorConstruction.hh" 46 47 #include "CheckVolumeSD.hh" 48 #include "DetectorMessenger.hh" 49 #include "PhantomSD.hh" 50 #include "TargetSD.hh" 51 52 #include "G4Box.hh" 53 #include "G4Colour.hh" 54 #include "G4GeometryManager.hh" 55 #include "G4LogicalVolume.hh" 56 #include "G4LogicalVolumeStore.hh" 57 #include "G4Material.hh" 58 #include "G4NistManager.hh" 59 #include "G4PVPlacement.hh" 60 #include "G4PhysicalConstants.hh" 61 #include "G4PhysicalVolumeStore.hh" 62 #include "G4RunManager.hh" 63 #include "G4SDManager.hh" 64 #include "G4SolidStore.hh" 65 #include "G4SystemOfUnits.hh" 66 #include "G4Tubs.hh" 67 #include "G4VPhysicalVolume.hh" 68 #include "G4VisAttributes.hh" 69 #include "G4ios.hh" 70 #include "globals.hh" 71 72 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 73 74 DetectorConstruction::DetectorConstruction() 75 { 76 fLogicTarget1 = 0; 77 fLogicTarget2 = 0; 78 79 fMessenger = new DetectorMessenger(this); 80 fVerbose = false; 81 82 fNumZ = 60; 83 fNumR = 80; 84 85 fNumE = 200; 86 fMaxEnergy = 50.0 * MeV; 87 88 fDistanceVacuumTarget = 30. * mm, 89 90 fDelta = 0.001 * mm; 91 92 fTargetRadius = 100. * mm; 93 fTarget1Z = 9. * mm; 94 fTarget2Z = 6. * mm; 95 96 fGasVolumeRadius = 210. * mm; 97 fGasVolumeZ = 690. * mm; 98 fMylarVolumeZ = 0.02 * mm; 99 100 fCheckVolumeZ = 0.1 * mm; 101 fCheckShiftZ = 200. * mm; 102 103 fAbsorberRadius = 200. * mm; 104 fPhantomRadius = 300. * mm; 105 fPhantomZ = 300. * mm; 106 107 fAirZ = 210. * mm; 108 fAbsorberShiftZ = 70. * mm; 109 fWindowZ = 0.05 * mm; 110 111 G4NistManager* man = G4NistManager::Instance(); 112 // man->SetVerbose(1); 113 114 fTarget1Material = man->FindOrBuildMaterial("G4_Be"); 115 fWindowMaterial = fTarget1Material; 116 fTarget2Material = man->FindOrBuildMaterial("G4_W"); 117 fLightMaterial = man->FindOrBuildMaterial("G4_He"); 118 fAbsorberMaterial = man->FindOrBuildMaterial("G4_WATER"); 119 fWorldMaterial = man->FindOrBuildMaterial("G4_AIR"); 120 fMylar = man->FindOrBuildMaterial("G4_MYLAR"); 121 122 G4cout << *(G4Material::GetMaterialTable()) << G4endl; 123 } 124 125 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 126 127 DetectorConstruction::~DetectorConstruction() 128 { 129 delete fMessenger; 130 } 131 132 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 133 134 void DetectorConstruction::InitialiseGeometryParameters() 135 { 136 // Volumee sizes 137 138 G4double factor = 1.2; 139 140 fWorldXY = factor * std::max(fPhantomRadius, fGasVolumeRadius); 141 fAbsorberZ = fPhantomZ / fNumZ; 142 fGasVolumeZ = 1000. * mm - fAbsorberShiftZ - fAirZ - fTarget1Z - fTarget2Z; 143 144 G4double ztot = fGasVolumeZ + fAirZ + fPhantomZ + fDistanceVacuumTarget; 145 fTargetVolumeZ = fDistanceVacuumTarget + fTarget2Z + fTarget1Z + fDelta; 146 fWorldZ = factor * ztot * 0.5; 147 148 if (fCheckShiftZ < fDelta) { 149 fCheckShiftZ = fDelta; 150 } 151 if (fCheckShiftZ > fAirZ - fCheckVolumeZ - fDelta) { 152 fCheckShiftZ = fAirZ - fCheckVolumeZ - fDelta; 153 } 154 155 // Z position of volumes from upstream to downstream 156 157 fWindowPosZ = -(ztot + fWindowZ) * 0.5; 158 fGeneratorPosZ = fWindowPosZ - 0.5 * fWindowZ - fDelta; 159 160 fTargetVolumePosZ = -0.5 * (ztot - fTargetVolumeZ); 161 fTarget1PosZ = -0.5 * (fTargetVolumeZ - fTarget1Z) + fDistanceVacuumTarget; 162 fTarget2PosZ = fTarget1PosZ + 0.5 * (fTarget2Z + fTarget1Z); 163 164 fGasVolumePosZ = fTargetVolumePosZ + 0.5 * (fTargetVolumeZ + fGasVolumeZ); 165 fCheckVolumePosZ = fGasVolumePosZ + 0.5 * (fGasVolumeZ + fCheckVolumeZ) + fCheckShiftZ; 166 fMylarPosZ = fGasVolumePosZ + 0.5 * (fGasVolumeZ + fMylarVolumeZ) + fDelta; 167 168 fPhantomPosZ = fGasVolumePosZ + 0.5 * (fGasVolumeZ + fPhantomZ) + fAirZ; 169 fAbsorberPosZ = fAbsorberShiftZ - 0.5 * (fPhantomZ - fAbsorberZ); 170 171 fShiftZPh = fPhantomPosZ - 0.5 * fPhantomZ; 172 173 DumpGeometryParameters(); 174 } 175 176 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 177 178 G4VPhysicalVolume* DetectorConstruction::Construct() 179 { 180 InitialiseGeometryParameters(); 181 182 G4GeometryManager::GetInstance()->OpenGeometry(); 183 G4PhysicalVolumeStore::GetInstance()->Clean(); 184 G4LogicalVolumeStore::GetInstance()->Clean(); 185 G4SolidStore::GetInstance()->Clean(); 186 // 187 // World 188 // 189 190 G4Box* solidWorld = new G4Box("World", fWorldXY, fWorldXY, fWorldZ); 191 G4LogicalVolume* logicWorld = new G4LogicalVolume(solidWorld, fWorldMaterial, "World"); 192 G4VPhysicalVolume* physWorld = 193 new G4PVPlacement(0, G4ThreeVector(), "World", logicWorld, 0, false, 0); 194 195 // Be Vacuum window 196 G4Tubs* solidWin = new G4Tubs("Window", 0., fTargetRadius * 0.25, 0.5 * fWindowZ, 0., twopi); 197 G4LogicalVolume* logicWin = new G4LogicalVolume(solidWin, fWindowMaterial, "Window"); 198 new G4PVPlacement(0, G4ThreeVector(0., 0., fWindowPosZ), "Window", logicWin, physWorld, false, 0); 199 200 // Target Volume 201 G4Tubs* solidTGVolume = 202 new G4Tubs("TargetVolume", 0., fTargetRadius, 0.5 * fTargetVolumeZ, 0., twopi); 203 G4LogicalVolume* logicTGVolume = 204 new G4LogicalVolume(solidTGVolume, fLightMaterial, "TargetVolume"); 205 new G4PVPlacement(0, G4ThreeVector(0., 0., fTargetVolumePosZ), logicTGVolume, "TargetVolume", 206 logicWorld, false, 0); 207 208 // Target 1 209 G4Tubs* solidTarget1 = new G4Tubs("Target1", 0., fTargetRadius * 0.5, 0.5 * fTarget1Z, 0., twopi); 210 fLogicTarget1 = new G4LogicalVolume(solidTarget1, fTarget1Material, "Target1"); 211 fTarget1 = new G4PVPlacement(0, G4ThreeVector(0., 0., fTarget1PosZ), fLogicTarget1, "Target1", 212 logicTGVolume, false, 0); 213 // fLogicTarget1->SetSensitiveDetector(fTargetSD); 214 215 // Target 2 (for combined targets) 216 G4Tubs* solidTarget2 = new G4Tubs("Target2", 0., fTargetRadius * 0.5, 0.5 * fTarget2Z, 0., twopi); 217 fLogicTarget2 = new G4LogicalVolume(solidTarget2, fTarget2Material, "Target2"); 218 fTarget2 = new G4PVPlacement(0, G4ThreeVector(0., 0., fTarget2PosZ), fLogicTarget2, "Target2", 219 logicTGVolume, false, 0); 220 221 // fLogicTarget2->SetSensitiveDetector(fTargetSD); 222 223 // Gas Volume 224 G4Tubs* solidGasVolume = 225 new G4Tubs("GasVolume", 0., fGasVolumeRadius, 0.5 * fGasVolumeZ, 0., twopi); 226 G4LogicalVolume* logicGasVolume = 227 new G4LogicalVolume(solidGasVolume, fLightMaterial, "GasVolume"); 228 fGasVolume = new G4PVPlacement(0, G4ThreeVector(0., 0., fGasVolumePosZ), "GasVolume", 229 logicGasVolume, physWorld, false, 0); 230 231 // Mylar window 232 G4Tubs* sMylarVolume = new G4Tubs("Mylar", 0., fGasVolumeRadius, 0.5 * fMylarVolumeZ, 0., twopi); 233 G4LogicalVolume* lMylarVolume = new G4LogicalVolume(sMylarVolume, fMylar, "Mylar"); 234 new G4PVPlacement(0, G4ThreeVector(0., 0., fMylarPosZ), "Mylar", lMylarVolume, physWorld, false, 235 0); 236 237 // Check Volume 238 G4Tubs* solidCheckVolume = 239 new G4Tubs("CheckVolume", 0., fGasVolumeRadius, 0.5 * fCheckVolumeZ, 0., twopi); 240 fLogicCheckVolume = new G4LogicalVolume(solidCheckVolume, fWorldMaterial, "CheckVolume"); 241 fCheckVolume = new G4PVPlacement(0, G4ThreeVector(0., 0., fCheckVolumePosZ), "CheckVolume", 242 fLogicCheckVolume, physWorld, false, 0); 243 // logicCheckVolume->SetSensitiveDetector(fCheckSD); 244 245 // Phantom 246 G4Box* solidPhantom = new G4Box("Phantom", fPhantomRadius, fPhantomRadius, 0.5 * fPhantomZ); 247 G4LogicalVolume* logicPhantom = new G4LogicalVolume(solidPhantom, fAbsorberMaterial, "Phantom"); 248 G4VPhysicalVolume* physPhantom = new G4PVPlacement(0, G4ThreeVector(0., 0., fPhantomPosZ), 249 "Phantom", logicPhantom, physWorld, false, 0); 250 251 G4Tubs* solidPh = new G4Tubs("PhantomSD", 0., fAbsorberRadius, 0.5 * fPhantomZ, 0., twopi); 252 fLogicPh = new G4LogicalVolume(solidPh, fAbsorberMaterial, "PhantomSD"); 253 fPhantom = 254 new G4PVPlacement(0, G4ThreeVector(0., 0., 0.), "Phantom", fLogicPh, physPhantom, false, 0); 255 G4cout << "Phantom R= " << fAbsorberRadius << " dz= " << 0.5 * fPhantomZ << G4endl; 256 257 // Sensitive Absorber 258 G4double absWidth = 0.5 * fAbsorberZ; 259 G4Tubs* solidAbsorber = new G4Tubs("Absorber", 0., fAbsorberRadius, absWidth, 0., twopi); 260 fLogicAbsorber = new G4LogicalVolume(solidAbsorber, fAbsorberMaterial, "Absorber"); 261 G4cout << "Absorber R= " << fAbsorberRadius << " dz= " << absWidth << " posZ= " << fAbsorberPosZ 262 << G4endl; 263 264 new G4PVPlacement(0, G4ThreeVector(0., 0., fAbsorberPosZ), "Absorber", fLogicAbsorber, fPhantom, 265 false, 0); 266 267 G4double stepR = fAbsorberRadius / (G4double)fNumR; 268 269 G4double r1 = 0.0; 270 G4double r2 = 0.0; 271 G4Tubs* solidRing; 272 273 G4VisAttributes* VisAtt_ring = new G4VisAttributes(G4VisAttributes::GetInvisible()); 274 for (G4int k = 0; k < fNumR; k++) { 275 r2 = r1 + stepR; 276 if (k == fNumR - 1) r2 = fAbsorberRadius; 277 // G4cout << "New ring r1= " << r1 << " r2= " << r2 278 // << " dz= " << absWidth << G4endl; 279 solidRing = new G4Tubs("Ring", r1, r2, absWidth, 0., twopi); 280 G4LogicalVolume* logicRing = new G4LogicalVolume(solidRing, fAbsorberMaterial, "Ring"); 281 // logicRing->SetSensitiveDetector(fPhantomSD); 282 logicRing->SetVisAttributes(VisAtt_ring); 283 fLogicRing.push_back(logicRing); 284 new G4PVPlacement(0, G4ThreeVector(0., 0., 0.), logicRing, "Ring", fLogicAbsorber, false, k); 285 r1 = r2; 286 } 287 288 // 289 // Visualization attributes 290 // 291 G4VisAttributes* VisAtt = 0; 292 VisAtt = new G4VisAttributes(G4Colour(1.0, 1.0, 1.0)); 293 VisAtt->SetVisibility(true); 294 fLogicAbsorber->SetVisAttributes(VisAtt); 295 296 VisAtt = new G4VisAttributes(G4Colour(1.0, 1.0, 2.0)); 297 VisAtt->SetVisibility(true); 298 logicPhantom->SetVisAttributes(VisAtt); 299 300 VisAtt = new G4VisAttributes(G4Colour(1.0, 0.0, 2.0)); 301 VisAtt->SetVisibility(true); 302 fLogicPh->SetVisAttributes(VisAtt); 303 304 VisAtt = new G4VisAttributes(G4Colour(1.0, 1.0, 0.0)); 305 VisAtt->SetVisibility(true); 306 fLogicAbsorber->SetVisAttributes(VisAtt); 307 308 VisAtt = new G4VisAttributes(G4Colour(0.1, 1.0, 2.0)); 309 VisAtt->SetVisibility(true); 310 logicWorld->SetVisAttributes(VisAtt); 311 312 VisAtt = new G4VisAttributes(G4Colour(1.0, 1.0, 0.0)); 313 VisAtt->SetVisibility(true); 314 logicGasVolume->SetVisAttributes(VisAtt); 315 316 VisAtt = new G4VisAttributes(G4Colour(0.0, 0.5, 1.0)); 317 VisAtt->SetVisibility(true); 318 fLogicTarget1->SetVisAttributes(VisAtt); 319 fLogicTarget2->SetVisAttributes(VisAtt); 320 logicTGVolume->SetVisAttributes(VisAtt); 321 322 return physWorld; 323 } 324 325 void DetectorConstruction::ConstructSDandField() 326 { 327 static G4ThreadLocal G4bool initialized = false; 328 if (!initialized) { 329 // Prepare sensitive detectors 330 CheckVolumeSD* fCheckSD = new CheckVolumeSD("checkSD"); 331 (G4SDManager::GetSDMpointer())->AddNewDetector(fCheckSD); 332 fLogicCheckVolume->SetSensitiveDetector(fCheckSD); 333 334 TargetSD* fTargetSD = new TargetSD("targetSD"); 335 (G4SDManager::GetSDMpointer())->AddNewDetector(fTargetSD); 336 fLogicTarget1->SetSensitiveDetector(fTargetSD); 337 fLogicTarget2->SetSensitiveDetector(fTargetSD); 338 339 PhantomSD* fPhantomSD = new PhantomSD("phantomSD"); 340 (G4SDManager::GetSDMpointer())->AddNewDetector(fPhantomSD); 341 fPhantomSD->SetShiftZ(fShiftZPh); 342 for (auto& v : fLogicRing) 343 v->SetSensitiveDetector(fPhantomSD); 344 fLogicPh->SetSensitiveDetector(fPhantomSD); 345 fLogicAbsorber->SetSensitiveDetector(fPhantomSD); 346 initialized = true; 347 } 348 } 349 350 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 351 352 void DetectorConstruction::SetTarget1Material(const G4String& mat) 353 { 354 // search the material by its name 355 G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(mat); 356 if (!pttoMaterial) { 357 G4cout << "Material " << mat << " is not found out!" << G4endl; 358 } 359 else if (pttoMaterial != fTarget1Material) { 360 G4cout << "New target1 material " << mat << G4endl; 361 if (fLogicTarget1) { 362 fLogicTarget1->SetMaterial(fTarget1Material); 363 } 364 G4RunManager::GetRunManager()->PhysicsHasBeenModified(); 365 } 366 } 367 368 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 369 370 void DetectorConstruction::SetTarget2Material(const G4String& mat) 371 { 372 // search the material by its name 373 G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(mat); 374 375 if (!pttoMaterial) { 376 G4cout << "Material " << mat << " is not found out!" << G4endl; 377 } 378 else if (pttoMaterial != fTarget2Material) { 379 fTarget2Material = pttoMaterial; 380 G4cout << "New target2 material " << mat << G4endl; 381 if (fLogicTarget2) { 382 fLogicTarget2->SetMaterial(fTarget2Material); 383 } 384 G4RunManager::GetRunManager()->PhysicsHasBeenModified(); 385 } 386 } 387 388 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 389 390 void DetectorConstruction::DumpGeometryParameters() 391 { 392 G4cout << "===================================================" << G4endl; 393 G4cout << "# GammaTherapy Geometry #" << G4endl; 394 G4cout << "===================================================" << G4endl; 395 G4cout << " World width= " << fWorldZ / mm << " mm " << G4endl; 396 G4cout << " Window width= " << fWindowZ / mm << " mm position = " << fWindowPosZ / mm 397 << " mm:" << G4endl; 398 G4cout << " TargetV width= " << fTargetVolumeZ / mm 399 << " mm position = " << fTargetVolumePosZ / mm << " mm:" << G4endl; 400 G4cout << " Target1 width= " << fTarget1Z / mm << " mm position = " << fTarget1PosZ / mm 401 << " mm:" << G4endl; 402 G4cout << " Target2 width= " << fTarget2Z / mm << " mm position = " << fTarget2PosZ / mm 403 << " mm:" << G4endl; 404 G4cout << " Gas width= " << fGasVolumeZ / mm << " mm position = " << fGasVolumePosZ / mm 405 << " mm:" << G4endl; 406 G4cout << " Mylar width= " << fMylarVolumeZ / mm << " mm position = " << fMylarPosZ / mm 407 << " mm:" << G4endl; 408 G4cout << " Check width= " << fCheckVolumeZ / mm 409 << " mm position = " << fCheckVolumePosZ / mm << " mm:" << G4endl; 410 G4cout << " Air width= " << fAirZ / mm << " mm " << G4endl; 411 G4cout << " Phantom width= " << fPhantomZ / mm << " mm position = " << fPhantomPosZ / mm 412 << " mm:" << G4endl; 413 G4cout << " Absorb width= " << fAbsorberZ / mm << " mm position = " << fAbsorberPosZ / mm 414 << " mm:" << G4endl; 415 G4cout << " Absorb shift= " << fShiftZPh / mm << " mm " << G4endl; 416 G4cout << " Target1 " << fTarget1Material->GetName() << G4endl; 417 G4cout << " Target2 " << fTarget2Material->GetName() << G4endl; 418 G4cout << " Phantom " << fAbsorberMaterial->GetName() << G4endl; 419 G4cout << "===================================================" << G4endl; 420 } 421