File indexing completed on 2026-03-28 07:49:47
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 "DetectorMessenger.hh"
0032 #include "TrackerSD.hh"
0033
0034 #include "G4AutoDelete.hh"
0035 #include "G4Box.hh"
0036 #include "G4Colour.hh"
0037 #include "G4GeometryManager.hh"
0038 #include "G4GeometryTolerance.hh"
0039 #include "G4GlobalMagFieldMessenger.hh"
0040 #include "G4LogicalVolume.hh"
0041 #include "G4Material.hh"
0042 #include "G4NistManager.hh"
0043 #include "G4PVPlacement.hh"
0044 #include "G4SDManager.hh"
0045 #include "G4SystemOfUnits.hh"
0046 #include "G4Tubs.hh"
0047 #include "G4UserLimits.hh"
0048 #include "G4VisAttributes.hh"
0049
0050 using namespace B2;
0051
0052 namespace B2a
0053 {
0054
0055
0056
0057 G4ThreadLocal G4GlobalMagFieldMessenger* DetectorConstruction::fMagFieldMessenger = nullptr;
0058
0059 DetectorConstruction::DetectorConstruction()
0060 {
0061 fMessenger = new DetectorMessenger(this);
0062
0063 fNbOfChambers = 5;
0064 fLogicChamber = new G4LogicalVolume*[fNbOfChambers];
0065 }
0066
0067
0068
0069 DetectorConstruction::~DetectorConstruction()
0070 {
0071 delete[] fLogicChamber;
0072 delete fStepLimit;
0073 delete fMessenger;
0074 }
0075
0076
0077
0078 G4VPhysicalVolume* DetectorConstruction::Construct()
0079 {
0080
0081 DefineMaterials();
0082
0083
0084 return DefineVolumes();
0085 }
0086
0087
0088
0089 void DetectorConstruction::DefineMaterials()
0090 {
0091
0092
0093 G4NistManager* nistManager = G4NistManager::Instance();
0094
0095
0096 nistManager->FindOrBuildMaterial("G4_AIR");
0097
0098
0099 fTargetMaterial = nistManager->FindOrBuildMaterial("G4_Pb");
0100
0101
0102 fChamberMaterial = nistManager->FindOrBuildMaterial("G4_Xe");
0103
0104
0105 G4cout << *(G4Material::GetMaterialTable()) << G4endl;
0106 }
0107
0108
0109
0110 G4VPhysicalVolume* DetectorConstruction::DefineVolumes()
0111 {
0112 G4Material* air = G4Material::GetMaterial("G4_AIR");
0113
0114
0115
0116 G4double chamberSpacing = 80 * cm;
0117
0118 G4double chamberWidth = 20.0 * cm;
0119 G4double targetLength = 5.0 * cm;
0120
0121 G4double trackerLength = (fNbOfChambers + 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 G4VisAttributes boxVisAtt(G4Colour::White());
0191 G4VisAttributes chamberVisAtt(G4Colour::Yellow());
0192
0193 worldLV->SetVisAttributes(boxVisAtt);
0194 fLogicTarget->SetVisAttributes(boxVisAtt);
0195 trackerLV->SetVisAttributes(boxVisAtt);
0196
0197
0198
0199 G4cout << "There are " << fNbOfChambers << " chambers in the tracker region. " << G4endl
0200 << "The chambers are " << chamberWidth / cm << " cm of " << fChamberMaterial->GetName()
0201 << G4endl << "The distance between chamber is " << chamberSpacing / cm << " cm" << G4endl;
0202
0203 G4double firstPosition = -trackerSize + chamberSpacing;
0204 G4double firstLength = trackerLength / 10;
0205 G4double lastLength = trackerLength;
0206
0207 G4double halfWidth = 0.5 * chamberWidth;
0208 G4double rmaxFirst = 0.5 * firstLength;
0209
0210 G4double rmaxIncr = 0.0;
0211 if (fNbOfChambers > 0) {
0212 rmaxIncr = 0.5 * (lastLength - firstLength) / (fNbOfChambers - 1);
0213 if (chamberSpacing < chamberWidth) {
0214 G4Exception("DetectorConstruction::DefineVolumes()", "InvalidSetup", FatalException,
0215 "Width>Spacing");
0216 }
0217 }
0218
0219 for (G4int copyNo = 0; copyNo < fNbOfChambers; copyNo++) {
0220 G4double Zposition = firstPosition + copyNo * chamberSpacing;
0221 G4double rmax = rmaxFirst + copyNo * rmaxIncr;
0222
0223 auto chamberS = new G4Tubs("Chamber_solid", 0, rmax, halfWidth, 0. * deg, 360. * deg);
0224
0225 fLogicChamber[copyNo] =
0226 new G4LogicalVolume(chamberS, fChamberMaterial, "Chamber_LV", nullptr, nullptr, nullptr);
0227
0228 fLogicChamber[copyNo]->SetVisAttributes(chamberVisAtt);
0229
0230 new G4PVPlacement(nullptr,
0231 G4ThreeVector(0, 0, Zposition),
0232 fLogicChamber[copyNo],
0233 "Chamber_PV",
0234 trackerLV,
0235 false,
0236 copyNo,
0237 fCheckOverlaps);
0238 }
0239
0240
0241
0242
0243
0244
0245
0246
0247 G4double maxStep = 0.5 * chamberWidth;
0248 fStepLimit = new G4UserLimits(maxStep);
0249 trackerLV->SetUserLimits(fStepLimit);
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261 return worldPV;
0262 }
0263
0264
0265
0266 void DetectorConstruction::ConstructSDandField()
0267 {
0268
0269
0270 G4String trackerChamberSDname = "/TrackerChamberSD";
0271 auto trackerSD = new TrackerSD(trackerChamberSDname, "TrackerHitsCollection");
0272 G4SDManager::GetSDMpointer()->AddNewDetector(trackerSD);
0273
0274
0275 SetSensitiveDetector("Chamber_LV", trackerSD, true);
0276
0277
0278
0279
0280 G4ThreeVector fieldValue = G4ThreeVector();
0281 fMagFieldMessenger = new G4GlobalMagFieldMessenger(fieldValue);
0282 fMagFieldMessenger->SetVerboseLevel(1);
0283
0284
0285 G4AutoDelete::Register(fMagFieldMessenger);
0286 }
0287
0288
0289
0290 void DetectorConstruction::SetTargetMaterial(G4String materialName)
0291 {
0292 G4NistManager* nistManager = G4NistManager::Instance();
0293
0294 G4Material* pttoMaterial = nistManager->FindOrBuildMaterial(materialName);
0295
0296 if (fTargetMaterial != pttoMaterial) {
0297 if (pttoMaterial) {
0298 fTargetMaterial = pttoMaterial;
0299 if (fLogicTarget) fLogicTarget->SetMaterial(fTargetMaterial);
0300 G4cout << G4endl << "----> The target is made of " << materialName << G4endl;
0301 }
0302 else {
0303 G4cout << G4endl << "--> WARNING from SetTargetMaterial : " << materialName << " not found"
0304 << G4endl;
0305 }
0306 }
0307 }
0308
0309
0310
0311 void DetectorConstruction::SetChamberMaterial(G4String materialName)
0312 {
0313 G4NistManager* nistManager = G4NistManager::Instance();
0314
0315 G4Material* pttoMaterial = nistManager->FindOrBuildMaterial(materialName);
0316
0317 if (fChamberMaterial != pttoMaterial) {
0318 if (pttoMaterial) {
0319 fChamberMaterial = pttoMaterial;
0320 for (G4int copyNo = 0; copyNo < fNbOfChambers; copyNo++) {
0321 if (fLogicChamber[copyNo]) fLogicChamber[copyNo]->SetMaterial(fChamberMaterial);
0322 }
0323 G4cout << G4endl << "----> The chambers are made of " << materialName << G4endl;
0324 }
0325 else {
0326 G4cout << G4endl << "--> WARNING from SetChamberMaterial : " << materialName << " not found"
0327 << G4endl;
0328 }
0329 }
0330 }
0331
0332
0333
0334 void DetectorConstruction::SetMaxStep(G4double maxStep)
0335 {
0336 if ((fStepLimit) && (maxStep > 0.)) fStepLimit->SetMaxAllowedStep(maxStep);
0337 }
0338
0339
0340
0341 void DetectorConstruction::SetCheckOverlaps(G4bool checkOverlaps)
0342 {
0343 fCheckOverlaps = checkOverlaps;
0344 }
0345
0346
0347
0348 }