OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
Multipole.cpp
Go to the documentation of this file.
1 // ------------------------------------------------------------------------
2 // $RCSfile: Multipole.cpp,v $
3 // ------------------------------------------------------------------------
4 // $Revision: 1.1.1.1 $
5 // ------------------------------------------------------------------------
6 // Copyright: see Copyright.readme
7 // ------------------------------------------------------------------------
8 //
9 // Class: Multipole
10 // Defines the abstract interface for a Multipole magnet.
11 //
12 // ------------------------------------------------------------------------
13 // Class category: AbsBeamline
14 // ------------------------------------------------------------------------
15 //
16 // $Date: 2000/03/27 09:32:31 $
17 // $Author: fci $
18 //
19 // ------------------------------------------------------------------------
20 
21 #include "AbsBeamline/Multipole.h"
24 #include "Fields/Fieldmap.h"
25 #include "Physics/Physics.h"
26 
27 extern Inform *gmsg;
28 
29 namespace{
30  enum {
31  DIPOLE,
32  QUADRUPOLE,
33  SEXTUPOLE,
34  OCTUPOLE,
35  DECAPOLE
36  };
37 }
38 
39 // Class Multipole
40 // ------------------------------------------------------------------------
41 
43  Multipole("")
44 {}
45 
46 
48  Component(right),
49  NormalComponents(right.NormalComponents),
50  NormalComponentErrors(right.NormalComponentErrors),
51  SkewComponents(right.SkewComponents),
52  SkewComponentErrors(right.SkewComponentErrors),
53  max_SkewComponent_m(right.max_SkewComponent_m),
54  max_NormalComponent_m(right.max_NormalComponent_m),
55  nSlices_m(right.nSlices_m) {
57 }
58 
59 
60 Multipole::Multipole(const std::string &name):
61  Component(name),
62  NormalComponents(1, 0.0),
63  NormalComponentErrors(1, 0.0),
64  SkewComponents(1, 0.0),
65  SkewComponentErrors(1, 0.0),
66  max_SkewComponent_m(1),
67  max_NormalComponent_m(1),
68  nSlices_m(1) {
70 }
71 
72 
74 {}
75 
76 
77 void Multipole::accept(BeamlineVisitor &visitor) const {
78  visitor.visitMultipole(*this);
79 }
80 
81 
82 double Multipole::getNormalComponent(int n) const {
83  if (n < max_NormalComponent_m) {
84  return NormalComponents[n];
85  }
86  return 0.0;
87 }
88 
89 
90 double Multipole::getSkewComponent(int n) const {
91  if (n < max_SkewComponent_m) {
92  return SkewComponents[n];
93  }
94  return 0.0;
95 }
96 
97 
98 void Multipole::setNormalComponent(int n, double v, double vError) {
99  // getField().setNormalComponent(n, v);
100  PAssert_GE(n, 1);
101 
102  if(n > max_NormalComponent_m) {
106  }
107  switch(n-1) {
108  case DIPOLE:
109  NormalComponents[n - 1] = (v + vError) / 2;
110  NormalComponentErrors[n - 1] = NormalComponents[n - 1];
111  break;
112  case SEXTUPOLE:
113  NormalComponents[n - 1] = (v + vError) / 2;
114  NormalComponentErrors[n - 1] = vError / 2;
115  break;
116  case OCTUPOLE:
117  case DECAPOLE:
118  NormalComponents[n - 1] = (v + vError) / 24;
119  NormalComponentErrors[n - 1] = vError / 24;
120  break;
121  default:
122  NormalComponents[n - 1] = (v + vError);
123  NormalComponentErrors[n - 1] = vError;
124  }
125 }
126 
127 void Multipole::setSkewComponent(int n, double v, double vError) {
128  // getField().setSkewComponent(n, v);
129  PAssert_GT(n, 1);
130 
131  if(n > max_SkewComponent_m) {
133  SkewComponents.resize(max_SkewComponent_m, 0.0);
135  }
136  switch(n-1) {
137  case DIPOLE:
138  SkewComponents[n - 1] = (v + vError) / 2;
139  SkewComponentErrors[n - 1] = SkewComponents[n - 1];
140  break;
141  case SEXTUPOLE:
142  SkewComponents[n - 1] = (v + vError) / 2;
143  SkewComponentErrors[n - 1] = vError / 2;
144  break;
145  case OCTUPOLE:
146  SkewComponents[n - 1] = (v + vError) / 6;
147  SkewComponentErrors[n - 1] = vError / 6;
148  break;
149  case DECAPOLE:
150  SkewComponents[n - 1] = (v + vError) / 24;
151  SkewComponentErrors[n - 1] = vError / 24;
152  break;
153  default:
154  SkewComponents[n - 1] = (v + vError);
155  SkewComponentErrors[n - 1] = vError;
156  }
157 }
158 
159 //set the number of slices for map tracking
160 void Multipole::setNSlices(const std::size_t& nSlices) {
161  nSlices_m = nSlices;
162 }
163 
164 //get the number of slices for map tracking
165 std::size_t Multipole::getNSlices() const {
166  return nSlices_m;
167 }
168 
169 //ff
170 // radial focussing term
171 void Multipole::addKR(int i, double t, Vector_t &K) {
172  Inform msg("Multipole::addK()");
173 
174  double b = RefPartBunch_m->getBeta(i);
175  double g = RefPartBunch_m->getGamma(i); //1 / sqrt(1 - b * b);
176 
177  // calculate the average of all normal components, to obtain the gradient
178  double l = NormalComponents.size();
179  double temp_n = 0;
180  for(int j = 0; j < l; j++)
181  temp_n += NormalComponents.at(j);
182 
183  double Grad = temp_n / l;
184  double k = -Physics::q_e * b * Physics::c * Grad / (g * Physics::EMASS);
185  //FIXME: factor? k *= 5?
186 
187  //FIXME: sign?
188  Vector_t temp(k, -k, 0.0);
189 
190  K += temp;
191 }
192 
193 //ff
194 //transverse kick
195 void Multipole::addKT(int i, double t, Vector_t &K) {
196  Inform msg("Multipole::addK()");
197 
198  Vector_t tmpE(0.0, 0.0, 0.0);
199  Vector_t tmpB(0.0, 0.0, 0.0);
200  Vector_t tmpE_diff(0.0, 0.0, 0.0);
201  Vector_t tmpB_diff(0.0, 0.0, 0.0);
202 
203  double b = RefPartBunch_m->getBeta(i);
204  double g = RefPartBunch_m->getGamma(i);
205 
206  // calculate the average of all normal components, to obtain the gradient
207 
208  double l = NormalComponents.size();
209  double temp_n = 0;
210  for(int j = 0; j < l; j++)
211  temp_n += NormalComponents.at(j);
212 
213  double G = temp_n / l;
214  double cf = -Physics::q_e * b * Physics::c * G / (g * Physics::EMASS);
215  double dx = RefPartBunch_m->getX0(i);
216  double dy = RefPartBunch_m->getY0(i);
217 
218  K += Vector_t(cf * dx, -cf * dy, 0.0);
219 }
220 
222  {
223  std::vector<Vector_t> Rn(max_NormalComponent_m + 1);
224  std::vector<double> fact(max_NormalComponent_m + 1);
225  Rn[0] = Vector_t(1.0);
226  fact[0] = 1;
227  for (int i = 0; i < max_NormalComponent_m; ++ i) {
228  switch(i) {
229  case DIPOLE:
230  B(1) += NormalComponents[i];
231  break;
232 
233  case QUADRUPOLE:
234  B(0) += NormalComponents[i] * R(1);
235  B(1) += NormalComponents[i] * R(0);
236  break;
237 
238  case SEXTUPOLE:
239  B(0) += 2 * NormalComponents[i] * R(0) * R(1);
240  B(1) += NormalComponents[i] * (Rn[2](0) - Rn[2](1));
241  break;
242 
243  case OCTUPOLE:
244  B(0) += NormalComponents[i] * (3 * Rn[2](0) * Rn[1](1) - Rn[3](1));
245  B(1) += NormalComponents[i] * (Rn[3](0) - 3 * Rn[1](0) * Rn[2](1));
246  break;
247 
248  case DECAPOLE:
249  B(0) += 4 * NormalComponents[i] * (Rn[3](0) * Rn[1](1) - Rn[1](0) * Rn[3](1));
250  B(1) += NormalComponents[i] * (Rn[4](0) - 6 * Rn[2](0) * Rn[2](1) + Rn[4](1));
251  break;
252 
253  default:
254  {
255  double powMinusOne = 1;
256  double Bx = 0.0, By = 0.0;
257  for (int j = 1; j <= (i + 1) / 2; ++ j) {
258  Bx += powMinusOne * NormalComponents[i] * (Rn[i - 2 * j + 1](0) * fact[i - 2 * j + 1] *
259  Rn[2 * j - 1](1) * fact[2 * j - 1]);
260  By += powMinusOne * NormalComponents[i] * (Rn[i - 2 * j + 2](0) * fact[i - 2 * j + 2] *
261  Rn[2 * j - 2](1) * fact[2 * j - 2]);
262  powMinusOne *= -1;
263  }
264 
265  if ((i + 1) / 2 == i / 2) {
266  int j = (i + 2) / 2;
267  By += powMinusOne * NormalComponents[i] * (Rn[i - 2 * j + 2](0) * fact[i - 2 * j + 2] *
268  Rn[2 * j - 2](1) * fact[2 * j - 2]);
269  }
270  B(0) += Bx;
271  B(1) += By;
272  }
273  }
274 
275  Rn[i + 1](0) = Rn[i](0) * R(0);
276  Rn[i + 1](1) = Rn[i](1) * R(1);
277  fact[i + 1] = fact[i] / (i + 1);
278  }
279  }
280 
281  {
282 
283  std::vector<Vector_t> Rn(max_SkewComponent_m + 1);
284  std::vector<double> fact(max_SkewComponent_m + 1);
285  Rn[0] = Vector_t(1.0);
286  fact[0] = 1;
287  for (int i = 0; i < max_SkewComponent_m; ++ i) {
288  switch(i) {
289  case DIPOLE:
290  B(0) -= SkewComponents[i];
291  break;
292 
293  case QUADRUPOLE:
294  B(0) -= SkewComponents[i] * R(0);
295  B(1) += SkewComponents[i] * R(1);
296  break;
297 
298  case SEXTUPOLE:
299  B(0) -= SkewComponents[i] * (Rn[2](0) - Rn[2](1));
300  B(1) += 2 * SkewComponents[i] * R(0) * R(1);
301  break;
302 
303  case OCTUPOLE:
304  B(0) -= SkewComponents[i] * (Rn[3](0) - 3 * Rn[1](0) * Rn[2](1));
305  B(1) += SkewComponents[i] * (3 * Rn[2](0) * Rn[1](1) - Rn[3](1));
306  break;
307 
308  case DECAPOLE:
309  B(0) -= SkewComponents[i] * (Rn[4](0) - 6 * Rn[2](0) * Rn[2](1) + Rn[4](1));
310  B(1) += 4 * SkewComponents[i] * (Rn[3](0) * Rn[1](1) - Rn[1](0) * Rn[3](1));
311  break;
312 
313  default:
314  {
315  double powMinusOne = 1;
316  double Bx = 0, By = 0;
317  for (int j = 1; j <= (i + 1) / 2; ++ j) {
318  Bx -= powMinusOne * SkewComponents[i] * (Rn[i - 2 * j + 2](0) * fact[i - 2 * j + 2] *
319  Rn[2 * j - 2](1) * fact[2 * j - 2]);
320  By += powMinusOne * SkewComponents[i] * (Rn[i - 2 * j + 1](0) * fact[i - 2 * j + 1] *
321  Rn[2 * j - 1](1) * fact[2 * j - 1]);
322  powMinusOne *= -1;
323  }
324 
325  if ((i + 1) / 2 == i / 2) {
326  int j = (i + 2) / 2;
327  Bx -= powMinusOne * SkewComponents[i] * (Rn[i - 2 * j + 2](0) * fact[i - 2 * j + 2] *
328  Rn[2 * j - 2](1) * fact[2 * j - 2]);
329  }
330 
331  B(0) += Bx;
332  B(1) += By;
333  }
334  }
335 
336  Rn[i + 1](0) = Rn[i](0) * R(0);
337  Rn[i + 1](1) = Rn[i](1) * R(1);
338  fact[i + 1] = fact[i] / (i + 1);
339  }
340  }
341 }
342 
343 
344 bool Multipole::apply(const size_t &i, const double &, Vector_t &E, Vector_t &B) {
345  const Vector_t &R = RefPartBunch_m->R[i];
346  if(R(2) < 0.0 || R(2) > getElementLength()) return false;
347  if (!isInsideTransverse(R)) return true;
348 
349  Vector_t Ef(0.0), Bf(0.0);
350  computeField(R, Ef, Bf);
351 
352  for (unsigned int d = 0; d < 3; ++ d) {
353  E[d] += Ef(d);
354  B[d] += Bf(d);
355  }
356 
357  return false;
358 }
359 
360 bool Multipole::apply(const Vector_t &R, const Vector_t &, const double &, Vector_t &E, Vector_t &B) {
361  if(R(2) < 0.0 || R(2) > getElementLength()) return false;
362  if (!isInsideTransverse(R)) return true;
363 
364  computeField(R, E, B);
365 
366  return false;
367 }
368 
369 bool Multipole::applyToReferenceParticle(const Vector_t &R, const Vector_t &, const double &, Vector_t &E, Vector_t &B) {
370  if(R(2) < 0.0 || R(2) > getElementLength()) return false;
371  if (!isInsideTransverse(R)) return true;
372 
373  for (int i = 0; i < max_NormalComponent_m; ++ i) {
375  }
376  for (int i = 0; i < max_SkewComponent_m; ++ i) {
378  }
379 
380  computeField(R, E, B);
381 
382  for (int i = 0; i < max_NormalComponent_m; ++ i) {
384  }
385  for (int i = 0; i < max_SkewComponent_m; ++ i) {
387  }
388 
389  return false;
390 }
391 
392 void Multipole::initialise(PartBunchBase<double, 3> *bunch, double &startField, double &endField) {
393  RefPartBunch_m = bunch;
394  endField = startField + getElementLength();
395  online_m = true;
396 }
397 
398 
400  online_m = false;
401 }
402 
403 bool Multipole::bends() const {
404  return false;
405 }
406 
407 
408 void Multipole::getDimensions(double &zBegin, double &zEnd) const {
409  zBegin = 0.0;
410  zEnd = getElementLength();
411 }
412 
413 
415  return MULTIPOLE;
416 }
417 
418 
419 bool Multipole::isInside(const Vector_t &r) const {
420  if (r(2) >= 0.0 && r(2) < getElementLength()) {
421  return isInsideTransverse(r);
422  }
423 
424  return false;
425 }
426 
427 bool Multipole::isFocusing(unsigned int component) const {
428  if (component >= NormalComponents.size()) throw GeneralClassicException("Multipole::isFocusing", "component to big");
429 
430  return NormalComponents[component] * std::pow(-1, component + 1) * RefPartBunch_m->getChargePerParticle() > 0.0;
431 }
virtual bool isInside(const Vector_t &r) const override
Definition: Multipole.cpp:419
double getNormalComponent(int n) const
Get normal component.
Definition: Multipole.cpp:82
void setSkewComponent(int, double)
Set skew component.
Definition: Multipole.h:155
virtual ~Multipole()
Definition: Multipole.cpp:73
virtual void addKT(int i, double t, Vector_t &K) override
Definition: Multipole.cpp:195
std::vector< double > NormalComponentErrors
Definition: Multipole.h:141
bool isFocusing(unsigned int component) const
Definition: Multipole.cpp:427
virtual void accept(BeamlineVisitor &) const override
Apply visitor to Multipole.
Definition: Multipole.cpp:77
void setNormalComponent(int, double)
Set normal component.
Definition: Multipole.h:150
Inform * gmsg
Definition: Main.cpp:21
bool online_m
Definition: Component.h:201
virtual void getDimensions(double &zBegin, double &zEnd) const override
Definition: Multipole.cpp:408
virtual bool applyToReferenceParticle(const Vector_t &R, const Vector_t &P, const double &t, Vector_t &E, Vector_t &B) override
Definition: Multipole.cpp:369
Interface for general multipole.
Definition: Multipole.h:46
Field< Vektor< T, 1U >, 1U, Cartesian< 1U, MFLOAT >, Cell > & Grad(Field< T, 1U, Cartesian< 1U, MFLOAT >, Vert > &x, Field< Vektor< T, 1U >, 1U, Cartesian< 1U, MFLOAT >, Cell > &r)
Definition: Cartesian.hpp:2709
int max_NormalComponent_m
Definition: Multipole.h:145
virtual bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) override
Definition: Multipole.cpp:344
virtual double getGamma(int i)
#define PAssert_GE(a, b)
Definition: PAssert.h:124
std::vector< double > NormalComponents
Definition: Multipole.h:140
void setElType(ElemType elt)
set the element type as enumeration needed in the envelope tracker
Definition: ElementBase.h:591
virtual double getElementLength() const
Get design length.
Definition: ElementBase.h:511
double getSkewComponent(int n) const
Get skew component.
Definition: Multipole.cpp:90
virtual double getBeta(int i)
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:52
double getChargePerParticle() const
get the macro particle charge
virtual double getY0(int i)
std::size_t getNSlices() const
Definition: Multipole.cpp:165
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:200
virtual bool bends() const override
Definition: Multipole.cpp:403
virtual void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField) override
Definition: Multipole.cpp:392
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
Definition: TpsMath.h:76
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6
void computeField(Vector_t R, Vector_t &E, Vector_t &B)
Definition: Multipole.cpp:221
std::vector< double > SkewComponents
Definition: Multipole.h:142
#define PAssert_GT(a, b)
Definition: PAssert.h:123
virtual double getX0(int i)
virtual void finalise() override
Definition: Multipole.cpp:399
constexpr double q_e
The elementary charge in As.
Definition: Physics.h:76
const std::string name
std::vector< double > SkewComponentErrors
Definition: Multipole.h:143
ParticlePos_t & R
constexpr double EMASS
Definition: Physics.h:140
bool isInsideTransverse(const Vector_t &r, double f=1) const
Definition: ElementBase.h:645
Interface for a single beam element.
Definition: Component.h:51
int max_SkewComponent_m
Definition: Multipole.h:144
#define K
Definition: integrate.cpp:118
virtual void visitMultipole(const Multipole &)=0
Apply the algorithm to a multipole.
Abstract algorithm.
Definition: Inform.h:41
std::size_t nSlices_m
Definition: Multipole.h:146
void setNSlices(const std::size_t &nSlices)
Definition: Multipole.cpp:160
virtual void addKR(int i, double t, Vector_t &K) override
Definition: Multipole.cpp:171
virtual ElementBase::ElementType getType() const override
Get element type std::string.
Definition: Multipole.cpp:414