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 B2/B2a/src/DetectorConstruction.cc 28 /// \brief Implementation of the B2a::DetectorConstruction class 29 30 #include "DetectorConstruction.hh" 31 32 #include "DetectorMessenger.hh" 33 #include "TrackerSD.hh" 34 35 #include "G4AutoDelete.hh" 36 #include "G4Box.hh" 37 #include "G4Colour.hh" 38 #include "G4GeometryManager.hh" 39 #include "G4GeometryTolerance.hh" 40 #include "G4GlobalMagFieldMessenger.hh" 41 #include "G4LogicalVolume.hh" 42 #include "G4Material.hh" 43 #include "G4NistManager.hh" 44 #include "G4PVPlacement.hh" 45 #include "G4SDManager.hh" 46 #include "G4SystemOfUnits.hh" 47 #include "G4Tubs.hh" 48 #include "G4UserLimits.hh" 49 #include "G4VisAttributes.hh" 50 51 using namespace B2; 52 53 namespace B2a 54 { 55 56 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 57 58 G4ThreadLocal G4GlobalMagFieldMessenger* DetectorConstruction::fMagFieldMessenger = nullptr; 59 60 DetectorConstruction::DetectorConstruction() 61 { 62 fMessenger = new DetectorMessenger(this); 63 64 fNbOfChambers = 5; 65 fLogicChamber = new G4LogicalVolume*[fNbOfChambers]; 66 } 67 68 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 69 70 DetectorConstruction::~DetectorConstruction() 71 { 72 delete[] fLogicChamber; 73 delete fStepLimit; 74 delete fMessenger; 75 } 76 77 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 78 79 G4VPhysicalVolume* DetectorConstruction::Construct() 80 { 81 // Define materials 82 DefineMaterials(); 83 84 // Define volumes 85 return DefineVolumes(); 86 } 87 88 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 89 90 void DetectorConstruction::DefineMaterials() 91 { 92 // Material definition 93 94 G4NistManager* nistManager = G4NistManager::Instance(); 95 96 // Air defined using NIST Manager 97 nistManager->FindOrBuildMaterial("G4_AIR"); 98 99 // Lead defined using NIST Manager 100 fTargetMaterial = nistManager->FindOrBuildMaterial("G4_Pb"); 101 102 // Xenon gas defined using NIST Manager 103 fChamberMaterial = nistManager->FindOrBuildMaterial("G4_Xe"); 104 105 // Print materials 106 G4cout << *(G4Material::GetMaterialTable()) << G4endl; 107 } 108 109 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 110 111 G4VPhysicalVolume* DetectorConstruction::DefineVolumes() 112 { 113 G4Material* air = G4Material::GetMaterial("G4_AIR"); 114 115 // Sizes of the principal geometrical components (solids) 116 117 G4double chamberSpacing = 80 * cm; // from chamber center to center! 118 119 G4double chamberWidth = 20.0 * cm; // width of the chambers 120 G4double targetLength = 5.0 * cm; // full length of Target 121 122 G4double trackerLength = (fNbOfChambers + 1) * chamberSpacing; 123 124 G4double worldLength = 1.2 * (2 * targetLength + trackerLength); 125 126 G4double targetRadius = 0.5 * targetLength; // Radius of Target 127 targetLength = 0.5 * targetLength; // Half length of the Target 128 G4double trackerSize = 0.5 * trackerLength; // Half length of the Tracker 129 130 // Definitions of Solids, Logical Volumes, Physical Volumes 131 132 // World 133 134 G4GeometryManager::GetInstance()->SetWorldMaximumExtent(worldLength); 135 136 G4cout << "Computed tolerance = " 137 << G4GeometryTolerance::GetInstance()->GetSurfaceTolerance() / mm << " mm" << G4endl; 138 139 auto worldS = new G4Box("world", // its name 140 worldLength / 2, worldLength / 2, worldLength / 2); // its size 141 auto worldLV = new G4LogicalVolume(worldS, // its solid 142 air, // its material 143 "World"); // its name 144 145 // Must place the World Physical volume unrotated at (0,0,0). 146 // 147 auto worldPV = new G4PVPlacement(nullptr, // no rotation 148 G4ThreeVector(), // at (0,0,0) 149 worldLV, // its logical volume 150 "World", // its name 151 nullptr, // its mother volume 152 false, // no boolean operations 153 0, // copy number 154 fCheckOverlaps); // checking overlaps 155 156 // Target 157 158 G4ThreeVector positionTarget = G4ThreeVector(0, 0, -(targetLength + trackerSize)); 159 160 auto targetS = new G4Tubs("target", 0., targetRadius, targetLength, 0. * deg, 360. * deg); 161 fLogicTarget = new G4LogicalVolume(targetS, fTargetMaterial, "Target", nullptr, nullptr, nullptr); 162 new G4PVPlacement(nullptr, // no rotation 163 positionTarget, // at (x,y,z) 164 fLogicTarget, // its logical volume 165 "Target", // its name 166 worldLV, // its mother volume 167 false, // no boolean operations 168 0, // copy number 169 fCheckOverlaps); // checking overlaps 170 171 G4cout << "Target is " << 2 * targetLength / cm << " cm of " << fTargetMaterial->GetName() 172 << G4endl; 173 174 // Tracker 175 176 G4ThreeVector positionTracker = G4ThreeVector(0, 0, 0); 177 178 auto trackerS = new G4Tubs("tracker", 0, trackerSize, trackerSize, 0. * deg, 360. * deg); 179 auto trackerLV = new G4LogicalVolume(trackerS, air, "Tracker", nullptr, nullptr, nullptr); 180 new G4PVPlacement(nullptr, // no rotation 181 positionTracker, // at (x,y,z) 182 trackerLV, // its logical volume 183 "Tracker", // its name 184 worldLV, // its mother volume 185 false, // no boolean operations 186 0, // copy number 187 fCheckOverlaps); // checking overlaps 188 189 // Visualization attributes 190 191 G4VisAttributes boxVisAtt(G4Colour::White()); 192 G4VisAttributes chamberVisAtt(G4Colour::Yellow()); 193 194 worldLV->SetVisAttributes(boxVisAtt); 195 fLogicTarget->SetVisAttributes(boxVisAtt); 196 trackerLV->SetVisAttributes(boxVisAtt); 197 198 // Tracker segments 199 200 G4cout << "There are " << fNbOfChambers << " chambers in the tracker region. " << G4endl 201 << "The chambers are " << chamberWidth / cm << " cm of " << fChamberMaterial->GetName() 202 << G4endl << "The distance between chamber is " << chamberSpacing / cm << " cm" << G4endl; 203 204 G4double firstPosition = -trackerSize + chamberSpacing; 205 G4double firstLength = trackerLength / 10; 206 G4double lastLength = trackerLength; 207 208 G4double halfWidth = 0.5 * chamberWidth; 209 G4double rmaxFirst = 0.5 * firstLength; 210 211 G4double rmaxIncr = 0.0; 212 if (fNbOfChambers > 0) { 213 rmaxIncr = 0.5 * (lastLength - firstLength) / (fNbOfChambers - 1); 214 if (chamberSpacing < chamberWidth) { 215 G4Exception("DetectorConstruction::DefineVolumes()", "InvalidSetup", FatalException, 216 "Width>Spacing"); 217 } 218 } 219 220 for (G4int copyNo = 0; copyNo < fNbOfChambers; copyNo++) { 221 G4double Zposition = firstPosition + copyNo * chamberSpacing; 222 G4double rmax = rmaxFirst + copyNo * rmaxIncr; 223 224 auto chamberS = new G4Tubs("Chamber_solid", 0, rmax, halfWidth, 0. * deg, 360. * deg); 225 226 fLogicChamber[copyNo] = 227 new G4LogicalVolume(chamberS, fChamberMaterial, "Chamber_LV", nullptr, nullptr, nullptr); 228 229 fLogicChamber[copyNo]->SetVisAttributes(chamberVisAtt); 230 231 new G4PVPlacement(nullptr, // no rotation 232 G4ThreeVector(0, 0, Zposition), // at (x,y,z) 233 fLogicChamber[copyNo], // its logical volume 234 "Chamber_PV", // its name 235 trackerLV, // its mother volume 236 false, // no boolean operations 237 copyNo, // copy number 238 fCheckOverlaps); // checking overlaps 239 } 240 241 // Example of User Limits 242 // 243 // Below is an example of how to set tracking constraints in a given 244 // logical volume 245 // 246 // Sets a max step length in the tracker region, with G4StepLimiter 247 248 G4double maxStep = 0.5 * chamberWidth; 249 fStepLimit = new G4UserLimits(maxStep); 250 trackerLV->SetUserLimits(fStepLimit); 251 252 /// Set additional contraints on the track, with G4UserSpecialCuts 253 /// 254 /// G4double maxLength = 2*trackerLength, maxTime = 0.1*ns, minEkin = 10*MeV; 255 /// trackerLV->SetUserLimits(new G4UserLimits(maxStep, 256 /// maxLength, 257 /// maxTime, 258 /// minEkin)); 259 260 // Always return the physical world 261 262 return worldPV; 263 } 264 265 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 266 267 void DetectorConstruction::ConstructSDandField() 268 { 269 // Sensitive detectors 270 271 G4String trackerChamberSDname = "/TrackerChamberSD"; 272 auto trackerSD = new TrackerSD(trackerChamberSDname, "TrackerHitsCollection"); 273 G4SDManager::GetSDMpointer()->AddNewDetector(trackerSD); 274 // Setting trackerSD to all logical volumes with the same name 275 // of "Chamber_LV". 276 SetSensitiveDetector("Chamber_LV", trackerSD, true); 277 278 // Create global magnetic field messenger. 279 // Uniform magnetic field is then created automatically if 280 // the field value is not zero. 281 G4ThreeVector fieldValue = G4ThreeVector(); 282 fMagFieldMessenger = new G4GlobalMagFieldMessenger(fieldValue); 283 fMagFieldMessenger->SetVerboseLevel(1); 284 285 // Register the field messenger for deleting 286 G4AutoDelete::Register(fMagFieldMessenger); 287 } 288 289 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 290 291 void DetectorConstruction::SetTargetMaterial(G4String materialName) 292 { 293 G4NistManager* nistManager = G4NistManager::Instance(); 294 295 G4Material* pttoMaterial = nistManager->FindOrBuildMaterial(materialName); 296 297 if (fTargetMaterial != pttoMaterial) { 298 if (pttoMaterial) { 299 fTargetMaterial = pttoMaterial; 300 if (fLogicTarget) fLogicTarget->SetMaterial(fTargetMaterial); 301 G4cout << G4endl << "----> The target is made of " << materialName << G4endl; 302 } 303 else { 304 G4cout << G4endl << "--> WARNING from SetTargetMaterial : " << materialName << " not found" 305 << G4endl; 306 } 307 } 308 } 309 310 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 311 312 void DetectorConstruction::SetChamberMaterial(G4String materialName) 313 { 314 G4NistManager* nistManager = G4NistManager::Instance(); 315 316 G4Material* pttoMaterial = nistManager->FindOrBuildMaterial(materialName); 317 318 if (fChamberMaterial != pttoMaterial) { 319 if (pttoMaterial) { 320 fChamberMaterial = pttoMaterial; 321 for (G4int copyNo = 0; copyNo < fNbOfChambers; copyNo++) { 322 if (fLogicChamber[copyNo]) fLogicChamber[copyNo]->SetMaterial(fChamberMaterial); 323 } 324 G4cout << G4endl << "----> The chambers are made of " << materialName << G4endl; 325 } 326 else { 327 G4cout << G4endl << "--> WARNING from SetChamberMaterial : " << materialName << " not found" 328 << G4endl; 329 } 330 } 331 } 332 333 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 334 335 void DetectorConstruction::SetMaxStep(G4double maxStep) 336 { 337 if ((fStepLimit) && (maxStep > 0.)) fStepLimit->SetMaxAllowedStep(maxStep); 338 } 339 340 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 341 342 void DetectorConstruction::SetCheckOverlaps(G4bool checkOverlaps) 343 { 344 fCheckOverlaps = checkOverlaps; 345 } 346 347 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 348 349 } // namespace B2a