OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
TravelingWave.cpp
Go to the documentation of this file.
1 // ------------------------------------------------------------------------
2 // $RCSfile: TravelingWave.cpp,v $
3 // ------------------------------------------------------------------------
4 // $Revision: 1.1.1.1 $
5 // ------------------------------------------------------------------------
6 // Copyright: see Copyright.readme
7 // ------------------------------------------------------------------------
8 //
9 // Class: TravelingWave
10 // Defines the abstract interface for an accelerating structure.
11 //
12 // ------------------------------------------------------------------------
13 // Class category: AbsBeamline
14 // ------------------------------------------------------------------------
15 //
16 // $Date: 2000/03/27 09:32:31 $
17 // $Author: fci $
18 //
19 // ------------------------------------------------------------------------
20 
24 #include "Fields/Fieldmap.h"
25 
26 #include "gsl/gsl_interp.h"
27 #include "gsl/gsl_spline.h"
28 
29 #include <cmath>
30 #include <iostream>
31 #include <fstream>
32 
33 extern Inform *gmsg;
34 
35 // Class TravelingWave
36 // ------------------------------------------------------------------------
37 
39  TravelingWave("")
40 {}
41 
42 
44  RFCavity(right),
45  scaleCore_m(right.scaleCore_m),
46  scaleCoreError_m(right.scaleCoreError_m),
47  phaseCore1_m(right.phaseCore1_m),
48  phaseCore2_m(right.phaseCore2_m),
49  phaseExit_m(right.phaseExit_m),
50  startCoreField_m(right.startCoreField_m),
51  startExitField_m(right.startExitField_m),
52  mappedStartExitField_m(right.mappedStartExitField_m),
53  PeriodLength_m(right.PeriodLength_m),
54  NumCells_m(right.NumCells_m),
55  CellLength_m(right.CellLength_m),
56  Mode_m(right.Mode_m)
57 {}
58 
59 
60 TravelingWave::TravelingWave(const std::string &name):
61  RFCavity(name),
62  scaleCore_m(1.0),
63  scaleCoreError_m(0.0),
64  phaseCore1_m(0.0),
65  phaseCore2_m(0.0),
66  phaseExit_m(0.0),
67  startCoreField_m(0.0),
68  startExitField_m(0.0),
69  mappedStartExitField_m(0.0),
70  PeriodLength_m(0.0),
71  NumCells_m(1),
72  CellLength_m(0.0),
73  Mode_m(1)
74 {}
75 
76 
78 }
79 
80 
81 void TravelingWave::accept(BeamlineVisitor &visitor) const {
82  visitor.visitTravelingWave(*this);
83 }
84 
85 bool TravelingWave::apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) {
86  return apply(RefPartBunch_m->R[i], RefPartBunch_m->P[i], t, E, B);
87 }
88 
89 bool TravelingWave::apply(const Vector_t &R, const Vector_t &/*P*/, const double &t, Vector_t &E, Vector_t &B) {
90  if (R(2) < -0.5 * PeriodLength_m || R(2) + 0.5 * PeriodLength_m >= getElementLength()) return false;
91 
92  Vector_t tmpR = Vector_t(R(0), R(1), R(2) + 0.5 * PeriodLength_m);
93  double tmpcos, tmpsin;
94  Vector_t tmpE(0.0, 0.0, 0.0), tmpB(0.0, 0.0, 0.0);
95 
96  if (tmpR(2) < startCoreField_m) {
97  if (!fieldmap_m->isInside(tmpR)) return true;
98 
100  tmpsin = -(scale_m + scaleError_m) * std::sin(frequency_m * t + phase_m + phaseError_m);
101 
102  } else if (tmpR(2) < startExitField_m) {
103  Vector_t tmpE2(0.0, 0.0, 0.0), tmpB2(0.0, 0.0, 0.0);
104  tmpR(2) -= startCoreField_m;
105  const double z = tmpR(2);
106  tmpR(2) = tmpR(2) - PeriodLength_m * std::floor(tmpR(2) / PeriodLength_m);
107  tmpR(2) += startCoreField_m;
108  if (!fieldmap_m->isInside(tmpR)) return true;
109 
112  fieldmap_m->getFieldstrength(tmpR, tmpE, tmpB);
113  E += tmpcos * tmpE;
114  B += tmpsin * tmpB;
115 
116  tmpE = 0.0;
117  tmpB = 0.0;
118 
119  tmpR(2) = z + CellLength_m;
120  tmpR(2) = tmpR(2) - PeriodLength_m * std::floor(tmpR(2) / PeriodLength_m);
121  tmpR(2) += startCoreField_m;
122 
125 
126  } else {
127  tmpR(2) -= mappedStartExitField_m;
128  if (!fieldmap_m->isInside(tmpR)) return true;
131  }
132 
133  fieldmap_m->getFieldstrength(tmpR, tmpE, tmpB);
134 
135  E += tmpcos * tmpE;
136  B += tmpsin * tmpB;
137 
138  return false;
139 }
140 
141 bool TravelingWave::applyToReferenceParticle(const Vector_t &R, const Vector_t &/*P*/, const double &t, Vector_t &E, Vector_t &B) {
142 
143  if (R(2) < -0.5 * PeriodLength_m || R(2) + 0.5 * PeriodLength_m >= getElementLength()) return false;
144 
145  Vector_t tmpR = Vector_t(R(0), R(1), R(2) + 0.5 * PeriodLength_m);
146  double tmpcos, tmpsin;
147  Vector_t tmpE(0.0, 0.0, 0.0), tmpB(0.0, 0.0, 0.0);
148 
149  if (tmpR(2) < startCoreField_m) {
150  if (!fieldmap_m->isInside(tmpR)) return true;
151  tmpcos = scale_m * std::cos(frequency_m * t + phase_m);
152  tmpsin = -scale_m * std::sin(frequency_m * t + phase_m);
153 
154  } else if (tmpR(2) < startExitField_m) {
155  Vector_t tmpE2(0.0, 0.0, 0.0), tmpB2(0.0, 0.0, 0.0);
156  tmpR(2) -= startCoreField_m;
157  const double z = tmpR(2);
158  tmpR(2) = tmpR(2) - PeriodLength_m * std::floor(tmpR(2) / PeriodLength_m);
159  tmpR(2) += startCoreField_m;
160  if (!fieldmap_m->isInside(tmpR)) return true;
161 
162  tmpcos = scaleCore_m * std::cos(frequency_m * t + phaseCore1_m);
163  tmpsin = -scaleCore_m * std::sin(frequency_m * t + phaseCore1_m);
164  fieldmap_m->getFieldstrength(tmpR, tmpE, tmpB);
165  E += tmpcos * tmpE;
166  B += tmpsin * tmpB;
167 
168  tmpE = 0.0;
169  tmpB = 0.0;
170 
171  tmpR(2) = z + CellLength_m;
172  tmpR(2) = tmpR(2) - PeriodLength_m * std::floor(tmpR(2) / PeriodLength_m);
173  tmpR(2) += startCoreField_m;
174 
175  tmpcos = scaleCore_m * std::cos(frequency_m * t + phaseCore2_m);
176  tmpsin = -scaleCore_m * std::sin(frequency_m * t + phaseCore2_m);
177 
178  } else {
179  tmpR(2) -= mappedStartExitField_m;
180  if (!fieldmap_m->isInside(tmpR)) return true;
181 
182  tmpcos = scale_m * std::cos(frequency_m * t + phaseExit_m);
183  tmpsin = -scale_m * std::sin(frequency_m * t + phaseExit_m);
184  }
185 
186  fieldmap_m->getFieldstrength(tmpR, tmpE, tmpB);
187  E += tmpcos * tmpE;
188  B += tmpsin * tmpB;
189 
190  return false;
191 }
192 
193 void TravelingWave::initialise(PartBunchBase<double, 3> *bunch, double &startField, double &endField) {
194 
195  if (bunch == NULL) {
196  startField = - 0.5 * PeriodLength_m;
197  endField = startExitField_m;
198  return;
199  }
200 
201  Inform msg("TravelingWave ", *gmsg);
202 
203  RefPartBunch_m = bunch;
204  double zBegin = 0.0, zEnd = 0.0;
205  RFCavity::initialise(bunch, zBegin, zEnd);
206  if (std::abs(startField_m) > 0.0) {
207  throw GeneralClassicException("TravelingWave::initialise",
208  "The field map of a traveling wave structure has to begin at 0.0");
209  }
210 
211  PeriodLength_m = (zEnd - zBegin) / 2.0;
213  startField_m = -0.5 * PeriodLength_m;
214 
218 
219  startField = -PeriodLength_m / 2.0;
220  endField = startField + startExitField_m + PeriodLength_m / 2.0;
221  setElementLength(endField - startField);
222 
228 }
229 
231 {}
232 
233 bool TravelingWave::bends() const {
234  return false;
235 }
236 
237 
238 void TravelingWave::goOnline(const double &) {
240  online_m = true;
241 }
242 
245 }
246 
247 void TravelingWave::getDimensions(double &zBegin, double &zEnd) const {
248  zBegin = -0.5 * PeriodLength_m;
249  zEnd = zBegin + getElementLength();
250 }
251 
252 
254  double &end) const {
255  begin = -0.5 * PeriodLength_m;
256  end = begin + getElementLength();
257 }
258 
260  return TRAVELINGWAVE;
261 }
262 
263 double TravelingWave::getAutoPhaseEstimate(const double &E0, const double &t0, const double &q, const double &mass) {
264  std::vector<double> t, E, t2, E2;
265  std::vector<std::pair<double, double> > F;
266  double phi = 0.0, tmp_phi, dphi = 0.5 * Physics::pi / 180.;
267  double phaseC1 = phaseCore1_m - phase_m;
268  double phaseC2 = phaseCore2_m - phase_m;
269  double phaseE = phaseExit_m - phase_m;
270 
272  if (F.size() == 0) return 0.0;
273 
274  int N1 = static_cast<int>(std::floor(F.size() / 4.)) + 1;
275  int N2 = F.size() - 2 * N1 + 1;
276  int N3 = 2 * N1 + static_cast<int>(std::floor((NumCells_m - 1) * N2 * Mode_m)) - 1;
277  int N4 = static_cast<int>(std::round(N2 * Mode_m));
278  double Dz = F[N1 + N2].first - F[N1].first;
279 
280  t.resize(N3, t0);
281  t2.resize(N3, t0);
282  E.resize(N3, E0);
283  E2.resize(N3, E0);
284  for (int i = 1; i < N1; ++ i) {
285  E[i] = E0 + (F[i].first + F[i - 1].first) / 2. * scale_m / mass;
286  E2[i] = E[i];
287  }
288  for (int i = N1; i < N3 - N1 + 1; ++ i) {
289  int I = (i - N1) % N2 + N1;
290  double Z = (F[I].first + F[I - 1].first) / 2. + std::floor((i - N1) / N2) * Dz;
291  E[i] = E0 + Z * scaleCore_m / mass;
292  E2[i] = E[i];
293  }
294  for (int i = N3 - N1 + 1; i < N3; ++ i) {
295  int I = i - N3 - 1 + 2 * N1 + N2;
296  double Z = (F[I].first + F[I - 1].first) / 2. + ((NumCells_m - 1) * Mode_m - 1) * Dz;
297  E[i] = E0 + Z * scale_m / mass;
298  E2[i] = E[i];
299  }
300 
301  for (int iter = 0; iter < 10; ++ iter) {
302  double A = 0.0;
303  double B = 0.0;
304  for (int i = 1; i < N1; ++ i) {
305  t[i] = t[i - 1] + getdT(i, i, E, F, mass);
306  t2[i] = t2[i - 1] + getdT(i, i, E2, F, mass);
307  A += scale_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * getdA(i, i, t, 0.0, F);
308  B += scale_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * getdB(i, i, t, 0.0, F);
309  }
310  for (int i = N1; i < N3 - N1 + 1; ++ i) {
311  int I = (i - N1) % N2 + N1;
312  int J = (i - N1 + N4) % N2 + N1;
313  t[i] = t[i - 1] + getdT(i, I, E, F, mass);
314  t2[i] = t2[i - 1] + getdT(i, I, E2, F, mass);
315  A += scaleCore_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * (getdA(i, I, t, phaseC1, F) + getdA(i, J, t, phaseC2, F));
316  B += scaleCore_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * (getdB(i, I, t, phaseC1, F) + getdB(i, J, t, phaseC2, F));
317  }
318  for (int i = N3 - N1 + 1; i < N3; ++ i) {
319  int I = i - N3 - 1 + 2 * N1 + N2;
320  t[i] = t[i - 1] + getdT(i, I, E, F, mass);
321  t2[i] = t2[i - 1] + getdT(i, I, E2, F, mass);
322  A += scale_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * getdA(i, I, t, phaseE, F);
323  B += scale_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * getdB(i, I, t, phaseE, F);
324  }
325 
326  if (std::abs(B) > 0.0000001) {
327  tmp_phi = std::atan(A / B);
328  } else {
329  tmp_phi = Physics::pi / 2;
330  }
331  if (q * (A * std::sin(tmp_phi) + B * std::cos(tmp_phi)) < 0) {
332  tmp_phi += Physics::pi;
333  }
334 
335  if (std::abs(phi - tmp_phi) < frequency_m * (t[N3 - 1] - t[0]) / N3) {
336  for (int i = 1; i < N1; ++ i) {
337  E[i] = E[i - 1] + q * scale_m * getdE(i, i, t, phi, F);
338  }
339  for (int i = N1; i < N3 - N1 + 1; ++ i) {
340  int I = (i - N1) % N2 + N1;
341  int J = (i - N1 + N4) % N2 + N1;
342  E[i] = E[i - 1] + q * scaleCore_m * (getdE(i, I, t, phi + phaseC1, F) + getdE(i, J, t, phi + phaseC2, F));
343  }
344  for (int i = N3 - N1 + 1; i < N3; ++ i) {
345  int I = i - N3 - 1 + 2 * N1 + N2;
346  E[i] = E[i - 1] + q * scale_m * getdE(i, I, t, phi + phaseE, F);
347  }
348 
349  const int prevPrecision = Ippl::Info->precision(8);
350  INFOMSG(level2 << "estimated phase= " << tmp_phi << " rad = "
351  << tmp_phi * Physics::rad2deg << " deg,\n"
352  << "Ekin= " << E[N3 - 1] << " MeV" << std::setprecision(prevPrecision) << "\n" << endl);
353  return tmp_phi;
354  }
355  phi = tmp_phi - std::round(tmp_phi / Physics::two_pi) * Physics::two_pi;
356 
357 
358  for (int i = 1; i < N1; ++ i) {
359  E[i] = E[i - 1] + q * scale_m * getdE(i, i, t, phi, F);
360  E2[i] = E2[i - 1] + q * scale_m * getdE(i, i, t, phi + dphi, F); // should I use here t or t2?
361  t[i] = t[i - 1] + getdT(i, i, E, F, mass);
362  t2[i] = t2[i - 1] + getdT(i, i, E2, F, mass);
363  E[i] = E[i - 1] + q * scale_m * getdE(i, i, t, phi, F);
364  E2[i] = E2[i - 1] + q * scale_m * getdE(i, i, t2, phi + dphi, F);
365  }
366  for (int i = N1; i < N3 - N1 + 1; ++ i) {
367  int I = (i - N1) % N2 + N1;
368  int J = (i - N1 + N4) % N2 + N1;
369  E[i] = E[i - 1] + q * scaleCore_m * (getdE(i, I, t, phi + phaseC1, F) + getdE(i, J, t, phi + phaseC2, F));
370  E2[i] = E2[i - 1] + q * scaleCore_m * (getdE(i, I, t, phi + phaseC1 + dphi, F) + getdE(i, J, t, phi + phaseC2 + dphi, F)); //concerning t: see above
371  t[i] = t[i - 1] + getdT(i, I, E, F, mass);
372  t2[i] = t2[i - 1] + getdT(i, I, E2, F, mass);
373  E[i] = E[i - 1] + q * scaleCore_m * (getdE(i, I, t, phi + phaseC1, F) + getdE(i, J, t, phi + phaseC2, F));
374  E2[i] = E2[i - 1] + q * scaleCore_m * (getdE(i, I, t2, phi + phaseC1 + dphi, F) + getdE(i, J, t2, phi + phaseC2 + dphi, F));
375  }
376  for (int i = N3 - N1 + 1; i < N3; ++ i) {
377  int I = i - N3 - 1 + 2 * N1 + N2;
378  E[i] = E[i - 1] + q * scale_m * getdE(i, I, t, phi + phaseE, F);
379  E2[i] = E2[i - 1] + q * scale_m * getdE(i, I, t, phi + phaseE + dphi, F); //concerning t: see above
380  t[i] = t[i - 1] + getdT(i, I, E, F, mass);
381  t2[i] = t2[i - 1] + getdT(i, I, E2, F, mass);
382  E[i] = E[i - 1] + q * scale_m * getdE(i, I, t, phi + phaseE, F);
383  E2[i] = E2[i - 1] + q * scale_m * getdE(i, I, t2, phi + phaseE + dphi, F);
384  }
385  // msg << ", Ekin= " << E[N3-1] << " MeV" << endl;
386  }
387 
388 
389  const int prevPrecision = Ippl::Info->precision(8);
390  INFOMSG(level2 << "estimated phase= " << tmp_phi << " rad = "
391  << tmp_phi * Physics::rad2deg << " deg,\n"
392  << "Ekin= " << E[N3 - 1] << " MeV" << std::setprecision(prevPrecision) << "\n" << endl);
393 
394  return phi;
395 }
396 
397 bool TravelingWave::isInside(const Vector_t &r) const {
398  return (isInsideTransverse(r)
399  && r(2) >= -0.5 * PeriodLength_m
400  && r(2) < startExitField_m);
401 }
Inform * gmsg
Definition: Main.cpp:62
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
PartBunchBase< T, Dim >::ConstIterator end(PartBunchBase< T, Dim > const &bunch)
PartBunchBase< T, Dim >::ConstIterator begin(PartBunchBase< T, Dim > const &bunch)
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
PETE_TUTree< FnArcTan, typename T::PETE_Expr_t > atan(const PETE_Expr< T > &l)
Definition: PETE.h:727
PETE_TUTree< FnFloor, typename T::PETE_Expr_t > floor(const PETE_Expr< T > &l)
Definition: PETE.h:733
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
Inform & level2(Inform &inf)
Definition: Inform.cpp:46
#define INFOMSG(msg)
Definition: IpplInfo.h:348
const std::string name
constexpr double two_pi
The value of.
Definition: Physics.h:33
constexpr double pi
The value of.
Definition: Physics.h:30
constexpr double rad2deg
The conversion factor from radians to degrees.
Definition: Physics.h:45
ParticlePos_t & R
ParticleAttrib< Vector_t > P
virtual void visitTravelingWave(const TravelingWave &)=0
Apply the algorithm to a traveling wave.
bool online_m
Definition: Component.h:195
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:194
virtual void setElementLength(double length)
Set design length.
Definition: ElementBase.h:436
bool isInsideTransverse(const Vector_t &r) const
Interface for RF cavity.
Definition: RFCavity.h:37
Fieldmap * fieldmap_m
Definition: RFCavity.h:228
std::string filename_m
Definition: RFCavity.h:215
double scale_m
Definition: RFCavity.h:217
double phaseError_m
Definition: RFCavity.h:220
virtual void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField) override
Definition: RFCavity.cpp:165
double frequency_m
Definition: RFCavity.h:221
double startField_m
Definition: RFCavity.h:229
double scaleError_m
Definition: RFCavity.h:218
virtual double getElementLength() const override
Get design length.
Definition: RFCavity.cpp:722
double phase_m
Definition: RFCavity.h:219
Interface for Traveling Wave.
Definition: TravelingWave.h:37
double CellLength_m
double mappedStartExitField_m
double getdA(const int &i, const int &I, const std::vector< double > &t, const double &phi, const std::vector< std::pair< double, double > > &F) const
double phaseCore2_m
virtual bool bends() const override
virtual void accept(BeamlineVisitor &) const override
Apply visitor to TravelingWave.
virtual void getDimensions(double &zBegin, double &zEnd) const override
virtual ElementBase::ElementType getType() const override
Get element type std::string.
double phaseExit_m
double getdB(const int &i, const int &I, const std::vector< double > &t, const double &phi, const std::vector< std::pair< double, double > > &F) const
virtual double getAutoPhaseEstimate(const double &E0, const double &t0, const double &q, const double &m) override
double startExitField_m
virtual bool isInside(const Vector_t &r) const override
virtual void goOffline() override
double getdE(const int &i, const int &I, const std::vector< double > &t, const double &phi, const std::vector< std::pair< double, double > > &F) const
double scaleCore_m
Definition: TravelingWave.h:98
virtual bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) override
virtual void finalise() override
double scaleCoreError_m
Definition: TravelingWave.h:99
virtual ~TravelingWave()
virtual void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField) override
virtual void getElementDimensions(double &begin, double &end) const override
double PeriodLength_m
virtual bool applyToReferenceParticle(const Vector_t &R, const Vector_t &P, const double &t, Vector_t &E, Vector_t &B) override
double getdT(const int &i, const int &I, const std::vector< double > &E, const std::vector< std::pair< double, double > > &F, const double mass) const
double phaseCore1_m
double startCoreField_m
virtual void goOnline(const double &kineticEnergy) override
virtual bool isInside(const Vector_t &) const
Definition: Fieldmap.h:101
virtual void freeMap()=0
virtual void getOnaxisEz(std::vector< std::pair< double, double > > &onaxis)
Definition: Fieldmap.cpp:709
virtual bool getFieldstrength(const Vector_t &R, Vector_t &E, Vector_t &B) const =0
virtual void readMap()=0
Definition: Inform.h:42
int precision() const
Definition: Inform.h:112
static Inform * Info
Definition: IpplInfo.h:78
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6