File indexing completed on 2025-10-17 08:06:16
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
0030
0031
0032
0033 #include "F04DetectorConstruction.hh"
0034
0035 #include "F04DetectorMessenger.hh"
0036 #include "F04FocusSolenoid.hh"
0037 #include "F04GlobalField.hh"
0038 #include "F04Materials.hh"
0039 #include "F04SimpleSolenoid.hh"
0040
0041 #include "G4AutoDelete.hh"
0042 #include "G4GeometryManager.hh"
0043 #include "G4LogicalVolume.hh"
0044 #include "G4LogicalVolumeStore.hh"
0045 #include "G4Material.hh"
0046 #include "G4NistManager.hh"
0047 #include "G4PVPlacement.hh"
0048 #include "G4PhysicalConstants.hh"
0049 #include "G4PhysicalVolumeStore.hh"
0050 #include "G4RotationMatrix.hh"
0051 #include "G4RunManager.hh"
0052 #include "G4SolidStore.hh"
0053 #include "G4StateManager.hh"
0054 #include "G4SystemOfUnits.hh"
0055 #include "G4Tubs.hh"
0056 #include "globals.hh"
0057
0058
0059
0060 F04DetectorConstruction::F04DetectorConstruction()
0061 {
0062 SetTargetAngle(170);
0063 SetCaptureMgntB1(2.5 * tesla);
0064 SetCaptureMgntB2(5.0 * tesla);
0065 SetTransferMgntB(5.0 * tesla);
0066
0067 fDegraderPos = -fTransferMgntLength / 2. + fDegraderThickness / 2.;
0068
0069 fDetectorMessenger = new F04DetectorMessenger(this);
0070 }
0071
0072
0073
0074 F04DetectorConstruction::~F04DetectorConstruction()
0075 {
0076 delete fDetectorMessenger;
0077 }
0078
0079
0080
0081 G4VPhysicalVolume* F04DetectorConstruction::Construct()
0082 {
0083 if (fPhysiWorld) {
0084 G4GeometryManager::GetInstance()->OpenGeometry();
0085 G4PhysicalVolumeStore::GetInstance()->Clean();
0086 G4LogicalVolumeStore::GetInstance()->Clean();
0087 G4SolidStore::GetInstance()->Clean();
0088 }
0089
0090 fMaterials = F04Materials::GetInstance();
0091
0092 DefineMaterials();
0093
0094 return ConstructDetector();
0095 }
0096
0097
0098
0099 void F04DetectorConstruction::DefineMaterials()
0100 {
0101
0102
0103 fVacuum = fMaterials->GetMaterial("G4_Galactic");
0104
0105 fWorldMaterial = fMaterials->GetMaterial("G4_AIR");
0106 fDegraderMaterial = fMaterials->GetMaterial("G4_Pb");
0107 fTargetMaterial = fMaterials->GetMaterial("G4_W");
0108 }
0109
0110
0111
0112 G4VPhysicalVolume* F04DetectorConstruction::ConstructDetector()
0113 {
0114 fSolidWorld = new G4Tubs("World", 0., GetWorldSizeR(), GetWorldSizeZ() / 2., 0., twopi);
0115
0116 fLogicWorld = new G4LogicalVolume(fSolidWorld, GetWorldMaterial(), "World");
0117
0118 fPhysiWorld =
0119 new G4PVPlacement(nullptr, G4ThreeVector(), "World", fLogicWorld, nullptr, false, 0);
0120
0121
0122
0123 fSolidCaptureMgnt =
0124 new G4Tubs("CaptureMgnt", 0., GetCaptureMgntRadius(), GetCaptureMgntLength() / 2., 0., twopi);
0125
0126 fLogicCaptureMgnt = new G4LogicalVolume(fSolidCaptureMgnt, fVacuum, "CaptureMgnt");
0127
0128 fCaptureMgntCenter = G4ThreeVector();
0129
0130 fPhysiCaptureMgnt = new G4PVPlacement(nullptr, fCaptureMgntCenter, "CaptureMgnt",
0131 fLogicCaptureMgnt, fPhysiWorld, false, 0);
0132
0133
0134
0135 fSolidTransferMgnt = new G4Tubs("TransferMgnt", 0., GetTransferMgntRadius(),
0136 GetTransferMgntLength() / 2., 0., twopi);
0137
0138 fLogicTransferMgnt = new G4LogicalVolume(fSolidTransferMgnt, fVacuum, "TransferMgnt");
0139
0140 G4double z = GetCaptureMgntLength() / 2. + GetTransferMgntLength() / 2. + GetTransferMgntPos();
0141 G4double x = GetTransferMgntPos() / 2.;
0142
0143 fTransferMgntCenter = G4ThreeVector(x, 0., z);
0144
0145 auto g4rot = new G4RotationMatrix();
0146 *g4rot = StringToRotationMatrix("Y30,X10");
0147 *g4rot = g4rot->inverse();
0148 if (*g4rot == G4RotationMatrix()) g4rot = nullptr;
0149
0150 fPhysiTransferMgnt = new G4PVPlacement(g4rot, fTransferMgntCenter, "TransferMgnt",
0151 fLogicTransferMgnt, fPhysiWorld, false, 0);
0152
0153
0154
0155 auto solidTestPlane = new G4Tubs("TestPlane", 0., GetTransferMgntRadius(), 1. * mm, 0., twopi);
0156
0157 auto logicTestPlane = new G4LogicalVolume(solidTestPlane, fVacuum, "TestPlane");
0158
0159 z = GetTransferMgntLength() / 2. - 1. * mm;
0160
0161 G4ThreeVector testPlaneCenter = G4ThreeVector(0., 0., z);
0162
0163 new G4PVPlacement(nullptr, testPlaneCenter, "TestPlane", logicTestPlane, fPhysiTransferMgnt,
0164 false, 0);
0165
0166
0167
0168 if (GetTargetThickness() > 0.) {
0169 fSolidTarget =
0170 new G4Tubs("Target", 0., GetTargetRadius(), GetTargetThickness() / 2., 0., twopi);
0171
0172 fLogicTarget = new G4LogicalVolume(fSolidTarget, GetTargetMaterial(), "Target");
0173
0174 G4int i = GetTargetAngle();
0175
0176 G4String angle = std::to_string(i);
0177 G4StrUtil::strip(angle);
0178 angle = "Y" + angle;
0179
0180 g4rot = new G4RotationMatrix();
0181 *g4rot = StringToRotationMatrix(angle);
0182 *g4rot = g4rot->inverse();
0183 if (*g4rot == G4RotationMatrix()) g4rot = nullptr;
0184
0185 G4ThreeVector targetCenter(0., 0., GetTargetPos());
0186
0187 fPhysiTarget =
0188 new G4PVPlacement(g4rot, targetCenter, "Target", fLogicTarget, fPhysiCaptureMgnt, false, 0);
0189 }
0190
0191
0192
0193 if (GetDegraderThickness() > 0.) {
0194 fSolidDegrader =
0195 new G4Tubs("Degrader", 0., GetDegraderRadius(), GetDegraderThickness() / 2., 0., twopi);
0196
0197 fLogicDegrader = new G4LogicalVolume(fSolidDegrader, GetDegraderMaterial(), "Degrader");
0198
0199 G4ThreeVector degraderCenter = G4ThreeVector(0., 0., GetDegraderPos());
0200
0201 fPhysiDegrader = new G4PVPlacement(nullptr, degraderCenter, "Degrader", fLogicDegrader,
0202 fPhysiTransferMgnt, false, 0);
0203 }
0204
0205 return fPhysiWorld;
0206 }
0207
0208
0209
0210 void F04DetectorConstruction::SetWorldMaterial(const G4String materialChoice)
0211 {
0212 G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(materialChoice);
0213
0214 if (pttoMaterial != fWorldMaterial) {
0215 if (pttoMaterial) {
0216 fWorldMaterial = pttoMaterial;
0217 G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0218 }
0219 else {
0220 G4cout << "\n--> WARNING from SetWorldMaterial : " << materialChoice << " not found"
0221 << G4endl;
0222 }
0223 }
0224 }
0225
0226
0227
0228 void F04DetectorConstruction::SetTargetMaterial(const G4String materialChoice)
0229 {
0230 G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(materialChoice);
0231
0232 if (pttoMaterial != fTargetMaterial) {
0233 if (pttoMaterial) {
0234 fTargetMaterial = pttoMaterial;
0235 G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0236 }
0237 else {
0238 G4cout << "\n--> WARNING from SetTargetMaterial : " << materialChoice << " not found"
0239 << G4endl;
0240 }
0241 }
0242 }
0243
0244
0245
0246 void F04DetectorConstruction::SetDegraderMaterial(const G4String materialChoice)
0247
0248 {
0249 G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(materialChoice);
0250
0251 if (pttoMaterial != fDegraderMaterial) {
0252 if (pttoMaterial) {
0253 fDegraderMaterial = pttoMaterial;
0254 G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0255 }
0256 else {
0257 G4cout << "\n--> WARNING from SetDegraderMaterial : " << materialChoice << " not found"
0258 << G4endl;
0259 }
0260 }
0261 }
0262
0263
0264
0265 void F04DetectorConstruction::SetWorldSizeZ(G4double val)
0266 {
0267 fWorldSizeZ = val;
0268 if (G4StateManager::GetStateManager()->GetCurrentState() != G4State_PreInit)
0269 G4RunManager::GetRunManager()->GeometryHasBeenModified();
0270 }
0271
0272
0273
0274 void F04DetectorConstruction::SetWorldSizeR(G4double val)
0275 {
0276 fWorldSizeR = val;
0277 if (G4StateManager::GetStateManager()->GetCurrentState() != G4State_PreInit)
0278 G4RunManager::GetRunManager()->GeometryHasBeenModified();
0279 }
0280
0281
0282
0283 void F04DetectorConstruction::SetCaptureMgntRadius(G4double val)
0284 {
0285 fCaptureMgntRadius = val;
0286 if (G4StateManager::GetStateManager()->GetCurrentState() != G4State_PreInit)
0287 G4RunManager::GetRunManager()->GeometryHasBeenModified();
0288 }
0289
0290
0291
0292 void F04DetectorConstruction::SetCaptureMgntLength(G4double val)
0293 {
0294 fCaptureMgntLength = val;
0295 if (G4StateManager::GetStateManager()->GetCurrentState() != G4State_PreInit)
0296 G4RunManager::GetRunManager()->GeometryHasBeenModified();
0297 }
0298
0299
0300
0301 void F04DetectorConstruction::SetCaptureMgntB1(G4double val)
0302 {
0303 fCaptureMgntB1 = val;
0304 if (G4StateManager::GetStateManager()->GetCurrentState() != G4State_PreInit)
0305 G4RunManager::GetRunManager()->GeometryHasBeenModified();
0306 }
0307
0308
0309
0310 void F04DetectorConstruction::SetCaptureMgntB2(G4double val)
0311 {
0312 fCaptureMgntB2 = val;
0313 if (G4StateManager::GetStateManager()->GetCurrentState() != G4State_PreInit)
0314 G4RunManager::GetRunManager()->GeometryHasBeenModified();
0315 }
0316
0317
0318
0319 void F04DetectorConstruction::SetTransferMgntRadius(G4double val)
0320 {
0321 fTransferMgntRadius = val;
0322 if (G4StateManager::GetStateManager()->GetCurrentState() != G4State_PreInit)
0323 G4RunManager::GetRunManager()->GeometryHasBeenModified();
0324 }
0325
0326
0327
0328 void F04DetectorConstruction::SetTransferMgntLength(G4double val)
0329 {
0330 fTransferMgntLength = val;
0331 if (G4StateManager::GetStateManager()->GetCurrentState() != G4State_PreInit)
0332 G4RunManager::GetRunManager()->GeometryHasBeenModified();
0333 }
0334
0335
0336
0337 void F04DetectorConstruction::SetTransferMgntB(G4double val)
0338 {
0339 fTransferMgntB = val;
0340 if (G4StateManager::GetStateManager()->GetCurrentState() != G4State_PreInit)
0341 G4RunManager::GetRunManager()->GeometryHasBeenModified();
0342 }
0343
0344
0345
0346 void F04DetectorConstruction::SetTransferMgntPos(G4double val)
0347 {
0348 fTransferMgntPos = val;
0349 if (G4StateManager::GetStateManager()->GetCurrentState() != G4State_PreInit)
0350 G4RunManager::GetRunManager()->GeometryHasBeenModified();
0351 }
0352
0353
0354
0355 void F04DetectorConstruction::SetTargetRadius(G4double val)
0356 {
0357 fTargetRadius = val;
0358 if (G4StateManager::GetStateManager()->GetCurrentState() != G4State_PreInit)
0359 G4RunManager::GetRunManager()->GeometryHasBeenModified();
0360 }
0361
0362
0363
0364 void F04DetectorConstruction::SetTargetThickness(G4double val)
0365 {
0366 fTargetThickness = val;
0367 if (G4StateManager::GetStateManager()->GetCurrentState() != G4State_PreInit)
0368 G4RunManager::GetRunManager()->GeometryHasBeenModified();
0369 }
0370
0371
0372
0373 void F04DetectorConstruction::SetTargetPos(G4double val)
0374 {
0375 fTargetPos = val;
0376 if (G4StateManager::GetStateManager()->GetCurrentState() != G4State_PreInit)
0377 G4RunManager::GetRunManager()->GeometryHasBeenModified();
0378 }
0379
0380
0381
0382 void F04DetectorConstruction::SetTargetAngle(G4int val)
0383 {
0384 fTargetAngle = val;
0385 if (G4StateManager::GetStateManager()->GetCurrentState() != G4State_PreInit)
0386 G4RunManager::GetRunManager()->GeometryHasBeenModified();
0387 }
0388
0389
0390
0391 void F04DetectorConstruction::SetDegraderRadius(G4double val)
0392 {
0393 fDegraderRadius = val;
0394 if (G4StateManager::GetStateManager()->GetCurrentState() != G4State_PreInit)
0395 G4RunManager::GetRunManager()->GeometryHasBeenModified();
0396 }
0397
0398
0399
0400 void F04DetectorConstruction::SetDegraderThickness(G4double val)
0401 {
0402 fDegraderThickness = val;
0403 if (G4StateManager::GetStateManager()->GetCurrentState() != G4State_PreInit)
0404 G4RunManager::GetRunManager()->GeometryHasBeenModified();
0405 }
0406
0407
0408
0409 void F04DetectorConstruction::SetDegraderPos(G4double val)
0410 {
0411 fDegraderPos = val;
0412 if (G4StateManager::GetStateManager()->GetCurrentState() != G4State_PreInit)
0413 G4RunManager::GetRunManager()->GeometryHasBeenModified();
0414 }
0415
0416
0417
0418 void F04DetectorConstruction::ConstructSDandField()
0419 {
0420 if (!fFieldSetUp.Get()) {
0421 F04GlobalField* field = F04GlobalField::GetObject(this);
0422 G4AutoDelete::Register(field);
0423 fFieldSetUp.Put(field);
0424 }
0425 }
0426
0427
0428
0429 G4RotationMatrix F04DetectorConstruction::StringToRotationMatrix(G4String rotation)
0430 {
0431
0432
0433
0434
0435 G4RotationMatrix rot;
0436
0437 unsigned int place = 0;
0438
0439 while (place < rotation.size()) {
0440 G4double angle;
0441 char* p(nullptr);
0442 G4String current = rotation.substr(place + 1);
0443 angle = strtod(current.c_str(), &p) * deg;
0444
0445 if (!p || (*p != ',' && *p != '\0')) {
0446 G4cerr << "Invalid rotation specification: " << rotation.c_str() << G4endl;
0447
0448 return rot;
0449 }
0450
0451 G4RotationMatrix thisRotation;
0452
0453 switch (rotation.substr(place, 1).c_str()[0]) {
0454 case 'X':
0455 case 'x':
0456 thisRotation = G4RotationMatrix(CLHEP::HepRotationX(angle));
0457 break;
0458 case 'Y':
0459 case 'y':
0460 thisRotation = G4RotationMatrix(CLHEP::HepRotationY(angle));
0461 break;
0462 case 'Z':
0463 case 'z':
0464 thisRotation = G4RotationMatrix(CLHEP::HepRotationZ(angle));
0465 break;
0466 default:
0467 G4cerr << " Invalid rotation specification: " << rotation << G4endl;
0468 return rot;
0469 }
0470
0471 rot = thisRotation * rot;
0472 place = rotation.find(',', place);
0473 if (place > rotation.size()) break;
0474 ++place;
0475 }
0476
0477 return rot;
0478 }