Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-23 09:22:46

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 RE06/src/RE06DetectorConstruction.cc
0027 /// \brief Implementation of the RE06DetectorConstruction class
0028 //
0029 //
0030 
0031 #include "RE06DetectorConstruction.hh"
0032 
0033 #include "RE06DetectorMessenger.hh"
0034 #include "RE06ParallelWorld.hh"
0035 #include "RE06PrimaryGeneratorAction.hh"
0036 
0037 #include "G4Box.hh"
0038 #include "G4Colour.hh"
0039 #include "G4LogicalVolume.hh"
0040 #include "G4Material.hh"
0041 #include "G4MultiFunctionalDetector.hh"
0042 #include "G4PSEnergyDeposit.hh"
0043 #include "G4PSMinKinEAtGeneration.hh"
0044 #include "G4PSNofSecondary.hh"
0045 #include "G4PSNofStep.hh"
0046 #include "G4PSTrackLength.hh"
0047 #include "G4PVPlacement.hh"
0048 #include "G4PVReplica.hh"
0049 #include "G4PhysicalConstants.hh"
0050 #include "G4RunManager.hh"
0051 #include "G4SDManager.hh"
0052 #include "G4SDParticleFilter.hh"
0053 #include "G4SystemOfUnits.hh"
0054 #include "G4VPrimitiveScorer.hh"
0055 #include "G4VSDFilter.hh"
0056 #include "G4VisAttributes.hh"
0057 #include "G4ios.hh"
0058 
0059 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0060 
0061 G4ThreadLocal G4bool RE06DetectorConstruction::fConstructedSDandField = false;
0062 
0063 RE06DetectorConstruction::RE06DetectorConstruction()
0064   : G4VUserDetectorConstruction(),
0065     fNumberOfLayers(40),
0066     fTotalThickness(2.0 * m),
0067     fLayerThickness(0.),
0068     fConstructed(false),
0069     fWorldMaterial(0),
0070     fAbsorberMaterial(0),
0071     fGapMaterial(0),
0072     fLayerSolid(0),
0073     fGapSolid(0),
0074     fWorldLogical(0),
0075     fWorldPhysical(0),
0076     fSerial(false),
0077     fDetectorMessenger(0),
0078     fVerboseLevel(1)
0079 {
0080   fLayerThickness = fTotalThickness / fNumberOfLayers;
0081 
0082   for (size_t i = 0; i < 3; i++) {
0083     fCalorLogical[i] = 0;
0084     fLayerLogical[i] = 0;
0085     fGapLogical[i] = 0;
0086     fCalorPhysical[i] = 0;
0087     fLayerPhysical[i] = 0;
0088     fGapPhysical[i] = 0;
0089   }
0090 
0091   fCalName[0] = "Calor-A";
0092   fCalName[1] = "Calor-B";
0093   fCalName[2] = "Calor-C";
0094 
0095   fDetectorMessenger = new RE06DetectorMessenger(this);
0096 }
0097 
0098 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0099 
0100 RE06DetectorConstruction::~RE06DetectorConstruction()
0101 {
0102   delete fDetectorMessenger;
0103 }
0104 
0105 G4VPhysicalVolume* RE06DetectorConstruction::Construct()
0106 {
0107   if (!fConstructed) {
0108     fConstructed = true;
0109     DefineMaterials();
0110     SetupGeometry();
0111   }
0112   if (GetVerboseLevel() > 0) {
0113     PrintCalorParameters();
0114   }
0115   return fWorldPhysical;
0116 }
0117 
0118 void RE06DetectorConstruction::ConstructSDandField()
0119 {
0120   if (!fConstructedSDandField) {
0121     fConstructedSDandField = true;
0122     SetupDetectors();
0123   }
0124 }
0125 
0126 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0127 
0128 void RE06DetectorConstruction::DefineMaterials()
0129 {
0130   G4String name, symbol;  // a=mass of a mole;
0131   G4double a, z, density;  // z=mean number of protons;
0132   G4int iz;  // iz=number of protons  in an isotope;
0133   G4int n;  // n=number of nucleons in an isotope;
0134 
0135   G4int ncomponents, natoms;
0136   G4double abundance, fractionmass;
0137   G4double temperature, pressure;
0138 
0139   //
0140   // define Elements
0141   //
0142 
0143   a = 1.01 * g / mole;
0144   G4Element* H = new G4Element(name = "Hydrogen", symbol = "H", z = 1., a);
0145 
0146   a = 12.01 * g / mole;
0147   G4Element* C = new G4Element(name = "Carbon", symbol = "C", z = 6., a);
0148 
0149   a = 14.01 * g / mole;
0150   G4Element* N = new G4Element(name = "Nitrogen", symbol = "N", z = 7., a);
0151 
0152   a = 16.00 * g / mole;
0153   G4Element* O = new G4Element(name = "Oxygen", symbol = "O", z = 8., a);
0154 
0155   //
0156   // define an Element from isotopes, by relative abundance
0157   //
0158 
0159   G4Isotope* U5 = new G4Isotope(name = "U235", iz = 92, n = 235, a = 235.01 * g / mole);
0160   G4Isotope* U8 = new G4Isotope(name = "U238", iz = 92, n = 238, a = 238.03 * g / mole);
0161 
0162   G4Element* U = new G4Element(name = "enriched Uranium", symbol = "U", ncomponents = 2);
0163   U->AddIsotope(U5, abundance = 90. * perCent);
0164   U->AddIsotope(U8, abundance = 10. * perCent);
0165 
0166   //
0167   // define simple materials
0168   //
0169 
0170   new G4Material(name = "Aluminium", z = 13., a = 26.98 * g / mole, density = 2.700 * g / cm3);
0171   new G4Material(name = "Silicon", z = 14., a = 28.09 * g / mole, density = 2.33 * g / cm3);
0172   new G4Material(name = "Iron", z = 26., a = 55.85 * g / mole, density = 7.87 * g / cm3);
0173   new G4Material(name = "ArgonGas", z = 18., a = 39.95 * g / mole, density = 1.782 * mg / cm3);
0174   new G4Material(name = "He", z = 2., a = 4.0 * g / mole, density = 0.1786e-03 * g / cm3);
0175 
0176   density = 1.390 * g / cm3;
0177   a = 39.95 * g / mole;
0178   G4Material* lAr = new G4Material(name = "liquidArgon", z = 18., a, density);
0179 
0180   density = 11.35 * g / cm3;
0181   a = 207.19 * g / mole;
0182   G4Material* Pb = new G4Material(name = "Lead", z = 82., a, density);
0183 
0184   //
0185   // define a material from elements.   case 1: chemical molecule
0186   //
0187 
0188   density = 1.000 * g / cm3;
0189   G4Material* H2O = new G4Material(name = "Water", density, ncomponents = 2);
0190   H2O->AddElement(H, natoms = 2);
0191   H2O->AddElement(O, natoms = 1);
0192 
0193   density = 1.032 * g / cm3;
0194   G4Material* Sci = new G4Material(name = "Scintillator", density, ncomponents = 2);
0195   Sci->AddElement(C, natoms = 9);
0196   Sci->AddElement(H, natoms = 10);
0197 
0198   //
0199   // define a material from elements.   case 2: mixture by fractional mass
0200   //
0201 
0202   density = 1.290 * mg / cm3;
0203   G4Material* Air = new G4Material(name = "Air", density, ncomponents = 2);
0204   Air->AddElement(N, fractionmass = 0.7);
0205   Air->AddElement(O, fractionmass = 0.3);
0206 
0207   //
0208   // examples of vacuum
0209   //
0210 
0211   density = universe_mean_density;
0212   pressure = 3.e-18 * pascal;
0213   temperature = 2.73 * kelvin;
0214   G4Material* Vacuum = new G4Material(name = "Galactic", z = 1., a = 1.01 * g / mole, density,
0215                                       kStateGas, temperature, pressure);
0216 
0217   if (GetVerboseLevel() > 1) {
0218     G4cout << *(G4Material::GetMaterialTable()) << G4endl;
0219   }
0220 
0221   // default materials of the calorimeter
0222   fWorldMaterial = Vacuum;
0223   fAbsorberMaterial = Pb;
0224   fGapMaterial = lAr;
0225 }
0226 
0227 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0228 
0229 void RE06DetectorConstruction::SetupGeometry()
0230 {
0231   //
0232   // World
0233   //
0234   G4VSolid* worldSolid = new G4Box("World", 2. * m, 2. * m, fTotalThickness * 2.);
0235   fWorldLogical = new G4LogicalVolume(worldSolid, fWorldMaterial, "World");
0236   fWorldPhysical = new G4PVPlacement(0, G4ThreeVector(), fWorldLogical, "World", 0, false, 0);
0237 
0238   //
0239   // Calorimeter
0240   //
0241   G4VSolid* calorSolid = new G4Box("Calor", 0.5 * m, 0.5 * m, fTotalThickness / 2.);
0242   G4int i;
0243   for (i = 0; i < 3; i++) {
0244     fCalorLogical[i] = new G4LogicalVolume(calorSolid, fAbsorberMaterial, fCalName[i]);
0245     if (fSerial) {
0246       fCalorPhysical[i] =
0247         new G4PVPlacement(0, G4ThreeVector(0., 0., G4double(i - 1) * fTotalThickness),
0248                           fCalorLogical[i], fCalName[i], fWorldLogical, false, i);
0249     }
0250     else {
0251       fCalorPhysical[i] = new G4PVPlacement(0, G4ThreeVector(0., G4double(i - 1) * m, 0.),
0252                                             fCalorLogical[i], fCalName[i], fWorldLogical, false, i);
0253     }
0254   }
0255 
0256   //
0257   // Layers --- as absorbers
0258   //
0259   fLayerSolid = new G4Box("Layer", 0.5 * m, 0.5 * m, fLayerThickness / 2.);
0260   for (i = 0; i < 3; i++) {
0261     fLayerLogical[i] =
0262       new G4LogicalVolume(fLayerSolid, fAbsorberMaterial, fCalName[i] + "_LayerLog");
0263     fLayerPhysical[i] = new G4PVReplica(fCalName[i] + "_Layer", fLayerLogical[i], fCalorLogical[i],
0264                                         kZAxis, fNumberOfLayers, fLayerThickness);
0265   }
0266 
0267   //
0268   // Gap
0269   //
0270   fGapSolid = new G4Box("Gap", 0.5 * m, 0.5 * m, fLayerThickness / 4.);
0271   for (i = 0; i < 3; i++) {
0272     fGapLogical[i] = new G4LogicalVolume(fGapSolid, fGapMaterial, fCalName[i] + "_Gap");
0273     fGapPhysical[i] =
0274       new G4PVPlacement(0, G4ThreeVector(0., 0., fLayerThickness / 4.), fGapLogical[i],
0275                         fCalName[i] + "_gap", fLayerLogical[i], false, 0);
0276   }
0277 
0278   //
0279   // Regions
0280   //
0281   for (i = 0; i < 3; i++) {
0282     G4Region* aRegion = new G4Region(fCalName[i]);
0283     fCalorLogical[i]->SetRegion(aRegion);
0284     aRegion->AddRootLogicalVolume(fCalorLogical[i]);
0285   }
0286 
0287   //
0288   // Visualization attributes
0289   //
0290   fWorldLogical->SetVisAttributes(G4VisAttributes::GetInvisible());
0291   G4VisAttributes* simpleBoxVisAtt = new G4VisAttributes(G4Colour(1.0, 1.0, 1.0));
0292   simpleBoxVisAtt->SetVisibility(true);
0293   for (i = 0; i < 3; i++) {
0294     fCalorLogical[i]->SetVisAttributes(simpleBoxVisAtt);
0295     fLayerLogical[i]->SetVisAttributes(simpleBoxVisAtt);
0296     fGapLogical[i]->SetVisAttributes(simpleBoxVisAtt);
0297   }
0298 }
0299 
0300 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0301 
0302 void RE06DetectorConstruction::SetupDetectors()
0303 {
0304   G4SDManager::GetSDMpointer()->SetVerboseLevel(1);
0305   G4String filterName, particleName;
0306 
0307   G4SDParticleFilter* gammaFilter =
0308     new G4SDParticleFilter(filterName = "gammaFilter", particleName = "gamma");
0309   G4SDParticleFilter* electronFilter =
0310     new G4SDParticleFilter(filterName = "electronFilter", particleName = "e-");
0311   G4SDParticleFilter* positronFilter =
0312     new G4SDParticleFilter(filterName = "positronFilter", particleName = "e+");
0313   G4SDParticleFilter* epFilter = new G4SDParticleFilter(filterName = "epFilter");
0314   epFilter->add(particleName = "e-");
0315   epFilter->add(particleName = "e+");
0316 
0317   for (G4int i = 0; i < 3; i++) {
0318     for (G4int j = 0; j < 2; j++) {
0319       // Loop counter j = 0 : absorber
0320       //                = 1 : gap
0321       G4String detName = fCalName[i];
0322       if (j == 0) {
0323         detName += "_abs";
0324       }
0325       else {
0326         detName += "_gap";
0327       }
0328       G4MultiFunctionalDetector* det = new G4MultiFunctionalDetector(detName);
0329       G4SDManager::GetSDMpointer()->AddNewDetector(det);
0330 
0331       // The second argument in each primitive means the "level" of geometrical
0332       // hierarchy, the copy number of that level is used as the key of the
0333       // G4THitsMap.
0334       // For absorber (j = 0), the copy number of its own physical volume is used.
0335       // For gap (j = 1), the copy number of its mother physical volume is used,
0336       // since there is only one physical volume of gap is placed with respect
0337       // to its mother.
0338       G4VPrimitiveScorer* primitive;
0339       primitive = new G4PSEnergyDeposit("eDep", j);
0340       det->RegisterPrimitive(primitive);
0341       primitive = new G4PSNofSecondary("nGamma", j);
0342       primitive->SetFilter(gammaFilter);
0343       det->RegisterPrimitive(primitive);
0344       primitive = new G4PSNofSecondary("nElectron", j);
0345       primitive->SetFilter(electronFilter);
0346       det->RegisterPrimitive(primitive);
0347       primitive = new G4PSNofSecondary("nPositron", j);
0348       primitive->SetFilter(positronFilter);
0349       det->RegisterPrimitive(primitive);
0350       primitive = new G4PSMinKinEAtGeneration("minEkinGamma", j);
0351       primitive->SetFilter(gammaFilter);
0352       det->RegisterPrimitive(primitive);
0353       primitive = new G4PSMinKinEAtGeneration("minEkinElectron", j);
0354       primitive->SetFilter(electronFilter);
0355       det->RegisterPrimitive(primitive);
0356       primitive = new G4PSMinKinEAtGeneration("minEkinPositron", j);
0357       primitive->SetFilter(positronFilter);
0358       det->RegisterPrimitive(primitive);
0359       primitive = new G4PSTrackLength("trackLength", j);
0360       primitive->SetFilter(epFilter);
0361       det->RegisterPrimitive(primitive);
0362       primitive = new G4PSNofStep("nStep", j);
0363       primitive->SetFilter(epFilter);
0364       det->RegisterPrimitive(primitive);
0365 
0366       if (j == 0) {
0367         SetSensitiveDetector(fLayerLogical[i], det);
0368       }
0369       else {
0370         SetSensitiveDetector(fGapLogical[i], det);
0371       }
0372     }
0373   }
0374   G4SDManager::GetSDMpointer()->SetVerboseLevel(0);
0375 }
0376 
0377 void RE06DetectorConstruction::PrintCalorParameters() const
0378 {
0379   G4cout << "--------------------------------------------------------" << G4endl;
0380   if (fSerial) {
0381     G4cout << " Calorimeters are placed in serial." << G4endl;
0382   }
0383   else {
0384     G4cout << " Calorimeters are placed in parallel." << G4endl;
0385   }
0386   G4cout << " Absorber is made of " << fAbsorberMaterial->GetName() << G4endl << " Gap is made of "
0387          << fGapMaterial->GetName() << G4endl
0388          << "--------------------------------------------------------" << G4endl;
0389 }
0390 
0391 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0392 
0393 void RE06DetectorConstruction::SetAbsorberMaterial(G4String materialChoice)
0394 {
0395   // search the material by its name
0396   G4Material* pttoMaterial = G4Material::GetMaterial(materialChoice);
0397   if (pttoMaterial) {
0398     fAbsorberMaterial = pttoMaterial;
0399     if (fConstructed)
0400       for (size_t i = 0; i < 3; i++) {
0401         fCalorLogical[i]->SetMaterial(fAbsorberMaterial);
0402         fLayerLogical[i]->SetMaterial(fAbsorberMaterial);
0403       }
0404     G4RunManager::GetRunManager()->GeometryHasBeenModified();
0405     if (GetVerboseLevel() > 1) {
0406       PrintCalorParameters();
0407     }
0408   }
0409   else {
0410     G4cerr << materialChoice << " is not defined. - Command is ignored." << G4endl;
0411   }
0412 }
0413 
0414 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0415 
0416 G4String RE06DetectorConstruction::GetAbsorberMaterial() const
0417 {
0418   return fAbsorberMaterial->GetName();
0419 }
0420 
0421 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0422 
0423 void RE06DetectorConstruction::SetGapMaterial(G4String materialChoice)
0424 {
0425   // search the material by its name
0426   G4Material* pttoMaterial = G4Material::GetMaterial(materialChoice);
0427   if (pttoMaterial) {
0428     fGapMaterial = pttoMaterial;
0429     if (fConstructed)
0430       for (size_t i = 0; i < 3; i++) {
0431         fGapLogical[i]->SetMaterial(fGapMaterial);
0432       }
0433     G4RunManager::GetRunManager()->GeometryHasBeenModified();
0434     if (GetVerboseLevel() > 1) {
0435       PrintCalorParameters();
0436     }
0437   }
0438   else {
0439     G4cerr << materialChoice << " is not defined. - Command is ignored." << G4endl;
0440   }
0441 }
0442 
0443 G4String RE06DetectorConstruction::GetGapMaterial() const
0444 {
0445   return fGapMaterial->GetName();
0446 }
0447 
0448 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0449 
0450 void RE06DetectorConstruction::SetSerialGeometry(G4bool serial)
0451 {
0452   if (fSerial == serial) return;
0453   fSerial = serial;
0454   RE06PrimaryGeneratorAction* gen =
0455     (RE06PrimaryGeneratorAction*)(G4RunManager::GetRunManager()->GetUserPrimaryGeneratorAction());
0456   if (gen) gen->SetSerial(fSerial);
0457   if (!fConstructed) return;
0458   for (G4int i = 0; i < 3; i++) {
0459     if (fSerial) {
0460       fCalorPhysical[i]->SetTranslation(G4ThreeVector(0., 0., G4double(i - 1) * 2. * m));
0461     }
0462     else {
0463       fCalorPhysical[i]->SetTranslation(G4ThreeVector(0., G4double(i - 1) * m, 0.));
0464     }
0465   }
0466   ((RE06ParallelWorld*)GetParallelWorld(0))->SetSerialGeometry(serial);
0467   G4RunManager::GetRunManager()->GeometryHasBeenModified();
0468 }
0469 
0470 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0471 
0472 void RE06DetectorConstruction::SetNumberOfLayers(G4int nl)
0473 {
0474   fNumberOfLayers = nl;
0475   fLayerThickness = fTotalThickness / fNumberOfLayers;
0476   if (!fConstructed) return;
0477 
0478   fLayerSolid->SetZHalfLength(fLayerThickness / 2.);
0479   fGapSolid->SetZHalfLength(fLayerThickness / 4.);
0480   for (size_t i = 0; i < 3; i++) {
0481     fCalorLogical[i]->RemoveDaughter(fLayerPhysical[i]);
0482     delete fLayerPhysical[i];
0483     fLayerPhysical[i] = new G4PVReplica(fCalName[i] + "_Layer", fLayerLogical[i], fCalorLogical[i],
0484                                         kZAxis, fNumberOfLayers, fLayerThickness);
0485     fGapPhysical[i]->SetTranslation(G4ThreeVector(0., 0., fLayerThickness / 4.));
0486   }
0487   G4RunManager::GetRunManager()->GeometryHasBeenModified();
0488 }
0489 
0490 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0491 
0492 void RE06DetectorConstruction::AddMaterial()
0493 {
0494   static G4bool isAdded = false;
0495 
0496   if (isAdded) return;
0497 
0498   G4String name, symbol;  // a=mass of a mole;
0499   G4double a, z, density;  // z=mean number of protons;
0500 
0501   G4int ncomponents, natoms;
0502 
0503   //
0504   // define simple materials
0505   //
0506 
0507   new G4Material(name = "Copper", z = 29., a = 63.546 * g / mole, density = 8.96 * g / cm3);
0508   new G4Material(name = "Tungsten", z = 74., a = 183.84 * g / mole, density = 19.3 * g / cm3);
0509 
0510   G4Element* C = G4Element::GetElement("Carbon");
0511   G4Element* O = G4Element::GetElement("Oxygen");
0512 
0513   G4Material* CO2 = new G4Material("CarbonicGas", density = 27. * mg / cm3, ncomponents = 2,
0514                                    kStateGas, 325. * kelvin, 50. * atmosphere);
0515   CO2->AddElement(C, natoms = 1);
0516   CO2->AddElement(O, natoms = 2);
0517 
0518   isAdded = true;
0519 }
0520 
0521 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......