OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
MPSplitIntegrator.cpp
Go to the documentation of this file.
1 // ------------------------------------------------------------------------
2 // $RCSfile: MPSplitIntegrator.cpp,v $
3 // ------------------------------------------------------------------------
4 // $Revision: 1.1.1.1 $
5 // ------------------------------------------------------------------------
6 // Copyright: see Copyright.readme
7 // ------------------------------------------------------------------------
8 //
9 // Class: MPSplitIntegrator
10 // A MPSplitIntegrator performs integration through an element using two
11 // thin lenses of force 1/2, one placed at 1/6 and the other at 5/6 of
12 // the length respectively.
13 //
14 // ------------------------------------------------------------------------
15 //
16 // $Date: 2000/03/27 09:33:36 $
17 // $Author: Andreas Adelmann $
18 //
19 // ------------------------------------------------------------------------
20 
23 #include "AbsBeamline/Multipole.h"
25 #include "Algorithms/PartData.h"
26 #include "Fields/BMultipoleField.h"
27 #include "FixedAlgebra/FTps.h"
28 #include "FixedAlgebra/FTpsMath.h"
29 #include "FixedAlgebra/FVps.h"
30 #include "Physics/Physics.h"
31 
32 using Physics::c;
33 
34 
35 // Class MPSplitIntegrator
36 // ------------------------------------------------------------------------
37 
39  MapIntegrator(mult), itsMultipole(mult), itsSlices(slices)
40 {}
41 
42 
44  MapIntegrator(rhs), itsSlices(rhs.itsSlices)
45 {}
46 
47 
49 {}
50 
51 
53  return new MPSplitIntegrator(*this);
54 }
55 
56 
58  return itsElement->getGeometry();
59 }
60 
61 
63  return itsElement->getGeometry();
64 }
65 
66 
68  return MPSPLITINTEGRATOR;
69 }
70 
71 
73  bool revBeam, bool revTrack) const {
74  map = FVps<double, 6>();
75  trackMap(map, ref, revBeam, revTrack);
76 }
77 
78 
80  const PartData &ref,
81  bool revBeam, bool revTrack) const {
82  double length = itsMultipole->getElementLength();
83  if(revTrack) length = - length;
85  double scale = (ref.getQ() * c) / (ref.getP());
86  if(revBeam) scale = - scale;
87 
88  if(length) {
89  std::vector<double> slices;
90  getSlices(slices);
91  scale *= length / double(itsSlices);
92 
93  // Drift to first slice position.
94  applyDrift(map, length * slices[0], ref);
95 
96  for(int i = 0; i < itsSlices; ++i) {
97  // Apply first thin multipole kick.
98  applyMultipole(map, field, scale);
99 
100  // Drift to next slice position or to end.
101  applyDrift(map, length * (slices[i+1] - slices[i]), ref);
102  }
103  } else {
104  // Length == 0, slicing not possible.
105  applyMultipole(map, field, scale);
106  }
107 }
108 
109 
111  bool revBeam, bool revTrack) const {
112  double length = itsMultipole->getElementLength();
113  if(revTrack) length = - length;
115  double scale = (ref.getQ() * c) / (ref.getP());
116  if(revBeam) scale = - scale;
117 
118  if(length) {
119  std::vector<double> slices;
120  getSlices(slices);
121  scale *= length / double(itsSlices);
122 
123  // Drift to first slice position.
124  applyDrift(part, length * slices[0], ref);
125 
126  for(int i = 0; i < itsSlices; ++i) {
127  // Apply first thin multipole kick.
128  applyMultipole(part, field, scale);
129 
130  // Drift to next slice position or to end.
131  applyDrift(part, length * (slices[i+1] - slices[i]), ref);
132  }
133  } else {
134  // Length == 0, slicing not possible.
135  applyMultipole(part, field, scale);
136  }
137 }
138 
139 
141  const PartData &ref,
142  bool revBeam, bool revTrack) const {
143  double length = itsMultipole->getElementLength();
144  if(revTrack) length = - length;
146  double scale = (ref.getQ() * c) / (ref.getP());
147  if(revBeam) scale = - scale;
148 
149  if(length) {
150  std::vector<double> slices;
151  getSlices(slices);
152  scale *= length / double(itsSlices);
153  for(unsigned int i = 0; i < bunch->getLocalNum(); i++) {
154  OpalParticle part = bunch->get_part(i);
155 
156  // Drift to first slice position.
157  applyDrift(part, length * slices[0], ref);
158 
159  for(int s = 0; s < itsSlices; ++s) {
160  // Apply first thin multipole kick.
161  applyMultipole(part, field, scale);
162 
163  // Drift to next slice position or to end.
164  applyDrift(part, length * (slices[s+1] - slices[s]), ref);
165  }
166  bunch->set_part(part, i);
167  }
168  } else {
169  // Length == 0, slicing not possible.
170  for(unsigned int i = 0; i < bunch->getLocalNum(); i++) {
171  OpalParticle part = bunch->get_part(i);
172  applyMultipole(part, field, scale);
173  bunch->set_part(part, i);
174  }
175  }
176 }
177 
178 
180  const PartData &reference) const {
181  double kin = reference.getM() / reference.getP();
182  double ref = kin * kin;
183  FTps<double, 6> px = map[1];
184  FTps<double, 6> py = map[3];
185  FTps<double, 6> pt = map[5];
186  FTps<double, 6> lByPz = length / (1.0 + pt);
187  map[0] += px * lByPz;
188  map[2] += py * lByPz;
189  map[4] += length * (pt * ref - (px * px + py * py + (3.0 * ref) * pt * pt) / 2.0);
190 }
191 
192 
193 void MPSplitIntegrator::applyDrift(OpalParticle &part, double length,
194  const PartData &reference) const {
195  double kin = reference.getM() / reference.getP();
196  double ref = kin * kin;
197  double px = part.px();
198  double py = part.py();
199  double pt = part.pt();
200  double lByPz = length / (1.0 + pt);
201  part.x() += px * lByPz;
202  part.y() += py * lByPz;
203  part.t() += length * (pt * ref - (px * px + py * py + (3.0 * ref) * pt * pt) / 2.0);
204 }
205 
206 
208  const BMultipoleField &field,
209  double scale) const {
210  int order = field.order();
211 
212  if(order > 0) {
213  FTps<double, 6> x = map[0];
214  FTps<double, 6> y = map[2];
215  FTps<double, 6> kx = + field.normal(order);
216  FTps<double, 6> ky = - field.skew(order);
217 
218  while(--order > 0) {
219  FTps<double, 6> kxt = x * kx - y * ky;
220  FTps<double, 6> kyt = x * ky + y * kx;
221  kx = kxt + field.normal(order);
222  ky = kyt - field.skew(order);
223  }
224 
225  map[1] -= kx * scale;
226  map[3] += ky * scale;
227  }
228 }
229 
230 
232  const BMultipoleField &field,
233  double scale) const {
234  int order = field.order();
235 
236  if(order > 0) {
237  double x = part.x();
238  double y = part.y();
239  double kx = + field.normal(order);
240  double ky = - field.skew(order);
241 
242  while(--order > 0) {
243  double kxt = x * kx - y * ky;
244  double kyt = x * ky + y * kx;
245  kx = kxt + field.normal(order);
246  ky = kyt - field.skew(order);
247  }
248 
249  part.px() -= kx * scale;
250  part.py() += ky * scale;
251  }
252 }
253 
254 
255 void MPSplitIntegrator::getSlices(std::vector<double> &slices) const {
256  slices.clear();
257  slices.reserve(itsSlices + 1);
258 
259  switch(itsSlices) {
260 
261  case 1:
262  slices.push_back(1.0 / 2.0);
263  break;
264 
265  case 2:
266  slices.push_back(1.0 / 6.0);
267  slices.push_back(5.0 / 6.0);
268  break;
269 
270  case 3:
271  slices.push_back(1.0 / 8.0);
272  slices.push_back(4.0 / 8.0);
273  slices.push_back(7.0 / 8.0);
274  break;
275 
276  case 4:
277  slices.push_back(3.0 / 30.0);
278  slices.push_back(11.0 / 30.0);
279  slices.push_back(19.0 / 30.0);
280  slices.push_back(27.0 / 30.0);
281  break;
282 
283  default: {
284  double step = 1.0 / double(itsSlices);
285  double pos = step / 2.0;
286  for(int i = 1; i < itsSlices; ++i) {
287  slices.push_back(pos);
288  pos += step;
289  }
290  break;
291  }
292  }
293 
294  slices.push_back(1.0);
295 }
double & py()
Get reference to vertical momentum (no dimension).
Definition: OpalParticle.h:122
double normal(int) const
Get component.
virtual BMultipoleField & getField() override=0
Get multipole field.
void getSlices(std::vector< double > &v) const
Return slice positions.
virtual MPSplitIntegrator * clone() const
Make clone.
virtual BGeometryBase & getGeometry()=0
Get geometry.
double & x()
Get reference to horizontal position in m.
Definition: OpalParticle.h:110
Particle reference data.
Definition: PartData.h:38
virtual BGeometryBase & getGeometry()
Get geometry.
Interface for general multipole.
Definition: Multipole.h:46
Abstract base class for accelerator geometry classes.
Definition: Geometry.h:43
double skew(int) const
Get component.
double getQ() const
The constant charge per particle.
Definition: PartData.h:107
virtual double getElementLength() const
Get design length.
Definition: ElementBase.h:511
OpalParticle get_part(int ii)
virtual void getMap(FVps< double, 6 > &map, const PartData &data, bool revBeam, bool revTrack) const
Get map from MPSplitIntegrator.
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:52
Pointer< ElementBase > itsElement
Pointer to the replaced element.
Definition: Integrator.h:84
Multipole * itsMultipole
size_t getLocalNum() const
void set_part(FVector< double, 6 > z, int ii)
double & pt()
Get reference to relative momentum error (no dimension).
Definition: OpalParticle.h:125
double getP() const
The constant reference momentum per particle.
Definition: PartData.h:117
void applyMultipole(FVps< double, 6 > &map, const BMultipoleField &field, double factor) const
virtual ElementBase::ElementType getType() const
Get element type string.
The magnetic field of a multipole.
double getM() const
The constant mass per particle.
Definition: PartData.h:112
virtual void trackParticle(OpalParticle &part, const PartData &data, bool revBeam, bool revTrack) const
Track particle through MPSplitIntegrator.
void applyDrift(FVps< double, 6 > &map, double, const PartData &) const
virtual void trackBunch(PartBunchBase< double, 3 > *bunch, const PartData &data, bool revBeam, bool revTrack) const
Track particle bunch through MPSplitIntegrator.
double & y()
Get reference to vertical displacement in m.
Definition: OpalParticle.h:113
Integrator replacing each multipole by a set of thin lenses.
virtual void trackMap(FVps< double, 6 > &map, const PartData &data, bool revBeam, bool revTrack) const
Track map through MPSplitIntegrator.
double & t()
Get reference to longitudinal displacement c*t in m.
Definition: OpalParticle.h:116
double & px()
Get reference to horizontal momentum (no dimension).
Definition: OpalParticle.h:119
OpalParticle position.
Definition: OpalParticle.h:38
int order() const
Return order.
Integrate a map.
Definition: MapIntegrator.h:41