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