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