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