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 src/DetectorConstruction.cc 27 /// \brief Implementation of the DetectorConstruction class 28 // 29 // 30 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 31 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 32 33 #include "DetectorConstruction.hh" 34 35 #include "DetectorMessenger.hh" 36 37 #include "G4Box.hh" 38 #include "G4LogicalVolume.hh" 39 #include "G4Material.hh" 40 #include "G4NistManager.hh" 41 #include "G4PVPlacement.hh" 42 #include "G4PVReplica.hh" 43 #include "G4PhysicalConstants.hh" 44 #include "G4ProductionCutsTable.hh" 45 #include "G4Region.hh" 46 #include "G4RunManager.hh" 47 #include "G4SystemOfUnits.hh" 48 #include "G4UnitsTable.hh" 49 50 #include <iomanip> 51 52 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 53 54 DetectorConstruction::DetectorConstruction() 55 : fWorldMaterial(nullptr), 56 fLogicWorld(nullptr), 57 fPhysiWorld(nullptr), 58 fLogicLayerFront(nullptr), 59 fLogicLayerBack(nullptr) 60 { 61 for (G4int i = 0; i < kMaxAbsor; ++i) { 62 fAbsorMaterial[i] = nullptr; 63 fAbsorThickness[i] = 0.0; 64 fLogicAbsorFront[i] = nullptr; 65 fLogicAbsorBack[i] = nullptr; 66 } 67 68 // default parameter values of the calorimeter 69 fNbOfAbsor = 2; 70 fAbsorThickness[1] = 2.3 * mm; 71 fAbsorThickness[2] = 5.7 * mm; 72 fNbOfLayers = 50; 73 fCalorSizeYZ = 40. * cm; 74 ComputeCalorParameters(); 75 76 // materials 77 SetWorldMaterial("G4_Galactic"); 78 SetAbsorMaterial(1, "G4_Pb"); 79 SetAbsorMaterial(2, "G4_lAr"); 80 81 // create commands for interactive definition of the calorimeter 82 fDetectorMessenger.reset(new DetectorMessenger(this)); 83 } 84 85 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 86 87 void DetectorConstruction::ComputeCalorParameters() 88 { 89 // Compute derived parameters of the calorimeter 90 fLayerThickness = 0.; 91 for (G4int iAbs = 1; iAbs <= fNbOfAbsor; iAbs++) { 92 fLayerThickness += fAbsorThickness[iAbs]; 93 } 94 fCalorThickness = fNbOfLayers * fLayerThickness; 95 fWorldSizeX = 1.2 * fCalorThickness; 96 fWorldSizeYZ = 1.2 * fCalorSizeYZ; 97 } 98 99 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 100 101 G4VPhysicalVolume* DetectorConstruction::Construct() 102 { 103 if (fPhysiWorld) { 104 return fPhysiWorld; 105 } 106 // complete the Calor parameters definition 107 ComputeCalorParameters(); 108 109 // 110 // World 111 // 112 auto* solidWorld = new G4Box("World", // its name 113 fWorldSizeX / 2, fWorldSizeYZ / 2, 114 fWorldSizeYZ / 2); // its size 115 116 fLogicWorld = new G4LogicalVolume(solidWorld, // its solid 117 fWorldMaterial, // its material 118 "World"); // its name 119 120 fPhysiWorld = new G4PVPlacement(0, // no rotation 121 G4ThreeVector(), // at (0,0,0) 122 fLogicWorld, // its fLogical volume 123 "World", // its name 124 0, // its mother volume 125 false, // no boolean operation 126 0); // copy number 127 // 128 // Calorimeter 129 // 130 131 auto* solidCalor = 132 new G4Box("Calorimeter", fCalorThickness / 2, fCalorSizeYZ / 2, fCalorSizeYZ / 2); 133 134 auto* logicCalor = new G4LogicalVolume(solidCalor, fWorldMaterial, "Calorimeter"); 135 136 new G4PVPlacement(0, // no rotation 137 G4ThreeVector(), // at (0,0,0) 138 logicCalor, // its fLogical volume 139 "Calorimeter", // its name 140 fLogicWorld, // its mother volume 141 false, // no boolean operation 142 0); // copy number 143 144 // 145 // Layers 146 // 147 148 auto* solidLayer = new G4Box("Layer", fLayerThickness / 2, fCalorSizeYZ / 2, fCalorSizeYZ / 2); 149 150 fLogicLayerFront = new G4LogicalVolume(solidLayer, fWorldMaterial, "Layer-front"); 151 fLogicLayerBack = new G4LogicalVolume(solidLayer, fWorldMaterial, "Layer-back"); 152 G4double xfront = -0.5 * fCalorThickness; 153 for (G4int l = 0; l < fNbOfLayers; ++l) { 154 G4double xcenter = xfront + 0.5 * fLayerThickness; 155 xfront += fLayerThickness; 156 G4LogicalVolume* logicLayer = fLogicLayerFront; 157 if (xcenter > 0) { 158 logicLayer = fLogicLayerBack; 159 } 160 161 new G4PVPlacement(0, G4ThreeVector(xcenter, 0, 0), logicLayer, "Layer", logicCalor, false, l); 162 } 163 164 // 165 // Regions 166 // 167 168 auto* regionFront = new G4Region("Front"); 169 regionFront->SetProductionCuts( 170 G4ProductionCutsTable::GetProductionCutsTable()->GetDefaultProductionCuts()); 171 regionFront->AddRootLogicalVolume(fLogicLayerFront); 172 auto* regionBack = new G4Region("Back"); 173 regionBack->SetProductionCuts( 174 G4ProductionCutsTable::GetProductionCutsTable()->GetDefaultProductionCuts()); 175 regionBack->AddRootLogicalVolume(fLogicLayerBack); 176 177 // 178 // Absorbers 179 // 180 181 xfront = -0.5 * fLayerThickness; 182 for (G4int k = 1; k <= fNbOfAbsor; ++k) { 183 auto* solidAbsor = new G4Box("Absorber", // its name 184 fAbsorThickness[k] / 2, fCalorSizeYZ / 2, fCalorSizeYZ / 2); 185 186 fLogicAbsorFront[k] = new G4LogicalVolume(solidAbsor, // its solid 187 fAbsorMaterial[k], // its material 188 fAbsorMaterial[k]->GetName()); 189 fLogicAbsorBack[k] = new G4LogicalVolume(solidAbsor, // its solid 190 fAbsorMaterial[k], // its material 191 fAbsorMaterial[k]->GetName()); 192 193 G4double xcenter = xfront + 0.5 * fAbsorThickness[k]; 194 xfront += fAbsorThickness[k]; 195 new G4PVPlacement(0, G4ThreeVector(xcenter, 0., 0.), fLogicAbsorFront[k], 196 fAbsorMaterial[k]->GetName(), fLogicLayerFront, false, 197 k); // copy number 198 new G4PVPlacement(0, G4ThreeVector(xcenter, 0., 0.), fLogicAbsorBack[k], 199 fAbsorMaterial[k]->GetName(), fLogicLayerBack, false, 200 k); // copy number 201 } 202 203 PrintCalorParameters(); 204 205 // always return the fPhysical World 206 // 207 return fPhysiWorld; 208 } 209 210 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 211 212 void DetectorConstruction::PrintCalorParameters() 213 { 214 G4cout << "\n-------------------------------------------------------------" 215 << "\n ---> The calorimeter is " << fNbOfLayers << " layers of:"; 216 for (G4int i = 1; i <= fNbOfAbsor; ++i) { 217 G4cout << "\n \t" << std::setw(12) << fAbsorMaterial[i]->GetName() << ": " << std::setw(6) 218 << G4BestUnit(fAbsorThickness[i], "Length"); 219 } 220 G4cout << "\n-------------------------------------------------------------\n"; 221 222 G4cout << "\n" << fWorldMaterial << G4endl; 223 for (G4int j = 1; j <= fNbOfAbsor; ++j) { 224 G4cout << "\n" << fAbsorMaterial[j] << G4endl; 225 } 226 G4cout << "\n-------------------------------------------------------------\n"; 227 } 228 229 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 230 231 void DetectorConstruction::SetWorldMaterial(const G4String& material) 232 { 233 // search the material by its name 234 G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(material); 235 if (pttoMaterial) { 236 fWorldMaterial = pttoMaterial; 237 if (fLogicWorld) { 238 fLogicWorld->SetMaterial(fWorldMaterial); 239 fLogicLayerFront->SetMaterial(fWorldMaterial); 240 fLogicLayerBack->SetMaterial(fWorldMaterial); 241 G4RunManager::GetRunManager()->PhysicsHasBeenModified(); 242 } 243 } 244 } 245 246 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 247 248 void DetectorConstruction::SetNbOfLayers(G4int ival) 249 { 250 // set the number of Layers 251 // 252 if (ival < 2) { 253 G4cout << "\n --->warning from SetfNbOfLayers: " << ival 254 << " must be at least 2. Command refused" << G4endl; 255 return; 256 } 257 fNbOfLayers = ival; 258 } 259 260 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 261 262 void DetectorConstruction::SetNbOfAbsor(G4int ival) 263 { 264 // set the number of Absorbers 265 // 266 if (ival < 1 || ival > (kMaxAbsor - 1)) { 267 G4cout << "\n ---> warning from SetfNbOfAbsor: " << ival << " must be at least 1 and and most " 268 << kMaxAbsor - 1 << ". Command refused" << G4endl; 269 return; 270 } 271 fNbOfAbsor = ival; 272 } 273 274 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 275 276 void DetectorConstruction::SetAbsorMaterial(G4int ival, const G4String& material) 277 { 278 // search the material by its name 279 // 280 if (ival > fNbOfAbsor || ival <= 0) { 281 G4cout << "\n --->warning from SetAbsorMaterial: absor number " << ival 282 << " out of range. Command refused" << G4endl; 283 return; 284 } 285 286 G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(material); 287 if (pttoMaterial) { 288 fAbsorMaterial[ival] = pttoMaterial; 289 if (fLogicAbsorFront[ival]) { 290 fLogicAbsorFront[ival]->SetMaterial(pttoMaterial); 291 fLogicAbsorBack[ival]->SetMaterial(pttoMaterial); 292 G4RunManager::GetRunManager()->PhysicsHasBeenModified(); 293 } 294 } 295 } 296 297 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 298 299 void DetectorConstruction::SetAbsorThickness(G4int ival, G4double val) 300 { 301 // change Absorber thickness 302 // 303 if (ival > fNbOfAbsor || ival <= 0) { 304 G4cout << "\n --->warning from SetAbsorThickness: absor number " << ival 305 << " out of range. Command refused" << G4endl; 306 return; 307 } 308 if (val <= DBL_MIN) { 309 G4cout << "\n --->warning from SetAbsorThickness: thickness " << val 310 << " out of range. Command refused" << G4endl; 311 return; 312 } 313 fAbsorThickness[ival] = val; 314 } 315 316 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 317 318 void DetectorConstruction::SetCalorSizeYZ(G4double val) 319 { 320 // change the transverse size 321 // 322 if (val <= DBL_MIN) { 323 G4cout << "\n --->warning from SetfCalorSizeYZ: thickness " << val 324 << " out of range. Command refused" << G4endl; 325 return; 326 } 327 fCalorSizeYZ = val; 328 } 329 330 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 331 332 #include "G4AutoDelete.hh" 333 #include "G4GlobalMagFieldMessenger.hh" 334 335 void DetectorConstruction::ConstructSDandField() 336 { 337 if (fFieldMessenger.Get() == nullptr) { 338 // Create global magnetic field messenger. 339 // Uniform magnetic field is then created automatically if 340 // the field value is not zero. 341 G4ThreeVector fieldValue = G4ThreeVector(); 342 G4GlobalMagFieldMessenger* msg = new G4GlobalMagFieldMessenger(fieldValue); 343 // msg->SetVerboseLevel(1); 344 G4AutoDelete::Register(msg); 345 fFieldMessenger.Put(msg); 346 } 347 } 348 349 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 350