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