Loading...
Searching...
No Matches
Par04DetectorConstruction.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
27#include <G4Colour.hh> // for G4Colour
28#include <G4Exception.hh> // for G4Exception
29#include <G4ExceptionSeverity.hh> // for FatalException
30#include <G4SystemOfUnits.hh> // for rad
31#include <G4ThreeVector.hh> // for G4ThreeVector
32#include <G4VUserDetectorConstruction.hh> // for G4VUserDetectorConstruction
33#include <G4ios.hh> // for G4endl, G4cout
34#include <algorithm> // for max
35#include <numeric> // for accumulate
36#include <ostream> // for operator<<, basic_ostream
37#include <string> // for allocator, char_traits
38#include "G4Box.hh" // for G4Box
39#include "G4LogicalVolume.hh" // for G4LogicalVolume
40#include "G4Material.hh" // for G4Material
41#include "G4NistManager.hh" // for G4NistManager
42#include "G4PVPlacement.hh" // for G4PVPlacement
43#include "G4Region.hh" // for G4Region
44#include "G4RegionStore.hh" // for G4RegionStore
45#include "G4RunManager.hh" // for G4RunManager
46#include "G4SDManager.hh" // for G4SDManager
47#include "G4Tubs.hh" // for G4Tubs
48#include "G4UnitsTable.hh" // for operator<<, G4BestUnit
49#include "G4VisAttributes.hh" // for G4VisAttributes
50#include "Par04DefineMeshModel.hh" // for Par04DefineMeshModel
51#include "Par04DetectorMessenger.hh" // for Par04DetectorMessenger
52#include "Par04SensitiveDetector.hh" // for Par04SensitiveDetector
54#ifdef USE_INFERENCE
56#endif
57
58//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
59
62{
64 G4NistManager* nistManager = G4NistManager::Instance();
65 fAbsorberMaterial[0] = nistManager->FindOrBuildMaterial("G4_PbWO4");
66}
67
68//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
69
71
72//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
73
75{
76 //--------- Material definition ---------
77 G4NistManager* nistManager = G4NistManager::Instance();
78 G4Material* air = nistManager->FindOrBuildMaterial("G4_AIR");
79
80 //--------- Derived dimensions ---------
81 G4double full2Pi = 2. * CLHEP::pi * rad;
82 G4double layerThickness =
83 std::accumulate(fAbsorberThickness.begin(), fAbsorberThickness.end(), 0.);
84 G4double detectorOuterRadius = fDetectorInnerRadius + fNbOfLayers * layerThickness;
85 G4double worldSizeXY = detectorOuterRadius * 4.;
86 G4double worldSizeZ = fDetectorLength * 2;
87 // check number of materials: (1 = homogeneous calo, 2 = sampling calo)
88 G4int nbOfMaterials = 0;
89 for(const auto material : fAbsorberMaterial)
90 {
91 if(material != nullptr)
92 nbOfMaterials++;
93 }
94
95 //--------- World ---------
96 auto fSolidWorld = new G4Box("World", // name
97 worldSizeXY / 2., // half-width in X
98 worldSizeXY / 2., // half-width in Y
99 worldSizeZ / 2.); // half-width in Z
100 auto fLogicWorld = new G4LogicalVolume(fSolidWorld, // solid
101 air, // material
102 "World"); // name
103 auto fPhysicWorld = new G4PVPlacement(0, // no rotation
104 G4ThreeVector(), // at (0,0,0)
105 fLogicWorld, // logical volume
106 "World", // name
107 0, // mother volume
108 false, // not used
109 99999, // copy number
110 false); // check overlaps
111 fLogicWorld->SetVisAttributes(G4VisAttributes::GetInvisible());
112
113 //--------- Detector envelope ---------
114 auto fSolidDetector = new G4Tubs("Detector", // name
115 fDetectorInnerRadius, // inner radius
116 detectorOuterRadius, // outer radius
117 fDetectorLength / 2., // half-width in Z
118 0, // start angle
119 full2Pi); // delta angle
120 auto fLogicDetector = new G4LogicalVolume(fSolidDetector, // solid
121 air, // material
122 "Detector"); // name
123 new G4PVPlacement(0, // no rotation
124 G4ThreeVector(0, 0, 0), // detector centre at (0,0,0)
125 fLogicDetector, // logical volume
126 "Detector", // name
127 fLogicWorld, // mother volume
128 false, // not used
129 999, // copy number
130 false); // check overlaps
131
132 // Region for fast simulation
133 auto detectorRegion = new G4Region("DetectorRegion");
134 detectorRegion->AddRootLogicalVolume(fLogicDetector);
135
136 //--------- Detector layers: material ---------
137 std::array<G4VisAttributes, 2> attribs;
138 attribs[0].SetColour(G4Colour(0, 0, 1, 0.1));
139 attribs[0].SetForceSolid(true);
140 attribs[1].SetColour(G4Colour(1, 0, 0, 0.1));
141 attribs[1].SetForceSolid(true);
142 /// useful variable
143 G4double innerRadius = fDetectorInnerRadius;
144 for(G4int iLayer = 0; iLayer < fNbOfLayers; iLayer++)
145 {
146 for(G4int iMaterial = 0; iMaterial < nbOfMaterials; iMaterial++)
147 {
148 auto fSolidLayer = new G4Tubs("Layer", // name
149 innerRadius, // inner radius
150 innerRadius + fAbsorberThickness[iMaterial], // outer radius
151 fDetectorLength / 2., // half-width in Z
152 0, // start angle
153 full2Pi); // delta angle
154 G4LogicalVolume* logical = new G4LogicalVolume(fSolidLayer, // solid
155 fAbsorberMaterial[iMaterial], // material
156 "Layer"); // name
157 new G4PVPlacement(0, // no rotation
158 G4ThreeVector(), // place at centre of mother volume
159 logical, // logical volume
160 "Layer", // name
161 fLogicDetector, // mother volume
162 false, // not used
163 iLayer * nbOfMaterials + iMaterial, // copy number
164 false); // check overlaps
165 logical->SetVisAttributes(attribs[iMaterial]);
166 innerRadius += fAbsorberThickness[iMaterial];
167 if(fAbsorberSensitivity[iMaterial])
168 {
169 fLayerLogical.push_back(logical);
170 }
171 }
172 }
173
174 Print();
175 return fPhysicWorld;
176}
177
178//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
179
181{
182 Par04SensitiveDetector* caloSD =
183 new Par04SensitiveDetector("sensitiveDetector", fMeshNbOfCells, fMeshSizeOfCells);
184 G4SDManager::GetSDMpointer()->AddNewDetector(caloSD);
185 for(const auto logical : fLayerLogical)
186 {
187 SetSensitiveDetector(logical, caloSD);
188 }
189
190 auto detectorRegion = G4RegionStore::GetInstance()->GetRegion("DetectorRegion");
191 // Par04DefineMeshModel needs to be first model to call
192 new Par04DefineMeshModel("defineMesh", detectorRegion);
193#ifdef USE_INFERENCE
194 new Par04MLFastSimModel("inferenceModel", detectorRegion);
195#endif
196}
197
198//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
199
201{
202 G4cout << "\n------------------------------------------------------"
203 << "\n--- Detector length:\t" << G4BestUnit(fDetectorLength, "Length")
204 << "\n--- Detector inner radius:\t" << G4BestUnit(fDetectorInnerRadius, "Length")
205 << "\n--- Number of layers:\t" << fNbOfLayers << G4endl << "\n--- 1st layer: \t"
206 << G4BestUnit(fAbsorberThickness[0], "Length") << " of "
207 << (fAbsorberSensitivity[0] ? "active " : "passive ") << fAbsorberMaterial[0]->GetName()
208 << G4endl;
209 if(fAbsorberMaterial[1] != nullptr)
210 G4cout << "--- 2nd layer: \t" << G4BestUnit(fAbsorberThickness[1], "Length") << " of "
211 << (fAbsorberSensitivity[1] ? "active " : "passive ") << fAbsorberMaterial[1]->GetName()
212 << G4endl;
213 G4cout << "-----------------------------------------------------" << G4endl;
214}
215
216//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
217
218void Par04DetectorConstruction::SetAbsorberMaterial(const std::size_t aLayer, const G4String& aName)
219{
220 // search material by its name
221 G4Material* material = G4NistManager::Instance()->FindOrBuildMaterial(aName);
222 if(material)
223 fAbsorberMaterial[aLayer] = material;
224 else
225 G4Exception("Par04DetectorConstruction::SetAbsorberMaterial()", "InvalidSetup", FatalException,
226 ("Unknown material name: " + aName).c_str());
227 G4RunManager::GetRunManager()->PhysicsHasBeenModified();
228}
229
230//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
231
233 const G4double aThickness)
234{
235 if(aLayer < fAbsorberThickness.size())
236 fAbsorberThickness[aLayer] = aThickness;
237 else
238 G4Exception("Par04DetectorConstruction::SetAbsorberThickness()", "InvalidSetup", FatalException,
239 ("Requested layer " + std::to_string(aLayer) +
240 " is larger than number of available layers (" +
241 std::to_string(fAbsorberThickness.size()) + ").")
242 .c_str());
243 G4RunManager::GetRunManager()->PhysicsHasBeenModified();
244}
245
246//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
247
249 const G4bool aSensitivity)
250{
251 if(aLayer < fAbsorberSensitivity.size())
252 fAbsorberSensitivity[aLayer] = aSensitivity;
253 else
254 G4Exception(
255 "Par04DetectorConstruction::SetAbsorberSensitivity()", "InvalidSetup", FatalException,
256 ("Requested layer " + std::to_string(aLayer) + " is larger than number of available layers ("+
257 std::to_string(fAbsorberSensitivity.size()) + ").")
258 .c_str());
259 G4RunManager::GetRunManager()->PhysicsHasBeenModified();
260}
261
262//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
263
265
266//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
267
268void Par04DetectorConstruction::SetLength(G4double aLength) { fDetectorLength = aLength; }
Defince mesh for energy scoring.
void SetAbsorberSensitivity(const std::size_t aLayer, const G4bool aSensitivity)
Set sensitivity of the layer.
void SetLength(G4double aLength)
Set length radius of the cylindrical detector.
Par04DetectorMessenger * fDetectorMessenger
Messenger that allows to modify geometry.
virtual G4VPhysicalVolume * Construct() final
G4double fDetectorInnerRadius
Inner radius of the cylindrical detector.
virtual ~Par04DetectorConstruction()
G4ThreeVector fMeshSizeOfCells
Mesh size of cells (dr, dphi, dz).
std::array< G4bool, 2 > fAbsorberSensitivity
Sensitivity of the layers.
std::vector< G4LogicalVolume * > fLayerLogical
Logical volume(s) of the sensitive absorbers.
void SetAbsorberMaterial(const std::size_t aLayer, const G4String &aMaterial)
Set material of the layer (from NIST materials)
std::array< G4double, 2 > fAbsorberThickness
Thickness(es) of the layers.
void Print() const
Print detector information.
std::array< G4Material *, 2 > fAbsorberMaterial
Material(s) of the layers.
void SetInnerRadius(G4double aInnerRadius)
Set inner radius of the cylindrical detector.
G4int fNbOfLayers
Number of layers = slices along z axis.
G4ThreeVector fMeshNbOfCells
Mesh number of cells (Nr, Nphi, Nz)
G4double fDetectorLength
Length of the cylindrical detector (along z axis)
void SetAbsorberThickness(const std::size_t aLayer, const G4double aThickness)
Set thickness of the layer.

Applications | User Support | Publications | Collaboration