File indexing completed on 2026-04-01 07:50:48
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 "DetectorConstruction.hh"
0030
0031 #include "DetectorMessenger.hh"
0032
0033 #include "G4Box.hh"
0034 #include "G4GeometryManager.hh"
0035 #include "G4LogicalVolume.hh"
0036 #include "G4LogicalVolumeStore.hh"
0037 #include "G4Material.hh"
0038 #include "G4NistManager.hh"
0039 #include "G4PVPlacement.hh"
0040 #include "G4PVReplica.hh"
0041 #include "G4PhysicalConstants.hh"
0042 #include "G4PhysicalVolumeStore.hh"
0043 #include "G4RunManager.hh"
0044 #include "G4SolidStore.hh"
0045 #include "G4SystemOfUnits.hh"
0046 #include "G4UnitsTable.hh"
0047
0048 #include <iomanip>
0049
0050
0051
0052 DetectorConstruction::DetectorConstruction()
0053 {
0054 for (G4int i = 0; i < kMaxAbsor; ++i) {
0055 fAbsorMaterial[i] = nullptr;
0056 fAbsorThickness[i] = 0.0;
0057 fSolidAbsor[i] = nullptr;
0058 fLogicAbsor[i] = nullptr;
0059 fPhysiAbsor[i] = nullptr;
0060 }
0061
0062
0063 fNbOfAbsor = 2;
0064 fAbsorThickness[1] = 36 * mm;
0065 fAbsorThickness[2] = 4 * mm;
0066 fNbOfLayers = 50;
0067 fCalorSizeYZ = 1.5 * m;
0068 ComputeCalorParameters();
0069
0070
0071 DefineMaterials();
0072 SetWorldMaterial("Galactic");
0073 SetAbsorMaterial(1, "Iron");
0074 SetAbsorMaterial(2, "Scintillator");
0075
0076
0077 fDetectorMessenger = new DetectorMessenger(this);
0078 }
0079
0080
0081
0082 DetectorConstruction::~DetectorConstruction()
0083 {
0084 delete fDetectorMessenger;
0085 }
0086
0087
0088
0089 void DetectorConstruction::DefineMaterials()
0090 {
0091
0092
0093 G4NistManager* manager = G4NistManager::Instance();
0094 manager->SetVerbose(0);
0095
0096
0097
0098 G4Element* H = manager->FindOrBuildElement(1);
0099 G4Element* C = manager->FindOrBuildElement(6);
0100 G4Element* O = manager->FindOrBuildElement(8);
0101
0102
0103
0104 G4int iz, n;
0105
0106 G4int ncomponents;
0107 G4double z, a;
0108 G4double abundance;
0109
0110 G4Isotope* U5 = new G4Isotope("U235", iz = 92, n = 235, a = 235.01 * g / mole);
0111 G4Isotope* U8 = new G4Isotope("U238", iz = 92, n = 238, a = 238.03 * g / mole);
0112
0113 G4Element* U = new G4Element("enriched Uranium", "U", ncomponents = 2);
0114 U->AddIsotope(U5, abundance = 90. * perCent);
0115 U->AddIsotope(U8, abundance = 10. * perCent);
0116
0117
0118
0119
0120 G4double density;
0121
0122 new G4Material("liquidH2", z = 1., a = 1.008 * g / mole, density = 70.8 * mg / cm3);
0123 new G4Material("Aluminium", z = 13., a = 26.98 * g / mole, density = 2.700 * g / cm3);
0124 new G4Material("liquidArgon", z = 18, a = 39.948 * g / mole, density = 1.396 * g / cm3);
0125 new G4Material("Titanium", z = 22., a = 47.867 * g / mole, density = 4.54 * g / cm3);
0126 new G4Material("Iron", z = 26., a = 55.85 * g / mole, density = 7.870 * g / cm3);
0127 new G4Material("Copper", z = 29., a = 63.55 * g / mole, density = 8.960 * g / cm3);
0128 new G4Material("Tungsten", z = 74., a = 183.85 * g / mole, density = 19.30 * g / cm3);
0129 new G4Material("Gold", z = 79., a = 196.97 * g / mole, density = 19.32 * g / cm3);
0130 new G4Material("Lead", z = 82., a = 207.20 * g / mole, density = 11.35 * g / cm3);
0131 new G4Material("Uranium", z = 92., a = 238.03 * g / mole, density = 18.95 * g / cm3);
0132
0133
0134
0135
0136 G4int natoms;
0137
0138 G4Material* H2O = new G4Material("Water", density = 1.000 * g / cm3, ncomponents = 2);
0139 H2O->AddElement(H, natoms = 2);
0140 H2O->AddElement(O, natoms = 1);
0141 H2O->GetIonisation()->SetMeanExcitationEnergy(78.0 * eV);
0142 H2O->SetChemicalFormula("H_2O");
0143
0144 G4Material* CH = new G4Material("Polystyrene", density = 1.032 * g / cm3, ncomponents = 2);
0145 CH->AddElement(C, natoms = 1);
0146 CH->AddElement(H, natoms = 1);
0147
0148 G4Material* Sci = new G4Material("Scintillator", density = 1.032 * g / cm3, ncomponents = 2);
0149 Sci->AddElement(C, natoms = 9);
0150 Sci->AddElement(H, natoms = 10);
0151
0152 Sci->GetIonisation()->SetBirksConstant(0.126 * mm / MeV);
0153
0154
0155
0156
0157 G4double temperature, pressure;
0158
0159 G4Material* CO2 =
0160 new G4Material("CarbonicGas", density = 27. * mg / cm3, ncomponents = 2, kStateGas,
0161 temperature = 325. * kelvin, pressure = 50. * atmosphere);
0162 CO2->AddElement(C, natoms = 1);
0163 CO2->AddElement(O, natoms = 2);
0164
0165 new G4Material("ArgonGas", z = 18, a = 39.948 * g / mole, density = 1.782 * mg / cm3, kStateGas,
0166 273.15 * kelvin, 1 * atmosphere);
0167
0168
0169
0170 density = universe_mean_density;
0171 pressure = 3.e-18 * pascal;
0172 temperature = 2.73 * kelvin;
0173 new G4Material("Galactic", z = 1., a = 1.008 * g / mole, density, kStateGas, temperature,
0174 pressure);
0175
0176
0177 }
0178
0179
0180
0181 G4Material* DetectorConstruction::MaterialWithSingleIsotope(G4String name, G4String symbol,
0182 G4double density, G4int Z, G4int A)
0183 {
0184
0185
0186 G4int ncomponents;
0187 G4double abundance, massfraction;
0188
0189 G4Isotope* isotope = new G4Isotope(symbol, Z, A);
0190
0191 G4Element* element = new G4Element(name, symbol, ncomponents = 1);
0192 element->AddIsotope(isotope, abundance = 100. * perCent);
0193
0194 G4Material* material = new G4Material(name, density, ncomponents = 1);
0195 material->AddElement(element, massfraction = 100. * perCent);
0196
0197 return material;
0198 }
0199
0200
0201
0202 void DetectorConstruction::ComputeCalorParameters()
0203 {
0204
0205 fLayerThickness = 0.;
0206 for (G4int iAbs = 1; iAbs <= fNbOfAbsor; iAbs++) {
0207 fLayerThickness += fAbsorThickness[iAbs];
0208 }
0209 fCalorThickness = fNbOfLayers * fLayerThickness;
0210 fWorldSizeX = 1.2 * fCalorThickness;
0211 fWorldSizeYZ = 1.2 * fCalorSizeYZ;
0212 }
0213
0214
0215
0216 G4VPhysicalVolume* DetectorConstruction::Construct()
0217 {
0218 if (fPhysiWorld) {
0219 return fPhysiWorld;
0220 }
0221
0222 ComputeCalorParameters();
0223
0224
0225
0226
0227 fSolidWorld = new G4Box("World",
0228 fWorldSizeX / 2, fWorldSizeYZ / 2, fWorldSizeYZ / 2);
0229
0230 fLogicWorld = new G4LogicalVolume(fSolidWorld,
0231 fWorldMaterial,
0232 "World");
0233
0234 fPhysiWorld = new G4PVPlacement(0,
0235 G4ThreeVector(),
0236 fLogicWorld,
0237 "World",
0238 0,
0239 false,
0240 0);
0241
0242
0243
0244
0245 fSolidCalor = new G4Box("Calorimeter", fCalorThickness / 2, fCalorSizeYZ / 2, fCalorSizeYZ / 2);
0246
0247 fLogicCalor = new G4LogicalVolume(fSolidCalor, fWorldMaterial, "Calorimeter");
0248
0249 fPhysiCalor = new G4PVPlacement(0,
0250 G4ThreeVector(),
0251 fLogicCalor,
0252 "Calorimeter",
0253 fLogicWorld,
0254 false,
0255 0);
0256
0257
0258
0259
0260
0261 fSolidLayer = new G4Box("Layer", fLayerThickness / 2, fCalorSizeYZ / 2, fCalorSizeYZ / 2);
0262
0263 fLogicLayer = new G4LogicalVolume(fSolidLayer, fWorldMaterial, "Layer");
0264 if (fNbOfLayers > 1) {
0265 fPhysiLayer =
0266 new G4PVReplica("Layer", fLogicLayer, fLogicCalor, kXAxis, fNbOfLayers, fLayerThickness);
0267 }
0268 else {
0269 fPhysiLayer =
0270 new G4PVPlacement(0, G4ThreeVector(), fLogicLayer, "Layer", fLogicCalor, false, 0);
0271 }
0272
0273
0274
0275
0276 G4double xfront = -0.5 * fLayerThickness;
0277 for (G4int k = 1; k <= fNbOfAbsor; ++k) {
0278 fSolidAbsor[k] = new G4Box("Absorber",
0279 fAbsorThickness[k] / 2, fCalorSizeYZ / 2, fCalorSizeYZ / 2);
0280
0281 fLogicAbsor[k] = new G4LogicalVolume(fSolidAbsor[k],
0282 fAbsorMaterial[k],
0283 fAbsorMaterial[k]->GetName());
0284
0285 G4double xcenter = xfront + 0.5 * fAbsorThickness[k];
0286 xfront += fAbsorThickness[k];
0287 fPhysiAbsor[k] = new G4PVPlacement(0, G4ThreeVector(xcenter, 0., 0.), fLogicAbsor[k],
0288 fAbsorMaterial[k]->GetName(), fLogicLayer, false,
0289 k);
0290 }
0291
0292 PrintCalorParameters();
0293
0294
0295
0296 return fPhysiWorld;
0297 }
0298
0299
0300
0301 void DetectorConstruction::PrintCalorParameters()
0302 {
0303 G4int prec = 4, wid = prec + 2;
0304 G4int dfprec = G4cout.precision(prec);
0305
0306 G4double totLength(0.), totRadl(0.), totNuclear(0.);
0307
0308 G4cout << "\n-------------------------------------------------------------"
0309 << "\n ---> The calorimeter is " << fNbOfLayers << " layers of:";
0310 for (G4int i = 1; i <= fNbOfAbsor; ++i) {
0311 G4Material* material = fAbsorMaterial[i];
0312 G4double radl = material->GetRadlen();
0313 G4double nuclearl = material->GetNuclearInterLength();
0314 G4double sumThickness = fNbOfLayers * fAbsorThickness[i];
0315 G4double nbRadl = sumThickness / radl;
0316 G4double nbNuclearl = sumThickness / nuclearl;
0317 totLength += sumThickness;
0318 totRadl += nbRadl;
0319 totNuclear += nbNuclearl;
0320 G4cout << "\n " << std::setw(12) << fAbsorMaterial[i]->GetName() << ": " << std::setw(wid)
0321 << G4BestUnit(fAbsorThickness[i], "Length") << " ---> sum = " << std::setw(wid)
0322 << G4BestUnit(sumThickness, "Length") << " = " << std::setw(wid) << nbRadl << " Radl "
0323 << " = " << std::setw(wid) << nbNuclearl << " NuclearInteractionLength ";
0324 }
0325 G4cout << "\n\n total thickness = " << std::setw(wid)
0326 << G4BestUnit(totLength, "Length") << " = " << std::setw(wid) << totRadl << " Radl "
0327 << " = " << std::setw(wid) << totNuclear << " NuclearInteractionLength " << G4endl;
0328
0329 G4cout << " transverse sizeYZ = " << std::setw(wid)
0330 << G4BestUnit(fCalorSizeYZ, "Length") << G4endl;
0331 G4cout << "-------------------------------------------------------------\n";
0332
0333 G4cout << "\n" << fWorldMaterial << G4endl;
0334 for (G4int j = 1; j <= fNbOfAbsor; ++j) {
0335 G4cout << "\n" << fAbsorMaterial[j] << G4endl;
0336 }
0337 G4cout << "\n-------------------------------------------------------------\n";
0338
0339
0340 G4cout.precision(dfprec);
0341 }
0342
0343
0344
0345 void DetectorConstruction::SetWorldMaterial(const G4String& material)
0346 {
0347
0348 G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(material);
0349 if (pttoMaterial) {
0350 fWorldMaterial = pttoMaterial;
0351 if (fLogicWorld) {
0352 fLogicWorld->SetMaterial(fWorldMaterial);
0353 fLogicLayer->SetMaterial(fWorldMaterial);
0354 G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0355 }
0356 }
0357 }
0358
0359
0360
0361 void DetectorConstruction::SetNbOfLayers(G4int ival)
0362 {
0363
0364
0365 if (ival < 1) {
0366 G4cout << "\n --->warning from SetfNbOfLayers: " << ival
0367 << " must be at least 1. Command refused" << G4endl;
0368 return;
0369 }
0370 fNbOfLayers = ival;
0371 }
0372
0373
0374
0375 void DetectorConstruction::SetNbOfAbsor(G4int ival)
0376 {
0377
0378
0379 if (ival < 1 || ival > (kMaxAbsor - 1)) {
0380 G4cout << "\n ---> warning from SetfNbOfAbsor: " << ival << " must be at least 1 and and most "
0381 << kMaxAbsor - 1 << ". Command refused" << G4endl;
0382 return;
0383 }
0384 fNbOfAbsor = ival;
0385 }
0386
0387
0388
0389 void DetectorConstruction::SetAbsorMaterial(G4int ival, const G4String& material)
0390 {
0391
0392
0393 if (ival > fNbOfAbsor || ival <= 0) {
0394 G4cout << "\n --->warning from SetAbsorMaterial: absor number " << ival
0395 << " out of range. Command refused" << G4endl;
0396 return;
0397 }
0398
0399 G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(material);
0400 if (pttoMaterial) {
0401 fAbsorMaterial[ival] = pttoMaterial;
0402 if (fLogicAbsor[ival]) {
0403 fLogicAbsor[ival]->SetMaterial(pttoMaterial);
0404 G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0405 }
0406 }
0407 }
0408
0409
0410
0411 void DetectorConstruction::SetAbsorThickness(G4int ival, G4double val)
0412 {
0413
0414
0415 if (ival > fNbOfAbsor || ival <= 0) {
0416 G4cout << "\n --->warning from SetAbsorThickness: absor number " << ival
0417 << " out of range. Command refused" << G4endl;
0418 return;
0419 }
0420 if (val <= DBL_MIN) {
0421 G4cout << "\n --->warning from SetAbsorThickness: thickness " << val
0422 << " out of range. Command refused" << G4endl;
0423 return;
0424 }
0425 fAbsorThickness[ival] = val;
0426 }
0427
0428
0429
0430 void DetectorConstruction::SetCalorSizeYZ(G4double val)
0431 {
0432
0433
0434 if (val <= DBL_MIN) {
0435 G4cout << "\n --->warning from SetfCalorSizeYZ: thickness " << val
0436 << " out of range. Command refused" << G4endl;
0437 return;
0438 }
0439 fCalorSizeYZ = val;
0440 }
0441
0442
0443
0444 #include "G4AutoDelete.hh"
0445 #include "G4GlobalMagFieldMessenger.hh"
0446
0447 void DetectorConstruction::ConstructSDandField()
0448 {
0449 if (fFieldMessenger.Get() == nullptr) {
0450
0451
0452
0453 G4ThreeVector fieldValue = G4ThreeVector();
0454 G4GlobalMagFieldMessenger* msg = new G4GlobalMagFieldMessenger(fieldValue);
0455
0456 G4AutoDelete::Register(msg);
0457 fFieldMessenger.Put(msg);
0458 }
0459 }
0460
0461