OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
Tracker.cpp
Go to the documentation of this file.
1 //
2 // Class Tracker
3 // Track particles or bunches.
4 // An abstract base class for all visitors capable of tracking particles
5 // through a beam element.
6 // [P]
7 // Phase space coordinates (in this order):
8 // [DL]
9 // [DT]x:[DD]
10 // horizontal displacement (metres).
11 // [DT]p_x/p_r:[DD]
12 // horizontal canonical momentum (no dimension).
13 // [DT]y:[DD]
14 // vertical displacement (metres).
15 // [DT]p_y/p_r:[DD]
16 // vertical canonical momentum (no dimension).
17 // [DT]delta_p/p_r:[DD]
18 // relative momentum error (no dimension).
19 // [DT]v*delta_t:[DD]
20 // time difference delta_t w.r.t. the reference frame which moves with
21 // uniform velocity
22 // [P]
23 // v_r = c*beta_r = p_r/m
24 // [P]
25 // along the design orbit, multiplied by the instantaneous velocity v of
26 // the particle (metres).
27 // [/DL]
28 // Where
29 // [DL]
30 // [DT]p_r:[DD]
31 // is the constant reference momentum defining the reference frame velocity.
32 // [DT]m:[DD]
33 // is the rest mass of the particles.
34 // [/DL]
35 // Other units used:
36 // [DL]
37 // [DT]reference momentum:[DD]
38 // electron-volts.
39 // [DT]accelerating voltage:[DD]
40 // volts.
41 // [DT]separator voltage:[DD]
42 // volts.
43 // [DT]frequencies:[DD]
44 // hertz.
45 // [DT]phase lags:[DD]
46 // multiples of (2*pi).
47 // [/DL]
48 //
49 // Copyright (c) 200x - 2020, Paul Scherrer Institut, Villigen PSI, Switzerland
50 // All rights reserved
51 //
52 // This file is part of OPAL.
53 //
54 // OPAL is free software: you can redistribute it and/or modify
55 // it under the terms of the GNU General Public License as published by
56 // the Free Software Foundation, either version 3 of the License, or
57 // (at your option) any later version.
58 //
59 // You should have received a copy of the GNU General Public License
60 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
61 //
62 #include "Algorithms/Tracker.h"
63 #include "Fields/BMultipoleField.h"
64 
65 //FIXME Remove headers and dynamic_cast in readOneBunchFromFile
66 #include "Algorithms/PartBunch.h"
67 #ifdef ENABLE_AMR
68  #include "Algorithms/AmrPartBunch.h"
69 #endif
70 
71 #include <cfloat>
72 #include <cmath>
73 #include <limits>
74 
77 
78 // Class Tracker
79 // ------------------------------------------------------------------------
80 
81 
82 Tracker::Tracker(const Beamline &beamline, const PartData &reference,
83  bool backBeam, bool backTrack):
84  Tracker(beamline, nullptr, reference, backBeam, backTrack)
85 {}
86 
87 
88 Tracker::Tracker(const Beamline &beamline,
90  const PartData &reference,
91  bool backBeam, bool backTrack):
92  AbstractTracker(beamline, reference, backBeam, backTrack),
93  itsBeamline_m(beamline),
94  itsBunch_m(bunch)
95 {}
96 
97 
99 {}
100 
101 
103  return itsBunch_m;
104 }
105 
106 
108  itsBunch_m->push_back(part);
109 }
110 
111 
112 //~ void Tracker::setBunch(const PartBunch &bunch) {
113  //~ itsBunch_m = &bunch;
114 //~ }
115 
116 
119 }
120 
121 
122 void Tracker::applyDrift(double length) {
123  double kin = itsReference.getM() / itsReference.getP();
124  double refTime = length / itsReference.getBeta();
125 
126  for(unsigned int i = 0; i < itsBunch_m->getLocalNum(); i++) {
128  if(part.getX() != std::numeric_limits<double>::max()) {
129  const Vector_t& P = part.getP();
130  double lByPz = length / std::sqrt(2 * P[2] * P[2] - dot(P, P));
131  part.setX(part.getX() + P[0] * lByPz);
132  part.setY(part.getY() + P[1] * lByPz);
133  part.setZ(part.getZ() + P[2] * (refTime / std::sqrt(P[2] * P[2] + kin * kin) - lByPz));
134  }
135  itsBunch_m->setParticle(part, i);
136  }
137 }
138 
139 
141 (const BMultipoleField &field, double scale) {
142  int order = field.order();
143 
144  if(order > 0) {
145  for(unsigned int i = 0; i < itsBunch_m->getLocalNum(); i++) {
147  if(part.getX() != std::numeric_limits<double>::max()) {
148  double x = part.getX();
149  double y = part.getY();
150  double kx = + field.normal(order);
151  double ky = - field.skew(order);
152 
153  int ord = order;
154  while(--ord > 0) {
155  double kxt = x * kx - y * ky;
156  double kyt = x * ky + y * kx;
157  kx = kxt + field.normal(ord);
158  ky = kyt - field.skew(ord);
159  }
160  part.setPx(part.getPx() - kx * scale);
161  part.setPy(part.getPy() + ky * scale);
162  }
163  itsBunch_m->setParticle(part, i);
164  }
165  }
166 }
167 
168 
170 (const BMultipoleField &field, double scale, double h) {
171  Series2 As = buildSBendVectorPotential2D(field, h) * scale;
172  Series2 Fx = As.derivative(0);
173  Series2 Fy = As.derivative(1);
174 
175  // These substitutions work because As depends on x and y only,
176  // and not on px or py.
177  for(unsigned int i = 0; i < itsBunch_m->getLocalNum(); i++) {
180  z[0] = part.getX();
181  z[1] = part.getY();
182  part.setPx(part.getPx() - Fx.evaluate(z));
183  part.setPy(part.getPy() - Fy.evaluate(z));
184  itsBunch_m->setParticle(part, i);
185  }
186 }
187 
188 
189 void Tracker::applyTransform(const Euclid3D &euclid, double refLength) {
190  if(! euclid.isIdentity()) {
191  double kin = itsReference.getM() / itsReference.getP();
192  double refTime = refLength / itsReference.getBeta();
193 
194  for(unsigned int i = 0; i < itsBunch_m->getLocalNum(); i++) {
196  double px = part.getPx();
197  double py = part.getPy();
198  double pt = part.getPz() + 1.0;
199  double pz = std::sqrt(pt * pt - px * px - py * py);
200 
201  part.setPx(euclid.M(0, 0) * px + euclid.M(1, 0) * py + euclid.M(2, 0) * pz);
202  part.setPy(euclid.M(0, 1) * px + euclid.M(1, 1) * py + euclid.M(2, 1) * pz);
203  pz = euclid.M(0, 2) * px + euclid.M(1, 2) * py + euclid.M(2, 2) * pz;
204 
205  double x = part.getX() - euclid.getX();
206  double y = part.getY() - euclid.getY();
207  double x2 =
208  euclid.M(0, 0) * x + euclid.M(1, 0) * y - euclid.M(2, 0) * euclid.getZ();
209  double y2 =
210  euclid.M(0, 1) * x + euclid.M(1, 1) * y - euclid.M(2, 1) * euclid.getZ();
211  double s2 =
212  euclid.M(0, 2) * x + euclid.M(1, 2) * y - euclid.M(2, 2) * euclid.getZ();
213  double sByPz = s2 / pz;
214 
215  double E = std::sqrt(pt * pt + kin * kin);
216  part.setX(x2 - sByPz * part.getPx());
217  part.setY(y2 - sByPz * part.getPy());
218  part.setZ(part.getZ() + pt * (refTime / E + sByPz));
219  itsBunch_m->setParticle(part, i);
220  }
221  }
222 }
223 
224 
227  int order = field.order();
228 
229  if(order > 0) {
230  static const Series2 x = Series2::makeVariable(0);
231  static const Series2 y = Series2::makeVariable(1);
232  Series2 kx = + field.normal(order) / double(order);
233  Series2 ky = - field.skew(order) / double(order);
234 
235  while(order > 1) {
236  Series2 kxt = x * kx - y * ky;
237  Series2 kyt = x * ky + y * kx;
238  order--;
239  kx = kxt + field.normal(order) / double(order);
240  ky = kyt - field.skew(order) / double(order);
241  }
242 
243  Series2 As = x * kx - y * ky;
244  As.setTruncOrder(As.getMaxOrder());
245  return As;
246  } else {
247  return Series2(0.0);
248  }
249 }
250 
251 
254  int order = field.order();
255 
256  if(order > 0) {
257  static const Series x = Series::makeVariable(X);
258  static const Series y = Series::makeVariable(Y);
259  Series kx = + field.normal(order) / double(order);
260  Series ky = - field.skew(order) / double(order);
261 
262  while(order > 1) {
263  Series kxt = x * kx - y * ky;
264  Series kyt = x * ky + y * kx;
265  order--;
266  kx = kxt + field.normal(order) / double(order);
267  ky = kyt - field.skew(order) / double(order);
268  }
269 
270  Series As = x * kx - y * ky;
271  As.setTruncOrder(As.getMaxOrder());
272  return As;
273  } else {
274  return Series(0.0);
275  }
276 }
277 
278 
279 Series2
281  int order = field.order();
282  Series2 As;
283 
284  if(order > 0) {
285  static const Series2 x = Series2::makeVariable(0);
286  static const Series2 y = Series2::makeVariable(1);
287 
288  // Construct terms constant and linear in y.
289  Series2 Ae = + field.normal(order); // Term even in y.
290  Series2 Ao = - field.skew(order); // Term odd in y.
291 
292  for(int i = order; --i >= 1;) {
293  Ae = Ae * x + field.normal(i);
294  Ao = Ao * x - field.skew(i);
295  }
296  Ae.setTruncOrder(Ae.getMaxOrder());
297  Ao.setTruncOrder(Ao.getMaxOrder());
298 
299  Series2 hx1 = 1. + h * x; // normalized radius
300  Ae = + (Ae * hx1).integral(X);
301  Ao = - (Ao * hx1);
302  // Add terms up to maximum order.
303  As = Ae + y * Ao;
304 
305  int k = 2;
306  if(k <= order) {
307  Series2 yp = y * y / 2.0;
308 
309  while(true) {
310  // Terms even in y.
311  Ae = Ae.derivative(0);
312  Ae = h * Ae / hx1 - Ae.derivative(0);
313  As += Ae * yp;
314  if(++k > order) break;
315  yp *= y / double(k);
316 
317  // Terms odd in y.
318  Ao = Ao.derivative(0);
319  Ao = h * Ao / hx1 - Ao.derivative(0);
320  As += Ao * yp;
321  if(++k > order) break;
322  yp *= y / double(k);
323  }
324  }
325  }
326 
327  return As;
328 }
329 
330 
331 Series
333  int order = field.order();
334  Series As;
335 
336  if(order > 0) {
337  static const Series x = Series::makeVariable(X);
338  static const Series y = Series::makeVariable(Y);
339 
340  // Construct terms constant and linear in y.
341  Series Ae = + field.normal(order); // Term even in y.
342  Series Ao = - field.skew(order); // Term odd in y.
343 
344  for(int i = order; --i >= 1;) {
345  Ae = Ae * x + field.normal(i);
346  Ao = Ao * x - field.skew(i);
347  }
348  Ae.setTruncOrder(Ae.getMaxOrder());
349  Ao.setTruncOrder(Ao.getMaxOrder());
350 
351  Series hx1 = 1. + h * x; // normalized radius
352  Ae = + (Ae * hx1).integral(X);
353  Ao = - (Ao * hx1);
354  // Add terms up to maximum order.
355  As = Ae + y * Ao;
356 
357  int k = 2;
358  if(k <= order) {
359  Series yp = y * y / 2.0;
360 
361  while(true) {
362  // Terms even in y.
363  Ae = Ae.derivative(X);
364  Ae = h * Ae / hx1 - Ae.derivative(X);
365  As += Ae * yp;
366  if(++k > order) break;
367  yp *= y / double(k);
368 
369  // Terms odd in y.
370  Ao = Ao.derivative(X);
371  Ao = h * Ao / hx1 - Ao.derivative(X);
372  As += Ao * yp;
373  if(++k > order) break;
374  yp *= y / double(k);
375  }
376  }
377  }
378 
379  return As;
380 }
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
FTps< double, 6 > Series
Definition: Tracker.cpp:76
FTps< double, 2 > Series2
Definition: Tracker.cpp:75
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition: Vector3D.cpp:118
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:84
size_t getLocalNum() const
void setParticle(FVector< double, 6 > z, int ii)
void push_back(OpalParticle const &p)
OpalParticle getParticle(int ii)
Interface for a single beam element.
Definition: Component.h:50
virtual void trackBunch(PartBunchBase< double, 3 > *bunch, const PartData &, bool revBeam, bool revTrack) const
Track particle bunch.
Definition: Component.cpp:71
Track particles or bunches.
const PartData itsReference
The reference information.
void setPy(double)
Set the vertical momentum.
Definition: OpalParticle.h:146
double getPy() const
Get vertical momentum (no dimension).
Definition: OpalParticle.h:213
const Vector_t & getP() const
Get momentum.
Definition: OpalParticle.h:231
double getPz() const
Get relative momentum error (no dimension).
Definition: OpalParticle.h:219
void setPx(double)
Set the horizontal momentum.
Definition: OpalParticle.h:140
void setZ(double)
Set longitudinal position in m.
Definition: OpalParticle.h:134
void setY(double)
Set the vertical displacement in m.
Definition: OpalParticle.h:128
double getY() const
Get vertical displacement in m.
Definition: OpalParticle.h:195
double getZ() const
Get longitudinal displacement c*t in m.
Definition: OpalParticle.h:201
double getPx() const
Get horizontal momentum (no dimension).
Definition: OpalParticle.h:207
double getX() const
Get horizontal position in m.
Definition: OpalParticle.h:189
void setX(double)
Set the horizontal position in m.
Definition: OpalParticle.h:122
Particle reference data.
Definition: PartData.h:35
double getBeta() const
The relativistic beta per particle.
Definition: PartData.h:124
double getP() const
The constant reference momentum per particle.
Definition: PartData.h:114
double getM() const
The constant mass per particle.
Definition: PartData.h:109
virtual ~Tracker()
Definition: Tracker.cpp:98
void applyThinMultipole(const BMultipoleField &field, double factor)
Definition: Tracker.cpp:141
void applyTransform(const Euclid3D &, double refLength=0.0)
Apply a geometric transformation.
Definition: Tracker.cpp:189
FTps< double, 2 > buildSBendVectorPotential2D(const BMultipoleField &, double h)
Construct vector potential for a SBend.
Definition: Tracker.cpp:280
FTps< double, 6 > buildSBendVectorPotential(const BMultipoleField &, double h)
Construct vector potential for a SBend.
Definition: Tracker.cpp:332
void applyThinSBend(const BMultipoleField &field, double scale, double h)
Definition: Tracker.cpp:170
FTps< double, 6 > buildMultipoleVectorPotential(const BMultipoleField &)
Construct vector potential for a Multipole.
Definition: Tracker.cpp:253
virtual void visitComponent(const Component &)
Store the bunch.
Definition: Tracker.cpp:117
void addToBunch(const OpalParticle &)
Add particle to bunch.
Definition: Tracker.cpp:107
void applyDrift(double length)
Apply a drift length.
Definition: Tracker.cpp:122
PartBunchBase< double, 3 > * itsBunch_m
The bunch of particles to be tracked.
Definition: Tracker.h:151
const PartBunchBase< double, 3 > * getBunch() const
Return the current bunch.
Definition: Tracker.cpp:102
FTps< double, 2 > buildMultipoleVectorPotential2D(const BMultipoleField &)
Construct vector potential for a Multipole.
Definition: Tracker.cpp:226
Displacement and rotation in space.
Definition: Euclid3D.h:68
double getX() const
Get displacement.
Definition: Euclid3D.h:216
double getY() const
Get displacement.
Definition: Euclid3D.h:220
double M(int row, int col) const
Get component.
Definition: Euclid3D.h:228
bool isIdentity() const
Test for identity.
Definition: Euclid3D.h:233
double getZ() const
Get displacement.
Definition: Euclid3D.h:224
An abstract sequence of beam line components.
Definition: Beamline.h:34
The magnetic field of a multipole.
int order() const
Return order.
double normal(int) const
Get component.
double skew(int) const
Get component.
Truncated power series in N variables of type T.
Definition: FTps.h:45
void setTruncOrder(int order)
Set truncation order.
Definition: FTps.hpp:393
FTps derivative(int var) const
Partial derivative.
Definition: FTps.hpp:1396
static FTps makeVariable(int var)
Make variable.
Definition: FTps.hpp:481
T evaluate(const FVector< T, N > &) const
Evaluate FTps at point.
Definition: FTps.hpp:934
int getMaxOrder() const
Get maximum order.
Definition: FTps.h:174
A templated representation for vectors.
Definition: FVector.h:38