OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
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 #include <iostream>
29 #include <fstream>
30 
31 extern Inform *gmsg;
32 
33 // Class TravelingWave
34 // ------------------------------------------------------------------------
35 
37  TravelingWave("")
38 {}
39 
40 
42  RFCavity(right),
43  CoreFieldmap_m(NULL),
44  scaleCore_m(right.scaleCore_m),
45  scaleCoreError_m(right.scaleCoreError_m),
46  phaseCore1_m(right.phaseCore1_m),
47  phaseCore2_m(right.phaseCore2_m),
48  phaseExit_m(right.phaseExit_m),
49  length_m(right.length_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  fast_m(right.fast_m),
58  autophaseVeto_m(right.autophaseVeto_m),
59  designEnergy_m(right.designEnergy_m)
60 {}
61 
62 
63 TravelingWave::TravelingWave(const std::string &name):
64  RFCavity(name),
65  CoreFieldmap_m(NULL),
66  scaleCore_m(1.0),
67  scaleCoreError_m(0.0),
68  phaseCore1_m(0.0),
69  phaseCore2_m(0.0),
70  phaseExit_m(0.0),
71  length_m(0.0),
72  startCoreField_m(0.0),
73  startExitField_m(0.0),
74  mappedStartExitField_m(0.0),
75  PeriodLength_m(0.0),
76  NumCells_m(1),
77  CellLength_m(0.0),
78  Mode_m(1),
79  fast_m(true),
80  autophaseVeto_m(false),
81  designEnergy_m(-1.0)
82 {}
83 
84 
86  // Fieldmap::deleteFieldmap(filename_m);
87  // Fieldmap::deleteFieldmap(EntryFilename_m);
88  // Fieldmap::deleteFieldmap(ExitFilename_m);
89 }
90 
91 
92 void TravelingWave::accept(BeamlineVisitor &visitor) const {
93  visitor.visitTravelingWave(*this);
94 }
95 
101 void TravelingWave::addKR(int i, double t, Vector_t &K) {
102  Inform msg("TravelingWave::addK()");
103 
104  Vector_t tmpE(0.0, 0.0, 0.0), tmpB(0.0, 0.0, 0.0);
105  Vector_t tmpE_diff(0.0, 0.0, 0.0), tmpB_diff(0.0, 0.0, 0.0);
107 
108  double g = RefPartBunch_m->getGamma(i);
109  double b = RefPartBunch_m->getBeta(i);
110  DiffDirection zdir(DZ);
111  double wtf = 0.0;
112  double k = 0.0;
113 
114  if(tmpA0(2) < startCoreField_m) {
115 
116  wtf = frequency_m * t + phase_m;
117  CoreFieldmap_m->getFieldstrength(tmpA0, tmpE, tmpB);
118  CoreFieldmap_m->getFieldDerivative(tmpA0, tmpE_diff, tmpB_diff, zdir);
119  k = scale_m * (tmpE_diff(2) * cos(wtf) - b * frequency_m * tmpE(2) * sin(wtf) / Physics::c);
120 
121  } else if(tmpA0(2) < startExitField_m) {
122 
123  wtf = frequency_m * t + phaseCore1_m;
124  tmpA0(2) -= startCoreField_m;
125  const double z = tmpA0(2);
126  tmpA0(2) = tmpA0(2) - PeriodLength_m * floor(tmpA0(2) / PeriodLength_m);
127  tmpA0(2) += startCoreField_m;
128  tmpE = 0.0;
129  tmpB = 0.0;
130  tmpE_diff = 0.0;
131  tmpB_diff = 0.0;
132 
133  CoreFieldmap_m->getFieldstrength(tmpA0, tmpE, tmpB);
134  CoreFieldmap_m->getFieldDerivative(tmpA0, tmpE_diff, tmpB_diff, zdir);
135  k = scaleCore_m * (tmpE_diff(2) * cos(wtf) - b * frequency_m * tmpE(2) * sin(wtf) / Physics::c);
136 
137  wtf = frequency_m * t + phaseCore2_m;
138  tmpA0(2) = z + CellLength_m;
139  tmpA0(2) = tmpA0(2) - PeriodLength_m * floor(tmpA0(2) / PeriodLength_m);
140  tmpA0(2) += startCoreField_m;
141  tmpE = 0.0;
142  tmpB = 0.0;
143  tmpE_diff = 0.0;
144  tmpB_diff = 0.0;
145 
146  CoreFieldmap_m->getFieldstrength(tmpA0, tmpE, tmpB);
147  CoreFieldmap_m->getFieldDerivative(tmpA0, tmpE_diff, tmpB_diff, zdir);
148  k += scaleCore_m * (tmpE_diff(2) * cos(wtf) - b * frequency_m * tmpE(2) * sin(wtf) / Physics::c);
149 
150  } else {
151 
152  wtf = frequency_m * t + phaseExit_m;
153  tmpA0(2) -= mappedStartExitField_m;
154  tmpE = 0.0;
155  tmpB = 0.0;
156  tmpE_diff = 0.0;
157  tmpB_diff = 0.0;
158 
159  CoreFieldmap_m->getFieldstrength(tmpA0, tmpE, tmpB);
160  CoreFieldmap_m->getFieldDerivative(tmpA0, tmpE_diff, tmpB_diff, zdir);
161  k = scale_m * (tmpE_diff(2) * cos(wtf) - b * frequency_m * tmpE(2) * sin(wtf) / Physics::c);
162 
163  }
164 
165  //XXX: we have to compensate for bet behaviour by using -q_e
166  k *= (-Physics::q_e / (2.0 * g * Physics::EMASS));
167  K += Vector_t(k, k, 0.0);
168 }
169 
170 
171 void TravelingWave::addKT(int i, double t, Vector_t &K) {
172  // get K from radial function, solves the lastk problem from BET
173  Vector_t tempK(0.0, 0.0, 0.0);
174  addKR(i, t, tempK);
175 
176  // x and y component are identical and equal to k
177  double oldK = tempK(0);
178 
179  //get coordinates
180  double dx = RefPartBunch_m->getX0(i);
181  double dy = RefPartBunch_m->getY0(i);
182 
183  K += Vector_t(oldK * dx, oldK * dy, 0.0);
184 }
185 
186 /*
187  Function to obtain z-k-component, copied from BET:
188  Field Kloc;
189 
190  if (isActive(z)){
191  double k,kx,ky;
192 
193  if (kLast == MAXFLOAT) {
194  Kloc = getK(g,b,z,t,m); // dummy call to set kLast
195  }
196  k = kLast;
197  kx = 0.0; ky = 0.0;
198  if (Cxy < 1.0) {
199  Field Eloc = getE(z,t);
200  double
201  cf = -e0/(g*m);
202 
203  kx = cf*Eloc.x;
204  ky = cf*Eloc.y;
205  }
206  Kloc = Field(k*Cxy*(x0-x) + kx,
207  k*Cxy*(y0-y) + ky,
208  0.0);
209  if (Ndamp > 0) {
210  Kloc *= fDamp(z - z0);
211  }
212  }
213 
214  return Kloc;
215 */
216 
217 
218 bool TravelingWave::apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) {
219  return apply(RefPartBunch_m->R[i], RefPartBunch_m->P[i], t, E, B);
220 }
221 
222 bool TravelingWave::apply(const Vector_t &R, const Vector_t &P, const double &t, Vector_t &E, Vector_t &B) {
223  if (R(2) < -0.5 * PeriodLength_m || R(2) + 0.5 * PeriodLength_m >= length_m) return false;
224 
225  Vector_t tmpR = Vector_t(R(0), R(1), R(2) + 0.5 * PeriodLength_m);
226  double tmpcos, tmpsin;
227  Vector_t tmpE(0.0, 0.0, 0.0), tmpB(0.0, 0.0, 0.0);
228 
229  if (tmpR(2) < startCoreField_m) {
230  if (!CoreFieldmap_m->isInside(tmpR)) return true;
231 
232  tmpcos = (scale_m + scaleError_m) * cos(frequency_m * t + phase_m + phaseError_m);
233  tmpsin = -(scale_m + scaleError_m) * sin(frequency_m * t + phase_m + phaseError_m);
234 
235  } else if (tmpR(2) < startExitField_m) {
236  Vector_t tmpE2(0.0, 0.0, 0.0), tmpB2(0.0, 0.0, 0.0);
237  tmpR(2) -= startCoreField_m;
238  const double z = tmpR(2);
239  tmpR(2) = tmpR(2) - PeriodLength_m * floor(tmpR(2) / PeriodLength_m);
240  tmpR(2) += startCoreField_m;
241  if (!CoreFieldmap_m->isInside(tmpR)) return true;
242 
245  CoreFieldmap_m->getFieldstrength(tmpR, tmpE, tmpB);
246  E += tmpcos * tmpE;
247  B += tmpsin * tmpB;
248 
249  tmpE = 0.0;
250  tmpB = 0.0;
251 
252  tmpR(2) = z + CellLength_m;
253  tmpR(2) = tmpR(2) - PeriodLength_m * floor(tmpR(2) / PeriodLength_m);
254  tmpR(2) += startCoreField_m;
255 
258 
259  } else {
260  tmpR(2) -= mappedStartExitField_m;
261  if (!CoreFieldmap_m->isInside(tmpR)) return true;
263  tmpsin = -(scale_m + scaleError_m) * sin(frequency_m * t + phaseExit_m + phaseError_m);
264  }
265 
266  CoreFieldmap_m->getFieldstrength(tmpR, tmpE, tmpB);
267 
268  E += tmpcos * tmpE;
269  B += tmpsin * tmpB;
270 
271  return false;
272 }
273 
274 bool TravelingWave::applyToReferenceParticle(const Vector_t &R, const Vector_t &P, const double &t, Vector_t &E, Vector_t &B) {
275 
276  if (R(2) < -0.5 * PeriodLength_m || R(2) + 0.5 * PeriodLength_m >= length_m) return false;
277 
278  Vector_t tmpR = Vector_t(R(0), R(1), R(2) + 0.5 * PeriodLength_m);
279  double tmpcos, tmpsin;
280  Vector_t tmpE(0.0, 0.0, 0.0), tmpB(0.0, 0.0, 0.0);
281 
282  if (tmpR(2) < startCoreField_m) {
283  if (!CoreFieldmap_m->isInside(tmpR)) return true;
284  tmpcos = scale_m * cos(frequency_m * t + phase_m);
285  tmpsin = -scale_m * sin(frequency_m * t + phase_m);
286 
287  } else if (tmpR(2) < startExitField_m) {
288  Vector_t tmpE2(0.0, 0.0, 0.0), tmpB2(0.0, 0.0, 0.0);
289  tmpR(2) -= startCoreField_m;
290  const double z = tmpR(2);
291  tmpR(2) = tmpR(2) - PeriodLength_m * floor(tmpR(2) / PeriodLength_m);
292  tmpR(2) += startCoreField_m;
293  if (!CoreFieldmap_m->isInside(tmpR)) return true;
294 
295  tmpcos = scaleCore_m * cos(frequency_m * t + phaseCore1_m);
296  tmpsin = -scaleCore_m * sin(frequency_m * t + phaseCore1_m);
297  CoreFieldmap_m->getFieldstrength(tmpR, tmpE, tmpB);
298  E += tmpcos * tmpE;
299  B += tmpsin * tmpB;
300 
301  tmpE = 0.0;
302  tmpB = 0.0;
303 
304  tmpR(2) = z + CellLength_m;
305  tmpR(2) = tmpR(2) - PeriodLength_m * floor(tmpR(2) / PeriodLength_m);
306  tmpR(2) += startCoreField_m;
307 
308  tmpcos = scaleCore_m * cos(frequency_m * t + phaseCore2_m);
309  tmpsin = -scaleCore_m * sin(frequency_m * t + phaseCore2_m);
310 
311  } else {
312  tmpR(2) -= mappedStartExitField_m;
313  if (!CoreFieldmap_m->isInside(tmpR)) return true;
314 
315  tmpcos = scale_m * cos(frequency_m * t + phaseExit_m);
316  tmpsin = -scale_m * sin(frequency_m * t + phaseExit_m);
317  }
318 
319  CoreFieldmap_m->getFieldstrength(tmpR, tmpE, tmpB);
320 
321  E += tmpcos * tmpE;
322  B += tmpsin * tmpB;
323 
324  return false;
325 }
326 
327 void TravelingWave::initialise(PartBunchBase<double, 3> *bunch, double &startField, double &endField) {
328  using Physics::pi;
329  using Physics::two_pi;
330 
331  if (bunch == NULL) {
332  startField = - 0.5 * PeriodLength_m;
333  endField = startExitField_m;
334  return;
335  }
336 
337  Inform msg("TravelingWave ", *gmsg);
338  std::stringstream errormsg;
339 
340  RefPartBunch_m = bunch;
341 
343  if(CoreFieldmap_m != NULL) {
344  double zBegin = 0.0, zEnd = 0.0, rBegin = 0.0, rEnd = 0.0;
345  CoreFieldmap_m->getFieldDimensions(zBegin, zEnd, rBegin, rEnd);
346 
347  if(zEnd > zBegin) {
348  msg << level2 << getName() << " using file ";
349  CoreFieldmap_m->getInfo(&msg);
351  errormsg << "FREQUENCY IN INPUT FILE DIFFERENT THAN IN FIELD MAP '" << filename_m + "';\n"
352  << frequency_m / two_pi * 1e-6 << " MHz <> "
353  << CoreFieldmap_m->getFrequency() / two_pi * 1e-6 << " MHz; TAKE ON THE LATTER\n";
354  std::string errormsg_str = Fieldmap::typeset_msg(errormsg.str(), "warning");
355  *gmsg << errormsg_str << endl;
356  ERRORMSG(errormsg_str << "\n" << endl);
357  if(Ippl::myNode() == 0) {
358  std::ofstream omsg("errormsg.txt", std::ios_base::app);
359  omsg << errormsg_str << std::endl;
360  omsg.close();
361  }
363  }
364 
365  PeriodLength_m = (zEnd - zBegin) / 2.0;
367 
371 
372  startField = -PeriodLength_m / 2.0;
373  endField = startField + startExitField_m + PeriodLength_m / 2.0;
374  length_m = endField - startField;
375 
376  scaleCore_m = scale_m / sin(2.0 * pi * Mode_m);
377  scaleCoreError_m = scaleError_m / sin(2.0 * pi * Mode_m);
378  phaseCore1_m = phase_m + pi * Mode_m / 2.0;
379  phaseCore2_m = phase_m + pi * Mode_m * 1.5;
380  phaseExit_m = phase_m - 2.0 * pi * ((NumCells_m - 1) * Mode_m - floor((NumCells_m - 1) * Mode_m));
381 
382  } else {
383  endField = startField - 1e-3;
384  }
385  } else {
386  endField = startField - 1e-3;
387  }
388 }
389 
391 {}
392 
393 bool TravelingWave::bends() const {
394  return false;
395 }
396 
397 
398 void TravelingWave::goOnline(const double &) {
400  online_m = true;
401 }
402 
405 }
406 
407 void TravelingWave::getDimensions(double &zBegin, double &zEnd) const {
408  zBegin = -0.5 * PeriodLength_m;
409  zEnd = zBegin + length_m;
410 }
411 
412 
414  return length_m;
415 }
416 
418  double &end) const {
419  begin = -0.5 * PeriodLength_m;
420  end = begin + length_m;
421 }
422 
424  return TRAVELINGWAVE;
425 }
426 
427 double TravelingWave::getAutoPhaseEstimate(const double &E0, const double &t0, const double &q, const double &mass) {
428  std::vector<double> t, E, t2, E2;
429  std::vector<std::pair<double, double> > F;
430  double Dz;
431  int N1, N2, N3, N4;
432  double A, B;
433  double phi = 0.0, tmp_phi, dphi = 0.5 * Physics::pi / 180.;
434  double phaseC1 = phaseCore1_m - phase_m;
435  double phaseC2 = phaseCore2_m - phase_m;
436  double phaseE = phaseExit_m - phase_m;
437 
439  if(F.size() == 0) return 0.0;
440 
441  N1 = static_cast<int>(floor(F.size() / 4.)) + 1;
442  N2 = F.size() - 2 * N1 + 1;
443  N3 = 2 * N1 + static_cast<int>(floor((NumCells_m - 1) * N2 * Mode_m)) - 1;
444  N4 = static_cast<int>(floor(0.5 + N2 * Mode_m));
445  Dz = F[N1 + N2].first - F[N1].first;
446 
447  t.resize(N3, t0);
448  t2.resize(N3, t0);
449  E.resize(N3, E0);
450  E2.resize(N3, E0);
451  for(int i = 1; i < N1; ++ i) {
452  E[i] = E0 + (F[i].first + F[i - 1].first) / 2. * scale_m / mass;
453  E2[i] = E[i];
454  }
455  for(int i = N1; i < N3 - N1 + 1; ++ i) {
456  int I = (i - N1) % N2 + N1;
457  double Z = (F[I].first + F[I - 1].first) / 2. + floor((i - N1) / N2) * Dz;
458  E[i] = E0 + Z * scaleCore_m / mass;
459  E2[i] = E[i];
460  }
461  for(int i = N3 - N1 + 1; i < N3; ++ i) {
462  int I = i - N3 - 1 + 2 * N1 + N2;
463  double Z = (F[I].first + F[I - 1].first) / 2. + ((NumCells_m - 1) * Mode_m - 1) * Dz;
464  E[i] = E0 + Z * scale_m / mass;
465  E2[i] = E[i];
466  }
467 
468  for(int iter = 0; iter < 10; ++ iter) {
469  A = B = 0.0;
470  for(int i = 1; i < N1; ++ i) {
471  t[i] = t[i - 1] + getdT(i, i, E, F, mass);
472  t2[i] = t2[i - 1] + getdT(i, i, E2, F, mass);
473  A += scale_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * getdA(i, i, t, 0.0, F);
474  B += scale_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * getdB(i, i, t, 0.0, F);
475  }
476  for(int i = N1; i < N3 - N1 + 1; ++ i) {
477  int I = (i - N1) % N2 + N1;
478  int J = (i - N1 + N4) % N2 + N1;
479  t[i] = t[i - 1] + getdT(i, I, E, F, mass);
480  t2[i] = t2[i - 1] + getdT(i, I, E2, F, mass);
481  A += scaleCore_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * (getdA(i, I, t, phaseC1, F) + getdA(i, J, t, phaseC2, F));
482  B += scaleCore_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * (getdB(i, I, t, phaseC1, F) + getdB(i, J, t, phaseC2, F));
483  }
484  for(int i = N3 - N1 + 1; i < N3; ++ i) {
485  int I = i - N3 - 1 + 2 * N1 + N2;
486  t[i] = t[i - 1] + getdT(i, I, E, F, mass);
487  t2[i] = t2[i - 1] + getdT(i, I, E2, F, mass);
488  A += scale_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * getdA(i, I, t, phaseE, F);
489  B += scale_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * getdB(i, I, t, phaseE, F);
490  }
491 
492  if(std::abs(B) > 0.0000001) {
493  tmp_phi = atan(A / B);
494  } else {
495  tmp_phi = Physics::pi / 2;
496  }
497  if(q * (A * sin(tmp_phi) + B * cos(tmp_phi)) < 0) {
498  tmp_phi += Physics::pi;
499  }
500 
501  if(std::abs(phi - tmp_phi) < frequency_m * (t[N3 - 1] - t[0]) / N3) {
502  for(int i = 1; i < N1; ++ i) {
503  E[i] = E[i - 1] + q * scale_m * getdE(i, i, t, phi, F);
504  }
505  for(int i = N1; i < N3 - N1 + 1; ++ i) {
506  int I = (i - N1) % N2 + N1;
507  int J = (i - N1 + N4) % N2 + N1;
508  E[i] = E[i - 1] + q * scaleCore_m * (getdE(i, I, t, phi + phaseC1, F) + getdE(i, J, t, phi + phaseC2, F));
509  }
510  for(int i = N3 - N1 + 1; i < N3; ++ i) {
511  int I = i - N3 - 1 + 2 * N1 + N2;
512  E[i] = E[i - 1] + q * scale_m * getdE(i, I, t, phi + phaseE, F);
513  }
514 
515  const int prevPrecision = Ippl::Info->precision(8);
516  INFOMSG(level2 << "estimated phase= " << tmp_phi << " rad = "
517  << tmp_phi * Physics::rad2deg << " deg,\n"
518  << "Ekin= " << E[N3 - 1] << " MeV" << std::setprecision(prevPrecision) << "\n" << endl);
519  return tmp_phi;
520  }
521  phi = tmp_phi - floor(tmp_phi / Physics::two_pi + 0.5) * Physics::two_pi;
522 
523 
524  for(int i = 1; i < N1; ++ i) {
525  E[i] = E[i - 1] + q * scale_m * getdE(i, i, t, phi, F);
526  E2[i] = E2[i - 1] + q * scale_m * getdE(i, i, t, phi + dphi, F); // should I use here t or t2?
527  t[i] = t[i - 1] + getdT(i, i, E, F, mass);
528  t2[i] = t2[i - 1] + getdT(i, i, E2, F, mass);
529  E[i] = E[i - 1] + q * scale_m * getdE(i, i, t, phi, F);
530  E2[i] = E2[i - 1] + q * scale_m * getdE(i, i, t2, phi + dphi, F);
531  }
532  for(int i = N1; i < N3 - N1 + 1; ++ i) {
533  int I = (i - N1) % N2 + N1;
534  int J = (i - N1 + N4) % N2 + N1;
535  E[i] = E[i - 1] + q * scaleCore_m * (getdE(i, I, t, phi + phaseC1, F) + getdE(i, J, t, phi + phaseC2, F));
536  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
537  t[i] = t[i - 1] + getdT(i, I, E, F, mass);
538  t2[i] = t2[i - 1] + getdT(i, I, E2, F, mass);
539  E[i] = E[i - 1] + q * scaleCore_m * (getdE(i, I, t, phi + phaseC1, F) + getdE(i, J, t, phi + phaseC2, F));
540  E2[i] = E2[i - 1] + q * scaleCore_m * (getdE(i, I, t2, phi + phaseC1 + dphi, F) + getdE(i, J, t2, phi + phaseC2 + dphi, F));
541  }
542  for(int i = N3 - N1 + 1; i < N3; ++ i) {
543  int I = i - N3 - 1 + 2 * N1 + N2;
544  E[i] = E[i - 1] + q * scale_m * getdE(i, I, t, phi + phaseE, F);
545  E2[i] = E2[i - 1] + q * scale_m * getdE(i, I, t, phi + phaseE + dphi, F); //concerning t: see above
546  t[i] = t[i - 1] + getdT(i, I, E, F, mass);
547  t2[i] = t2[i - 1] + getdT(i, I, E2, F, mass);
548  E[i] = E[i - 1] + q * scale_m * getdE(i, I, t, phi + phaseE, F);
549  E2[i] = E2[i - 1] + q * scale_m * getdE(i, I, t2, phi + phaseE + dphi, F);
550  }
551  // msg << ", Ekin= " << E[N3-1] << " MeV" << endl;
552  }
553 
554 
555  const int prevPrecision = Ippl::Info->precision(8);
556  INFOMSG(level2 << "estimated phase= " << tmp_phi << " rad = "
557  << tmp_phi * Physics::rad2deg << " deg,\n"
558  << "Ekin= " << E[N3 - 1] << " MeV" << std::setprecision(prevPrecision) << "\n" << endl);
559 
560  return phi;
561 }
562 
563 std::pair<double, double> TravelingWave::trackOnAxisParticle(const double &p0,
564  const double &t0,
565  const double &dt,
566  const double &q,
567  const double &mass,
568  std::ofstream *out) {
569  double phase = frequency_m * t0 + phase_m;
570  double p = p0;
571  double t = t0;
572  double cdt = Physics::c * dt;
573  double dphi = frequency_m * dt;
574  std::vector<std::pair<double, double> > F;
576 
577  double *zvals = new double[F.size()];
578  double *onAxisField = new double[F.size()];
579  double Ezmax = 0.0;
580  for(unsigned int i = 0; i < F.size(); ++i) {
581  zvals[i] = F[i].first;
582  onAxisField[i] = F[i].second;
583  if(std::abs(onAxisField[i]) > Ezmax) Ezmax = std::abs(onAxisField[i]);
584  }
585  // Ezmax /= 1e6;
586  double z = zvals[0];
587  double zbegin = z;
588 
589  gsl_spline *onAxisInterpolants = gsl_spline_alloc(gsl_interp_cspline, F.size());
590  gsl_interp_accel *onAxisAccel = gsl_interp_accel_alloc();
591  gsl_spline_init(onAxisInterpolants, zvals, onAxisField, F.size());
592 
593  delete[] zvals;
594  delete[] onAxisField;
595 
596  if (out) *out << std::setw(18) << z
597  << std::setw(18) << Util::getEnergy(p, mass)
598  << std::endl;
599  double dz = 0.5 * p / sqrt(1.0 + p * p) * cdt;
600  while(z + dz < startCoreField_m + zbegin) {
601  z += dz;
602  double ez = scale_m / Ezmax * cos(phase) * gsl_spline_eval(onAxisInterpolants, z, onAxisAccel);
603  p += ez * q * cdt / mass;
604  dz = 0.5 * p / sqrt(1.0 + p * p) * cdt;
605  z += 0.5 * p / sqrt(1.0 + p * p) * cdt;
606  phase += dphi;
607  t += dt;
608  }
609  double phase2 = phase - phase_m + phaseCore2_m;
610  phase = phase - phase_m + phaseCore1_m;
611  while(z + dz < startExitField_m + zbegin) {
612  z += dz;
613 
614  double tmpz = z - (startCoreField_m + zbegin);
615  tmpz -= PeriodLength_m * floor(tmpz / PeriodLength_m);
616  tmpz += startCoreField_m + zbegin;
617 
618  double ez = scaleCore_m / Ezmax * cos(phase) * gsl_spline_eval(onAxisInterpolants, tmpz, onAxisAccel);
619 
620  tmpz = z - (startCoreField_m + zbegin) + CellLength_m;
621  tmpz -= PeriodLength_m * floor(tmpz / PeriodLength_m);
622  tmpz += startCoreField_m + zbegin;
623 
624  ez += scaleCore_m / Ezmax * cos(phase2) * gsl_spline_eval(onAxisInterpolants, tmpz, onAxisAccel);
625 
626  p += ez * q * cdt / mass;
627  dz = 0.5 * p / sqrt(1.0 + p * p) * cdt;
628  z += dz;
629  phase += dphi;
630  phase2 += dphi;
631  t += dt;
632 
633  if (out) *out << std::setw(18) << z
634  << std::setw(18) << Util::getEnergy(p, mass)
635  << std::endl;
636  }
637  phase = phase - phaseCore1_m + phaseExit_m;
638  while(z + dz < startExitField_m + 0.5 * PeriodLength_m + zbegin) {
639  z += dz;
640  double tmpz = z - (startExitField_m + zbegin);
641  tmpz -= PeriodLength_m * floor(tmpz / PeriodLength_m);
642  tmpz += 3.0 * PeriodLength_m / 2.0;
643  double ez = scale_m / Ezmax * cos(phase) * gsl_spline_eval(onAxisInterpolants, tmpz, onAxisAccel);
644  p += ez * q * cdt / mass;
645  dz = 0.5 * p / sqrt(1.0 + p * p) * cdt;
646  z += dz;
647  phase += dphi;
648  t += dt;
649  }
650 
651  gsl_spline_free(onAxisInterpolants);
652  gsl_interp_accel_free(onAxisAccel);
653 
654  const double beta = sqrt(1. - 1 / (p * p + 1.));
655  const double tErr = (z - (startExitField_m + 0.5 * PeriodLength_m + zbegin)) / (Physics::c * beta);
656 
657  return std::pair<double, double>(p, t - tErr);
658 }
659 
660 bool TravelingWave::isInside(const Vector_t &r) const {
661  return (isInsideTransverse(r) && r(2) >= -0.5 * PeriodLength_m && r(2) < startExitField_m);
662 }
ParticleAttrib< Vector_t > P
virtual void getInfo(Inform *msg)=0
virtual void freeMap()=0
double scale_m
Definition: RFCavity.h:221
double scaleError_m
Definition: RFCavity.h:222
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
double scaleCoreError_m
virtual void accept(BeamlineVisitor &) const override
Apply visitor to TravelingWave.
constexpr double e
The value of .
Definition: Physics.h:40
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 phaseCore1_m
virtual void readMap()=0
DiffDirection
Definition: Fieldmap.h:54
virtual void goOffline() override
virtual void getOnaxisEz(std::vector< std::pair< double, double > > &onaxis)
Definition: Fieldmap.cpp:704
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
#define ERRORMSG(msg)
Definition: IpplInfo.h:399
constexpr double two_pi
The value of .
Definition: Physics.h:34
virtual bool isInside(const Vector_t &r) const
Definition: Fieldmap.h:203
Inform * gmsg
Definition: Main.cpp:21
virtual bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) override
bool online_m
Definition: Component.h:201
virtual void addKR(int i, double t, Vector_t &K) 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
virtual void getFieldDimensions(double &zBegin, double &zEnd, double &rBegin, double &rEnd) const =0
static int myNode()
Definition: IpplInfo.cpp:794
virtual const std::string & getName() const
Get element name.
Definition: ElementBase.cpp:95
std::string filename_m
Definition: RFCavity.h:219
static std::string typeset_msg(const std::string &msg, const std::string &title)
Definition: Fieldmap.cpp:647
static Fieldmap * getFieldmap(std::string Filename, bool fast=false)
Definition: Fieldmap.cpp:46
virtual double getY(int i)
constexpr double rad2deg
The conversion factor from radians to degrees.
Definition: Physics.h:46
virtual void finalise() override
double phaseCore2_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 void getElementDimensions(double &begin, double &end) const override
double startExitField_m
Inform & level2(Inform &inf)
Definition: Inform.cpp:46
virtual void goOnline(const double &kineticEnergy) override
virtual ElementBase::ElementType getType() const override
Get element type std::string.
virtual bool getFieldstrength(const Vector_t &R, Vector_t &E, Vector_t &B) const =0
virtual double getGamma(int i)
virtual void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField) override
constexpr double pi
The value of .
Definition: Physics.h:31
virtual void getDimensions(double &zBegin, double &zEnd) const override
double phaseError_m
Definition: RFCavity.h:224
virtual bool isInside(const Vector_t &r) const override
Fieldmap * CoreFieldmap_m
virtual double getElementLength() const override
Get design length.
virtual double getBeta(int i)
double scaleCore_m
const double pi
Definition: fftpack.cpp:894
PETE_TUTree< FnArcTan, typename T::PETE_Expr_t > atan(const PETE_Expr< T > &l)
Definition: PETE.h:810
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:52
double PeriodLength_m
virtual double getY0(int i)
Interface for RF cavity.
Definition: TravelingWave.h:37
#define INFOMSG(msg)
Definition: IpplInfo.h:397
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:200
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6
virtual double getFrequency() const =0
int precision() const
Definition: Inform.h:115
double phaseExit_m
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
double frequency_m
Definition: RFCavity.h:225
double CellLength_m
virtual double getAutoPhaseEstimate(const double &E0, const double &t0, const double &q, const double &m) override
virtual void addKT(int i, double t, Vector_t &K) override
Definition: Fieldmap.h:57
virtual std::pair< double, double > trackOnAxisParticle(const double &p0, const double &t0, const double &dt, const double &q, const double &mass, std::ofstream *out=NULL) override
Interface for RF cavity.
Definition: RFCavity.h:37
virtual double getX0(int i)
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
static Inform * Info
Definition: IpplInfo.h:87
constexpr double q_e
The elementary charge in As.
Definition: Physics.h:76
const std::string name
double phase_m
Definition: RFCavity.h:223
double getEnergy(Vector_t p, double mass)
Definition: Util.h:29
virtual double getZ(int i)
ParticlePos_t & R
constexpr double EMASS
Definition: Physics.h:140
bool isInsideTransverse(const Vector_t &r, double f=1) const
Definition: ElementBase.h:645
virtual void visitTravelingWave(const TravelingWave &)=0
Apply the algorithm to a RF cavity.
virtual double getX(int i)
double mappedStartExitField_m
#define K
Definition: integrate.cpp:118
virtual bool bends() const override
Abstract algorithm.
Definition: Inform.h:41
virtual bool getFieldDerivative(const Vector_t &R, Vector_t &E, Vector_t &B, const DiffDirection &dir) const =0
virtual ~TravelingWave()
double startCoreField_m
PETE_TUTree< FnFloor, typename T::PETE_Expr_t > floor(const PETE_Expr< T > &l)
Definition: PETE.h:816
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
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
virtual bool applyToReferenceParticle(const Vector_t &R, const Vector_t &P, const double &t, Vector_t &E, Vector_t &B) override