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