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