Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 09:22:50

0001 //
0002 // ********************************************************************
0003 // * License and Disclaimer                                           *
0004 // *                                                                  *
0005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
0006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
0007 // * conditions of the Geant4 Software License,  included in the file *
0008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
0009 // * include a list of copyright holders.                             *
0010 // *                                                                  *
0011 // * Neither the authors of this software system, nor their employing *
0012 // * institutes,nor the agencies providing financial support for this *
0013 // * work  make  any representation or  warranty, express or implied, *
0014 // * regarding  this  software system or assume any liability for its *
0015 // * use.  Please see the license in the file  LICENSE  and URL above *
0016 // * for the full disclaimer and the limitation of liability.         *
0017 // *                                                                  *
0018 // * This  code  implementation is the result of  the  scientific and *
0019 // * technical work of the GEANT4 collaboration.                      *
0020 // * By using,  copying,  modifying or  distributing the software (or *
0021 // * any work based  on the software)  you  agree  to acknowledge its *
0022 // * use  in  resulting  scientific  publications,  and indicate your *
0023 // * acceptance of all terms of the Geant4 Software license.          *
0024 // ********************************************************************
0025 //
0026 //
0027 /// \file B2/B2b/src/DetectorConstruction.cc
0028 /// \brief Implementation of the B2b::DetectorConstruction class
0029 
0030 #include "DetectorConstruction.hh"
0031 
0032 #include "ChamberParameterisation.hh"
0033 #include "DetectorMessenger.hh"
0034 #include "TrackerSD.hh"
0035 
0036 #include "G4AutoDelete.hh"
0037 #include "G4Box.hh"
0038 #include "G4Colour.hh"
0039 #include "G4GeometryManager.hh"
0040 #include "G4GeometryTolerance.hh"
0041 #include "G4GlobalMagFieldMessenger.hh"
0042 #include "G4LogicalVolume.hh"
0043 #include "G4Material.hh"
0044 #include "G4NistManager.hh"
0045 #include "G4PVParameterised.hh"
0046 #include "G4PVPlacement.hh"
0047 #include "G4SDManager.hh"
0048 #include "G4SystemOfUnits.hh"
0049 #include "G4ThreeVector.hh"
0050 #include "G4Tubs.hh"
0051 #include "G4UserLimits.hh"
0052 #include "G4VisAttributes.hh"
0053 
0054 using namespace B2;
0055 
0056 namespace B2b
0057 {
0058 
0059 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0060 
0061 G4ThreadLocal G4GlobalMagFieldMessenger* DetectorConstruction::fMagFieldMessenger = nullptr;
0062 
0063 DetectorConstruction::DetectorConstruction()
0064 {
0065   fMessenger = new DetectorMessenger(this);
0066 }
0067 
0068 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0069 
0070 DetectorConstruction::~DetectorConstruction()
0071 {
0072   delete fStepLimit;
0073   delete fMessenger;
0074 }
0075 
0076 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0077 
0078 G4VPhysicalVolume* DetectorConstruction::Construct()
0079 {
0080   // Define materials
0081   DefineMaterials();
0082 
0083   // Define volumes
0084   return DefineVolumes();
0085 }
0086 
0087 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0088 
0089 void DetectorConstruction::DefineMaterials()
0090 {
0091   // Material definition
0092 
0093   G4NistManager* nistManager = G4NistManager::Instance();
0094 
0095   // Air defined using NIST Manager
0096   nistManager->FindOrBuildMaterial("G4_AIR");
0097 
0098   // Lead defined using NIST Manager
0099   fTargetMaterial = nistManager->FindOrBuildMaterial("G4_Pb");
0100 
0101   // Xenon gas defined using NIST Manager
0102   fChamberMaterial = nistManager->FindOrBuildMaterial("G4_Xe");
0103 
0104   // Print materials
0105   G4cout << *(G4Material::GetMaterialTable()) << G4endl;
0106 }
0107 
0108 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0109 
0110 G4VPhysicalVolume* DetectorConstruction::DefineVolumes()
0111 {
0112   G4Material* air = G4Material::GetMaterial("G4_AIR");
0113 
0114   // Sizes of the principal geometrical components (solids)
0115 
0116   G4int NbOfChambers = 5;
0117   G4double chamberSpacing = 80 * cm;  // from chamber center to center!
0118 
0119   G4double chamberWidth = 20.0 * cm;  // width of the chambers
0120   G4double targetLength = 5.0 * cm;  // full length of Target
0121 
0122   G4double trackerLength = (NbOfChambers + 1) * chamberSpacing;
0123 
0124   G4double worldLength = 1.2 * (2 * targetLength + trackerLength);
0125 
0126   G4double targetRadius = 0.5 * targetLength;  // Radius of Target
0127   targetLength = 0.5 * targetLength;  // Half length of the Target
0128   G4double trackerSize = 0.5 * trackerLength;  // Half length of the Tracker
0129 
0130   // Definitions of Solids, Logical Volumes, Physical Volumes
0131 
0132   // World
0133 
0134   G4GeometryManager::GetInstance()->SetWorldMaximumExtent(worldLength);
0135 
0136   G4cout << "Computed tolerance = "
0137          << G4GeometryTolerance::GetInstance()->GetSurfaceTolerance() / mm << " mm" << G4endl;
0138 
0139   auto worldS = new G4Box("world",  // its name
0140                           worldLength / 2, worldLength / 2, worldLength / 2);  // its size
0141   auto worldLV = new G4LogicalVolume(worldS,  // its solid
0142                                      air,  // its material
0143                                      "World");  // its name
0144 
0145   //  Must place the World Physical volume unrotated at (0,0,0).
0146   //
0147   auto worldPV = new G4PVPlacement(nullptr,  // no rotation
0148                                    G4ThreeVector(),  // at (0,0,0)
0149                                    worldLV,  // its logical volume
0150                                    "World",  // its name
0151                                    nullptr,  // its mother  volume
0152                                    false,  // no boolean operations
0153                                    0,  // copy number
0154                                    fCheckOverlaps);  // checking overlaps
0155 
0156   // Target
0157 
0158   G4ThreeVector positionTarget = G4ThreeVector(0, 0, -(targetLength + trackerSize));
0159 
0160   auto targetS = new G4Tubs("target", 0., targetRadius, targetLength, 0. * deg, 360. * deg);
0161   fLogicTarget = new G4LogicalVolume(targetS, fTargetMaterial, "Target", nullptr, nullptr, nullptr);
0162   new G4PVPlacement(nullptr,  // no rotation
0163                     positionTarget,  // at (x,y,z)
0164                     fLogicTarget,  // its logical volume
0165                     "Target",  // its name
0166                     worldLV,  // its mother volume
0167                     false,  // no boolean operations
0168                     0,  // copy number
0169                     fCheckOverlaps);  // checking overlaps
0170 
0171   G4cout << "Target is " << 2 * targetLength / cm << " cm of " << fTargetMaterial->GetName()
0172          << G4endl;
0173 
0174   // Tracker
0175 
0176   G4ThreeVector positionTracker = G4ThreeVector(0, 0, 0);
0177 
0178   auto trackerS = new G4Tubs("tracker", 0, trackerSize, trackerSize, 0. * deg, 360. * deg);
0179   auto trackerLV = new G4LogicalVolume(trackerS, air, "Tracker", nullptr, nullptr, nullptr);
0180   new G4PVPlacement(nullptr,  // no rotation
0181                     positionTracker,  // at (x,y,z)
0182                     trackerLV,  // its logical volume
0183                     "Tracker",  // its name
0184                     worldLV,  // its mother  volume
0185                     false,  // no boolean operations
0186                     0,  // copy number
0187                     fCheckOverlaps);  // checking overlaps
0188 
0189   // Tracker segments
0190 
0191   // An example of Parameterised volumes
0192   // Dummy values for G4Tubs -- modified by parameterised volume
0193 
0194   auto chamberS = new G4Tubs("tracker", 0, 100 * cm, 100 * cm, 0. * deg, 360. * deg);
0195   fLogicChamber =
0196     new G4LogicalVolume(chamberS, fChamberMaterial, "Chamber", nullptr, nullptr, nullptr);
0197 
0198   G4double firstPosition = -trackerSize + chamberSpacing;
0199   G4double firstLength = trackerLength / 10;
0200   G4double lastLength = trackerLength;
0201 
0202   G4VPVParameterisation* chamberParam =
0203     new ChamberParameterisation(NbOfChambers,  // NoChambers
0204                                 firstPosition,  // Z of center of first
0205                                 chamberSpacing,  // Z spacing of centers
0206                                 chamberWidth,  // chamber width
0207                                 firstLength,  // initial length
0208                                 lastLength);  // final length
0209 
0210   // dummy value : kZAxis -- modified by parameterised volume
0211 
0212   new G4PVParameterised("Chamber",  // their name
0213                         fLogicChamber,  // their logical volume
0214                         trackerLV,  // Mother logical volume
0215                         kZAxis,  // Are placed along this axis
0216                         NbOfChambers,  // Number of chambers
0217                         chamberParam,  // The parametrisation
0218                         fCheckOverlaps);  // checking overlaps
0219 
0220   G4cout << "There are " << NbOfChambers << " chambers in the tracker region. " << G4endl
0221          << "The chambers are " << chamberWidth / cm << " cm of " << fChamberMaterial->GetName()
0222          << G4endl << "The distance between chamber is " << chamberSpacing / cm << " cm" << G4endl;
0223 
0224   // Visualization attributes
0225 
0226   G4VisAttributes boxVisAtt(G4Colour::White());
0227 
0228   worldLV->SetVisAttributes(boxVisAtt);
0229   fLogicTarget->SetVisAttributes(boxVisAtt);
0230   trackerLV->SetVisAttributes(boxVisAtt);
0231 
0232   G4VisAttributes chamberVisAtt(G4Colour::Yellow());
0233   fLogicChamber->SetVisAttributes(chamberVisAtt);
0234 
0235   // Example of User Limits
0236   //
0237   // Below is an example of how to set tracking constraints in a given
0238   // logical volume
0239   //
0240   // Sets a max step length in the tracker region, with G4StepLimiter
0241 
0242   G4double maxStep = 0.5 * chamberWidth;
0243   fStepLimit = new G4UserLimits(maxStep);
0244   trackerLV->SetUserLimits(fStepLimit);
0245 
0246   /// Set additional contraints on the track, with G4UserSpecialCuts
0247   ///
0248   /// G4double maxLength = 2*trackerLength, maxTime = 0.1*ns, minEkin = 10*MeV;
0249   /// trackerLV->SetUserLimits(new G4UserLimits(maxStep,
0250   ///                                           maxLength,
0251   ///                                           maxTime,
0252   ///                                           minEkin));
0253 
0254   // Always return the physical world
0255 
0256   return worldPV;
0257 }
0258 
0259 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0260 
0261 void DetectorConstruction::ConstructSDandField()
0262 {
0263   // Sensitive detectors
0264 
0265   G4String trackerChamberSDname = "B2/TrackerChamberSD";
0266   auto trackerSD = new TrackerSD(trackerChamberSDname, "TrackerHitsCollection");
0267   G4SDManager::GetSDMpointer()->AddNewDetector(trackerSD);
0268   SetSensitiveDetector(fLogicChamber, trackerSD);
0269 
0270   // Create global magnetic field messenger.
0271   // Uniform magnetic field is then created automatically if
0272   // the field value is not zero.
0273   G4ThreeVector fieldValue = G4ThreeVector();
0274   fMagFieldMessenger = new G4GlobalMagFieldMessenger(fieldValue);
0275   fMagFieldMessenger->SetVerboseLevel(1);
0276 
0277   // Register the field messenger for deleting
0278   G4AutoDelete::Register(fMagFieldMessenger);
0279 }
0280 
0281 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0282 
0283 void DetectorConstruction::SetTargetMaterial(G4String materialName)
0284 {
0285   G4NistManager* nistManager = G4NistManager::Instance();
0286 
0287   G4Material* pttoMaterial = nistManager->FindOrBuildMaterial(materialName);
0288 
0289   if (fTargetMaterial != pttoMaterial) {
0290     if (pttoMaterial) {
0291       fTargetMaterial = pttoMaterial;
0292       if (fLogicTarget) fLogicTarget->SetMaterial(fTargetMaterial);
0293       G4cout << G4endl << "----> The target is made of " << materialName << G4endl;
0294     }
0295     else {
0296       G4cout << G4endl << "-->  WARNING from SetTargetMaterial : " << materialName << " not found"
0297              << G4endl;
0298     }
0299   }
0300 }
0301 
0302 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0303 
0304 void DetectorConstruction::SetChamberMaterial(G4String materialName)
0305 {
0306   G4NistManager* nistManager = G4NistManager::Instance();
0307 
0308   G4Material* pttoMaterial = nistManager->FindOrBuildMaterial(materialName);
0309 
0310   if (fChamberMaterial != pttoMaterial) {
0311     if (pttoMaterial) {
0312       fChamberMaterial = pttoMaterial;
0313       if (fLogicChamber) fLogicChamber->SetMaterial(fChamberMaterial);
0314       G4cout << G4endl << "----> The chambers are made of " << materialName << G4endl;
0315     }
0316     else {
0317       G4cout << G4endl << "-->  WARNING from SetChamberMaterial : " << materialName << " not found"
0318              << G4endl;
0319     }
0320   }
0321 }
0322 
0323 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0324 
0325 void DetectorConstruction::SetMaxStep(G4double maxStep)
0326 {
0327   if ((fStepLimit) && (maxStep > 0.)) fStepLimit->SetMaxAllowedStep(maxStep);
0328 }
0329 
0330 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0331 
0332 }  // namespace B2b