File indexing completed on 2025-02-23 09:22:47
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
0032
0033 #include "DetectorConstruction.hh"
0034
0035 #include "DetectorMessenger.hh"
0036
0037 #include "G4Box.hh"
0038 #include "G4LogicalVolume.hh"
0039 #include "G4Material.hh"
0040 #include "G4NistManager.hh"
0041 #include "G4PVPlacement.hh"
0042 #include "G4PVReplica.hh"
0043 #include "G4PhysicalConstants.hh"
0044 #include "G4ProductionCutsTable.hh"
0045 #include "G4Region.hh"
0046 #include "G4RunManager.hh"
0047 #include "G4SystemOfUnits.hh"
0048 #include "G4UnitsTable.hh"
0049
0050 #include <iomanip>
0051
0052
0053
0054 DetectorConstruction::DetectorConstruction()
0055 : fWorldMaterial(nullptr),
0056 fLogicWorld(nullptr),
0057 fPhysiWorld(nullptr),
0058 fLogicLayerFront(nullptr),
0059 fLogicLayerBack(nullptr)
0060 {
0061 for (G4int i = 0; i < kMaxAbsor; ++i) {
0062 fAbsorMaterial[i] = nullptr;
0063 fAbsorThickness[i] = 0.0;
0064 fLogicAbsorFront[i] = nullptr;
0065 fLogicAbsorBack[i] = nullptr;
0066 }
0067
0068
0069 fNbOfAbsor = 2;
0070 fAbsorThickness[1] = 2.3 * mm;
0071 fAbsorThickness[2] = 5.7 * mm;
0072 fNbOfLayers = 50;
0073 fCalorSizeYZ = 40. * cm;
0074 ComputeCalorParameters();
0075
0076
0077 SetWorldMaterial("G4_Galactic");
0078 SetAbsorMaterial(1, "G4_Pb");
0079 SetAbsorMaterial(2, "G4_lAr");
0080
0081
0082 fDetectorMessenger.reset(new DetectorMessenger(this));
0083 }
0084
0085
0086
0087 void DetectorConstruction::ComputeCalorParameters()
0088 {
0089
0090 fLayerThickness = 0.;
0091 for (G4int iAbs = 1; iAbs <= fNbOfAbsor; iAbs++) {
0092 fLayerThickness += fAbsorThickness[iAbs];
0093 }
0094 fCalorThickness = fNbOfLayers * fLayerThickness;
0095 fWorldSizeX = 1.2 * fCalorThickness;
0096 fWorldSizeYZ = 1.2 * fCalorSizeYZ;
0097 }
0098
0099
0100
0101 G4VPhysicalVolume* DetectorConstruction::Construct()
0102 {
0103 if (fPhysiWorld) {
0104 return fPhysiWorld;
0105 }
0106
0107 ComputeCalorParameters();
0108
0109
0110
0111
0112 auto* solidWorld = new G4Box("World",
0113 fWorldSizeX / 2, fWorldSizeYZ / 2,
0114 fWorldSizeYZ / 2);
0115
0116 fLogicWorld = new G4LogicalVolume(solidWorld,
0117 fWorldMaterial,
0118 "World");
0119
0120 fPhysiWorld = new G4PVPlacement(0,
0121 G4ThreeVector(),
0122 fLogicWorld,
0123 "World",
0124 0,
0125 false,
0126 0);
0127
0128
0129
0130
0131 auto* solidCalor =
0132 new G4Box("Calorimeter", fCalorThickness / 2, fCalorSizeYZ / 2, fCalorSizeYZ / 2);
0133
0134 auto* logicCalor = new G4LogicalVolume(solidCalor, fWorldMaterial, "Calorimeter");
0135
0136 new G4PVPlacement(0,
0137 G4ThreeVector(),
0138 logicCalor,
0139 "Calorimeter",
0140 fLogicWorld,
0141 false,
0142 0);
0143
0144
0145
0146
0147
0148 auto* solidLayer = new G4Box("Layer", fLayerThickness / 2, fCalorSizeYZ / 2, fCalorSizeYZ / 2);
0149
0150 fLogicLayerFront = new G4LogicalVolume(solidLayer, fWorldMaterial, "Layer-front");
0151 fLogicLayerBack = new G4LogicalVolume(solidLayer, fWorldMaterial, "Layer-back");
0152 G4double xfront = -0.5 * fCalorThickness;
0153 for (G4int l = 0; l < fNbOfLayers; ++l) {
0154 G4double xcenter = xfront + 0.5 * fLayerThickness;
0155 xfront += fLayerThickness;
0156 G4LogicalVolume* logicLayer = fLogicLayerFront;
0157 if (xcenter > 0) {
0158 logicLayer = fLogicLayerBack;
0159 }
0160
0161 new G4PVPlacement(0, G4ThreeVector(xcenter, 0, 0), logicLayer, "Layer", logicCalor, false, l);
0162 }
0163
0164
0165
0166
0167
0168 auto* regionFront = new G4Region("Front");
0169 regionFront->SetProductionCuts(
0170 G4ProductionCutsTable::GetProductionCutsTable()->GetDefaultProductionCuts());
0171 regionFront->AddRootLogicalVolume(fLogicLayerFront);
0172 auto* regionBack = new G4Region("Back");
0173 regionBack->SetProductionCuts(
0174 G4ProductionCutsTable::GetProductionCutsTable()->GetDefaultProductionCuts());
0175 regionBack->AddRootLogicalVolume(fLogicLayerBack);
0176
0177
0178
0179
0180
0181 xfront = -0.5 * fLayerThickness;
0182 for (G4int k = 1; k <= fNbOfAbsor; ++k) {
0183 auto* solidAbsor = new G4Box("Absorber",
0184 fAbsorThickness[k] / 2, fCalorSizeYZ / 2, fCalorSizeYZ / 2);
0185
0186 fLogicAbsorFront[k] = new G4LogicalVolume(solidAbsor,
0187 fAbsorMaterial[k],
0188 fAbsorMaterial[k]->GetName());
0189 fLogicAbsorBack[k] = new G4LogicalVolume(solidAbsor,
0190 fAbsorMaterial[k],
0191 fAbsorMaterial[k]->GetName());
0192
0193 G4double xcenter = xfront + 0.5 * fAbsorThickness[k];
0194 xfront += fAbsorThickness[k];
0195 new G4PVPlacement(0, G4ThreeVector(xcenter, 0., 0.), fLogicAbsorFront[k],
0196 fAbsorMaterial[k]->GetName(), fLogicLayerFront, false,
0197 k);
0198 new G4PVPlacement(0, G4ThreeVector(xcenter, 0., 0.), fLogicAbsorBack[k],
0199 fAbsorMaterial[k]->GetName(), fLogicLayerBack, false,
0200 k);
0201 }
0202
0203 PrintCalorParameters();
0204
0205
0206
0207 return fPhysiWorld;
0208 }
0209
0210
0211
0212 void DetectorConstruction::PrintCalorParameters()
0213 {
0214 G4cout << "\n-------------------------------------------------------------"
0215 << "\n ---> The calorimeter is " << fNbOfLayers << " layers of:";
0216 for (G4int i = 1; i <= fNbOfAbsor; ++i) {
0217 G4cout << "\n \t" << std::setw(12) << fAbsorMaterial[i]->GetName() << ": " << std::setw(6)
0218 << G4BestUnit(fAbsorThickness[i], "Length");
0219 }
0220 G4cout << "\n-------------------------------------------------------------\n";
0221
0222 G4cout << "\n" << fWorldMaterial << G4endl;
0223 for (G4int j = 1; j <= fNbOfAbsor; ++j) {
0224 G4cout << "\n" << fAbsorMaterial[j] << G4endl;
0225 }
0226 G4cout << "\n-------------------------------------------------------------\n";
0227 }
0228
0229
0230
0231 void DetectorConstruction::SetWorldMaterial(const G4String& material)
0232 {
0233
0234 G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(material);
0235 if (pttoMaterial) {
0236 fWorldMaterial = pttoMaterial;
0237 if (fLogicWorld) {
0238 fLogicWorld->SetMaterial(fWorldMaterial);
0239 fLogicLayerFront->SetMaterial(fWorldMaterial);
0240 fLogicLayerBack->SetMaterial(fWorldMaterial);
0241 G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0242 }
0243 }
0244 }
0245
0246
0247
0248 void DetectorConstruction::SetNbOfLayers(G4int ival)
0249 {
0250
0251
0252 if (ival < 2) {
0253 G4cout << "\n --->warning from SetfNbOfLayers: " << ival
0254 << " must be at least 2. Command refused" << G4endl;
0255 return;
0256 }
0257 fNbOfLayers = ival;
0258 }
0259
0260
0261
0262 void DetectorConstruction::SetNbOfAbsor(G4int ival)
0263 {
0264
0265
0266 if (ival < 1 || ival > (kMaxAbsor - 1)) {
0267 G4cout << "\n ---> warning from SetfNbOfAbsor: " << ival << " must be at least 1 and and most "
0268 << kMaxAbsor - 1 << ". Command refused" << G4endl;
0269 return;
0270 }
0271 fNbOfAbsor = ival;
0272 }
0273
0274
0275
0276 void DetectorConstruction::SetAbsorMaterial(G4int ival, const G4String& material)
0277 {
0278
0279
0280 if (ival > fNbOfAbsor || ival <= 0) {
0281 G4cout << "\n --->warning from SetAbsorMaterial: absor number " << ival
0282 << " out of range. Command refused" << G4endl;
0283 return;
0284 }
0285
0286 G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(material);
0287 if (pttoMaterial) {
0288 fAbsorMaterial[ival] = pttoMaterial;
0289 if (fLogicAbsorFront[ival]) {
0290 fLogicAbsorFront[ival]->SetMaterial(pttoMaterial);
0291 fLogicAbsorBack[ival]->SetMaterial(pttoMaterial);
0292 G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0293 }
0294 }
0295 }
0296
0297
0298
0299 void DetectorConstruction::SetAbsorThickness(G4int ival, G4double val)
0300 {
0301
0302
0303 if (ival > fNbOfAbsor || ival <= 0) {
0304 G4cout << "\n --->warning from SetAbsorThickness: absor number " << ival
0305 << " out of range. Command refused" << G4endl;
0306 return;
0307 }
0308 if (val <= DBL_MIN) {
0309 G4cout << "\n --->warning from SetAbsorThickness: thickness " << val
0310 << " out of range. Command refused" << G4endl;
0311 return;
0312 }
0313 fAbsorThickness[ival] = val;
0314 }
0315
0316
0317
0318 void DetectorConstruction::SetCalorSizeYZ(G4double val)
0319 {
0320
0321
0322 if (val <= DBL_MIN) {
0323 G4cout << "\n --->warning from SetfCalorSizeYZ: thickness " << val
0324 << " out of range. Command refused" << G4endl;
0325 return;
0326 }
0327 fCalorSizeYZ = val;
0328 }
0329
0330
0331
0332 #include "G4AutoDelete.hh"
0333 #include "G4GlobalMagFieldMessenger.hh"
0334
0335 void DetectorConstruction::ConstructSDandField()
0336 {
0337 if (fFieldMessenger.Get() == nullptr) {
0338
0339
0340
0341 G4ThreeVector fieldValue = G4ThreeVector();
0342 G4GlobalMagFieldMessenger* msg = new G4GlobalMagFieldMessenger(fieldValue);
0343
0344 G4AutoDelete::Register(msg);
0345 fFieldMessenger.Put(msg);
0346 }
0347 }
0348
0349