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 /// \file electromagnetic/TestEm8/src/DetectorConstruction.cc 27 /// \brief Implementation of the DetectorConstruction class 28 // 29 // 30 ///////////////////////////////////////////////////////////////////////// 31 // 32 // TestEm8: Gaseous detector 33 // 34 // Created: 31.08.2010 V.Ivanchenko ob base of V.Grichine code 35 // 36 // Modified: 37 // 38 //////////////////////////////////////////////////////////////////////// 39 // 40 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 41 42 #include "DetectorConstruction.hh" 43 44 #include "DetectorMessenger.hh" 45 #include "TargetSD.hh" 46 #include "TestParameters.hh" 47 48 #include "G4Colour.hh" 49 #include "G4GeometryManager.hh" 50 #include "G4LogicalVolume.hh" 51 #include "G4LogicalVolumeStore.hh" 52 #include "G4Material.hh" 53 #include "G4NistManager.hh" 54 #include "G4PVPlacement.hh" 55 #include "G4PhysicalConstants.hh" 56 #include "G4PhysicalVolumeStore.hh" 57 #include "G4PionPlus.hh" 58 #include "G4ProductionCuts.hh" 59 #include "G4Region.hh" 60 #include "G4RegionStore.hh" 61 #include "G4RunManager.hh" 62 #include "G4SDManager.hh" 63 #include "G4SolidStore.hh" 64 #include "G4SystemOfUnits.hh" 65 #include "G4Tubs.hh" 66 #include "G4UnitsTable.hh" 67 #include "G4VisAttributes.hh" 68 #include "G4ios.hh" 69 70 #include <vector> 71 72 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 73 74 DetectorConstruction::DetectorConstruction() 75 { 76 fGasThickness = 23.0 * mm; 77 fGasRadius = 10. * cm; 78 fMaxStep = DBL_MAX; 79 80 fWindowThick = 51.0 * micrometer; 81 82 DefineMaterials(); 83 84 fDetectorMessenger = new DetectorMessenger(this); 85 86 G4double cut = 0.7 * mm; 87 fGasDetectorCuts = new G4ProductionCuts(); 88 fGasDetectorCuts->SetProductionCut(cut, "gamma"); 89 fGasDetectorCuts->SetProductionCut(cut, "e-"); 90 fGasDetectorCuts->SetProductionCut(cut, "e+"); 91 fGasDetectorCuts->SetProductionCut(cut, "proton"); 92 } 93 94 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 95 96 DetectorConstruction::~DetectorConstruction() 97 { 98 delete fDetectorMessenger; 99 } 100 101 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 102 103 void DetectorConstruction::DefineMaterials() 104 { 105 // This function illustrates the possible ways to define materials 106 G4String name, symbol; 107 G4double density; 108 G4int nel; 109 G4int ncomponents; 110 G4double fractionmass; 111 112 G4NistManager* manager = G4NistManager::Instance(); 113 // 114 // define Elements 115 // 116 G4Element* elH = manager->FindOrBuildElement(1); 117 G4Element* elC = manager->FindOrBuildElement(6); 118 G4Element* elO = manager->FindOrBuildElement(8); 119 G4Element* elF = manager->FindOrBuildElement(9); 120 G4Element* elNe = manager->FindOrBuildElement(10); 121 G4Element* elXe = manager->FindOrBuildElement(54); 122 // 123 // simple gases at STP conditions 124 // 125 G4Material* Argon = manager->FindOrBuildMaterial("G4_Ar"); 126 G4Material* Kr = manager->FindOrBuildMaterial("G4_Kr"); 127 G4Material* Xe = manager->FindOrBuildMaterial("G4_Xe"); 128 // 129 // gases at STP conditions 130 // 131 G4Material* CarbonDioxide = manager->FindOrBuildMaterial("G4_CARBON_DIOXIDE"); 132 G4Material* Mylar = manager->FindOrBuildMaterial("G4_MYLAR"); 133 G4Material* Methane = manager->FindOrBuildMaterial("G4_METHANE"); 134 G4Material* Propane = manager->FindOrBuildMaterial("G4_PROPANE"); 135 136 // propane at 10 atmospheres 137 manager->ConstructNewGasMaterial("Propane10", "G4_PROPANE", NTP_Temperature, 10. * atmosphere); 138 139 G4Material* empty = manager->FindOrBuildMaterial("G4_Galactic"); 140 141 // 93% Kr + 7% CH4, STP 142 density = 3.491 * mg / cm3; 143 G4Material* Kr7CH4 = new G4Material(name = "Kr7CH4", density, ncomponents = 2); 144 Kr7CH4->AddMaterial(Kr, fractionmass = 0.986); 145 Kr7CH4->AddMaterial(Methane, fractionmass = 0.014); 146 147 G4double TRT_Xe_density = 5.485 * mg / cm3; 148 G4Material* TRT_Xe = new G4Material(name = "TRT_Xe", TRT_Xe_density, nel = 1, kStateGas, 149 293.15 * kelvin, 1. * atmosphere); 150 TRT_Xe->AddElement(elXe, 1); 151 152 G4double TRT_CO2_density = 1.842 * mg / cm3; 153 G4Material* TRT_CO2 = new G4Material(name = "TRT_CO2", TRT_CO2_density, nel = 2, kStateGas, 154 293.15 * kelvin, 1. * atmosphere); 155 TRT_CO2->AddElement(elC, 1); 156 TRT_CO2->AddElement(elO, 2); 157 158 // check alternative constructor 159 std::vector<G4String> trtatom = {"C", "O"}; 160 std::vector<G4int> trtnum = {1, 2}; 161 manager->ConstructNewMaterial("TRT_CO2p", trtatom, trtnum, TRT_CO2_density, true, kStateGas, 162 NTP_Temperature, atmosphere); 163 164 G4double TRT_CF4_density = 3.9 * mg / cm3; 165 G4Material* TRT_CF4 = new G4Material(name = "TRT_CF4", TRT_CF4_density, nel = 2, kStateGas, 166 293.15 * kelvin, 1. * atmosphere); 167 TRT_CF4->AddElement(elC, 1); 168 TRT_CF4->AddElement(elF, 4); 169 170 // ATLAS TRT straw tube gas mixture (20 C, 1 atm) 171 G4double XeCO2CF4_density = 4.76 * mg / cm3; 172 G4Material* XeCO2CF4 = new G4Material(name = "XeCO2CF4", XeCO2CF4_density, ncomponents = 3, 173 kStateGas, 293.15 * kelvin, 1. * atmosphere); 174 XeCO2CF4->AddMaterial(TRT_Xe, 0.807); 175 XeCO2CF4->AddMaterial(TRT_CO2, 0.039); 176 XeCO2CF4->AddMaterial(TRT_CF4, 0.154); 177 178 // C3H8,20 C, 2 atm 179 density = 3.758 * mg / cm3; 180 G4Material* C3H8 = 181 new G4Material(name = "C3H8", density, nel = 2, kStateGas, 293.15 * kelvin, 2. * atmosphere); 182 C3H8->AddElement(elC, 3); 183 C3H8->AddElement(elH, 8); 184 185 // The same material via different constructor 186 std::vector<G4String> elmname = {"C", "H"}; 187 std::vector<G4int> atomnum = {3, 8}; 188 manager->ConstructNewIdealGasMaterial("C3H8p", elmname, atomnum, true, 293.15 * kelvin, 189 2. * atmosphere); 190 191 // 87.5% Xe + 7.5% CH4 + 5% C3H8, 20 C, 1. atm 192 density = 4.9196 * mg / cm3; 193 G4Material* XeCH4C3H8 = new G4Material(name = "XeCH4C3H8", density, ncomponents = 3, kStateGas, 194 NTP_Temperature, 1. * atmosphere); 195 XeCH4C3H8->AddMaterial(Xe, fractionmass = 0.971); 196 XeCH4C3H8->AddMaterial(Methane, fractionmass = 0.010); 197 XeCH4C3H8->AddMaterial(Propane, fractionmass = 0.019); 198 199 // 93% Ar + 7% CH4, STP 200 density = 1.709 * mg / cm3; 201 G4Material* Ar7CH4 = new G4Material(name = "Ar7CH4", density, ncomponents = 2, kStateGas, 202 STP_Temperature, STP_Pressure); 203 Ar7CH4->AddMaterial(Argon, fractionmass = 0.971); 204 Ar7CH4->AddMaterial(Methane, fractionmass = 0.029); 205 206 // 80% Ar + 20% CO2, STP 207 density = 1.8223 * mg / cm3; 208 G4Material* Ar_80CO2_20 = new G4Material(name = "ArCO2", density, ncomponents = 2, kStateGas, 209 STP_Temperature, STP_Pressure); 210 Ar_80CO2_20->AddMaterial(Argon, fractionmass = 0.783); 211 Ar_80CO2_20->AddMaterial(CarbonDioxide, fractionmass = 0.217); 212 213 // 80% Xe + 20% CO2, STP 214 density = 5.0818 * mg / cm3; 215 G4Material* Xe20CO2 = new G4Material(name = "Xe20CO2", density, ncomponents = 2, kStateGas, 216 STP_Temperature, STP_Pressure); 217 Xe20CO2->AddMaterial(Xe, fractionmass = 0.922); 218 Xe20CO2->AddMaterial(CarbonDioxide, fractionmass = 0.078); 219 220 // 80% Kr + 20% CO2, STP 221 density = 3.601 * mg / cm3; 222 G4Material* Kr20CO2 = new G4Material(name = "Kr20CO2", density, ncomponents = 2, kStateGas, 223 STP_Temperature, STP_Pressure); 224 Kr20CO2->AddMaterial(Kr, fractionmass = 0.89); 225 Kr20CO2->AddMaterial(CarbonDioxide, fractionmass = 0.11); 226 227 // ALICE mixture TPC_Ne-CO2-2 228 density = 0.939 * mg / cm3; 229 G4Material* NeCO2 = new G4Material(name = "TPC_Ne-CO2-2", density, ncomponents = 3, kStateGas, 230 NTP_Temperature, 1. * atmosphere); 231 NeCO2->AddElement(elNe, fractionmass = 0.8039); 232 NeCO2->AddElement(elO, fractionmass = 0.1426); 233 NeCO2->AddElement(elC, fractionmass = 0.0535); 234 235 // check alternative constructor 236 std::vector<G4String> neatom = {"Ne", "O", "C"}; 237 std::vector<G4double> nefr = {0.8039, 0.1426, 0.0536}; 238 manager->ConstructNewMaterial("TPC_Ne-CO2-2p", neatom, nefr, density, true, kStateGas, 239 NTP_Temperature, atmosphere); 240 241 // ALICE TRD mixure 85% Xe + 15% CO2 NTP 242 density = 4.9389 * mg / cm3; 243 G4Material* Xe15CO2 = new G4Material(name = "Xe15CO2", density, ncomponents = 2, kStateGas, 244 NTP_Temperature, atmosphere); 245 Xe15CO2->AddMaterial(Xe, fractionmass = 0.944); 246 Xe15CO2->AddMaterial(CarbonDioxide, fractionmass = 0.056); 247 248 fGasMat = XeCH4C3H8; 249 fWindowMat = Mylar; 250 fWorldMaterial = empty; 251 252 G4cout << *(G4Material::GetMaterialTable()) << G4endl; 253 } 254 255 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 256 257 G4VPhysicalVolume* DetectorConstruction::Construct() 258 { 259 if (nullptr != fPhysWorld) { 260 return fPhysWorld; 261 } 262 263 G4double contThick = fWindowThick * 2 + fGasThickness; 264 G4double contR = fWindowThick * 2 + fGasRadius; 265 266 G4double worldSizeZ = contThick * 1.2; 267 G4double worldSizeR = contR * 1.2; 268 269 TestParameters::GetPointer()->SetPositionZ(-0.55 * contThick); 270 271 // Printout parameters 272 G4cout << "\n The WORLD is made of " << worldSizeZ / mm << "mm of " 273 << fWorldMaterial->GetName(); 274 G4cout << ", the transverse size (R) of the world is " << worldSizeR / mm << " mm. " << G4endl; 275 G4cout << " The CONTAINER is made of " << fWindowThick / mm << "mm of " << fWindowMat->GetName() 276 << G4endl; 277 G4cout << " The TARGET is made of " << fGasThickness / mm << "mm of " << fGasMat->GetName(); 278 G4cout << ", the transverse size (R) is " << fGasRadius / mm << " mm. " << G4endl; 279 G4cout << G4endl; 280 281 // World 282 fSolidWorld = new G4Tubs("World", 0., worldSizeR, worldSizeZ / 2., 0., CLHEP::twopi); 283 284 fLogicWorld = new G4LogicalVolume(fSolidWorld, fWorldMaterial, "World"); 285 286 fPhysWorld = new G4PVPlacement(0, G4ThreeVector(0., 0., 0.), "World", fLogicWorld, 0, false, 0); 287 288 // Window 289 fSolidContainer = new G4Tubs("Absorber", 0., contR, contThick / 2., 0., CLHEP::twopi); 290 291 fLogicContainer = new G4LogicalVolume(fSolidContainer, fWindowMat, "Window"); 292 293 G4PVPlacement* PhysWind = new G4PVPlacement(0, G4ThreeVector(0., 0., 0.), "Window", 294 fLogicContainer, fPhysWorld, false, 0); 295 296 // Detector volume 297 fSolidDetector = new G4Tubs("Gas", 0., fGasRadius, fGasThickness / 2., 0., CLHEP::twopi); 298 299 fLogicDetector = new G4LogicalVolume(fSolidDetector, fGasMat, "Gas"); 300 301 new G4PVPlacement(0, G4ThreeVector(0., 0., 0.), "Gas", fLogicDetector, PhysWind, false, 0); 302 303 // defined gas detector region 304 fRegGasDet = new G4Region("GasDetector"); 305 fRegGasDet->SetProductionCuts(fGasDetectorCuts); 306 fRegGasDet->AddRootLogicalVolume(fLogicDetector); 307 308 // visualisation 309 fLogicWorld->SetVisAttributes(G4VisAttributes::GetInvisible()); 310 G4VisAttributes* color1 = new G4VisAttributes(G4Colour(0.3, 0.3, 0.3)); 311 fLogicContainer->SetVisAttributes(color1); 312 G4VisAttributes* color2 = new G4VisAttributes(G4Colour(0.0, 0.3, 0.7)); 313 fLogicDetector->SetVisAttributes(color2); 314 315 if (0.0 == fGasMat->GetIonisation()->GetMeanEnergyPerIonPair()) { 316 SetPairEnergy(20 * eV); 317 } 318 return fPhysWorld; 319 } 320 321 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 322 323 void DetectorConstruction::ConstructSDandField() 324 { 325 auto sd = new TargetSD("GasSD"); 326 G4SDManager::GetSDMpointer()->AddNewDetector(sd); 327 SetSensitiveDetector(fLogicDetector, sd); 328 } 329 330 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 331 332 void DetectorConstruction::SetGasMaterial(const G4String& name) 333 { 334 // get the pointer to the existing material 335 G4Material* mat = G4Material::GetMaterial(name, false); 336 337 // create the material by its name 338 if (!mat) { 339 mat = G4NistManager::Instance()->FindOrBuildMaterial(name); 340 } 341 342 if (mat && mat != fGasMat) { 343 G4cout << "### New target material: " << mat->GetName() << G4endl; 344 fGasMat = mat; 345 if (fLogicDetector) { 346 fLogicDetector->SetMaterial(mat); 347 G4RunManager::GetRunManager()->PhysicsHasBeenModified(); 348 } 349 } 350 } 351 352 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 353 354 void DetectorConstruction::SetContainerMaterial(const G4String& name) 355 { 356 // get the pointer to the existing material 357 G4Material* mat = G4Material::GetMaterial(name, false); 358 359 // create the material by its name 360 if (!mat) { 361 mat = G4NistManager::Instance()->FindOrBuildMaterial(name); 362 } 363 364 if (mat && mat != fWindowMat) { 365 G4cout << "### New material for container: " << mat->GetName() << G4endl; 366 fWindowMat = mat; 367 if (fLogicContainer) { 368 fLogicContainer->SetMaterial(mat); 369 G4RunManager::GetRunManager()->PhysicsHasBeenModified(); 370 } 371 } 372 } 373 374 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 375 376 void DetectorConstruction::SetWorldMaterial(const G4String& name) 377 { 378 // get the pointer to the existing material 379 G4Material* mat = G4Material::GetMaterial(name, false); 380 381 // create the material by its name 382 if (!mat) { 383 mat = G4NistManager::Instance()->FindOrBuildMaterial(name); 384 } 385 386 if (mat && mat != fWorldMaterial) { 387 G4cout << "### New World material: " << mat->GetName() << G4endl; 388 fWorldMaterial = mat; 389 if (fLogicWorld) { 390 fLogicWorld->SetMaterial(mat); 391 G4RunManager::GetRunManager()->PhysicsHasBeenModified(); 392 } 393 } 394 } 395 396 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 397 398 void DetectorConstruction::SetGasThickness(G4double val) 399 { 400 if (val <= 0.0) { 401 return; 402 } 403 fGasThickness = val; 404 if (nullptr != fPhysWorld) { 405 ChangeGeometry(); 406 } 407 } 408 409 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 410 411 void DetectorConstruction::SetGasRadius(G4double val) 412 { 413 if (val <= 0.0) { 414 return; 415 } 416 fGasRadius = val; 417 if (nullptr != fPhysWorld) { 418 ChangeGeometry(); 419 } 420 } 421 422 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 423 424 void DetectorConstruction::SetContainerThickness(G4double val) 425 { 426 if (val <= 0.0) { 427 return; 428 } 429 fWindowThick = val; 430 if (nullptr != fPhysWorld) { 431 ChangeGeometry(); 432 } 433 } 434 435 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 436 437 void DetectorConstruction::SetPairEnergy(G4double val) 438 { 439 if (val > 0.0) { 440 fGasMat->GetIonisation()->SetMeanEnergyPerIonPair(val); 441 } 442 } 443 444 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 445 446 void DetectorConstruction::ChangeGeometry() 447 { 448 G4double contThick = fWindowThick * 2 + fGasThickness; 449 G4double contR = fWindowThick * 2 + fGasRadius; 450 451 G4double worldSizeZ = contThick * 1.2; 452 G4double worldSizeR = contR * 1.2; 453 454 TestParameters::GetPointer()->SetPositionZ(-0.55 * contThick); 455 456 fSolidWorld->SetOuterRadius(worldSizeR); 457 fSolidWorld->SetZHalfLength(worldSizeZ * 0.5); 458 459 fSolidContainer->SetOuterRadius(contR); 460 fSolidContainer->SetZHalfLength(contThick * 0.5); 461 462 fSolidDetector->SetOuterRadius(fGasRadius); 463 fSolidDetector->SetZHalfLength(fGasThickness * 0.5); 464 } 465 466 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 467