32 #include "gsl/gsl_poly.h"
48 messageHeader_m(
" * "),
49 pusher_m(right.pusher_m),
50 designRadius_m(right.designRadius_m),
51 exitAngle_m(right.exitAngle_m),
52 fieldIndex_m(right.fieldIndex_m),
53 startField_m(right.startField_m),
54 endField_m(right.endField_m),
55 widthEntranceFringe_m(right.widthEntranceFringe_m),
56 widthExitFringe_m(right.widthExitFringe_m),
57 reinitialize_m(right.reinitialize_m),
58 entranceParameter1_m(right.entranceParameter1_m),
59 entranceParameter2_m(right.entranceParameter2_m),
60 entranceParameter3_m(right.entranceParameter3_m),
61 exitParameter1_m(right.exitParameter1_m),
62 exitParameter2_m(right.exitParameter2_m),
63 exitParameter3_m(right.exitParameter3_m),
64 engeCoeffsEntry_m(right.engeCoeffsEntry_m),
65 engeCoeffsExit_m(right.engeCoeffsExit_m),
66 entryFieldValues_m(nullptr),
67 exitFieldValues_m(nullptr),
68 entryFieldAccel_m(nullptr),
69 exitFieldAccel_m(nullptr),
70 deltaBeginEntry_m(right.deltaBeginEntry_m),
71 deltaEndEntry_m(right.deltaEndEntry_m),
72 polyOrderEntry_m(right.polyOrderEntry_m),
73 deltaBeginExit_m(right.deltaBeginExit_m),
74 deltaEndExit_m(right.deltaEndExit_m),
75 polyOrderExit_m(right.polyOrderExit_m),
76 cosEntranceAngle_m(right.cosEntranceAngle_m),
77 sinEntranceAngle_m(right.sinEntranceAngle_m),
78 tanEntranceAngle_m(right.tanEntranceAngle_m),
79 tanExitAngle_m(right.tanExitAngle_m),
80 beginToEnd_m(right.beginToEnd_m),
81 beginToEnd_lcs_m(right.beginToEnd_lcs_m),
82 toEntranceRegion_m(right.toEntranceRegion_m),
83 toExitRegion_m(right.toExitRegion_m),
84 computeAngleTrafo_m(right.computeAngleTrafo_m),
85 maxAngle_m(right.maxAngle_m),
86 nSlices_m(right.nSlices_m){
91 messageHeader_m(
" * "),
98 widthEntranceFringe_m(0.0),
99 widthExitFringe_m(0.0),
100 reinitialize_m(false),
101 entranceParameter1_m(0.0),
102 entranceParameter2_m(0.0),
103 entranceParameter3_m(0.0),
104 exitParameter1_m(0.0),
105 exitParameter2_m(0.0),
106 exitParameter3_m(0.0),
107 entryFieldValues_m(nullptr),
108 exitFieldValues_m(nullptr),
109 entryFieldAccel_m(nullptr),
110 exitFieldAccel_m(nullptr),
111 deltaBeginEntry_m(0.0),
112 deltaEndEntry_m(0.0),
114 deltaBeginExit_m(0.0),
117 cosEntranceAngle_m(1.0),
118 sinEntranceAngle_m(0.0),
119 tanEntranceAngle_m(0.0),
127 for (
unsigned int i = 0; i < 3u; ++ i) {
185 return apply(R, P, t, E, B);
201 <<
"======================================================================\n"
202 <<
"===== " << std::left << std::setw(64) << std::setfill(
'=') << name <<
"\n"
203 <<
"======================================================================\n";
209 double bendAngleX = 0.0;
210 double bendAngleY = 0.0;
212 print(msg, bendAngleX, bendAngleY);
224 <<
"======================================================================\n"
225 <<
"======================================================================\n"
228 ERRORMSG(
"There is something wrong with your field map '"
230 endField = startField - 1.0e-3;
264 const Vector_t eField(0.0);
266 while (deltaS < bendLength) {
272 Vector_t bField(0.0, 0.0, 0.0);
292 const std::vector<double> &engeCoeff,
295 double &engeFuncDeriv,
296 double &engeFuncSecDerivNorm) {
299 double expSumDeriv = 0.0;
300 double expSumSecDeriv = 0.0;
302 if (polyOrder >= 2) {
304 expSum = engeCoeff.at(0)
305 + engeCoeff.at(1) * zNormalized;
306 expSumDeriv = engeCoeff.at(1);
308 for (
int index = 2; index <= polyOrder; index++) {
309 expSum += engeCoeff.at(index) *
std::pow(zNormalized, index);
310 expSumDeriv += index * engeCoeff.at(index)
312 expSumSecDeriv += index * (index - 1) * engeCoeff.at(index)
316 }
else if (polyOrder == 1) {
318 expSum = engeCoeff.at(0)
319 + engeCoeff.at(1) * zNormalized;
320 expSumDeriv = engeCoeff.at(1);
323 expSum = engeCoeff.at(0);
326 engeFunc = 1.0 / (1.0 + engeExp);
330 expSumDeriv /=
gap_m;
332 double engeExpDeriv = expSumDeriv * engeExp;
333 double engeExpSecDeriv = (expSumSecDeriv +
std::pow(expSumDeriv, 2.0))
335 double engeFuncSq =
std::pow(engeFunc, 2.0);
337 engeFuncDeriv = -engeExpDeriv * engeFuncSq;
341 engeFuncSecDerivNorm = -engeExpSecDeriv * engeFunc
345 engeFuncSecDerivNorm = 0.0;
350 engeFuncSecDerivNorm = 0.0;
403 B(1) = (engeFunc - 0.5 * engeFuncSecDeriv *
std::pow(Rprime(1), 2.0));
405 B(2) = engeFuncDeriv * Rprime(1);
440 B(1) = (engeFunc - 0.5 * engeFuncSecDeriv *
std::pow(Rprime(1), 2.0));
442 B(2) = engeFuncDeriv * Rprime(1);
451 bool horizontallyInside =
false;
454 if (verticallyInside) {
459 if (inEntranceRegion && inExitRegion) {
464 inExitRegion =
false;
466 inEntranceRegion =
false;
469 if (inEntranceRegion) {
471 }
else if (inExitRegion) {
482 Vector_t BEntrance(0.0), BExit(0.0);
488 if (inEntranceRegion) {
489 horizontallyInside =
true;
490 if (verticallyInside) {
496 horizontallyInside =
true;
497 if (verticallyInside) {
504 B = BEntrance + BExit;
506 bool hitMaterial = (horizontallyInside && (!verticallyInside));
512 std::ofstream trajectoryOutput;
518 trajectoryOutput.open(fname);
519 trajectoryOutput.precision(12);
520 trajectoryOutput <<
"# " << std::setw(18) <<
"s"
521 << std::setw(20) <<
"x"
522 << std::setw(20) <<
"z"
523 << std::setw(20) <<
"By"
537 const Vector_t eField(0.0);
540 const double stepSize = betaGamma / gamma *
Physics::c * dt;
543 while (deltaS < bendLength) {
549 Vector_t bField(0.0, 0.0, 0.0);
550 Vector_t XInBendFrame =
X;
556 trajectoryOutput << std::setw(20) << deltaS + 0.5 * stepSize
557 << std::setw(20) <<
X(0)
558 << std::setw(20) <<
X(2)
559 << std::setw(20) << bField(1)
583 double fieldStep = (
angle_m - actualBendAngle) * effectiveFieldAmplitude;
584 if (ratioSquared < 1.0) {
585 fieldStep = (
angle_m - actualBendAngle) * effectiveFieldAmplitude *
std::sqrt(1.0 - ratioSquared);
607 if (error > 1.0
e-6) {
609 double deltaStep = 0.0;
611 deltaStep = -
gap_m / 2.0;
613 deltaStep =
gap_m / 2.0;
616 double bendAngle1 = actualBendAngle;
618 double delta2 = deltaStep;
643 unsigned int iterations = 1;
645 while (error > 1.0
e-6 && iterations < 100) {
647 double delta = (delta1 + delta2) / 2.0;
655 if (error > 1.0
e-6) {
657 if (bendAngle1 -
angle_m < 0.0) {
659 if (newBendAngle -
angle_m < 0.0) {
660 bendAngle1 = newBendAngle;
669 if (newBendAngle -
angle_m < 0.0) {
673 bendAngle1 = newBendAngle;
690 const double tolerance = 1
e-7;
693 if (error < tolerance)
698 double amplitude2 = amplitude1;
699 double bendAngle1 = actualBendAngle;
700 double bendAngle2 = bendAngle1;
704 amplitude1 = amplitude2;
705 bendAngle1 = bendAngle2;
707 amplitude2 += stepSign * fieldStep;
716 unsigned int iterations = 1;
717 while (error > tolerance && iterations < 100) {
724 if (error > tolerance) {
726 if (bendAngle1 -
angle_m < 0.0) {
728 if (newBendAngle -
angle_m < 0.0) {
729 bendAngle1 = newBendAngle;
738 if (newBendAngle -
angle_m < 0.0) {
742 bendAngle1 = newBendAngle;
753 bool reinitialize =
false;
771 if (refCharge < 0.0) {
778 reinitialize =
false;
808 effectiveAngle >= 0.0 && effectiveAngle <
maxAngle_m) {
809 if (effectiveAngle < 0.5 *
maxAngle_m)
return R(2) >= 0.0;
810 return Rprime(2) < 0.0;
827 return (Rprime(2) >= 0 &&
849 <<
"Start of field map: "
851 <<
" m (in s coordinates)"
853 msg <<
"End of field map: "
855 <<
" m (in s coordinates)"
857 msg <<
"Entrance edge of magnet: "
859 <<
" m (in s coordinates)"
862 <<
"Reference Trajectory Properties"
864 <<
"======================================================================"
866 msg <<
"Bend angle magnitude: "
872 msg <<
"Entrance edge angle: "
878 msg <<
"Exit edge angle: "
884 msg <<
"Bend design radius: "
888 msg <<
"Bend design energy: "
893 <<
"Bend Field and Rotation Properties"
895 <<
"======================================================================"
897 msg <<
"Field amplitude: "
901 msg <<
"Field index: "
904 msg <<
"Rotation about z axis: "
911 <<
"Reference Trajectory Properties Through Bend Magnet with Fringe Fields"
913 <<
"======================================================================"
915 msg <<
"Reference particle is bent: "
918 << bendAngleX * Units::rad2deg
919 <<
" degrees) in x plane"
921 msg <<
"Reference particle is bent: "
924 << bendAngleY * Units::rad2deg
925 <<
" degrees) in y plane"
930 <<
"Effective Field Map\n"
931 <<
"======================================================================\n"
967 unsigned int numStepsEntry =
std::ceil(entryLength / stepSize) + 3;
968 double stepSizeEntry = entryLength / (numStepsEntry - 3);
969 std::vector<double> zvalsEntry(numStepsEntry);
970 std::vector<std::vector<double> > fieldValuesEntry(3);
973 unsigned int numStepsExit =
std::ceil(exitLength / stepSize) + 3;
974 double stepSizeExit = exitLength / (numStepsExit - 3);
975 std::vector<double> zvalsExit(numStepsExit);
976 std::vector<std::vector<double> > fieldValuesExit(3);
983 for (
unsigned int i = 0; i < 3u; ++ i) {
984 fieldValuesEntry[i].resize(numStepsEntry);
985 fieldValuesExit[i].resize(numStepsExit);
991 for (
unsigned int j = 0; j < numStepsEntry; ++ j) {
995 zvalsEntry[j] = zvalsEntry[j - 1] + stepSizeEntry;
1000 fieldValuesEntry[0][j],
1001 fieldValuesEntry[1][j],
1002 fieldValuesEntry[2][j]);
1003 fieldValuesEntry[2][j] *= fieldValuesEntry[0][j];
1006 for (
unsigned int j = 0; j < numStepsExit; ++ j) {
1010 zvalsExit[j] = zvalsExit[j - 1] + stepSizeExit;
1015 fieldValuesExit[0][j],
1016 fieldValuesExit[1][j],
1017 fieldValuesExit[2][j]);
1018 fieldValuesExit[2][j] *= fieldValuesExit[0][j];
1021 for (
unsigned int i = 0; i < 3u; ++ i) {
1022 gsl_spline_init(
entryFieldValues_m[i], &(zvalsEntry[0]), &(fieldValuesEntry[i][0]), numStepsEntry);
1023 gsl_spline_init(
exitFieldValues_m[i], &(zvalsExit[0]), &(fieldValuesExit[i][0]), numStepsExit);
1087 std::sin(0.5 * (0.5 * bendAngle - entranceAngle)) * rotationAxis);
1103 if (rotationCenter(2) < 0.0) {
1106 gsl_poly_solve_quadratic(
dot(P,P),
1112 maxAngleEntranceAperture = tau * P;
1116 gsl_poly_solve_quadratic(
dot(P,P),
1122 maxAngleEntranceAperture = tau * P;
1128 gsl_poly_solve_quadratic(
dot(P,P),
1138 gsl_poly_solve_quadratic(
dot(P,P),
1147 maxAngleEntranceAperture -= rotationCenter;
1155 maxAngleExitAperture -= rotationCenter;
1222 ERRORMSG(
"If using \"1DPROFILE1-DEFAULT\" field map you must set the "
1223 "chord length of the bend using the L attribute in the OPAL "
1251 WARNMSG(
"Warning: bend design energy is zero. Treating as drift."
1262 WARNMSG(
"Warning: bend strength and defined reference trajectory "
1263 <<
"chord length are not consistent. Treating bend as drift."
1272 WARNMSG(
"Warning bend angle/strength is zero. Treating as drift."
1282 std::vector<Vector_t> outline;
1284 unsigned int numSteps = 2;
1295 gsl_poly_solve_quadratic(
dot(P,P),
1301 Vector_t upperCornerAtEntry = tau1 * P;
1304 gsl_poly_solve_quadratic(
dot(P,P),
1316 double dAngle = 0.5 * totalAngle / (1.0 * numSteps - 1.0);
1318 outline.push_back(upperCornerAtEntry);
1320 for (
unsigned int i = 0; i < numSteps; ++ i, angle += dAngle) {
1322 outline.push_back(rot.
rotate(upperCornerAtEntry - rotationCenter) + rotationCenter);
1324 outline.push_back(upperCornerAtExit);
1336 gsl_poly_solve_quadratic(
dot(P,P),
1342 Vector_t lowerCornerAtEntry = tau1 * P;
1345 gsl_poly_solve_quadratic(
dot(P,P),
1356 double dAngle = 0.5 * totalAngle / (1.0 * numSteps - 1.0);
1358 outline.push_back(lowerCornerAtExit);
1359 double angle = 0.5 * totalAngle;
1360 for (
unsigned int i = 0; i < numSteps; ++ i, angle -= dAngle) {
1362 outline.push_back(rot.
rotate(lowerCornerAtEntry - rotationCenter) + rotationCenter);
1364 outline.push_back(lowerCornerAtEntry);
1367 std::ofstream outlineOutput;
1373 outlineOutput.open(fname);
1374 outlineOutput.precision(8);
1376 for (
auto a: outline) {
1377 outlineOutput << std::setw(18) << a(2)
1378 << std::setw(18) << a(0)
1381 outlineOutput << std::setw(18) << outline.front()(2)
1382 << std::setw(18) << outline.front()(0)
1391 std::vector<Vector_t> outline =
getOutline();
1393 unsigned int size = outline.size();
1394 unsigned int last = size - 1;
1395 unsigned int numSteps = (size - 14) / 2;
1396 unsigned int midIdx = numSteps + 7;
1398 for (
unsigned int i = 0; i < 6; ++ i) {
1399 mesh.
vertices_m.push_back(outline[i] + 2 * hgap);
1401 for (
unsigned int i = 6; i < 6 + numSteps; ++ i) {
1402 mesh.
vertices_m.push_back(outline[i] + hgap);
1404 for (
unsigned int i = 6 + numSteps; i < 13 + numSteps; ++ i) {
1405 mesh.
vertices_m.push_back(outline[i] + 2 * hgap);
1407 for (
unsigned int i = 13 + numSteps; i < 13 + 2 * numSteps; ++ i) {
1408 mesh.
vertices_m.push_back(outline[i] + hgap);
1410 mesh.
vertices_m.push_back(outline[last] + 2 * hgap);
1412 for (
unsigned int i = 0; i < 6; ++ i) {
1413 mesh.
vertices_m.push_back(outline[i] - 2 * hgap);
1415 for (
unsigned int i = 6; i < 6 + numSteps; ++ i) {
1416 mesh.
vertices_m.push_back(outline[i] - hgap);
1418 for (
unsigned int i = 6 + numSteps; i < 13 + numSteps; ++ i) {
1419 mesh.
vertices_m.push_back(outline[i] - 2 * hgap);
1421 for (
unsigned int i = 13 + numSteps; i < 13 + 2 * numSteps; ++ i) {
1422 mesh.
vertices_m.push_back(outline[i] - hgap);
1424 mesh.
vertices_m.push_back(outline[last] - 2 * hgap);
1429 mesh.
vertices_m.push_back(outline[midIdx + 4]);
1467 for (
unsigned int i = 6; i < 5 + numSteps; ++ i) {
1476 for (
unsigned int i = 0; i < size - 2; ++ i) {
1477 if (i == 4u || i == 5u ||
1478 i == 5 + numSteps || i == 6 + numSteps ||
1479 i == 11 + numSteps || i == 12 + numSteps)
continue;
1481 unsigned int next = (i + 1) % size;
1520 mesh.
decorations_m.push_back(std::make_pair(0.5 * (P1 + P2) - 0.25 * dir1,
1521 0.5 * (P1 + P2) + 0.25 * dir1));
1525 double det = -dir1[0] * dir2[2] + dir1[2] * dir2[0];
1526 inv(0, 0) = -dir2[2] /
det;
1527 inv(0, 2) = dir2[0] /
det;
1529 inv(2, 0) = -dir1[2] /
det;
1530 inv(2, 2) = dir1[0] /
det;
1532 boost::numeric::ublas::vector<double> Tau(3);
1539 Vector_t crossPoint = P1 + Tau[0] * dir1;
1543 Vector_t R = crossPoint - rotationCenter;
1547 gsl_poly_solve_quadratic(
dot(P,P),
1553 std::swap(tau1, tau2);
1555 Vector_t lowerCornerFringeLimit = crossPoint + tau1 * P;
1558 gsl_poly_solve_quadratic(
dot(P,P),
1564 std::swap(tau1, tau2);
1566 Vector_t upperCornerFringeLimit = crossPoint + tau1 * P;
1568 mesh.
decorations_m.push_back(std::make_pair(lowerCornerFringeLimit,
1569 upperCornerFringeLimit));
1576 gsl_poly_solve_quadratic(
dot(P,P),
1584 gsl_poly_solve_quadratic(
dot(P,P),
1594 gsl_poly_solve_quadratic(
dot(P,P),
1602 gsl_poly_solve_quadratic(
dot(P,P),
1610 mesh.
decorations_m.push_back(std::make_pair(lowerCornerFringeLimitEntrance, upperCornerFringeLimitEntrance));
1611 mesh.
decorations_m.push_back(std::make_pair(lowerCornerFringeLimitExit, upperCornerFringeLimitExit));
1656 double entrParam1, entrParam2, entrParam3;
1658 fieldmap_m->get1DProfile1EntranceParam(entrParam1,
1662 std::array<double,2> entFFL;
1663 entFFL[0]=entrParam2-entrParam1;
1664 entFFL[1]=entrParam3-entrParam2;
1676 std::array<double,2> extFFL;
1678 double exitParam1, exitParam2, exitParam3;
1680 fieldmap_m->get1DProfile1ExitParam(exitParam1,
1684 extFFL[0]=exitParam3-exitParam2;
1685 extFFL[1]=exitParam2-exitParam1;
1697 std::vector<Vector_t> outline =
getOutline();
1701 for (
int i : {-1, 1}) {
bool findIdealBendParameters(double chordLength)
double entranceParameter3_m
static OpalData * getInstance()
boost::numeric::ublas::matrix< double > matrix_t
Tps< T > sqrt(const Tps< T > &x)
Square root.
constexpr double c
The velocity of light in m/s.
double tanEntranceAngle_m
std::size_t getNSlices() const
void setFieldBoundaries(double startField, double endField)
bool isPositionInExitField(const Vector_t &R) const
Quaternion conjugate() const
std::vector< Vector_t > getOutline() const
Vector_t rotate(const Vector_t &) const
double designRadius_m
through the bend.
int polyOrderEntry_m
function origin that Enge function ends.
bool setupBendGeometry(double &startField, double &endField)
double startField_m
Dipole field index.
T det(const AntiSymTenzor< T, 3 > &)
item[EANGLE] Entrance edge angle(radians).\item[ROTATION] Rotation of the magnet about its central axis(radians
PETE_TBTree< FnCopysign, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > copysign(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
std::array< double, 2 > getEntranceFringeFieldLength() const
Get entrance fringe field length.
double deltaEndEntry_m
function origin where Enge function starts.
constexpr double two_pi
The value of .
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
double endField_m
Start of magnet field map in s coordinates (m).
Vector_t transformToEntranceRegion(const Vector_t &R) const
virtual bool isInside(const Vector_t &r) const override
gsl_interp_accel * entryFieldAccel_m
CoordinateSystemTrafo toEntranceRegion_m
gsl_spline ** exitFieldValues_m
Vector_t calcCentralField(const Vector_t &R, double deltaX)
double calcGamma() const
Calculate gamma from design energy.
Vektor< double, 3 > Vector_t
double entranceParameter2_m
std::array< double, 2 > getExitFringeFieldLength() const
Get exit fringe field length.
virtual ElementType getType() const override=0
Get element type std::string.
double getChordLength() const
double calcBetaGamma() const
Calculate beta*gamma from design energy.
void enlargeToContainPosition(const Vector_t &position)
Vector_t calcEntranceFringeField(const Vector_t &R, double deltaX)
double widthEntranceFringe_m
End of magnet field map in s coordinates (m).
double calcBendAngle(double chordLength, double radius) const
Calculate bend angle from chord length and design radius.
bool setupDefaultFieldMap()
PartBunchBase< double, 3 > * RefPartBunch_m
void push(Vector_t &R, const Vector_t &P, const double &dt) const
bool calculateMapField(const Vector_t &R, Vector_t &B)
void findBendEffectiveLength(double startField, double endField)
Tps< T > exp(const Tps< T > &x)
Exponential.
bool inMagnetEntranceRegion(const Vector_t &R) const
bool writeBendTrajectories
void initialise(const PartData *ref)
virtual const std::string & getName() const
Get element name.
virtual bool findChordLength(double &chordLength)=0
double getQ() const
Access to reference data.
constexpr double pi
The value of .
double calculateBendAngle()
std::string toUpper(const std::string &str)
virtual bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) override
Apply field to particles with coordinates in magnet frame.
Inform & endl(Inform &inf)
Vector_t transformFrom(const Vector_t &r) const
std::vector< Vector_t > vertices_m
PETE_TBTree< FnArcTan2, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > atan2(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
bool initializeFieldMap()
double getBendAngle() const
double fieldIndex_m
and the exit face of the magnet (radians).
virtual void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField) override
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
double calcDesignRadius(double fieldAmplitude) const
Calculate design radius from design energy and field amplitude.
Vector_t rotateFrom(const Vector_t &r) const
double getEntranceAngle() const
virtual bool applyToReferenceParticle(const Vector_t &R, const Vector_t &P, const double &t, Vector_t &E, Vector_t &B) override
bool isPositionInEntranceField(const Vector_t &R) const
T euclidean_norm(const Vector< T > &)
Euclidean norm.
CoordinateSystemTrafo getBeginToEnd_local() const
double exitAngle_m
Bend design radius (m).
bool getFlagDeleteOnTransverseExit() const
bool inMagnetCentralRegion(const Vector_t &R) const
std::vector< std::pair< Vector_t, Vector_t > > decorations_m
virtual CoordinateSystemTrafo getEdgeToBegin() const
std::string getAuxiliaryOutputDirectory() const
get the name of the the additional data directory
CoordinateSystemTrafo csTrafoGlobal2Local_m
Vector3D cross(const Vector3D &lhs, const Vector3D &rhs)
Vector cross product.
T::PETE_Expr_t::PETE_Return_t prod(const PETE_Expr< T > &expr)
std::string messageHeader_m
double deltaBeginExit_m
Enge function order for entry region.
double sinEntranceAngle_m
double angle_m
Bend angle.
bool inMagnetExitRegion(const Vector_t &R) const
void adjustFringeFields(double ratio)
CoordinateSystemTrafo beginToEnd_lcs_m
MeshData getSurfaceMesh() const
std::vector< Vektor< unsigned int, 3 > > triangles_m
gsl_spline ** entryFieldValues_m
Vector_t calcExitFringeField(const Vector_t &R, double deltaX)
void calcEngeFunction(double zNormalized, const std::vector< double > &engeCoeff, int polyOrder, double &engeFunc, double &engeFuncDeriv, double &engeFuncSecDerivNorm)
virtual double getElementLength() const
Get design length.
void setGapFromFieldMap()
double getFullGap() const
double getRotationAboutZ() const
void setEngeOriginDelta(double delta)
Vector_t transformTo(const Vector_t &r) const
std::vector< double > engeCoeffsEntry_m
Enge coefficients for map entry and exit regions.
void setExitAngle(double exitAngle)
Tps< T > cos(const Tps< T > &x)
Cosine.
PETE_TBTree< FnFmod, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > fmod(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
double cosEntranceAngle_m
Enge function order for entry region.
std::string combineFilePath(std::initializer_list< std::string > ilist)
Fieldmap fieldmap_m
Magnet field map.
void setupPusher(PartBunchBase< double, 3 > *bunch)
virtual CoordinateSystemTrafo getEdgeToEnd() const override
Quaternion getQuaternion(Vector_t u, Vector_t ref)
void calculateRefTrajectory(double &angleX, double &angleY)
const bool fast_m
Flag to turn on fast field calculation.
gsl_interp_accel * exitFieldAccel_m
std::string getInputBasename()
get input file name without extension
virtual void setElementLength(double length)
Set design length.
CoordinateSystemTrafo computeAngleTrafo_m
virtual void goOnline(const double &kineticEnergy) override
void print(Inform &msg, double bendAngleX, double bendAngle)
T isnan(T x)
isnan function with adjusted return type
constexpr double e
The value of .
CoordinateSystemTrafo toExitRegion_m
Inform & level2(Inform &inf)
double designEnergy_m
Bend design energy (eV).
PETE_TUTree< FnCeil, typename T::PETE_Expr_t > ceil(const PETE_Expr< T > &l)
const PartData * getReference() const
double fieldAmplitude_m
Field amplitude.
PETE_TUTree< FnArcSin, typename T::PETE_Expr_t > asin(const PETE_Expr< T > &l)
void setBendEffectiveLength(double startField, double endField)
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
std::vector< Vector_t > refTrajMap_m
Map of reference particle trajectory.
double gap_m
Full vertical gap of the magnets.
virtual void setEntranceAngle(double entranceAngle) override
Tps< T > sin(const Tps< T > &x)
Sine.
void kick(const Vector_t &R, Vector_t &P, const Vector_t &Ef, const Vector_t &Bf, const double &dt) const
BoundingBox getBoundingBoxInLabCoords() const override
int polyOrderExit_m
function origin that Enge function ends.
static Fieldmap getFieldmap(std::string Filename, bool fast=false)
std::pair< ApertureType, std::vector< double > > aperture_m
double calcFieldAmplitude(double radius) const
Calculate field amplitude from design energy and radius.
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
CoordinateSystemTrafo beginToEnd_m
double estimateFieldAdjustmentStep(double actualBendAngle)
T isinf(T x)
isinf function with adjusted return type
double deltaEndExit_m
function origin that Enge function starts.
void readFieldMap(Inform &msg)
std::vector< double > engeCoeffsExit_m
void setNSlices(const std::size_t &nSlices)
double entranceParameter1_m
Vector_t transformToExitRegion(const Vector_t &R) const