18#include "BDSArrayReflectionType.hh"
19#include "BDSBeamPipeInfo.hh"
21#include "BDSException.hh"
22#include "BDSPTCOneTurnMap.hh"
23#include "BDSPrimaryGeneratorAction.hh"
24#include "BDSFieldClassType.hh"
25#include "BDSFieldE.hh"
26#include "BDSFieldEGlobal.hh"
27#include "BDSFieldEGlobalPlacement.hh"
28#include "BDSFieldEInterpolated.hh"
29#include "BDSFieldEInterpolated2Layer.hh"
30#include "BDSFieldESinusoid.hh"
31#include "BDSFieldEZero.hh"
32#include "BDSFieldEM.hh"
33#include "BDSFieldEMGlobal.hh"
34#include "BDSFieldEMGlobalPlacement.hh"
35#include "BDSFieldEMInterpolated.hh"
36#include "BDSFieldEMMuonCooler.hh"
37#include "BDSFieldEMRFCavity.hh"
38#include "BDSFieldEMZero.hh"
39#include "BDSFieldFactory.hh"
40#include "BDSFieldGaborLens.hh"
41#include "BDSFieldInfo.hh"
42#include "BDSFieldInfoExtra.hh"
43#include "BDSFieldLoader.hh"
44#include "BDSFieldMag.hh"
45#include "BDSFieldMagDecapole.hh"
46#include "BDSFieldMagDipole.hh"
47#include "BDSFieldMagDipoleOuter.hh"
48#include "BDSFieldMagDipoleOuterOld.hh"
49#include "BDSFieldMagDipoleQuadrupole.hh"
50#include "BDSFieldMagGlobal.hh"
51#include "BDSFieldMagGlobalPlacement.hh"
52#include "BDSFieldMagInterpolated.hh"
53#include "BDSFieldMagInterpolated2Layer.hh"
54#include "BDSFieldMagMultipole.hh"
55#include "BDSFieldMagMultipoleOuter.hh"
56#include "BDSFieldMagMultipoleOuterDual.hh"
57#include "BDSFieldMagMultipoleOuterDualOld.hh"
58#include "BDSFieldMagMultipoleOuterOld.hh"
59#include "BDSFieldMagMuonSpoiler.hh"
60#include "BDSFieldMagOctupole.hh"
61#include "BDSFieldMagQuadrupole.hh"
62#include "BDSFieldMagSextupole.hh"
63#include "BDSFieldMagSolenoidBlock.hh"
64#include "BDSFieldMagSolenoidSheet.hh"
65#include "BDSFieldMagSolenoidLoop.hh"
66#include "BDSFieldMagSkewOwn.hh"
67#include "BDSFieldMagUndulator.hh"
68#include "BDSFieldMagZero.hh"
69#include "BDSFieldObjects.hh"
70#include "BDSFieldType.hh"
71#include "BDSGlobalConstants.hh"
72#include "BDSIntegratorCavityFringe.hh"
73#include "BDSIntegratorDecapole.hh"
74#include "BDSIntegratorDipoleRodrigues.hh"
75#include "BDSIntegratorDipoleRodrigues2.hh"
76#include "BDSIntegratorDipoleFringe.hh"
77#include "BDSIntegratorDipoleFringeScaling.hh"
78#include "BDSIntegratorDipoleQuadrupole.hh"
79#include "BDSIntegratorEuler.hh"
80#include "BDSIntegratorG4RK4MinStep.hh"
81#include "BDSIntegratorKickerThin.hh"
82#include "BDSIntegratorOctupole.hh"
83#include "BDSIntegratorQuadrupole.hh"
84#include "BDSIntegratorMultipoleThin.hh"
85#include "BDSIntegratorParallelTransport.hh"
86#include "BDSIntegratorSextupole.hh"
87#include "BDSIntegratorSolenoid.hh"
88#include "BDSIntegratorTeleporter.hh"
89#include "BDSIntegratorRMatrixThin.hh"
90#include "BDSIntegratorType.hh"
91#include "BDSMagnetOuterFactoryLHC.hh"
92#include "BDSMagnetStrength.hh"
93#include "BDSMagnetType.hh"
94#include "BDSModulator.hh"
95#include "BDSModulatorInfo.hh"
96#include "BDSModulatorLinearT.hh"
97#include "BDSModulatorSinT.hh"
98#include "BDSModulatorTopHatT.hh"
99#include "BDSModulatorType.hh"
100#include "BDSParser.hh"
101#include "BDSParticleDefinition.hh"
102#include "BDSUtilities.hh"
103#include "BDSWarning.hh"
105#include "parser/field.h"
106#include "parser/modulator.h"
109#include "G4EquationOfMotion.hh"
110#include "G4EqMagElectricField.hh"
111#include "G4MagIntegratorStepper.hh"
112#include "G4Mag_UsualEqRhs.hh"
113#include "G4RotationMatrix.hh"
114#include "G4String.hh"
115#include "G4ThreeVector.hh"
116#include "G4Transform3D.hh"
117#include "G4Version.hh"
120#include "G4CashKarpRKF45.hh"
121#include "G4ClassicalRK4.hh"
122#include "G4ConstRK4.hh"
123#include "G4ExactHelixStepper.hh"
124#include "G4ExplicitEuler.hh"
125#include "G4HelixExplicitEuler.hh"
126#include "G4HelixHeum.hh"
127#include "G4HelixImplicitEuler.hh"
128#include "G4HelixMixedStepper.hh"
129#include "G4HelixSimpleRunge.hh"
130#include "G4ImplicitEuler.hh"
131#include "G4NystromRK4.hh"
132#include "G4RKG3_Stepper.hh"
133#include "G4SimpleHeum.hh"
134#include "G4SimpleRunge.hh"
135#if G4VERSION_NUMBER > 1029
136#include "G4BogackiShampine23.hh"
137#include "G4BogackiShampine45.hh"
138#include "G4DoLoMcPriRK34.hh"
139#include "G4DormandPrince745.hh"
140#include "G4DormandPrinceRK56.hh"
141#include "G4TsitourasRK45.hh"
143#if G4VERSION_NUMBER > 1039
144#include "G4DormandPrinceRK78.hh"
145#include "G4RK547FEq1.hh"
146#include "G4RK547FEq2.hh"
147#include "G4RK547FEq3.hh"
150#include "CLHEP/Units/SystemOfUnits.h"
151#include "CLHEP/Vector/EulerAngles.h"
171 useOldMultipoleOuterFields(false)
173 G4double defaultRigidity = std::numeric_limits<double>::max();
185BDSFieldFactory::~BDSFieldFactory()
188 {
delete info.second;}
189 for (
auto& info : parserModulatorDefinitions)
190 {
delete info.second;}
194 G4double defaultBRho)
196 for (
const auto& definition : definitions)
198 if (definition.type.empty())
200 G4String msg =
"\"type\" not specified in field definition \"";
201 msg += definition.name +
"\", but required.";
207 G4ThreeVector offset = G4ThreeVector(definition.x*CLHEP::m,
208 definition.y*CLHEP::m,
209 definition.z*CLHEP::m);
212 if (definition.axisAngle)
214 G4ThreeVector axis = G4ThreeVector(definition.axisX,
217 rm = G4RotationMatrix(axis, definition.angle*CLHEP::rad);
225 CLHEP::HepEulerAngles ang = CLHEP::HepEulerAngles(definition.phi*CLHEP::rad,
226 definition.theta*CLHEP::rad,
227 definition.psi*CLHEP::rad);
228 rm = G4RotationMatrix(ang);
233 G4Transform3D transform = G4Transform3D(rm, offset);
236 G4String magFile =
"";
237 G4bool magFileSpecified = !definition.magneticFile.empty();
238 if (magFileSpecified)
240 std::pair<G4String, G4String> bf =
BDS::SplitOnColon(G4String(definition.magneticFile));
246 G4String eleFile =
"";
247 G4bool eleFileSpecified = !definition.electricFile.empty();
248 if (eleFileSpecified)
250 std::pair<G4String, G4String> ef =
BDS::SplitOnColon(G4String(definition.electricFile));
256 if (magFileSpecified)
259 if (!definition.magneticInterpolator.empty())
268 if (nDimFF != nDimInt)
270 G4String message =
"mismatch in number of dimensions between magnetic interpolator ";
271 message +=
"and field map format for field definition \"" + definition.name +
"\"";
281 if (eleFileSpecified)
284 if (!definition.electricInterpolator.empty())
293 if (nDimFF != nDimInt)
295 G4String message =
"mismatch in number of dimensions between electric interpolator ";
296 message +=
"and field map format for field definition \"" + definition.name +
"\"";
305 G4UserLimits* fieldLimit =
nullptr;
306 G4bool ignoreUpdateOfMaximumStepSize = definition.maximumStepLengthOverride > 0;
307 if (definition.maximumStepLength > 0 || ignoreUpdateOfMaximumStepSize)
311 G4double limit = G4double(definition.maximumStepLength) * CLHEP::m;
312 if (ignoreUpdateOfMaximumStepSize)
314 limit = definition.maximumStepLengthOverride * CLHEP::m;
315 G4cout << __METHOD_NAME__ <<
"maximumStepLengthOverride set to " << limit <<
" mm for field definition \""
316 << definition.name <<
"\" -> careful!" << G4endl;
326 if (!definition.fieldParameters.empty())
333 G4bool(definition.globalTransform),
342 G4double(definition.eScaling),
343 G4double(definition.bScaling),
344 G4double(definition.t*CLHEP::s),
345 G4bool(definition.autoScale),
347 info->SetScalingRadius(poleTipRadius);
349 if (ignoreUpdateOfMaximumStepSize)
350 {info->SetIgnoreUpdateOfMaximumStepSize(
true);}
352 if (!definition.magneticSubField.empty())
354 if (definition.magneticSubField == definition.name)
355 {
throw BDSException(__METHOD_NAME__,
"error in \"" + definition.name +
"\": magneticSubField cannot be the field itself");}
356 info->SetMagneticSubField(G4String(definition.magneticSubField));
358 if (!definition.electricSubField.empty())
360 if (definition.electricSubField == definition.name)
361 {
throw BDSException(__METHOD_NAME__,
"error in \"" + definition.name +
"\": electricSubField cannot be the field itself");}
362 info->SetElectricSubField(G4String(definition.electricSubField));
364 if (!definition.magneticReflection.empty())
366 G4String magneticReflection = G4String(definition.magneticReflection);
368 info->SetMagneticArrayReflectionType(mar);
370 if (!definition.electricReflection.empty())
372 G4String electricReflection = G4String(definition.electricReflection);
374 info->SetElectricArrayReflectionType(ear);
377 info->SetNameOfParserDefinition(G4String(definition.name));
380 G4cout <<
"Definition: \"" << definition.name <<
"\"" << G4endl;
381 G4cout << *info << G4endl;
389 for (
const auto& definition : definitions)
391 if (definition.type.empty())
393 G4String msg =
"\"type\" not specified in modulator definition \"";
394 msg += definition.name +
"\", but required.";
399 G4double frequency = definition.frequency * CLHEP::hertz;
400 G4double phase = definition.phase * CLHEP::rad;
404 {
throw BDSException(__METHOD_NAME__,
"definition: " + definition.name +
" has both tOffset and phase specified - only one can be used.");}
405 phase = definition.tOffset*CLHEP::s * frequency * CLHEP::twopi;
413 definition.tOffset * CLHEP::s,
414 definition.amplitudeScale,
415 definition.amplitudeOffset,
416 definition.T0 * CLHEP::s,
417 definition.T1 * CLHEP::s);
418 info->nameOfParserDefinition = definition.name;
419 parserModulatorDefinitions[G4String(definition.name)] = info;
424 const G4String& parameterNameForError)
const
428 {result = std::stod(value);}
429 catch (std::exception& e)
431 G4String msg(e.what());
432 G4String baseMsg =
"Unable to interpret value (\"" + value +
"\" of parameter \"";
433 baseMsg += parameterNameForError +
"\" as a number: ";
440 const G4String& fieldParameters,
441 G4double& poleTipRadius)
const
447 for (
const auto& keyValue : map)
454 else if (keyValue.first ==
"poletipradius")
458 G4String msg =
"Invalid key \"" + keyValue.first +
"\" for field parameters. ";
459 msg +=
"Acceptable parameters are: \n";
461 for (G4int i = 0; i < (G4int)allKeys.size(); i++)
463 msg += allKeys[i] +
", ";
464 if ((i % 10 == 0) && (i > 0))
482 G4cerr << __METHOD_NAME__ <<
"\"" << name <<
"\" is not a valid field specifier" << G4endl;
483 G4cout <<
"Defined field specifiers are:" << G4endl;
485 {G4cout <<
"\"" << it.first <<
"\"" << G4endl;}
486 throw BDSException(__METHOD_NAME__,
"invalid field name");
488 return result->second;
493 if (modulatorName.empty())
496 auto search = parserModulatorDefinitions.find(modulatorName);
497 if (search == parserModulatorDefinitions.end())
499 G4cerr << __METHOD_NAME__ <<
"\"" << modulatorName <<
"\" is not a valid modulator definition name" << G4endl;
500 G4cout <<
"Defined modulator definitions are:" << G4endl;
501 for (
const auto& it : parserModulatorDefinitions)
502 {G4cout <<
"\"" << it.first <<
"\"" << G4endl;}
503 throw BDSException(__METHOD_NAME__,
"invalid modulator name");
506 {
return search->second;}
511 const G4String& scalingKey)
517 if (info.
FieldType() == BDSFieldType::none)
525 case BDSFieldClassType::magnetic:
526 {field =
CreateFieldMag(info, scalingStrength, scalingKey);
break;}
527 case BDSFieldClassType::electromagnetic:
529 case BDSFieldClassType::electric:
531 case BDSFieldClassType::irregular:
548 switch (numberOfDimensions)
551 {result = BDSInterpolatorType::cubic1d;
break;}
553 {result = BDSInterpolatorType::cubic2d;
break;}
555 {result = BDSInterpolatorType::cubic3d;
break;}
557 {result = BDSInterpolatorType::cubic4d;
break;}
559 {
throw BDSException(__METHOD_NAME__,
"unsupported number of dimensions " + std::to_string(numberOfDimensions));}
566 const G4String& scalingKey)
587 return completeField;
592 const G4String& scalingKey)
596 G4double brho = info.
BRho();
601 case BDSFieldType::bmap1d:
602 case BDSFieldType::bmap2d:
603 case BDSFieldType::bmap3d:
604 case BDSFieldType::bmap4d:
605 case BDSFieldType::mokka:
615 case BDSFieldType::bfieldzero:
617 case BDSFieldType::solenoid:
618 case BDSFieldType::dipole:
619 case BDSFieldType::dipole3d:
621 case BDSFieldType::solenoidblock:
623 case BDSFieldType::solenoidloop:
625 case BDSFieldType::solenoidsheet:
627 case BDSFieldType::quadrupole:
629 case BDSFieldType::undulator:
631 case BDSFieldType::dipolequadrupole:
633 case BDSFieldType::sextupole:
635 case BDSFieldType::octupole:
637 case BDSFieldType::decapole:
639 case BDSFieldType::multipole:
641 case BDSFieldType::muonspoiler:
643 case BDSFieldType::skewquadrupole:
645 case BDSFieldType::skewsextupole:
647 case BDSFieldType::skewoctupole:
649 case BDSFieldType::skewdecapole:
651 case BDSFieldType::multipoleouterdipole:
654 G4bool positiveField = (*strength)[
"field"] < 0;
655 if (useOldMultipoleOuterFields)
662 case BDSFieldType::multipoleouterquadrupole:
665 G4bool positiveField = (*strength)[
"k1"] > 0;
666 if (useOldMultipoleOuterFields)
673 case BDSFieldType::multipoleoutersextupole:
676 G4bool positiveField = (*strength)[
"k2"] > 0;
677 if (useOldMultipoleOuterFields)
684 case BDSFieldType::multipoleouteroctupole:
687 G4bool positiveField = (*strength)[
"k3"] > 0;
688 if (useOldMultipoleOuterFields)
695 case BDSFieldType::multipoleouterdecapole:
698 G4bool positiveField = (*strength)[
"k4"] > 0;
699 if (useOldMultipoleOuterFields)
706 case BDSFieldType::skewmultipoleouterquadrupole:
709 G4bool positiveField = (*strength)[
"k1"] > 0;
711 if (useOldMultipoleOuterFields)
719 case BDSFieldType::skewmultipoleoutersextupole:
722 G4bool positiveField = (*strength)[
"k2"] > 0;
724 if (useOldMultipoleOuterFields)
732 case BDSFieldType::skewmultipoleouteroctupole:
735 G4bool positiveField = (*strength)[
"k3"] > 0;
737 if (useOldMultipoleOuterFields)
745 case BDSFieldType::skewmultipoleouterdecapole:
748 G4bool positiveField = (*strength)[
"k4"] > 0;
750 if (useOldMultipoleOuterFields)
758 case BDSFieldType::multipoleouterdipole3d:
760 if (useOldMultipoleOuterFields)
766 case BDSFieldType::multipoleouterdipolelhc:
769 G4bool positiveField = (*strength)[
"field"] < 0;
770 G4bool positiveField2 = (*strength)[
"angle"] > 0;
772 if (useOldMultipoleOuterFields)
785 case BDSFieldType::multipoleouterquadrupolelhc:
788 G4bool positiveField = (*strength)[
"k1"] > 0;
790 if (useOldMultipoleOuterFields)
803 case BDSFieldType::multipoleoutersextupolelhc:
806 G4bool positiveField = (*strength)[
"k2"] > 0;
808 if (useOldMultipoleOuterFields)
821 case BDSFieldType::paralleltransporter:
839 {BDS::Warning(__METHOD_NAME__,
"using a time varying modulation on a time varying field for field \"" + info.
NameOfParserDefinition() +
"\"");}
844 <<
"\" so will not reduce maximum step size for modulator\n";
858 {
throw BDSException(__METHOD_NAME__,
"subfield specified for non-field map type field - not supported");}
864 {
throw BDSException(__METHOD_NAME__,
"subfield type is not a field map type field - not supported");}
868 delete subFieldRecipe;
876 G4double brho = info.
BRho();
880 case BDSFieldType::rfpillbox:
882 case BDSFieldType::ebmap1d:
883 case BDSFieldType::ebmap2d:
884 case BDSFieldType::ebmap3d:
885 case BDSFieldType::ebmap4d:
893 case BDSFieldType::ebfieldzero:
895 case BDSFieldType::gaborlens:
897 case BDSFieldType::muoncooler:
913 {BDS::Warning(__METHOD_NAME__,
"using a time varying modulation on a time varying field for field \"" + info.
NameOfParserDefinition() +
"\"");}
930 G4EqMagElectricField* eqOfM =
new G4EqMagElectricField(resultantField);
936 return completeField;
953 G4EqMagElectricField* eqOfM =
new G4EqMagElectricField(resultantField);
959 return completeField;
967 case BDSFieldType::rfconstantinx:
968 case BDSFieldType::rfconstantiny:
969 case BDSFieldType::rfconstantinz:
971 case BDSFieldType::emap1d:
972 case BDSFieldType::emap2d:
973 case BDSFieldType::emap3d:
974 case BDSFieldType::emap4d:
982 case BDSFieldType::efieldzero:
998 {BDS::Warning(__METHOD_NAME__,
"using a time varying modulation on a time varying field for field \"" + info.
NameOfParserDefinition() +
"\"");}
1011 {
throw BDSException(__METHOD_NAME__,
"subfield specified for non-field map type field - not supported");}
1017 {
throw BDSException(__METHOD_NAME__,
"subfield type is not a field map type field - not supported");}
1021 delete subFieldRecipe;
1033 case BDSFieldType::teleporter:
1035 case BDSFieldType::rmatrix:
1037 case BDSFieldType::cavityfringe:
1039 case BDSFieldType::paralleltransporter:
1051 const G4double minimumRadiusOfCurvature = 10*CLHEP::cm;
1052 G4double brho = info.
BRho();
1053 G4MagIntegratorStepper* integrator =
nullptr;
1057 case BDSIntegratorType::solenoid:
1059 case BDSIntegratorType::dipolerodrigues:
1061 case BDSIntegratorType::dipolerodrigues2:
1063 case BDSIntegratorType::dipolematrix:
1065 case BDSIntegratorType::quadrupole:
1067 case BDSIntegratorType::sextupole:
1069 case BDSIntegratorType::octupole:
1071 case BDSIntegratorType::decapole:
1073 case BDSIntegratorType::multipolethin:
1075 case BDSIntegratorType::dipolefringe:
1077 case BDSIntegratorType::dipolefringescaling:
1079 case BDSIntegratorType::euler:
1081 case BDSIntegratorType::kickerthin:
1083 case BDSIntegratorType::g4rk4minimumstep:
1085 case BDSIntegratorType::rmatrixthin:
1087 case BDSIntegratorType::cavityfringe:
1089 case BDSIntegratorType::g4constrk4:
1090 integrator =
new G4ConstRK4(eqOfM);
break;
1091 case BDSIntegratorType::g4exacthelixstepper:
1092 integrator =
new G4ExactHelixStepper(eqOfM);
break;
1093 case BDSIntegratorType::g4helixexpliciteuler:
1094 integrator =
new G4HelixExplicitEuler(eqOfM);
break;
1095 case BDSIntegratorType::g4helixheum:
1096 integrator =
new G4HelixHeum(eqOfM);
break;
1097 case BDSIntegratorType::g4heliximpliciteuler:
1098 integrator =
new G4HelixImplicitEuler(eqOfM);
break;
1099 case BDSIntegratorType::g4helixmixedstepper:
1100 integrator =
new G4HelixMixedStepper(eqOfM);
break;
1101 case BDSIntegratorType::g4helixsimplerunge:
1102 integrator =
new G4HelixSimpleRunge(eqOfM);
break;
1103 case BDSIntegratorType::g4nystromrk4:
1104 integrator =
new G4NystromRK4(eqOfM);
break;
1105 case BDSIntegratorType::g4rkg3stepper:
1106 integrator =
new G4RKG3_Stepper(eqOfM);
break;
1107 case BDSIntegratorType::g4cashkarprkf45:
1108 case BDSIntegratorType::g4classicalrk4:
1109 case BDSIntegratorType::g4expliciteuler:
1110 case BDSIntegratorType::g4impliciteuler:
1111 case BDSIntegratorType::g4simpleheum:
1112 case BDSIntegratorType::g4simplerunge:
1113#if G4VERSION_NUMBER > 1029
1114 case BDSIntegratorType::g4bogackishampine23:
1115 case BDSIntegratorType::g4bogackishampine45:
1116 case BDSIntegratorType::g4dolomcprirk34:
1117 case BDSIntegratorType::g4dormandprince745:
1118 case BDSIntegratorType::g4dormandprincerk56:
1119 case BDSIntegratorType::g4tsitourasrk45:
1121#if G4VERSION_NUMBER > 1039
1122 case BDSIntegratorType::g4dormandprincerk78:
1123 case BDSIntegratorType::g4rk547feq1:
1124 case BDSIntegratorType::g4rk547feq2:
1125 case BDSIntegratorType::g4rk547feq3:
1136 G4EquationOfMotion* eqOfM)
1138 G4MagIntegratorStepper* integrator =
nullptr;
1142 case BDSIntegratorType::g4cashkarprkf45:
1143 integrator =
new G4CashKarpRKF45(eqOfM, 8);
break;
1144 case BDSIntegratorType::g4classicalrk4:
1145 integrator =
new G4ClassicalRK4(eqOfM, 8);
break;
1146 case BDSIntegratorType::g4expliciteuler:
1147 integrator =
new G4ExplicitEuler(eqOfM, 8);
break;
1148 case BDSIntegratorType::g4impliciteuler:
1149 integrator =
new G4ImplicitEuler(eqOfM, 8);
break;
1150 case BDSIntegratorType::g4simpleheum:
1151 integrator =
new G4SimpleHeum(eqOfM, 8);
break;
1152 case BDSIntegratorType::g4simplerunge:
1153 integrator =
new G4SimpleRunge(eqOfM, 8);
break;
1154#if G4VERSION_NUMBER > 1029
1155 case BDSIntegratorType::g4bogackishampine23:
1156 {integrator =
new G4BogackiShampine45(eqOfM, 8);
break;}
1157 case BDSIntegratorType::g4bogackishampine45:
1158 {integrator =
new G4BogackiShampine45(eqOfM, 8);
break;}
1159 case BDSIntegratorType::g4dolomcprirk34:
1160 {integrator =
new G4DoLoMcPriRK34(eqOfM, 8);
break;}
1161 case BDSIntegratorType::g4dormandprince745:
1162 {integrator =
new G4DormandPrince745(eqOfM, 8);
break;}
1163 case BDSIntegratorType::g4dormandprincerk56:
1164 {integrator =
new G4DormandPrinceRK56(eqOfM, 8);
break;}
1165 case BDSIntegratorType::g4tsitourasrk45:
1166 {integrator =
new G4TsitourasRK45(eqOfM, 8);
break;}
1168#if G4VERSION_NUMBER > 1039
1169 case BDSIntegratorType::g4dormandprincerk78:
1170 {integrator =
new G4DormandPrinceRK78(eqOfM, 8);
break;}
1171 case BDSIntegratorType::g4rk547feq1:
1172 {integrator =
new G4RK547FEq1(eqOfM, 8);
break;}
1173 case BDSIntegratorType::g4rk547feq2:
1174 {integrator =
new G4RK547FEq2(eqOfM, 8);
break;}
1175 case BDSIntegratorType::g4rk547feq3:
1176 {integrator =
new G4RK547FEq3(eqOfM, 8);
break;}
1178 case BDSIntegratorType::solenoid:
1179 case BDSIntegratorType::dipolerodrigues:
1180 case BDSIntegratorType::quadrupole:
1181 case BDSIntegratorType::sextupole:
1182 case BDSIntegratorType::octupole:
1183 case BDSIntegratorType::decapole:
1184 case BDSIntegratorType::dipolefringe:
1185 case BDSIntegratorType::g4constrk4:
1186 case BDSIntegratorType::g4exacthelixstepper:
1187 case BDSIntegratorType::g4helixexpliciteuler:
1188 case BDSIntegratorType::g4helixheum:
1189 case BDSIntegratorType::g4heliximpliciteuler:
1190 case BDSIntegratorType::g4helixmixedstepper:
1191 case BDSIntegratorType::g4helixsimplerunge:
1192 case BDSIntegratorType::g4nystromrk4:
1193 case BDSIntegratorType::g4rkg3stepper:
1195 G4cerr <<
"Error: integrator \"" << info.
IntegratorType() <<
"\" is not suitable for an EM field." << G4endl;
1196 G4cout <<
"Suitable integrators are:" << G4endl;
1197 std::vector<BDSIntegratorType> types = {
1198 BDSIntegratorType::g4cashkarprkf45,
1199 BDSIntegratorType::g4classicalrk4,
1200 BDSIntegratorType::g4expliciteuler,
1201 BDSIntegratorType::g4impliciteuler,
1202 BDSIntegratorType::g4simpleheum,
1203 BDSIntegratorType::g4simplerunge
1204#if G4VERSION_NUMBER > 1029
1206 BDSIntegratorType::g4bogackishampine23,
1207 BDSIntegratorType::g4bogackishampine45,
1208 BDSIntegratorType::g4dolomcprirk34,
1209 BDSIntegratorType::g4dormandprince745,
1210 BDSIntegratorType::g4dormandprincerk56,
1211 BDSIntegratorType::g4tsitourasrk45
1213#if G4VERSION_NUMBER > 1039
1215 BDSIntegratorType::g4dormandprincerk78,
1216 BDSIntegratorType::g4rk547feq1,
1217 BDSIntegratorType::g4rk547feq2,
1218 BDSIntegratorType::g4rk547feq3
1221 for (
auto type : types)
1222 {G4cout << type << G4endl;}
1223 throw BDSException(__METHOD_NAME__,
"invalid integrator type");
1232 G4EquationOfMotion* eqOfM)
1240 G4Mag_EqRhs* bEqOfMotion =
new G4Mag_UsualEqRhs(bGlobalField);
1242 G4MagIntegratorStepper* integrator;
1246 if (!mapfile.empty())
1257 bEqOfMotion, integrator);
1258 return completeField;
1264 G4Mag_EqRhs* bEqOfMotion =
new G4Mag_UsualEqRhs(bGlobalField);
1267 bEqOfMotion, integrator);
1268 return completeField;
1277 bEqOfMotion, integrator);
1278 return completeField;
1284 G4Mag_EqRhs* bEqOfMotion =
new G4Mag_UsualEqRhs(bGlobalField);
1287 bEqOfMotion, integrator);
1288 return completeField;
1293 G4double result = 1.0;
1295 {result = (*st)[
"scalingOuter"];}
1300 G4double brho)
const
1313 if (!modulatorRecipe)
1320 case BDSModulatorType::lineart:
1323 modulatorRecipe->
T1,
1324 modulatorRecipe->
scale,
1328 case BDSModulatorType::sint:
1331 modulatorRecipe->
phase,
1332 info.SynchronousT(),
1334 modulatorRecipe->
scale);
1337 case BDSModulatorType::singlobalt:
1340 modulatorRecipe->
phase,
1343 modulatorRecipe->
scale);
1346 case BDSModulatorType::tophatt:
1349 modulatorRecipe->
T1,
1350 modulatorRecipe->
scale);
1353 case BDSModulatorType::none:
1360 G4String extraMsg =
"\nProblem in field definition for component \"" + info.
NameOfParserDefinition() +
"\"";
1361 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.