OPALX (Object Oriented Parallel Accelerator Library for Exascale) MINIorX
OPALX
MultipoleT.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017, Titus Dascalu
3 * Copyright (c) 2018, Martin Duy Tat
4 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * 3. Neither the name of STFC nor the names of its contributors may be used to
13 * endorse or promote products derived from this software without specific
14 * prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
32
33#include <gsl/gsl_math.h>
34#include "MultipoleT.h"
39
40using namespace endfieldmodel;
41
42MultipoleT::MultipoleT(const std::string& name)
43 : Component(name),
44 fringeField_l(endfieldmodel::Tanh()),
45 fringeField_r(endfieldmodel::Tanh()),
46 maxOrder_m(5),
47 maxOrderX_m(10),
48 transMaxOrder_m(0),
49 planarArcGeometry_m(1., 1.),
50 length_m(1.0),
51 angle_m(0.0),
52 entranceAngle_m(0.0),
53 rotation_m(0.0),
54 variableRadius_m(false),
55 boundingBoxLength_m(0.0),
56 verticalApert_m(0.5),
57 horizApert_m(0.5) {
58}
59
61 : Component(right),
62 fringeField_l(right.fringeField_l),
63 fringeField_r(right.fringeField_r),
64 maxOrder_m(right.maxOrder_m),
65 maxOrderX_m(right.maxOrderX_m),
66 recursion_VarRadius_m(right.recursion_VarRadius_m),
67 recursion_ConstRadius_m(right.recursion_ConstRadius_m),
68 transMaxOrder_m(right.transMaxOrder_m),
69 transProfile_m(right.transProfile_m),
70 planarArcGeometry_m(right.planarArcGeometry_m),
71 length_m(right.length_m),
72 angle_m(right.angle_m),
73 entranceAngle_m(right.entranceAngle_m),
74 rotation_m(right.rotation_m),
75 variableRadius_m(right.variableRadius_m),
76 boundingBoxLength_m(right.boundingBoxLength_m),
77 verticalApert_m(right.verticalApert_m),
78 horizApert_m(right.horizApert_m),
79 dummy() {
81}
82
84}
85
87 MultipoleT* newMultipole = new MultipoleT(*this);
88 newMultipole->initialise();
89 return newMultipole;
90}
91
93 RefPartBunch_m = nullptr;
94}
95
97 const Vector_t<double, 3>& R, const Vector_t<double, 3>& /*P*/, const double& /*t*/,
100 Vector_t<double, 3> R_prime = rotateFrame(R);
102 // R_prime[2] *= -1; //OPAL uses different sign convention...
103 Vector_t<double, 3> X = R_prime;
104 R_prime = transformCoords(X);
105 if (insideAperture(R_prime)) {
107 double theta;
108 double prefactor = (length_m / angle_m)
111 if (angle_m == 0.0) {
112 theta = 0.0;
113 } else if (!variableRadius_m) {
114 theta = R_prime[2] * angle_m / length_m;
115 } else { // variableRadius_m == true
116 theta =
118 * log(cosh((R_prime[2] + fringeField_l.getX0()) / fringeField_l.getLambda()))
120 * log(cosh((R_prime[2] - fringeField_r.getX0()) / fringeField_r.getLambda()));
121 theta /= prefactor;
122 }
123 double Bx = getBx(R_prime);
124 double Bs = getBs(R_prime);
125 B[0] = Bx * cos(theta) - Bs * sin(theta);
126 B[2] = Bx * sin(theta) + Bs * cos(theta);
127 B[1] = getBz(R_prime);
128 // B[2] *= -1; //OPAL uses different sign convention
129 return false;
130 } else {
131 for (int i = 0; i < 3; i++) {
132 B[i] = 0.0;
133 }
135 }
136}
137
139 const size_t& i, const double& t, Vector_t<double, 3>& E, Vector_t<double, 3>& B) {
140 std::shared_ptr<ParticleContainer_t> pc = RefPartBunch_m->getParticleContainer();
141 auto Rview = pc->R.getView();
142 auto Pview = pc->P.getView();
143
144 const Vector_t<double, 3> R = Rview(i);
145 const Vector_t<double, 3> P = Pview(i);
146
147 return apply(R(i), P(i), t, E, B);
148}
149
151 Vector_t<double, 3> R_prime(3), R_pprime(3);
156 // 1st rotation
157 R_prime[0] = R[0] * cos(rotation_m) + R[1] * sin(rotation_m);
158 R_prime[1] = -R[0] * sin(rotation_m) + R[1] * cos(rotation_m);
159 R_prime[2] = R[2];
160 // 2nd rotation
161 R_pprime[0] = R_prime[2] * sin(entranceAngle_m) + R_prime[0] * cos(entranceAngle_m);
162 R_pprime[1] = R_prime[1];
163 R_pprime[2] = R_prime[2] * cos(entranceAngle_m) - R_prime[0] * sin(entranceAngle_m);
164 return R_pprime;
165}
166
172 Vector_t<double, 3> B_prime(3);
173 B_prime[0] = B[0] * cos(rotation_m) + B[1] * sin(rotation_m);
174 B_prime[1] = -B[0] * sin(rotation_m) + B[1] * cos(rotation_m);
175 B_prime[2] = B[2];
176 return B_prime;
177}
178
180 if (std::abs(R[1]) <= verticalApert_m / 2. && std::abs(R[0]) <= horizApert_m / 2.) {
181 return true;
182 } else {
183 return false;
184 }
185}
186
189 // If radius is constant
190 if (!variableRadius_m) {
191 double radius = length_m / angle_m;
192 // Transform from Cartesian to Frenet-Serret along the magnet
193 double alpha = atan(R[2] / (R[0] + radius));
194 if (alpha != 0.0 && angle_m != 0.0) {
195 X[0] = R[2] / sin(alpha) - radius;
196 X[1] = R[1];
197 X[2] = radius * alpha; // + boundingBoxLength_m;
198 } else {
199 X[0] = R[0];
200 X[1] = R[1];
201 X[2] = R[2]; // + boundingBoxLength_m;
202 }
203 } else {
204 // If radius is variable
206 R[0], R[1], R[2], fringeField_l.getX0(), fringeField_l.getLambda(),
208 std::vector<double> r = t.getTransformation();
209 X[0] = r[0];
210 X[1] = r[1];
211 X[2] = r[2];
212 }
213 return X;
214}
215
216void MultipoleT::setMaxOrder(std::size_t maxOrder) {
217 if (variableRadius_m && angle_m != 0.0) {
218 std::size_t N = recursion_VarRadius_m.size();
219 while (maxOrder >= N) {
223 recursion_VarRadius_m.push_back(r);
224 N = recursion_VarRadius_m.size();
225 }
226 } else if (!variableRadius_m && angle_m != 0.0) {
227 std::size_t N = recursion_ConstRadius_m.size();
228 while (maxOrder >= N) {
229 polynomial::RecursionRelation r(N, 2 * (N + maxOrderX_m + 1));
232 recursion_ConstRadius_m.push_back(r);
233 N = recursion_ConstRadius_m.size();
234 }
235 }
236 maxOrder_m = maxOrder;
237}
238
239void MultipoleT::setTransProfile(std::size_t n, double dTn) {
240 if (n > transMaxOrder_m) {
241 transMaxOrder_m = n;
242 transProfile_m.resize(n + 1, 0.0);
243 }
244 transProfile_m[n] = dTn;
245}
246
247bool MultipoleT::setFringeField(double s0, double lambda_l, double lambda_r) {
248 fringeField_l.Tanh::setLambda(lambda_l);
249 fringeField_l.Tanh::setX0(s0);
250 fringeField_l.Tanh::setTanhDiffIndices(2 * maxOrder_m + 1);
251
252 fringeField_r.Tanh::setLambda(lambda_r);
253 fringeField_r.Tanh::setX0(s0);
254 fringeField_r.Tanh::setTanhDiffIndices(2 * maxOrder_m + 1);
255
256 return true;
257}
258
263 double Bz = 0.0;
264 if (angle_m == 0.0) {
265 // Straight geometry -> Use corresponding field expansion directly
266 for (std::size_t n = 0; n <= maxOrder_m; n++) {
267 double f_n = 0.0;
268 for (std::size_t i = 0; i <= n; i++) {
269 f_n += gsl_sf_choose(n, i) * getTransDeriv(2 * i, R[0])
270 * getFringeDeriv(2 * n - 2 * i, R[2]);
271 }
272 f_n *= gsl_sf_pow_int(-1.0, n);
273 Bz += gsl_sf_pow_int(R[1], 2 * n) / gsl_sf_fact(2 * n) * f_n;
274 }
275 } else {
276 if (variableRadius_m == true and getFringeDeriv(0, R[2]) < 1.0e-12) {
277 // Return 0 if end of fringe field is reached
278 // This is to avoid functions being called at infinite radius
279 return 0.0;
280 }
281 // Curved geometry -> Use full machinery of differential operators
282 for (std::size_t n = 0; n <= maxOrder_m; n++) {
283 double f_n = getFn(n, R[0], R[2]);
284 Bz += gsl_sf_pow_int(R[1], 2 * n) / gsl_sf_fact(2 * n) * f_n;
285 }
286 }
287 return Bz;
288}
289
294 double Bx = 0.0;
295 if (angle_m == 0.0) {
296 // Straight geometry -> Use corresponding field expansion directly
297 for (std::size_t n = 0; n <= maxOrder_m; n++) {
298 double f_n = 0.0;
299 for (std::size_t i = 0; i <= n; i++) {
300 f_n += gsl_sf_choose(n, i) * getTransDeriv(2 * i + 1, R[0])
301 * getFringeDeriv(2 * n - 2 * i, R[2]);
302 }
303 f_n *= gsl_sf_pow_int(-1.0, n);
304 Bx += gsl_sf_pow_int(R[1], 2 * n + 1) / gsl_sf_fact(2 * n + 1) * f_n;
305 }
306 } else {
307 if (variableRadius_m == true and getFringeDeriv(0, R[2]) < 1.0e-12) {
308 // Return 0 if end of fringe field is reached
309 // This is to avoid functions being called at infinite radius
310 return 0.0;
311 }
312 // Curved geometry -> Use full machinery of differential operators
313 for (std::size_t n = 0; n <= maxOrder_m; n++) {
314 double partialX_fn = getFnDerivX(n, R[0], R[2]);
315 Bx += partialX_fn * gsl_sf_pow_int(R[1], 2 * n + 1) / gsl_sf_fact(2 * n + 1);
316 }
317 }
318 return Bx;
319}
320
325 double Bs = 0.0;
326 if (angle_m == 0.0) {
327 // Straight geometry -> Use corresponding field expansion directly
328 for (std::size_t n = 0; n <= maxOrder_m; n++) {
329 double f_n = 0.0;
330 for (std::size_t i = 0; i <= n; i++) {
331 f_n += gsl_sf_choose(n, i) * getTransDeriv(2 * i, R[0])
332 * getFringeDeriv(2 * n - 2 * i + 1, R[2]);
333 }
334 f_n *= gsl_sf_pow_int(-1.0, n);
335 Bs += gsl_sf_pow_int(R[1], 2 * n + 1) / gsl_sf_fact(2 * n + 1) * f_n;
336 }
337 } else {
338 if (variableRadius_m == true and getFringeDeriv(0, R[2]) < 1.0e-12) {
339 // Return 0 if end of fringe field is reached
340 // This is to avoid functions being called at infinite radius
341 return 0.0;
342 }
343 // Curved geometry -> Use full machinery of differential operators
344 for (std::size_t n = 0; n <= maxOrder_m; n++) {
345 double partialS_fn = getFnDerivS(n, R[0], R[2]);
346 Bs += partialS_fn * gsl_sf_pow_int(R[1], 2 * n + 1) / gsl_sf_fact(2 * n + 1);
347 }
348 Bs /= getScaleFactor(R[0], R[2]);
349 }
350 return Bs;
351}
352
353double MultipoleT::getFringeDeriv(int n, double s) {
354 if (n <= 10) {
355 return (fringeField_l.getTanh(s, n) - fringeField_r.getNegTanh(s, n)) / 2;
356 } else {
358 s, fringeField_l.Tanh::getX0(), fringeField_l.Tanh::getLambda(),
359 fringeField_r.Tanh::getLambda(), n);
360 }
361}
362
363double MultipoleT::getTransDeriv(std::size_t n, double x) {
369 double func = 0;
370 std::vector<double> temp = transProfile_m;
371 if (n <= transMaxOrder_m) {
372 if (n != 0) {
373 for (std::size_t i = 1; i <= n; i++) {
374 for (std::size_t j = 0; j <= transMaxOrder_m; j++) {
375 if (j <= transMaxOrder_m - i) {
376 // Move terms to the left and multiply by power
377 temp[j] = temp[j + 1] * (j + 1);
378 } else {
379 // Put 0 at the end for missing higher powers
380 temp[j] = 0.0;
381 }
382 }
383 }
384 }
385 // Now use the vector to calculate value of the function
386 for (std::size_t k = 0; k <= transMaxOrder_m; k++) {
387 func += temp[k] * gsl_sf_pow_int(x, k);
388 }
389 }
390 return func;
391}
392
394 if (transMaxOrder_m < 1) {
395 transProfile_m.resize(1, 0.);
396 }
397 transProfile_m[0] = B0;
398}
399
401 visitor.visitMultipoleT(*this);
402}
403
404void MultipoleT::getDimensions(double& /*zBegin*/, double& /*zEnd*/) const {
405}
406
407void MultipoleT::setAperture(double vertAp, double horizAp) {
408 verticalApert_m = vertAp;
409 horizApert_m = horizAp;
410}
411
412std::vector<double> MultipoleT::getAperture() const {
413 std::vector<double> temp(2, 0.0);
414 temp[0] = verticalApert_m;
415 temp[1] = horizApert_m;
416 return temp;
417}
418
419std::vector<double> MultipoleT::getFringeLength() const {
420 std::vector<double> temp(2, 0.0);
421 temp[0] = fringeField_l.getLambda();
422 temp[1] = fringeField_r.getLambda();
423 return temp;
424}
425
426double MultipoleT::getRadius(double s) {
427 double centralRadius = length_m / angle_m;
428 if (!variableRadius_m) {
429 return centralRadius;
430 }
431 if (getFringeDeriv(0, s) != 0.0) {
432 return centralRadius * getFringeDeriv(0, 0) / getFringeDeriv(0, s);
433 } else {
434 return -1; // Return -1 if radius is infinite
435 }
436}
437
438double MultipoleT::getScaleFactor(double x, double s) {
439 if (!variableRadius_m) {
440 return 1 + x * angle_m / length_m;
441 } else {
442 return 1 + x / getRadius(s);
443 }
444}
445
446double MultipoleT::getFnDerivX(std::size_t n, double x, double s) {
447 if (n == 0) {
448 return getTransDeriv(1, x) * getFringeDeriv(0, s);
449 }
450 double deriv = 0.0;
451 double stepSize = 1e-3;
452 deriv += 1. * getFn(n, x - 2. * stepSize, s);
453 deriv += -8. * getFn(n, x - stepSize, s);
454 deriv += 8. * getFn(n, x + stepSize, s);
455 deriv += -1. * getFn(n, x + 2. * stepSize, s);
456 deriv /= 12 * stepSize;
457 return deriv;
458}
459
460double MultipoleT::getFnDerivS(std::size_t n, double x, double s) {
461 if (n == 0) {
462 return getTransDeriv(0, x) * getFringeDeriv(1, s);
463 }
464 double deriv = 0.0;
465 double stepSize = 1e-3;
466 deriv += 1. * getFn(n, x, s - 2. * stepSize);
467 deriv += -8. * getFn(n, x, s - stepSize);
468 deriv += 8. * getFn(n, x, s + stepSize);
469 deriv += -1. * getFn(n, x, s + 2. * stepSize);
470 deriv /= 12 * stepSize;
471 return deriv;
472}
473
474double MultipoleT::getFn(std::size_t n, double x, double s) {
475 if (n == 0) {
476 return getTransDeriv(0, x) * getFringeDeriv(0, s);
477 }
478 if (!variableRadius_m) {
479 double rho = length_m / angle_m;
480 double func = 0.0;
481
482 for (std::size_t j = 0; j <= recursion_ConstRadius_m.at(n).getMaxSDerivatives(); j++) {
483 double FringeDerivj = getFringeDeriv(2 * j, s);
484 for (std::size_t i = 0; i <= recursion_ConstRadius_m.at(n).getMaxXDerivatives(); i++) {
485 if (recursion_ConstRadius_m.at(n).isPolynomialZero(i, j)) {
486 continue;
487 }
488 func += (recursion_ConstRadius_m.at(n).evaluatePolynomial(x / rho, i, j)
489 * getTransDeriv(i, x) * FringeDerivj)
490 / gsl_sf_pow_int(rho, 2 * n - i - 2 * j);
491 }
492 }
493 func *= gsl_sf_pow_int(-1.0, n);
494 return func;
495 } else {
496 double rho = length_m / angle_m;
497 double S_0 = getFringeDeriv(0, 0);
498 double y = getFringeDeriv(0, s) / (S_0 * rho);
499 double func = 0.0;
500 std::vector<double> fringeDerivatives;
501 for (std::size_t j = 0; j <= recursion_VarRadius_m.at(n).getMaxSDerivatives(); j++) {
502 fringeDerivatives.push_back(getFringeDeriv(j, s) / (S_0 * rho));
503 }
504 for (std::size_t i = 0; i <= recursion_VarRadius_m.at(n).getMaxXDerivatives(); i++) {
505 double temp = 0.0;
506 for (std::size_t j = 0; j <= recursion_VarRadius_m.at(n).getMaxSDerivatives(); j++) {
507 temp +=
508 recursion_VarRadius_m.at(n).evaluatePolynomial(x, y, i, j, fringeDerivatives)
509 * fringeDerivatives.at(j);
510 }
511 func += temp * getTransDeriv(i, x);
512 }
513 func *= gsl_sf_pow_int(-1.0, n) * S_0 * rho;
514 return func;
515 }
516}
517
521}
522
523void MultipoleT::initialise(PartBunch_t* bunch, double& /*startField*/, double& /*endField*/) {
524 RefPartBunch_m = bunch;
525 initialise();
526}
527
528bool MultipoleT::bends() const {
529 return (transProfile_m[0] != 0);
530}
531
533 return planarArcGeometry_m;
534}
535
537 return planarArcGeometry_m;
538}
539
541 return dummy;
542}
543
545 return dummy;
546}
PartBunch< PLayout_t< double, 3 >, double, 3 > PartBunch_t
double integrate(const double &a, const double &s0, const double &lambdaleft, const double &lambdaright, const int &n)
Perform Cauchy's integral to find derivative.
Definition: tanhDeriv.cpp:66
constexpr double alpha
The fine structure constant, no dimension.
Definition: Physics.h:72
constexpr double e
The value of.
Definition: Physics.h:39
virtual void visitMultipoleT(const MultipoleT &)=0
Apply the algorithm to an arbitrary multipole.
Interface for a single beam element.
Definition: Component.h:50
PartBunch_t * RefPartBunch_m
Definition: Component.h:185
bool getFlagDeleteOnTransverseExit() const
Definition: ElementBase.h:574
Calculate the Tanh function (e.g.
Definition: Tanh.h:48
double getNegTanh(double x, int n) const
Returns the value of tanh((x-x0)/lambda) or its derivative.
Definition: Tanh.cpp:61
double getX0() const
Return x0 (flat top length)
Definition: Tanh.h:104
double getLambda() const
Return lambda (end length)
Definition: Tanh.h:101
double getTanh(double x, int n) const
Returns the value of tanh((x+x0)/lambda) or its derivative.
Definition: Tanh.cpp:50
std::vector< double > transProfile_m
List of transverse profile coefficients.
Definition: MultipoleT.h:264
void setDipoleConstant(double B0)
Set the dipole constant B_0.
Definition: MultipoleT.cpp:393
std::size_t transMaxOrder_m
Highest power in given mid-plane field.
Definition: MultipoleT.h:262
double horizApert_m
Definition: MultipoleT.h:296
void setAperture(double vertAp, double horizAp)
Set the aperture dimensions This element only supports a rectangular aperture.
Definition: MultipoleT.cpp:407
BMultipoleField dummy
Not implemented.
Definition: MultipoleT.h:298
Vector_t< double, 3 > rotateFrameInverse(Vector_t< double, 3 > &B)
Inverse of the 1st rotation in rotateFrame() method Used to rotate B field back to global coordinate...
Definition: MultipoleT.cpp:167
Vector_t< double, 3 > transformCoords(const Vector_t< double, 3 > &R)
Transform to Frenet-Serret coordinates for sector magnets.
Definition: MultipoleT.cpp:187
double getTransDeriv(std::size_t n, double x)
Returns the value of the transverse field n-th derivative at x.
Definition: MultipoleT.cpp:363
double entranceAngle_m
Definition: MultipoleT.h:283
void setMaxOrder(std::size_t maxOrder)
Set the number of terms used in calculation of field components Maximum power of z in Bz is 2 * maxO...
Definition: MultipoleT.cpp:216
std::vector< polynomial::RecursionRelationTwo > recursion_VarRadius_m
Objects for storing differential operator acting on Fn.
Definition: MultipoleT.h:259
void initialise()
Initialises the geometry.
Definition: MultipoleT.cpp:518
bool apply(const Vector_t< double, 3 > &R, const Vector_t< double, 3 > &P, const double &t, Vector_t< double, 3 > &E, Vector_t< double, 3 > &B) override
Calculate the field at some arbitrary position If particle is outside field map true is returned,...
Definition: MultipoleT.cpp:96
endfieldmodel::Tanh fringeField_r
Definition: MultipoleT.h:251
endfieldmodel::Tanh fringeField_l
Definition: MultipoleT.h:250
double getBz(const Vector_t< double, 3 > &R)
Definition: MultipoleT.cpp:259
ElementBase * clone() const override
Inheritable copy constructor.
Definition: MultipoleT.cpp:86
bool insideAperture(const Vector_t< double, 3 > &R)
Tests if inside the magnet.
Definition: MultipoleT.cpp:179
~MultipoleT()
Destructor.
Definition: MultipoleT.cpp:83
EMField & getField() override
Return a dummy field value.
Definition: MultipoleT.cpp:540
double getScaleFactor(double x, double s)
Returns the scale factor .
Definition: MultipoleT.cpp:438
double getFnDerivX(std::size_t n, double x, double s)
Calculate partial derivative of fn wrt x using a 5-point finite difference formula Error of order st...
Definition: MultipoleT.cpp:446
void accept(BeamlineVisitor &visitor) const override
Accept a beamline visitor.
Definition: MultipoleT.cpp:400
double verticalApert_m
Assume rectangular aperture with these dimensions.
Definition: MultipoleT.h:295
double rotation_m
Definition: MultipoleT.h:284
void getDimensions(double &zBegin, double &zEnd) const override
Not implemented.
Definition: MultipoleT.cpp:404
double angle_m
Definition: MultipoleT.h:282
double getFnDerivS(std::size_t n, double x, double s)
Calculate partial derivative of fn wrt s using a 5-point finite difference formuln Error of order ste...
Definition: MultipoleT.cpp:460
std::size_t maxOrderX_m
Highest order of polynomial expansions in x.
Definition: MultipoleT.h:257
double getRadius(double s)
Radius of curvature If radius of curvature is infinite, -1 is returned If radius is constant,...
Definition: MultipoleT.cpp:426
std::vector< polynomial::RecursionRelation > recursion_ConstRadius_m
Definition: MultipoleT.h:260
double getBx(const Vector_t< double, 3 > &R)
Get field component methods.
Definition: MultipoleT.cpp:290
double length_m
Magnet parameters.
Definition: MultipoleT.h:281
double getFn(std::size_t n, double x, double s)
Calculate fn(x, s) by expanding the differential operator (from Laplacian and scalar potential) in te...
Definition: MultipoleT.cpp:474
bool setFringeField(double s0, double lambda_left, double lambda_right)
Set fringe field model Tanh model used here .
Definition: MultipoleT.cpp:247
void initialise(PartBunch_t *, double &startField, double &endField) override
Initialise the MultipoleT.
void finalise() override
Finalise the MultipoleT - sets bunch to nullptr.
Definition: MultipoleT.cpp:92
double getFringeDeriv(int n, double s)
Returns the value of the fringe field n-th derivative at s.
Definition: MultipoleT.cpp:353
PlanarArcGeometry planarArcGeometry_m
Geometry.
Definition: MultipoleT.h:266
bool bends() const override
Return true if dipole component not zero.
Definition: MultipoleT.cpp:528
std::vector< double > getAperture() const
Get the aperture dimensions Returns a vector of 2 doubles.
Definition: MultipoleT.cpp:412
void setTransProfile(std::size_t n, double Bn)
Set transverse profile T(x) T(x) = B_0 + B1 x + B2 x^2 + B3 x^3 + ...
Definition: MultipoleT.cpp:239
std::size_t maxOrder_m
Field expansion parameters Number of terms in z expansion used in calculating field components.
Definition: MultipoleT.h:255
bool variableRadius_m
Variable radius flag.
Definition: MultipoleT.h:286
double boundingBoxLength_m
Distance between centre of magnet and entrance.
Definition: MultipoleT.h:288
MultipoleT(const std::string &name)
Constructor.
Definition: MultipoleT.cpp:42
Vector_t< double, 3 > rotateFrame(const Vector_t< double, 3 > &R)
Rotate frame for skew elements Consecutive rotations: 1st -> about central axis 2nd -> azimuthal rota...
Definition: MultipoleT.cpp:150
double getBs(const Vector_t< double, 3 > &R)
Definition: MultipoleT.cpp:321
PlanarArcGeometry & getGeometry() override
Return the cell geometry.
Definition: MultipoleT.cpp:532
std::vector< double > getFringeLength() const
Return vector of 2 doubles [left fringe length, right fringelength].
Definition: MultipoleT.cpp:419
std::vector< double > getTransformation() const
Returns a list of transformed coordinates.
void resizeX(const std::size_t &xDerivatives)
Change number of x-derivatives to xDerivatives.
void truncate(std::size_t highestXorder)
Truncate series in x at highestXorder.
void truncate(std::size_t highestXorder)
Truncate series in x at highestXorder.
void resizeX(const std::size_t &xDerivatives)
Change number of x-derivatives to xDerivatives.
A simple arc in the XZ plane.
void setCurvature(double)
Set curvature.
virtual void setElementLength(double)
Set length.
Abstract base class for electromagnetic fields.
Definition: EMField.h:188