OPAL (Object Oriented Parallel Accelerator Library) 2022.1
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"
64
65//FIXME Remove headers and dynamic_cast in readOneBunchFromFile
67#ifdef ENABLE_AMR
69#endif
70
71#include <cfloat>
72#include <cmath>
73#include <limits>
74
77
78// Class Tracker
79// ------------------------------------------------------------------------
80
81
82Tracker::Tracker(const Beamline &beamline, const PartData &reference,
83 bool backBeam, bool backTrack):
84 Tracker(beamline, nullptr, reference, backBeam, backTrack)
85{}
86
87
88Tracker::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
122void 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
189void 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
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
331Series
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}
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition: Vector3D.cpp:118
FTps< double, 6 > Series
Definition: Tracker.cpp:76
FTps< double, 2 > Series2
Definition: Tracker.cpp:75
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
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