File indexing completed on 2026-05-17 07:42:01
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 #include "ExGflashDetectorConstruction.hh"
0031
0032 #include "ExGflashHomoShowerTuning.hh"
0033 #include "ExGflashMessenger.hh"
0034 #include "ExGflashSensitiveDetector.hh"
0035
0036
0037 #include "G4AutoDelete.hh"
0038 #include "G4Box.hh"
0039 #include "G4Colour.hh"
0040 #include "G4LogicalVolume.hh"
0041 #include "G4Material.hh"
0042 #include "G4NistManager.hh"
0043 #include "G4PVPlacement.hh"
0044 #include "G4RunManager.hh"
0045 #include "G4SDManager.hh"
0046 #include "G4SystemOfUnits.hh"
0047 #include "G4ThreeVector.hh"
0048 #include "G4VPhysicalVolume.hh"
0049 #include "G4VisAttributes.hh"
0050 #include "globals.hh"
0051
0052
0053 #include "GFlashHitMaker.hh"
0054 #include "GFlashHomoShowerParameterisation.hh"
0055 #include "GFlashParticleBounds.hh"
0056 #include "GFlashShowerModel.hh"
0057
0058 #include "G4FastSimulationManager.hh"
0059
0060
0061
0062 const G4int kMaxBin = 500;
0063
0064
0065
0066 ExGflashDetectorConstruction::ExGflashDetectorConstruction()
0067 {
0068 if (fVerbose > 3) G4cout << "ExGflashDetectorConstruction::Detector constructor" << G4endl;
0069 fGflashMessenger = new ExGflashMessenger(this);
0070
0071
0072 fCrystalWidth = 3 * cm;
0073 fCrystalLength = 140 * cm;
0074
0075 DefineMaterials();
0076 SetMaterial("G4_PbWO4");
0077 }
0078
0079
0080
0081 ExGflashDetectorConstruction::~ExGflashDetectorConstruction()
0082 {
0083 delete fGflashMessenger;
0084 delete fFastShowerModel;
0085 delete fParameterisation;
0086 delete fParticleBounds;
0087 delete fHitMaker;
0088 }
0089
0090
0091
0092 void ExGflashDetectorConstruction::DefineMaterials()
0093 {
0094 if (fVerbose > 3) G4cout << "Defining the materials" << G4endl;
0095
0096 G4NistManager* nistManager = G4NistManager::Instance();
0097
0098 fHallMat = nistManager->FindOrBuildMaterial("G4_AIR");
0099 fDetMat = nistManager->FindOrBuildMaterial("G4_PbWO4");
0100 nistManager->FindOrBuildMaterial("G4_CESIUM_IODIDE");
0101 }
0102
0103
0104
0105 G4VPhysicalVolume* ExGflashDetectorConstruction::Construct()
0106 {
0107
0108
0109
0110
0111
0112
0113
0114
0115 G4double calo_xside = (fCrystalWidth * fNbOfCrystals);
0116 G4double calo_yside = (fCrystalWidth * fNbOfCrystals);
0117 G4double calo_zside = fCrystalLength;
0118
0119
0120 G4double experimentalHall_x = calo_xside * 4;
0121 G4double experimentalHall_y = calo_yside * 4;
0122 G4double experimentalHall_z = calo_zside * 4;
0123
0124 G4VSolid* experimentalHall_box = new G4Box("expHall_box",
0125 experimentalHall_x,
0126 experimentalHall_y,
0127 experimentalHall_z);
0128
0129 auto experimentalHall_log = new G4LogicalVolume(experimentalHall_box, fHallMat, "expHall_log",
0130 nullptr,
0131 nullptr,
0132 nullptr);
0133 G4VPhysicalVolume* experimentalHall_phys =
0134 new G4PVPlacement(nullptr,
0135 G4ThreeVector(),
0136 "expHall", experimentalHall_log, nullptr, false, 0);
0137
0138 auto calo_box = new G4Box("Calorimeter",
0139 calo_xside / 2.,
0140 calo_yside / 2., calo_zside / 2.);
0141 auto calo_log = new G4LogicalVolume(calo_box,
0142 fHallMat,
0143 "calo_log",
0144 nullptr,
0145 nullptr,
0146 nullptr);
0147
0148 G4double xpos = 0.0;
0149 G4double ypos = 0.0;
0150 G4double zpos = calo_zside / 2.;
0151
0152 new G4PVPlacement(nullptr, G4ThreeVector(xpos, ypos, zpos), calo_log, "calorimeter",
0153 experimentalHall_log, false, 1);
0154
0155
0156 G4VSolid* crystal_box = new G4Box("Crystal",
0157 fCrystalWidth / 2, fCrystalWidth / 2, fCrystalLength / 2);
0158
0159 fCrystal_log = new G4LogicalVolume(crystal_box,
0160 fDetMat,
0161 "Crystal_log");
0162
0163 for (G4int i = 0; i < fNbOfCrystals; i++) {
0164 for (G4int j = 0; j < fNbOfCrystals; j++) {
0165 G4int n = i * 10 + j;
0166 G4ThreeVector crystalPos((i * fCrystalWidth) - (calo_xside - fCrystalWidth) / 2.,
0167 (j * fCrystalWidth) - (calo_yside - fCrystalWidth) / 2., 0);
0168 new G4PVPlacement(nullptr,
0169 crystalPos,
0170 fCrystal_log,
0171 "crystal",
0172 calo_log, false, n);
0173 }
0174 }
0175 G4cout << "There are " << fNbOfCrystals << " crystals per row in the calorimeter, so in total "
0176 << fNbOfCrystals * fNbOfCrystals << " crystals" << G4endl;
0177 G4cout << "They have width of " << fCrystalWidth / cm << " cm and a length of "
0178 << fCrystalLength / cm << " cm." << G4endl;
0179 G4cout << fDetMat << G4endl;
0180 G4cout << "Total Calorimeter size " << calo_xside / cm << " cm x " << calo_yside / cm << " cm x "
0181 << calo_zside / cm << " cm" << G4endl;
0182
0183 experimentalHall_log->SetVisAttributes(G4VisAttributes::GetInvisible());
0184 auto caloVisAtt = new G4VisAttributes(G4Colour(1.0, 1.0, 1.0));
0185 auto crystalVisAtt = new G4VisAttributes(G4Colour(1.0, 1.0, 0.0));
0186 calo_log->SetVisAttributes(caloVisAtt);
0187 fCrystal_log->SetVisAttributes(crystalVisAtt);
0188
0189
0190
0191 fRegion = new G4Region("crystals");
0192 calo_log->SetRegion(fRegion);
0193 fRegion->AddRootLogicalVolume(calo_log);
0194
0195 return experimentalHall_phys;
0196 }
0197
0198
0199
0200 void ExGflashDetectorConstruction::ConstructSDandField()
0201 {
0202
0203
0204
0205
0206 if (fParameterisation != nullptr) {
0207 fParameterisation->SetMaterial(fDetMat);
0208 if (fVerbose > 3) G4cout << "Info " << __func__ << " Param Mat " << fDetMat << G4endl;
0209 fParameterisation->PrintMaterial(fDetMat);
0210 }
0211 else {
0212
0213
0214 G4SDManager* SDman = G4SDManager::GetSDMpointer();
0215
0216 auto SD = new ExGflashSensitiveDetector("Calorimeter", this);
0217
0218 SDman->AddNewDetector(SD);
0219 if (fCrystal_log != nullptr) {
0220 fCrystal_log->SetSensitiveDetector(SD);
0221 }
0222
0223 if (fVerbose > 3) G4cout << "\n--> Creating shower parameterization models" << G4endl;
0224 fFastShowerModel = new GFlashShowerModel("fFastShowerModel", fRegion);
0225 fParameterisation =
0226 new GFlashHomoShowerParameterisation(fDetMat, new ExGflashHomoShowerTuning());
0227 fFastShowerModel->SetParameterisation(*fParameterisation);
0228
0229 fParticleBounds = new GFlashParticleBounds();
0230 fFastShowerModel->SetParticleBounds(*fParticleBounds);
0231
0232 fHitMaker = new GFlashHitMaker();
0233 fFastShowerModel->SetHitMaker(*fHitMaker);
0234 if (fVerbose > 3) G4cout << "end shower parameterization." << G4endl;
0235 }
0236
0237
0238 fSDRadLen = fParameterisation->GetX0();
0239 fSDRm = fParameterisation->GetRm();
0240 if (fVerbose > 2) {
0241 G4cout << "Info " << __func__ << "Total Calorimeter size" << G4endl;
0242 auto calo_xyside = fCrystalWidth * fNbOfCrystals;
0243 G4cout << "Info Z " << __func__ << " " << fCrystalLength / cm << " cm "
0244 << fCrystalLength / fSDRadLen << " RadLen " << G4endl;
0245 G4cout << "Info XY " << __func__ << " " << calo_xyside / cm << " cm " << calo_xyside / fSDRm
0246 << " Rm " << G4endl;
0247 }
0248 }
0249
0250
0251
0252 void ExGflashDetectorConstruction::SetLBining(G4ThreeVector Value)
0253 {
0254 fNLtot = (G4int)Value(0);
0255 if (fNLtot > kMaxBin) {
0256 G4cout << "\n ---> warning from SetLBining: " << fNLtot << " truncated to " << kMaxBin
0257 << G4endl;
0258 fNLtot = kMaxBin;
0259 }
0260 fDLradl = Value(1);
0261 }
0262
0263
0264
0265 void ExGflashDetectorConstruction::SetRBining(G4ThreeVector Value)
0266 {
0267 fNRtot = (G4int)Value(0);
0268 if (fNRtot > kMaxBin) {
0269 G4cout << "\n ---> warning from SetRBining: " << fNRtot << " truncated to " << kMaxBin
0270 << G4endl;
0271 fNRtot = kMaxBin;
0272 }
0273 fDRradl = Value(1);
0274 }
0275
0276
0277
0278 void ExGflashDetectorConstruction::SetMaterial(G4String mat)
0279 {
0280
0281 G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(mat);
0282
0283 if (pttoMaterial != nullptr && fDetMat != pttoMaterial) {
0284 fDetMat = pttoMaterial;
0285 if (fCrystal_log != nullptr) {
0286 fCrystal_log->SetMaterial(fDetMat);
0287 }
0288 G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0289 }
0290 }
0291
0292