19#include "BDSComponentFactory.hh"
23#include "BDSAwakeScintillatorScreen.hh"
24#include "BDSAwakeSpectrometer.hh"
26#include "BDSCavityElement.hh"
27#include "BDSCollimatorCrystal.hh"
28#include "BDSCollimatorElliptical.hh"
29#include "BDSCollimatorJaw.hh"
30#include "BDSCollimatorRectangular.hh"
31#include "BDSColours.hh"
32#include "BDSComponentFactoryUser.hh"
35#include "BDSDicomIntersectVolume.hh"
37#include "BDSDegrader.hh"
40#include "BDSElement.hh"
41#include "BDSLaserWire.hh"
43#include "BDSMagnet.hh"
44#include "BDSSamplerPlane.hh"
45#include "BDSScreen.hh"
46#include "BDSShield.hh"
47#include "BDSTarget.hh"
48#include "BDSTeleporter.hh"
49#include "BDSTerminator.hh"
50#include "BDSTiltOffset.hh"
51#include "BDSTransform3D.hh"
52#include "BDSWireScanner.hh"
53#include "BDSUndulator.hh"
54#include "BDSWarning.hh"
57#include "BDSAcceleratorComponentRegistry.hh"
58#include "BDSBeamPipeFactory.hh"
59#include "BDSBeamPipeInfo.hh"
60#include "BDSBeamPipeType.hh"
61#include "BDSBendBuilder.hh"
63#include "BDSCavityInfo.hh"
64#include "BDSCavityType.hh"
65#include "BDSCrystalInfo.hh"
66#include "BDSCrystalType.hh"
68#include "BDSException.hh"
69#include "BDSExecOptions.hh"
70#include "BDSFieldInfo.hh"
71#include "BDSFieldFactory.hh"
72#include "BDSFieldType.hh"
73#include "BDSGlobalConstants.hh"
75#include "BDSIntegratorSet.hh"
76#include "BDSIntegratorSetType.hh"
77#include "BDSIntegratorType.hh"
78#include "BDSIntegratorDipoleFringe.hh"
79#include "BDSMagnetOuterFactory.hh"
80#include "BDSMagnetOuterInfo.hh"
81#include "BDSMagnetGeometryType.hh"
82#include "BDSMagnetStrength.hh"
83#include "BDSMagnetType.hh"
84#include "BDSMaterials.hh"
85#include "BDSParser.hh"
86#include "BDSParticleDefinition.hh"
87#include "BDSUtilities.hh"
91#include "G4Transform3D.hh"
93#include "CLHEP/Units/SystemOfUnits.h"
94#include "CLHEP/Units/PhysicalConstants.h"
96#include "parser/element.h"
97#include "parser/elementtype.h"
98#include "parser/cavitymodel.h"
99#include "parser/newcolour.h"
100#include "parser/crystal.h"
113 G4bool usualPrintOut):
114 designParticle(designParticleIn),
115 userComponentFactory(userComponentFactoryIn),
123 {
throw BDSException(__METHOD_NAME__,
"no valid design particle - required.");}
124 brho = designParticle->BRho();
125 beta0 = designParticle->Beta();
129 {G4cout << __METHOD_NAME__ <<
"Using \"" << integratorSetType <<
"\" set of integrators" << G4endl;}
132 PrepareCavityModels();
136BDSComponentFactory::~BDSComponentFactory()
139 {
delete info.second;}
141 {
delete info.second;}
157 G4double currentArcLength)
162 G4double angleIn = 0.0;
163 G4double angleOut = 0.0;
164 G4bool registered =
false;
167 G4bool differentFromDefinition =
false;
170 G4cout << __METHOD_NAME__ <<
"named: \"" <<
element->name <<
"\"" << G4endl;
185 {differentFromDefinition =
true;}
193 {differentFromDefinition =
true;}
199 {differentFromDefinition =
true;}
207 {differentFromDefinition =
true;}
212 {differentFromDefinition =
true;}
222 if (prevType == ElementType::_DRIFT && nextType != ElementType::_DRIFT)
224 else if (prevType != ElementType::_DRIFT && nextType == ElementType::_DRIFT)
234 {differentFromDefinition =
true;}
241 {differentFromDefinition =
true;}
246 {differentFromDefinition =
true;}
252 if (registered && !differentFromDefinition)
255 G4cout << __METHOD_NAME__ <<
"using already manufactured component" << G4endl;
263 if (differentFromDefinition)
281 G4cout << __METHOD_NAME__ <<
" - creating \"" <<
elementName <<
"\"" << G4endl;
286 case ElementType::_DRIFT:
287 {component = CreateDrift(angleIn, angleOut);
break;}
288 case ElementType::_RF:
290 component = CreateRF(currentArcLength);
291 differentFromDefinition =
true;
294 case ElementType::_SBEND:
295 {component = CreateSBend();
break;}
296 case ElementType::_RBEND:
297 {component = CreateRBend();
break;}
298 case ElementType::_HKICKER:
299 {component = CreateKicker(KickerType::horizontal);
break;}
300 case ElementType::_VKICKER:
301 {component = CreateKicker(KickerType::vertical);
break;}
302 case ElementType::_KICKER:
303 case ElementType::_TKICKER:
304 {component = CreateKicker(KickerType::general);
break;}
305 case ElementType::_QUAD:
306 {component = CreateQuad();
break;}
307 case ElementType::_SEXTUPOLE:
308 {component = CreateSextupole();
break;}
309 case ElementType::_OCTUPOLE:
310 {component = CreateOctupole();
break;}
311 case ElementType::_DECAPOLE:
312 {component = CreateDecapole();
break;}
313 case ElementType::_MULT:
317 component = CreateThinMultipole(angleIn);
320 component = CreateMultipole();
322 case ElementType::_THINMULT:
323 {component = CreateThinMultipole(angleIn);
break;}
324 case ElementType::_ELEMENT:
325 {component = CreateElement();
break;}
326 case ElementType::_SOLENOID:
327 {component = CreateSolenoid();
break;}
328 case ElementType::_ECOL:
329 {component = CreateEllipticalCollimator();
break;}
330 case ElementType::_RCOL:
331 {component = CreateRectangularCollimator();
break;}
332 case ElementType::_TARGET:
333 {component = CreateTarget();
break;}
334 case ElementType::_JCOL:
335 {component = CreateJawCollimator();
break;}
336 case ElementType::_MUONSPOILER:
337 {component = CreateMuonSpoiler();
break;}
338 case ElementType::_SHIELD:
339 {component = CreateShield();
break;}
340 case ElementType::_DEGRADER:
341 {component = CreateDegrader();
break;}
342 case ElementType::_WIRESCANNER:
343 {component = CreateWireScanner();
break;}
344 case ElementType::_GAP:
345 {component = CreateGap();
break;}
346 case ElementType::_CRYSTALCOL:
347 {component = CreateCrystalCollimator();
break;}
348 case ElementType::_LASER:
349 {component = CreateLaser();
break;}
350 case ElementType::_SCREEN:
351 {component = CreateScreen();
break;}
352 case ElementType::_TRANSFORM3D:
353 {component = CreateTransform3D();
break;}
354 case ElementType::_THINRMATRIX:
355 {component = CreateThinRMatrix(angleIn,
elementName);
break;}
356 case ElementType::_PARALLELTRANSPORTER:
357 {component = CreateParallelTransporter();
break;}
358 case ElementType::_RMATRIX:
359 {component = CreateRMatrix();
break;}
360 case ElementType::_UNDULATOR:
361 {component = CreateUndulator();
break;}
362 case ElementType::_USERCOMPONENT:
365 {
throw BDSException(__METHOD_NAME__,
"no user component factory registered");}
379 case ElementType::_DUMP:
380 {component = CreateDump();
break;}
381 case ElementType::_CT:
383 {component = CreateCT();
break;}
385 {
throw BDSException(__METHOD_NAME__,
"ct element can't be used - not compiled with dicom module!");}
387 case ElementType::_AWAKESCREEN:
389 {component = CreateAwakeScreen();
break;}
391 throw BDSException(__METHOD_NAME__,
"Awake Screen can't be used - not compiled with AWAKE module!");
393 case ElementType::_AWAKESPECTROMETER:
395 {component = CreateAwakeSpectrometer();
break;}
397 {
throw BDSException(__METHOD_NAME__,
"Awake Spectrometer can't be used - not compiled with AWAKE module!");}
400 case ElementType::_MARKER:
401 case ElementType::_LINE:
402 case ElementType::_REV_LINE:
403 {component =
nullptr;
break;}
406 G4cerr << __METHOD_NAME__ <<
"unknown type " <<
element->
type << G4endl;
426 case ElementType::_ECOL:
427 case ElementType::_RCOL:
428 case ElementType::_JCOL:
448 const G4double teleporterHorizontalWidth,
449 const G4Transform3D& transformIn)
452 (*st)[
"length"] = teleporterLength;
455 BDSIntegratorType::teleporter,
460 G4cout <<
"---->creating Teleporter, "
461 <<
"l = " << teleporterLength/CLHEP::m <<
"m"
464 return(
new BDSTeleporter(teleporterLength, teleporterHorizontalWidth, vacuumFieldInfo));
477 G4double prevTilt = 0;
478 G4double nextTilt = 0;
483 G4ThreeVector inputFaceNormal = faces.first.rotateZ(prevTilt - currentTilt);
484 G4ThreeVector outputFaceNormal = faces.second.rotateZ(nextTilt - currentTilt);
486 const G4double length =
element->
l*CLHEP::m;
494 length, extent, extent);
496 if (facesWillIntersect)
498 G4cerr << __METHOD_NAME__ <<
"Drift \"" <<
elementName
504 G4cerr <<
"\" and \"";
509 G4cerr <<
"\" is too short given its width and the angle of its faces." << G4endl;
532 G4double cavityLength =
element->
l * CLHEP::m;
537 G4bool buildIncomingFringe = buildCavityFringes;
544 G4bool buildOutgoingFringe = buildCavityFringes;
551 if (buildIncomingFringe)
553 if (buildOutgoingFringe)
576 G4double stepFraction = 0.025;
580 G4double limit = std::min((*st)[
"length"], CLHEP::c_light*period) * stepFraction;
593 G4double cavityApertureRadius = cavityInfo->
irisRadius;
608 if (buildIncomingFringe)
612 (*stIn)[
"rmat11"] = 1;
613 (*stIn)[
"rmat21"] = 0;
614 (*stIn)[
"rmat22"] = 1;
615 (*stIn)[
"rmat33"] = 1;
616 (*stIn)[
"rmat43"] = 0;
617 (*stIn)[
"rmat44"] = 1;
619 (*stIn)[
"isentrance"] =
true;
620 auto cavityFringeIn = CreateCavityFringe(0, stIn,
elementName +
"_fringe_in", cavityApertureRadius);
634 if (buildOutgoingFringe)
638 (*stOut)[
"rmat11"] = 1;
639 (*stOut)[
"rmat21"] = 0;
640 (*stOut)[
"rmat22"] = 1;
641 (*stOut)[
"rmat33"] = 1;
642 (*stOut)[
"rmat43"] = 0;
643 (*stOut)[
"rmat44"] = 1;
645 (*stOut)[
"isentrance"] =
false;
646 auto cavityFringeIn = CreateCavityFringe(0, stOut,
elementName +
"_fringe_out", cavityApertureRadius);
669 (*st)[
"angle"] = angle;
672 (*st)[
"length"] =
element->
l * CLHEP::m;
680 G4cout <<
"Angle (rad) " << (*st)[
"angle"] / CLHEP::rad << G4endl;
681 G4cout <<
"Field (T) " << (*st)[
"field"] / CLHEP::tesla << G4endl;
688 incomingFaceAngle, outgoingFaceAngle,
706 G4double arcLength = 0, chordLength = 0, field = 0, angle = 0;
709 (*st)[
"angle"] = angle;
712 (*st)[
"length"] = arcLength;
726 -incomingFaceAngle, -outgoingFaceAngle,
735 incomingFaceAngle -= 0.5*angle;
736 outgoingFaceAngle -= 0.5*angle;
740 incomingFaceAngle, outgoingFaceAngle,
751 case KickerType::horizontal:
761 case KickerType::vertical:
771 case KickerType::general:
777 {BDS::Warning(__METHOD_NAME__,
"'kick' parameter defined in element \"" +
elementName +
"\" but will be ignored as general kicker.");}
791 G4double chordLength;
796 (*st)[
"scaling"] = scaling;
797 (*st)[
"hkick"] = scaling * hkick;
798 (*st)[
"vkick"] = scaling * vkick;
810 (*fringeStOut)[
"isentrance"] =
false;
813 G4bool finiteEntrFringe =
false;
814 G4bool finiteExitFringe =
false;
817 {finiteEntrFringe =
true;}
820 {finiteExitFringe =
true;}
823 G4bool buildEntranceFringe =
false;
824 G4bool buildExitFringe =
false;
826 {buildEntranceFringe =
true;}
828 {buildExitFringe =
true;}
831 buildEntranceFringe =
false;
832 buildExitFringe =
false;
837 fieldType = BDSFieldType::bfieldzero;
838 intType = BDSIntegratorType::kickerthin;
849 if (buildEntranceFringe || buildExitFringe)
851 G4cout << __METHOD_NAME__ <<
"WARNING - finite B field required for kicker pole face and fringe fields,"
852 " effects are unavailable for element ""\"" <<
elementName <<
"\"." << G4endl;
854 buildEntranceFringe =
false;
855 buildExitFringe =
false;
860 else if (type == KickerType::general)
863 if (buildEntranceFringe || buildExitFringe)
865 G4cerr << __METHOD_NAME__ <<
" Poleface and fringe field effects are unavailable "
866 <<
"for the thin (t)kicker element ""\"" <<
elementName <<
"\"." << G4endl;
868 buildEntranceFringe =
false;
869 buildExitFringe =
false;
880 (*st)[
"field"] =
element->
B * CLHEP::tesla * scaling;
881 (*fringeStIn) [
"field"] = (*st)[
"field"];
882 (*fringeStOut) [
"field"] = (*st)[
"field"];
886 if (type == KickerType::vertical)
896 G4double angleX = std::asin(hkick * scaling);
897 G4double angleY = std::asin(vkick * scaling);
899 if (std::isnan(angleX))
900 {
throw BDSException(__METHOD_NAME__,
"hkick too strong for element \"" +
element->name +
"\" ");}
901 if (std::isnan(angleY))
902 {
throw BDSException(__METHOD_NAME__,
"vkick too strong for element \"" +
element->name +
"\" ");}
916 case KickerType::horizontal:
917 case KickerType::general:
918 {fieldX =
element->
B * CLHEP::tesla * scaling;
break;}
919 case KickerType::vertical:
920 {fieldY =
element->
B * CLHEP::tesla * scaling;
break;}
931 G4double fieldChordLengthX = chordLength / std::cos(0.5*angleX);
934 G4double bendingRadiusX = fieldChordLengthX * 0.5 / sin(std::abs(angleX) * 0.5);
937 G4double arcLengthX = std::abs(bendingRadiusX * angleX);
945 G4double fieldChordLengthY = chordLength / std::cos(0.5*angleY);
946 G4double bendingRadiusY = fieldChordLengthY * 0.5 / sin(std::abs(angleY) * 0.5);
947 G4double arcLengthY = std::abs(bendingRadiusY * angleY);
954 G4ThreeVector field = G4ThreeVector(fieldY, fieldX, 0);
955 G4double fieldMag = field.mag();
956 G4ThreeVector unitField = field.unit();
958 (*st)[
"field"] = fieldMag;
959 (*st)[
"bx"] = unitField.x();
960 (*st)[
"by"] = unitField.y();
964 (*fringeStIn)[
"field"] = (*st)[
"field"];
965 (*fringeStOut)[
"field"] = (*st)[
"field"];
966 if (fieldX < 0 || fieldY < 0)
968 (*fringeStIn)[
"field"] *= -1;
969 (*fringeStOut)[
"field"] *= -1;
973 (*fringeStIn) [
"bx"] = (*st)[
"bx"];
974 (*fringeStIn) [
"by"] = (*st)[
"by"];
975 (*fringeStOut)[
"bx"] = (*st)[
"bx"];
976 (*fringeStOut)[
"by"] = (*st)[
"by"];
979 G4double defaultVHRatio = 1.5;
982 case KickerType::horizontal:
983 case KickerType::general:
984 {t = BDSMagnetType::hkicker;
break;}
985 case KickerType::vertical:
987 t = BDSMagnetType::vkicker;
988 defaultVHRatio = 1./defaultVHRatio;
992 {t = BDSMagnetType::hkicker;
break;}
1010 G4double defaultHorizontalWidth = 0.3 * globalDefaultHW;
1012 G4double bpDX = bpExt.
DX();
1013 G4double bpDY = bpExt.
DY();
1014 if (bpDX > defaultHorizontalWidth && bpDX < globalDefaultHW)
1015 {defaultHorizontalWidth = globalDefaultHW;}
1016 else if (bpDY > defaultHorizontalWidth && bpDY > globalDefaultHW)
1017 {defaultHorizontalWidth = globalDefaultHW;}
1020 defaultHorizontalWidth, defaultVHRatio, 0.9);
1055 G4double kickerChordLength = chordLength;
1056 if (buildEntranceFringe)
1058 if (buildExitFringe)
1061 if (buildEntranceFringe)
1063 G4String entrFringeName = baseName +
"_e1_fringe";
1073 G4String kickerName = baseName;
1084 if (buildEntranceFringe)
1086 G4String exitFringeName = baseName +
"_e2_fringe";
1160 beamPipeInfo->
beamPipeType = BDSBeamPipeType::circularvacuum;
1162 -angleIn, angleIn, beamPipeInfo);
1163 magnetOuterInfo->geometryType = BDSMagnetGeometryType::none;
1184 beamPipeInfo->
aper1,
1187 return thinMultipole;
1193 {
throw BDSException(__METHOD_NAME__,
"insufficient length for element \"" +
element->name +
"\" - must specify a suitable length");}
1203 &vacuumBiasVolumeNames,
1217 (*st)[
"length"] =
element->
l * CLHEP::m * 0.8;
1221 (*st)[
"field"] = scaling *
element->
B * CLHEP::tesla;
1222 (*st)[
"ks"] = (*st)[
"field"] /
brho;
1236 auto strength = [](G4double phi){
1242 (*s)[
"rmat41"] = -phi;
1243 (*s)[
"rmat23"] = phi;
1247 G4bool buildIncomingFringe =
true;
1252 G4bool buildOutgoingFringe =
true;
1258 G4double solenoidBodyLength =
element->
l * CLHEP::m;
1260 if (buildIncomingFringe)
1262 if (buildOutgoingFringe)
1266 G4double lengthScaling = solenoidBodyLength / (
element->
l * CLHEP::m);
1267 G4double s = 0.5*(*st)[
"ks"] * lengthScaling;
1270 if (buildIncomingFringe)
1272 auto stIn = strength(s);
1273 auto solenoidIn = CreateThinRMatrix(0, stIn,
elementName +
"_fringe_in");
1291 vacuumField->SetScalingRadius(outerInfo->innerRadius);
1300 BDSFieldType::solenoid,
1312 G4double outerRadius = outerInfo->horizontalWidth * 0.5;
1313 G4double coilRadius = beamPipeRadius + 0.25*(outerRadius - beamPipeRadius);
1314 outerField->SetScalingRadius(coilRadius);
1317 auto solenoid =
new BDSMagnet(BDSMagnetType::solenoid,
1328 if (buildOutgoingFringe)
1330 auto stOut = strength(-s);
1331 auto solenoidOut = CreateThinRMatrix(0, stOut,
elementName +
"_fringe_out");
1341 return CreateMagnet(
element, st, BDSFieldType::paralleltransporter, BDSMagnetType::paralleltransporter);
1348 G4bool circularOuter =
false;
1350 if (apertureType ==
"circular")
1351 {circularOuter =
true;}
1369 G4bool circularOuter =
false;
1371 if (apertureType ==
"circular")
1372 {circularOuter =
true;}
1386 G4bool circularOuter =
false;
1388 if (apertureType ==
"circular")
1389 {circularOuter =
true;}
1427 G4double elLength =
element->
l*CLHEP::m;
1435 outerField =
new BDSFieldInfo(BDSFieldType::muonspoiler,
1443 G4double limit = elLength / 20.0;
1445 if (ul != defaultUL)
1450 return new BDSMagnet(BDSMagnetType::muonspoiler,
1486 G4double degraderOffset;
1488 {
throw BDSException(__METHOD_NAME__,
"both \"materialThickness\" and \"degraderOffset\" are either undefined or < 0");}
1490 {
throw BDSException(__METHOD_NAME__,
"\"degraderOffset\" cannot be < 0");}
1492 {
throw BDSException(__METHOD_NAME__,
"\"materialThickness\" cannot be greater than the element length");}
1506 degraderOffset = (0.5*thicknessPerWedge) * (std::sin(CLHEP::halfpi - theta) / std::sin(theta));
1512 G4double baseWidth = bpi->aper1;
1534 {
throw BDSException(__METHOD_NAME__,
"\"angle\" parameter set for wirescanner \"" +
elementName +
"\" but this should not be set. Please unset and use \"wireAngle\".");}
1576 G4double limit = (*st)[
"length"] * 0.075;
1578 if (ul != defaultUL)
1595 G4double chordLength =
element->
l*CLHEP::m;
1598 G4cout << __METHOD_NAME__ <<
"Using default length of 1 mm for dump" << G4endl;
1599 chordLength = 1*CLHEP::mm;
1602 G4bool circular =
false;
1604 if (apertureType ==
"circular")
1606 else if (apertureType !=
"rectangular" && !apertureType.empty())
1607 {
throw BDSException(__METHOD_NAME__,
"unknown shape for dump: \"" + apertureType +
"\"");}
1625 new BDSDicomIntersectVolume();
1648 if (!
element->crystalBoth.empty())
1653 else if (
element->crystalBoth.empty() && !
element->crystalRight.empty() && !
element->crystalLeft.empty())
1658 else if (
element->crystalRight.empty())
1665 G4cout << G4endl << G4endl << __METHOD_NAME__
1666 <<
"Left crystal being used but right angle set - perhaps check input for element "
1671 G4cout << G4endl << G4endl << __METHOD_NAME__
1672 <<
"Right crystal being used but left angle set - perhaps check input for element "
1683 element->crystalAngleYAxisLeft*CLHEP::rad,
1684 element->crystalAngleYAxisRight*CLHEP::rad));
1692 G4double length =
element->
l*CLHEP::m;
1696 G4ThreeVector position = G4ThreeVector(0,0,0);
1707 size.setX(
element->screenXSize*CLHEP::m);
1709 G4cout << __METHOD_NAME__ <<
" - size = " << size << G4endl;
1719 "same number of materials as layers - check 'layerMaterials'");
1725 std::list<std::string>::const_iterator itm;
1726 std::list<double>::const_iterator itt;
1727 std::list<int>::const_iterator itIsSampler;
1735 G4cout << __METHOD_NAME__ <<
" - screen layer: thickness: "
1736 << *(itt) <<
", material " << (*itm)
1737 <<
", isSampler: " << (*itIsSampler) << G4endl;
1753 return (
new BDSAwakeScintillatorScreen(
elementName,
1770 (*awakeStrength)[
"by"] = 1;
1775 BDSIntegratorType::g4classicalrk4,
1830 G4cout <<
"---->creating Terminator" << G4endl;
1844 BDSFieldType::paralleltransporter,
1845 BDSMagnetType::paralleltransporter);
1850 BDSFieldType::paralleltransporter,
1851 BDSMagnetType::paralleltransporter);
1865 const G4String& name)
1868 return CreateThinRMatrix(angleIn, st, name);
1873 const G4String& name,
1876 G4double beamPipeRadius)
1879 beamPipeInfo->
beamPipeType = BDSBeamPipeType::circularvacuum;
1883 {beamPipeInfo->
aper1 = beamPipeRadius;}
1886 -angleIn, angleIn, beamPipeInfo);
1887 magnetOuterInfo->geometryType = BDSMagnetGeometryType::none;
1896 vacuumField->SetBeamPipeRadius(beamPipeInfo->
aper1);
1908 beamPipeInfo->
aper1,
1916 const G4String& name,
1917 G4double irisRadius)
1922 return cavityFringe;
1930 const G4String& nameSuffix)
const
1943 vacuumField->SetScalingRadius(outerInfo->innerRadius);
1948 G4bool externalOuterField = !(el->
fieldOuter.empty());
1972 G4bool printWarning)
1977 {BDS::Warning(
"---> NOT creating element \"" + el->name +
"\" -> l < 1e-7 m: l = " + std::to_string(el->
l) +
" m");}
1989 " is greater than " + std::to_string(maxAngle));}
1992 " is greater than " + std::to_string(maxAngle));}
2000 if (mgt == BDSMagnetGeometryType::lhcleft)
2002 if (mgt == BDSMagnetGeometryType::lhcright)
2005 G4double angle = (*st)[
"angle"];
2006 G4double hkickAng = -(*st)[
"hkick"];
2007 G4double vkickAng = -(*st)[
"vkick"];
2013 if ((angle < 0) && (
element->yokeOnInside))
2014 {yokeOnLeft =
true;}
2015 else if ((angle > 0) && (!(
element->yokeOnInside)))
2016 {yokeOnLeft =
true;}
2018 {yokeOnLeft =
false;}
2022G4double BDSComponentFactory::ScalingFieldOuter(
const GMAD::Element* ele)
2031 const G4Transform3D& fieldTransform,
2034 G4double outerFieldScaling)
2039 case BDSFieldType::dipole:
2040 {outerType = BDSFieldType::multipoleouterdipole;
break;}
2041 case BDSFieldType::quadrupole:
2042 {outerType = BDSFieldType::multipoleouterquadrupole;
break;}
2043 case BDSFieldType::sextupole:
2044 {outerType = BDSFieldType::multipoleoutersextupole;
break;}
2045 case BDSFieldType::octupole:
2046 {outerType = BDSFieldType::multipoleouteroctupole;
break;}
2047 case BDSFieldType::decapole:
2048 {outerType = BDSFieldType::multipoleouterdecapole;
break;}
2049 case BDSFieldType::skewquadrupole:
2050 {outerType = BDSFieldType::skewmultipoleouterquadrupole;
break;}
2051 case BDSFieldType::skewsextupole:
2052 {outerType = BDSFieldType::skewmultipoleoutersextupole;
break;}
2053 case BDSFieldType::skewoctupole:
2054 {outerType = BDSFieldType::skewmultipoleouteroctupole;
break;}
2055 case BDSFieldType::skewdecapole:
2056 {outerType = BDSFieldType::skewmultipoleouterdecapole;
break;}
2057 case BDSFieldType::dipole3d:
2058 case BDSFieldType::solenoid:
2059 {outerType = BDSFieldType::solenoidsheet;
break;}
2061 {
return nullptr;
break;}
2065 (*stCopy)[
"scalingOuter"] = outerFieldScaling;
2077 outerField->SetScalingRadius(outerInfo->innerRadius);
2078 outerField->SetSecondFieldOnLeft(outerInfo->yokeOnLeft);
2079 auto gt = outerInfo->geometryType;
2081 if ((gt == BDSMagnetGeometryType::lhcleft || gt == BDSMagnetGeometryType::lhcright) && yfmLHC)
2083 if (fieldType == BDSFieldType::dipole)
2084 {outerField->
SetFieldType(BDSFieldType::multipoleouterdipolelhc);}
2085 else if (fieldType == BDSFieldType::quadrupole)
2086 {outerField->
SetFieldType(BDSFieldType::multipoleouterquadrupolelhc);}
2087 else if (fieldType == BDSFieldType::sextupole)
2088 {outerField->
SetFieldType(BDSFieldType::multipoleoutersextupolelhc);}
2101 G4double defaultHorizontalWidth,
2102 G4double defaultVHRatio,
2103 G4double defaultCoilWidthFraction,
2104 G4double defaultCoilHeightFraction)
2107 G4double angle = (*st)[
"angle"];
2110 defaultHorizontalWidth, defaultVHRatio, defaultCoilWidthFraction,
2111 defaultCoilHeightFraction);
2119 if (el->magnetGeometryType.empty() || globals->IgnoreLocalMagnetGeometry())
2120 {result = globals->MagnetGeometryType();}
2128 const G4double angleIn,
2129 const G4double angleOut,
2131 const G4bool yokeOnLeft,
2132 G4double defaultHorizontalWidth,
2133 G4double defaultVHRatio,
2134 G4double defaultCoilWidthFraction,
2135 G4double defaultCoilHeightFraction)
2140 info->name = elementNameIn;
2144 if (! (el->magnetGeometryType.empty() || globals->IgnoreLocalMagnetGeometry()) )
2146 info->geometryTypeAndPath = el->magnetGeometryType;
2148 {BDS::Warning(__METHOD_NAME__,
"stripOuterVolume for element \"" + el->name +
"\" will have no effect");}
2152 info->angleIn = angleIn;
2153 info->angleOut = angleOut;
2162 G4Material* outerMaterial;
2163 if (el->material.empty())
2165 G4String defaultMaterialName = globals->OuterMaterialName();
2170 info->outerMaterial = outerMaterial;
2173 info->yokeOnLeft = yokeOnLeft;
2176 {info->
hStyle = globals->HStyle();}
2181 {info->vhRatio = G4double(el->
vhRatio);}
2182 else if (globals->VHRatio() > 0)
2183 {info->vhRatio = globals->VHRatio();}
2184 else if (defaultVHRatio > 0)
2185 {info->vhRatio = defaultVHRatio;}
2187 {info->vhRatio = info->
hStyle ? 0.8 : 1.0;}
2191 else if (globals->CoilWidthFraction() > 0)
2192 {info->coilWidthFraction = globals->CoilWidthFraction();}
2193 else if (defaultCoilHeightFraction > 0)
2194 {info->coilWidthFraction = defaultCoilWidthFraction;}
2196 {info->coilWidthFraction = info->
hStyle ? 0.8 : 0.65;}
2200 else if (globals->CoilHeightFraction() > 0)
2201 {info->coilHeightFraction = globals->CoilHeightFraction();}
2202 else if (defaultCoilHeightFraction > 0)
2203 {info->coilHeightFraction = defaultCoilHeightFraction;}
2205 {info->coilHeightFraction = 0.8;}
2214 G4double defaultHorizontalWidth)
2216 G4double horizontalWidth = el->horizontalWidth*CLHEP::m;
2217 if (horizontalWidth < 1e-6)
2219 if (defaultHorizontalWidth > 0)
2220 {horizontalWidth = defaultHorizontalWidth;}
2224 return horizontalWidth;
2229 G4Material* result =
nullptr;
2238 const G4ThreeVector& inputFaceNormalIn,
2239 const G4ThreeVector& outputFaceNormalIn)
2249 el->
aper1 * CLHEP::m,
2250 el->
aper2 * CLHEP::m,
2251 el->
aper3 * CLHEP::m,
2252 el->
aper4 * CLHEP::m,
2257 outputFaceNormalIn);
2261 G4String msg =
"\nProblem in element: \"" + el->name +
"\"";
2262 e.AppendToMessage(msg);
2276 const G4double angleIn,
2277 const G4double angleOut)
2287 G4cout << __METHOD_NAME__ <<
"offsetX,Y: " << el->
offsetX <<
" " << el->
offsetY <<
" tilt: " << el->
tilt << G4endl;
2289 G4double xOffset = el->
offsetX * CLHEP::m;
2290 G4double yOffset = el->
offsetY * CLHEP::m;
2291 G4double tilt = el->
tilt * CLHEP::rad;
2301 return tiltOffset ? tiltOffset->
Transform3D() : G4Transform3D();
2314 G4double horizontalWidth,
2315 const G4String& name)
2317 G4double radiusFromAngleLength = std::abs(arcLength / angle);
2318 if (horizontalWidth > 2*radiusFromAngleLength)
2320 G4cerr <<
"Error: the combination of length, angle and horizontalWidth in element named \"" << name
2321 <<
"\" will result in overlapping faces!" << G4endl <<
"Please reduce the horizontalWidth" << G4endl;
2331 G4Material* material =
nullptr;
2332 if (!model.material.empty())
2337 model.irisRadius*CLHEP::m,
2338 model.thickness*CLHEP::m,
2339 model.equatorRadius*CLHEP::m,
2340 model.halfCellLength*CLHEP::m,
2341 model.numberOfPoints,
2342 model.numberOfCells,
2343 model.equatorHorizontalAxis*CLHEP::m,
2344 model.equatorVerticalAxis*CLHEP::m,
2345 model.irisHorizontalAxis*CLHEP::m,
2346 model.irisVerticalAxis*CLHEP::m,
2347 model.tangentLineAngle);
2361 (G4double) colour.red,
2362 (G4double) colour.green,
2363 (G4double) colour.blue,
2364 (G4double) colour.alpha);
2377 G4String(model.data),
2379 G4double(model.lengthX)*CLHEP::m,
2380 G4double(model.lengthY)*CLHEP::m,
2381 G4double(model.lengthZ)*CLHEP::m,
2382 G4double(model.sizeA)*CLHEP::m,
2383 G4double(model.sizeB)*CLHEP::m,
2384 G4double(model.sizeC)*CLHEP::m,
2385 G4double(model.alpha)*CLHEP::halfpi,
2386 G4double(model.beta)*CLHEP::halfpi,
2387 G4double(model.gamma)*CLHEP::halfpi,
2388 G4int (model.spaceGroup),
2389 G4double(model.bendingAngleYAxis)*CLHEP::rad,
2390 G4double(model.bendingAngleZAxis)*CLHEP::rad,
2391 G4double(model.miscutAngleY)*CLHEP::rad);
2402 G4cout <<
"Defined crystals are:" << G4endl;
2404 {G4cout << kv.first << G4endl;}
2405 throw BDSException(__METHOD_NAME__,
"unknown crystal \"" + crystalName +
"\" - please define it");
2414 G4double frequency)
const
2422 if (modelName ==
"")
2428 {
throw BDSException(__METHOD_NAME__,
"unknown cavity model identifier \"" + el->
cavityModel +
"\" - please define it");}
2436 if (cavityRadius > horizontalWidth)
2438 throw BDSException(__METHOD_NAME__,
"Cavity horizontalWidth for element \"" +
elementName +
"\" is smaller " +
2439 "than the cavity model radius.");
2446 if (el->material.empty())
2448 G4cout <<
"ERROR: Cavity material is not defined for cavity \"" <<
elementName <<
"\""
2449 <<
"or for cavity model \"" << el->
cavityModel <<
"\" - please define it" << G4endl;
2460 G4double frequency)
const
2465 G4double aper1 = aperture->
aper1;
2467 G4double defaultHorizontalWidth = 20*CLHEP::cm;
2468 if (aper1 < defaultHorizontalWidth)
2469 {horizontalWidth = std::min(defaultHorizontalWidth, horizontalWidth);}
2471 G4double equatorRadius = horizontalWidth - thickness;
2472 if (equatorRadius <= 0)
2474 throw BDSException(__METHOD_NAME__,
"combination of horizontalWidth and beampipeThickness for element \"" +
2475 el->name +
"\" produce 0 size cavity");
2479 G4double length = el->
l * CLHEP::m;
2480 G4double cellLength = length;
2487 cellLength = 2*CLHEP::c_light / frequency;
2488 G4double nCavities = length / cellLength;
2489 nCells = G4int(std::floor(nCavities));
2495 cellLength = length;
2510 G4double cavityLength,
2511 G4double currentArcLength,
2517 G4double chordLength = cavityLength;
2518 G4double scaling = el->
scaling;
2519 (*st)[
"equatorradius"] = 1*CLHEP::m;
2520 (*st)[
"length"] = chordLength;
2523 G4double lengthScaling = cavityLength / (
element->
l * CLHEP::m);
2526 {(*st)[
"efield"] = scaling * el->
gradient * CLHEP::volt / CLHEP::m;}
2528 {(*st)[
"efield"] = scaling * el->
E * CLHEP::volt / chordLength;}
2529 (*st)[
"efield"] /= lengthScaling;
2531 G4double frequency = std::abs(el->
frequency * CLHEP::hertz);
2532 (*st)[
"frequency"] = frequency;
2535 G4double phase = el->
phase * CLHEP::rad;
2536 (*st)[
"phase"] = phase;
2548 G4double period = 1. / frequency;
2549 G4double tOffset = 0;
2551 {tOffset = el->
tOffset * CLHEP::s;}
2553 {tOffset = (currentArcLength + 0.5 * chordLength) / CLHEP::c_light;}
2556 auto getPhaseFromT = [](G4double tOffsetIn, G4double periodIn)
2558 G4double nPeriods = tOffsetIn / periodIn;
2560 G4double integerPart = 0;
2561 G4double fractionalPart = std::modf(nPeriods, &integerPart);
2562 G4double phaseOffset = fractionalPart * CLHEP::twopi;
2566 G4double phaseOffset = getPhaseFromT(tOffset, period);
2567 (*st)[
"phase"] -= phaseOffset;
2570 G4double tOffsetIn = tOffset;
2571 G4double tOffsetOut = tOffset;
2572 G4double tHalfCavity = (0.5 * chordLength) / CLHEP::c_light;
2574 tOffsetIn -= tHalfCavity;
2576 tOffsetOut += tHalfCavity;
2578 G4double phaseOffsetIn = getPhaseFromT(tOffsetIn, period);
2579 G4double phaseOffsetOut = getPhaseFromT(tOffsetOut, period);
2580 (*fringeIn)[
"phase"] = phaseOffsetIn;
2581 (*fringeOut)[
"phase"] = phaseOffsetOut;
2588 G4String colour = el->
colour;
2596 const G4String& defaultMaterialName)
2598 G4String materialName = el->material;
2599 if (materialName.empty())
2607 G4String materialName = el->material;
2608 if (materialName.empty())
2609 {
throw BDSException(__METHOD_NAME__,
"element \"" + el->name +
"\" has no material specified.");}
2621 for (
auto comp : *line)
2629 <<
"\" is a magnet, but has fieldAll defined." << G4endl
2630 <<
"Can only have fieldOuter and or fieldVacuum specified." << G4endl;
2639 mag->SetOuterField(info);
2646 mag->SetVacuumField(info);
2657 {BDS::Warning(
"component \"" + el->name +
"\" has \"scalingFieldOuter\" != 1.0 -> this will have no effect for \"fieldAll\"");}
2667 G4double scaling = el->
scaling;
2668 (*st)[
"length"] = el->
l * CLHEP::m;
2671 {(*st)[
"length"] = 1*CLHEP::m;}
2672 auto kn = el->
knl.begin();
2673 auto ks = el->
ksl.begin();
2676 auto nkey = normKeys.begin();
2677 auto skey = skewKeys.begin();
2679 for (; kn != el->
knl.end(); kn++, nkey++)
2680 {(*st)[*nkey] = scaling * (*kn);}
2681 for (; ks != el->
ksl.end(); ks++, skey++)
2682 {(*st)[*skey] = scaling * (*ks);}
2690 G4double scaling = el->
scaling;
2693 (*st)[
"kick1"] = scaling * el->
kick1;
2694 (*st)[
"kick2"] = scaling * el->
kick2;
2695 (*st)[
"kick3"] = scaling * el->
kick3;
2696 (*st)[
"kick4"] = scaling * el->
kick4;
2698 (*st)[
"rmat11"] = scaling * el->
rmat11;
2699 (*st)[
"rmat12"] = scaling * el->
rmat12;
2700 (*st)[
"rmat13"] = scaling * el->
rmat13;
2701 (*st)[
"rmat14"] = scaling * el->
rmat14;
2703 (*st)[
"rmat21"] = scaling * el->
rmat21;
2704 (*st)[
"rmat22"] = scaling * el->
rmat22;
2705 (*st)[
"rmat23"] = scaling * el->
rmat23;
2706 (*st)[
"rmat24"] = scaling * el->
rmat24;
2708 (*st)[
"rmat31"] = scaling * el->
rmat31;
2709 (*st)[
"rmat32"] = scaling * el->
rmat32;
2710 (*st)[
"rmat33"] = scaling * el->
rmat33;
2711 (*st)[
"rmat34"] = scaling * el->
rmat34;
2713 (*st)[
"rmat41"] = scaling * el->
rmat41;
2714 (*st)[
"rmat42"] = scaling * el->
rmat42;
2715 (*st)[
"rmat43"] = scaling * el->
rmat43;
2716 (*st)[
"rmat44"] = scaling * el->
rmat44;
2722 const G4double arcLength)
const
2727 {
return brho * angle / arcLength;}
2731 const G4double arcLength)
const
2736 {
return field * arcLength /
brho;}
2741 G4double& field)
const
2743 G4double arcLength = el->
l * CLHEP::m;
2746 field = el->
B * CLHEP::tesla;
2747 angle = el->
angle * CLHEP::rad;
2751 field = el->
B * CLHEP::tesla;
2756 angle = el->
angle * CLHEP::rad;
2762 {
throw BDSException(
"Error: the unsplit sbend "+ el->name +
" cannot be constucted as its bending angle is defined to be greater than pi/2.");}
2764 else if (std::abs(angle) > CLHEP::pi*2.0)
2765 {
throw BDSException(
"Error: the sbend "+ el->name +
" cannot be constucted as its bending angle is defined to be greater than 2 pi.");}
2769 G4double& arcLength,
2770 G4double& chordLength,
2772 G4double& angle)
const
2776 chordLength = el->
l * CLHEP::m;
2777 G4double arcLengthLocal = chordLength;
2781 field = el->
B * CLHEP::tesla;
2784 angle = el->
angle * CLHEP::rad;
2785 G4double bendingRadius =
brho / field;
2789 {arcLengthLocal = bendingRadius * angle;}
2791 {arcLengthLocal = chordLength;}
2795 field = el->
B * CLHEP::tesla;
2796 G4double bendingRadius =
brho / field;
2797 angle = 2.0*std::asin(chordLength*0.5 / bendingRadius);
2798 if (std::isnan(angle))
2799 {
throw BDSException(
"Field too strong for element " + el->name +
", magnet bending angle will be greater than pi.");}
2801 arcLengthLocal = bendingRadius * angle;
2805 angle = el->
angle * CLHEP::rad;
2811 G4double bendingRadius = chordLength * 0.5 / std::sin(std::abs(angle) * 0.5);
2812 arcLengthLocal = bendingRadius * angle;
2813 field =
brho * angle / std::abs(arcLengthLocal);
2820 arcLength = std::abs(arcLengthLocal);
2822 if (std::abs(angle) > CLHEP::pi/2.0)
2823 {
throw BDSException(
"Error: the rbend " + el->name +
" cannot be constucted as its bending angle is defined to be greater than pi/2.");}
2828 G4double bendAngle = 0;
2829 if (el->
type == ElementType::_RBEND)
2831 G4double arcLength = 0, chordLength = 0, field = 0;
2834 else if (el->
type == ElementType::_SBEND)
2851 G4double outgoingFaceAngle = 0;
2854 if (el->
type == ElementType::_RBEND)
2857 {
return outgoingFaceAngle;}
2860 outgoingFaceAngle += 0.5 * bendAngle;
2866 {
return outgoingFaceAngle;}
2873 G4double e2 = el->
e2*CLHEP::rad;
2876 G4double factor = bendAngle < 0 ? -1 : 1;
2877 outgoingFaceAngle += factor * e2;
2880 return outgoingFaceAngle;
2891 G4double incomingFaceAngle = 0;
2894 if (el->
type == ElementType::_RBEND)
2897 {
return incomingFaceAngle;}
2900 incomingFaceAngle += 0.5 * bendAngle;
2906 {
return incomingFaceAngle;}
2913 G4double e1 = el->
e1*CLHEP::rad;
2916 G4double factor = bendAngle < 0 ? -1 : 1;
2917 incomingFaceAngle += factor * e1;
2920 return incomingFaceAngle;
static BDSAcceleratorComponentRegistry * Instance()
Singleton accessor.
void RegisterComponent(BDSAcceleratorComponent *component, bool isModified=false)
BDSAcceleratorComponent * GetComponent(const G4String &name)
Abstract class that represents a component of an accelerator.
virtual void Initialise()
virtual void SetMinimumKineticEnergy(G4double)
virtual void SetBiasVacuumList(const std::list< std::string > &biasVacuumListIn)
Copy the bias list to this element.
void SetField(BDSFieldInfo *fieldInfoIn)
Set the field definition for the whole component.
virtual void SetBiasMaterialList(const std::list< std::string > &biasMaterialListIn)
Copy the bias list to this element.
virtual void SetRegion(const G4String ®ionIn)
Set the region name for this component.
static BDSBeamPipeFactory * Instance()
Singleton accessor.
Holder class for all information required to describe a beam pipe model.
G4double aper1
Public member for direct access.
G4ThreeVector outputFaceNormal
Public member for direct access.
G4double beamPipeThickness
Public member for direct access.
G4double IndicativeRadius() const
Return an indicative extent of the beam pipe - typically the maximum of x or y extent.
BDSBeamPipeType beamPipeType
Public member for direct access.
G4ThreeVector inputFaceNormal
Public member for direct access.
RF Cavity. Uses factories to construct appropriate geometry.
Holder for all Geometrical information required to create an RF cavity.
G4double equatorRadius
Equator radius - half width of widest part.
G4double irisRadius
Iris radius - half width of narrowest part.
G4Material * material
Material.
G4double thickness
Thickness of wall material.
A piece of vacuum beam pipe with a crystal for channelling.
A class for an elliptical collimator.
Collimator with only two jaw and no top bit.
A class for a rectangular collimator.
Colour class that holds all colours used in BDSIM.
static BDSColours * Instance()
singleton pattern
G4Colour * GetColour(const G4String &type, G4bool normaliseTo255=true)
Get colour from name.
void DefineColour(const G4String &name, G4double red, G4double green, G4double blue, G4double alpha=1, G4bool normaliseTo255=true)
Define a new colour.
Factory for user specified accelerator components.
G4bool CanConstructComponentByName(const G4String &componentTypeName) const
Check whether a component can be constructed - ie if the name exists.
BDSAcceleratorComponent * ConstructComponent(const G4String &componentTypeName, GMAD::Element const *elementIn, GMAD::Element const *prevElementIn, GMAD::Element const *nextElementIn, G4double currentArcLength=0)
static G4bool YokeOnLeft(const GMAD::Element *el, const BDSMagnetStrength *st)
std::map< G4String, BDSCrystalInfo * > crystalInfos
Maps of crystal info instances by name.
G4double OutgoingFaceAngle(const GMAD::Element *el) const
G4double AngleFromField(const G4double field, const G4double arcLength) const
BDSComponentFactoryUser * userComponentFactory
User component factory if any.
KickerType
Private enum for kicker types.
G4double FieldFromAngle(const G4double angle, const G4double arcLength) const
static G4double PrepareHorizontalWidth(GMAD::Element const *el, G4double defaultHorizontalWidth=-1)
Prepare the element horizontal width in Geant4 units - if not set, use the global default.
BDSComponentFactory()=delete
No default constructor.
BDSAcceleratorComponent * CreateTeleporter(const G4double teleporterLength, const G4double teleporterWidth, const G4Transform3D &transformIn)
G4Material * PrepareVacuumMaterial(GMAD::Element const *el) const
Prepare the vacuum material from the element or resort to default in options.
void CalculateAngleAndFieldRBend(const GMAD::Element *el, G4double &arcLength, G4double &chordLength, G4double &field, G4double &angle) const
static G4Transform3D CreateFieldTransform(const BDSTiltOffset *tiltOffset)
Create a transform from a tilt offset. If nullptr, returns identity transform.
BDSMagnet * CreateMagnet(const GMAD::Element *el, BDSMagnetStrength *st, BDSFieldType fieldType, BDSMagnetType magnetType, G4double angle=0.0, const G4String &nameSuffix="") const
Helper method for common magnet construction.
BDSMagnetStrength * PrepareMagnetStrengthForMultipoles(GMAD::Element const *el) const
Prepare magnet strength for multipoles.
GMAD::Element const * element
element for storing instead of passing around
static void PoleFaceRotationsNotTooLarge(const GMAD::Element *el, G4double maxAngle=0.5 *CLHEP::halfpi)
Check whether the pole face rotation angles are too big for practical construction.
G4double thinElementLength
Length of a thin element.
BDSCavityInfo * PrepareCavityModelInfoForElement(GMAD::Element const *el, G4double frequency) const
GMAD::Element const * nextElement
element access to previous element (can be nullptr)
BDSCavityInfo * PrepareCavityModelInfo(GMAD::Element const *el, G4double frequency) const
G4bool yokeFields
Cache of whether to include yoke magnetic fields.
static G4bool coloursInitialised
void PrepareColours()
Prepare all colours defined in the parser.
static BDSMagnetOuterInfo * PrepareMagnetOuterInfo(const G4String &elementNameIn, const GMAD::Element *el, const BDSMagnetStrength *st, const BDSBeamPipeInfo *beamPipe, G4double defaultHorizontalWidth=-1, G4double defaultVHRatio=1.0, G4double defaultCoilWidthFraction=-1, G4double defaultCoilHeightFraction=-1)
BDSAcceleratorComponent * CreateTerminator(G4double witdth)
static G4Colour * PrepareColour(GMAD::Element const *element)
Checks if colour is specified for element, else uses the default for that element type.
BDSMagnetStrength * PrepareCavityStrength(GMAD::Element const *el, G4double cavityLength, G4double currentArcLength, BDSMagnetStrength *&fringeIn, BDSMagnetStrength *&fringeOut) const
BDSMagnetStrength * PrepareMagnetStrengthForRMatrix(GMAD::Element const *el) const
Prepare magnet strength for rmatrix.
G4bool includeFringeFields
Cache of whether to include fringe fields.
void SetFieldDefinitions(GMAD::Element const *el, BDSAcceleratorComponent *component) const
BDSAcceleratorComponent * CreateComponent(GMAD::Element const *elementIn, GMAD::Element const *prevElementIn, GMAD::Element const *nextElementIn, G4double currentArcLength=0)
static void CheckBendLengthAngleWidthCombo(G4double arcLength, G4double angle, G4double horizontalWidth, const G4String &name="not given")
void PrepareCrystals()
Prepare all crystals in defined the parser.
G4double lengthSafety
Length safety from global constants.
G4String elementName
Variable used to pass around the possibly modified name of an element.
std::map< G4String, G4int > modifiedElements
void GetKickValue(G4double &hkick, G4double &vkick, const KickerType type) const
G4double BendAngle(const GMAD::Element *el) const
Calculate the angle of a bend whether it's an rbend or an sbend.
G4double IncomingFaceAngle(const GMAD::Element *el) const
void CalculateAngleAndFieldSBend(GMAD::Element const *el, G4double &angle, G4double &field) const
static G4Material * PrepareMaterial(GMAD::Element const *element, const G4String &defaultMaterialName)
Checks if a material is named in Element::material, else uses the supplied default.
static BDSTiltOffset * CreateTiltOffset(GMAD::Element const *el)
Create the tilt and offset information object by inspecting the parser element.
void PrepareCavityModels()
static BDSFieldInfo * PrepareMagnetOuterFieldInfo(const BDSMagnetStrength *vacuumSt, const BDSFieldType &fieldType, const BDSBeamPipeInfo *bpInfo, const BDSMagnetOuterInfo *outerInfo, const G4Transform3D &fieldTransform, const BDSIntegratorSet *integratorSetIn, G4double brhoIn, G4double outerFieldScaling=1.0)
Prepare the field definition for the yoke of a magnet.
const BDSIntegratorSet * integratorSet
Local copy of reference to integrator set to use.
G4double brho
Rigidity in T*m (G4units) for beam particles.
void SetBeta0(BDSMagnetStrength *stIn) const
Simple setter used to add Beta0 to a strength instance.
BDSCrystalInfo * PrepareCrystalInfo(const G4String &crystalName) const
static BDSBeamPipeInfo * PrepareBeamPipeInfo(GMAD::Element const *el, const G4ThreeVector &inputFaceNormal=G4ThreeVector(0, 0,-1), const G4ThreeVector &outputFaceNormal=G4ThreeVector(0, 0, 1))
static BDSMagnetGeometryType MagnetGeometryType(const GMAD::Element *el)
std::map< G4String, BDSCavityInfo * > cavityInfos
Map of cavity model info instances by name.
G4bool HasSufficientMinimumLength(GMAD::Element const *el, G4bool printWarning=true)
Test the component length is sufficient for practical construction.
GMAD::Element const * prevElement
element access to previous element (can be nullptr)
Holder for all information required to create a crystal.
Degrader based on wedge design used in the PSI medical accelerator.
A piece of vacuum beam pipe.
A class for a generic piece of external geometry.
General exception with possible name of object and message.
Holder for +- extents in 3 dimensions.
G4double DX() const
The difference in a dimension.
G4double DY() const
The difference in a dimension.
static BDSFieldFactory * Instance()
Public accessor method for singleton pattern.
BDSFieldInfo * GetDefinition(const G4String &name) const
All info required to build complete field of any type.
void SetTransformBeamline(const G4Transform3D &transformIn)
Set the beam line transform.
void CompoundBScaling(G4double extraBScalingIn)
*= for BScaling.
G4bool ProvideGlobal() const
Accessor.
void SetFieldType(BDSFieldType fieldTypeIn)
Set Transform - could be done afterwards once instance of this class is passed around.
BDSFieldType FieldType() const
Accessor.
void SetUserLimits(G4UserLimits *userLimitsIn)
Delete and replace the user limits which this class owns (only if not default ul).
Gap in accelerator beamline.
void SetExtent(const BDSExtent &extIn)
Set extent.
A class that holds global options and constants.
static BDSGlobalConstants * Instance()
Access method.
Which integrator to use for each type of magnet / field object.
G4bool IsMatrixIntegratorSet() const
Accessor for bool of is the integrator set matrix style.
BDSIntegratorType Integrator(const BDSFieldType field) const
Get appropriate integrator based on the field type.
A class that hold multiple accelerator components.
void AddComponent(BDSAcceleratorComponent *component)
Add a component to the line.
static BDSMagnetOuterFactory * Instance()
Singleton accessor.
Holder struct of all information required to create the outer geometry of a magnet.
G4bool hStyle
H Style for dipoles. If not, it's assumed C style.
Efficient storage of magnet strengths.
static std::vector< G4String > SkewComponentKeys()
Accessor for skew component keys - k1 - k12.
static std::vector< G4String > NormalComponentKeys()
Accessor for normal component keys - k1 - k12.
Abstract base class that implements features common to all magnets.
static BDSMaterials * Instance()
Singleton pattern access.
G4Material * GetMaterial(G4String material) const
Get material by name.
static BDSParser * Instance()
Access method.
Wrapper for particle definition.
A multilayer screen in a beam pipe.
void AddScreenLayer(G4double thickness, G4String material, G4int isSampler=0)
Add a screen layer.
A square mask of solid material with a square aperture.
A class for a box or cylinder piece of 1 material.
An element that unnaturally shifts the beam across its length - a fudge volume.
Class for small control volume for circular macines.
A holder for any placement offsets and rotations for a BDSAcceleratorComponent.
G4Transform3D Transform3D() const
Get a transform to represent this tilt offset.
type underlying() const
return underlying value (can be used in switch statement)
Single cylindrical wire inside beam pipe.
const BDSIntegratorSet * IntegratorSet(G4String set)
Return the appropriate set of integrators to use for each magnet type.
BDSMagnetGeometryType DetermineMagnetGeometryType(G4String geometryType)
function to determine the enum type of the magnet geometry (case-insensitive)
G4bool WillIntersect(const G4ThreeVector &incomingNormal, const G4ThreeVector &outgoingNormal, const G4double &zSeparation, const BDSExtent &incomingExtent, const BDSExtent &outgoingExtent)
BDSCrystalType DetermineCrystalType(G4String crystalType)
function to determine the enum type of the cavity geometry (case-insensitive)
G4double SecondFringeFieldCorrection(BDSMagnetStrength const *strength, G4bool entranceOrExit)
Function to calculate the value of the second fringe field correction term.
BDSMagnet * BuildDipoleFringe(const GMAD::Element *element, G4double angleIn, G4double angleOut, const G4String &name, BDSMagnetStrength *st, G4double brho, const BDSIntegratorSet *integratorSet, BDSFieldType dipoleFieldType)
BDSLine * BuildRBendLine(const G4String &elementName, const GMAD::Element *element, const GMAD::Element *prevElement, const GMAD::Element *nextElement, G4double brho, BDSMagnetStrength *st, const BDSIntegratorSet *integratorSet, G4double incomingFaceAngle, G4double outgoingFaceAngle, G4bool buildFringeFields)
G4UserLimits * CreateUserLimits(G4UserLimits *defaultUL, G4double length, G4double fraction=1.6)
BDSAcceleratorComponent * BuildSBendLine(const G4String &elementName, const GMAD::Element *element, BDSMagnetStrength *st, G4double brho, const BDSIntegratorSet *integratorSet, G4double incomingFaceAngle, G4double outgoingFaceAngle, G4bool buildFringeFields, const GMAD::Element *prevElement, const GMAD::Element *nextElement)
std::vector< G4String > SplitOnWhiteSpace(const G4String &input)
Split a string on whitespace and return a vector of these 'words'.
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())
BDSCavityType DetermineCavityType(G4String cavityType)
function to determine the enum type of the cavity geometry (case-insensitive)
std::pair< G4ThreeVector, G4ThreeVector > CalculateFaces(G4double angleInIn, G4double angleOutIn)
Calculate input and output normal vector.
G4double FringeFieldCorrection(BDSMagnetStrength const *strength, G4bool entranceOrExit)
Function to calculate the value of the fringe field correction term.
Parser namespace for GMAD language. Combination of Geant4 and MAD.
ElementType
types of elements
std::string typestr(ElementType type)
conversion from enum to string
double hkick
fractional delta px for hkicker
std::string dicomDataFile
for CT, file for DICOM construction data
std::string spec
arbitrary specification to pass to beamline builder
void print(int ident=0) const
print method
double twindow
thickness of window
double aper4
beampipe information, new aperture model
std::string beampipeMaterial
beampipe information, new aperture model
double rmat33
rmatrix elements, only 4x4
double rmat11
rmatrix elements, only 4x4
double rmat43
rmatrix elements, only 4x4
std::list< std::string > layerMaterials
for screen
double scaling
Overall scaling of field strength.
double windowScreenGap
air gap between window and screen
double gradient
for rf cavities in V / m
double degraderOffset
for degrader
double wireAngle
for wirescanner
double aper2
beampipe information, new aperture model
double fintx
fringe field integral at the dipole exit
double kick4
rmatrix elements, only 4x4
double rmat42
rmatrix elements, only 4x4
double aper1
beampipe information, new aperture model
double rmat41
rmatrix elements, only 4x4
double awakeMagnetOffsetX
for AWAKE spectrometer
double zdir
for 3d transform and laser
std::string namedVacuumVolumes
For imported geometry - identify vacuum volumes.
bool stripOuterVolume
For Element. Make it an assembly.
double screenPSize
for AWAKE spectrometer
double xdir
for 3d transform and laser
double rmat34
rmatrix elements, only 4x4
double psi
for 3d transforms
double wireOffsetX
for wirescanner
double rmat31
rmatrix elements, only 4x4
double wedgeLength
for degrader
double vhRatio
ratio of vertial to horizontal for some magnets
double waveLength
for laser wire and 3d transforms
double rmat22
rmatrix elements, only 4x4
std::string userTypeName
User component element type name.
double wireOffsetY
for wirescanner
double kick3
rmatrix elements, only 4x4
double rmat24
rmatrix elements, only 4x4
double tOffset
time offset used for phase calculation (ns)
std::list< std::string > biasMaterialList
double xsizeRight
individual collimator jaw half widths
double coilWidthFraction
Fraction of available h space the coil will take up.
double rmat44
rmatrix elements, only 4x4
std::string fieldAll
Field for everything.
std::string region
region with range cuts
double wireDiameter
for wirescanner
double tmount
thickness of the screen mount
double wireOffsetZ
for wirescanner
std::list< double > ksl
skew multipole expansion
int numberWedges
for degrader
double kick1
rmatrix elements, only 4x4
std::list< double > knl
multipole expansion coefficients
std::string windowmaterial
for AWAKE spectrometer
double e2
output pole face rotation for bends
double phase
phase of rf cavity (rad)
double ysizeOut
collimator aperture or laser spotsize for laser
std::string fieldVacuum
Vacuum field.
bool autoColour
Automagically colour the external geometry.
double angle
bending angle
int hStyle
-1 = unset; 0 = false (ie c style); 1 = true, use hstyle
std::string geometryFile
For Element. File for external geometry.
std::string vacuumMaterial
beampipe information, new aperture model
double vkick
fractional delta py for vkicker
double E
electric field amplitude for rf cavities in V
double coilHeightFraction
Fraction of availalbe v space the coil will take up.
std::list< int > layerIsSampler
for screen
double screenEndZ
for AWAKE spectrometer
double ysize
collimator aperture or laser spotsize for laser
double rmat23
rmatrix elements, only 4x4
std::string colour
Override colour for certain items.
double rmat13
rmatrix elements, only 4x4
double materialThickness
for degrader
double kick
fractional delta p for either h or v kicker
double rmat14
rmatrix elements, only 4x4
double beampipeThickness
beampipe information, new aperture model
std::string dicomDataPath
for CT, file for DICOM construction data
double minimumKineticEnergy
minimum kinetic energy for user limits - respected on element by element basis
std::string scintmaterial
for AWAKE spectrometer
double ydir
for 3d transform and laser
double undulatorMagnetHeight
for undulator
std::string cavityModel
model for rf cavities
double e1
input pole face rotation for bends
std::string fieldOuter
Outer field.
double undulatorPeriod
for undulator
double wireLength
for wirescanner
double undulatorGap
for undulator
double poleStartZ
for AWAKE spectrometer
std::string mountmaterial
for AWAKE spectrometer
double aper3
beampipe information, new aperture model
ElementType type
element enum
std::list< std::string > biasVacuumList
physics biasing list for the vacuum
std::list< double > layerThicknesses
for screen
double scalingFieldOuter
Extra arbitrary scaling for outer field - compounded with 'scaling'.
double degraderHeight
for degrader
double tscint
thickness of scintillating part of screen
double screenWidth
for AWAKE spectrometer
double frequency
frequency for rf cavity in Hz
double kick2
rmatrix elements, only 4x4
double rmat12
rmatrix elements, only 4x4
std::string apertureType
beampipe information, new aperture model
double rmat21
rmatrix elements, only 4x4
double rmat32
rmatrix elements, only 4x4