File indexing completed on 2025-02-23 09:22:46
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 #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
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
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
0127
0128 void RE06DetectorConstruction::DefineMaterials()
0129 {
0130 G4String name, symbol;
0131 G4double a, z, density;
0132 G4int iz;
0133 G4int n;
0134
0135 G4int ncomponents, natoms;
0136 G4double abundance, fractionmass;
0137 G4double temperature, pressure;
0138
0139
0140
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
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
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
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
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
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
0222 fWorldMaterial = Vacuum;
0223 fAbsorberMaterial = Pb;
0224 fGapMaterial = lAr;
0225 }
0226
0227
0228
0229 void RE06DetectorConstruction::SetupGeometry()
0230 {
0231
0232
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
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
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
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
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
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
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
0320
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
0332
0333
0334
0335
0336
0337
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
0392
0393 void RE06DetectorConstruction::SetAbsorberMaterial(G4String materialChoice)
0394 {
0395
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
0415
0416 G4String RE06DetectorConstruction::GetAbsorberMaterial() const
0417 {
0418 return fAbsorberMaterial->GetName();
0419 }
0420
0421
0422
0423 void RE06DetectorConstruction::SetGapMaterial(G4String materialChoice)
0424 {
0425
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
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
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
0491
0492 void RE06DetectorConstruction::AddMaterial()
0493 {
0494 static G4bool isAdded = false;
0495
0496 if (isAdded) return;
0497
0498 G4String name, symbol;
0499 G4double a, z, density;
0500
0501 G4int ncomponents, natoms;
0502
0503
0504
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