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 B4/B4d/src/DetectorConstruction.cc 28 /// \brief Implementation of the B4d::DetectorConstruction class 29 30 #include "DetectorConstruction.hh" 31 32 #include "G4AutoDelete.hh" 33 #include "G4Box.hh" 34 #include "G4Colour.hh" 35 #include "G4GlobalMagFieldMessenger.hh" 36 #include "G4LogicalVolume.hh" 37 #include "G4Material.hh" 38 #include "G4MultiFunctionalDetector.hh" 39 #include "G4NistManager.hh" 40 #include "G4PSEnergyDeposit.hh" 41 #include "G4PSTrackLength.hh" 42 #include "G4PVPlacement.hh" 43 #include "G4PVReplica.hh" 44 #include "G4PhysicalConstants.hh" 45 #include "G4SDChargedFilter.hh" 46 #include "G4SDManager.hh" 47 #include "G4SystemOfUnits.hh" 48 #include "G4VPrimitiveScorer.hh" 49 #include "G4VisAttributes.hh" 50 51 namespace B4d 52 { 53 54 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 55 56 G4ThreadLocal G4GlobalMagFieldMessenger* DetectorConstruction::fMagFieldMessenger = nullptr; 57 58 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 59 60 G4VPhysicalVolume* DetectorConstruction::Construct() 61 { 62 // Define materials 63 DefineMaterials(); 64 65 // Define volumes 66 return DefineVolumes(); 67 } 68 69 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 70 71 void DetectorConstruction::DefineMaterials() 72 { 73 // Lead material defined using NIST Manager 74 auto nistManager = G4NistManager::Instance(); 75 nistManager->FindOrBuildMaterial("G4_Pb"); 76 77 // Liquid argon material 78 G4double a; // mass of a mole; 79 G4double z; // z=mean number of protons; 80 G4double density; 81 new G4Material("liquidArgon", z = 18., a = 39.95 * g / mole, density = 1.390 * g / cm3); 82 // The argon by NIST Manager is a gas with a different density 83 84 // Vacuum 85 new G4Material("Galactic", z = 1., a = 1.01 * g / mole, density = universe_mean_density, 86 kStateGas, 2.73 * kelvin, 3.e-18 * pascal); 87 88 // Print materials 89 G4cout << *(G4Material::GetMaterialTable()) << G4endl; 90 } 91 92 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 93 94 G4VPhysicalVolume* DetectorConstruction::DefineVolumes() 95 { 96 // Geometry parameters 97 G4int nofLayers = 10; 98 G4double absoThickness = 10. * mm; 99 G4double gapThickness = 5. * mm; 100 G4double calorSizeXY = 10. * cm; 101 102 auto layerThickness = absoThickness + gapThickness; 103 auto calorThickness = nofLayers * layerThickness; 104 auto worldSizeXY = 1.2 * calorSizeXY; 105 auto worldSizeZ = 1.2 * calorThickness; 106 107 // Get materials 108 auto defaultMaterial = G4Material::GetMaterial("Galactic"); 109 auto absorberMaterial = G4Material::GetMaterial("G4_Pb"); 110 auto gapMaterial = G4Material::GetMaterial("liquidArgon"); 111 112 if (!defaultMaterial || !absorberMaterial || !gapMaterial) { 113 G4ExceptionDescription msg; 114 msg << "Cannot retrieve materials already defined."; 115 G4Exception("DetectorConstruction::DefineVolumes()", "MyCode0001", FatalException, msg); 116 } 117 118 // 119 // World 120 // 121 auto worldS = new G4Box("World", // its name 122 worldSizeXY / 2, worldSizeXY / 2, worldSizeZ / 2); // its size 123 124 auto worldLV = new G4LogicalVolume(worldS, // its solid 125 defaultMaterial, // its material 126 "World"); // its name 127 128 auto worldPV = new G4PVPlacement(nullptr, // no rotation 129 G4ThreeVector(), // at (0,0,0) 130 worldLV, // its logical volume 131 "World", // its name 132 nullptr, // its mother volume 133 false, // no boolean operation 134 0, // copy number 135 fCheckOverlaps); // checking overlaps 136 137 // 138 // Calorimeter 139 // 140 auto calorimeterS = new G4Box("Calorimeter", // its name 141 calorSizeXY / 2, calorSizeXY / 2, calorThickness / 2); // its size 142 143 auto calorLV = new G4LogicalVolume(calorimeterS, // its solid 144 defaultMaterial, // its material 145 "Calorimeter"); // its name 146 147 new G4PVPlacement(nullptr, // no rotation 148 G4ThreeVector(), // at (0,0,0) 149 calorLV, // its logical volume 150 "Calorimeter", // its name 151 worldLV, // its mother volume 152 false, // no boolean operation 153 0, // copy number 154 fCheckOverlaps); // checking overlaps 155 156 // 157 // Layer 158 // 159 auto layerS = new G4Box("Layer", // its name 160 calorSizeXY / 2, calorSizeXY / 2, layerThickness / 2); // its size 161 162 auto layerLV = new G4LogicalVolume(layerS, // its solid 163 defaultMaterial, // its material 164 "Layer"); // its name 165 166 new G4PVReplica("Layer", // its name 167 layerLV, // its logical volume 168 calorLV, // its mother 169 kZAxis, // axis of replication 170 nofLayers, // number of replica 171 layerThickness); // witdth of replica 172 173 // 174 // Absorber 175 // 176 auto absorberS = new G4Box("Abso", // its name 177 calorSizeXY / 2, calorSizeXY / 2, absoThickness / 2); // its size 178 179 auto absorberLV = new G4LogicalVolume(absorberS, // its solid 180 absorberMaterial, // its material 181 "AbsoLV"); // its name 182 183 new G4PVPlacement(nullptr, // no rotation 184 G4ThreeVector(0., 0., -gapThickness / 2), // its position 185 absorberLV, // its logical volume 186 "Abso", // its name 187 layerLV, // its mother volume 188 false, // no boolean operation 189 0, // copy number 190 fCheckOverlaps); // checking overlaps 191 192 // 193 // Gap 194 // 195 auto gapS = new G4Box("Gap", // its name 196 calorSizeXY / 2, calorSizeXY / 2, gapThickness / 2); // its size 197 198 auto gapLV = new G4LogicalVolume(gapS, // its solid 199 gapMaterial, // its material 200 "GapLV"); // its name 201 202 new G4PVPlacement(nullptr, // no rotation 203 G4ThreeVector(0., 0., absoThickness / 2), // its position 204 gapLV, // its logical volume 205 "Gap", // its name 206 layerLV, // its mother volume 207 false, // no boolean operation 208 0, // copy number 209 fCheckOverlaps); // checking overlaps 210 211 // 212 // print parameters 213 // 214 G4cout << G4endl << "------------------------------------------------------------" << G4endl 215 << "---> The calorimeter is " << nofLayers << " layers of: [ " << absoThickness / mm 216 << "mm of " << absorberMaterial->GetName() << " + " << gapThickness / mm << "mm of " 217 << gapMaterial->GetName() << " ] " << G4endl 218 << "------------------------------------------------------------" << G4endl; 219 220 // 221 // Visualization attributes 222 // 223 worldLV->SetVisAttributes(G4VisAttributes::GetInvisible()); 224 calorLV->SetVisAttributes(G4VisAttributes(G4Colour::White())); 225 226 // 227 // Always return the physical World 228 // 229 return worldPV; 230 } 231 232 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 233 234 void DetectorConstruction::ConstructSDandField() 235 { 236 G4SDManager::GetSDMpointer()->SetVerboseLevel(1); 237 // 238 // Scorers 239 // 240 241 // declare Absorber as a MultiFunctionalDetector scorer 242 // 243 auto absDetector = new G4MultiFunctionalDetector("Absorber"); 244 G4SDManager::GetSDMpointer()->AddNewDetector(absDetector); 245 246 G4VPrimitiveScorer* primitive; 247 primitive = new G4PSEnergyDeposit("Edep"); 248 absDetector->RegisterPrimitive(primitive); 249 250 primitive = new G4PSTrackLength("TrackLength"); 251 auto charged = new G4SDChargedFilter("chargedFilter"); 252 primitive->SetFilter(charged); 253 absDetector->RegisterPrimitive(primitive); 254 255 SetSensitiveDetector("AbsoLV", absDetector); 256 257 // declare Gap as a MultiFunctionalDetector scorer 258 // 259 auto gapDetector = new G4MultiFunctionalDetector("Gap"); 260 G4SDManager::GetSDMpointer()->AddNewDetector(gapDetector); 261 262 primitive = new G4PSEnergyDeposit("Edep"); 263 gapDetector->RegisterPrimitive(primitive); 264 265 primitive = new G4PSTrackLength("TrackLength"); 266 primitive->SetFilter(charged); 267 gapDetector->RegisterPrimitive(primitive); 268 269 SetSensitiveDetector("GapLV", gapDetector); 270 271 // 272 // Magnetic field 273 // 274 // Create global magnetic field messenger. 275 // Uniform magnetic field is then created automatically if 276 // the field value is not zero. 277 G4ThreeVector fieldValue; 278 fMagFieldMessenger = new G4GlobalMagFieldMessenger(fieldValue); 279 fMagFieldMessenger->SetVerboseLevel(1); 280 281 // Register the field messenger for deleting 282 G4AutoDelete::Register(fMagFieldMessenger); 283 } 284 285 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 286 287 } // namespace B4d 288