// // ******************************************************************** // * License and Disclaimer * // * * // * The Geant4 software is copyright of the Copyright Holders of * // * the Geant4 Collaboration. It is provided under the terms and * // * conditions of the Geant4 Software License, included in the file * // * LICENSE and available at http://cern.ch/geant4/license . These * // * include a list of copyright holders. * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. Please see the license in the file LICENSE and URL above * // * for the full disclaimer and the limitation of liability. * // * * // * This code implementation is the result of the scientific and * // * technical work of the GEANT4 collaboration. * // * By using, copying, modifying or distributing the software (or * // * any work based on the software) you agree to acknowledge its * // * use in resulting scientific publications, and indicate your * // * acceptance of all terms of the Geant4 Software license. * // ******************************************************************** // // /// \file B2/B2a/src/DetectorConstruction.cc /// \brief Implementation of the B2a::DetectorConstruction class #include "DetectorConstruction.hh" #include "DetectorMessenger.hh" #include "detectorSD.hh" #include "G4Material.hh" #include "G4NistManager.hh" #include "G4SDManager.hh" #include "G4Box.hh" #include "G4Tubs.hh" #include "G4LogicalVolume.hh" #include "G4PVPlacement.hh" #include "G4GlobalMagFieldMessenger.hh" #include "G4AutoDelete.hh" #include "G4Trd.hh" #include "G4GeometryTolerance.hh" #include "G4GeometryManager.hh" #include "G4UserLimits.hh" #include "G4VisAttributes.hh" #include "G4Colour.hh" #include "G4SystemOfUnits.hh" using namespace B2; namespace B2a { //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4ThreadLocal G4GlobalMagFieldMessenger* DetectorConstruction::fMagFieldMessenger = nullptr; DetectorConstruction::DetectorConstruction() { fMessenger = new DetectorMessenger(this); fLogicTargets = new G4LogicalVolume*[fNbOfTargets]; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... DetectorConstruction::~DetectorConstruction() { delete [] fLogicDetector; delete fStepLimit; delete fMessenger; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4VPhysicalVolume* DetectorConstruction::Construct() { // Define materials DefineMaterials(); // Define volumes return DefineVolumes(); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void DetectorConstruction::DefineMaterials() { // Material definition G4NistManager* nistManager = G4NistManager::Instance(); // Air defined using NIST Manager nistManager->FindOrBuildMaterial("G4_AIR"); // Lead defined using NIST Manager G4Isotope* Li6 = new G4Isotope("6Li", 3, 6, 6.015 * g / mole); G4Element* el6Li = new G4Element("6Li", "Li", 1);; el6Li->AddIsotope(Li6, 1); G4Element* elF = nistManager->FindOrBuildElement("F"); /*G4double LiFdensity = 2.635 * g / cm3; G4Material* isotope_6LiF = new G4Material("6LiF", LiFdensity, 2); isotope_6LiF->AddElement(el6Li, 1); isotope_6LiF->AddElement(elF, 1); fTargetMaterial = nistManager->FindOrBuildMaterial("6LiF");*/ G4Isotope* B10 = new G4Isotope("B10", 5, 10, 10.012937 * g / mole); G4Element* elB10 = new G4Element("B10", "B", 1); elB10->AddIsotope(B10, 1); G4double B10density = 2.34 * g / cm3; G4Material* matB10 = new G4Material("B10", B10density, 1); matB10->AddElement(elB10, 1); fTargetMaterial = nistManager->FindOrBuildMaterial("B10"); // SiC defined using NIST Manager G4Element* elSi = nistManager->FindOrBuildElement("Si"); G4Element* elC = nistManager->FindOrBuildElement("C"); G4double density = 3.17 * g / cm3; G4Material* SiC = new G4Material("SiC", density, 2); SiC->AddElement(elSi, 1); SiC->AddElement(elC, 1); fDetectorMaterial = nistManager->FindOrBuildMaterial("SiC"); // Print materials G4cout << *(G4Material::GetMaterialTable()) << G4endl; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4VPhysicalVolume* DetectorConstruction::DefineVolumes() { G4Material* air = G4Material::GetMaterial("G4_AIR"); // Sizes of the principal geometrical components (solids) G4double TargetSpacing = 0*um; // from Target center to center! G4double DetectorWidth = 4*mm; // width of the Detectors G4double DetectorDepth = 500*um; // depth of the Detectors G4double targetDepth = 100*um; // full length of Target // G4double trackerLength = (fNbOfTargets+1)*TargetSpacing; G4double worldLength = 1.5 * DetectorWidth; G4double worldDepth = 60*cm; G4double targetWidth = DetectorWidth; // targetDepth = 0.5*targetDepth; // Half length of the Target // G4double trackerSize = 0.5*trackerLength; // Half length of the Tracker // Definitions of Solids, Logical Volumes, Physical Volumes // World G4GeometryManager::GetInstance()->SetWorldMaximumExtent(worldLength); G4cout << "Computed tolerance = " << G4GeometryTolerance::GetInstance()->GetSurfaceTolerance()/mm << " mm" << G4endl; auto worldS = new G4Box("world", // its name worldLength / 2, worldLength / 2, worldDepth / 2); // its size auto worldLV = new G4LogicalVolume(worldS, // its solid air, // its material "World"); // its name // Must place the World Physical volume unrotated at (0,0,0). // auto worldPV = new G4PVPlacement(nullptr, // no rotation G4ThreeVector(), // at (0,0,0) worldLV, // its logical volume "World", // its name nullptr, // its mother volume false, // no boolean operations 0, // copy number fCheckOverlaps); // checking overlaps // Target G4ThreeVector positionDetector = G4ThreeVector(0,0,0); // Tracker /* G4ThreeVector positionTracker = G4ThreeVector(0,0,0); auto trackerS = new G4Tubs("tracker", 0, trackerSize, trackerSize, 0. * deg, 360. * deg); auto trackerLV = new G4LogicalVolume(trackerS, air, "Tracker", nullptr, nullptr, nullptr); new G4PVPlacement(nullptr, // no rotation positionTracker, // at (x,y,z) trackerLV, // its logical volume "Tracker", // its name worldLV, // its mother volume false, // no boolean operations 0, // copy number fCheckOverlaps); // checking overlaps */ // Visualization attributes G4VisAttributes boxVisAtt(G4Colour::White()); G4VisAttributes DetectorVisAtt(G4Colour::Yellow()); G4VisAttributes TargetVisAtt(G4Colour::Blue()); worldLV ->SetVisAttributes(boxVisAtt); // trackerLV ->SetVisAttributes(boxVisAtt); // Tracker segments G4double firstPosition = -DetectorWidth/2 + TargetSpacing+targetWidth/2; fNbOfTargets = 0; auto DetectorS = new G4Box("Detector", DetectorWidth/2 , DetectorWidth / 2, DetectorDepth/2); fLogicDetector = new G4LogicalVolume(DetectorS, fDetectorMaterial, "Detector", nullptr, nullptr, nullptr); new G4PVPlacement(nullptr, // no rotation positionDetector, // at (x,y,z) fLogicDetector, // its logical volume "Detector", // its name worldLV, // its mother volume false, // no boolean operations 0, // copy number fCheckOverlaps); // checking overlaps fLogicDetector->SetVisAttributes(DetectorVisAtt); G4cout << "Detector is " << DetectorDepth/um << " um of " << fDetectorMaterial->GetName() << G4endl; auto targetS = new G4Box("Target", 0.5 * DetectorWidth, 0.5 * targetWidth, 0.5 * targetDepth); G4double Zposition = DetectorDepth/2 - targetDepth*0.5; for (G4int copyNo=0; copyNo<1; copyNo++) { G4double Yposition = firstPosition + copyNo * TargetSpacing; G4ThreeVector TargetPosition(0, Yposition, Zposition); fLogicTargets[copyNo] = new G4LogicalVolume(targetS, fTargetMaterial, "target_LV", nullptr, nullptr, nullptr); new G4PVPlacement(nullptr, // no rotation TargetPosition, // at (x,y,z) fLogicTargets[copyNo], // its logical volume "target_PV", // its name fLogicDetector, // its mother volume false, // no boolean operations copyNo, // copy number fCheckOverlaps); // checking overlaps G4double targetmaxStep = 0.5*targetWidth; fStepLimit = new G4UserLimits(targetmaxStep); fLogicTargets[copyNo]->SetUserLimits(fStepLimit); // fLogicTargets[copyNo]->SetVisAttributes(TargetVisAtt); fNbOfTargets = copyNo + 1; } G4cout << "There are " << fNbOfTargets << " targets in the tracker region. " << G4endl << "The Targets are " << targetWidth / um << " um of " << fDetectorMaterial->GetName() << G4endl << "The distance between targets is " << TargetSpacing / um << " um" << G4endl; // Example of User Limits // // Below is an example of how to set tracking constraints in a given // logical volume // // Sets a max step length in the tracker region, with G4StepLimiter G4double WorldmaxStep = 0.5 * targetDepth; fStepLimit = new G4UserLimits(WorldmaxStep); worldLV->SetUserLimits(fStepLimit); G4double DetectormaxStep = 0.5 * targetDepth; fStepLimit = new G4UserLimits(DetectormaxStep); fLogicDetector->SetUserLimits(fStepLimit); G4double TargetmaxStep = 0.5 * targetDepth; fStepLimit = new G4UserLimits(DetectormaxStep); fLogicTargets[0]->SetUserLimits(fStepLimit); /// Set additional contraints on the track, with G4UserSpecialCuts /// /// G4double maxLength = 2*trackerLength, maxTime = 0.1*ns, minEkin = 10*MeV; /// trackerLV->SetUserLimits(new G4UserLimits(maxStep, /// maxLength, /// maxTime, /// minEkin)); // Always return the physical world return worldPV; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void DetectorConstruction::ConstructSDandField() { // Sensitive detectors G4String DetectorSDname = "/DetectorSD"; auto adetectorSD = new detectorSD(DetectorSDname, "DetectorHitsCollection"); G4SDManager::GetSDMpointer()->AddNewDetector(adetectorSD); // Setting adetectorSD to all logical volumes with the same name // of "Detector_LV". SetSensitiveDetector("Detector", adetectorSD, true); // Create global magnetic field messenger. // Uniform magnetic field is then created automatically if // the field value is not zero. G4ThreeVector fieldValue = G4ThreeVector(); fMagFieldMessenger = new G4GlobalMagFieldMessenger(fieldValue); fMagFieldMessenger->SetVerboseLevel(1); // Register the field messenger for deleting G4AutoDelete::Register(fMagFieldMessenger); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void DetectorConstruction::SetTargetMaterial(G4String materialName) { G4NistManager* nistManager = G4NistManager::Instance(); G4Material* pttoMaterial = nistManager->FindOrBuildMaterial(materialName); if (fTargetMaterial != pttoMaterial) { if ( pttoMaterial ) { fTargetMaterial = pttoMaterial; if (fLogicTargets) for(G4int copyNo = 0; copyNo < fNbOfTargets; copyNo++) fLogicTargets[copyNo]->SetMaterial(fTargetMaterial); G4cout << G4endl << "----> The target is made of " << materialName << G4endl; } else { G4cout << G4endl << "--> WARNING from SetTargetMaterial : " << materialName << " not found" << G4endl; } } } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void DetectorConstruction::SetDetectorMaterial(G4String materialName) { G4NistManager* nistManager = G4NistManager::Instance(); G4Material* pttoMaterial = nistManager->FindOrBuildMaterial(materialName); if (fDetectorMaterial != pttoMaterial) { if ( pttoMaterial ) { fDetectorMaterial = pttoMaterial; fLogicDetector-> SetMaterial(fDetectorMaterial); } G4cout << G4endl << "----> The Detectors are made of " << materialName << G4endl; } else { G4cout << G4endl << "--> WARNING from SetDetectorMaterial : " << materialName << " not found" << G4endl; } } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void DetectorConstruction::SetMaxStep(G4double maxStep) { if ((fStepLimit)&&(maxStep>0.)) fStepLimit->SetMaxAllowedStep(maxStep); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void DetectorConstruction::SetCheckOverlaps(G4bool checkOverlaps) { fCheckOverlaps = checkOverlaps; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... }