File indexing completed on 2026-04-18 07:42:19
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 "G4Box.hh"
0032 #include "G4Exception.hh"
0033 #include "G4GeometryManager.hh"
0034 #include "G4Material.hh"
0035 #include "G4NistManager.hh"
0036 #include "G4PVPlacement.hh"
0037 #include "G4Region.hh"
0038 #include "G4RunManager.hh"
0039 #include "G4SDManager.hh"
0040 #include "G4StateManager.hh"
0041 #include "G4SystemOfUnits.hh"
0042 #include "globals.hh"
0043
0044 #include "DetectorMessenger.hh"
0045 #include "TrackerSD.hh"
0046
0047
0048
0049 DetectorConstruction::DetectorConstruction() : G4VUserDetectorConstruction()
0050 {
0051
0052 fDetectorMessenger = std::make_unique<DetectorMessenger>(this);
0053 }
0054
0055
0056
0057 DetectorConstruction::~DetectorConstruction() = default;
0058
0059
0060
0061 G4VPhysicalVolume* DetectorConstruction::Construct()
0062 {
0063
0064 DefineMaterials();
0065
0066
0067 G4VPhysicalVolume* World = DefineWorld();
0068 DefineSD(World);
0069 return World;
0070 }
0071
0072
0073
0074 void DetectorConstruction::DefineMaterials()
0075 {
0076
0077 G4NistManager* nist = G4NistManager::Instance();
0078 if (!fMat) {
0079 fMat = nist->FindOrBuildMaterial("G4_WATER");
0080 }
0081
0082
0083 G4cout << "Material: " << fMat->GetName() << G4endl;
0084 G4cout << *(G4Material::GetMaterialTable()) << G4endl;
0085 }
0086
0087
0088
0089 void DetectorConstruction::CheckConsistency()
0090 {
0091 if (!(fMaxRange > 0.)) {
0092 G4ExceptionDescription msg;
0093 msg << "fMaxRange must be > 0.\n"
0094 << "Please consider using the formula by Tabata for the calculation "
0095 << "of the maximum range of secondary electrons:\n"
0096 << "\t https://doi.org/10.1016/0029-554X(72)90463-6" << G4endl
0097 << "Note: This parameter affects the world volume size only along "
0098 << "the z-axis.\n"
0099 << "Sizes along x- and y-axes are set by fHitSelRegXY and the "
0100 << "site radius." << G4endl;
0101 G4Exception("DetectorConstruction::CheckConsistency()", "DetCons0001",
0102 FatalException, msg);
0103 }
0104 if (!(fHitSelRegZ > 0.)) {
0105 G4ExceptionDescription msg;
0106 msg << "fHitSelRegZ must be > 0.\n"
0107 << "Otherwise, no hits are eligible to set randomly the site "
0108 << "position using the weighted method.\n"
0109 << G4endl;
0110 G4Exception("DetectorConstruction::CheckConsistency()", "DetCons0002",
0111 FatalException, msg);
0112 }
0113 if (!(fHitSelRegXY > 0.)) {
0114 G4ExceptionDescription msg;
0115 msg << "fHitSelRegXY must be > 0.\n"
0116 << "Otherwise, no hits are eligible to set randomly the site "
0117 << "position using the weighted method." << G4endl
0118 << "Note: This parameter, together with the site radius, sets the "
0119 << "world volume size along the xy-axes." << G4endl;
0120 G4Exception("DetectorConstruction::CheckConsistency()", "DetCons0003",
0121 FatalException, msg);
0122 }
0123 }
0124
0125
0126
0127 G4VPhysicalVolume* DetectorConstruction::DefineWorld()
0128 {
0129
0130 CheckConsistency();
0131
0132
0133
0134 G4double WorldZ = fHitSelRegZ + 4. * fSiteRadius + 2. * fMaxRange;
0135 G4double WorldXY = fHitSelRegXY + 4. * fSiteRadius;
0136
0137 auto* sWorld = new G4Box("World", WorldXY / 2., WorldXY / 2., WorldZ / 2.);
0138 auto* lWorld = new G4LogicalVolume(sWorld, fMat, "World", 0, 0, 0);
0139 G4VPhysicalVolume* World =
0140 new G4PVPlacement(0, G4ThreeVector(), lWorld, "World", nullptr, false, 0);
0141
0142
0143 PrintParameters(World);
0144
0145 return World;
0146 }
0147
0148
0149
0150 G4VPhysicalVolume*
0151 DetectorConstruction::DefineSD(G4VPhysicalVolume* mother) const
0152 {
0153
0154
0155 G4double SensDetZ = fHitSelRegZ + 4. * fSiteRadius;
0156 G4double SensDetXY = fHitSelRegXY + 4. * fSiteRadius;
0157
0158 auto* sSDbox =
0159 new G4Box("SDbox", SensDetXY / 2., SensDetXY / 2., SensDetZ / 2.);
0160 auto* lSDbox = new G4LogicalVolume(sSDbox, fMat, "SDbox", 0, 0, 0);
0161 G4VPhysicalVolume* SDbox = new G4PVPlacement(
0162 0, G4ThreeVector(), lSDbox, "SDbox", mother->GetLogicalVolume(), false, 0);
0163
0164 PrintParameters(SDbox);
0165
0166 return SDbox;
0167 }
0168
0169
0170
0171 void DetectorConstruction::ConstructSDandField()
0172 {
0173
0174 G4String SDname = "SDbox";
0175
0176 auto* aSD = new TrackerSD(SDname, "TrackerHitColl");
0177
0178
0179 G4SDManager* SDMan = G4SDManager::GetSDMpointer();
0180 SDMan->AddNewDetector(aSD);
0181
0182
0183 SetSensitiveDetector("SDbox", aSD, true);
0184 }
0185
0186
0187
0188 void DetectorConstruction::SetMaterial(const G4String& name)
0189 {
0190 auto* nist = G4NistManager::Instance();
0191
0192 G4Material* mat = nist->FindOrBuildMaterial(name);
0193
0194 if (!mat) {
0195 G4ExceptionDescription ed;
0196 ed << "Material '" << name << "' not found. Falling back to G4_WATER.";
0197 G4Exception("DetectorConstruction::SetMaterial", "MTK001", JustWarning, ed);
0198 mat = nist->FindOrBuildMaterial("G4_WATER");
0199 }
0200
0201 if (fMat != mat) {
0202 fMat = mat;
0203 }
0204 }
0205
0206
0207
0208 void DetectorConstruction::PrintParameters(G4VPhysicalVolume* physVol) const
0209 {
0210 if (!physVol) {
0211 G4cerr << "Error: Physical volume is null!" << G4endl;
0212 return;
0213 }
0214
0215 G4ThreeVector pos = physVol->GetObjectTranslation();
0216 G4LogicalVolume* logVol = physVol->GetLogicalVolume();
0217 G4VSolid* solid = logVol->GetSolid();
0218 G4Material* material = logVol->GetMaterial();
0219
0220 G4cout << "\n================ Volume Parameters ================" << G4endl;
0221 G4cout << "Physical Volume Name: " << physVol->GetName() << G4endl;
0222 G4cout << "Position: " << pos / mm << " mm" << G4endl;
0223 G4cout << "Material: " << material->GetName() << G4endl;
0224
0225
0226 if (auto box = dynamic_cast<G4Box*>(solid)) {
0227 G4cout << "Shape: Box" << G4endl;
0228 G4cout << "Dimensions (full): " << 2 * box->GetXHalfLength() / mm << " x "
0229 << 2 * box->GetYHalfLength() / mm << " x "
0230 << 2 * box->GetZHalfLength() / mm << " mm" << G4endl;
0231 }
0232 else {
0233 G4cout << "Shape: Unknown or not handled yet." << G4endl;
0234 }
0235
0236 G4cout << "===================================================\n" << G4endl;
0237 }
0238
0239