OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
OrbitTracker.cpp
Go to the documentation of this file.
1 // ------------------------------------------------------------------------
2 // $RCSfile: OrbitTracker.cpp,v $
3 // ------------------------------------------------------------------------
4 // $Revision: 1.3.2.1 $
5 // ------------------------------------------------------------------------
6 // Copyright: see Copyright.readme
7 // ------------------------------------------------------------------------
8 //
9 // Class: OrbitTracker
10 // An visitor class allowing to tracking an orbit through a beamline.
11 //
12 // ------------------------------------------------------------------------
13 // Class category: Algorithms
14 // ------------------------------------------------------------------------
15 //
16 // $Date: 2003/11/07 18:01:13 $
17 // $Author: dbruhwil $
18 //
19 // ------------------------------------------------------------------------
20 
22 #include "Algorithms/PartBunch.h"
23 #include "Algorithms/PartData.h"
29 #include "Fields/BMultipoleField.h"
30 #include "FixedAlgebra/FTps.h"
31 #include "Physics/Physics.h"
34 #include "AbsBeamline/Corrector.h"
35 #include "AbsBeamline/Diagnostic.h"
36 #include "AbsBeamline/Drift.h"
37 #include "AbsBeamline/Degrader.h"
40 #include "AbsBeamline/Lambertson.h"
41 #include "AbsBeamline/Monitor.h"
42 #include "AbsBeamline/Multipole.h"
43 #include "AbsBeamline/Patch.h"
44 #include "AbsBeamline/Probe.h"
45 #include "AbsBeamline/RBend.h"
46 #include "AbsBeamline/RFCavity.h"
48 #include "AbsBeamline/SBend.h"
49 #include "AbsBeamline/Separator.h"
50 #include "AbsBeamline/Septum.h"
51 #include "AbsBeamline/Solenoid.h"
54 
55 #include <cmath>
56 
58 
59 using Physics::c;
60 
61 
62 //: Abstract tracker class.
63 // An visitor class implementing tracking of an orbit through a beam line.
64 
65 // Class OrbitTracker
66 // ------------------------------------------------------------------------
67 
68 
70  const PartData &reference,
71  bool backBeam, bool backTrack):
72  AbstractTracker(beamline, reference, backBeam, backTrack)
73 {}
74 
75 
77 {}
78 
79 
81  return itsOrbit;
82 }
83 
84 
86  itsOrbit = orbit;
87 }
88 
89 
91  // *** MISSING *** Map for beam-beam.
92 }
93 
94 
96  // *** MISSING *** Map for beam stripping.
97 }
98 
99 
102 }
103 
106 }
107 
109  //do nothing in orbittracker.
110 }
111 
112 
114  //do nothing in orbittracker.
115 }
116 
118  std::unique_ptr<PartBunchBase<double, 3> > bunch(new PartBunch(&itsReference));
120  itsOrbit[Y], itsOrbit[PY],
121  itsOrbit[T], itsOrbit[PT]);
122  bunch->push_back(part);
123  comp.trackBunch(bunch.get(), itsReference, back_beam, back_track);
124  itsOrbit[X] = part.x();
125  itsOrbit[PX] = part.px();
126  itsOrbit[Y] = part.y();
127  itsOrbit[PY] = part.py();
128  itsOrbit[T] = part.t();
129  itsOrbit[PY] = part.pt();
130 }
131 
132 
134  // Drift through first half of length.
135  double length = flip_s * corr.getElementLength();
136  if(length) applyDrift(length / 2.0);
137 
138  // Apply kick.
139  double scale = (flip_B * itsReference.getQ() * c) / itsReference.getP();
140  const BDipoleField &field = corr.getField();
141  itsOrbit[PX] -= field.getBy() * scale;
142  itsOrbit[PY] += field.getBx() * scale;
143 
144  // Drift through second half of length.
145  if(length) applyDrift(length / 2.0);
146 }
147 
148 
151 }
152 
153 
154 void OrbitTracker::visitDrift(const Drift &drift) {
156 }
157 
160 }
161 
163  // Assume the orbit goes through the magnet's window.
165 }
166 
167 
169  // Do nothing.
170 }
171 
172 
175 }
176 
177 
179  double length = flip_s * mult.getElementLength();
180  double scale = (flip_B * itsReference.getQ() * c) / itsReference.getP();
181  const BMultipoleField &field = mult.getField();
182 
183  if(length) {
184  // Normal case: Finite-length multipole, field coefficients are B.
185  applyMultipoleBody(length, length, field, scale);
186  } else {
187  // Special case: Thin multipole, field coefficients are integral(B*dl).
188  scale *= flip_s;
189  applyThinMultipole(field, scale);
190  }
191 }
192 
193 
194 void OrbitTracker::visitPatch(const Patch &patch) {
195  Euclid3D transform = patch.getPatch();
196  if(back_path) transform = Inverse(transform);
197  applyTransform(transform, 0.0);
198 }
199 
200 void OrbitTracker::visitProbe(const Probe &prob) {
201  // Do nothing.
202 }
203 
204 void OrbitTracker::visitRBend(const RBend &bend) {
205  const RBendGeometry &geometry = bend.getGeometry();
206  double length = flip_s * geometry.getElementLength();
207  double scale = (flip_B * itsReference.getQ() * c) / itsReference.getP();
208  const BMultipoleField &field = bend.getField();
209 
210  if(length == 0.0) {
211  double half_angle = flip_s * geometry.getBendAngle() / 2.0;
212  Euclid3D rotat = Euclid3D::YRotation(- half_angle);
213 
214  // Transform from in-plane to mid-plane.
215  applyTransform(rotat, 0.0);
216 
217  // Apply multipole kick.
218  applyThinMultipole(field, scale);
219 
220  // Transform from mid-plane to out-plane.
221  applyTransform(rotat, 0.0);
222  } else {
223  double refLength = flip_s * geometry.getArcLength();
224 
225  if(back_path) {
226  // Transform from global to local.
227  applyTransform(Inverse(geometry.getExitPatch()), 0.0);
228 
229  // Apply entrance fringe field.
230  applyEntranceFringe(bend.getExitFaceRotation(), field, scale);
231 
232  // Traverse rbend body.
233  applyMultipoleBody(length, refLength, field, scale);
234 
235  // Apply exit fringe field.
236  applyExitFringe(bend.getEntryFaceRotation(), field, scale);
237 
238  // Apply rotation local to global.
239  applyTransform(Inverse(geometry.getEntrancePatch()), 0.0);
240  } else {
241  // Apply rotation global to local.
242  applyTransform(geometry.getEntrancePatch(), 0.0);
243 
244  // Apply entrance fringe field.
245  applyEntranceFringe(bend.getEntryFaceRotation(), field, scale);
246 
247  // Traverse rbend body.
248  applyMultipoleBody(length, refLength, field, scale);
249 
250  // Apply exit fringe field.
251  applyExitFringe(bend.getExitFaceRotation(), field, scale);
252 
253  // Apply rotation local to global.
254  applyTransform(geometry.getExitPatch(), 0.0);
255  }
256  }
257 }
258 
259 
261  // Drift through half length.
262  double length = flip_s * as.getElementLength();
263  if(length) applyDrift(length / 2.0);
264 
265  // Apply accelerating voltage.
266  double time = itsOrbit[T] / (c * itsReference.getBeta());
267  double peak = flip_s * as.getAmplitude() / itsReference.getP();
268  double phase = as.getPhase() + as.getFrequency() * time;
269  itsOrbit[PT] += peak * sin(phase);
270 
271  // Drift through half length.
272  if(length) applyDrift(length / 2.0);
273 }
274 
275 
277  // *** MISSING *** Map for RF Quadrupole.
279 }
280 
281 
282 void OrbitTracker::visitSBend(const SBend &bend) {
283  const PlanarArcGeometry &geometry = bend.getGeometry();
284  double length = flip_s * geometry.getElementLength();
285  double scale = (flip_B * itsReference.getQ() * c) / itsReference.getP();
286  const BMultipoleField &field = bend.getField();
287 
288  if(length == 0.0) {
289  double half_angle = geometry.getBendAngle() / 2.0;
290  Euclid3D rotat = Euclid3D::YRotation(- half_angle);
291 
292  // Transform from in-plane to mid-plane.
293  applyTransform(rotat, 0.0);
294 
295  // Apply multipole kick.
296  // Curvature is unknown for zero-length bend.
297  applyThinMultipole(field, scale);
298 
299  // Transform from mid-plane to out-plane.
300  applyTransform(rotat, 0.0);
301  } else {
302  double h = geometry.getCurvature();
303  double refLength = flip_s * geometry.getArcLength();
304 
305  if(back_path) {
306  // Apply entrance fringe field.
307  applyEntranceFringe(bend.getExitFaceRotation(), field, scale);
308 
309  // Traverse sbend body.
310  applySBendBody(length, refLength, h, field, scale);
311 
312  // Apply exit fringe field.
313  applyExitFringe(bend.getEntryFaceRotation(), field, scale);
314  } else {
315  // Apply entrance fringe field.
316  applyEntranceFringe(bend.getEntryFaceRotation(), field, scale);
317 
318  // Traverse sbend body.
319  applySBendBody(length, refLength, h, field, scale);
320 
321  // Apply exit fringe field.
322  applyExitFringe(bend.getExitFaceRotation(), field, scale);
323  }
324  }
325 }
326 
327 
329  // Drift through first half of length.
330  double length = flip_s * sep.getElementLength();
331  if(length) applyDrift(length / 2.0);
332 
333  // Electrostatic kick.
334  double scale = (length * itsReference.getQ()) / itsReference.getP();
335  double Ex = scale * sep.getEx();
336  double Ey = scale * sep.getEy();
337  double pt = 1.0 + itsOrbit[PT];
338  itsOrbit[PX] += Ex / pt;
339  itsOrbit[PY] += Ey / pt;
340 
341  if(length) applyDrift(length / 2.0);
342 }
343 
344 
346  // Assume the orbit goes through the magnet's window.
348 }
349 
350 
351 void OrbitTracker::visitSolenoid(const Solenoid &solenoid) {
352  double length = flip_s * solenoid.getElementLength();
353 
354  if(length) {
355  double ks = (flip_B * itsReference.getQ() * solenoid.getBz() * c) /
356  (2.0 * itsReference.getP());
357 
358  if(ks) {
359  double C = cos(ks * length);
360  double S = sin(ks * length);
361 
362  double xt = C * itsOrbit[X] + S * itsOrbit[Y];
363  double yt = C * itsOrbit[Y] - S * itsOrbit[X];
364  double pxt = C * itsOrbit[PX] + S * itsOrbit[PY];
365  double pyt = C * itsOrbit[PY] - S * itsOrbit[PX];
366 
367  itsOrbit[X] = C * xt + (S / ks) * pxt;
368  itsOrbit[Y] = C * yt + (S / ks) * pyt;
369  itsOrbit[PX] = C * pxt - (S * ks) * xt;
370  itsOrbit[PY] = C * pyt - (S * ks) * yt;
371 
372  double kin = itsReference.getM() / itsReference.getP();
373  itsOrbit[T] += length * itsOrbit[PT] * kin * kin;
374  } else {
375  applyDrift(length);
376  }
377  }
378 }
379 
380 
382  if(wrap.offset().isIdentity()) {
383  wrap.getElement()->accept(*this);
384  } else {
385  Euclid3D e1 = wrap.getEntranceTransform();
386  Euclid3D e2 = wrap.getExitTransform();
387 
388  if(back_path) {
389  // Tracking right to left.
390  applyTransform(Inverse(e2), 0.0);
391  wrap.getElement()->accept(*this);
392  applyTransform(Inverse(e1), 0.0);
393  } else {
394  // Tracking left to right.
395  applyTransform(e1, 0.0);
396  wrap.getElement()->accept(*this);
397  applyTransform(e2, 0.0);
398  }
399  }
400 }
401 
402 
403 void OrbitTracker::applyDrift(double length) {
404  double kin = itsReference.getM() / itsReference.getP();
405  itsOrbit[X] += length * itsOrbit[PX];
406  itsOrbit[Y] += length * itsOrbit[PY];
407  itsOrbit[T] += length * itsOrbit[PT] * kin * kin;
408 }
409 
410 
412 (double edge, const BMultipoleField &field, double scale) {
413  double hx = scale * field.normal(1);
414  double ex = hx * tan(edge);
415  double ey = hx * tan(edge + itsOrbit[PX]);
416  itsOrbit[PX] += ex * itsOrbit[X];
417  itsOrbit[PY] -= ey * itsOrbit[Y];
418 }
419 
420 
422 (double edge, const BMultipoleField &field, double scale) {
423  double hx = scale * field.normal(1);
424  double ex = hx * tan(edge);
425  double ey = hx * tan(edge - itsOrbit[PX]);
426  itsOrbit[PX] += ex * itsOrbit[X];
427  itsOrbit[PY] -= ey * itsOrbit[Y];
428 }
429 
430 
432 (double length, double refLength, double h,
433  const FTps<double, 2> &Fx, const FTps<double, 2> &Fy) {
434  // Extract the phase coordinates.
435  double x = itsOrbit[X];
436  double px = itsOrbit[PX];
437  double y = itsOrbit[Y];
438  double py = itsOrbit[PY];
439  double pt = itsOrbit[PT];
440  double pt1 = 1.0 - pt;
441 
442  // Extract coefficients for equations of motion.
443  // These coefficients are w. r. t. the position (x,y).
444  // Indexing: 0 = constant, 1 = X, 2 = Y.
445  double kx = Fx[1] * pt1;
446  double ks = (Fx[2] - Fy[1]) * (pt1 / 2.0);
447  double ky = - Fy[2] * pt1;
448  double hx = h - Fx[0] * pt1;
449  double hy = Fy[0] * pt1;
450 
451  // Parameters for longitudinal motion.
452  double kin = itsReference.getM() / itsReference.getE();
453  double refTime = refLength * kin * kin;
454 
455  // Test for zero skew quadrupole component.
456  if(ks == 0.0) {
457  // Transport coefficients.
458  double cx, sx, dx, fx, cy, sy, dy, fy;
459  makeFocus(kx, length, cx, sx, dx, fx);
460  makeFocus(ky, length, cy, sy, dy, fy);
461 
462  // Advance through field.
463  itsOrbit[X] = sx * px + dx * hx;
464  itsOrbit[PX] = cx * px + sx * hx;
465  itsOrbit[Y] = sy * py + dy * hy;
466  itsOrbit[PY] = cy * py + sy * hy;
467  itsOrbit[T] += h * (dx * px + fx * hx);
468  } else {
469  // Find transformation to principal axes.
470  double s1 = (kx + ky) / 2.0;
471  double d1 = (kx - ky) / 2.0;
472  double root = sqrt(d1 * d1 + ks * ks);
473  double c2 = d1 / root;
474  double s2 = ks / root;
475 
476  // Transport coefficients.
477  double cu, su, du, fu, cv, sv, dv, fv;
478  double ku = s1 + (d1 * d1 - ks * ks) / root;
479  double kv = s1 - (d1 * d1 - ks * ks) / root;
480  makeFocus(ku, length, cu, su, du, fu);
481  makeFocus(kv, length, cv, sv, dv, fv);
482 
483  // Rotate the coordinates to orientation of quadrupole.
484  double pu = c2 * px - s2 * py;
485  double pv = c2 * py + s2 * px;
486  double hu = c2 * (h + hx) - s2 * hy;
487  double hv = c2 * hy + s2 * (h + hx);
488 
489  // Advance through field.
490  itsOrbit[X] = ((su + sv) * px + (su - sv) * pu +
491  (du + dv) * hx + (du - dv) * hu) / 2.0;
492  itsOrbit[PX] = ((cu + cv) * px + (cu - cv) * pu +
493  (su + sv) * hx + (su - sv) * hu) / 2.0;
494  itsOrbit[Y] = ((su + sv) * py - (su - sv) * pv +
495  (du + dv) * hy - (du - dv) * hv) / 2.0;
496  itsOrbit[PY] = ((cu + cv) * py - (cu - cv) * pv +
497  (su + sv) * hy - (su - sv) * hv) / 2.0;
498  itsOrbit[T] += ((du + dv) * px + (du - dv) * pu +
499  (fu + fv) * hx + (fu - fv) * hu) * (h / 2.0);
500  }
501 
502  // Add in constant terms.
503  itsOrbit[X] += x;
504  itsOrbit[Y] += y;
505  itsOrbit[T] += refTime * pt + length * h * x;
506 }
507 
508 
509 void OrbitTracker::applyMultipoleBody(double length, double refLength,
510  const BMultipoleField &field, double scale) {
511  // Determine normalised field coefficients around actual orbit.
512  // Fx and Fy are the normalised field coefficients,
513  // expressed as linear functions in x and y.
514  int order = field.order();
515 
516  if(order > 0) {
517  static Series2 x = Series2::makeVariable(0);
518  static Series2 y = Series2::makeVariable(1);
519 
520  Series2 Fx = field.normal(order);
521  Series2 Fy = - field.skew(order);
522 
523  while(order > 1) {
524  Series2 Fxt = x * Fx - y * Fy;
525  Series2 Fyt = x * Fy + y * Fx;
526  --order;
527  Fx = Fxt + field.normal(order);
528  Fy = Fyt - field.skew(order);
529  };
530  Fx.setTruncOrder(Fx.getMaxOrder());
531  Fy.setTruncOrder(Fy.getMaxOrder());
532 
533  Fx *= scale;
534  Fy *= scale;
535 
536  FVps<double, 2> to_fixpt;
537  to_fixpt[0] += itsOrbit[X];
538  to_fixpt[1] += itsOrbit[Y];
539 
540  Fx = Fx.substitute(to_fixpt);
541  Fy = Fy.substitute(to_fixpt);
542  applyLinearMap(length, refLength, 0.0, Fx, Fy);
543  } else applyDrift(length);
544 }
545 
546 
547 void OrbitTracker::applySBendBody(double length, double refLength, double h,
548  const BMultipoleField &field, double scale) {
549  // Determine normalised field coefficients around actual orbit.
550  // As is the vector potential times (1 + h*x),
551  // expressed as a linear function in x and y.
552  Series2 As = buildSBendVectorPotential(field, h) * scale;
553 
554  // Fx and Fy are the normalised field coefficients times (1 + h*x).
555  Series2 Fx = + As.derivative(0);
556  Series2 Fy = - As.derivative(1);
557  applyLinearMap(length, refLength, h, Fx, Fy);
558 }
559 
560 
562 (const BMultipoleField &field, double factor) {
563  int order = field.order();
564 
565  if(order > 0) {
566  double x = itsOrbit[X];
567  double y = itsOrbit[Y];
568  double kx = + field.normal(order);
569  double ky = - field.skew(order);
570 
571  while(--order > 0) {
572  double kxt = x * kx - y * ky;
573  double kyt = x * ky + y * kx;
574  kx = kxt + field.normal(order);
575  ky = kyt - field.skew(order);
576  }
577 
578  itsOrbit[PX] -= kx * factor;
579  itsOrbit[PY] += ky * factor;
580  }
581 }
582 
583 
584 void OrbitTracker::applyTransform(const Euclid3D &euclid, double refLength) {
585  if(! euclid.isIdentity()) {
586  double px1 = itsOrbit[PX];
587  double py1 = itsOrbit[PY];
588  double pt = itsOrbit[PT] + 1.0;
589  double pz1 = sqrt(pt * pt - px1 * px1 - py1 * py1);
590 
591  itsOrbit[PX] = euclid.M(0, 0) * px1 + euclid.M(1, 0) * py1 + euclid.M(2, 0) * pz1;
592  itsOrbit[PY] = euclid.M(0, 1) * px1 + euclid.M(1, 1) * py1 + euclid.M(2, 1) * pz1;
593  double pz2 = euclid.M(0, 2) * px1 + euclid.M(1, 2) * py1 + euclid.M(2, 2) * pz1;
594 
595  double x = itsOrbit[X] - euclid.getX();
596  double y = itsOrbit[Y] - euclid.getY();
597  double x2 =
598  euclid.M(0, 0) * x + euclid.M(1, 0) * y + euclid.M(2, 0) * euclid.getZ();
599  double y2 =
600  euclid.M(0, 1) * x + euclid.M(1, 1) * y + euclid.M(2, 1) * euclid.getZ();
601  double s2 =
602  euclid.M(0, 2) * x + euclid.M(1, 2) * y + euclid.M(2, 2) * euclid.getZ();
603  double sByPz = s2 / pz2;
604 
605  double kin = itsReference.getM() / itsReference.getP();
606  double E = sqrt(pt * pt + kin * kin);
607  double refTime = refLength / itsReference.getBeta();
608  itsOrbit[X] = x2 - sByPz * itsOrbit[PX];
609  itsOrbit[Y] = y2 - sByPz * itsOrbit[PY];
610  itsOrbit[T] += pt * (- refTime / E + sByPz);
611  }
612 }
613 
614 
615 Series2
617  // Check sanity.
618  if(h == 0.) {
619  std::cerr << " <*** ERROR ***> in LinearMapper::buildSBendVectorPotential():\n"
620  << " attempt to use an infinite radius of curvature." << std::endl;
621  throw DomainError("buildSBendVectorPotential(const BMultipoleField &, double)");
622  }
623 
624  int order = field.order();
625  Series2 As;
626 
627  if(order > 0) {
628  static Series2 x = Series2::makeVariable(0);
629  static Series2 y = Series2::makeVariable(1);
630 
631  // Terms even in y.
632  Series2 Ae = + field.normal(order);
633  // Terms odd in y.
634  Series2 Ao = - field.skew(order);
635 
636  int i = order;
637  while(i > 1) {
638  i--;
639  Ae = Ae * x + field.normal(i);
640  Ao = Ao * x - field.skew(i);
641  };
642  Ae.setTruncOrder(Ae.getMaxOrder());
643  Ao.setTruncOrder(Ao.getMaxOrder());
644 
645  {
646  Series2 hx1 = 1. + h * x;
647  Ae = + (Ae * hx1).integral(0);
648  Ao = - (Ao * hx1);
649  }
650  // Add terms up to maximum order.
651  As = Ae + y * Ao;
652 
653  int k = 2;
654  if(k <= order) {
655  Series2 yp = y * y / 2.0;
656  Series2 radius = 1.0 / h + x;
657 
658  while(true) {
659  // Terms even in y.
660  Ae = Ae.derivative(0);
661  Ae = Ae / radius - Ae.derivative(0); // replace this line by following if we decide to treat case h==0.
662  // Ae = (h==0. ? 0. : Ae/radius) - Ae.derivative(0);
663  As += Ae * yp;
664  if(++k > order) break;
665  yp *= y / double(k);
666 
667  // Terms odd in y.
668  Ao = Ao.derivative(0);
669  Ao = Ao / radius - Ao.derivative(0); // replace this line by following if we decide to treat case h==0.
670  // Ao = (h==0. ? 0. : Ao/radius) - Ao.derivative(0);
671  As += Ao * yp;
672  if(++k > order) break;
673  yp *= y / double(k);
674  }
675  }
676  }
677 
678  FVps<double, 2> to_fixpt;
679  to_fixpt[0] += itsOrbit[X];
680  to_fixpt[1] += itsOrbit[Y];
681 
682  return As.substitute(to_fixpt);
683 
684 }
685 
686 
688 (double k, double L, double &c, double &s, double &d, double &f) {
689  double t = k * L * L;
690  if(std::abs(t) < 1.0e-4) {
691  c = 1.0 - t / 2.0;
692  s = L * (1.0 - t / 6.0);
693  d = L * L * (0.5 - t / 24.0);
694  f = L * L * L * ((1.0 / 6.0) - t / 120.0);
695  } else if(k > 0.0) {
696  double r = sqrt(k);
697  c = cos(r * L);
698  s = sin(r * L) / r;
699  d = (1.0 - c) / k;
700  f = (L - s) / k;
701  } else {
702  double r = sqrt(- k);
703  c = cosh(r * L);
704  s = sinh(r * L) / r;
705  d = (1.0 - c) / k;
706  f = (L - s) / k;
707  }
708 }
virtual void visitSolenoid(const Solenoid &)
Apply the algorithm to a solenoid.
virtual void visitCCollimator(const CCollimator &)
Apply the algorithm to a collimator.
double & py()
Get reference to vertical momentum (no dimension).
Definition: OpalParticle.h:122
virtual double getExitFaceRotation() const =0
Get exit pole face rotation.
virtual void visitRBend(const RBend &)
Apply the algorithm to a rectangular bend.
virtual ElementBase * getElement() const
Return the contained element.
Definition: rbendmap.h:8
virtual double getArcLength() const
Get arc length.
Euclid3D & offset() const
Return the offset.
virtual BMultipoleField & getField() override=0
Get multipole expansion of field.
virtual void visitCorrector(const Corrector &)
Apply the algorithm to a corrector.
virtual void visitDegrader(const Degrader &)
Apply the algorithm to a drift.
virtual void visitBeamBeam(const BeamBeam &)
Apply the algorithm to a beam-beam.
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
double getX() const
Get displacement.
Definition: Euclid3D.h:216
virtual BDipoleField & getField()=0
Return the corrector field.
virtual void visitSBend(const SBend &)
Apply the algorithm to a sector bend.
constexpr double e
The value of .
Definition: Physics.h:40
Track particles or bunches.
int getMaxOrder() const
Get maximum order.
Definition: FTps.h:174
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.
Interface for septum magnet.
Definition: Septum.h:11
virtual BMultipoleField & getField() override=0
Get multipole field.
Interface for electrostatic separator.
Definition: Separator.h:33
Euclid3D getExitPatch() const
Get patch.
virtual double getArcLength() const
Get arc length.
void applySBendBody(double length, double refLength, double h, const BMultipoleField &field, double scale)
Apply thin multipole kick (integrated over length) to all particles.
virtual double getPhase() const =0
Get RF phase.
Interface for beam position monitors.
Definition: Monitor.h:41
Interface for RF Quadrupole.
Definition: RFQuadrupole.h:30
A simple arc in the XZ plane.
FVector< double, 6 > itsOrbit
Definition: OrbitTracker.h:183
Definition: rbendmap.h:8
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
double & x()
Get reference to horizontal position in m.
Definition: OpalParticle.h:110
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
virtual void visitParallelPlate(const ParallelPlate &)
Apply the algorithm to a ParallelPlate.
double getZ() const
Get displacement.
Definition: Euclid3D.h:224
virtual double getElementLength() const override
Get design length.
Definition: RFCavity.cpp:818
virtual void visitRFQuadrupole(const RFQuadrupole &)
Apply the algorithm to a RF quadrupole.
virtual Euclid3D getEntranceTransform() const
Get entrance patch.
Particle reference data.
Definition: PartData.h:38
virtual void visitMonitor(const Monitor &)
Apply the algorithm to a monitor.
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.
void applyTransform(const Euclid3D &, double refLength)
Apply transform.
virtual PlanarArcGeometry & getGeometry() override=0
Get SBend geometry.
Definition: rbendmap.h:8
virtual void visitMarker(const Marker &)
Apply the algorithm to a marker.
Tps< T > tan(const Tps< T > &x)
Tangent.
Definition: TpsMath.h:147
virtual double getEntryFaceRotation() const =0
Get pole entry face rotation.
virtual ~OrbitTracker()
Interface for drift space.
Definition: Drift.h:33
virtual void visitAlignWrapper(const AlignWrapper &)
Apply the algorithm to an align wrapper..
double getBeta() const
The relativistic beta per particle.
Definition: PartData.h:127
double M(int row, int col) const
Get component.
Definition: Euclid3D.h:228
Interface for general multipole.
Definition: Multipole.h:46
virtual void visitSeparator(const Separator &)
Apply the algorithm to a separator.
void setOrbit(const FVector< double, 6 > orbit)
Reset the current orbit.
static Euclid3D YRotation(double angle)
Make rotation.
Definition: Euclid3D.cpp:164
void applyLinearMap(double length, double refLength, double h, const FTps< double, 2 > &Fx, const FTps< double, 2 > &Fy)
Apply linear map, defined by the linear expansions Fx and Fy.
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
virtual Euclid3D getExitTransform() const
Get exit patch.
virtual void visitProbe(const Probe &prob)
Apply the algorithm to a probe.
double skew(int) const
Get component.
double getQ() const
The constant charge per particle.
Definition: PartData.h:107
virtual void accept(BeamlineVisitor &visitor) const =0
Apply visitor.
virtual double getElementLength() const
Get design length.
Definition: ElementBase.h:511
virtual void visitComponent(const Component &)
Apply the algorithm to an arbitrary component.
void applyThinMultipole(const BMultipoleField &field, double factor)
Thin multipole kick.
virtual double getFrequency() const =0
Get RF frequencey.
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:52
virtual void trackBunch(PartBunchBase< double, 3 > *bunch, const PartData &, bool revBeam, bool revTrack) const
Track particle bunch.
Definition: Component.cpp:71
Interface for cyclotron collimator.
Definition: CCollimator.h:13
Displacement and rotation in space.
Definition: Euclid3D.h:68
Abstract beam-beam interaction.
Definition: BeamBeam.h:37
void applyDrift(double length)
Apply drift length.
void applyExitFringe(double edge, const BMultipoleField &field, double scale)
Definition: SBend.h:68
bool isIdentity() const
Test for identity.
Definition: Euclid3D.h:233
Interface for cyclotron valley.
virtual double getBx() const
Get horizontal component.
virtual void visitDiagnostic(const Diagnostic &)
Apply the algorithm to a diagnostic.
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 void visitRFCavity(const RFCavity &)
Apply the algorithm to a RF cavity.
const PartData itsReference
The reference information.
virtual void visitSeptum(const Septum &)
Apply the algorithm to a septum.
FTps substitute(const FMatrix< T, N, N > &M, int n) const
Substitute.
Definition: FTps.hpp:1075
virtual double getElementLength() const
Get element length.
double & pt()
Get reference to relative momentum error (no dimension).
Definition: OpalParticle.h:125
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
FTps< double, 2 > buildSBendVectorPotential(const BMultipoleField &, double h)
Construct the vector potential for a SBend.
virtual void visitPatch(const Patch &pat)
Apply the algorithm to a patch.
virtual void visitFlexibleCollimator(const FlexibleCollimator &)
Apply the algorithm to a flexible collimator.
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
double getP() const
The constant reference momentum per particle.
Definition: PartData.h:117
The magnetic field of a multipole.
double hv(FRONT)
virtual void visitLambertson(const Lambertson &)
Apply the algorithm to a Lambertson.
Domain error exception.
Definition: DomainError.h:32
Interface for RF cavity.
Definition: RFCavity.h:37
double getM() const
The constant mass per particle.
Definition: PartData.h:112
void applyMultipoleBody(double length, double refLength, const BMultipoleField &field, double scale)
Apply body of SBend.
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.
virtual void visitBeamStripping(const BeamStripping &)
Apply the algorithm to a beam stripping.
FTps< double, 2 > Series2
double & y()
Get reference to vertical displacement in m.
Definition: OpalParticle.h:113
const FVector< double, 6 > & getOrbit() const
Return the current orbit.
Particle Bunch.
Definition: PartBunch.h:30
void applyEntranceFringe(double edge, const BMultipoleField &field, double scale)
Transforms fringing fields.
double getCurvature() const
Get curvature.
double & t()
Get reference to longitudinal displacement c*t in m.
Definition: OpalParticle.h:116
virtual void visitCyclotronValley(const CyclotronValley &)
Apply the algorithm to a CyclotronValley.
virtual RBendGeometry & getGeometry() override=0
Get RBend geometry.
virtual double getBendAngle() const
Get angle.
static void makeFocus(double k, double L, double &c, double &s, double &d, double &f)
Helper function for finding first-order coefficients.
void setTruncOrder(int order)
Set truncation order.
Definition: FTps.hpp:393
double & px()
Get reference to horizontal momentum (no dimension).
Definition: OpalParticle.h:119
Truncated power series in N variables of type T.
Interface for a geometric patch.
Definition: Patch.h:34
Interface for a single beam element.
Definition: Component.h:51
virtual const Euclid3D & getPatch() const =0
Get patch transform.
Definition: rbendmap.h:8
OpalParticle position.
Definition: OpalParticle.h:38
double getY() const
Get displacement.
Definition: Euclid3D.h:220
virtual void visitDrift(const Drift &)
Apply the algorithm to a drift.
Tps< T > sinh(const Tps< T > &x)
Hyperbolic sine.
Definition: TpsMath.h:204
Vector truncated power series in n variables.
static FTps makeVariable(int var)
Make variable.
Definition: FTps.hpp:481
int order() const
Return order.
Definition: rbendmap.h:8
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
Interface for a Lambertson septum.
Definition: Lambertson.h:33