File indexing completed on 2026-03-28 07:51:07
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 "Par04DetectorConstruction.hh"
0030
0031 #include "Par04DefineMeshModel.hh" // for Par04DefineMeshModel
0032 #include "Par04DetectorMessenger.hh" // for Par04DetectorMessenger
0033 #include "Par04SensitiveDetector.hh" // for Par04SensitiveDetector
0034
0035 #include "G4Box.hh" // for G4Box
0036 #include "G4LogicalVolume.hh" // for G4LogicalVolume
0037 #include "G4Material.hh" // for G4Material
0038 #include "G4NistManager.hh" // for G4NistManager
0039 #include "G4PVPlacement.hh" // for G4PVPlacement
0040 #include "G4Region.hh" // for G4Region
0041 #include "G4RegionStore.hh" // for G4RegionStore
0042 #include "G4RunManager.hh" // for G4RunManager
0043 #include "G4SDManager.hh" // for G4SDManager
0044 #include "G4Tubs.hh" // for G4Tubs
0045 #include "G4UnitsTable.hh" // for operator<<, G4BestUnit
0046 #include "G4VisAttributes.hh" // for G4VisAttributes
0047
0048 #include <G4Colour.hh> // for G4Colour
0049 #include <G4Exception.hh> // for G4Exception
0050 #include <G4ExceptionSeverity.hh> // for FatalException
0051 #include <G4SystemOfUnits.hh> // for rad
0052 #include <G4ThreeVector.hh> // for G4ThreeVector
0053 #include <G4VUserDetectorConstruction.hh> // for G4VUserDetectorConstruction
0054 #include <G4ios.hh> // for G4endl, G4cout
0055 #include <algorithm> // for max
0056 #include <numeric> // for accumulate
0057 #include <ostream> // for operator<<, basic_ostream
0058 #include <string> // for allocator, char_traits
0059 class G4VPhysicalVolume;
0060 #ifdef USE_INFERENCE
0061 # include "Par04MLFastSimModel.hh"
0062 #endif
0063
0064
0065
0066 Par04DetectorConstruction::Par04DetectorConstruction() : G4VUserDetectorConstruction()
0067 {
0068 fDetectorMessenger = new Par04DetectorMessenger(this);
0069 G4NistManager* nistManager = G4NistManager::Instance();
0070 fAbsorberMaterial[0] = nistManager->FindOrBuildMaterial("G4_PbWO4");
0071 }
0072
0073
0074
0075 Par04DetectorConstruction::~Par04DetectorConstruction() = default;
0076
0077
0078
0079 G4VPhysicalVolume* Par04DetectorConstruction::Construct()
0080 {
0081
0082 G4NistManager* nistManager = G4NistManager::Instance();
0083 G4Material* air = nistManager->FindOrBuildMaterial("G4_AIR");
0084
0085
0086 G4double full2Pi = 2. * CLHEP::pi * rad;
0087 G4double layerThickness =
0088 std::accumulate(fAbsorberThickness.begin(), fAbsorberThickness.end(), 0.);
0089 G4double detectorOuterRadius = fDetectorInnerRadius + fNbOfLayers * layerThickness;
0090 G4double worldSizeXY = detectorOuterRadius * 4.;
0091 G4double worldSizeZ = fDetectorLength * 2;
0092
0093 G4int nbOfMaterials = 0;
0094 for (const auto material : fAbsorberMaterial) {
0095 if (material != nullptr) nbOfMaterials++;
0096 }
0097
0098
0099 auto fSolidWorld = new G4Box("World",
0100 worldSizeXY / 2.,
0101 worldSizeXY / 2.,
0102 worldSizeZ / 2.);
0103 auto fLogicWorld = new G4LogicalVolume(fSolidWorld,
0104 air,
0105 "World");
0106 auto fPhysicWorld = new G4PVPlacement(0,
0107 G4ThreeVector(),
0108 fLogicWorld,
0109 "World",
0110 0,
0111 false,
0112 99999,
0113 false);
0114 fLogicWorld->SetVisAttributes(G4VisAttributes::GetInvisible());
0115
0116
0117 auto fSolidDetector = new G4Tubs("Detector",
0118 fDetectorInnerRadius,
0119 detectorOuterRadius,
0120 fDetectorLength / 2.,
0121 0,
0122 full2Pi);
0123 auto fLogicDetector = new G4LogicalVolume(fSolidDetector,
0124 air,
0125 "Detector");
0126 new G4PVPlacement(0,
0127 G4ThreeVector(0, 0, 0),
0128 fLogicDetector,
0129 "Detector",
0130 fLogicWorld,
0131 false,
0132 999,
0133 false);
0134
0135
0136 auto detectorRegion = new G4Region("DetectorRegion");
0137 detectorRegion->AddRootLogicalVolume(fLogicDetector);
0138
0139
0140 std::array<G4VisAttributes, 2> attribs;
0141 attribs[0].SetColour(G4Colour(0, 0, 1, 0.1));
0142 attribs[0].SetForceSolid(true);
0143 attribs[1].SetColour(G4Colour(1, 0, 0, 0.1));
0144 attribs[1].SetForceSolid(true);
0145
0146 G4double innerRadius = fDetectorInnerRadius;
0147 for (G4int iLayer = 0; iLayer < fNbOfLayers; iLayer++) {
0148 for (G4int iMaterial = 0; iMaterial < nbOfMaterials; iMaterial++) {
0149 auto fSolidLayer = new G4Tubs("Layer",
0150 innerRadius,
0151 innerRadius + fAbsorberThickness[iMaterial],
0152 fDetectorLength / 2.,
0153 0,
0154 full2Pi);
0155 G4LogicalVolume* logical = new G4LogicalVolume(fSolidLayer,
0156 fAbsorberMaterial[iMaterial],
0157 "Layer");
0158 new G4PVPlacement(0,
0159 G4ThreeVector(),
0160 logical,
0161 "Layer",
0162 fLogicDetector,
0163 false,
0164 iLayer * nbOfMaterials + iMaterial,
0165 false);
0166 logical->SetVisAttributes(attribs[iMaterial]);
0167 innerRadius += fAbsorberThickness[iMaterial];
0168 if (fAbsorberSensitivity[iMaterial]) {
0169 fLayerLogical.push_back(logical);
0170 }
0171 }
0172 }
0173
0174 Print();
0175 return fPhysicWorld;
0176 }
0177
0178
0179
0180 void Par04DetectorConstruction::ConstructSDandField()
0181 {
0182 Par04SensitiveDetector* caloSD =
0183 new Par04SensitiveDetector("sensitiveDetector", fMeshNbOfCells, fMeshSizeOfCells);
0184 G4SDManager::GetSDMpointer()->AddNewDetector(caloSD);
0185 for (const auto logical : fLayerLogical) {
0186 SetSensitiveDetector(logical, caloSD);
0187 }
0188
0189 auto detectorRegion = G4RegionStore::GetInstance()->GetRegion("DetectorRegion");
0190
0191 new Par04DefineMeshModel("defineMesh", detectorRegion);
0192 #ifdef USE_INFERENCE
0193 new Par04MLFastSimModel("inferenceModel", detectorRegion);
0194 #endif
0195 }
0196
0197
0198
0199 void Par04DetectorConstruction::Print() const
0200 {
0201 G4cout << "\n------------------------------------------------------"
0202 << "\n--- Detector length:\t" << G4BestUnit(fDetectorLength, "Length")
0203 << "\n--- Detector inner radius:\t" << G4BestUnit(fDetectorInnerRadius, "Length")
0204 << "\n--- Number of layers:\t" << fNbOfLayers << G4endl << "\n--- 1st layer: \t"
0205 << G4BestUnit(fAbsorberThickness[0], "Length") << " of "
0206 << (fAbsorberSensitivity[0] ? "active " : "passive ") << fAbsorberMaterial[0]->GetName()
0207 << G4endl;
0208 if (fAbsorberMaterial[1] != nullptr)
0209 G4cout << "--- 2nd layer: \t" << G4BestUnit(fAbsorberThickness[1], "Length") << " of "
0210 << (fAbsorberSensitivity[1] ? "active " : "passive ") << fAbsorberMaterial[1]->GetName()
0211 << G4endl;
0212 G4cout << "-----------------------------------------------------" << G4endl;
0213 }
0214
0215
0216
0217 void Par04DetectorConstruction::SetAbsorberMaterial(const std::size_t aLayer, const G4String& aName)
0218 {
0219
0220 G4Material* material = G4NistManager::Instance()->FindOrBuildMaterial(aName);
0221 if (material)
0222 fAbsorberMaterial[aLayer] = material;
0223 else
0224 G4Exception("Par04DetectorConstruction::SetAbsorberMaterial()", "InvalidSetup", FatalException,
0225 ("Unknown material name: " + aName).c_str());
0226 G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0227 }
0228
0229
0230
0231 void Par04DetectorConstruction::SetAbsorberThickness(const std::size_t aLayer,
0232 const G4double aThickness)
0233 {
0234 if (aLayer < fAbsorberThickness.size())
0235 fAbsorberThickness[aLayer] = aThickness;
0236 else
0237 G4Exception("Par04DetectorConstruction::SetAbsorberThickness()", "InvalidSetup", FatalException,
0238 ("Requested layer " + std::to_string(aLayer)
0239 + " is larger than number of available layers ("
0240 + std::to_string(fAbsorberThickness.size()) + ").")
0241 .c_str());
0242 G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0243 }
0244
0245
0246
0247 void Par04DetectorConstruction::SetAbsorberSensitivity(const std::size_t aLayer,
0248 const G4bool aSensitivity)
0249 {
0250 if (aLayer < fAbsorberSensitivity.size())
0251 fAbsorberSensitivity[aLayer] = aSensitivity;
0252 else
0253 G4Exception(
0254 "Par04DetectorConstruction::SetAbsorberSensitivity()", "InvalidSetup", FatalException,
0255 ("Requested layer " + std::to_string(aLayer) + " is larger than number of available layers ("
0256 + std::to_string(fAbsorberSensitivity.size()) + ").")
0257 .c_str());
0258 G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0259 }
0260
0261
0262
0263 void Par04DetectorConstruction::SetInnerRadius(G4double aRadius)
0264 {
0265 fDetectorInnerRadius = aRadius;
0266 }
0267
0268
0269
0270 void Par04DetectorConstruction::SetLength(G4double aLength)
0271 {
0272 fDetectorLength = aLength;
0273 }