OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
TransportMapper.cpp
Go to the documentation of this file.
1 // ------------------------------------------------------------------------
2 // $RCSfile: TransportMapper.cpp,v $
3 // ------------------------------------------------------------------------
4 // $Revision: 1.4 $
5 // ------------------------------------------------------------------------
6 // Copyright: see Copyright.readme
7 // ------------------------------------------------------------------------
8 //
9 // Class: TransportMapper
10 // The visitor class for building a transport map for a beamline using
11 // transport maps for all elements.
12 //
13 // ------------------------------------------------------------------------
14 //
15 // $Date: 2000/05/03 08:16:30 $
16 // $Author: opal $
17 //
18 // ------------------------------------------------------------------------
19 
21 
24 #include "AbsBeamline/Corrector.h"
25 #include "AbsBeamline/Diagnostic.h"
26 #include "AbsBeamline/Degrader.h"
27 #include "AbsBeamline/Drift.h"
30 #include "AbsBeamline/Lambertson.h"
31 #include "AbsBeamline/Monitor.h"
32 #include "AbsBeamline/Multipole.h"
33 #include "AbsBeamline/Patch.h"
34 #include "AbsBeamline/Probe.h"
35 #include "AbsBeamline/RBend.h"
36 #include "AbsBeamline/RFCavity.h"
38 #include "AbsBeamline/SBend.h"
39 #include "AbsBeamline/Separator.h"
40 #include "AbsBeamline/Septum.h"
41 #include "AbsBeamline/Solenoid.h"
44 
49 #include "Fields/BMultipoleField.h"
50 #include "FixedAlgebra/FTpsMath.h"
51 #include "FixedAlgebra/FVps.h"
54 #include "Physics/Physics.h"
55 #include <cmath>
56 
57 using Physics::c;
58 
61 
62 
63 // Class TransportMapper
64 // ------------------------------------------------------------------------
65 
67  const PartData &reference,
68  bool revBeam, bool revTrack):
69  AbstractMapper(beamline, reference, revBeam, revTrack)
70 {}
71 
72 
74 {}
75 
76 
78  for(int i = 0; i < 6; ++i) {
79  for(int j = 0; j <= 6; ++j) {
80  map[i][j] = itsMap[i][j];
81  }
82  }
83 }
84 
85 
87  map = itsMap;
88 }
89 
90 
92  map = FVps<double, 6>(itsMap);
93 }
94 
95 
97  for(int i = 0; i < 6; ++i) {
98  for(int j = 0; j <= 6; ++j) {
99  itsMap[i][j] = map[i][j];
100  }
101 
102  for(int j = 7; j < 28; ++j) {
103  itsMap[i][j] = 0.0;
104  }
105  }
106 }
107 
108 
110  itsMap = map;
111 }
112 
113 
116 }
117 
118 
120  // *** MISSING *** Map for beam-beam.
121 }
122 
124  // *** MISSING *** Map for beam Stripping.
125 }
126 
129 }
130 
131 
133  FVps<double, 6> map(itsMap);
136 }
137 
138 
140  // Drift through first half of length.
141  double length = flip_s * corr.getElementLength();
142  if(length) applyDrift(length / 2.0);
143 
144  // Apply kick.
145  double scale = (flip_B * itsReference.getQ() * c) / itsReference.getP();
146  const BDipoleField &field = corr.getField();
147  itsMap[PX] -= field.getBy() * scale;
148  itsMap[PY] += field.getBx() * scale;
149 
150  // Drift through second half of length.
151  if(length) applyDrift(length / 2.0);
152 }
153 
156 }
157 
160 }
161 
162 
163 void TransportMapper::visitDrift(const Drift &drift) {
165 }
166 
169 }
170 
172  // Assume the particle go through the magnet's window.
174 }
175 
176 
178  // Do nothing.
179 }
180 
181 
184 }
185 
186 
188  double length = flip_s * multipole.getElementLength();
189  double scale = (flip_B * itsReference.getQ() * c) / itsReference.getP();
190  const BMultipoleField &field = multipole.getField();
191 
192  if(length) {
193  // Normal case: Finite-length multipole, field coefficients are B.
194  applyMultipoleBody(length, length, field, scale);
195  } else {
196  // Special case: Thin multipole, field coefficients are integral(B*dl).
197  scale *= flip_s;
198  applyThinMultipole(field, scale);
199  }
200 }
201 
202 
203 void TransportMapper::visitPatch(const Patch &patch) {
204  Euclid3D transform = patch.getPatch();
205  if(back_path) transform = Inverse(transform);
206  applyTransform(transform, 0.0);
207 }
209  // Do nothing.
210 }
211 
212 
214  const RBendGeometry &geometry = bend.getGeometry();
215  double length = flip_s * geometry.getElementLength();
216  double scale = (flip_B * itsReference.getQ() * c) / itsReference.getP();
217  const BMultipoleField &field = bend.getField();
218 
219  if(length == 0.0) {
220  double half_angle = flip_s * geometry.getBendAngle() / 2.0;
221  Euclid3D rotat = Euclid3D::YRotation(- half_angle);
222 
223  // Transform from in-plane to mid-plane.
224  applyTransform(rotat, 0.0);
225 
226  // Apply multipole kick.
227  applyThinMultipole(field, scale);
228 
229  // Transform from mid-plane to out-plane.
230  applyTransform(rotat, 0.0);
231  } else {
232  double refLength = flip_s * geometry.getArcLength();
233 
234  if(back_path) {
235  // Transform from global to local.
236  applyTransform(Inverse(geometry.getExitPatch()), 0.0);
237 
238  // Apply entrance fringe field.
239  applyEntranceFringe(bend.getExitFaceRotation(), field, scale);
240 
241  // Traverse rbend body.
242  applyMultipoleBody(length, refLength, field, scale);
243 
244  // Apply exit fringe field.
245  applyExitFringe(bend.getEntryFaceRotation(), field, scale);
246 
247  // Apply rotation local to global.
248  applyTransform(Inverse(geometry.getEntrancePatch()), 0.0);
249  } else {
250  // Apply rotation global to local.
251  applyTransform(geometry.getEntrancePatch(), 0.0);
252 
253  // Apply entrance fringe field.
254  applyEntranceFringe(bend.getEntryFaceRotation(), field, scale);
255 
256  // Traverse rbend body.
257  applyMultipoleBody(length, refLength, field, scale);
258 
259  // Apply exit fringe field.
260  applyExitFringe(bend.getExitFaceRotation(), field, scale);
261 
262  // Apply rotation local to global.
263  applyTransform(geometry.getExitPatch(), 0.0);
264  }
265  }
266 }
267 
268 
270  // Drift through half length.
271  double length = flip_s * as.getElementLength();
272  if(length) applyDrift(length / 2.0);
273 
274  // Apply accelerating voltage.
275  TptFun time = itsMap[T] / (c * itsReference.getBeta());
276  double peak = flip_s * as.getAmplitude() / itsReference.getP();
277  TptFun phase = as.getPhase() + as.getFrequency() * time;
278  itsMap[PT] += peak * sin(phase);
279 
280  // Drift through half length.
281  if(length) applyDrift(length / 2.0);
282 }
283 
284 
286  // *** MISSING *** Map for RF Quadrupole.
288 }
289 
290 
292  const PlanarArcGeometry &geometry = bend.getGeometry();
293  double length = flip_s * geometry.getElementLength();
294  double scale = (flip_B * itsReference.getQ() * c) / itsReference.getP();
295  const BMultipoleField &field = bend.getField();
296 
297  if(length == 0.0) {
298  double half_angle = geometry.getBendAngle() / 2.0;
299  Euclid3D rotat = Euclid3D::YRotation(- half_angle);
300 
301  // Transform from in-plane to mid-plane.
302  applyTransform(rotat, 0.0);
303 
304  // Apply multipole kick.
305  // Curvature is unknown for zero-length bend.
306  applyThinMultipole(field, scale);
307 
308  // Transform from mid-plane to out-plane.
309  applyTransform(rotat, 0.0);
310  } else {
311  double h = geometry.getCurvature();
312  double refLength = flip_s * geometry.getArcLength();
313 
314  if(back_path) {
315  // Apply entrance fringe field.
316  applyEntranceFringe(bend.getExitFaceRotation(), field, scale);
317 
318  // Traverse sbend body.
319  applySBendBody(length, refLength, h, field, scale);
320 
321  // Apply exit fringe field.
322  applyExitFringe(bend.getEntryFaceRotation(), field, scale);
323  } else {
324  // Apply entrance fringe field.
325  applyEntranceFringe(bend.getEntryFaceRotation(), field, scale);
326 
327  // Traverse sbend body.
328  applySBendBody(length, refLength, h, field, scale);
329 
330  // Apply exit fringe field.
331  applyExitFringe(bend.getExitFaceRotation(), field, scale);
332  }
333  }
334 }
335 
336 
338  // Drift through first half of length.
339  double length = flip_s * sep.getElementLength();
340  if(length) applyDrift(length / 2.0);
341 
342  // Electrostatic kick.
343  double scale = (length * itsReference.getQ()) / itsReference.getP();
344  double Ex = scale * sep.getEx();
345  double Ey = scale * sep.getEy();
346  TptFun pt = 1.0 + itsMap[PT];
347  itsMap[PX] += Ex / pt;
348  itsMap[PY] += Ey / pt;
349 
350  if(length) applyDrift(length / 2.0);
351 }
352 
353 
355  // Assume the particle go through the magnet's window.
357 }
358 
359 
361  double length = flip_s * solenoid.getElementLength();
362 
363  if(length) {
364  double ks = (flip_B * itsReference.getQ() * solenoid.getBz() * c) /
365  (2.0 * itsReference.getP());
366 
367  if(ks) {
368  double kin = itsReference.getM() / itsReference.getP();
369  double refTime = length / itsReference.getBeta();
370  TptFun pt = itsMap[PT] + 1.0;
371  TptFun px = itsMap[PX] + ks * itsMap[Y];
372  TptFun py = itsMap[PY] - ks * itsMap[X];
373  TptFun pz = sqrt(pt * pt - px * px - py * py);
374  TptFun E = sqrt(pt * pt + kin * kin);
375  TptFun k = ks / pz;
376 
377  TptFun C = cos(k * length);
378  TptFun S = sin(k * length);
379 
380  TptFun xt = C * itsMap[X] + S * itsMap[Y];
381  TptFun yt = C * itsMap[Y] - S * itsMap[X];
382  TptFun pxt = C * itsMap[PX] + S * itsMap[PY];
383  TptFun pyt = C * itsMap[PY] - S * itsMap[PX];
384 
385  itsMap[X] = C * xt + (S / ks) * pxt;
386  itsMap[Y] = C * yt + (S / ks) * pyt;
387  itsMap[PX] = C * pxt - (S * ks) * xt;
388  itsMap[PY] = C * pyt - (S * ks) * yt;
389  itsMap[T] += pt * (refTime / E - length / pz);
390  } else {
391  applyDrift(length);
392  }
393  }
394 }
395 
396 
398  // Do nothing.
399 }
400 
402  // Do nothing here.
403 }
404 
406  if(wrap.offset().isIdentity()) {
407  wrap.getElement()->accept(*this);
408  } else {
409  Euclid3D e1 = wrap.getEntranceTransform();
410  Euclid3D e2 = wrap.getExitTransform();
411 
412  if(back_path) {
413  // Tracking right to left.
414  applyTransform(Inverse(e2), 0.0);
415  wrap.getElement()->accept(*this);
416  applyTransform(Inverse(e1), 0.0);
417  } else {
418  // Tracking left to right.
419  applyTransform(e1, 0.0);
420  wrap.getElement()->accept(*this);
421  applyTransform(e2, 0.0);
422  }
423  }
424 }
425 
426 
428  FVps<double, 6> map(itsMap);
431 }
432 
433 
434 // Helper function for finding first-order coefficients.
435 static void makeFocus
436 (double k, double L, double &c, double &s, double &d, double &f) {
437  double t = k * L * L;
438  if(std::abs(t) < 1.0e-4) {
439  c = 1.0 - t / 2.0;
440  s = L * (1.0 - t / 6.0);
441  d = L * L * (0.5 - t / 24.0);
442  f = L * L * L * (1.0 / 6.0 - t / 120.0);
443  } else if(k > 0.0) {
444  double r = sqrt(k);
445  c = cos(r * L);
446  s = sin(r * L) / r;
447  d = (1.0 - c) / k;
448  f = (L - s) / k;
449  } else {
450  double r = sqrt(- k);
451  c = cosh(r * L);
452  s = sinh(r * L) / r;
453  d = (1.0 - c) / k;
454  f = (L - s) / k;
455  }
456 }
457 
458 
459 void TransportMapper::applyDrift(double length) {
460  double kin = itsReference.getM() / itsReference.getP();
461  double refTime = length / itsReference.getBeta();
462 
463  TptFun px = itsMap[PX];
464  TptFun py = itsMap[PY];
465  TptFun pt = itsMap[PT] + 1.0;
466  TptFun pz = sqrt(pt * pt - px * px - py * py);
467  TptFun E = sqrt(pt * pt + kin * kin);
468 
469  itsMap[X] += length * px / pz;
470  itsMap[Y] += length * py / pz;
471  itsMap[T] += pt * (refTime / E - length / pz);
472 }
473 
474 
476  const BMultipoleField &field,
477  double scale) {
478  // ***** MISSING: second-order fringe at entrance
479  double hx = scale * field.normal(1);
480  double ex = hx * tan(angle);
481  double ey = hx * tan(angle + itsMap[PX][0]);
482  itsMap[PX] += ex * itsMap[X];
483  itsMap[PY] -= ey * itsMap[Y];
484 }
485 
486 
488  const BMultipoleField &field,
489  double scale) {
490  // ***** MISSING: second-order fringe at exit
491  double hx = scale * field.normal(1);
492  double ex = hx * tan(angle);
493  double ey = hx * tan(angle - itsMap[PX][0]);
494  itsMap[PX] += ex * itsMap[X];
495  itsMap[PY] -= ey * itsMap[Y];
496 }
497 
498 
500 (double length, double refLength, double h,
501  const Series2 &Fx, const Series2 &Fy) {
502  // ***** MISSING: Transport map for thick element.
503  // Extract the phase coordinates.
504  TptFun x = itsMap[X];
505  TptFun px = itsMap[PX];
506  TptFun y = itsMap[Y];
507  TptFun py = itsMap[PY];
508  TptFun pt = itsMap[PT];
509 
510  // (x0, y0) is the position of the entry point,
511  // (x, y) is the position relative to the entry point.
512  double x0 = x[0];
513  double y0 = y[0];
514  x.setCoefficient(0, 0.0);
515  y.setCoefficient(0, 0.0);
516 
517  // Extract coefficients for equations of motion.
518  // Indexing: 0 = constant, 1 = X, 2 = Y.
519  double kx = Fx[1];
520  double ks = (Fx[2] - Fy[1]) / 2.0;
521  double ky = - Fy[2];
522  double hx = h - Fx[0];
523  double hy = Fy[0];
524 
525  // Longitudinal data.
526  double kin = itsReference.getM() / itsReference.getE();
527  double refTime = refLength * kin * kin;
528 
529  // Test for zero skew quadrupole component.
530  if(ks == 0.0) {
531  // Transport coefficients.
532  double cx, sx, dx, fx, cy, sy, dy, fy;
533  makeFocus(kx, length, cx, sx, dx, fx);
534  makeFocus(ky, length, cy, sy, dy, fy);
535  double wx = - kx * sx;
536  double wy = - ky * sy;
537 
538  // Advance through field.
539  itsMap[X] = cx * x + sx * px + dx * hx + h * dx * pt + x0;
540  itsMap[PX] = wx * x + cx * px + sx * hx + h * sx * pt;
541  itsMap[Y] = cy * y + sy * py + dy * hy + y0;
542  itsMap[PY] = wy * y + cy * py + sy * hy;
543  itsMap[T] += refTime * pt + h * (sx * x + dx * px + fx * hx + length * x0);
544  } else {
545  // Find transformation to principal axes.
546  double s1 = (kx + ky) / 2.0;
547  double d1 = (kx - ky) / 2.0;
548  double root = sqrt(d1 * d1 + ks * ks);
549  double c2 = d1 / root;
550  double s2 = ks / root;
551 
552  // Transport coefficients.
553  double cu, su, du, fu, cv, sv, dv, fv;
554  double ku = s1 + (d1 * d1 - ks * ks) / root;
555  double kv = s1 - (d1 * d1 - ks * ks) / root;
556  makeFocus(ku, length, cu, su, du, fu);
557  makeFocus(kv, length, cv, sv, dv, fv);
558  double wu = - ku * su;
559  double wv = - kv * sv;
560 
561  // Rotate the coordinates to orientation of quadrupole.
562  TptFun u = c2 * x - s2 * y;
563  TptFun v = c2 * y + s2 * x;
564  TptFun pu = c2 * px - s2 * py;
565  TptFun pv = c2 * py + s2 * px;
566  double hu = c2 * (h + hx) - s2 * hy;
567  double hv = c2 * hy + s2 * (h + hx);
568  double bu = c2 * h;
569  double bv = s2 * h;
570 
571  // Advance through field.
572  itsMap[X] = x0 +
573  ((cu + cv) * x + (cu - cv) * u + (su + sv) * px + (su - sv) * pu +
574  (du + dv) * hx + (du - dv) * hu + ((du + dv) * h + (du - dv) * bu) * pt) / 2.0;
575  itsMap[PX] =
576  ((wu + wv) * x + (wu - wv) * u + (cu + cv) * px + (cu - cv) * pu +
577  (su + sv) * hx + (su - sv) * hu + ((su + sv) * h + (su - sv) * bu) * pt) / 2.0;
578  itsMap[Y] = y0 +
579  ((cu + cv) * y - (cu - cv) * v + (su + sv) * py - (su - sv) * pv +
580  (du + dv) * hy - (du - dv) * hv - (du - dv) * bv * pt) / 2.0;
581  itsMap[PY] =
582  ((wu + wv) * y - (wu - wv) * v + (cu + cv) * py - (cu - cv) * pv +
583  (su + sv) * hy - (su - sv) * hv - (su - sv) * bv * pt) / 2.0;
584  itsMap[T] += refTime * pt;
585  }
586 }
587 
588 
589 void TransportMapper::applyMultipoleBody(double length, double refLength,
590  const BMultipoleField &field,
591  double scale) {
592  // Determine normalised field coefficients around actual orbit.
593  // Fx and Fy are the normalised field coefficients,
594  // expressed as transport functions in x and y.
595  int order = field.order();
596  Series2 Fx;
597  Series2 Fy;
599 
600  if(order > 0) {
601  static Series2 x = Series2::makeVariable(0);
602  static Series2 y = Series2::makeVariable(1);
603  x.setCoefficient(0, itsMap[X][0]);
604  y.setCoefficient(0, itsMap[Y][0]);
605  Fx = + field.normal(order);
606  Fy = - field.skew(order);
607 
608  while(order > 1) {
609  Series2 Fxt = x * Fx - y * Fy;
610  Series2 Fyt = x * Fy + y * Fx;
611  order--;
612  Fx = Fxt + field.normal(order);
613  Fy = Fyt - field.skew(order);
614  };
615 
616  Fx *= scale;
617  Fy *= scale;
618  }
619 
620  applyTransportMap(length, refLength, 0.0, Fx, Fy);
621 }
622 
623 
625 applySBendBody(double length, double refLength, double h,
626  const BMultipoleField &field, double scale) {
627  // Determine normalised field coefficients around actual orbit.
628  // As is the vector potential times (1 + h*x),
629  // expressed as a transport function in x and y.
630  Series2 As = buildSBendVectorPotential(field, h) * scale;
631 
632  // Fx and Fy are the normalised field coefficients times (1 + h*x).
633  Series2 Fx = + As.derivative(0);
634  Series2 Fy = - As.derivative(1);
635  applyTransportMap(length, refLength, h, Fx, Fy);
636 }
637 
638 
640 applyThinMultipole(const BMultipoleField &field, double scale) {
641  int order = field.order();
642 
643  if(order > 0) {
644  TptFun x = itsMap[X];
645  TptFun y = itsMap[Y];
646  TptFun kx = + field.normal(order);
647  TptFun ky = - field.skew(order);
648 
649  while(--order > 0) {
650  TptFun kxt = x * kx - y * ky;
651  TptFun kyt = x * ky + y * kx;
652  kx = kxt + field.normal(order);
653  ky = kyt - field.skew(order);
654  }
655 
656  itsMap[PX] -= kx * scale;
657  itsMap[PY] += ky * scale;
658  }
659 }
660 
661 
663 applyThinSBend(const BMultipoleField &field, double scale, double h) {
664  Series2 As = buildSBendVectorPotential(field, h) * scale;
665 
666  // Fx and Fy are the normalised kicks,
667  // expressed as transport functions in x and y.
668  Series2 Fx = + As.derivative(0);
669  Series2 Fy = - As.derivative(1);
670 
671  // These substitutions work because As depends on x and y only,
672  // and not on px or py.
673  itsMap[PX] -= Fx[0] + Fx[1] * itsMap[X] + Fx[2] * itsMap[Y];
674  itsMap[PY] -= Fy[0] + Fy[1] * itsMap[X] + Fy[2] * itsMap[Y];
675 }
676 
677 
679 applyTransform(const Euclid3D &euclid, double refLength) {
680  if(! euclid.isIdentity()) {
681  TptFun px1 = itsMap[PX];
682  TptFun py1 = itsMap[PY];
683  TptFun pt = itsMap[PT] + 1.0;
684  TptFun pz1 = sqrt(pt * pt - px1 * px1 - py1 * py1);
685 
686  itsMap[PX] = euclid.M(0, 0) * px1 + euclid.M(1, 0) * py1 + euclid.M(2, 0) * pz1;
687  itsMap[PY] = euclid.M(0, 1) * px1 + euclid.M(1, 1) * py1 + euclid.M(2, 1) * pz1;
688  TptFun pz2 = euclid.M(0, 2) * px1 + euclid.M(1, 2) * py1 + euclid.M(2, 2) * pz1;
689 
690  TptFun x = itsMap[X] - euclid.getX();
691  TptFun y = itsMap[Y] - euclid.getY();
692  TptFun x2 =
693  euclid.M(0, 0) * x + euclid.M(1, 0) * y - euclid.M(2, 0) * euclid.getZ();
694  TptFun y2 =
695  euclid.M(0, 1) * x + euclid.M(1, 1) * y - euclid.M(2, 1) * euclid.getZ();
696  TptFun s2 =
697  euclid.M(0, 2) * x + euclid.M(1, 2) * y - euclid.M(2, 2) * euclid.getZ();
698  TptFun sByPz = s2 / pz2;
699 
700  double kin = itsReference.getM() / itsReference.getP();
701  TptFun E = sqrt(pt * pt + kin * kin);
702  double refTime = refLength / itsReference.getBeta();
703  itsMap[X] = x2 - sByPz * itsMap[PX];
704  itsMap[Y] = y2 - sByPz * itsMap[PY];
705  itsMap[T] += pt * (refTime / E + sByPz);
706  }
707 }
708 
709 
712  int order = field.order();
713  Series2::setGlobalTruncOrder(order + 1);
714  Series2 As;
715 
716  if(order > 0) {
717  static Series2 x = Series2::makeVariable(0);
718  static Series2 y = Series2::makeVariable(1);
719  x.setCoefficient(0, itsMap[X][0]);
720  y.setCoefficient(0, itsMap[Y][0]);
721 
722  // Construct terms constant and transport in y.
723  Series2 Ae = + field.normal(order); // Term even in y.
724  Series2 Ao = - field.skew(order); // Term odd in y.
725  int i = order;
726 
727  while(i > 1) {
728  i--;
729  Ae = Ae * x + field.normal(i);
730  Ao = Ao * x - field.skew(i);
731  };
732 
733  Ae = + (Ae * (1.0 + h * x)).integral(0);
734  Ao = - (Ao * (1.0 + h * x));
735 
736  // Add terms up to maximum order.
737  As = Ae + y * Ao;
738  int k = 2;
739 
740  if(k <= order) {
741  Series2 yp = y * y / 2.0;
742  Series2 factor = h / (1.0 + h * x);
743 
744  while(true) {
745  // Terms even in y.
746  Ae = Ae.derivative(0);
747  Ae = (factor * Ae - Ae.derivative(0)) * yp;
748  As += Ae;
749  if(++k > order) break;
750  yp *= y / double(k);
751 
752  // Terms odd in y.
753  Ao = Ao.derivative(0);
754  Ao = (factor * Ao - Ao.derivative(0)) * yp;
755  As += Ao;
756  if(++k > order) break;
757  yp *= y / double(k);
758  }
759  }
760  }
761 
762  return As;
763 }
Build transfer map.
virtual double getExitFaceRotation() const =0
Get exit pole face rotation.
virtual void visitSeptum(const Septum &)
Apply the algorithm to a Septum.
virtual ElementBase * getElement() const
Return the contained element.
Definition: rbendmap.h:8
void applyThinSBend(const BMultipoleField &field, double scale, double h)
Thin SBend kick.
virtual double getArcLength() const
Get arc length.
Euclid3D & offset() const
Return the offset.
virtual BMultipoleField & getField() override=0
Get multipole expansion of field.
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
virtual void visitDrift(const Drift &)
Apply the algorithm to a Drift.
virtual void visitSBend(const SBend &)
Apply the algorithm to a SBend.
double getX() const
Get displacement.
Definition: Euclid3D.h:216
virtual BDipoleField & getField()=0
Return the corrector field.
constexpr double e
The value of .
Definition: Physics.h:40
virtual void visitMonitor(const Monitor &)
Apply the algorithm to a Monitor.
virtual void visitPatch(const Patch &pat)
Apply the algorithm to a patch.
virtual double getAmplitude() const =0
Get RF amplitude.
double normal(int) const
Get component.
Definition: rbendmap.h:8
The field of a magnetic dipole.
Definition: BDipoleField.h:31
virtual BMultipoleField & getField() override=0
Get multipole expansion of field.
virtual void visitSeparator(const Separator &)
Apply the algorithm to a Separator.
Interface for septum magnet.
Definition: Septum.h:11
virtual void visitRFCavity(const RFCavity &)
Apply the algorithm to a RFCavity.
virtual BMultipoleField & getField() override=0
Get multipole field.
virtual void trackMap(FVps< double, 6 > &, const PartData &, bool revBeam, bool revTrack) const
Track a map.
Interface for electrostatic separator.
Definition: Separator.h:33
Euclid3D getExitPatch() const
Get patch.
virtual ~TransportMapper()
virtual void trackMap(FVps< double, 6 > &map, const PartData &, bool revBeam, bool revTrack) const
Track a map.
Definition: Component.cpp:78
virtual double getArcLength() const
Get arc length.
virtual double getPhase() const =0
Get RF phase.
virtual void visitBeamStripping(const BeamStripping &)
Apply the algorithm to a BeamStripping.
Interface for beam position monitors.
Definition: Monitor.h:41
Interface for RF Quadrupole.
Definition: RFQuadrupole.h:30
A simple arc in the XZ plane.
Definition: rbendmap.h:8
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
virtual void visitAlignWrapper(const AlignWrapper &)
Apply the algorithm to an offset beamline object wrapper.
virtual void visitBeamBeam(const BeamBeam &)
Apply the algorithm to a BeamBeam.
virtual double getBz() const =0
Get solenoid field Bz in Teslas.
Define the position of a misaligned element.
Definition: AlignWrapper.h:39
Interface for RF cavity.
Definition: ParallelPlate.h:36
double getZ() const
Get displacement.
Definition: Euclid3D.h:224
virtual double getElementLength() const override
Get design length.
Definition: RFCavity.cpp:818
virtual Euclid3D getEntranceTransform() const
Get entrance patch.
virtual void setMap(const LinearMap< double, 6 > &)
Reset the linear part of the accumulated map for restart.
Particle reference data.
Definition: PartData.h:38
virtual double getEx() const =0
Get horizontal component Ex of field in V/m.
Interface for general corrector.
Definition: Corrector.h:35
virtual double getEy() const =0
Get vertical component Ey of field in V/m.
Abstract collimator.
Definition: RBend.h:73
Interface for beam diagnostics.
Definition: Diagnostic.h:32
Euclid3D getEntrancePatch() const
Get patch.
Interface for a marker.
Definition: Marker.h:32
virtual double getBy() const
Get vertical component.
virtual PlanarArcGeometry & getGeometry() override=0
Get SBend geometry.
Definition: rbendmap.h:8
Tps< T > tan(const Tps< T > &x)
Tangent.
Definition: TpsMath.h:147
virtual double getEntryFaceRotation() const =0
Get pole entry face rotation.
Interface for drift space.
Definition: Drift.h:33
virtual void visitMarker(const Marker &)
Apply the algorithm to a Marker.
double getBeta() const
The relativistic beta per particle.
Definition: PartData.h:127
virtual void visitMapIntegrator(const MapIntegrator &)
Apply the algorithm to an integrator capable of mapping.
double M(int row, int col) const
Get component.
Definition: Euclid3D.h:228
Interface for general multipole.
Definition: Multipole.h:46
static Euclid3D YRotation(double angle)
Make rotation.
Definition: Euclid3D.cpp:164
T deg(T x)
Convert radians to degrees.
Definition: matheval.hpp:82
Euclid3D Inverse(const Euclid3D &t)
Euclidean inverse.
Definition: Euclid3D.h:204
virtual double getElementLength() const override
Get design length.
Definition: Solenoid.cpp:256
Tps< T > cosh(const Tps< T > &x)
Hyperbolic cosine.
Definition: TpsMath.h:222
virtual double getExitFaceRotation() const =0
Get exit pole face rotation.
double getBendAngle() const
Get angle.
Interface for probe.
Definition: Probe.h:16
void applyDrift(double length)
virtual Euclid3D getExitTransform() const
Get exit patch.
virtual void visitRBend(const RBend &)
Apply the algorithm to a RBend.
double skew(int) const
Get component.
Transport function in N variables of type T.
Definition: TransportFun.h:40
double getQ() const
The constant charge per particle.
Definition: PartData.h:107
virtual void getMap(LinearMap< double, 6 > &) const
Return the linear part of the accumulated map.
virtual void accept(BeamlineVisitor &visitor) const =0
Apply visitor.
virtual double getElementLength() const
Get design length.
Definition: ElementBase.h:511
virtual void visitCorrector(const Corrector &)
Apply the algorithm to a Corrector.
virtual double getFrequency() const =0
Get RF frequencey.
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:52
virtual void visitCyclotronValley(const CyclotronValley &)
Apply the algorithm to a CyclotronValley.
virtual void visitCCollimator(const CCollimator &)
Apply the algorithm to a collimator.
Interface for cyclotron collimator.
Definition: CCollimator.h:13
virtual void visitFlexibleCollimator(const FlexibleCollimator &)
Apply the algorithm to a flexible collimator.
virtual void visitProbe(const Probe &)
Apply the algorithm to a probe.
Displacement and rotation in space.
Definition: Euclid3D.h:68
Abstract beam-beam interaction.
Definition: BeamBeam.h:37
Definition: SBend.h:68
void setCoefficient(int index, const T &value)
Set coefficient.
void applyEntranceFringe(double edge, const BMultipoleField &field, double scale)
bool isIdentity() const
Test for identity.
Definition: Euclid3D.h:233
Interface for cyclotron valley.
virtual double getBx() const
Get horizontal component.
Interface for solenoids.
Definition: Solenoid.h:36
virtual double getElementLength() const
Get element length.
An abstract sequence of beam line components.
Definition: Beamline.h:37
virtual double getElementLength() const
Get element length.
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
virtual double getEntryFaceRotation() const =0
Get pole entry face rotation.
FTps derivative(int var) const
Partial derivative.
Definition: FTps.hpp:1396
The geometry for a RBend element.
Definition: RBendGeometry.h:41
virtual void visitComponent(const Component &)
Apply the algorithm to an arbitrary component.
double getP() const
The constant reference momentum per particle.
Definition: PartData.h:117
virtual void visitDiagnostic(const Diagnostic &)
Apply the algorithm to a Diagnostic.
The magnetic field of a multipole.
double hv(FRONT)
virtual void visitLambertson(const Lambertson &)
Apply the algorithm to a Lambertson.
Interface for RF cavity.
Definition: RFCavity.h:37
double getM() const
The constant mass per particle.
Definition: PartData.h:112
void applyTransform(const Euclid3D &, double refLength)
Apply transform.
void applyExitFringe(double edge, const BMultipoleField &field, double scale)
virtual void visitDegrader(const Degrader &)
Apply the algorithm to a Degrader.
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
Abstract collimator.
Definition: Degrader.h:37
virtual void visitMultipole(const Multipole &)
Apply the algorithm to a Multipole.
void applyTransportMap(double length, double refLength, double h, const FTps< double, 2 > &Fx, const FTps< double, 2 > &Fy)
static void setGlobalTruncOrder(int order)
Set the global truncation order.
Definition: FTps.hpp:419
FTps< double, 2 > Series2
void applySBendBody(double length, double refLength, double h, const BMultipoleField &field, double scale)
double getCurvature() const
Get curvature.
FTps integral(int var, int trunc=EXACT) const
Partial integral.
Definition: FTps.hpp:1441
virtual RBendGeometry & getGeometry() override=0
Get RBend geometry.
virtual double getBendAngle() const
Get angle.
Truncated power series in N variables of type T.
TransportMap< double, 6 > itsMap
Interface for a geometric patch.
Definition: Patch.h:34
Interface for a single beam element.
Definition: Component.h:51
void applyThinMultipole(const BMultipoleField &field, double factor)
Thin multipole kick.
FTps< double, 2 > buildSBendVectorPotential(const BMultipoleField &, double h)
Construct the vector potential for a SBend.
virtual const Euclid3D & getPatch() const =0
Get patch transform.
Definition: rbendmap.h:8
const PartData itsReference
The reference information.
double getY() const
Get displacement.
Definition: Euclid3D.h:220
Tps< T > sinh(const Tps< T > &x)
Hyperbolic sine.
Definition: TpsMath.h:204
static FTps makeVariable(int var)
Make variable.
Definition: FTps.hpp:481
int order() const
Return order.
virtual void visitParallelPlate(const ParallelPlate &)
Apply the algorithm to a ParallelPlate.
virtual void visitRFQuadrupole(const RFQuadrupole &)
Apply the algorithm to a RFQuadrupole.
Definition: rbendmap.h:8
void applyMultipoleBody(double length, double refLength, const BMultipoleField &field, double scale)
TransportFun< double, 6 > TptFun
void setCoefficient(int index, const T &value)
Set coefficient.
Definition: FTps.hpp:236
Interface for a Lambertson septum.
Definition: Lambertson.h:33
Integrate a map.
Definition: MapIntegrator.h:41
virtual void visitSolenoid(const Solenoid &)
Apply the algorithm to a Solenoid.