File indexing completed on 2026-09-21 08:28:42
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 "G4AutoDelete.hh"
0032 #include "G4Box.hh"
0033 #include "G4Colour.hh"
0034 #include "G4GlobalMagFieldMessenger.hh"
0035 #include "G4LogicalVolume.hh"
0036 #include "G4Material.hh"
0037 #include "G4MultiFunctionalDetector.hh"
0038 #include "G4NistManager.hh"
0039 #include "G4PSEnergyDeposit.hh"
0040 #include "G4PSTrackLength.hh"
0041 #include "G4PVPlacement.hh"
0042 #include "G4PVReplica.hh"
0043 #include "G4PhysicalConstants.hh"
0044 #include "G4SDChargedFilter.hh"
0045 #include "G4SDManager.hh"
0046 #include "G4SystemOfUnits.hh"
0047 #include "G4VPrimitiveScorer.hh"
0048 #include "G4VisAttributes.hh"
0049
0050 namespace B4d
0051 {
0052
0053
0054
0055 G4ThreadLocal G4GlobalMagFieldMessenger* DetectorConstruction::fMagFieldMessenger = nullptr;
0056
0057
0058
0059 G4VPhysicalVolume* DetectorConstruction::Construct()
0060 {
0061
0062 DefineMaterials();
0063
0064
0065 return DefineVolumes();
0066 }
0067
0068
0069
0070 void DetectorConstruction::DefineMaterials()
0071 {
0072
0073 auto nistManager = G4NistManager::Instance();
0074 nistManager->FindOrBuildMaterial("G4_Pb");
0075
0076
0077 G4double a;
0078 G4double z;
0079 G4double density;
0080 new G4Material("liquidArgon", z = 18., a = 39.95 * g / mole, density = 1.390 * g / cm3);
0081
0082
0083
0084 new G4Material("Galactic", z = 1., a = 1.01 * g / mole, density = universe_mean_density,
0085 kStateGas, 2.73 * kelvin, 3.e-18 * pascal);
0086
0087
0088 G4cout << *(G4Material::GetMaterialTable()) << G4endl;
0089 }
0090
0091
0092
0093 G4VPhysicalVolume* DetectorConstruction::DefineVolumes()
0094 {
0095
0096 G4int nofLayers = 10;
0097 G4double absoThickness = 10. * mm;
0098 G4double gapThickness = 5. * mm;
0099 G4double calorSizeXY = 10. * cm;
0100
0101 auto layerThickness = absoThickness + gapThickness;
0102 auto calorThickness = nofLayers * layerThickness;
0103 auto worldSizeXY = 1.2 * calorSizeXY;
0104 auto worldSizeZ = 1.2 * calorThickness;
0105
0106
0107 auto defaultMaterial = G4Material::GetMaterial("Galactic");
0108 auto absorberMaterial = G4Material::GetMaterial("G4_Pb");
0109 auto gapMaterial = G4Material::GetMaterial("liquidArgon");
0110
0111 if (!defaultMaterial || !absorberMaterial || !gapMaterial) {
0112 G4ExceptionDescription msg;
0113 msg << "Cannot retrieve materials already defined.";
0114 G4Exception("DetectorConstruction::DefineVolumes()", "MyCode0001", FatalException, msg);
0115 }
0116
0117
0118
0119
0120 auto worldS = new G4Box("World",
0121 worldSizeXY / 2, worldSizeXY / 2, worldSizeZ / 2);
0122
0123 auto worldLV = new G4LogicalVolume(worldS,
0124 defaultMaterial,
0125 "World");
0126
0127 auto worldPV = new G4PVPlacement(nullptr,
0128 G4ThreeVector(),
0129 worldLV,
0130 "World",
0131 nullptr,
0132 false,
0133 0,
0134 fCheckOverlaps);
0135
0136
0137
0138
0139 auto calorimeterS = new G4Box("Calorimeter",
0140 calorSizeXY / 2, calorSizeXY / 2, calorThickness / 2);
0141
0142 auto calorLV = new G4LogicalVolume(calorimeterS,
0143 defaultMaterial,
0144 "Calorimeter");
0145
0146 new G4PVPlacement(nullptr,
0147 G4ThreeVector(),
0148 calorLV,
0149 "Calorimeter",
0150 worldLV,
0151 false,
0152 0,
0153 fCheckOverlaps);
0154
0155
0156
0157
0158 auto layerS = new G4Box("Layer",
0159 calorSizeXY / 2, calorSizeXY / 2, layerThickness / 2);
0160
0161 auto layerLV = new G4LogicalVolume(layerS,
0162 defaultMaterial,
0163 "Layer");
0164
0165 new G4PVReplica("Layer",
0166 layerLV,
0167 calorLV,
0168 kZAxis,
0169 nofLayers,
0170 layerThickness);
0171
0172
0173
0174
0175 auto absorberS = new G4Box("Abso",
0176 calorSizeXY / 2, calorSizeXY / 2, absoThickness / 2);
0177
0178 auto absorberLV = new G4LogicalVolume(absorberS,
0179 absorberMaterial,
0180 "AbsoLV");
0181
0182 new G4PVPlacement(nullptr,
0183 G4ThreeVector(0., 0., -gapThickness / 2),
0184 absorberLV,
0185 "Abso",
0186 layerLV,
0187 false,
0188 0,
0189 fCheckOverlaps);
0190
0191
0192
0193
0194 auto gapS = new G4Box("Gap",
0195 calorSizeXY / 2, calorSizeXY / 2, gapThickness / 2);
0196
0197 auto gapLV = new G4LogicalVolume(gapS,
0198 gapMaterial,
0199 "GapLV");
0200
0201 new G4PVPlacement(nullptr,
0202 G4ThreeVector(0., 0., absoThickness / 2),
0203 gapLV,
0204 "Gap",
0205 layerLV,
0206 false,
0207 0,
0208 fCheckOverlaps);
0209
0210
0211
0212
0213 G4cout << G4endl << "------------------------------------------------------------" << G4endl
0214 << "---> The calorimeter is " << nofLayers << " layers of: [ " << absoThickness / mm
0215 << "mm of " << absorberMaterial->GetName() << " + " << gapThickness / mm << "mm of "
0216 << gapMaterial->GetName() << " ] " << G4endl
0217 << "------------------------------------------------------------" << G4endl;
0218
0219
0220
0221
0222 worldLV->SetVisAttributes(G4VisAttributes::GetInvisible());
0223 calorLV->SetVisAttributes(G4VisAttributes(G4Colour::White()));
0224
0225
0226
0227
0228 return worldPV;
0229 }
0230
0231
0232
0233 void DetectorConstruction::ConstructSDandField()
0234 {
0235 G4SDManager::GetSDMpointer()->SetVerboseLevel(1);
0236
0237
0238
0239
0240
0241
0242 auto absDetector = new G4MultiFunctionalDetector("Absorber");
0243 G4SDManager::GetSDMpointer()->AddNewDetector(absDetector);
0244
0245 G4VPrimitiveScorer* primitive;
0246 primitive = new G4PSEnergyDeposit("Edep");
0247 absDetector->RegisterPrimitive(primitive);
0248
0249 primitive = new G4PSTrackLength("TrackLength");
0250 auto charged = new G4SDChargedFilter("chargedFilter");
0251 primitive->SetFilter(charged);
0252 absDetector->RegisterPrimitive(primitive);
0253
0254 SetSensitiveDetector("AbsoLV", absDetector);
0255
0256
0257
0258 auto gapDetector = new G4MultiFunctionalDetector("Gap");
0259 G4SDManager::GetSDMpointer()->AddNewDetector(gapDetector);
0260
0261 primitive = new G4PSEnergyDeposit("Edep");
0262 gapDetector->RegisterPrimitive(primitive);
0263
0264 primitive = new G4PSTrackLength("TrackLength");
0265 primitive->SetFilter(charged);
0266 gapDetector->RegisterPrimitive(primitive);
0267
0268 SetSensitiveDetector("GapLV", gapDetector);
0269
0270
0271
0272
0273
0274
0275
0276 G4ThreeVector fieldValue;
0277 fMagFieldMessenger = new G4GlobalMagFieldMessenger(fieldValue);
0278 fMagFieldMessenger->SetVerboseLevel(1);
0279
0280
0281 G4AutoDelete::Register(fMagFieldMessenger);
0282 }
0283
0284
0285
0286 }