Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-03-30 07:50:12

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 /// \file DetectorConstruction.cc
0027 /// \brief Implementation of the DetectorConstruction class
0028 
0029 /////////////////////////////////////////////////////////////////////////
0030 //
0031 // TestEm8: Gaseous detector
0032 //
0033 // Created: 31.08.2010 V.Ivanchenko ob base of V.Grichine code
0034 //
0035 // Modified:
0036 //
0037 ////////////////////////////////////////////////////////////////////////
0038 //
0039 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0040 
0041 #include "DetectorConstruction.hh"
0042 
0043 #include "DetectorMessenger.hh"
0044 #include "TargetSD.hh"
0045 #include "TestParameters.hh"
0046 
0047 #include "G4Colour.hh"
0048 #include "G4GeometryManager.hh"
0049 #include "G4LogicalVolume.hh"
0050 #include "G4LogicalVolumeStore.hh"
0051 #include "G4Material.hh"
0052 #include "G4NistManager.hh"
0053 #include "G4PVPlacement.hh"
0054 #include "G4PhysicalConstants.hh"
0055 #include "G4PhysicalVolumeStore.hh"
0056 #include "G4PionPlus.hh"
0057 #include "G4ProductionCuts.hh"
0058 #include "G4Region.hh"
0059 #include "G4RegionStore.hh"
0060 #include "G4RunManager.hh"
0061 #include "G4SDManager.hh"
0062 #include "G4SolidStore.hh"
0063 #include "G4SystemOfUnits.hh"
0064 #include "G4Tubs.hh"
0065 #include "G4UnitsTable.hh"
0066 #include "G4VisAttributes.hh"
0067 #include "G4ios.hh"
0068 
0069 #include <vector>
0070 
0071 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0072 
0073 DetectorConstruction::DetectorConstruction()
0074 {
0075   fGasThickness = 23.0 * mm;
0076   fGasRadius = 10. * cm;
0077   fMaxStep = DBL_MAX;
0078 
0079   fWindowThick = 51.0 * micrometer;
0080 
0081   DefineMaterials();
0082 
0083   fDetectorMessenger = new DetectorMessenger(this);
0084 
0085   G4double cut = 0.7 * mm;
0086   fGasDetectorCuts = new G4ProductionCuts();
0087   fGasDetectorCuts->SetProductionCut(cut, "gamma");
0088   fGasDetectorCuts->SetProductionCut(cut, "e-");
0089   fGasDetectorCuts->SetProductionCut(cut, "e+");
0090   fGasDetectorCuts->SetProductionCut(cut, "proton");
0091 }
0092 
0093 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0094 
0095 DetectorConstruction::~DetectorConstruction()
0096 {
0097   delete fDetectorMessenger;
0098 }
0099 
0100 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0101 
0102 void DetectorConstruction::DefineMaterials()
0103 {
0104   // This function illustrates the possible ways to define materials
0105   G4String name, symbol;
0106   G4double density;
0107   G4int nel;
0108   G4int ncomponents;
0109   G4double fractionmass;
0110 
0111   G4NistManager* manager = G4NistManager::Instance();
0112   //
0113   // define Elements
0114   //
0115   G4Element* elH = manager->FindOrBuildElement(1);
0116   G4Element* elC = manager->FindOrBuildElement(6);
0117   G4Element* elO = manager->FindOrBuildElement(8);
0118   G4Element* elF = manager->FindOrBuildElement(9);
0119   G4Element* elNe = manager->FindOrBuildElement(10);
0120   G4Element* elXe = manager->FindOrBuildElement(54);
0121   //
0122   // simple gases at STP conditions
0123   //
0124   G4Material* Argon = manager->FindOrBuildMaterial("G4_Ar");
0125   G4Material* Kr = manager->FindOrBuildMaterial("G4_Kr");
0126   G4Material* Xe = manager->FindOrBuildMaterial("G4_Xe");
0127   //
0128   // gases at STP conditions
0129   //
0130   G4Material* CarbonDioxide = manager->FindOrBuildMaterial("G4_CARBON_DIOXIDE");
0131   G4Material* Mylar = manager->FindOrBuildMaterial("G4_MYLAR");
0132   G4Material* Methane = manager->FindOrBuildMaterial("G4_METHANE");
0133   G4Material* Propane = manager->FindOrBuildMaterial("G4_PROPANE");
0134 
0135   // propane at 10 atmospheres
0136   manager->ConstructNewGasMaterial("Propane10", "G4_PROPANE", NTP_Temperature, 10. * atmosphere);
0137 
0138   G4Material* empty = manager->FindOrBuildMaterial("G4_Galactic");
0139 
0140   // 93% Kr + 7% CH4, STP
0141   density = 3.491 * mg / cm3;
0142   G4Material* Kr7CH4 = new G4Material(name = "Kr7CH4", density, ncomponents = 2);
0143   Kr7CH4->AddMaterial(Kr, fractionmass = 0.986);
0144   Kr7CH4->AddMaterial(Methane, fractionmass = 0.014);
0145 
0146   G4double TRT_Xe_density = 5.485 * mg / cm3;
0147   G4Material* TRT_Xe = new G4Material(name = "TRT_Xe", TRT_Xe_density, nel = 1, kStateGas,
0148                                       293.15 * kelvin, 1. * atmosphere);
0149   TRT_Xe->AddElement(elXe, 1);
0150 
0151   G4double TRT_CO2_density = 1.842 * mg / cm3;
0152   G4Material* TRT_CO2 = new G4Material(name = "TRT_CO2", TRT_CO2_density, nel = 2, kStateGas,
0153                                        293.15 * kelvin, 1. * atmosphere);
0154   TRT_CO2->AddElement(elC, 1);
0155   TRT_CO2->AddElement(elO, 2);
0156 
0157   // check alternative constructor
0158   std::vector<G4String> trtatom = {"C", "O"};
0159   std::vector<G4int> trtnum = {1, 2};
0160   manager->ConstructNewMaterial("TRT_CO2p", trtatom, trtnum, TRT_CO2_density, true, kStateGas,
0161                                 NTP_Temperature, atmosphere);
0162 
0163   G4double TRT_CF4_density = 3.9 * mg / cm3;
0164   G4Material* TRT_CF4 = new G4Material(name = "TRT_CF4", TRT_CF4_density, nel = 2, kStateGas,
0165                                        293.15 * kelvin, 1. * atmosphere);
0166   TRT_CF4->AddElement(elC, 1);
0167   TRT_CF4->AddElement(elF, 4);
0168 
0169   // ATLAS TRT straw tube gas mixture (20 C, 1 atm)
0170   G4double XeCO2CF4_density = 4.76 * mg / cm3;
0171   G4Material* XeCO2CF4 = new G4Material(name = "XeCO2CF4", XeCO2CF4_density, ncomponents = 3,
0172                                         kStateGas, 293.15 * kelvin, 1. * atmosphere);
0173   XeCO2CF4->AddMaterial(TRT_Xe, 0.807);
0174   XeCO2CF4->AddMaterial(TRT_CO2, 0.039);
0175   XeCO2CF4->AddMaterial(TRT_CF4, 0.154);
0176 
0177   // C3H8,20 C, 2 atm
0178   density = 3.758 * mg / cm3;
0179   G4Material* C3H8 =
0180     new G4Material(name = "C3H8", density, nel = 2, kStateGas, 293.15 * kelvin, 2. * atmosphere);
0181   C3H8->AddElement(elC, 3);
0182   C3H8->AddElement(elH, 8);
0183 
0184   // The same material via different constructor
0185   std::vector<G4String> elmname = {"C", "H"};
0186   std::vector<G4int> atomnum = {3, 8};
0187   manager->ConstructNewIdealGasMaterial("C3H8p", elmname, atomnum, true, 293.15 * kelvin,
0188                                         2. * atmosphere);
0189 
0190   // 87.5% Xe + 7.5% CH4 + 5% C3H8, 20 C, 1. atm
0191   density = 4.9196 * mg / cm3;
0192   G4Material* XeCH4C3H8 = new G4Material(name = "XeCH4C3H8", density, ncomponents = 3, kStateGas,
0193                                          NTP_Temperature, 1. * atmosphere);
0194   XeCH4C3H8->AddMaterial(Xe, fractionmass = 0.971);
0195   XeCH4C3H8->AddMaterial(Methane, fractionmass = 0.010);
0196   XeCH4C3H8->AddMaterial(Propane, fractionmass = 0.019);
0197 
0198   // 93% Ar + 7% CH4, STP
0199   density = 1.709 * mg / cm3;
0200   G4Material* Ar7CH4 = new G4Material(name = "Ar7CH4", density, ncomponents = 2, kStateGas,
0201                                       STP_Temperature, STP_Pressure);
0202   Ar7CH4->AddMaterial(Argon, fractionmass = 0.971);
0203   Ar7CH4->AddMaterial(Methane, fractionmass = 0.029);
0204 
0205   // 80% Ar + 20% CO2, STP
0206   density = 1.8223 * mg / cm3;
0207   G4Material* Ar_80CO2_20 = new G4Material(name = "ArCO2", density, ncomponents = 2, kStateGas,
0208                                            STP_Temperature, STP_Pressure);
0209   Ar_80CO2_20->AddMaterial(Argon, fractionmass = 0.783);
0210   Ar_80CO2_20->AddMaterial(CarbonDioxide, fractionmass = 0.217);
0211 
0212   // 80% Xe + 20% CO2, STP
0213   density = 5.0818 * mg / cm3;
0214   G4Material* Xe20CO2 = new G4Material(name = "Xe20CO2", density, ncomponents = 2, kStateGas,
0215                                        STP_Temperature, STP_Pressure);
0216   Xe20CO2->AddMaterial(Xe, fractionmass = 0.922);
0217   Xe20CO2->AddMaterial(CarbonDioxide, fractionmass = 0.078);
0218 
0219   // 80% Kr + 20% CO2, STP
0220   density = 3.601 * mg / cm3;
0221   G4Material* Kr20CO2 = new G4Material(name = "Kr20CO2", density, ncomponents = 2, kStateGas,
0222                                        STP_Temperature, STP_Pressure);
0223   Kr20CO2->AddMaterial(Kr, fractionmass = 0.89);
0224   Kr20CO2->AddMaterial(CarbonDioxide, fractionmass = 0.11);
0225 
0226   // ALICE mixture TPC_Ne-CO2-2
0227   density = 0.939 * mg / cm3;
0228   G4Material* NeCO2 = new G4Material(name = "TPC_Ne-CO2-2", density, ncomponents = 3, kStateGas,
0229                                      NTP_Temperature, 1. * atmosphere);
0230   NeCO2->AddElement(elNe, fractionmass = 0.8039);
0231   NeCO2->AddElement(elO, fractionmass = 0.1426);
0232   NeCO2->AddElement(elC, fractionmass = 0.0535);
0233 
0234   // check alternative constructor
0235   std::vector<G4String> neatom = {"Ne", "O", "C"};
0236   std::vector<G4double> nefr = {0.8039, 0.1426, 0.0536};
0237   manager->ConstructNewMaterial("TPC_Ne-CO2-2p", neatom, nefr, density, true, kStateGas,
0238                                 NTP_Temperature, atmosphere);
0239 
0240   // ALICE TRD mixure 85% Xe + 15% CO2 NTP
0241   density = 4.9389 * mg / cm3;
0242   G4Material* Xe15CO2 = new G4Material(name = "Xe15CO2", density, ncomponents = 2, kStateGas,
0243                                        NTP_Temperature, atmosphere);
0244   Xe15CO2->AddMaterial(Xe, fractionmass = 0.944);
0245   Xe15CO2->AddMaterial(CarbonDioxide, fractionmass = 0.056);
0246 
0247   fGasMat = XeCH4C3H8;
0248   fWindowMat = Mylar;
0249   fWorldMaterial = empty;
0250 
0251   G4cout << *(G4Material::GetMaterialTable()) << G4endl;
0252 }
0253 
0254 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0255 
0256 G4VPhysicalVolume* DetectorConstruction::Construct()
0257 {
0258   if (nullptr != fPhysWorld) {
0259     return fPhysWorld;
0260   }
0261 
0262   G4double contThick = fWindowThick * 2 + fGasThickness;
0263   G4double contR = fWindowThick * 2 + fGasRadius;
0264 
0265   G4double worldSizeZ = contThick * 1.2;
0266   G4double worldSizeR = contR * 1.2;
0267 
0268   TestParameters::GetPointer()->SetPositionZ(-0.55 * contThick);
0269 
0270   // Printout parameters
0271   G4cout << "\n The  WORLD   is made of " << worldSizeZ / mm << "mm of "
0272          << fWorldMaterial->GetName();
0273   G4cout << ", the transverse size (R) of the world is " << worldSizeR / mm << " mm. " << G4endl;
0274   G4cout << " The CONTAINER is made of " << fWindowThick / mm << "mm of " << fWindowMat->GetName()
0275          << G4endl;
0276   G4cout << " The TARGET is made of " << fGasThickness / mm << "mm of " << fGasMat->GetName();
0277   G4cout << ", the transverse size (R) is " << fGasRadius / mm << " mm. " << G4endl;
0278   G4cout << G4endl;
0279 
0280   // World
0281   fSolidWorld = new G4Tubs("World", 0., worldSizeR, worldSizeZ / 2., 0., CLHEP::twopi);
0282 
0283   fLogicWorld = new G4LogicalVolume(fSolidWorld, fWorldMaterial, "World");
0284 
0285   fPhysWorld = new G4PVPlacement(0, G4ThreeVector(0., 0., 0.), "World", fLogicWorld, 0, false, 0);
0286 
0287   // Window
0288   fSolidContainer = new G4Tubs("Absorber", 0., contR, contThick / 2., 0., CLHEP::twopi);
0289 
0290   fLogicContainer = new G4LogicalVolume(fSolidContainer, fWindowMat, "Window");
0291 
0292   G4PVPlacement* PhysWind = new G4PVPlacement(0, G4ThreeVector(0., 0., 0.), "Window",
0293                                               fLogicContainer, fPhysWorld, false, 0);
0294 
0295   // Detector volume
0296   fSolidDetector = new G4Tubs("Gas", 0., fGasRadius, fGasThickness / 2., 0., CLHEP::twopi);
0297 
0298   fLogicDetector = new G4LogicalVolume(fSolidDetector, fGasMat, "Gas");
0299 
0300   new G4PVPlacement(0, G4ThreeVector(0., 0., 0.), "Gas", fLogicDetector, PhysWind, false, 0);
0301 
0302   // defined gas detector region
0303   fRegGasDet = new G4Region("GasDetector");
0304   fRegGasDet->SetProductionCuts(fGasDetectorCuts);
0305   fRegGasDet->AddRootLogicalVolume(fLogicDetector);
0306 
0307   // visualisation
0308   fLogicWorld->SetVisAttributes(G4VisAttributes::GetInvisible());
0309   G4VisAttributes* color1 = new G4VisAttributes(G4Colour(0.3, 0.3, 0.3));
0310   fLogicContainer->SetVisAttributes(color1);
0311   G4VisAttributes* color2 = new G4VisAttributes(G4Colour(0.0, 0.3, 0.7));
0312   fLogicDetector->SetVisAttributes(color2);
0313 
0314   if (0.0 == fGasMat->GetIonisation()->GetMeanEnergyPerIonPair()) {
0315     SetPairEnergy(20 * eV);
0316   }
0317   return fPhysWorld;
0318 }
0319 
0320 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0321 
0322 void DetectorConstruction::ConstructSDandField()
0323 {
0324   auto sd = new TargetSD("GasSD");
0325   G4SDManager::GetSDMpointer()->AddNewDetector(sd);
0326   SetSensitiveDetector(fLogicDetector, sd);
0327 }
0328 
0329 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0330 
0331 void DetectorConstruction::SetGasMaterial(const G4String& name)
0332 {
0333   // get the pointer to the existing material
0334   G4Material* mat = G4Material::GetMaterial(name, false);
0335 
0336   // create the material by its name
0337   if (!mat) {
0338     mat = G4NistManager::Instance()->FindOrBuildMaterial(name);
0339   }
0340 
0341   if (mat && mat != fGasMat) {
0342     G4cout << "### New target material: " << mat->GetName() << G4endl;
0343     fGasMat = mat;
0344     if (fLogicDetector) {
0345       fLogicDetector->SetMaterial(mat);
0346       G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0347     }
0348   }
0349 }
0350 
0351 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0352 
0353 void DetectorConstruction::SetContainerMaterial(const G4String& name)
0354 {
0355   // get the pointer to the existing material
0356   G4Material* mat = G4Material::GetMaterial(name, false);
0357 
0358   // create the material by its name
0359   if (!mat) {
0360     mat = G4NistManager::Instance()->FindOrBuildMaterial(name);
0361   }
0362 
0363   if (mat && mat != fWindowMat) {
0364     G4cout << "### New material for container: " << mat->GetName() << G4endl;
0365     fWindowMat = mat;
0366     if (fLogicContainer) {
0367       fLogicContainer->SetMaterial(mat);
0368       G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0369     }
0370   }
0371 }
0372 
0373 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0374 
0375 void DetectorConstruction::SetWorldMaterial(const G4String& name)
0376 {
0377   // get the pointer to the existing material
0378   G4Material* mat = G4Material::GetMaterial(name, false);
0379 
0380   // create the material by its name
0381   if (!mat) {
0382     mat = G4NistManager::Instance()->FindOrBuildMaterial(name);
0383   }
0384 
0385   if (mat && mat != fWorldMaterial) {
0386     G4cout << "### New World material: " << mat->GetName() << G4endl;
0387     fWorldMaterial = mat;
0388     if (fLogicWorld) {
0389       fLogicWorld->SetMaterial(mat);
0390       G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0391     }
0392   }
0393 }
0394 
0395 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0396 
0397 void DetectorConstruction::SetGasThickness(G4double val)
0398 {
0399   if (val <= 0.0) {
0400     return;
0401   }
0402   fGasThickness = val;
0403   if (nullptr != fPhysWorld) {
0404     ChangeGeometry();
0405   }
0406 }
0407 
0408 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0409 
0410 void DetectorConstruction::SetGasRadius(G4double val)
0411 {
0412   if (val <= 0.0) {
0413     return;
0414   }
0415   fGasRadius = val;
0416   if (nullptr != fPhysWorld) {
0417     ChangeGeometry();
0418   }
0419 }
0420 
0421 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0422 
0423 void DetectorConstruction::SetContainerThickness(G4double val)
0424 {
0425   if (val <= 0.0) {
0426     return;
0427   }
0428   fWindowThick = val;
0429   if (nullptr != fPhysWorld) {
0430     ChangeGeometry();
0431   }
0432 }
0433 
0434 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0435 
0436 void DetectorConstruction::SetPairEnergy(G4double val)
0437 {
0438   if (val > 0.0) {
0439     fGasMat->GetIonisation()->SetMeanEnergyPerIonPair(val);
0440   }
0441 }
0442 
0443 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0444 
0445 void DetectorConstruction::ChangeGeometry()
0446 {
0447   G4double contThick = fWindowThick * 2 + fGasThickness;
0448   G4double contR = fWindowThick * 2 + fGasRadius;
0449 
0450   G4double worldSizeZ = contThick * 1.2;
0451   G4double worldSizeR = contR * 1.2;
0452 
0453   TestParameters::GetPointer()->SetPositionZ(-0.55 * contThick);
0454 
0455   fSolidWorld->SetOuterRadius(worldSizeR);
0456   fSolidWorld->SetZHalfLength(worldSizeZ * 0.5);
0457 
0458   fSolidContainer->SetOuterRadius(contR);
0459   fSolidContainer->SetZHalfLength(contThick * 0.5);
0460 
0461   fSolidDetector->SetOuterRadius(fGasRadius);
0462   fSolidDetector->SetZHalfLength(fGasThickness * 0.5);
0463 }
0464 
0465 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......