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 "BDSFieldEMRFCavity.hh"
38#include "BDSFieldEMZero.hh"
39#include "BDSFieldFactory.hh"
40#include "BDSFieldInfo.hh"
41#include "BDSFieldLoader.hh"
42#include "BDSFieldMag.hh"
43#include "BDSFieldMagDecapole.hh"
44#include "BDSFieldMagDipole.hh"
45#include "BDSFieldMagDipoleOuter.hh"
46#include "BDSFieldMagDipoleOuterOld.hh"
47#include "BDSFieldMagDipoleQuadrupole.hh"
48#include "BDSFieldMagGlobal.hh"
49#include "BDSFieldMagGlobalPlacement.hh"
50#include "BDSFieldMagInterpolated.hh"
51#include "BDSFieldMagInterpolated2Layer.hh"
52#include "BDSFieldMagMultipole.hh"
53#include "BDSFieldMagMultipoleOuter.hh"
54#include "BDSFieldMagMultipoleOuterDual.hh"
55#include "BDSFieldMagMultipoleOuterDualOld.hh"
56#include "BDSFieldMagMultipoleOuterOld.hh"
57#include "BDSFieldMagMuonSpoiler.hh"
58#include "BDSFieldMagOctupole.hh"
59#include "BDSFieldMagQuadrupole.hh"
60#include "BDSFieldMagSextupole.hh"
61#include "BDSFieldMagSolenoidSheet.hh"
62#include "BDSFieldMagSkewOwn.hh"
63#include "BDSFieldMagUndulator.hh"
64#include "BDSFieldMagZero.hh"
65#include "BDSFieldObjects.hh"
66#include "BDSFieldType.hh"
67#include "BDSGlobalConstants.hh"
68#include "BDSIntegratorCavityFringe.hh"
69#include "BDSIntegratorDecapole.hh"
70#include "BDSIntegratorDipoleRodrigues.hh"
71#include "BDSIntegratorDipoleRodrigues2.hh"
72#include "BDSIntegratorDipoleFringe.hh"
73#include "BDSIntegratorDipoleFringeScaling.hh"
74#include "BDSIntegratorDipoleQuadrupole.hh"
75#include "BDSIntegratorEuler.hh"
76#include "BDSIntegratorG4RK4MinStep.hh"
77#include "BDSIntegratorKickerThin.hh"
78#include "BDSIntegratorOctupole.hh"
79#include "BDSIntegratorQuadrupole.hh"
80#include "BDSIntegratorMultipoleThin.hh"
81#include "BDSIntegratorParallelTransport.hh"
82#include "BDSIntegratorSextupole.hh"
83#include "BDSIntegratorSolenoid.hh"
84#include "BDSIntegratorTeleporter.hh"
85#include "BDSIntegratorRMatrixThin.hh"
86#include "BDSIntegratorType.hh"
87#include "BDSMagnetOuterFactoryLHC.hh"
88#include "BDSMagnetStrength.hh"
89#include "BDSMagnetType.hh"
90#include "BDSModulator.hh"
91#include "BDSModulatorInfo.hh"
92#include "BDSModulatorSinT.hh"
93#include "BDSModulatorTopHatT.hh"
94#include "BDSModulatorType.hh"
95#include "BDSParser.hh"
96#include "BDSParticleDefinition.hh"
97#include "BDSUtilities.hh"
98#include "BDSWarning.hh"
100#include "parser/field.h"
101#include "parser/modulator.h"
104#include "G4EquationOfMotion.hh"
105#include "G4EqMagElectricField.hh"
106#include "G4MagIntegratorStepper.hh"
107#include "G4Mag_UsualEqRhs.hh"
108#include "G4RotationMatrix.hh"
109#include "G4String.hh"
110#include "G4ThreeVector.hh"
111#include "G4Transform3D.hh"
112#include "G4Version.hh"
115#include "G4CashKarpRKF45.hh"
116#include "G4ClassicalRK4.hh"
117#include "G4ConstRK4.hh"
118#include "G4ExactHelixStepper.hh"
119#include "G4ExplicitEuler.hh"
120#include "G4HelixExplicitEuler.hh"
121#include "G4HelixHeum.hh"
122#include "G4HelixImplicitEuler.hh"
123#include "G4HelixMixedStepper.hh"
124#include "G4HelixSimpleRunge.hh"
125#include "G4ImplicitEuler.hh"
126#include "G4NystromRK4.hh"
127#include "G4RKG3_Stepper.hh"
128#include "G4SimpleHeum.hh"
129#include "G4SimpleRunge.hh"
130#if G4VERSION_NUMBER > 1029
131#include "G4BogackiShampine23.hh"
132#include "G4BogackiShampine45.hh"
133#include "G4DoLoMcPriRK34.hh"
134#include "G4DormandPrince745.hh"
135#include "G4DormandPrinceRK56.hh"
136#include "G4TsitourasRK45.hh"
138#if G4VERSION_NUMBER > 1039
139#include "G4DormandPrinceRK78.hh"
140#include "G4RK547FEq1.hh"
141#include "G4RK547FEq2.hh"
142#include "G4RK547FEq3.hh"
145#include "CLHEP/Units/SystemOfUnits.h"
146#include "CLHEP/Vector/EulerAngles.h"
166 useOldMultipoleOuterFields(false)
168 G4double defaultRigidity = std::numeric_limits<double>::max();
180BDSFieldFactory::~BDSFieldFactory()
183 {
delete info.second;}
184 for (
auto& info : parserModulatorDefinitions)
185 {
delete info.second;}
189 G4double defaultBRho)
191 for (
const auto& definition : definitions)
193 if (definition.type.empty())
195 G4String msg =
"\"type\" not specified in field definition \"";
196 msg += definition.name +
"\", but required.";
202 G4ThreeVector offset = G4ThreeVector(definition.x*CLHEP::m,
203 definition.y*CLHEP::m,
204 definition.z*CLHEP::m);
207 if (definition.axisAngle)
209 G4ThreeVector axis = G4ThreeVector(definition.axisX,
212 rm = G4RotationMatrix(axis, definition.angle*CLHEP::rad);
220 CLHEP::HepEulerAngles ang = CLHEP::HepEulerAngles(definition.phi*CLHEP::rad,
221 definition.theta*CLHEP::rad,
222 definition.psi*CLHEP::rad);
223 rm = G4RotationMatrix(ang);
228 G4Transform3D transform = G4Transform3D(rm, offset);
231 G4String magFile =
"";
232 G4bool magFileSpecified = !definition.magneticFile.empty();
233 if (magFileSpecified)
235 std::pair<G4String, G4String> bf =
BDS::SplitOnColon(G4String(definition.magneticFile));
241 G4String eleFile =
"";
242 G4bool eleFileSpecified = !definition.electricFile.empty();
243 if (eleFileSpecified)
245 std::pair<G4String, G4String> ef =
BDS::SplitOnColon(G4String(definition.electricFile));
251 if (magFileSpecified)
254 if (!definition.magneticInterpolator.empty())
263 if (nDimFF != nDimInt)
265 G4String message =
"mismatch in number of dimensions between magnetic interpolator ";
266 message +=
"and field map format for field definition \"" + definition.name +
"\"";
276 if (eleFileSpecified)
279 if (!definition.electricInterpolator.empty())
288 if (nDimFF != nDimInt)
290 G4String message =
"mismatch in number of dimensions between electric interpolator ";
291 message +=
"and field map format for field definition \"" + definition.name +
"\"";
300 G4UserLimits* fieldLimit =
nullptr;
301 if (definition.maximumStepLength > 0)
305 G4double limit = G4double(definition.maximumStepLength) * CLHEP::m;
314 if (!definition.fieldParameters.empty())
321 G4bool(definition.globalTransform),
330 G4double(definition.eScaling),
331 G4double(definition.bScaling),
332 G4double(definition.t*CLHEP::s),
333 G4bool(definition.autoScale),
335 info->SetScalingRadius(poleTipRadius);
338 if (!definition.magneticSubField.empty())
340 if (definition.magneticSubField == definition.name)
341 {
throw BDSException(__METHOD_NAME__,
"error in \"" + definition.name +
"\": magneticSubField cannot be the field itself");}
342 info->SetMagneticSubField(G4String(definition.magneticSubField));
344 if (!definition.electricSubField.empty())
346 if (definition.electricSubField == definition.name)
347 {
throw BDSException(__METHOD_NAME__,
"error in \"" + definition.name +
"\": electricSubField cannot be the field itself");}
348 info->SetElectricSubField(G4String(definition.electricSubField));
350 if (!definition.magneticReflection.empty())
352 G4String magneticReflection = G4String(definition.magneticReflection);
354 info->SetMagneticArrayReflectionType(mar);
356 if (!definition.electricReflection.empty())
358 G4String electricReflection = G4String(definition.electricReflection);
360 info->SetElectricArrayReflectionType(ear);
363 info->SetNameOfParserDefinition(G4String(definition.name));
366 G4cout <<
"Definition: \"" << definition.name <<
"\"" << G4endl;
367 G4cout << *info << G4endl;
375 for (
const auto& definition : definitions)
377 if (definition.type.empty())
379 G4String msg =
"\"type\" not specified in modulator definition \"";
380 msg += definition.name +
"\", but required.";
388 definition.frequency * CLHEP::hertz,
389 definition.phase * CLHEP::rad,
390 definition.tOffset * CLHEP::s,
391 definition.amplitudeScale,
392 definition.amplitudeOffset,
395 info->nameOfParserDefinition = definition.name;
396 parserModulatorDefinitions[G4String(definition.name)] = info;
400G4double BDSFieldFactory::CalculateGlobalPhase(G4double oscillatorFrequency,
405 G4double period = 1. / oscillatorFrequency;
406 G4double nPeriods = tOffsetIn / period;
408 G4double integerPart = 0;
409 G4double fractionalPart = std::modf(nPeriods, &integerPart);
410 G4double phaseOffset = fractionalPart * CLHEP::twopi;
414G4double BDSFieldFactory::CalculateGlobalPhase(
const BDSModulatorInfo& modulatorInfo,
417 G4double synchronousT0 = 0.0;
420 {synchronousT0 = (*magnetStrength)[
"synchronousT0"];}
424 G4double tOffset = 0;
426 {tOffset = modulatorInfo.
tOffset;}
428 {tOffset = synchronousT0;}
430 G4double globalPhase = CalculateGlobalPhase(modulatorInfo.
frequency, tOffset);
435 const G4String& parameterNameForError)
const
439 {result = std::stod(value);}
440 catch (std::exception& e)
442 G4String msg(e.what());
443 G4String baseMsg =
"Unable to interpret value (\"" + value +
"\" of parameter \"";
444 baseMsg += parameterNameForError +
"\" as a number: ";
451 const G4String& fieldParameters,
452 G4double& poleTipRadius)
const
458 for (
const auto& keyValue : map)
465 else if (keyValue.first ==
"poletipradius")
469 G4String msg =
"Invalid key \"" + keyValue.first +
"\" for field parameters. ";
470 msg +=
"Acceptable parameters are: \n";
472 for (G4int i = 0; i < (G4int)allKeys.size(); i++)
474 msg += allKeys[i] +
", ";
475 if ((i % 10 == 0) && (i > 0))
493 G4cerr << __METHOD_NAME__ <<
"\"" << name <<
"\" is not a valid field specifier" << G4endl;
494 G4cout <<
"Defined field specifiers are:" << G4endl;
496 {G4cout <<
"\"" << it.first <<
"\"" << G4endl;}
497 throw BDSException(__METHOD_NAME__,
"invalid field name");
499 return result->second;
504 if (modulatorName.empty())
507 auto search = parserModulatorDefinitions.find(modulatorName);
508 if (search == parserModulatorDefinitions.end())
510 G4cerr << __METHOD_NAME__ <<
"\"" << modulatorName <<
"\" is not a valid modulator definition name" << G4endl;
511 G4cout <<
"Defined modulator definitions are:" << G4endl;
512 for (
const auto& it : parserModulatorDefinitions)
513 {G4cout <<
"\"" << it.first <<
"\"" << G4endl;}
514 throw BDSException(__METHOD_NAME__,
"invalid modulator name");
517 {
return search->second;}
522 const G4String& scalingKey)
528 if (info.
FieldType() == BDSFieldType::none)
536 case BDSFieldClassType::magnetic:
537 {field =
CreateFieldMag(info, scalingStrength, scalingKey);
break;}
538 case BDSFieldClassType::electromagnetic:
540 case BDSFieldClassType::electric:
542 case BDSFieldClassType::irregular:
559 switch (numberOfDimensions)
562 {result = BDSInterpolatorType::cubic1d;
break;}
564 {result = BDSInterpolatorType::cubic2d;
break;}
566 {result = BDSInterpolatorType::cubic3d;
break;}
568 {result = BDSInterpolatorType::cubic4d;
break;}
570 {
throw BDSException(__METHOD_NAME__,
"unsupported number of dimensions " + std::to_string(numberOfDimensions));}
577 const G4String& scalingKey)
598 return completeField;
603 const G4String& scalingKey)
607 G4double brho = info.
BRho();
612 case BDSFieldType::bmap1d:
613 case BDSFieldType::bmap2d:
614 case BDSFieldType::bmap3d:
615 case BDSFieldType::bmap4d:
616 case BDSFieldType::mokka:
626 case BDSFieldType::bfieldzero:
628 case BDSFieldType::solenoid:
629 case BDSFieldType::dipole:
630 case BDSFieldType::dipole3d:
632 case BDSFieldType::solenoidsheet:
634 case BDSFieldType::quadrupole:
636 case BDSFieldType::undulator:
638 case BDSFieldType::dipolequadrupole:
640 case BDSFieldType::sextupole:
642 case BDSFieldType::octupole:
644 case BDSFieldType::decapole:
646 case BDSFieldType::multipole:
648 case BDSFieldType::muonspoiler:
650 case BDSFieldType::skewquadrupole:
652 case BDSFieldType::skewsextupole:
654 case BDSFieldType::skewoctupole:
656 case BDSFieldType::skewdecapole:
658 case BDSFieldType::multipoleouterdipole:
661 G4bool positiveField = (*strength)[
"field"] < 0;
662 if (useOldMultipoleOuterFields)
669 case BDSFieldType::multipoleouterquadrupole:
672 G4bool positiveField = (*strength)[
"k1"] > 0;
673 if (useOldMultipoleOuterFields)
680 case BDSFieldType::multipoleoutersextupole:
683 G4bool positiveField = (*strength)[
"k2"] > 0;
684 if (useOldMultipoleOuterFields)
691 case BDSFieldType::multipoleouteroctupole:
694 G4bool positiveField = (*strength)[
"k3"] > 0;
695 if (useOldMultipoleOuterFields)
702 case BDSFieldType::multipoleouterdecapole:
705 G4bool positiveField = (*strength)[
"k4"] > 0;
706 if (useOldMultipoleOuterFields)
713 case BDSFieldType::skewmultipoleouterquadrupole:
716 G4bool positiveField = (*strength)[
"k1"] > 0;
718 if (useOldMultipoleOuterFields)
726 case BDSFieldType::skewmultipoleoutersextupole:
729 G4bool positiveField = (*strength)[
"k2"] > 0;
731 if (useOldMultipoleOuterFields)
739 case BDSFieldType::skewmultipoleouteroctupole:
742 G4bool positiveField = (*strength)[
"k3"] > 0;
744 if (useOldMultipoleOuterFields)
752 case BDSFieldType::skewmultipoleouterdecapole:
755 G4bool positiveField = (*strength)[
"k4"] > 0;
757 if (useOldMultipoleOuterFields)
765 case BDSFieldType::multipoleouterdipole3d:
767 if (useOldMultipoleOuterFields)
773 case BDSFieldType::multipoleouterdipolelhc:
776 G4bool positiveField = (*strength)[
"field"] < 0;
777 G4bool positiveField2 = (*strength)[
"angle"] > 0;
779 if (useOldMultipoleOuterFields)
792 case BDSFieldType::multipoleouterquadrupolelhc:
795 G4bool positiveField = (*strength)[
"k1"] > 0;
797 if (useOldMultipoleOuterFields)
810 case BDSFieldType::multipoleoutersextupolelhc:
813 G4bool positiveField = (*strength)[
"k2"] > 0;
815 if (useOldMultipoleOuterFields)
828 case BDSFieldType::paralleltransporter:
846 {BDS::Warning(__METHOD_NAME__,
"using a time varying modulation on a time varying field for field \"" + info.
NameOfParserDefinition() +
"\"");}
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;
880 case BDSFieldType::rfpillbox:
882 case BDSFieldType::ebmap1d:
883 case BDSFieldType::ebmap2d:
884 case BDSFieldType::ebmap3d:
885 case BDSFieldType::ebmap4d:
893 case BDSFieldType::ebfieldzero:
909 {BDS::Warning(__METHOD_NAME__,
"using a time varying modulation on a time varying field for field \"" + info.
NameOfParserDefinition() +
"\"");}
926 G4EqMagElectricField* eqOfM =
new G4EqMagElectricField(resultantField);
932 return completeField;
949 G4EqMagElectricField* eqOfM =
new G4EqMagElectricField(resultantField);
955 return completeField;
963 case BDSFieldType::rfconstantinx:
964 case BDSFieldType::rfconstantiny:
965 case BDSFieldType::rfconstantinz:
967 case BDSFieldType::emap1d:
968 case BDSFieldType::emap2d:
969 case BDSFieldType::emap3d:
970 case BDSFieldType::emap4d:
978 case BDSFieldType::efieldzero:
994 {BDS::Warning(__METHOD_NAME__,
"using a time varying modulation on a time varying field for field \"" + info.
NameOfParserDefinition() +
"\"");}
1007 {
throw BDSException(__METHOD_NAME__,
"subfield specified for non-field map type field - not supported");}
1013 {
throw BDSException(__METHOD_NAME__,
"subfield type is not a field map type field - not supported");}
1017 delete subFieldRecipe;
1029 case BDSFieldType::teleporter:
1031 case BDSFieldType::rmatrix:
1033 case BDSFieldType::cavityfringe:
1035 case BDSFieldType::paralleltransporter:
1047 const G4double minimumRadiusOfCurvature = 10*CLHEP::cm;
1048 G4double brho = info.
BRho();
1049 G4MagIntegratorStepper* integrator =
nullptr;
1053 case BDSIntegratorType::solenoid:
1055 case BDSIntegratorType::dipolerodrigues:
1057 case BDSIntegratorType::dipolerodrigues2:
1059 case BDSIntegratorType::dipolematrix:
1061 case BDSIntegratorType::quadrupole:
1063 case BDSIntegratorType::sextupole:
1065 case BDSIntegratorType::octupole:
1067 case BDSIntegratorType::decapole:
1069 case BDSIntegratorType::multipolethin:
1071 case BDSIntegratorType::dipolefringe:
1073 case BDSIntegratorType::dipolefringescaling:
1075 case BDSIntegratorType::euler:
1077 case BDSIntegratorType::kickerthin:
1079 case BDSIntegratorType::g4rk4minimumstep:
1081 case BDSIntegratorType::rmatrixthin:
1083 case BDSIntegratorType::cavityfringe:
1085 case BDSIntegratorType::g4constrk4:
1086 integrator =
new G4ConstRK4(eqOfM);
break;
1087 case BDSIntegratorType::g4exacthelixstepper:
1088 integrator =
new G4ExactHelixStepper(eqOfM);
break;
1089 case BDSIntegratorType::g4helixexpliciteuler:
1090 integrator =
new G4HelixExplicitEuler(eqOfM);
break;
1091 case BDSIntegratorType::g4helixheum:
1092 integrator =
new G4HelixHeum(eqOfM);
break;
1093 case BDSIntegratorType::g4heliximpliciteuler:
1094 integrator =
new G4HelixImplicitEuler(eqOfM);
break;
1095 case BDSIntegratorType::g4helixmixedstepper:
1096 integrator =
new G4HelixMixedStepper(eqOfM);
break;
1097 case BDSIntegratorType::g4helixsimplerunge:
1098 integrator =
new G4HelixSimpleRunge(eqOfM);
break;
1099 case BDSIntegratorType::g4nystromrk4:
1100 integrator =
new G4NystromRK4(eqOfM);
break;
1101 case BDSIntegratorType::g4rkg3stepper:
1102 integrator =
new G4RKG3_Stepper(eqOfM);
break;
1103 case BDSIntegratorType::g4cashkarprkf45:
1104 case BDSIntegratorType::g4classicalrk4:
1105 case BDSIntegratorType::g4expliciteuler:
1106 case BDSIntegratorType::g4impliciteuler:
1107 case BDSIntegratorType::g4simpleheum:
1108 case BDSIntegratorType::g4simplerunge:
1109#if G4VERSION_NUMBER > 1029
1110 case BDSIntegratorType::g4bogackishampine23:
1111 case BDSIntegratorType::g4bogackishampine45:
1112 case BDSIntegratorType::g4dolomcprirk34:
1113 case BDSIntegratorType::g4dormandprince745:
1114 case BDSIntegratorType::g4dormandprincerk56:
1115 case BDSIntegratorType::g4tsitourasrk45:
1117#if G4VERSION_NUMBER > 1039
1118 case BDSIntegratorType::g4dormandprincerk78:
1119 case BDSIntegratorType::g4rk547feq1:
1120 case BDSIntegratorType::g4rk547feq2:
1121 case BDSIntegratorType::g4rk547feq3:
1132 G4EquationOfMotion* eqOfM)
1134 G4MagIntegratorStepper* integrator =
nullptr;
1138 case BDSIntegratorType::g4cashkarprkf45:
1139 integrator =
new G4CashKarpRKF45(eqOfM, 8);
break;
1140 case BDSIntegratorType::g4classicalrk4:
1141 integrator =
new G4ClassicalRK4(eqOfM, 8);
break;
1142 case BDSIntegratorType::g4expliciteuler:
1143 integrator =
new G4ExplicitEuler(eqOfM, 8);
break;
1144 case BDSIntegratorType::g4impliciteuler:
1145 integrator =
new G4ImplicitEuler(eqOfM, 8);
break;
1146 case BDSIntegratorType::g4simpleheum:
1147 integrator =
new G4SimpleHeum(eqOfM, 8);
break;
1148 case BDSIntegratorType::g4simplerunge:
1149 integrator =
new G4SimpleRunge(eqOfM, 8);
break;
1150#if G4VERSION_NUMBER > 1029
1151 case BDSIntegratorType::g4bogackishampine23:
1152 {integrator =
new G4BogackiShampine45(eqOfM, 8);
break;}
1153 case BDSIntegratorType::g4bogackishampine45:
1154 {integrator =
new G4BogackiShampine45(eqOfM, 8);
break;}
1155 case BDSIntegratorType::g4dolomcprirk34:
1156 {integrator =
new G4DoLoMcPriRK34(eqOfM, 8);
break;}
1157 case BDSIntegratorType::g4dormandprince745:
1158 {integrator =
new G4DormandPrince745(eqOfM, 8);
break;}
1159 case BDSIntegratorType::g4dormandprincerk56:
1160 {integrator =
new G4DormandPrinceRK56(eqOfM, 8);
break;}
1161 case BDSIntegratorType::g4tsitourasrk45:
1162 {integrator =
new G4TsitourasRK45(eqOfM, 8);
break;}
1164#if G4VERSION_NUMBER > 1039
1165 case BDSIntegratorType::g4dormandprincerk78:
1166 {integrator =
new G4DormandPrinceRK78(eqOfM, 8);
break;}
1167 case BDSIntegratorType::g4rk547feq1:
1168 {integrator =
new G4RK547FEq1(eqOfM, 8);
break;}
1169 case BDSIntegratorType::g4rk547feq2:
1170 {integrator =
new G4RK547FEq2(eqOfM, 8);
break;}
1171 case BDSIntegratorType::g4rk547feq3:
1172 {integrator =
new G4RK547FEq3(eqOfM, 8);
break;}
1174 case BDSIntegratorType::solenoid:
1175 case BDSIntegratorType::dipolerodrigues:
1176 case BDSIntegratorType::quadrupole:
1177 case BDSIntegratorType::sextupole:
1178 case BDSIntegratorType::octupole:
1179 case BDSIntegratorType::decapole:
1180 case BDSIntegratorType::dipolefringe:
1181 case BDSIntegratorType::g4constrk4:
1182 case BDSIntegratorType::g4exacthelixstepper:
1183 case BDSIntegratorType::g4helixexpliciteuler:
1184 case BDSIntegratorType::g4helixheum:
1185 case BDSIntegratorType::g4heliximpliciteuler:
1186 case BDSIntegratorType::g4helixmixedstepper:
1187 case BDSIntegratorType::g4helixsimplerunge:
1188 case BDSIntegratorType::g4nystromrk4:
1189 case BDSIntegratorType::g4rkg3stepper:
1191 G4cerr <<
"Error: integrator \"" << info.
IntegratorType() <<
"\" is not suitable for an EM field." << G4endl;
1192 G4cout <<
"Suitable integrators are:" << G4endl;
1193 std::vector<BDSIntegratorType> types = {
1194 BDSIntegratorType::g4cashkarprkf45,
1195 BDSIntegratorType::g4classicalrk4,
1196 BDSIntegratorType::g4expliciteuler,
1197 BDSIntegratorType::g4impliciteuler,
1198 BDSIntegratorType::g4simpleheum,
1199 BDSIntegratorType::g4simplerunge
1200#if G4VERSION_NUMBER > 1029
1202 BDSIntegratorType::g4bogackishampine23,
1203 BDSIntegratorType::g4bogackishampine45,
1204 BDSIntegratorType::g4dolomcprirk34,
1205 BDSIntegratorType::g4dormandprince745,
1206 BDSIntegratorType::g4dormandprincerk56,
1207 BDSIntegratorType::g4tsitourasrk45
1209#if G4VERSION_NUMBER > 1039
1211 BDSIntegratorType::g4dormandprincerk78,
1212 BDSIntegratorType::g4rk547feq1,
1213 BDSIntegratorType::g4rk547feq2,
1214 BDSIntegratorType::g4rk547feq3
1217 for (
auto type : types)
1218 {G4cout << type << G4endl;}
1219 throw BDSException(__METHOD_NAME__,
"invalid integrator type");
1228 G4EquationOfMotion* eqOfM)
1236 G4Mag_EqRhs* bEqOfMotion =
new G4Mag_UsualEqRhs(bGlobalField);
1238 G4MagIntegratorStepper* integrator;
1242 if (!mapfile.empty())
1253 bEqOfMotion, integrator);
1254 return completeField;
1260 G4Mag_EqRhs* bEqOfMotion =
new G4Mag_UsualEqRhs(bGlobalField);
1263 bEqOfMotion, integrator);
1264 return completeField;
1273 bEqOfMotion, integrator);
1274 return completeField;
1280 G4Mag_EqRhs* bEqOfMotion =
new G4Mag_UsualEqRhs(bGlobalField);
1283 bEqOfMotion, integrator);
1284 return completeField;
1289 G4double result = 1.0;
1291 {result = (*st)[
"scalingOuter"];}
1298 if (!modulatorRecipe)
1305 case BDSModulatorType::sint:
1307 G4double globalPhase = CalculateGlobalPhase(*modulatorRecipe, info);
1311 modulatorRecipe->
scale);
1314 case BDSModulatorType::singlobalt:
1321 modulatorRecipe->
scale);
1324 case BDSModulatorType::tophatt:
1327 modulatorRecipe->
T1,
1328 modulatorRecipe->
scale);
1331 case BDSModulatorType::none:
1338 G4String extraMsg =
"\nProblem in field definition for component \"" + info.
NameOfParserDefinition() +
"\"";
1339 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.
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)
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.
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.
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.
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 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 tOffset
Public member for direct access.
G4double scale
Public member for direct access.
G4double amplitudeOffset
Public member for direct access.
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.