File indexing completed on 2025-10-30 08:00:01
0001 
0002 
0003 
0004 
0005 
0006 
0007 
0008 
0009 
0010 
0011 
0012 
0013 
0014 
0015 
0016 
0017 
0018 
0019 
0020 
0021 
0022 
0023 
0024 
0025 
0026 
0027 
0028 
0029 
0030 
0031 
0032 
0033 
0034 
0035 #include "F03DetectorConstruction.hh"
0036 
0037 #include "F03CalorimeterSD.hh"
0038 #include "F03DetectorMessenger.hh"
0039 
0040 #include "G4AutoDelete.hh"
0041 #include "G4GeometryManager.hh"
0042 #include "G4FieldBuilder.hh"
0043 #include "G4LogicalVolume.hh"
0044 #include "G4LogicalVolumeStore.hh"
0045 #include "G4Material.hh"
0046 #include "G4PVPlacement.hh"
0047 #include "G4PhysicalConstants.hh"
0048 #include "G4PhysicalVolumeStore.hh"
0049 #include "G4RunManager.hh"
0050 #include "G4SDManager.hh"
0051 #include "G4SolidStore.hh"
0052 #include "G4SystemOfUnits.hh"
0053 #include "G4Tubs.hh"
0054 #include "G4UniformMagField.hh"
0055 
0056 
0057 
0058 F03DetectorConstruction::F03DetectorConstruction()
0059 {
0060   fDetectorMessenger = new F03DetectorMessenger(this);
0061 
0062   
0063   
0064   G4FieldBuilder* fieldBuilder = G4FieldBuilder::Instance();
0065   
0066 
0067   auto globalFieldParameters = fieldBuilder->GetFieldParameters();
0068   auto localFieldParameters = fieldBuilder->CreateFieldParameters("Radiator");
0069 
0070   
0071   globalFieldParameters->SetMinimumStep(0.25 * mm);
0072   localFieldParameters->SetMinimumStep(0.25 * mm);
0073 
0074   
0075   DefineMaterials();
0076 }
0077 
0078 
0079 
0080 F03DetectorConstruction::~F03DetectorConstruction()
0081 {
0082   delete fDetectorMessenger;
0083 }
0084 
0085 
0086 
0087 G4VPhysicalVolume* F03DetectorConstruction::Construct()
0088 {
0089   return ConstructCalorimeter();
0090 }
0091 
0092 
0093 
0094 void F03DetectorConstruction::DefineMaterials()
0095 {
0096   
0097 
0098   G4String name, symbol;  
0099   G4double a, z, density;  
0100   G4int nel;
0101   G4int ncomponents;
0102   G4double fractionmass, pressure, temperature;
0103 
0104   
0105   
0106   
0107 
0108   a = 1.01 * g / mole;
0109   auto elH = new G4Element(name = "Hydrogen", symbol = "H", z = 1., a);
0110 
0111   a = 12.01 * g / mole;
0112   auto elC = new G4Element(name = "Carbon", symbol = "C", z = 6., a);
0113 
0114   a = 14.01 * g / mole;
0115   auto elN = new G4Element(name = "Nitrogen", symbol = "N", z = 7., a);
0116 
0117   a = 16.00 * g / mole;
0118   auto elO = new G4Element(name = "Oxygen", symbol = "O", z = 8., a);
0119 
0120   a = 39.948 * g / mole;
0121   auto elAr = new G4Element(name = "Argon", symbol = "Ar", z = 18., a);
0122 
0123   
0124   
0125   
0126 
0127   
0128 
0129   density = 1.39 * g / cm3;
0130   auto mylar = new G4Material(name = "Mylar", density, nel = 3);
0131   mylar->AddElement(elO, 2);
0132   mylar->AddElement(elC, 5);
0133   mylar->AddElement(elH, 4);
0134 
0135   
0136 
0137   auto CH2 = new G4Material("Polypropelene", 0.91 * g / cm3, 2);
0138   CH2->AddElement(elH, 2);
0139   CH2->AddElement(elC, 1);
0140 
0141   
0142 
0143   density = 3.700 * mg / cm3;
0144   a = 83.80 * g / mole;
0145   auto Kr = new G4Material(name = "Kr", z = 36., a, density);
0146 
0147   
0148 
0149   density = 1.7836 * mg / cm3;  
0150   auto argon = new G4Material(name = "Argon", density, ncomponents = 1);
0151   argon->AddElement(elAr, 1);
0152 
0153   density = 1.25053 * mg / cm3;  
0154   auto nitrogen = new G4Material(name = "N2", density, ncomponents = 1);
0155   nitrogen->AddElement(elN, 2);
0156 
0157   density = 1.4289 * mg / cm3;  
0158   auto oxygen = new G4Material(name = "O2", density, ncomponents = 1);
0159   oxygen->AddElement(elO, 2);
0160 
0161   density = 1.2928 * mg / cm3;  
0162   density *= 1.0e-8;  
0163   temperature = STP_Temperature;
0164   pressure = 1.0e-8 * STP_Pressure;
0165 
0166   auto air =
0167     new G4Material(name = "Air", density, ncomponents = 3, kStateGas, temperature, pressure);
0168   air->AddMaterial(nitrogen, fractionmass = 0.7557);
0169   air->AddMaterial(oxygen, fractionmass = 0.2315);
0170   air->AddMaterial(argon, fractionmass = 0.0128);
0171 
0172   
0173 
0174   density = 5.858 * mg / cm3;
0175   a = 131.29 * g / mole;
0176   auto Xe = new G4Material(name = "Xenon", z = 54., a, density);
0177 
0178   
0179 
0180   density = 1.842 * mg / cm3;
0181   auto CarbonDioxide = new G4Material(name = "CO2", density, nel = 2);
0182   CarbonDioxide->AddElement(elC, 1);
0183   CarbonDioxide->AddElement(elO, 2);
0184 
0185   
0186 
0187   density = 5.0818 * mg / cm3;
0188   auto Xe20CO2 = new G4Material(name = "Xe20CO2", density, ncomponents = 2);
0189   Xe20CO2->AddMaterial(Xe, fractionmass = 0.922);
0190   Xe20CO2->AddMaterial(CarbonDioxide, fractionmass = 0.078);
0191 
0192   
0193 
0194   density = 3.601 * mg / cm3;
0195   auto Kr20CO2 = new G4Material(name = "Kr20CO2", density, ncomponents = 2);
0196   Kr20CO2->AddMaterial(Kr, fractionmass = 0.89);
0197   Kr20CO2->AddMaterial(CarbonDioxide, fractionmass = 0.11);
0198 
0199   G4cout << *(G4Material::GetMaterialTable()) << G4endl;
0200 
0201   
0202 
0203   fRadiatorMat = air;  
0204 
0205   fAbsorberMaterial = air;  
0206 
0207   fWorldMaterial = air;
0208 }
0209 
0210 
0211 
0212 G4VPhysicalVolume* F03DetectorConstruction::ConstructCalorimeter()
0213 {
0214   
0215 
0216   if (fPhysiWorld) {
0217     G4GeometryManager::GetInstance()->OpenGeometry();
0218     G4PhysicalVolumeStore::GetInstance()->Clean();
0219     G4LogicalVolumeStore::GetInstance()->Clean();
0220     G4SolidStore::GetInstance()->Clean();
0221   }
0222 
0223   
0224 
0225   ComputeCalorParameters();
0226   PrintCalorParameters();
0227 
0228   G4bool checkOverlaps = true;
0229 
0230   fSolidWorld = new G4Tubs("World",  
0231                            0., fWorldSizeR, fWorldSizeZ / 2., 0., twopi);  
0232 
0233   fLogicWorld = new G4LogicalVolume(fSolidWorld,  
0234                                     fWorldMaterial,  
0235                                     "World");  
0236 
0237   fPhysiWorld = new G4PVPlacement(nullptr,  
0238                                   G4ThreeVector(),  
0239                                   "World",  
0240                                   fLogicWorld,  
0241                                   nullptr,  
0242                                   false,  
0243                                   0,  
0244                                   checkOverlaps);  
0245 
0246   
0247   G4double radThick = fFoilNumber * (fRadThickness + fGasGap) + fDetGap;
0248   G4double zRad = fZAbsorber - 0.5 * (radThick + fAbsorberThickness);
0249 
0250   G4cout << "zRad = " << zRad / mm << " mm" << G4endl;
0251   G4cout << "radThick = " << radThick / mm << " mm" << G4endl;
0252   G4cout << "fFoilNumber = " << fFoilNumber << G4endl;
0253   G4cout << "fRadiatorMat = " << fRadiatorMat->GetName() << G4endl;
0254   G4cout << "WorldMaterial = " << fWorldMaterial->GetName() << G4endl;
0255 
0256   fSolidRadiator = new G4Tubs("Radiator", 0.0, fAbsorberRadius, 0.5 * radThick, 0.0, twopi);
0257 
0258   fLogicRadiator = new G4LogicalVolume(fSolidRadiator, fWorldMaterial, "Radiator");
0259 
0260   fPhysiRadiator = new G4PVPlacement(nullptr, G4ThreeVector(0, 0, zRad), "Radiator", fLogicRadiator,
0261                                      fPhysiWorld, false, 0, checkOverlaps);
0262 
0263   fSolidRadSlice = new G4Tubs("RadSlice", 0.0, fAbsorberRadius, 0.5 * fRadThickness, 0.0, twopi);
0264 
0265   fLogicRadSlice = new G4LogicalVolume(fSolidRadSlice, fRadiatorMat, "RadSlice");
0266 
0267   
0268   G4double radSliceThick = fRadThickness + fGasGap;
0269   G4double zStart = 0.5 * (-radThick + radSliceThick) + fDetGap;
0270   
0271 
0272   for (G4int j = 0; j < fFoilNumber; j++) {
0273     G4double zSlice = zStart + j * radSliceThick;
0274     G4cout << zSlice / mm << " mm"
0275            << "\t";
0276 
0277     fPhysiRadSlice = new G4PVPlacement(nullptr, G4ThreeVector(0., 0., zSlice), "RadSlice",
0278                                        fLogicRadSlice, fPhysiRadiator, false, j, checkOverlaps);
0279   }
0280   G4cout << G4endl;
0281 
0282   
0283 
0284   fSolidAbsorber =
0285     new G4Tubs("Absorber", 1.0 * mm, fAbsorberRadius, fAbsorberThickness / 2., 0.0, twopi);
0286 
0287   fLogicAbsorber = new G4LogicalVolume(fSolidAbsorber, fAbsorberMaterial, "Absorber");
0288 
0289   fPhysiAbsorber = new G4PVPlacement(nullptr, G4ThreeVector(0., 0., fZAbsorber), "Absorber",
0290                                      fLogicAbsorber, fPhysiWorld, false, 0, checkOverlaps);
0291 
0292   return fPhysiWorld;
0293 }
0294 
0295 
0296 
0297 void F03DetectorConstruction::PrintCalorParameters()
0298 {
0299   G4cout << "\n The  WORLD   is made of " << fWorldSizeZ / mm << "mm of "
0300          << fWorldMaterial->GetName();
0301   G4cout << ", the transverse size (R) of the world is " << fWorldSizeR / mm << " mm. " << G4endl;
0302   G4cout << " The ABSORBER is made of " << fAbsorberThickness / mm << "mm of "
0303          << fAbsorberMaterial->GetName();
0304   G4cout << ", the transverse size (R) is " << fAbsorberRadius / mm << " mm. " << G4endl;
0305   G4cout << " Z position of the (middle of the) absorber " << fZAbsorber / mm << "  mm." << G4endl;
0306   G4cout << G4endl;
0307 }
0308 
0309 
0310 
0311 void F03DetectorConstruction::SetAbsorberMaterial(G4String materialChoice)
0312 {
0313   
0314   const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
0315 
0316   
0317   G4Material* material;
0318   for (size_t j = 0; j < theMaterialTable->size(); j++) {
0319     material = (*theMaterialTable)[j];
0320     if (material->GetName() == materialChoice) {
0321       fAbsorberMaterial = material;
0322       fLogicAbsorber->SetMaterial(material);
0323       G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0324     }
0325   }
0326 }
0327 
0328 
0329 
0330 void F03DetectorConstruction::SetWorldMaterial(G4String materialChoice)
0331 {
0332   
0333   const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
0334 
0335   
0336   G4Material* material;
0337   for (size_t j = 0; j < theMaterialTable->size(); j++) {
0338     material = (*theMaterialTable)[j];
0339     if (material->GetName() == materialChoice) {
0340       fWorldMaterial = material;
0341       fLogicWorld->SetMaterial(material);
0342       G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0343     }
0344   }
0345 }
0346 
0347 
0348 
0349 void F03DetectorConstruction::SetAbsorberThickness(G4double val)
0350 {
0351   
0352   fAbsorberThickness = val;
0353   ComputeCalorParameters();
0354   G4RunManager::GetRunManager()->GeometryHasBeenModified();
0355 }
0356 
0357 
0358 
0359 void F03DetectorConstruction::SetAbsorberRadius(G4double val)
0360 {
0361   
0362   fAbsorberRadius = val;
0363   ComputeCalorParameters();
0364   G4RunManager::GetRunManager()->GeometryHasBeenModified();
0365 }
0366 
0367 
0368 
0369 void F03DetectorConstruction::SetWorldSizeZ(G4double val)
0370 {
0371   fWorldSizeZ = val;
0372   ComputeCalorParameters();
0373   G4RunManager::GetRunManager()->GeometryHasBeenModified();
0374 }
0375 
0376 
0377 
0378 void F03DetectorConstruction::SetWorldSizeR(G4double val)
0379 {
0380   fWorldSizeR = val;
0381   ComputeCalorParameters();
0382   G4RunManager::GetRunManager()->GeometryHasBeenModified();
0383 }
0384 
0385 
0386 
0387 void F03DetectorConstruction::SetAbsorberZpos(G4double val)
0388 {
0389   fZAbsorber = val;
0390   ComputeCalorParameters();
0391   G4RunManager::GetRunManager()->GeometryHasBeenModified();
0392 }
0393 
0394 
0395 
0396 void F03DetectorConstruction::SetFieldValue(G4ThreeVector value)
0397 {
0398   fFieldVector = value;
0399 
0400   G4UniformMagField* magField = nullptr;
0401   if (fFieldVector != G4ThreeVector(0.,0.,0.)) {
0402     magField = new G4UniformMagField(fFieldVector);
0403   }
0404 
0405   
0406   auto fieldBuilder = G4FieldBuilder::Instance();
0407   fieldBuilder->SetGlobalField(magField);
0408 }
0409 
0410 
0411 
0412 
0413 void F03DetectorConstruction::SetLocalFieldValue(G4ThreeVector value)
0414 {
0415   fLocalFieldVector = value;
0416 
0417   G4UniformMagField* magField = nullptr;
0418   if (fLocalFieldVector != G4ThreeVector(0.,0.,0.)) {
0419     magField = new G4UniformMagField(fLocalFieldVector);
0420   }
0421 
0422   
0423   auto fieldBuilder = G4FieldBuilder::Instance();
0424   fieldBuilder->SetLocalField(magField, fLogicRadiator);
0425 }
0426 
0427 
0428 
0429 void F03DetectorConstruction::ConstructSDandField()
0430 {
0431   
0432 
0433   if (!fCalorimeterSD.Get()) {
0434     auto calorimeterSD = new F03CalorimeterSD("CalorSD", this);
0435     fCalorimeterSD.Put(calorimeterSD);
0436   }
0437   G4SDManager::GetSDMpointer()->AddNewDetector(fCalorimeterSD.Get());
0438   SetSensitiveDetector(fLogicAbsorber, fCalorimeterSD.Get());
0439 
0440   
0441   SetFieldValue(fFieldVector);
0442   SetLocalFieldValue(fLocalFieldVector);
0443 
0444   
0445   auto fieldBuilder = G4FieldBuilder::Instance();
0446   fieldBuilder->ConstructFieldSetup();
0447 }
0448 
0449