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