File indexing completed on 2026-04-13 07:40:40
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 "GB03DetectorConstruction.hh"
0030
0031 #include "GB03BOptrGeometryBasedBiasing.hh"
0032 #include "GB03HodoSD.hh"
0033
0034 #include "G4Box.hh"
0035 #include "G4Colour.hh"
0036 #include "G4GenericMessenger.hh"
0037 #include "G4LogicalVolume.hh"
0038 #include "G4Material.hh"
0039 #include "G4PVPlacement.hh"
0040 #include "G4PVReplica.hh"
0041 #include "G4PhysicalConstants.hh"
0042 #include "G4RunManager.hh"
0043 #include "G4SDManager.hh"
0044 #include "G4SystemOfUnits.hh"
0045 #include "G4VisAttributes.hh"
0046 #include "G4ios.hh"
0047
0048 G4int GB03DetectorConstruction::fNumberOfLayers = 40;
0049 G4ThreadLocal G4bool GB03DetectorConstruction::fConstructedSDandField = false;
0050
0051
0052
0053 GB03DetectorConstruction::GB03DetectorConstruction(G4bool bf)
0054 : G4VUserDetectorConstruction(),
0055 fTotalThickness(2.0 * m),
0056 fLayerThickness(0.),
0057 fConstructed(false),
0058 fWorldMaterial(nullptr),
0059 fAbsorberMaterial(nullptr),
0060 fGapMaterial(nullptr),
0061 fLayerSolid(nullptr),
0062 fGapSolid(nullptr),
0063 fCalorLogical(nullptr),
0064 fLayerLogical(nullptr),
0065 fGapLogical(nullptr),
0066 fWorldPhysical(nullptr),
0067 fLayerPhysical(nullptr),
0068 fGapPhysical(nullptr),
0069 fDetectorMessenger(nullptr),
0070 fVerboseLevel(1),
0071 fBiasingFlag(bf)
0072 {
0073 fLayerThickness = fTotalThickness / fNumberOfLayers;
0074 fCalName = "Calor";
0075
0076 DefineMaterials();
0077
0078
0079 G4String matList;
0080 const G4MaterialTable* matTbl = G4Material::GetMaterialTable();
0081 for (size_t i = 0; i < G4Material::GetNumberOfMaterials(); i++) {
0082 matList += (*matTbl)[i]->GetName();
0083 matList += " ";
0084 }
0085
0086
0087 fDetectorMessenger = new G4GenericMessenger(this, "/GB03/", "UI commands of this example");
0088 fDetectorMessenger
0089 ->DeclareMethod("setAbsMat", &GB03DetectorConstruction::SetAbsorberMaterial,
0090 "Select Material of the Absorber.")
0091 .SetParameterName("material", false)
0092 .SetStates(G4State_Idle)
0093 .SetCandidates(matList);
0094
0095 fDetectorMessenger
0096 ->DeclareMethod("setGapMat", &GB03DetectorConstruction::SetGapMaterial,
0097 "Select Material of the Gap.")
0098 .SetParameterName("choice", false)
0099 .SetStates(G4State_Idle)
0100 .SetCandidates(matList);
0101
0102 fDetectorMessenger
0103 ->DeclareMethod("numberOfLayers", &GB03DetectorConstruction::SetNumberOfLayers,
0104 "Set number of layers.")
0105 .SetParameterName("nl", false)
0106 .SetStates(G4State_Idle)
0107 .SetRange("nl>0");
0108
0109 fDetectorMessenger
0110 ->DeclareMethod("verbose", &GB03DetectorConstruction::SetVerboseLevel, "Set verbosity level.")
0111 .SetParameterName("verbose", false)
0112 .SetStates(G4State_Idle)
0113 .SetRange("verbose>=0");
0114 }
0115
0116
0117
0118 GB03DetectorConstruction::~GB03DetectorConstruction()
0119 {
0120 delete fDetectorMessenger;
0121 }
0122
0123
0124
0125 G4VPhysicalVolume* GB03DetectorConstruction::Construct()
0126 {
0127 if (!fConstructed) {
0128 fConstructed = true;
0129 SetupGeometry();
0130 }
0131 if (GetVerboseLevel() > 0) {
0132 PrintCalorParameters();
0133 }
0134
0135 return fWorldPhysical;
0136 }
0137
0138
0139
0140 void GB03DetectorConstruction::ConstructSDandField()
0141 {
0142 if (!fConstructedSDandField) {
0143 fConstructedSDandField = true;
0144 SetupDetectors();
0145 if (fBiasingFlag) {
0146 SetupBiasing();
0147 }
0148 }
0149 }
0150
0151
0152
0153 void GB03DetectorConstruction::DefineMaterials()
0154 {
0155 G4String name, symbol;
0156 G4double a, z, density;
0157 G4int iz;
0158 G4int n;
0159
0160 G4int ncomponents, natoms;
0161 G4double abundance, fractionmass;
0162 G4double temperature, pressure;
0163
0164
0165
0166
0167
0168 a = 1.01 * g / mole;
0169 auto H = new G4Element(name = "Hydrogen", symbol = "H", z = 1., a);
0170
0171 a = 12.01 * g / mole;
0172 auto C = new G4Element(name = "Carbon", symbol = "C", z = 6., a);
0173
0174 a = 14.01 * g / mole;
0175 auto N = new G4Element(name = "Nitrogen", symbol = "N", z = 7., a);
0176
0177 a = 16.00 * g / mole;
0178 auto O = new G4Element(name = "Oxygen", symbol = "O", z = 8., a);
0179
0180
0181
0182
0183
0184 auto U5 = new G4Isotope(name = "U235", iz = 92, n = 235, a = 235.01 * g / mole);
0185 auto U8 = new G4Isotope(name = "U238", iz = 92, n = 238, a = 238.03 * g / mole);
0186
0187 auto U = new G4Element(name = "enriched Uranium", symbol = "U", ncomponents = 2);
0188 U->AddIsotope(U5, abundance = 90. * perCent);
0189 U->AddIsotope(U8, abundance = 10. * perCent);
0190
0191
0192
0193
0194
0195 new G4Material(name = "Aluminium", z = 13., a = 26.98 * g / mole, density = 2.700 * g / cm3);
0196 new G4Material(name = "Silicon", z = 14., a = 28.09 * g / mole, density = 2.33 * g / cm3);
0197 new G4Material(name = "Iron", z = 26., a = 55.85 * g / mole, density = 7.87 * g / cm3);
0198 new G4Material(name = "ArgonGas", z = 18., a = 39.95 * g / mole, density = 1.782 * mg / cm3);
0199 new G4Material(name = "He", z = 2., a = 4.0 * g / mole, density = 0.1786e-03 * g / cm3);
0200
0201 density = 1.390 * g / cm3;
0202 a = 39.95 * g / mole;
0203 new G4Material(name = "liquidArgon", z = 18., a, density);
0204
0205 density = 11.35 * g / cm3;
0206 a = 207.19 * g / mole;
0207 auto Pb = new G4Material(name = "Lead", z = 82., a, density);
0208
0209
0210
0211
0212
0213 density = 1.000 * g / cm3;
0214 auto H2O = new G4Material(name = "Water", density, ncomponents = 2);
0215 H2O->AddElement(H, natoms = 2);
0216 H2O->AddElement(O, natoms = 1);
0217
0218 density = 1.032 * g / cm3;
0219 auto Sci = new G4Material(name = "Scintillator", density, ncomponents = 2);
0220 Sci->AddElement(C, natoms = 9);
0221 Sci->AddElement(H, natoms = 10);
0222
0223
0224
0225
0226
0227 density = 1.290 * mg / cm3;
0228 auto Air = new G4Material(name = "Air", density, ncomponents = 2);
0229 Air->AddElement(N, fractionmass = 0.7);
0230 Air->AddElement(O, fractionmass = 0.3);
0231
0232
0233
0234
0235
0236 density = universe_mean_density;
0237 pressure = 3.e-18 * pascal;
0238 temperature = 2.73 * kelvin;
0239 auto Vacuum = new G4Material(name = "Galactic", z = 1., a = 1.01 * g / mole, density, kStateGas,
0240 temperature, pressure);
0241
0242 if (GetVerboseLevel() > 1) {
0243 G4cout << *(G4Material::GetMaterialTable()) << G4endl;
0244 }
0245
0246
0247 fWorldMaterial = Vacuum;
0248 fAbsorberMaterial = Pb;
0249 fGapMaterial = Sci;
0250 fHodoMaterial = Sci;
0251 }
0252
0253
0254
0255 void GB03DetectorConstruction::SetupGeometry()
0256 {
0257
0258
0259
0260 G4VSolid* worldSolid = new G4Box("World", 2. * m, 2. * m, fTotalThickness * 2.);
0261 auto* WorldLogical = new G4LogicalVolume(worldSolid, fWorldMaterial, "World");
0262 fWorldPhysical =
0263 new G4PVPlacement(nullptr, G4ThreeVector(), WorldLogical, "World", nullptr, false, 0);
0264
0265
0266
0267
0268 G4VSolid* calorSolid = new G4Box("Calor", 0.5 * m, 0.5 * m, fTotalThickness / 2.);
0269 fCalorLogical = new G4LogicalVolume(calorSolid, fAbsorberMaterial, fCalName);
0270 new G4PVPlacement(nullptr, G4ThreeVector(0., 0., 0.), fCalorLogical, fCalName, WorldLogical,
0271 false, 0);
0272
0273
0274
0275
0276 fLayerSolid = new G4Box("Layer", 0.5 * m, 0.5 * m, fLayerThickness / 2.);
0277 fLayerLogical = new G4LogicalVolume(fLayerSolid, fAbsorberMaterial, fCalName + "_LayerLog");
0278 fLayerPhysical = new G4PVReplica(fCalName + "_Layer", fLayerLogical, fCalorLogical, kZAxis,
0279 fNumberOfLayers, fLayerThickness);
0280
0281
0282
0283
0284 fGapSolid = new G4Box("Gap", 0.5 * m, 0.5 * m, fLayerThickness / 4.);
0285 fGapLogical = new G4LogicalVolume(fGapSolid, fGapMaterial, fCalName + "_Gap");
0286 fGapPhysical = new G4PVPlacement(nullptr, G4ThreeVector(0., 0., fLayerThickness / 4.),
0287 fGapLogical, fCalName + "_gap", fLayerLogical, false, 0);
0288
0289
0290
0291
0292 G4VSolid* measSolid = new G4Box("Hodo", 0.5 * m, 0.5 * m, 5 * cm);
0293 fHodoLogical = new G4LogicalVolume(measSolid, fHodoMaterial, "Hodo_l");
0294 new G4PVPlacement(nullptr, G4ThreeVector(0., 0., fTotalThickness / 2. + 5 * cm), fHodoLogical,
0295 "Hodo_p", WorldLogical, false, 0);
0296
0297
0298
0299 WorldLogical->SetVisAttributes(G4VisAttributes::GetInvisible());
0300 auto simpleBoxVisAtt = new G4VisAttributes(G4Colour(1.0, 1.0, 1.0));
0301 auto GapBoxVisAtt = new G4VisAttributes(G4Colour::Blue());
0302
0303 auto HodoBoxVisAtt = new G4VisAttributes(G4Colour::Red());
0304 simpleBoxVisAtt->SetVisibility(true);
0305 fCalorLogical->SetVisAttributes(simpleBoxVisAtt);
0306 fLayerLogical->SetVisAttributes(simpleBoxVisAtt);
0307 fGapLogical->SetVisAttributes(GapBoxVisAtt);
0308 fHodoLogical->SetVisAttributes(HodoBoxVisAtt);
0309 }
0310
0311
0312
0313 void GB03DetectorConstruction::SetupDetectors()
0314 {
0315
0316
0317
0318
0319 G4SDManager* SDman = G4SDManager::GetSDMpointer();
0320 G4VSensitiveDetector* sd = new GB03HodoSD("HodoSD");
0321 SDman->AddNewDetector(sd);
0322
0323 fHodoLogical->SetSensitiveDetector(sd);
0324 }
0325
0326
0327
0328 void GB03DetectorConstruction::SetupBiasing()
0329 {
0330 auto biasingOperator = new GB03BOptrGeometryBasedBiasing();
0331 biasingOperator->AttachTo(fLayerLogical);
0332 }
0333
0334
0335
0336 void GB03DetectorConstruction::PrintCalorParameters() const
0337 {
0338 G4cout << "--------------------------------------------------------" << G4endl;
0339 G4cout << " Absorber is made of " << fAbsorberMaterial->GetName() << G4endl << " Gap is made of "
0340 << fGapMaterial->GetName() << G4endl
0341 << "--------------------------------------------------------" << G4endl;
0342 }
0343
0344
0345
0346 void GB03DetectorConstruction::SetAbsorberMaterial(G4String materialChoice)
0347 {
0348
0349 G4Material* pttoMaterial = G4Material::GetMaterial(materialChoice);
0350 if (pttoMaterial) {
0351 fAbsorberMaterial = pttoMaterial;
0352 if (fConstructed) {
0353 fCalorLogical->SetMaterial(fAbsorberMaterial);
0354 fLayerLogical->SetMaterial(fAbsorberMaterial);
0355 }
0356 G4RunManager::GetRunManager()->GeometryHasBeenModified();
0357 if (GetVerboseLevel() > 1) {
0358 PrintCalorParameters();
0359 }
0360 }
0361 else {
0362 G4cerr << materialChoice << " is not defined. - Command is ignored." << G4endl;
0363 }
0364 }
0365
0366
0367
0368 G4String GB03DetectorConstruction::GetAbsorberMaterial() const
0369 {
0370 return fAbsorberMaterial->GetName();
0371 }
0372
0373
0374
0375 void GB03DetectorConstruction::SetGapMaterial(G4String materialChoice)
0376 {
0377
0378 G4Material* pttoMaterial = G4Material::GetMaterial(materialChoice);
0379 if (pttoMaterial) {
0380 fGapMaterial = pttoMaterial;
0381 if (fConstructed) {
0382 fGapLogical->SetMaterial(fGapMaterial);
0383 }
0384 G4RunManager::GetRunManager()->GeometryHasBeenModified();
0385 if (GetVerboseLevel() > 1) {
0386 PrintCalorParameters();
0387 }
0388 }
0389 else {
0390 G4cerr << materialChoice << " is not defined. - Command is ignored." << G4endl;
0391 }
0392 }
0393
0394
0395
0396 G4String GB03DetectorConstruction::GetGapMaterial() const
0397 {
0398 return fGapMaterial->GetName();
0399 }
0400
0401
0402
0403 void GB03DetectorConstruction::SetNumberOfLayers(G4int nl)
0404 {
0405 fNumberOfLayers = nl;
0406 fLayerThickness = fTotalThickness / fNumberOfLayers;
0407 if (!fConstructed) return;
0408
0409 fLayerSolid->SetZHalfLength(fLayerThickness / 2.);
0410 fGapSolid->SetZHalfLength(fLayerThickness / 4.);
0411
0412 fCalorLogical->RemoveDaughter(fLayerPhysical);
0413 delete fLayerPhysical;
0414 fLayerPhysical = new G4PVReplica(fCalName + "_Layer", fLayerLogical, fCalorLogical, kZAxis,
0415 fNumberOfLayers, fLayerThickness);
0416 fGapPhysical->SetTranslation(G4ThreeVector(0., 0., fLayerThickness / 4.));
0417
0418 G4RunManager::GetRunManager()->GeometryHasBeenModified();
0419 }
0420
0421