OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
RFCavity.cpp
Go to the documentation of this file.
1 // ------------------------------------------------------------------------
2 // $RCSfile: RFCavity.cpp,v $
3 // ------------------------------------------------------------------------
4 // $Revision: 1.1.1.1 $
5 // ------------------------------------------------------------------------
6 // Copyright: see Copyright.readme
7 // ------------------------------------------------------------------------
8 //
9 // Class: RFCavity
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: andreas adelmann $
18 //
19 // ------------------------------------------------------------------------
20 
21 #include "AbsBeamline/RFCavity.h"
24 #include "Steppers/BorisPusher.h"
25 #include "Fields/Fieldmap.h"
27 #include "Utilities/Util.h"
28 
29 #include "gsl/gsl_interp.h"
30 #include "gsl/gsl_spline.h"
31 #include <iostream>
32 #include <fstream>
33 
34 extern Inform *gmsg;
35 
36 using namespace std;
37 
38 // Class RFCavity
39 // ------------------------------------------------------------------------
40 
42  RFCavity("")
43 {}
44 
45 
47  Component(right),
48  phase_td_m(right.phase_td_m),
49  phase_name_m(right.phase_name_m),
50  amplitude_td_m(right.amplitude_td_m),
51  amplitude_name_m(right.amplitude_name_m),
52  frequency_td_m(right.frequency_td_m),
53  frequency_name_m(right.frequency_name_m),
54  filename_m(right.filename_m),
55  scale_m(right.scale_m),
56  scaleError_m(right.scaleError_m),
57  phase_m(right.phase_m),
58  phaseError_m(right.phaseError_m),
59  frequency_m(right.frequency_m),
60  fast_m(right.fast_m),
61  autophaseVeto_m(right.autophaseVeto_m),
62  designEnergy_m(right.designEnergy_m),
63  fieldmap_m(right.fieldmap_m),
64  startField_m(right.startField_m),
65  endField_m(right.endField_m),
66  length_m(right.length_m),
67  type_m(right.type_m),
68  rmin_m(right.rmin_m),
69  rmax_m(right.rmax_m),
70  angle_m(right.angle_m),
71  sinAngle_m(right.sinAngle_m),
72  cosAngle_m(right.cosAngle_m),
73  pdis_m(right.pdis_m),
74  gapwidth_m(right.gapwidth_m),
75  phi0_m(right.phi0_m),
76  RNormal_m(nullptr),
77  VrNormal_m(nullptr),
78  DvDr_m(nullptr),
79  num_points_m(right.num_points_m)
80 {
81  setElType(isRF);
82 }
83 
84 
85 RFCavity::RFCavity(const std::string &name):
86  Component(name),
87  phase_td_m(nullptr),
88  amplitude_td_m(nullptr),
89  frequency_td_m(nullptr),
90  filename_m(""),
91  scale_m(1.0),
92  scaleError_m(0.0),
93  phase_m(0.0),
94  phaseError_m(0.0),
95  frequency_m(0.0),
96  fast_m(true),
97  autophaseVeto_m(false),
98  designEnergy_m(-1.0),
99  fieldmap_m(nullptr),
100  startField_m(0.0),
101  endField_m(0.0),
102  length_m(0.0),
103  type_m(SW),
104  rmin_m(0.0),
105  rmax_m(0.0),
106  angle_m(0.0),
107  sinAngle_m(0.0),
108  cosAngle_m(0.0),
109  pdis_m(0.0),
110  gapwidth_m(0.0),
111  phi0_m(0.0),
112  RNormal_m(nullptr),
113  VrNormal_m(nullptr),
114  DvDr_m(nullptr),
115  // RNormal_m(std::nullptr_t(NULL)),
116  // VrNormal_m(std::nullptr_t(NULL)),
117  // DvDr_m(std::nullptr_t(NULL)),
118  num_points_m(0)
119 {
120  setElType(isRF);
121 }
122 
123 
125  // FIXME: in deleteFielmak, a map find makes problems
126  // Fieldmap::deleteFieldmap(filename_m);
127  //~ if(RNormal_m) {
128  //~ delete[] RNormal_m;
129  //~ delete[] VrNormal_m;
130  //~ delete[] DvDr_m;
131  //~ }
132 }
133 
134 void RFCavity::accept(BeamlineVisitor &visitor) const {
135  visitor.visitRFCavity(*this);
136 }
137 
143 void RFCavity::addKR(int i, double t, Vector_t &K) {
144 
145  double pz = RefPartBunch_m->getZ(i) - startField_m;
146  if (pz < 0.0 ||
147  pz >= length_m) return;
148 
149  const Vector_t tmpR(RefPartBunch_m->getX(i), RefPartBunch_m->getY(i), pz);
150  double k = -Physics::q_e / (2.0 * RefPartBunch_m->getGamma(i) * Physics::EMASS);
151 
152  Vector_t tmpE(0.0, 0.0, 0.0), tmpB(0.0, 0.0, 0.0);
153  fieldmap_m->getFieldstrength(tmpR, tmpE, tmpB);
154  double Ez = tmpE(2);
155 
156  tmpE = Vector_t(0.0);
157  fieldmap_m->getFieldDerivative(tmpR, tmpE, tmpB, DZ);
158 
159  double wtf = frequency_m * t + phase_m;
160  double kj = k * scale_m * (tmpE(2) * cos(wtf) - RefPartBunch_m->getBeta(i) * frequency_m * Ez * sin(wtf) / Physics::c);
161 
162  K += Vector_t(kj, kj, 0.0);
163 }
164 
165 
171 void RFCavity::addKT(int i, double t, Vector_t &K) {
172 
173  RefPartBunch_m->actT();
174 
175  double pz = RefPartBunch_m->getZ(i) - startField_m;
176  if (pz < 0.0 ||
177  pz >= length_m) return;
178 
179  //XXX: BET parameter, default is 1.
180  //If cxy != 1, then cxy = true
181  bool cxy = false; // default
182  double kx = 0.0, ky = 0.0;
183  if(cxy) {
184  const Vector_t tmpA(RefPartBunch_m->getX(i), RefPartBunch_m->getY(i), pz);
185 
186  Vector_t tmpE(0.0, 0.0, 0.0), tmpB(0.0, 0.0, 0.0);
187  fieldmap_m->getFieldstrength(tmpA, tmpE, tmpB);
188 
189  double cwtf = cos(frequency_m * t + phase_m);
190  double cf = -Physics::q_e / (RefPartBunch_m->getGamma(i) * Physics::m_e);
191  kx += -cf * scale_m * tmpE(0) * cwtf;
192  ky += -cf * scale_m * tmpE(1) * cwtf;
193  }
194 
195  double dx = RefPartBunch_m->getX0(i);
196  double dy = RefPartBunch_m->getY0(i);
197 
198  Vector_t KR(0.0, 0.0, 0.0);
199  addKR(i, t, KR);
200  //FIXME ?? different in bet src
201  K += Vector_t(KR(1) * dx + kx, KR(1) * dy + ky, 0.0);
202  //
203  //K += Vector_t(kx - KR(1) * dx, ky - KR(1) * dy, 0.0);
204 }
205 
206 
207 bool RFCavity::apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) {
208  return apply(RefPartBunch_m->R[i], RefPartBunch_m->P[i], t, E, B);
209 }
210 
212  const Vector_t &P,
213  const double &t,
214  Vector_t &E,
215  Vector_t &B) {
216  Vector_t tmpR(R(0), R(1), R(2) - startField_m);
217  Vector_t tmpE(0.0, 0.0, 0.0), tmpB(0.0, 0.0, 0.0);
218 
219  if (tmpR(2) >= 0.0 &&
220  tmpR(2) < length_m) {
221  bool outOfBounds = fieldmap_m->getFieldstrength(tmpR, tmpE, tmpB);
222  if (outOfBounds) return true;
223 
224  E += (scale_m + scaleError_m) * cos(frequency_m * t + phase_m + phaseError_m) * tmpE;
225  B -= (scale_m + scaleError_m) * sin(frequency_m * t + phase_m + phaseError_m) * tmpB;
226 
227  }
228  return false;
229 }
230 
232  const Vector_t &P,
233  const double &t,
234  Vector_t &E,
235  Vector_t &B) {
236 
237  Vector_t tmpR(R(0), R(1), R(2) - startField_m);
238  Vector_t tmpE(0.0, 0.0, 0.0), tmpB(0.0, 0.0, 0.0);
239 
240  if (tmpR(2) >= 0.0 &&
241  tmpR(2) < length_m) {
242  bool outOfBounds = fieldmap_m->getFieldstrength(tmpR, tmpE, tmpB);
243  if (outOfBounds) return true;
244 
245  E += scale_m * cos(frequency_m * t + phase_m) * tmpE;
246  B -= scale_m * sin(frequency_m * t + phase_m) * tmpB;
247 
248  }
249  return false;
250 }
251 
252 void RFCavity::initialise(PartBunchBase<double, 3> *bunch, double &startField, double &endField) {
253  using Physics::two_pi;
254 
255  if (bunch == NULL) {
256  startField = startField_m;
257  endField = endField_m;
258 
259  return;
260  }
261 
262  double rBegin = 0.0, rEnd = 0.0;
263  Inform msg("RFCavity ", *gmsg);
264  std::stringstream errormsg;
265  RefPartBunch_m = bunch;
266 
268 
270  if(endField_m > startField_m) {
271  msg << level2 << getName() << " using file ";
272  fieldmap_m->getInfo(&msg);
274  errormsg << "FREQUENCY IN INPUT FILE DIFFERENT THAN IN FIELD MAP '" << filename_m << "';\n"
275  << frequency_m / two_pi * 1e-6 << " MHz <> "
276  << fieldmap_m->getFrequency() / two_pi * 1e-6 << " MHz; TAKE ON THE LATTER";
277  std::string errormsg_str = Fieldmap::typeset_msg(errormsg.str(), "warning");
278  ERRORMSG(errormsg_str << "\n" << endl);
279  if(Ippl::myNode() == 0) {
280  std::ofstream omsg("errormsg.txt", std::ios_base::app);
281  omsg << errormsg_str << std::endl;
282  omsg.close();
283  }
285  }
287  endField = startField + length_m;
288  } else {
289  endField = startField - 1e-3;
290  }
291 }
292 
293 // In current version ,this function reads in the cavity voltage profile data from file.
295  std::shared_ptr<AbstractTimeDependence> freq_atd,
296  std::shared_ptr<AbstractTimeDependence> ampl_atd,
297  std::shared_ptr<AbstractTimeDependence> phase_atd) {
298  using Physics::pi;
299 
300  RefPartBunch_m = bunch;
301 
303  setAmplitudeModel(ampl_atd);
304  setPhaseModel(phase_atd);
305  setFrequencyModel(freq_atd);
306 
307  ifstream in(filename_m.c_str());
308  if(!in.good()) {
309  throw GeneralClassicException("RFCavity::initialise",
310  "failed to open file '" + filename_m + "', please check if it exists");
311  }
312  *gmsg << "* Read cavity voltage profile data" << endl;
313 
314  in >> num_points_m;
315 
316  RNormal_m = std::unique_ptr<double[]>(new double[num_points_m]);
317  VrNormal_m = std::unique_ptr<double[]>(new double[num_points_m]);
318  DvDr_m = std::unique_ptr<double[]>(new double[num_points_m]);
319 
320  for(int i = 0; i < num_points_m; i++) {
321  if(in.eof()) {
322  throw GeneralClassicException("RFCavity::initialise",
323  "not enough data in file '" + filename_m + "', please check the data format");
324  }
325  in >> RNormal_m[i] >> VrNormal_m[i] >> DvDr_m[i];
326 
327  VrNormal_m[i] *= RefPartBunch_m->getQ();
328  DvDr_m[i] *= RefPartBunch_m->getQ();
329  }
330  sinAngle_m = sin(angle_m / 180.0 * pi);
331  cosAngle_m = cos(angle_m / 180.0 * pi);
332 
333  if (frequency_name_m != "")
334  *gmsg << "* Timedependent frequency model " << frequency_name_m << endl;
335 
336  *gmsg << "* Cavity voltage data read successfully!" << endl;
337 }
338 
340 {}
341 
342 bool RFCavity::bends() const {
343  return false;
344 }
345 
346 
347 void RFCavity::goOnline(const double &) {
349 
350  online_m = true;
351 }
352 
355 
356  online_m = false;
357 }
358 
359 void RFCavity::setRmin(double rmin) {
360  rmin_m = rmin;
361 }
362 
363 void RFCavity::setRmax(double rmax) {
364  rmax_m = rmax;
365 }
366 
367 void RFCavity::setAzimuth(double angle) {
368  angle_m = angle;
369 }
370 
371 void RFCavity::setPerpenDistance(double pdis) {
372  pdis_m = pdis;
373 }
374 
375 void RFCavity::setGapWidth(double gapwidth) {
376  gapwidth_m = gapwidth;
377 }
378 
379 void RFCavity::setPhi0(double phi0) {
380  phi0_m = phi0;
381 }
382 
383 double RFCavity::getRmin() const {
384  return rmin_m;
385 }
386 
387 double RFCavity::getRmax() const {
388  return rmax_m;
389 }
390 
391 double RFCavity::getAzimuth() const {
392  return angle_m;
393 }
394 
395 double RFCavity::getSinAzimuth() const {
396  return sinAngle_m;
397 }
398 
399 double RFCavity::getCosAzimuth() const {
400  return cosAngle_m;
401 }
402 
404  return pdis_m;
405 }
406 
407 double RFCavity::getGapWidth() const {
408  return gapwidth_m;
409 }
410 
411 double RFCavity::getPhi0() const {
412  return phi0_m;
413 }
414 
415 void RFCavity::setComponentType(std::string name) {
416  name = Util::toUpper(name);
417  if(name == "STANDING") {
418  type_m = SW;
419  } else if(name == "SINGLEGAP") {
420  type_m = SGSW;
421  } else if(name != "") {
422  std::stringstream errormsg;
423  errormsg << getName() << ": CAVITY TYPE " << name << " DOES NOT EXIST;";
424  std::string errormsg_str = Fieldmap::typeset_msg(errormsg.str(), "warning");
425  ERRORMSG(errormsg_str << "\n" << endl);
426  if(Ippl::myNode() == 0) {
427  ofstream omsg("errormsg.txt", ios_base::app);
428  omsg << errormsg_str << endl;
429  omsg.close();
430  }
431  throw GeneralClassicException("RFCavity::setComponentType", errormsg_str);
432  } else {
433  type_m = SW;
434  }
435 
436 }
437 
439  if(type_m == SGSW)
440  return std::string("SINGLEGAP");
441  else
442  return std::string("STANDING");
443 }
444 
446  return frequency_m;
447 }
448 
459 void RFCavity::getMomentaKick(const double normalRadius, double momentum[], const double t, const double dtCorrt, const int PID, const double restMass, const int chargenumber) {
460  using Physics::two_pi;
461  using Physics::pi;
462  using Physics::c;
463  double derivate;
464  double Voltage;
465 
466  double momentum2 = momentum[0] * momentum[0] + momentum[1] * momentum[1] + momentum[2] * momentum[2];
467  double betgam = sqrt(momentum2);
468 
469  double gamma = sqrt(1.0 + momentum2);
470  double beta = betgam / gamma;
471 
472  Voltage = spline(normalRadius, &derivate) * scale_m * 1.0e6; // V
473 
474  double transit_factor = 0.0;
475  double Ufactor = 1.0;
476 
477  double frequency = frequency_m * frequency_td_m->getValue(t);
478 
479  if(gapwidth_m > 0.0) {
480  transit_factor = 0.5 * frequency * gapwidth_m * 1.0e-3 / (c * beta);
481  Ufactor = sin(transit_factor) / transit_factor;
482  }
483 
484  Voltage *= Ufactor;
485 
486  double nphase = (frequency * (t + dtCorrt) * 1.0e-9) - phi0_m / 180.0 * pi ; // rad/s, ns --> rad
487  double dgam = Voltage * cos(nphase) / (restMass);
488 
489  double tempdegree = fmod(nphase * 360.0 / two_pi, 360.0);
490  if(tempdegree > 270.0) tempdegree -= 360.0;
491 
492  gamma += dgam;
493 
494  double newmomentum2 = pow(gamma, 2) - 1.0;
495 
496  double pr = momentum[0] * cosAngle_m + momentum[1] * sinAngle_m;
497  double ptheta = sqrt(newmomentum2 - pow(pr, 2));
498  double px = pr * cosAngle_m - ptheta * sinAngle_m ; // x
499  double py = pr * sinAngle_m + ptheta * cosAngle_m; // y
500 
501  double rotate = -derivate * (scale_m * 1.0e6) / ((rmax_m - rmin_m) / 1000.0) * sin(nphase) / (frequency * two_pi) / (betgam * restMass / c / chargenumber); // radian
502 
504  momentum[0] = cos(rotate) * px + sin(rotate) * py;
505  momentum[1] = -sin(rotate) * px + cos(rotate) * py;
506 
507  if(PID == 0) {
508 
509  Inform m("OPAL", *gmsg, Ippl::myNode());
510 
511  m << "* Cavity " << getName() << " Phase= " << tempdegree << " [deg] transit time factor= " << Ufactor
512  << " dE= " << dgam *restMass * 1.0e-6 << " [MeV]"
513  << " E_kin= " << (gamma - 1.0)*restMass * 1.0e-6 << " [MeV] Time dep freq = " << frequency_td_m->getValue(t) << endl;
514  }
515 
516 }
517 
518 /* cubic spline subrutine */
519 double RFCavity::spline(double z, double *za) {
520  double splint;
521 
522  // domain-test and handling of case "1-support-point"
523  if(num_points_m < 1) {
524  throw GeneralClassicException("RFCavity::spline",
525  "no support points!");
526  }
527  if(num_points_m == 1) {
528  splint = RNormal_m[0];
529  *za = 0.0;
530  return splint;
531  }
532 
533  // search the two support-points
534  int il, ih;
535  il = 0;
536  ih = num_points_m - 1;
537  while((ih - il) > 1) {
538  int i = (int)((il + ih) / 2.0);
539  if(z < RNormal_m[i]) {
540  ih = i;
541  } else if(z > RNormal_m[i]) {
542  il = i;
543  } else if(z == RNormal_m[i]) {
544  il = i;
545  ih = i + 1;
546  break;
547  }
548  }
549 
550  double x1 = RNormal_m[il];
551  double x2 = RNormal_m[ih];
552  double y1 = VrNormal_m[il];
553  double y2 = VrNormal_m[ih];
554  double y1a = DvDr_m[il];
555  double y2a = DvDr_m[ih];
556  //
557  // determination of the requested function-values and its derivatives
558  //
559  double dx = x2 - x1;
560  double dy = y2 - y1;
561  double u = (z - x1) / dx;
562  double u2 = u * u;
563  double u3 = u2 * u;
564  double dy2 = -2.0 * dy;
565  double ya2 = y2a + 2.0 * y1a;
566  double dy3 = 3.0 * dy;
567  double ya3 = y2a + y1a;
568  double yb2 = dy2 + dx * ya3;
569  double yb4 = dy3 - dx * ya2;
570  splint = y1 + u * dx * y1a + u2 * yb4 + u3 * yb2;
571  *za = y1a + 2.0 * u / dx * yb4 + 3.0 * u2 / dx * yb2;
572  // if(m>=1) za=y1a+2.0*u/dx*yb4+3.0*u2/dx*yb2;
573  // if(m>=2) za[1]=2.0/dx2*yb4+6.0*u/dx2*yb2;
574  // if(m>=3) za[2]=6.0/dx3*yb2;
575 
576  return splint;
577 }
578 
579 void RFCavity::getDimensions(double &zBegin, double &zEnd) const {
580  zBegin = startField_m;
581  zEnd = endField_m;
582 }
583 
584 
586  return RFCAVITY;
587 }
588 
589 double RFCavity::getAutoPhaseEstimateFallback(double E0, double t0, double q, double mass) {
590  using Physics::pi;
591  const double dt = 1e-13;
592  const double p0 = Util::getP(E0, mass);
593  const double origPhase =getPhasem();
594 
595  double dphi = pi / 18;
596 
597  double phi = 0.0;
598  setPhasem(phi);
599  std::pair<double, double> ret = trackOnAxisParticle(E0 / mass, t0, dt, q, mass);
600  double phimax = 0.0;
601  double Emax = Util::getEnergy(Vector_t(0.0, 0.0, ret.first), mass);
602  phi += dphi;
603 
604  for (unsigned int j = 0; j < 2; ++ j) {
605  for (unsigned int i = 0; i < 36; ++ i, phi += dphi) {
606  setPhasem(phi);
607  ret = trackOnAxisParticle(p0, t0, dt, q, mass);
608  double Ekin = Util::getEnergy(Vector_t(0.0, 0.0, ret.first), mass);
609  if (Ekin > Emax) {
610  Emax = Ekin;
611  phimax = phi;
612  }
613  }
614 
615  phi = phimax - dphi;
616  dphi = dphi / 17.5;
617  }
618 
619  phimax = phimax - floor(phimax / Physics::two_pi + 0.5) * Physics::two_pi;
620  phimax = fmod(phimax, Physics::two_pi);
621 
622  const int prevPrecision = Ippl::Info->precision(8);
624  << "estimated phase= " << phimax << " rad = "
625  << phimax * Physics::rad2deg << " deg \n"
626  << "Ekin= " << Emax << " MeV" << setprecision(prevPrecision) << "\n" << endl);
627 
628  setPhasem(origPhase);
629  return phimax;
630 }
631 
632 double RFCavity::getAutoPhaseEstimate(const double &E0, const double &t0, const double &q, const double &mass) {
633  vector<double> t, E, t2, E2;
634  std::vector< double > F;
635  std::vector< std::pair< double, double > > G;
636  gsl_spline *onAxisInterpolants;
637  gsl_interp_accel *onAxisAccel;
638 
639  unsigned int N;
640  double A, B;
641  double phi = 0.0, tmp_phi, dphi = 0.5 * Physics::pi / 180.;
642  double dz = 1.0, length = 0.0;
644  double begin = (G.front()).first;
645  double end = (G.back()).first;
646  std::unique_ptr<double[]> zvals(new double[G.size()]);
647  std::unique_ptr<double[]> onAxisField(new double[G.size()]);
648 
649  for(size_t j = 0; j < G.size(); ++ j) {
650  zvals[j] = G[j].first;
651  onAxisField[j] = G[j].second;
652  }
653  onAxisInterpolants = gsl_spline_alloc(gsl_interp_cspline, G.size());
654  onAxisAccel = gsl_interp_accel_alloc();
655  gsl_spline_init(onAxisInterpolants, zvals.get(), onAxisField.get(), G.size());
656 
657  length = end - begin;
658  dz = length / G.size();
659 
660  G.clear();
661 
662  N = (int)floor(length / dz + 1);
663  dz = length / N;
664 
665  F.resize(N);
666  double z = begin;
667  for(size_t j = 0; j < N; ++ j, z += dz) {
668  F[j] = gsl_spline_eval(onAxisInterpolants, z, onAxisAccel);
669  }
670  gsl_spline_free(onAxisInterpolants);
671  gsl_interp_accel_free(onAxisAccel);
672 
673  t.resize(N, t0);
674  t2.resize(N, t0);
675  E.resize(N, E0);
676  E2.resize(N, E0);
677 
678  z = begin + dz;
679  for(unsigned int i = 1; i < N; ++ i, z += dz) {
680  E[i] = E[i - 1] + dz * scale_m / mass;
681  E2[i] = E[i];
682  }
683 
684  for(int iter = 0; iter < 10; ++ iter) {
685  A = B = 0.0;
686  for(unsigned int i = 1; i < N; ++ i) {
687  t[i] = t[i - 1] + getdT(i, E, dz, mass);
688  t2[i] = t2[i - 1] + getdT(i, E2, dz, mass);
689  A += scale_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * getdA(i, t, dz, frequency_m, F);
690  B += scale_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * getdB(i, t, dz, frequency_m, F);
691  }
692 
693  if(std::abs(B) > 0.0000001) {
694  tmp_phi = atan(A / B);
695  } else {
696  tmp_phi = Physics::pi / 2;
697  }
698  if(q * (A * sin(tmp_phi) + B * cos(tmp_phi)) < 0) {
699  tmp_phi += Physics::pi;
700  }
701 
702  if(std::abs(phi - tmp_phi) < frequency_m * (t[N - 1] - t[0]) / (10 * N)) {
703  for(unsigned int i = 1; i < N; ++ i) {
704  E[i] = E[i - 1];
705  E[i] += q * scale_m * getdE(i, t, dz, phi, frequency_m, F) ;
706  }
707  const int prevPrecision = Ippl::Info->precision(8);
708  INFOMSG(level2 << "estimated phase= " << tmp_phi << " rad = "
709  << tmp_phi * Physics::rad2deg << " deg \n"
710  << "Ekin= " << E[N - 1] << " MeV" << setprecision(prevPrecision) << "\n" << endl);
711 
712  return tmp_phi;
713  }
714  phi = tmp_phi - floor(tmp_phi / Physics::two_pi + 0.5) * Physics::two_pi;
715 
716  for(unsigned int i = 1; i < N; ++ i) {
717  E[i] = E[i - 1];
718  E2[i] = E2[i - 1];
719  E[i] += q * scale_m * getdE(i, t, dz, phi, frequency_m, F) ;
720  E2[i] += q * scale_m * getdE(i, t2, dz, phi + dphi, frequency_m, F);
721  double a = E[i], b = E2[i];
722  if (std::isnan(a) || std::isnan(b)) {
723  return getAutoPhaseEstimateFallback(E0, t0, q, mass);
724  }
725  t[i] = t[i - 1] + getdT(i, E, dz, mass);
726  t2[i] = t2[i - 1] + getdT(i, E2, dz, mass);
727 
728  E[i] = E[i - 1];
729  E2[i] = E2[i - 1];
730  E[i] += q * scale_m * getdE(i, t, dz, phi, frequency_m, F) ;
731  E2[i] += q * scale_m * getdE(i, t2, dz, phi + dphi, frequency_m, F);
732  }
733 
734  double cosine_part = 0.0, sine_part = 0.0;
735  double p0 = sqrt((E0 / mass + 1) * (E0 / mass + 1) - 1);
736  cosine_part += scale_m * cos(frequency_m * t0) * F[0];
737  sine_part += scale_m * sin(frequency_m * t0) * F[0];
738 
739  double totalEz0 = cos(phi) * cosine_part - sin(phi) * sine_part;
740 
741  if(p0 + q * totalEz0 * (t[1] - t[0]) * Physics::c / mass < 0) {
742  // make totalEz0 = 0
743  tmp_phi = atan(cosine_part / sine_part);
744  if(abs(tmp_phi - phi) > Physics::pi) {
745  phi = tmp_phi + Physics::pi;
746  } else {
747  phi = tmp_phi;
748  }
749  }
750  }
751 
752  const int prevPrecision = Ippl::Info->precision(8);
754  << "estimated phase= " << tmp_phi << " rad = "
755  << tmp_phi * Physics::rad2deg << " deg \n"
756  << "Ekin= " << E[N - 1] << " MeV" << setprecision(prevPrecision) << "\n" << endl);
757 
758  return phi;
759 }
760 
761 pair<double, double> RFCavity::trackOnAxisParticle(const double &p0,
762  const double &t0,
763  const double &dt,
764  const double &q,
765  const double &mass,
766  std::ofstream *out) {
767  Vector_t p(0, 0, p0);
768  double t = t0;
769  BorisPusher integrator(*RefPartBunch_m->getReference());
770  const double cdt = Physics::c * dt;
771  const double zbegin = startField_m;
772  const double zend = length_m + startField_m;
773 
774  Vector_t z(0.0, 0.0, zbegin);
775  double dz = 0.5 * p(2) / sqrt(1.0 + dot(p, p)) * cdt;
776  Vector_t Ef(0.0), Bf(0.0);
777 
778  if (out) *out << std::setw(18) << z[2]
779  << std::setw(18) << Util::getEnergy(p, mass)
780  << std::endl;
781  while(z(2) + dz < zend && z(2) + dz > zbegin) {
782  z /= cdt;
783  integrator.push(z, p, dt);
784  z *= cdt;
785 
786  if(z(2) >= zbegin && z(2) <= zend) {
787  Ef = 0.0;
788  Bf = 0.0;
789  applyToReferenceParticle(z, p, t + 0.5 * dt, Ef, Bf);
790  }
791  integrator.kick(z, p, Ef, Bf, dt);
792 
793  dz = 0.5 * p(2) / sqrt(1.0 + dot(p, p)) * cdt;
794  z /= cdt;
795  integrator.push(z, p, dt);
796  z *= cdt;
797  t += dt;
798 
799  if (out) *out << std::setw(18) << z[2]
800  << std::setw(18) << Util::getEnergy(p, mass)
801  << std::endl;
802  }
803 
804  const double beta = sqrt(1. - 1 / (dot(p, p) + 1.));
805  const double tErr = (z(2) - zend) / (Physics::c * beta);
806 
807  return pair<double, double>(p(2), t - tErr);
808 }
809 
810 bool RFCavity::isInside(const Vector_t &r) const {
811  if (isInsideTransverse(r)) {
812  return fieldmap_m->isInside(r);
813  }
814 
815  return false;
816 }
817 
819  double length = ElementBase::getElementLength();
820  if (length < 1e-10 && fieldmap_m != NULL) {
821  double start, end, tmp;
822  fieldmap_m->getFieldDimensions(start, end, tmp, tmp);
823  length = end - start;
824  }
825 
826  return length;
827 }
828 
830  double &end) const {
831  double tmp;
832  fieldmap_m->getFieldDimensions(begin, end, tmp, tmp);
833 }
ParticleAttrib< Vector_t > P
virtual ~RFCavity()
Definition: RFCavity.cpp:124
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 rmax_m
Definition: RFCavity.h:240
constexpr double e
The value of .
Definition: Physics.h:40
virtual void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField) override
Definition: RFCavity.cpp:252
virtual void addKR(int i, double t, Vector_t &K) override
Definition: RFCavity.cpp:143
double length_m
Definition: RFCavity.h:235
void setRmin(double rmin)
Definition: RFCavity.cpp:359
virtual ElementBase::ElementType getType() const override
Get element type std::string.
Definition: RFCavity.cpp:585
double getP(double E, double mass)
Definition: Util.h:34
virtual void readMap()=0
virtual void goOffline() override
Definition: RFCavity.cpp:353
virtual void actT()
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
double spline(double z, double *za)
Definition: RFCavity.cpp:519
virtual bool isInside(const Vector_t &r) const
Definition: Fieldmap.h:203
double getdB(const int &i, const std::vector< double > &t, const double &dz, const double &frequency, const std::vector< double > &F) const
Definition: RFCavity.h:334
virtual void setComponentType(std::string name) override
Definition: RFCavity.cpp:415
virtual double getElementLength() const override
Get design length.
Definition: RFCavity.cpp:818
double startField_m
Definition: RFCavity.h:233
Inform * gmsg
Definition: Main.cpp:21
std::string toUpper(const std::string &str)
Definition: Util.cpp:130
bool online_m
Definition: Component.h:201
void setRmax(double rmax)
Definition: RFCavity.cpp:363
virtual void getFieldDimensions(double &zBegin, double &zEnd, double &rBegin, double &rEnd) const =0
virtual void visitRFCavity(const RFCavity &)=0
Apply the algorithm to a RF cavity.
const PartData * getReference() const
virtual void getElementDimensions(double &begin, double &end) const override
Definition: RFCavity.cpp:829
double pdis_m
Definition: RFCavity.h:244
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
virtual void finalise() override
Definition: RFCavity.cpp:339
static std::string typeset_msg(const std::string &msg, const std::string &title)
Definition: Fieldmap.cpp:647
double endField_m
Definition: RFCavity.h:234
std::string frequency_name_m
Definition: RFCavity.h:217
static Fieldmap * getFieldmap(std::string Filename, bool fast=false)
Definition: Fieldmap.cpp:46
virtual double getY(int i)
void setAmplitudeModel(std::shared_ptr< AbstractTimeDependence > time_dep)
Definition: RFCavity.h:463
virtual double getRmin() const
Definition: RFCavity.cpp:383
constexpr double rad2deg
The conversion factor from radians to degrees.
Definition: Physics.h:46
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition: Vector3D.cpp:118
double getdT(const int &i, const std::vector< double > &E, const double &dz, const double mass) const
Definition: RFCavity.h:294
double getdE(const int &i, const std::vector< double > &t, const double &dz, const double &phi, const double &frequency, const std::vector< double > &F) const
Definition: RFCavity.h:282
std::unique_ptr< double[]> RNormal_m
Definition: RFCavity.h:248
double angle_m
Definition: RFCavity.h:241
std::unique_ptr< double[]> VrNormal_m
Definition: RFCavity.h:249
void setFrequencyModel(std::shared_ptr< AbstractTimeDependence > time_dep)
Definition: RFCavity.h:493
constexpr double m_e
The electron rest mass in GeV.
Definition: Physics.h:85
Inform & level2(Inform &inf)
Definition: Inform.cpp:46
double rmin_m
Definition: RFCavity.h:239
virtual void getDimensions(double &zBegin, double &zEnd) const override
Definition: RFCavity.cpp:579
virtual double getAzimuth() const
Definition: RFCavity.cpp:391
bool fast_m
Definition: RFCavity.h:227
virtual bool getFieldstrength(const Vector_t &R, Vector_t &E, Vector_t &B) const =0
void setPhaseModel(std::shared_ptr< AbstractTimeDependence > time_dep)
Definition: RFCavity.h:478
virtual double getGamma(int i)
void setPhi0(double phi0)
Definition: RFCavity.cpp:379
virtual bool bends() const override
Definition: RFCavity.cpp:342
std::unique_ptr< double[]> DvDr_m
Definition: RFCavity.h:250
CavityType type_m
Definition: RFCavity.h:237
virtual double getPhi0() const
Definition: RFCavity.cpp:411
virtual double getGapWidth() const
Definition: RFCavity.cpp:407
void setAzimuth(double angle)
Definition: RFCavity.cpp:367
constexpr double pi
The value of .
Definition: Physics.h:31
void setElType(ElemType elt)
set the element type as enumeration needed in the envelope tracker
Definition: ElementBase.h:591
double phaseError_m
Definition: RFCavity.h:224
Fieldmap * fieldmap_m
Definition: RFCavity.h:232
virtual double getPerpenDistance() const
Definition: RFCavity.cpp:403
virtual double getElementLength() const
Get design length.
Definition: ElementBase.h:511
double sinAngle_m
Definition: RFCavity.h:242
virtual std::string getComponentType() const override
Definition: RFCavity.cpp:438
virtual double getBeta(int i)
virtual double getPhasem() const
Definition: RFCavity.h:413
double phi0_m
Definition: RFCavity.h:246
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
virtual double getY0(int i)
#define INFOMSG(msg)
Definition: IpplInfo.h:397
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:200
void splint(double xa[], double ya[], double y2a[], int n, double x, double *y)
Definition: interpol.cpp:95
void setGapWidth(double gapwidth)
Definition: RFCavity.cpp:375
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
Definition: TpsMath.h:76
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6
virtual double getFrequency() const =0
double getdA(const int &i, const std::vector< double > &t, const double &dz, const double &frequency, const std::vector< double > &F) const
Definition: RFCavity.h:322
PETE_TBTree< FnFmod, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > fmod(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
void setPerpenDistance(double pdis)
Definition: RFCavity.cpp:371
int precision() const
Definition: Inform.h:115
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
double frequency_m
Definition: RFCavity.h:225
virtual void addKT(int i, double t, Vector_t &K) override
Definition: RFCavity.cpp:171
virtual bool applyToReferenceParticle(const Vector_t &R, const Vector_t &P, const double &t, Vector_t &E, Vector_t &B) override
Definition: RFCavity.cpp:231
virtual void setPhasem(double phase)
Definition: RFCavity.h:408
virtual double getAutoPhaseEstimateFallback(double E0, double t0, double q, double m)
Definition: RFCavity.cpp:589
virtual double getCycFrequency() const
Definition: RFCavity.cpp:445
Definition: Fieldmap.h:57
void getMomentaKick(const double normalRadius, double momentum[], const double t, const double dtCorrt, const int PID, const double restMass, const int chargenumber)
used in OPAL-cycl
Definition: RFCavity.cpp:459
virtual double getRmax() const
Definition: RFCavity.cpp:387
Interface for RF cavity.
Definition: RFCavity.h:37
virtual double getX0(int i)
virtual double getSinAzimuth() const
Definition: RFCavity.cpp:395
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
static Inform * Info
Definition: IpplInfo.h:87
virtual bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) override
Definition: RFCavity.cpp:207
constexpr double q_e
The elementary charge in As.
Definition: Physics.h:76
double getQ() const
Access to reference data.
double cosAngle_m
Definition: RFCavity.h:243
const std::string name
virtual void accept(BeamlineVisitor &) const override
Apply visitor to RFCavity.
Definition: RFCavity.cpp:134
T isnan(T x)
isnan function with adjusted return type
Definition: matheval.hpp:74
double phase_m
Definition: RFCavity.h:223
virtual bool isInside(const Vector_t &r) const override
Definition: RFCavity.cpp:810
double getEnergy(Vector_t p, double mass)
Definition: Util.h:29
int num_points_m
Definition: RFCavity.h:251
std::shared_ptr< AbstractTimeDependence > frequency_td_m
Definition: RFCavity.h:216
double gapwidth_m
Definition: RFCavity.h:245
virtual double getZ(int i)
ParticlePos_t & R
constexpr double EMASS
Definition: Physics.h:140
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)
Definition: RFCavity.cpp:761
virtual double getCosAzimuth() const
Definition: RFCavity.cpp:399
bool isInsideTransverse(const Vector_t &r, double f=1) const
Definition: ElementBase.h:645
Interface for a single beam element.
Definition: Component.h:51
virtual double getX(int i)
#define K
Definition: integrate.cpp:118
Abstract algorithm.
Definition: Inform.h:41
virtual bool getFieldDerivative(const Vector_t &R, Vector_t &E, Vector_t &B, const DiffDirection &dir) const =0
RFCavity()
Definition: RFCavity.cpp:41
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
virtual double getAutoPhaseEstimate(const double &E0, const double &t0, const double &q, const double &m)
Definition: RFCavity.cpp:632
virtual void goOnline(const double &kineticEnergy) override
Definition: RFCavity.cpp:347