File indexing completed on 2026-06-13 07:53:59
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 "ChamberParameterisation.hh"
0032 #include "DetectorMessenger.hh"
0033 #include "TrackerSD.hh"
0034
0035 #include "G4AutoDelete.hh"
0036 #include "G4Box.hh"
0037 #include "G4Colour.hh"
0038 #include "G4GeometryManager.hh"
0039 #include "G4GeometryTolerance.hh"
0040 #include "G4GlobalMagFieldMessenger.hh"
0041 #include "G4LogicalVolume.hh"
0042 #include "G4Material.hh"
0043 #include "G4NistManager.hh"
0044 #include "G4PVParameterised.hh"
0045 #include "G4PVPlacement.hh"
0046 #include "G4SDManager.hh"
0047 #include "G4SystemOfUnits.hh"
0048 #include "G4ThreeVector.hh"
0049 #include "G4Tubs.hh"
0050 #include "G4UserLimits.hh"
0051 #include "G4VisAttributes.hh"
0052
0053 using namespace B2;
0054
0055 namespace B2b
0056 {
0057
0058
0059
0060 G4ThreadLocal G4GlobalMagFieldMessenger* DetectorConstruction::fMagFieldMessenger = nullptr;
0061
0062 DetectorConstruction::DetectorConstruction()
0063 {
0064 fMessenger = new DetectorMessenger(this);
0065 }
0066
0067
0068
0069 DetectorConstruction::~DetectorConstruction()
0070 {
0071 delete fStepLimit;
0072 delete fMessenger;
0073 }
0074
0075
0076
0077 G4VPhysicalVolume* DetectorConstruction::Construct()
0078 {
0079
0080 DefineMaterials();
0081
0082
0083 return DefineVolumes();
0084 }
0085
0086
0087
0088 void DetectorConstruction::DefineMaterials()
0089 {
0090
0091
0092 G4NistManager* nistManager = G4NistManager::Instance();
0093
0094
0095 nistManager->FindOrBuildMaterial("G4_AIR");
0096
0097
0098 fTargetMaterial = nistManager->FindOrBuildMaterial("G4_Pb");
0099
0100
0101 fChamberMaterial = nistManager->FindOrBuildMaterial("G4_Xe");
0102
0103
0104 G4cout << *(G4Material::GetMaterialTable()) << G4endl;
0105 }
0106
0107
0108
0109 G4VPhysicalVolume* DetectorConstruction::DefineVolumes()
0110 {
0111 G4Material* air = G4Material::GetMaterial("G4_AIR");
0112
0113
0114
0115 G4int NbOfChambers = 5;
0116 G4double chamberSpacing = 80 * cm;
0117
0118 G4double chamberWidth = 20.0 * cm;
0119 G4double targetLength = 5.0 * cm;
0120
0121 G4double trackerLength = (NbOfChambers + 1) * chamberSpacing;
0122
0123 G4double worldLength = 1.2 * (2 * targetLength + trackerLength);
0124
0125 G4double targetRadius = 0.5 * targetLength;
0126 targetLength = 0.5 * targetLength;
0127 G4double trackerSize = 0.5 * trackerLength;
0128
0129
0130
0131
0132
0133 G4GeometryManager::GetInstance()->SetWorldMaximumExtent(worldLength);
0134
0135 G4cout << "Computed tolerance = "
0136 << G4GeometryTolerance::GetInstance()->GetSurfaceTolerance() / mm << " mm" << G4endl;
0137
0138 auto worldS = new G4Box("world",
0139 worldLength / 2, worldLength / 2, worldLength / 2);
0140 auto worldLV = new G4LogicalVolume(worldS,
0141 air,
0142 "World");
0143
0144
0145
0146 auto worldPV = new G4PVPlacement(nullptr,
0147 G4ThreeVector(),
0148 worldLV,
0149 "World",
0150 nullptr,
0151 false,
0152 0,
0153 fCheckOverlaps);
0154
0155
0156
0157 G4ThreeVector positionTarget = G4ThreeVector(0, 0, -(targetLength + trackerSize));
0158
0159 auto targetS = new G4Tubs("target", 0., targetRadius, targetLength, 0. * deg, 360. * deg);
0160 fLogicTarget = new G4LogicalVolume(targetS, fTargetMaterial, "Target", nullptr, nullptr, nullptr);
0161 new G4PVPlacement(nullptr,
0162 positionTarget,
0163 fLogicTarget,
0164 "Target",
0165 worldLV,
0166 false,
0167 0,
0168 fCheckOverlaps);
0169
0170 G4cout << "Target is " << 2 * targetLength / cm << " cm of " << fTargetMaterial->GetName()
0171 << G4endl;
0172
0173
0174
0175 G4ThreeVector positionTracker = G4ThreeVector(0, 0, 0);
0176
0177 auto trackerS = new G4Tubs("tracker", 0, trackerSize, trackerSize, 0. * deg, 360. * deg);
0178 auto trackerLV = new G4LogicalVolume(trackerS, air, "Tracker", nullptr, nullptr, nullptr);
0179 new G4PVPlacement(nullptr,
0180 positionTracker,
0181 trackerLV,
0182 "Tracker",
0183 worldLV,
0184 false,
0185 0,
0186 fCheckOverlaps);
0187
0188
0189
0190
0191
0192
0193 auto chamberS = new G4Tubs("tracker", 0, 100 * cm, 100 * cm, 0. * deg, 360. * deg);
0194 fLogicChamber =
0195 new G4LogicalVolume(chamberS, fChamberMaterial, "Chamber", nullptr, nullptr, nullptr);
0196
0197 G4double firstPosition = -trackerSize + chamberSpacing;
0198 G4double firstLength = trackerLength / 10;
0199 G4double lastLength = trackerLength;
0200
0201 G4VPVParameterisation* chamberParam =
0202 new ChamberParameterisation(NbOfChambers,
0203 firstPosition,
0204 chamberSpacing,
0205 chamberWidth,
0206 firstLength,
0207 lastLength);
0208
0209
0210
0211 new G4PVParameterised("Chamber",
0212 fLogicChamber,
0213 trackerLV,
0214 kZAxis,
0215 NbOfChambers,
0216 chamberParam,
0217 fCheckOverlaps);
0218
0219 G4cout << "There are " << NbOfChambers << " chambers in the tracker region. " << G4endl
0220 << "The chambers are " << chamberWidth / cm << " cm of " << fChamberMaterial->GetName()
0221 << G4endl << "The distance between chamber is " << chamberSpacing / cm << " cm" << G4endl;
0222
0223
0224
0225 G4VisAttributes boxVisAtt(G4Colour::White());
0226
0227 worldLV->SetVisAttributes(boxVisAtt);
0228 fLogicTarget->SetVisAttributes(boxVisAtt);
0229 trackerLV->SetVisAttributes(boxVisAtt);
0230
0231 G4VisAttributes chamberVisAtt(G4Colour::Yellow());
0232 fLogicChamber->SetVisAttributes(chamberVisAtt);
0233
0234
0235
0236
0237
0238
0239
0240
0241 G4double maxStep = 0.5 * chamberWidth;
0242 fStepLimit = new G4UserLimits(maxStep);
0243 trackerLV->SetUserLimits(fStepLimit);
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255 return worldPV;
0256 }
0257
0258
0259
0260 void DetectorConstruction::ConstructSDandField()
0261 {
0262
0263
0264 G4String trackerChamberSDname = "B2/TrackerChamberSD";
0265 auto trackerSD = new TrackerSD(trackerChamberSDname, "TrackerHitsCollection");
0266 G4SDManager::GetSDMpointer()->AddNewDetector(trackerSD);
0267 SetSensitiveDetector(fLogicChamber, trackerSD);
0268
0269
0270
0271
0272 G4ThreeVector fieldValue = G4ThreeVector();
0273 fMagFieldMessenger = new G4GlobalMagFieldMessenger(fieldValue);
0274 fMagFieldMessenger->SetVerboseLevel(1);
0275
0276
0277 G4AutoDelete::Register(fMagFieldMessenger);
0278 }
0279
0280
0281
0282 void DetectorConstruction::SetTargetMaterial(G4String materialName)
0283 {
0284 G4NistManager* nistManager = G4NistManager::Instance();
0285
0286 G4Material* pttoMaterial = nistManager->FindOrBuildMaterial(materialName);
0287
0288 if (fTargetMaterial != pttoMaterial) {
0289 if (pttoMaterial) {
0290 fTargetMaterial = pttoMaterial;
0291 if (fLogicTarget) fLogicTarget->SetMaterial(fTargetMaterial);
0292 G4cout << G4endl << "----> The target is made of " << materialName << G4endl;
0293 }
0294 else {
0295 G4cout << G4endl << "--> WARNING from SetTargetMaterial : " << materialName << " not found"
0296 << G4endl;
0297 }
0298 }
0299 }
0300
0301
0302
0303 void DetectorConstruction::SetChamberMaterial(G4String materialName)
0304 {
0305 G4NistManager* nistManager = G4NistManager::Instance();
0306
0307 G4Material* pttoMaterial = nistManager->FindOrBuildMaterial(materialName);
0308
0309 if (fChamberMaterial != pttoMaterial) {
0310 if (pttoMaterial) {
0311 fChamberMaterial = pttoMaterial;
0312 if (fLogicChamber) fLogicChamber->SetMaterial(fChamberMaterial);
0313 G4cout << G4endl << "----> The chambers are made of " << materialName << G4endl;
0314 }
0315 else {
0316 G4cout << G4endl << "--> WARNING from SetChamberMaterial : " << materialName << " not found"
0317 << G4endl;
0318 }
0319 }
0320 }
0321
0322
0323
0324 void DetectorConstruction::SetMaxStep(G4double maxStep)
0325 {
0326 if ((fStepLimit) && (maxStep > 0.)) fStepLimit->SetMaxAllowedStep(maxStep);
0327 }
0328
0329
0330
0331 }