19#include "BDSArrayReflectionType.hh"
20#include "BDSBeamPipeInfo.hh"
22#include "BDSException.hh"
23#include "BDSPTCOneTurnMap.hh"
24#include "BDSPrimaryGeneratorAction.hh"
25#include "BDSFieldClassType.hh"
26#include "BDSFieldE.hh"
27#include "BDSFieldEGlobal.hh"
28#include "BDSFieldEGlobalPlacement.hh"
29#include "BDSFieldEInterpolated.hh"
30#include "BDSFieldEInterpolated2Layer.hh"
31#include "BDSFieldESinusoid.hh"
32#include "BDSFieldEZero.hh"
33#include "BDSFieldEM.hh"
34#include "BDSFieldEMGlobal.hh"
35#include "BDSFieldEMGlobalPlacement.hh"
36#include "BDSFieldEMInterpolated.hh"
37#include "BDSFieldEMMuonCooler.hh"
38#include "BDSFieldEMRFCavity.hh"
39#include "BDSFieldEMZero.hh"
40#include "BDSFieldFactory.hh"
41#include "BDSFieldGaborLens.hh"
42#include "BDSFieldInfo.hh"
43#include "BDSFieldInfoExtra.hh"
44#include "BDSFieldLoader.hh"
45#include "BDSFieldMag.hh"
46#include "BDSFieldMagDecapole.hh"
47#include "BDSFieldMagDipole.hh"
48#include "BDSFieldMagDipoleOuter.hh"
49#include "BDSFieldMagDipoleOuterOld.hh"
50#include "BDSFieldMagDipoleQuadrupole.hh"
51#include "BDSFieldMagGlobal.hh"
52#include "BDSFieldMagGlobalPlacement.hh"
53#include "BDSFieldMagInterpolated.hh"
54#include "BDSFieldMagInterpolated2Layer.hh"
55#include "BDSFieldMagMultipole.hh"
56#include "BDSFieldMagMultipoleOuter.hh"
57#include "BDSFieldMagMultipoleOuterDual.hh"
58#include "BDSFieldMagMultipoleOuterDualOld.hh"
59#include "BDSFieldMagMultipoleOuterOld.hh"
60#include "BDSFieldMagMuonSpoiler.hh"
61#include "BDSFieldMagOctupole.hh"
62#include "BDSFieldMagQuadrupole.hh"
63#include "BDSFieldMagSextupole.hh"
64#include "BDSFieldMagSolenoidBlock.hh"
65#include "BDSFieldMagSolenoidSheet.hh"
66#include "BDSFieldMagSolenoidLoop.hh"
67#include "BDSFieldMagSkewOwn.hh"
68#include "BDSFieldMagUndulator.hh"
69#include "BDSFieldMagZero.hh"
70#include "BDSFieldObjects.hh"
71#include "BDSFieldType.hh"
72#include "BDSGlobalConstants.hh"
73#include "BDSIntegratorCavityFringe.hh"
74#include "BDSIntegratorDecapole.hh"
75#include "BDSIntegratorDipoleRodrigues.hh"
76#include "BDSIntegratorDipoleRodrigues2.hh"
77#include "BDSIntegratorDipoleFringe.hh"
78#include "BDSIntegratorDipoleFringeScaling.hh"
79#include "BDSIntegratorDipoleQuadrupole.hh"
80#include "BDSIntegratorEuler.hh"
81#include "BDSIntegratorG4RK4MinStep.hh"
82#include "BDSIntegratorKickerThin.hh"
83#include "BDSIntegratorOctupole.hh"
84#include "BDSIntegratorQuadrupole.hh"
85#include "BDSIntegratorMultipoleThin.hh"
86#include "BDSIntegratorParallelTransport.hh"
87#include "BDSIntegratorSextupole.hh"
88#include "BDSIntegratorSolenoid.hh"
89#include "BDSIntegratorTeleporter.hh"
90#include "BDSIntegratorRMatrixThin.hh"
91#include "BDSIntegratorType.hh"
92#include "BDSMagnetOuterFactoryLHC.hh"
93#include "BDSMagnetStrength.hh"
94#include "BDSMagnetType.hh"
95#include "BDSModulator.hh"
96#include "BDSModulatorInfo.hh"
97#include "BDSModulatorLinearT.hh"
98#include "BDSModulatorSinT.hh"
99#include "BDSModulatorTopHatT.hh"
100#include "BDSModulatorType.hh"
101#include "BDSParser.hh"
102#include "BDSParticleDefinition.hh"
103#include "BDSUtilities.hh"
104#include "BDSWarning.hh"
106#include "parser/field.h"
107#include "parser/modulator.h"
110#include "G4EquationOfMotion.hh"
111#include "G4EqMagElectricField.hh"
112#include "G4MagIntegratorStepper.hh"
113#include "G4Mag_UsualEqRhs.hh"
114#include "G4RotationMatrix.hh"
115#include "G4String.hh"
116#include "G4ThreeVector.hh"
117#include "G4Transform3D.hh"
118#include "G4Version.hh"
121#include "G4CashKarpRKF45.hh"
122#include "G4ClassicalRK4.hh"
123#include "G4ConstRK4.hh"
124#include "G4ExactHelixStepper.hh"
125#include "G4ExplicitEuler.hh"
126#include "G4HelixExplicitEuler.hh"
127#include "G4HelixHeum.hh"
128#include "G4HelixImplicitEuler.hh"
129#include "G4HelixMixedStepper.hh"
130#include "G4HelixSimpleRunge.hh"
131#include "G4ImplicitEuler.hh"
132#include "G4NystromRK4.hh"
133#include "G4RKG3_Stepper.hh"
134#include "G4SimpleHeum.hh"
135#include "G4SimpleRunge.hh"
136#if G4VERSION_NUMBER > 1029
137#include "G4BogackiShampine23.hh"
138#include "G4BogackiShampine45.hh"
139#include "G4DoLoMcPriRK34.hh"
140#include "G4DormandPrince745.hh"
141#include "G4DormandPrinceRK56.hh"
142#include "G4TsitourasRK45.hh"
144#if G4VERSION_NUMBER > 1039
145#include "G4DormandPrinceRK78.hh"
146#include "G4RK547FEq1.hh"
147#include "G4RK547FEq2.hh"
148#include "G4RK547FEq3.hh"
151#include "CLHEP/Units/SystemOfUnits.h"
152#include "CLHEP/Vector/EulerAngles.h"
172 useOldMultipoleOuterFields(false)
174 G4double defaultRigidity = std::numeric_limits<double>::max();
186BDSFieldFactory::~BDSFieldFactory()
189 {
delete info.second;}
190 for (
auto& info : parserModulatorDefinitions)
191 {
delete info.second;}
195 G4double defaultBRho)
197 for (
const auto& definition : definitions)
199 if (definition.type.empty())
201 G4String msg =
"\"type\" not specified in field definition \"";
202 msg += definition.name +
"\", but required.";
208 G4ThreeVector offset = G4ThreeVector(definition.x*CLHEP::m,
209 definition.y*CLHEP::m,
210 definition.z*CLHEP::m);
213 if (definition.axisAngle)
215 G4ThreeVector axis = G4ThreeVector(definition.axisX,
218 rm = G4RotationMatrix(axis, definition.angle*CLHEP::rad);
226 CLHEP::HepEulerAngles ang = CLHEP::HepEulerAngles(definition.phi*CLHEP::rad,
227 definition.theta*CLHEP::rad,
228 definition.psi*CLHEP::rad);
229 rm = G4RotationMatrix(ang);
234 G4Transform3D transform = G4Transform3D(rm, offset);
237 G4String magFile =
"";
238 G4bool magFileSpecified = !definition.magneticFile.empty();
239 if (magFileSpecified)
241 std::pair<G4String, G4String> bf =
BDS::SplitOnColon(G4String(definition.magneticFile));
247 G4String eleFile =
"";
248 G4bool eleFileSpecified = !definition.electricFile.empty();
249 if (eleFileSpecified)
251 std::pair<G4String, G4String> ef =
BDS::SplitOnColon(G4String(definition.electricFile));
257 if (magFileSpecified)
260 if (!definition.magneticInterpolator.empty())
269 if (nDimFF != nDimInt)
271 G4String message =
"mismatch in number of dimensions between magnetic interpolator ";
272 message +=
"and field map format for field definition \"" + definition.name +
"\"";
282 if (eleFileSpecified)
285 if (!definition.electricInterpolator.empty())
294 if (nDimFF != nDimInt)
296 G4String message =
"mismatch in number of dimensions between electric interpolator ";
297 message +=
"and field map format for field definition \"" + definition.name +
"\"";
306 G4UserLimits* fieldLimit =
nullptr;
307 G4bool ignoreUpdateOfMaximumStepSize = definition.maximumStepLengthOverride > 0;
308 if (definition.maximumStepLength > 0 || ignoreUpdateOfMaximumStepSize)
312 G4double limit = G4double(definition.maximumStepLength) * CLHEP::m;
313 if (ignoreUpdateOfMaximumStepSize)
315 limit = definition.maximumStepLengthOverride * CLHEP::m;
316 G4cout << __METHOD_NAME__ <<
"maximumStepLengthOverride set to " << limit <<
" mm for field definition \""
317 << definition.name <<
"\" -> careful!" << G4endl;
327 if (!definition.fieldParameters.empty())
334 G4bool(definition.globalTransform),
343 G4double(definition.eScaling),
344 G4double(definition.bScaling),
345 G4double(definition.t*CLHEP::s),
346 G4bool(definition.autoScale),
348 info->SetScalingRadius(poleTipRadius);
350 if (ignoreUpdateOfMaximumStepSize)
351 {info->SetIgnoreUpdateOfMaximumStepSize(
true);}
353 if (!definition.magneticSubField.empty())
355 if (definition.magneticSubField == definition.name)
356 {
throw BDSException(__METHOD_NAME__,
"error in \"" + definition.name +
"\": magneticSubField cannot be the field itself");}
357 info->SetMagneticSubField(G4String(definition.magneticSubField));
359 if (!definition.electricSubField.empty())
361 if (definition.electricSubField == definition.name)
362 {
throw BDSException(__METHOD_NAME__,
"error in \"" + definition.name +
"\": electricSubField cannot be the field itself");}
363 info->SetElectricSubField(G4String(definition.electricSubField));
365 if (!definition.magneticReflection.empty())
367 G4String magneticReflection = G4String(definition.magneticReflection);
369 info->SetMagneticArrayReflectionType(mar);
371 if (!definition.electricReflection.empty())
373 G4String electricReflection = G4String(definition.electricReflection);
375 info->SetElectricArrayReflectionType(ear);
378 info->SetNameOfParserDefinition(G4String(definition.name));
381 G4cout <<
"Definition: \"" << definition.name <<
"\"" << G4endl;
382 G4cout << *info << G4endl;
390 for (
const auto& definition : definitions)
392 if (definition.type.empty())
394 G4String msg =
"\"type\" not specified in modulator definition \"";
395 msg += definition.name +
"\", but required.";
400 G4double frequency = definition.frequency * CLHEP::hertz;
401 G4double phase = definition.phase * CLHEP::rad;
405 {
throw BDSException(__METHOD_NAME__,
"definition: " + definition.name +
" has both tOffset and phase specified - only one can be used.");}
406 phase = definition.tOffset*CLHEP::s * frequency * CLHEP::twopi;
414 definition.tOffset * CLHEP::s,
415 definition.amplitudeScale,
416 definition.amplitudeOffset,
417 definition.T0 * CLHEP::s,
418 definition.T1 * CLHEP::s);
419 info->nameOfParserDefinition = definition.name;
420 parserModulatorDefinitions[G4String(definition.name)] = info;
425 const G4String& parameterNameForError)
const
429 {result = std::stod(value);}
430 catch (std::exception& e)
432 G4String msg(e.what());
433 G4String baseMsg =
"Unable to interpret value (\"" + value +
"\" of parameter \"";
434 baseMsg += parameterNameForError +
"\" as a number: ";
441 const G4String& fieldParameters,
442 G4double& poleTipRadius)
const
448 for (
const auto& keyValue : map)
455 else if (keyValue.first ==
"poletipradius")
459 G4String msg =
"Invalid key \"" + keyValue.first +
"\" for field parameters. ";
460 msg +=
"Acceptable parameters are: \n";
462 for (G4int i = 0; i < (G4int)allKeys.size(); i++)
464 msg += allKeys[i] +
", ";
465 if ((i % 10 == 0) && (i > 0))
483 G4cerr << __METHOD_NAME__ <<
"\"" << name <<
"\" is not a valid field specifier" << G4endl;
484 G4cout <<
"Defined field specifiers are:" << G4endl;
486 {G4cout <<
"\"" << it.first <<
"\"" << G4endl;}
487 throw BDSException(__METHOD_NAME__,
"invalid field name");
489 return result->second;
494 if (modulatorName.empty())
497 auto search = parserModulatorDefinitions.find(modulatorName);
498 if (search == parserModulatorDefinitions.end())
500 G4cerr << __METHOD_NAME__ <<
"\"" << modulatorName <<
"\" is not a valid modulator definition name" << G4endl;
501 G4cout <<
"Defined modulator definitions are:" << G4endl;
502 for (
const auto& it : parserModulatorDefinitions)
503 {G4cout <<
"\"" << it.first <<
"\"" << G4endl;}
504 throw BDSException(__METHOD_NAME__,
"invalid modulator name");
507 {
return search->second;}
512 const G4String& scalingKey)
518 if (info.
FieldType() == BDSFieldType::none)
526 case BDSFieldClassType::magnetic:
527 {field =
CreateFieldMag(info, scalingStrength, scalingKey);
break;}
528 case BDSFieldClassType::electromagnetic:
530 case BDSFieldClassType::electric:
532 case BDSFieldClassType::irregular:
549 switch (numberOfDimensions)
552 {result = BDSInterpolatorType::cubic1d;
break;}
554 {result = BDSInterpolatorType::cubic2d;
break;}
556 {result = BDSInterpolatorType::cubic3d;
break;}
558 {result = BDSInterpolatorType::cubic4d;
break;}
560 {
throw BDSException(__METHOD_NAME__,
"unsupported number of dimensions " + std::to_string(numberOfDimensions));}
567 const G4String& scalingKey)
588 return completeField;
593 const G4String& scalingKey)
597 G4double brho = info.
BRho();
602 case BDSFieldType::bmap1d:
603 case BDSFieldType::bmap2d:
604 case BDSFieldType::bmap3d:
605 case BDSFieldType::bmap4d:
606 case BDSFieldType::mokka:
616 case BDSFieldType::bfieldzero:
618 case BDSFieldType::solenoid:
619 case BDSFieldType::dipole:
620 case BDSFieldType::dipole3d:
622 case BDSFieldType::solenoidblock:
624 case BDSFieldType::solenoidloop:
626 case BDSFieldType::solenoidsheet:
628 case BDSFieldType::quadrupole:
630 case BDSFieldType::undulator:
632 case BDSFieldType::dipolequadrupole:
634 case BDSFieldType::sextupole:
636 case BDSFieldType::octupole:
638 case BDSFieldType::decapole:
640 case BDSFieldType::multipole:
642 case BDSFieldType::muonspoiler:
644 case BDSFieldType::skewquadrupole:
646 case BDSFieldType::skewsextupole:
648 case BDSFieldType::skewoctupole:
650 case BDSFieldType::skewdecapole:
652 case BDSFieldType::multipoleouterdipole:
655 G4bool positiveField = (*strength)[
"field"] < 0;
656 if (useOldMultipoleOuterFields)
663 case BDSFieldType::multipoleouterquadrupole:
666 G4bool positiveField = (*strength)[
"k1"] > 0;
667 if (useOldMultipoleOuterFields)
674 case BDSFieldType::multipoleoutersextupole:
677 G4bool positiveField = (*strength)[
"k2"] > 0;
678 if (useOldMultipoleOuterFields)
685 case BDSFieldType::multipoleouteroctupole:
688 G4bool positiveField = (*strength)[
"k3"] > 0;
689 if (useOldMultipoleOuterFields)
696 case BDSFieldType::multipoleouterdecapole:
699 G4bool positiveField = (*strength)[
"k4"] > 0;
700 if (useOldMultipoleOuterFields)
707 case BDSFieldType::skewmultipoleouterquadrupole:
710 G4bool positiveField = (*strength)[
"k1"] > 0;
712 if (useOldMultipoleOuterFields)
720 case BDSFieldType::skewmultipoleoutersextupole:
723 G4bool positiveField = (*strength)[
"k2"] > 0;
725 if (useOldMultipoleOuterFields)
733 case BDSFieldType::skewmultipoleouteroctupole:
736 G4bool positiveField = (*strength)[
"k3"] > 0;
738 if (useOldMultipoleOuterFields)
746 case BDSFieldType::skewmultipoleouterdecapole:
749 G4bool positiveField = (*strength)[
"k4"] > 0;
751 if (useOldMultipoleOuterFields)
759 case BDSFieldType::multipoleouterdipole3d:
761 if (useOldMultipoleOuterFields)
767 case BDSFieldType::multipoleouterdipolelhc:
770 G4bool positiveField = (*strength)[
"field"] < 0;
771 G4bool positiveField2 = (*strength)[
"angle"] > 0;
773 if (useOldMultipoleOuterFields)
786 case BDSFieldType::multipoleouterquadrupolelhc:
789 G4bool positiveField = (*strength)[
"k1"] > 0;
791 if (useOldMultipoleOuterFields)
804 case BDSFieldType::multipoleoutersextupolelhc:
807 G4bool positiveField = (*strength)[
"k2"] > 0;
809 if (useOldMultipoleOuterFields)
822 case BDSFieldType::paralleltransporter:
840 {BDS::Warning(__METHOD_NAME__,
"using a time varying modulation on a time varying field for field \"" + info.
NameOfParserDefinition() +
"\"");}
845 <<
"\" so will not reduce maximum step size for modulator\n";
859 {
throw BDSException(__METHOD_NAME__,
"subfield specified for non-field map type field - not supported");}
865 {
throw BDSException(__METHOD_NAME__,
"subfield type is not a field map type field - not supported");}
869 delete subFieldRecipe;
877 G4double brho = info.
BRho();
881 case BDSFieldType::rfpillbox:
883 case BDSFieldType::ebmap1d:
884 case BDSFieldType::ebmap2d:
885 case BDSFieldType::ebmap3d:
886 case BDSFieldType::ebmap4d:
894 case BDSFieldType::ebfieldzero:
896 case BDSFieldType::gaborlens:
898 case BDSFieldType::muoncooler:
914 {BDS::Warning(__METHOD_NAME__,
"using a time varying modulation on a time varying field for field \"" + info.
NameOfParserDefinition() +
"\"");}
931 G4EqMagElectricField* eqOfM =
new G4EqMagElectricField(resultantField);
937 return completeField;
954 G4EqMagElectricField* eqOfM =
new G4EqMagElectricField(resultantField);
960 return completeField;
968 case BDSFieldType::rfconstantinx:
969 case BDSFieldType::rfconstantiny:
970 case BDSFieldType::rfconstantinz:
972 case BDSFieldType::emap1d:
973 case BDSFieldType::emap2d:
974 case BDSFieldType::emap3d:
975 case BDSFieldType::emap4d:
983 case BDSFieldType::efieldzero:
999 {BDS::Warning(__METHOD_NAME__,
"using a time varying modulation on a time varying field for field \"" + info.
NameOfParserDefinition() +
"\"");}
1012 {
throw BDSException(__METHOD_NAME__,
"subfield specified for non-field map type field - not supported");}
1018 {
throw BDSException(__METHOD_NAME__,
"subfield type is not a field map type field - not supported");}
1022 delete subFieldRecipe;
1034 case BDSFieldType::teleporter:
1036 case BDSFieldType::rmatrix:
1038 case BDSFieldType::cavityfringe:
1040 case BDSFieldType::paralleltransporter:
1052 const G4double minimumRadiusOfCurvature = 10*CLHEP::cm;
1053 G4double brho = info.
BRho();
1054 G4MagIntegratorStepper* integrator =
nullptr;
1058 case BDSIntegratorType::solenoid:
1060 case BDSIntegratorType::dipolerodrigues:
1062 case BDSIntegratorType::dipolerodrigues2:
1064 case BDSIntegratorType::dipolematrix:
1066 case BDSIntegratorType::quadrupole:
1068 case BDSIntegratorType::sextupole:
1070 case BDSIntegratorType::octupole:
1072 case BDSIntegratorType::decapole:
1074 case BDSIntegratorType::multipolethin:
1076 case BDSIntegratorType::dipolefringe:
1078 case BDSIntegratorType::dipolefringescaling:
1080 case BDSIntegratorType::euler:
1082 case BDSIntegratorType::kickerthin:
1084 case BDSIntegratorType::g4rk4minimumstep:
1086 case BDSIntegratorType::rmatrixthin:
1088 case BDSIntegratorType::cavityfringe:
1090 case BDSIntegratorType::g4constrk4:
1091 integrator =
new G4ConstRK4(eqOfM);
break;
1092 case BDSIntegratorType::g4exacthelixstepper:
1093 integrator =
new G4ExactHelixStepper(eqOfM);
break;
1094 case BDSIntegratorType::g4helixexpliciteuler:
1095 integrator =
new G4HelixExplicitEuler(eqOfM);
break;
1096 case BDSIntegratorType::g4helixheum:
1097 integrator =
new G4HelixHeum(eqOfM);
break;
1098 case BDSIntegratorType::g4heliximpliciteuler:
1099 integrator =
new G4HelixImplicitEuler(eqOfM);
break;
1100 case BDSIntegratorType::g4helixmixedstepper:
1101 integrator =
new G4HelixMixedStepper(eqOfM);
break;
1102 case BDSIntegratorType::g4helixsimplerunge:
1103 integrator =
new G4HelixSimpleRunge(eqOfM);
break;
1104 case BDSIntegratorType::g4nystromrk4:
1105 integrator =
new G4NystromRK4(eqOfM);
break;
1106 case BDSIntegratorType::g4rkg3stepper:
1107 integrator =
new G4RKG3_Stepper(eqOfM);
break;
1108 case BDSIntegratorType::g4cashkarprkf45:
1109 case BDSIntegratorType::g4classicalrk4:
1110 case BDSIntegratorType::g4expliciteuler:
1111 case BDSIntegratorType::g4impliciteuler:
1112 case BDSIntegratorType::g4simpleheum:
1113 case BDSIntegratorType::g4simplerunge:
1114#if G4VERSION_NUMBER > 1029
1115 case BDSIntegratorType::g4bogackishampine23:
1116 case BDSIntegratorType::g4bogackishampine45:
1117 case BDSIntegratorType::g4dolomcprirk34:
1118 case BDSIntegratorType::g4dormandprince745:
1119 case BDSIntegratorType::g4dormandprincerk56:
1120 case BDSIntegratorType::g4tsitourasrk45:
1122#if G4VERSION_NUMBER > 1039
1123 case BDSIntegratorType::g4dormandprincerk78:
1124 case BDSIntegratorType::g4rk547feq1:
1125 case BDSIntegratorType::g4rk547feq2:
1126 case BDSIntegratorType::g4rk547feq3:
1137 G4EquationOfMotion* eqOfM)
1139 G4MagIntegratorStepper* integrator =
nullptr;
1143 case BDSIntegratorType::g4cashkarprkf45:
1144 integrator =
new G4CashKarpRKF45(eqOfM, 8);
break;
1145 case BDSIntegratorType::g4classicalrk4:
1146 integrator =
new G4ClassicalRK4(eqOfM, 8);
break;
1147 case BDSIntegratorType::g4expliciteuler:
1148 integrator =
new G4ExplicitEuler(eqOfM, 8);
break;
1149 case BDSIntegratorType::g4impliciteuler:
1150 integrator =
new G4ImplicitEuler(eqOfM, 8);
break;
1151 case BDSIntegratorType::g4simpleheum:
1152 integrator =
new G4SimpleHeum(eqOfM, 8);
break;
1153 case BDSIntegratorType::g4simplerunge:
1154 integrator =
new G4SimpleRunge(eqOfM, 8);
break;
1155#if G4VERSION_NUMBER > 1029
1156 case BDSIntegratorType::g4bogackishampine23:
1157 {integrator =
new G4BogackiShampine45(eqOfM, 8);
break;}
1158 case BDSIntegratorType::g4bogackishampine45:
1159 {integrator =
new G4BogackiShampine45(eqOfM, 8);
break;}
1160 case BDSIntegratorType::g4dolomcprirk34:
1161 {integrator =
new G4DoLoMcPriRK34(eqOfM, 8);
break;}
1162 case BDSIntegratorType::g4dormandprince745:
1163 {integrator =
new G4DormandPrince745(eqOfM, 8);
break;}
1164 case BDSIntegratorType::g4dormandprincerk56:
1165 {integrator =
new G4DormandPrinceRK56(eqOfM, 8);
break;}
1166 case BDSIntegratorType::g4tsitourasrk45:
1167 {integrator =
new G4TsitourasRK45(eqOfM, 8);
break;}
1169#if G4VERSION_NUMBER > 1039
1170 case BDSIntegratorType::g4dormandprincerk78:
1171 {integrator =
new G4DormandPrinceRK78(eqOfM, 8);
break;}
1172 case BDSIntegratorType::g4rk547feq1:
1173 {integrator =
new G4RK547FEq1(eqOfM, 8);
break;}
1174 case BDSIntegratorType::g4rk547feq2:
1175 {integrator =
new G4RK547FEq2(eqOfM, 8);
break;}
1176 case BDSIntegratorType::g4rk547feq3:
1177 {integrator =
new G4RK547FEq3(eqOfM, 8);
break;}
1179 case BDSIntegratorType::solenoid:
1180 case BDSIntegratorType::dipolerodrigues:
1181 case BDSIntegratorType::quadrupole:
1182 case BDSIntegratorType::sextupole:
1183 case BDSIntegratorType::octupole:
1184 case BDSIntegratorType::decapole:
1185 case BDSIntegratorType::dipolefringe:
1186 case BDSIntegratorType::g4constrk4:
1187 case BDSIntegratorType::g4exacthelixstepper:
1188 case BDSIntegratorType::g4helixexpliciteuler:
1189 case BDSIntegratorType::g4helixheum:
1190 case BDSIntegratorType::g4heliximpliciteuler:
1191 case BDSIntegratorType::g4helixmixedstepper:
1192 case BDSIntegratorType::g4helixsimplerunge:
1193 case BDSIntegratorType::g4nystromrk4:
1194 case BDSIntegratorType::g4rkg3stepper:
1196 G4cerr <<
"Error: integrator \"" << info.
IntegratorType() <<
"\" is not suitable for an EM field." << G4endl;
1197 G4cout <<
"Suitable integrators are:" << G4endl;
1198 std::vector<BDSIntegratorType> types = {
1199 BDSIntegratorType::g4cashkarprkf45,
1200 BDSIntegratorType::g4classicalrk4,
1201 BDSIntegratorType::g4expliciteuler,
1202 BDSIntegratorType::g4impliciteuler,
1203 BDSIntegratorType::g4simpleheum,
1204 BDSIntegratorType::g4simplerunge
1205#if G4VERSION_NUMBER > 1029
1207 BDSIntegratorType::g4bogackishampine23,
1208 BDSIntegratorType::g4bogackishampine45,
1209 BDSIntegratorType::g4dolomcprirk34,
1210 BDSIntegratorType::g4dormandprince745,
1211 BDSIntegratorType::g4dormandprincerk56,
1212 BDSIntegratorType::g4tsitourasrk45
1214#if G4VERSION_NUMBER > 1039
1216 BDSIntegratorType::g4dormandprincerk78,
1217 BDSIntegratorType::g4rk547feq1,
1218 BDSIntegratorType::g4rk547feq2,
1219 BDSIntegratorType::g4rk547feq3
1222 for (
auto type : types)
1223 {G4cout << type << G4endl;}
1224 throw BDSException(__METHOD_NAME__,
"invalid integrator type");
1233 G4EquationOfMotion* eqOfM)
1241 G4Mag_EqRhs* bEqOfMotion =
new G4Mag_UsualEqRhs(bGlobalField);
1243 G4MagIntegratorStepper* integrator;
1247 if (!mapfile.empty())
1258 bEqOfMotion, integrator);
1259 return completeField;
1265 G4Mag_EqRhs* bEqOfMotion =
new G4Mag_UsualEqRhs(bGlobalField);
1268 bEqOfMotion, integrator);
1269 return completeField;
1278 bEqOfMotion, integrator);
1279 return completeField;
1285 G4Mag_EqRhs* bEqOfMotion =
new G4Mag_UsualEqRhs(bGlobalField);
1288 bEqOfMotion, integrator);
1289 return completeField;
1294 G4double result = 1.0;
1296 {result = (*st)[
"scalingOuter"];}
1301 G4double brho)
const
1314 if (!modulatorRecipe)
1321 case BDSModulatorType::lineart:
1324 modulatorRecipe->
T1,
1325 modulatorRecipe->
scale,
1329 case BDSModulatorType::sint:
1332 modulatorRecipe->
phase,
1333 info.SynchronousT(),
1335 modulatorRecipe->
scale);
1338 case BDSModulatorType::singlobalt:
1341 modulatorRecipe->
phase,
1344 modulatorRecipe->
scale);
1347 case BDSModulatorType::tophatt:
1350 modulatorRecipe->
T1,
1351 modulatorRecipe->
scale);
1354 case BDSModulatorType::none:
1361 G4String extraMsg =
"\nProblem in field definition for component \"" + info.
NameOfParserDefinition() +
"\"";
1362 e.AppendToMessage(extraMsg);
G4double aper1
Public member for direct access.
General exception with possible name of object and message.
Wrapper class to convert to global coordinates using a navigator for placements.
A base class for electric fields in local to be used in global coordinates.
Two interpolated fields in one. One takes precedence in a subregion.
Class to provide scaling and a base class pointer for interpolator fields.
A base class for electro-magnetic fields in local to be used in global coordinates.
A base class for electro-magnetic fields in local to be used in global coordinates.
Class to provide scaling and a base class pointer for interpolator fields.
A composite RF and B field for a muon cooler.
Pill box cavity electromagnetic field.
Null EM field - for special cases where we need a valid object.
Interface for BDSIM electro-magnetic fields that may or may not be local.
void SetModulator(BDSModulator *modulatorIn)
Set the optional modulator.
virtual G4bool TimeVarying() const
virtual void SetTransform(const G4Transform3D &transformIn)
A sinusoidal electric (only) field that doesn't vary with position. Uses cosine.
Null E field - for special cases where we need a valid object.
Interface for BDSIM electric fields that may or may not be local.
virtual G4bool TimeVarying() const
void SetModulator(BDSModulator *modulatorIn)
Set the optional modulator.
virtual void SetTransform(const G4Transform3D &transformIn)
Factory that produces fields and their associated objects.
G4double GetOuterScaling(const BDSMagnetStrength *st) const
Return the parameter "outerScaling" from strength st, but default to 1.
void PrepareFieldDefinitions(const std::vector< GMAD::Field > &definitions, G4double defaultBRho)
Prepare all required definitions that can be used dynamically.
void PrepareModulatorDefinitions(const std::vector< GMAD::Modulator > &definitions)
Prepare all required modulator definitions that can be used dynamically.
BDSFieldObjects * CreateFieldE(const BDSFieldInfo &info)
Create an electric field.
BDSFieldObjects * CreateFieldIrregular(const BDSFieldInfo &info)
Create an irregular (special) field.
BDSFieldObjects * CreateRMatrix(const BDSFieldInfo &info)
Create special rmatrix 'field' that applies an rmatrix.
void PrepareFieldStrengthFromParameters(BDSMagnetStrength *st, const G4String &fieldParameters, G4double &poleTipRadius) const
static BDSPrimaryGeneratorAction * primaryGeneratorAction
Cache of primary generator action.
BDSModulator * CreateModulator(const BDSModulatorInfo *modulatorRecipe, const BDSFieldInfo &info) const
Create the necessary modulator.
BDSFieldE * CreateFieldERaw(const BDSFieldInfo &info)
Creat just the electric field object.
G4double ConvertToDoubleWithException(const G4String &value, const G4String ¶meterNameForError) const
Convert the string 'value' to a double. Throw an exception including the parameterNameForError if it ...
static BDSFieldFactory * Instance()
Public accessor method for singleton pattern.
BDSFieldObjects * CreateField(const BDSFieldInfo &info, const BDSMagnetStrength *scalingStrength=nullptr, const G4String &scalingKey="none")
Main interface to field factory.
BDSFieldObjects * CreateParallelTransport(const BDSFieldInfo &info)
static BDSFieldFactory * instance
Instance - singleton pattern.
BDSFieldInfo * GetDefinition(const G4String &name) const
BDSFieldObjects * CreateCavityFringe(const BDSFieldInfo &info)
Create special rf cavity fringe 'field' that applies an rmatrix.
std::map< G4String, BDSFieldInfo * > parserDefinitions
BDSFieldInfo definitions prepare from parser vector of definitions.
G4MagIntegratorStepper * CreateIntegratorMag(const BDSFieldInfo &info, G4Mag_EqRhs *eqOfM, const BDSMagnetStrength *strength)
BDSFieldEM * CreateMuonCoolerField(const BDSFieldInfo &info, G4double brho) const
Create a composite muon cooler field EM field.
G4MagIntegratorStepper * CreateIntegratorE(const BDSFieldInfo &info, G4EquationOfMotion *eqOfM)
BDSFieldObjects * CreateFieldMag(const BDSFieldInfo &info, const BDSMagnetStrength *scalingStrength=nullptr, const G4String &scalingKey="none")
Create a purely magnetic field.
static BDSInterpolatorType DefaultInterpolatorType(G4int numberOfDimensions)
Suggest a default interpolator.
BDSFieldObjects * CreateFieldEM(const BDSFieldInfo &info)
Create a general EM field.
BDSFieldMag * CreateFieldMagRaw(const BDSFieldInfo &info, const BDSMagnetStrength *scalingStrength=nullptr, const G4String &scalingKey="none")
Creat just the magnetic field object.
BDSFieldFactory()
Private default constructor as singleton class.
BDSModulatorInfo * GetModulatorDefinition(const G4String &modulatorName) const
BDSFieldObjects * CreateTeleporter(const BDSFieldInfo &info)
G4MagIntegratorStepper * CreateIntegratorEM(const BDSFieldInfo &info, G4EquationOfMotion *eqOfM)
static const BDSParticleDefinition * designParticle
Cache of design particle for fields.
Gabor lens electromagnetic field.
All info required to build complete field of any type.
G4String MagneticSubFieldName() const
Accessor.
void UpdateUserLimitsLengthMaximumStepSize(G4double maximumStepSize, G4bool warn=false) const
G4Transform3D TransformComplete() const
Compound transform of field + beam line transform.
G4String NameOfParserDefinition() const
Accessor.
G4bool SecondFieldOnLeft() const
Accessor.
G4double PoleTipRadius() const
Accessor.
G4bool ProvideGlobal() const
Accessor.
BDSIntegratorType IntegratorType() const
Accessor.
G4double BeamPipeRadius() const
Accessor.
G4String ElectricSubFieldName() const
Accessor.
G4Transform3D Transform() const
Transform for the field definition only.
G4bool UsePlacementWorldTransform() const
Accessor.
G4bool IgnoreUpdateOfMaximumStepSize() const
Accessor.
BDSModulatorInfo * ModulatorInfo() const
Accessor.
G4double Tilt() const
Accessor.
BDSFieldType FieldType() const
Accessor.
BDSMagnetStrength * MagnetStrength() const
Accessor.
G4double BRho() const
Accessor.
G4Transform3D TransformBeamline() const
Transform from the curvilinear coordinates to the beam line component.
BDSFieldInfoExtra * ExtraInfo() const
Accessor.
BDSFieldEMInterpolated * LoadEMField(const BDSFieldInfo &info)
Main interface to load an electro-magnetic field.
BDSFieldMagInterpolated * LoadMagField(const BDSFieldInfo &info, const BDSMagnetStrength *scalingStrength=nullptr, const G4String &scalingKey="none")
Main interface to load a magnetic field.
static BDSFieldLoader * Instance()
Singleton accessor.
BDSFieldEInterpolated * LoadEField(const BDSFieldInfo &info)
Main interface to load an electric field.
Class that provides the magnetic strength in a decapole.
A perfect magetic dipole in 3D, normal field inside 1/2 poleTipRadius.
A perfect magetic dipole in 3D, normal field inside 1/2 poleTipRadius.
Class that provides the magnetic strength in a mixed dipole / quadrupole.
A base class for magnetic fields in local to be used in global coordinates.
A base class for magnetic fields in local to be used in global coordinates.
Two interpolated fields in one. One takes precedence in a subregion.
Class to provide scaling and a base class pointer for interpolator fields.
Sum of two multipole fields spaced by a distance in x.
Sum of two multipole fields spaced by a distance in x.
A simple paramaterisation of N-Pole outer yoke magnetic field.
A simple parameterisation of N-Pole outer yoke magnetic field.
Class that provides the magnetic strength in a quadrupole.
Class that provides the magnetic strength in an octupole.
Class that provides the magnetic strength in a quadrupole.
Class that provides the magnetic strength in a sextupole.
A wrapper class for BDSFieldMagSkew where it owns the field.
Class that provides the magnetic field due to a square annulus of current.
Class that provides the magnetic field due to a cylinder of current.
Class that provides the magnetic field due to a cylinder of current.
Class that provides the magnetic strength in a quadrupole.
Null B field - for special cases where we need a valid object.
Interface for static magnetic fields that may or may not be local.
virtual void SetTransform(const G4Transform3D &transformIn)
virtual G4bool TimeVarying() const
void SetModulator(BDSModulator *modulatorIn)
Set the optional modulator.
A holder for all the Geant4 field related objects.
static BDSGlobalConstants * Instance()
Access method.
Integrator for RF cavity fringes. Only the transverse momentum kicks are applied, this integrator wil...
Integrator for Decapolar field.
Derived fringe field integrator that does normalise to momentum.
Integrator that ignores the field and uses the analytical solution for a dipole kick.
Integrator for combined dipole and quadrupolar field.
Exact helix through pure dipole field.
Stepper that calculates trajectory through uniform magnetic field.
BDSIM 2nd order Euler integration.
Integrator that wraps a G4ClassicalRK4 and below a minimum step size uses a drift.
Integrator for thin h or v kick.
Integrator that ignores the field and uses the analytical solution to a multipole.
Integrator for octupole field.
Integrator that just moves the particle parallel to the s axis.
Integrator that ignores the field and uses the analytical solution to a quadrupole.
Integrator that just moves the particle parallel to the s axis.
Integrator for sextupole field.
Integrator that ignores the field and uses the analytical solution to a solenoid.
Custom unphysical integrator to advance particle in teleporter.
Override G4Mag_UsualEqRhs, provides BDSIM integrators access to particle attributes.
static const G4double beamSeparation
Used in many places - make it a constant in the code and put here as most relevant.
Efficient storage of magnet strengths.
G4bool KeyHasBeenSet(const G4String &key) const
Whether a key has been set.
static G4bool ValidKey(const G4String &key)
Whether or not the supplied key is a valid magnet strength parameter.
static const std::vector< G4String > & AllKeys()
Accessor to all keys.
static G4double Unit(const G4String &key)
Access a unit factor for a given key.
Holder class for all information required to describe a modulator.
G4double T1
Public member for direct access.
G4double frequency
Public member for direct access.
BDSModulatorType modulatorType
Public member for direct access.
G4double T0
Public member for direct access.
G4double phase
Public member for direct access.
G4double scale
Public member for direct access.
G4double amplitudeOffset
Public member for direct access.
Top-hat modulator as a function of T.
Sinusoidal modulator as a function of global time.
Top-hat modulator as a function of T.
Base class for a modulator.
virtual G4double RecommendedMaxStepLength() const =0
Must return the smallest spatial.
virtual G4bool VariesWithTime() const =0
Each derived class should override this.
Class to load and use PTC 1 turn map.
static BDSParser * Instance()
Access method.
static bool IsInitialised()
Returns if parser is initialised.
Wrapper for particle definition.
G4double BRho() const
Accessor.
Generates primary particle vertices using BDSBunch.
void RegisterPTCOneTurnMap(BDSPTCOneTurnMap *otmIn)
type underlying() const
return underlying value (can be used in switch statement)
BDSArrayReflectionTypeSet DetermineArrayReflectionTypeSet(const G4String &arrayReflectionType)
Return a std::set of reflection types. Split string on white space.
BDSInterpolatorType InterpolatorTypeSpecificFromAuto(G4int nDimension, BDSInterpolatorType autoType)
BDSModulatorType DetermineModulatorType(G4String mType)
Function that gives corresponding enum value for string (case-insensitive)
G4bool InterpolatorTypeIsAuto(BDSInterpolatorType typeIn)
Return true if the type is one containing 'auto'.
BDSFieldFormat DetermineFieldFormat(G4String fieldformat)
Function that gives corresponding enum value for string (case-insensitive)
std::pair< G4String, G4String > SplitOnColon(const G4String &formatAndPath)
BDSFieldType DetermineFieldType(G4String fieldType)
Function that gives corresponding enum value for string (case-insensitive)
BDSInterpolatorType DetermineInterpolatorType(G4String interpolatorType)
Function that determines enum from string (case-insensitive).
BDSFieldClassType DetermineFieldClassType(BDSFieldType fieldType)
Function that gives the corresponding enum value for a field type enum.
G4String GetFullPath(G4String filename, bool excludeNameFromPath=false, bool useCWDForPrefix=false)
G4UserLimits * CreateUserLimits(G4UserLimits *defaultUL, G4double length, G4double fraction=1.6)
BDSIntegratorType DetermineIntegratorType(G4String integratorType)
Function that determines enum from string (case-insensitive).
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())
G4int NDimensionsOfInterpolatorType(const BDSInterpolatorType &it)
Report the number of dimensions for that interpolator type.
G4int NDimensionsOfFieldFormat(const BDSFieldFormat &ff)
Report the number of dimensions for that format.
std::map< G4String, G4String > GetUserParametersMap(const G4String &userParameters, char delimiter=':')
Take one long string and split on space and then on colon. "key1:value1 key2:value2" etc.