OPAL (Object Oriented Parallel Accelerator Library)  2024.1
OPAL
RFCavity.cpp
Go to the documentation of this file.
1 //
2 // Class RFCavity
3 // Defines the abstract interface for for RF cavities.
4 //
5 // Copyright (c) 200x - 2021, Paul Scherrer Institut, Villigen PSI, Switzerland
6 // All rights reserved
7 //
8 // This file is part of OPAL.
9 //
10 // OPAL is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
17 //
18 #include "AbsBeamline/RFCavity.h"
19 
22 #include "Fields/Fieldmap.h"
23 #include "Physics/Units.h"
24 #include "Steppers/BorisPusher.h"
26 #include "Utilities/Util.h"
27 
28 #include <boost/assign.hpp>
29 #include <filesystem>
30 
31 #include "gsl/gsl_interp.h"
32 #include "gsl/gsl_spline.h"
33 
34 #include <iostream>
35 #include <fstream>
36 
37 extern Inform *gmsg;
38 
39 const boost::bimap<CavityType, std::string> RFCavity::bmCavityTypeString_s =
40  boost::assign::list_of<const boost::bimap<CavityType, std::string>::relation>
41  (CavityType::SW, "STANDING")
42  (CavityType::SGSW, "SINGLEGAP");
43 
44 
46  RFCavity("")
47 {}
48 
50  Component(right),
51  phaseTD_m(right.phaseTD_m),
52  phaseName_m(right.phaseName_m),
53  amplitudeTD_m(right.amplitudeTD_m),
54  amplitudeName_m(right.amplitudeName_m),
55  frequencyTD_m(right.frequencyTD_m),
56  frequencyName_m(right.frequencyName_m),
57  filename_m(right.filename_m),
58  scale_m(right.scale_m),
59  scaleError_m(right.scaleError_m),
60  phase_m(right.phase_m),
61  phaseError_m(right.phaseError_m),
62  frequency_m(right.frequency_m),
63  fast_m(right.fast_m),
64  autophaseVeto_m(right.autophaseVeto_m),
65  designEnergy_m(right.designEnergy_m),
66  fieldmap_m(right.fieldmap_m),
67  startField_m(right.startField_m),
68  endField_m(right.endField_m),
69  type_m(right.type_m),
70  rmin_m(right.rmin_m),
71  rmax_m(right.rmax_m),
72  angle_m(right.angle_m),
73  sinAngle_m(right.sinAngle_m),
74  cosAngle_m(right.cosAngle_m),
75  pdis_m(right.pdis_m),
76  gapwidth_m(right.gapwidth_m),
77  phi0_m(right.phi0_m),
78  RNormal_m(nullptr),
79  VrNormal_m(nullptr),
80  DvDr_m(nullptr),
81  num_points_m(right.num_points_m)
82 {}
83 
84 RFCavity::RFCavity(const std::string& name):
85  Component(name),
86  phaseTD_m(nullptr),
87  amplitudeTD_m(nullptr),
88  frequencyTD_m(nullptr),
89  filename_m(""),
90  scale_m(1.0),
91  scaleError_m(0.0),
92  phase_m(0.0),
93  phaseError_m(0.0),
94  frequency_m(0.0),
95  fast_m(true),
96  autophaseVeto_m(false),
97  designEnergy_m(-1.0),
98  fieldmap_m(nullptr),
99  startField_m(0.0),
100  endField_m(0.0),
101  type_m(CavityType::SW),
102  rmin_m(0.0),
103  rmax_m(0.0),
104  angle_m(0.0),
105  sinAngle_m(0.0),
106  cosAngle_m(0.0),
107  pdis_m(0.0),
108  gapwidth_m(0.0),
109  phi0_m(0.0),
110  RNormal_m(nullptr),
111  VrNormal_m(nullptr),
112  DvDr_m(nullptr),
113  num_points_m(0)
114 {}
115 
117 }
118 
119 void RFCavity::accept(BeamlineVisitor& visitor) const {
120  visitor.visitRFCavity(*this);
121 }
122 
123 bool RFCavity::apply(const size_t& i, const double& t, Vector_t& E, Vector_t& B) {
124  return apply(RefPartBunch_m->R[i], RefPartBunch_m->P[i], t, E, B);
125 }
126 
128  const Vector_t& /*P*/,
129  const double& t,
130  Vector_t& E,
131  Vector_t& B) {
132 
133  if (R(2) >= startField_m &&
134  R(2) < startField_m + getElementLength()) {
135 
136  Vector_t tmpE(0.0, 0.0, 0.0), tmpB(0.0, 0.0, 0.0);
137 
138  bool outOfBounds = fieldmap_m->getFieldstrength(R, tmpE, tmpB);
139  if (outOfBounds) return getFlagDeleteOnTransverseExit();
140 
141  E += (scale_m + scaleError_m) * std::cos(frequency_m * t + phase_m + phaseError_m) * tmpE;
142  B -= (scale_m + scaleError_m) * std::sin(frequency_m * t + phase_m + phaseError_m) * tmpB;
143  }
144  return false;
145 }
146 
148  const Vector_t& /*P*/,
149  const double& t,
150  Vector_t& E,
151  Vector_t& B) {
152 
153  if (R(2) >= startField_m &&
154  R(2) < startField_m + getElementLength()) {
155  Vector_t tmpE(0.0, 0.0, 0.0), tmpB(0.0, 0.0, 0.0);
156 
157  bool outOfBounds = fieldmap_m->getFieldstrength(R, tmpE, tmpB);
158  if (outOfBounds) return true;
159 
160  E += scale_m * std::cos(frequency_m * t + phase_m) * tmpE;
161  B -= scale_m * std::sin(frequency_m * t + phase_m) * tmpB;
162  }
163 
164  return false;
165 }
166 
167 void RFCavity::initialise(PartBunchBase<double, 3>* bunch, double& startField, double& endField) {
168 
169  startField_m = endField_m = 0.0;
170  if (bunch == nullptr) {
171  startField = startField_m;
172  endField = endField_m;
173 
174  return;
175  }
176 
177  Inform msg("RFCavity ", *gmsg);
178  std::stringstream errormsg;
179  RefPartBunch_m = bunch;
180 
182  fieldmap_m->getFieldDimensions(startField_m, endField);
183  if (endField <= startField_m) {
184  throw GeneralClassicException("RFCavity::initialise",
185  "The length of the field map '" + filename_m + "' is zero or negative");
186  }
187 
188  msg << level2 << getName() << " using file ";
189  fieldmap_m->getInfo(&msg);
190  if (std::abs((frequency_m - fieldmap_m->getFrequency()) / frequency_m) > 0.01) {
191  errormsg << "FREQUENCY IN INPUT FILE DIFFERENT THAN IN FIELD MAP '" << filename_m << "';\n"
192  << frequency_m / Physics::two_pi * Units::Hz2MHz << " MHz <> "
193  << fieldmap_m->getFrequency() / Physics::two_pi * Units::Hz2MHz << " MHz; TAKE ON THE LATTER";
194  std::string errormsg_str = _Fieldmap::typeset_msg(errormsg.str(), "warning");
195  ERRORMSG(errormsg_str << "\n" << endl);
196  if (Ippl::myNode() == 0) {
197  std::ofstream omsg("errormsg.txt", std::ios_base::app);
198  omsg << errormsg_str << std::endl;
199  omsg.close();
200  }
201  frequency_m = fieldmap_m->getFrequency();
202  }
203  setElementLength(endField - startField_m);
204 }
205 
206 // In current version ,this function reads in the cavity voltage profile data from file.
208  std::shared_ptr<AbstractTimeDependence> freq_atd,
209  std::shared_ptr<AbstractTimeDependence> ampl_atd,
210  std::shared_ptr<AbstractTimeDependence> phase_atd) {
211 
212  RefPartBunch_m = bunch;
213 
215  setAmplitudeModel(ampl_atd);
216  setPhaseModel(phase_atd);
217  setFrequencyModel(freq_atd);
218 
219  std::ifstream in(filename_m.c_str());
220  in >> num_points_m;
221 
222  RNormal_m = std::unique_ptr<double[]>(new double[num_points_m]);
223  VrNormal_m = std::unique_ptr<double[]>(new double[num_points_m]);
224  DvDr_m = std::unique_ptr<double[]>(new double[num_points_m]);
225 
226  for (int i = 0; i < num_points_m; i++) {
227  if (in.eof()) {
228  throw GeneralClassicException("RFCavity::initialise",
229  "Not enough data in file '" + filename_m +
230  "', please check the data format");
231  }
232  in >> RNormal_m[i] >> VrNormal_m[i] >> DvDr_m[i];
233 
234  VrNormal_m[i] *= RefPartBunch_m->getQ();
235  DvDr_m[i] *= RefPartBunch_m->getQ();
236  }
239 
240  if (!frequencyName_m.empty()) {
241  *gmsg << "* Timedependent frequency model " << frequencyName_m << endl;
242  }
243 
244  *gmsg << "* Cavity voltage data read successfully!" << endl;
245 }
246 
248 {}
249 
250 bool RFCavity::bends() const {
251  return false;
252 }
253 
254 void RFCavity::goOnline(const double&) {
256 
257  online_m = true;
258 }
259 
262 
263  online_m = false;
264 }
265 
266 void RFCavity::setRmin(double rmin) {
267  rmin_m = rmin;
268 }
269 
270 void RFCavity::setRmax(double rmax) {
271  rmax_m = rmax;
272 }
273 
275  angle_m = angle;
276 }
277 
278 void RFCavity::setPerpenDistance(double pdis) {
279  pdis_m = pdis;
280 }
281 
282 void RFCavity::setGapWidth(double gapwidth) {
283  gapwidth_m = gapwidth;
284 }
285 
286 void RFCavity::setPhi0(double phi0) {
287  phi0_m = phi0;
288 }
289 
290 double RFCavity::getRmin() const {
291  if (rmin_m >= 0.0) {
292  return rmin_m;
293  } else {
294  throw GeneralClassicException("RFCavity::getRmin",
295  "RMIN must be positive");
296  }
297 }
298 
299 double RFCavity::getRmax() const {
300  if (rmax_m > rmin_m) {
301  return rmax_m;
302  } else {
303  throw GeneralClassicException("RFCavity::getRmax",
304  "The attribute RMAX has to be higher than RMIN");
305  }
306 }
307 
308 double RFCavity::getAzimuth() const {
309  return angle_m;
310 }
311 
312 double RFCavity::getSinAzimuth() const {
313  return sinAngle_m;
314 }
315 
316 double RFCavity::getCosAzimuth() const {
317  return cosAngle_m;
318 }
319 
321  return pdis_m;
322 }
323 
324 double RFCavity::getGapWidth() const {
325  return gapwidth_m;
326 }
327 
328 double RFCavity::getPhi0() const {
329  return phi0_m;
330 }
331 
332 void RFCavity::setCavityType(const std::string& name) {
333  auto it = bmCavityTypeString_s.right.find(name);
334  if (it != bmCavityTypeString_s.right.end()) {
335  type_m = it->second;
336  } else {
338  }
339 }
340 
341 std::string RFCavity::getCavityTypeString() const {
342  return bmCavityTypeString_s.left.at(type_m);
343 }
344 
345 std::string RFCavity::getFieldMapFN() const {
346  if (filename_m.empty()) {
347  throw GeneralClassicException("RFCavity::getFieldMapFN",
348  "The attribute \"FMAPFN\" isn't set "
349  "for the \"RFCAVITY\" element!");
350  } else if (std::filesystem::exists(filename_m)) {
351  return filename_m;
352  } else {
353  throw GeneralClassicException("RFCavity::getFieldMapFN",
354  "Failed to open file '" + filename_m +
355  "', please check if it exists");
356  }
357 }
358 
360  return frequency_m;
361 }
362 
373 void RFCavity::getMomentaKick(const double normalRadius,
374  double momentum[],
375  const double t,
376  const double dtCorrt,
377  const int PID,
378  const double restMass,
379  const int chargenumber) {
380 
381  double derivate;
382 
383  double momentum2 = momentum[0] * momentum[0] + momentum[1] * momentum[1] + momentum[2] * momentum[2];
384  double betgam = std::sqrt(momentum2);
385 
386  double gamma = std::sqrt(1.0 + momentum2);
387  double beta = betgam / gamma;
388 
389  double Voltage = spline(normalRadius, &derivate) * scale_m * Units::MVpm2Vpm;
390 
391  double Ufactor = 1.0;
392 
393  double frequency = frequency_m * frequencyTD_m->getValue(t);
394 
395  if (gapwidth_m > 0.0) {
396  double transit_factor = 0.5 * frequency * gapwidth_m / (Physics::c * beta);
397  Ufactor = std::sin(transit_factor) / transit_factor;
398  }
399 
400  Voltage *= Ufactor;
401  // rad/s, ns --> rad
402 
403  double nphase = (frequency * (t + dtCorrt)) - phi0_m;
404  double dgam = Voltage * std::cos(nphase) / (restMass);
405 
406  double tempdegree = std::fmod(nphase * Units::rad2deg, 360.0);
407  if (tempdegree > 270.0) tempdegree -= 360.0;
408 
409  gamma += dgam;
410 
411  double newmomentum2 = std::pow(gamma, 2) - 1.0;
412 
413  double pr = momentum[0] * cosAngle_m + momentum[1] * sinAngle_m;
414  double ptheta = std::sqrt(newmomentum2 - std::pow(pr, 2));
415  double px = pr * cosAngle_m - ptheta * sinAngle_m ; // x
416  double py = pr * sinAngle_m + ptheta * cosAngle_m; // y
417 
418  double rotate = -derivate * (scale_m * Units::MVpm2Vpm) / (rmax_m - rmin_m) * std::sin(nphase) / (frequency * Physics::two_pi) / (betgam * restMass / Physics::c / chargenumber); // radian
419 
421  momentum[0] = std::cos(rotate) * px + std::sin(rotate) * py;
422  momentum[1] = -std::sin(rotate) * px + std::cos(rotate) * py;
423 
424  if (PID == 0) {
425  Inform m("OPAL", *gmsg, Ippl::myNode());
426  m << "* Cavity " << getName() << " Phase= " << tempdegree << " [deg] transit time factor= " << Ufactor
427  << " dE= " << dgam * restMass * Units::eV2MeV << " [MeV]"
428  << " E_kin= " << (gamma - 1.0) * restMass * Units::eV2MeV << " [MeV] Time dep freq = " << frequencyTD_m->getValue(t) << endl;
429  }
430 }
431 
432 /* cubic spline subrutine */
433 double RFCavity::spline(double z, double* za) {
434  double splint;
435 
436  // domain-test and handling of case "1-support-point"
437  if (num_points_m < 1) {
438  throw GeneralClassicException("RFCavity::spline",
439  "no support points!");
440  }
441  if (num_points_m == 1) {
442  splint = RNormal_m[0];
443  *za = 0.0;
444  return splint;
445  }
446 
447  // search the two support-points
448  int il, ih;
449  il = 0;
450  ih = num_points_m - 1;
451  while ((ih - il) > 1) {
452  int i = (int)((il + ih) / 2.0);
453  if (z < RNormal_m[i]) {
454  ih = i;
455  } else if (z > RNormal_m[i]) {
456  il = i;
457  } else if (z == RNormal_m[i]) {
458  il = i;
459  ih = i + 1;
460  break;
461  }
462  }
463 
464  double x1 = RNormal_m[il];
465  double x2 = RNormal_m[ih];
466  double y1 = VrNormal_m[il];
467  double y2 = VrNormal_m[ih];
468  double y1a = DvDr_m[il];
469  double y2a = DvDr_m[ih];
470  //
471  // determination of the requested function-values and its derivatives
472  //
473  double dx = x2 - x1;
474  double dy = y2 - y1;
475  double u = (z - x1) / dx;
476  double u2 = u * u;
477  double u3 = u2 * u;
478  double dy2 = -2.0 * dy;
479  double ya2 = y2a + 2.0 * y1a;
480  double dy3 = 3.0 * dy;
481  double ya3 = y2a + y1a;
482  double yb2 = dy2 + dx * ya3;
483  double yb4 = dy3 - dx * ya2;
484  splint = y1 + u * dx * y1a + u2 * yb4 + u3 * yb2;
485  *za = y1a + 2.0 * u / dx * yb4 + 3.0 * u2 / dx * yb2;
486  // if(m>=1) za=y1a+2.0*u/dx*yb4+3.0*u2/dx*yb2;
487  // if(m>=2) za[1]=2.0/dx2*yb4+6.0*u/dx2*yb2;
488  // if(m>=3) za[2]=6.0/dx3*yb2;
489 
490  return splint;
491 }
492 
493 void RFCavity::getDimensions(double& zBegin, double& zEnd) const {
494  zBegin = startField_m;
495  zEnd = endField_m;
496 }
497 
498 
500  return ElementType::RFCAVITY;
501 }
502 
503 double RFCavity::getAutoPhaseEstimateFallback(double E0, double t0, double q, double mass) {
504 
505  const double dt = 1e-13;
506  const double p0 = Util::getBetaGamma(E0, mass);
507  const double origPhase =getPhasem();
508  double dphi = Physics::pi / 18;
509 
510  double phi = 0.0;
511  setPhasem(phi);
512  std::pair<double, double> ret = trackOnAxisParticle(p0, t0, dt, q, mass);
513  double phimax = 0.0;
514  double Emax = Util::getKineticEnergy(Vector_t(0.0, 0.0, ret.first), mass);
515  phi += dphi;
516 
517  for (unsigned int j = 0; j < 2; ++ j) {
518  for (unsigned int i = 0; i < 36; ++ i, phi += dphi) {
519  setPhasem(phi);
520  ret = trackOnAxisParticle(p0, t0, dt, q, mass);
521  double Ekin = Util::getKineticEnergy(Vector_t(0.0, 0.0, ret.first), mass);
522  if (Ekin > Emax) {
523  Emax = Ekin;
524  phimax = phi;
525  }
526  }
527 
528  phi = phimax - dphi;
529  dphi = dphi / 17.5;
530  }
531 
532  phimax = phimax - std::round(phimax / Physics::two_pi) * Physics::two_pi;
533  phimax = std::fmod(phimax, Physics::two_pi);
534 
535  const int prevPrecision = Ippl::Info->precision(8);
537  << "estimated phase= " << phimax << " rad = "
538  << phimax * Units::rad2deg << " deg \n"
539  << "Ekin= " << Emax << " MeV" << std::setprecision(prevPrecision) << "\n" << endl);
540 
541  setPhasem(origPhase);
542  return phimax;
543 }
544 
545 double RFCavity::getAutoPhaseEstimate(const double& E0, const double& t0,
546  const double& q, const double& mass) {
547  std::vector<double> t, E, t2, E2;
548  std::vector<double> F;
549  std::vector< std::pair< double, double > > G;
550  gsl_spline *onAxisInterpolants;
551  gsl_interp_accel *onAxisAccel;
552 
553  double phi = 0.0, tmp_phi, dphi = 0.5 * Units::deg2rad;
554  double dz = 1.0, length = 0.0;
555  fieldmap_m->getOnaxisEz(G);
556  if (G.size() == 0) return 0.0;
557  double begin = (G.front()).first;
558  double end = (G.back()).first;
559  std::unique_ptr<double[]> zvals( new double[G.size()]);
560  std::unique_ptr<double[]> onAxisField(new double[G.size()]);
561 
562  for (size_t j = 0; j < G.size(); ++ j) {
563  zvals[j] = G[j].first;
564  onAxisField[j] = G[j].second;
565  }
566  onAxisInterpolants = gsl_spline_alloc(gsl_interp_cspline, G.size());
567  onAxisAccel = gsl_interp_accel_alloc();
568  gsl_spline_init(onAxisInterpolants, zvals.get(), onAxisField.get(), G.size());
569 
570  length = end - begin;
571  dz = length / G.size();
572 
573  G.clear();
574 
575  unsigned int N = (int)std::floor(length / dz + 1);
576  dz = length / N;
577 
578  F.resize(N);
579  double z = begin;
580  for (size_t j = 0; j < N; ++ j, z += dz) {
581  F[j] = gsl_spline_eval(onAxisInterpolants, z, onAxisAccel);
582  }
583  gsl_spline_free(onAxisInterpolants);
584  gsl_interp_accel_free(onAxisAccel);
585 
586  t.resize(N, t0);
587  t2.resize(N, t0);
588  E.resize(N, E0);
589  E2.resize(N, E0);
590 
591  z = begin + dz;
592  for (unsigned int i = 1; i < N; ++ i, z += dz) {
593  E[i] = E[i - 1] + dz * scale_m / mass;
594  E2[i] = E[i];
595  }
596 
597  for (int iter = 0; iter < 10; ++ iter) {
598  double A = 0.0;
599  double B = 0.0;
600  for (unsigned int i = 1; i < N; ++ i) {
601  t[i] = t[i - 1] + getdT(i, E, dz, mass);
602  t2[i] = t2[i - 1] + getdT(i, E2, dz, mass);
603  A += scale_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * getdA(i, t, dz, frequency_m, F);
604  B += scale_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * getdB(i, t, dz, frequency_m, F);
605  }
606 
607  if (std::abs(B) > 0.0000001) {
608  tmp_phi = std::atan(A / B);
609  } else {
610  tmp_phi = Physics::pi / 2;
611  }
612  if (q * (A * std::sin(tmp_phi) + B * std::cos(tmp_phi)) < 0) {
613  tmp_phi += Physics::pi;
614  }
615 
616  if (std::abs (phi - tmp_phi) < frequency_m * (t[N - 1] - t[0]) / (10 * N)) {
617  for (unsigned int i = 1; i < N; ++ i) {
618  E[i] = E[i - 1];
619  E[i] += q * scale_m * getdE(i, t, dz, phi, frequency_m, F) ;
620  }
621  const int prevPrecision = Ippl::Info->precision(8);
622  INFOMSG(level2 << "estimated phase= " << tmp_phi << " rad = "
623  << tmp_phi * Units::rad2deg << " deg \n"
624  << "Ekin= " << E[N - 1] << " MeV" << std::setprecision(prevPrecision) << "\n" << endl);
625 
626  return tmp_phi;
627  }
628  phi = tmp_phi - std::round(tmp_phi / Physics::two_pi) * Physics::two_pi;
629 
630  for (unsigned int i = 1; i < N; ++ i) {
631  E[i] = E[i - 1];
632  E2[i] = E2[i - 1];
633  E[i] += q * scale_m * getdE(i, t, dz, phi, frequency_m, F) ;
634  E2[i] += q * scale_m * getdE(i, t2, dz, phi + dphi, frequency_m, F);
635  double a = E[i], b = E2[i];
636  if (std::isnan(a) || std::isnan(b)) {
637  return getAutoPhaseEstimateFallback(E0, t0, q, mass);
638  }
639  t[i] = t[i - 1] + getdT(i, E, dz, mass);
640  t2[i] = t2[i - 1] + getdT(i, E2, dz, mass);
641 
642  E[i] = E [i - 1];
643  E2[i] = E2[i - 1];
644  E[i] += q * scale_m * getdE(i, t, dz, phi, frequency_m, F) ;
645  E2[i] += q * scale_m * getdE(i, t2, dz, phi + dphi, frequency_m, F);
646  }
647 
648  double cosine_part = 0.0, sine_part = 0.0;
649  double p0 = Util::getBetaGamma(E0, mass);
650  cosine_part += scale_m * std::cos(frequency_m * t0) * F[0];
651  sine_part += scale_m * std::sin(frequency_m * t0) * F[0];
652 
653  double totalEz0 = std::cos(phi) * cosine_part - std::sin(phi) * sine_part;
654 
655  if (p0 + q * totalEz0 * (t[1] - t[0]) * Physics::c / mass < 0) {
656  // make totalEz0 = 0
657  tmp_phi = std::atan(cosine_part / sine_part);
658  if (std::abs (tmp_phi - phi) > Physics::pi) {
659  phi = tmp_phi + Physics::pi;
660  } else {
661  phi = tmp_phi;
662  }
663  }
664  }
665 
666  const int prevPrecision = Ippl::Info->precision(8);
668  << "estimated phase= " << tmp_phi << " rad = "
669  << tmp_phi * Units::rad2deg << " deg \n"
670  << "Ekin= " << E[N - 1] << " MeV" << std::setprecision(prevPrecision) << "\n" << endl);
671 
672  return phi;
673 }
674 
675 std::pair<double, double> RFCavity::trackOnAxisParticle(const double& p0,
676  const double& t0,
677  const double& dt,
678  const double& /*q*/,
679  const double& mass,
680  std::ofstream *out) {
681  Vector_t p(0, 0, p0);
682  double t = t0;
683  BorisPusher integrator(*RefPartBunch_m->getReference());
684  const double cdt = Physics::c * dt;
685  const double zbegin = startField_m;
686  const double zend = getElementLength() + startField_m;
687 
688  Vector_t z(0.0, 0.0, zbegin);
689  double dz = 0.5 * p(2) / Util::getGamma(p) * cdt;
690  Vector_t Ef(0.0), Bf(0.0);
691 
692  if (out) *out << std::setw(18) << z[2]
693  << std::setw(18) << Util::getKineticEnergy(p, mass)
694  << std::endl;
695  while (z(2) + dz < zend && z(2) + dz > zbegin) {
696  z /= cdt;
697  integrator.push(z, p, dt);
698  z *= cdt;
699 
700  Ef = 0.0;
701  Bf = 0.0;
702  if (z(2) >= zbegin && z(2) <= zend) {
703  applyToReferenceParticle(z, p, t + 0.5 * dt, Ef, Bf);
704  }
705  integrator.kick(z, p, Ef, Bf, dt);
706 
707  dz = 0.5 * p(2) / std::sqrt(1.0 + dot(p, p)) * cdt;
708  z /= cdt;
709  integrator.push(z, p, dt);
710  z *= cdt;
711  t += dt;
712 
713  if (out) *out << std::setw(18) << z[2]
714  << std::setw(18) << Util::getKineticEnergy(p, mass)
715  << std::endl;
716  }
717 
718  const double beta = std::sqrt(1. - 1 / (dot(p, p) + 1.));
719  const double tErr = (z(2) - zend) / (Physics::c * beta);
720 
721  return std::pair<double, double>(p(2), t - tErr);
722 }
723 
724 bool RFCavity::isInside(const Vector_t& r) const {
725  if (isInsideTransverse(r)) {
726  return fieldmap_m->isInside(r);
727  }
728 
729  return false;
730 }
731 
733  double length = ElementBase::getElementLength();
734  if (length < 1e-10 && fieldmap_m != nullptr) {
735  double start, end;
736  fieldmap_m->getFieldDimensions(start, end);
737  length = end - start;
738  }
739 
740  return length;
741 }
742 
743 void RFCavity::getElementDimensions(double& begin, double& end) const {
744  fieldmap_m->getFieldDimensions(begin, end);
745 }
virtual double getCosAzimuth() const
Definition: RFCavity.cpp:316
std::unique_ptr< double[]> RNormal_m
Definition: RFCavity.h:236
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:45
double cosAngle_m
Definition: RFCavity.h:231
virtual double getRmax() const
Definition: RFCavity.cpp:299
virtual double getAutoPhaseEstimate(const double &E0, const double &t0, const double &q, const double &m)
Definition: RFCavity.cpp:545
virtual double getRmin() const
Definition: RFCavity.cpp:290
std::string getCavityTypeString() const
Definition: RFCavity.cpp:341
item[EANGLE] Entrance edge angle(radians).\item[ROTATION] Rotation of the magnet about its central axis(radians
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:322
and that you know you can do these things To protect your we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights These restrictions translate to certain responsibilities for you if you distribute copies of the or if you modify it For if you distribute copies of such a whether gratis or for a you must give the recipients all the rights that you have You must make sure that receive or can get the source code And you must show them these terms so they know their rights We protect your rights with two distribute and or modify the software for each author s protection and we want to make certain that everyone understands that there is no warranty for this free software If the software is modified by someone else and passed we want its recipients to know that what they have is not the so that any problems introduced by others will not reflect on the original authors reputations any free program is threatened constantly by software patents We wish to avoid the danger that redistributors of a free program will individually obtain patent in effect making the program proprietary To prevent we have made it clear that any patent must be licensed for everyone s free use or not licensed at all The precise terms and conditions for distribution and modification follow GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR DISTRIBUTION AND MODIFICATION This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License The refers to any such program or and a work based on the Program means either the Program or any derivative work under copyright a work containing the Program or a portion of it
Definition: LICENSE:43
virtual void freeMap()=0
constexpr double MVpm2Vpm
Definition: Units.h:128
virtual double getAzimuth() const
Definition: RFCavity.cpp:308
virtual double getAutoPhaseEstimateFallback(double E0, double t0, double q, double m)
Definition: RFCavity.cpp:503
constexpr double two_pi
The value of .
Definition: Physics.h:33
virtual bool bends() const override
Definition: RFCavity.cpp:250
double rmin_m
Definition: RFCavity.h:227
static const boost::bimap< CavityType, std::string > bmCavityTypeString_s
Definition: RFCavity.h:225
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
virtual void visitRFCavity(const RFCavity &)=0
Apply the algorithm to a RF cavity.
CavityType
Definition: RFCavity.h:31
double phaseError_m
Definition: RFCavity.h:209
ParticleAttrib< Vector_t > P
CavityType type_m
Definition: RFCavity.h:223
void setCavityType(const std::string &type)
Definition: RFCavity.cpp:332
static int myNode()
Definition: IpplInfo.cpp:691
int num_points_m
Definition: RFCavity.h:239
void setRmax(double rmax)
Definition: RFCavity.cpp:270
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6
virtual void goOnline(const double &kineticEnergy) override
Definition: RFCavity.cpp:254
double sinAngle_m
Definition: RFCavity.h:230
constexpr double Hz2MHz
Definition: Units.h:116
#define ERRORMSG(msg)
Definition: IpplInfo.h:350
void setPhaseModel(std::shared_ptr< AbstractTimeDependence > time_dep)
Definition: RFCavity.h:454
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:191
static std::string typeset_msg(const std::string &msg, const std::string &title)
Definition: Fieldmap.cpp:649
virtual double getPhi0() const
Definition: RFCavity.cpp:328
std::unique_ptr< double[]> VrNormal_m
Definition: RFCavity.h:237
void setAzimuth(double angle)
Definition: RFCavity.cpp:274
virtual ElementType getType() const override
Get element type std::string.
Definition: RFCavity.cpp:499
virtual const std::string & getName() const
Get element name.
int precision() const
Definition: Inform.h:112
clearpage the user may choose between constant or variable radius This model includes fringe fields begin
Definition: multipole_t.tex:6
virtual void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField) override
Definition: RFCavity.cpp:167
double getQ() const
Access to reference data.
constexpr double pi
The value of .
Definition: Physics.h:30
#define INFOMSG(msg)
Definition: IpplInfo.h:348
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
virtual double getGapWidth() const
Definition: RFCavity.cpp:324
PETE_TUTree< FnArcTan, typename T::PETE_Expr_t > atan(const PETE_Expr< T > &l)
Definition: PETE.h:727
virtual double getCycFrequency() const
Definition: RFCavity.cpp:359
double scale_m
Definition: RFCavity.h:206
virtual void getElementDimensions(double &begin, double &end) const override
Definition: RFCavity.cpp:743
static Inform * Info
Definition: IpplInfo.h:78
double scaleError_m
Definition: RFCavity.h:207
RFCavity()
Definition: RFCavity.cpp:45
virtual bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) override
Definition: RFCavity.cpp:123
void setAmplitudeModel(std::shared_ptr< AbstractTimeDependence > time_dep)
Definition: RFCavity.h:439
virtual double getPhasem() const
Definition: RFCavity.h:394
virtual void readMap()=0
bool getFlagDeleteOnTransverseExit() const
Definition: ElementBase.h:614
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:373
constexpr double deg2rad
Definition: Units.h:143
bool online_m
Definition: Component.h:192
std::string frequencyName_m
Definition: RFCavity.h:202
double angle_m
Definition: RFCavity.h:229
virtual void accept(BeamlineVisitor &) const override
Apply visitor to RFCavity.
Definition: RFCavity.cpp:119
virtual std::pair< double, double > trackOnAxisParticle(const double &p0, const double &t0, const double &dt, const double &q, const double &mass, std::ofstream *out=nullptr)
Definition: RFCavity.cpp:675
double phase_m
Definition: RFCavity.h:208
void setGapWidth(double gapwidth)
Definition: RFCavity.cpp:282
Definition: Inform.h:42
ElementType
Definition: ElementBase.h:88
double frequency_m
Definition: RFCavity.h:210
double pdis_m
Definition: RFCavity.h:232
std::unique_ptr< double[]> DvDr_m
Definition: RFCavity.h:238
void setRmin(double rmin)
Definition: RFCavity.cpp:266
double getKineticEnergy(Vector_t p, double mass)
Definition: Util.h:56
virtual double getElementLength() const
Get design length.
Definition: ElementBase.h:415
double startField_m
Definition: RFCavity.h:218
virtual void goOffline() override
Definition: RFCavity.cpp:260
constexpr double rad2deg
Definition: Units.h:146
virtual bool applyToReferenceParticle(const Vector_t &R, const Vector_t &P, const double &t, Vector_t &E, Vector_t &B) override
Definition: RFCavity.cpp:147
virtual void finalise() override
Definition: RFCavity.cpp:247
double getGamma(Vector_t p)
Definition: Util.h:46
void setPerpenDistance(double pdis)
Definition: RFCavity.cpp:278
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
void setFrequencyModel(std::shared_ptr< AbstractTimeDependence > time_dep)
Definition: RFCavity.h:469
bool isInsideTransverse(const Vector_t &r) const
PETE_TBTree< FnFmod, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > fmod(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
double endField_m
Definition: RFCavity.h:221
const std::string name
Fieldmap fieldmap_m
Definition: RFCavity.h:217
ParticlePos_t & R
virtual double getElementLength() const override
Get design length.
Definition: RFCavity.cpp:732
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:310
virtual double getPerpenDistance() const
Definition: RFCavity.cpp:320
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:270
virtual void setElementLength(double length)
Set design length.
Definition: ElementBase.h:419
double phi0_m
Definition: RFCavity.h:234
virtual std::string getFieldMapFN() const
Definition: RFCavity.cpp:345
T isnan(T x)
isnan function with adjusted return type
Definition: matheval.hpp:67
constexpr double e
The value of .
Definition: Physics.h:39
Inform & level2(Inform &inf)
Definition: Inform.cpp:46
const PartData * getReference() const
void setPhi0(double phi0)
Definition: RFCavity.cpp:286
double spline(double z, double *za)
Definition: RFCavity.cpp:433
virtual void getDimensions(double &zBegin, double &zEnd) const override
Definition: RFCavity.cpp:493
Interface for a single beam element.
Definition: Component.h:50
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
Definition: TpsMath.h:76
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
std::shared_ptr< AbstractTimeDependence > frequencyTD_m
Definition: RFCavity.h:201
virtual bool isInside(const Vector_t &r) const override
Definition: RFCavity.cpp:724
PETE_TUTree< FnFloor, typename T::PETE_Expr_t > floor(const PETE_Expr< T > &l)
Definition: PETE.h:733
virtual ~RFCavity()
Definition: RFCavity.cpp:116
double getdT(const int &i, const std::vector< double > &E, const double &dz, const double mass) const
Definition: RFCavity.h:282
virtual double getSinAzimuth() const
Definition: RFCavity.cpp:312
static Fieldmap getFieldmap(std::string Filename, bool fast=false)
Definition: Fieldmap.cpp:48
Inform * gmsg
Definition: Main.cpp:70
double rmax_m
Definition: RFCavity.h:228
end
Definition: multipole_t.tex:9
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition: Vector3D.cpp:118
double getBetaGamma(double Ekin, double mass)
Definition: Util.h:61
double gapwidth_m
Definition: RFCavity.h:233
constexpr double eV2MeV
Definition: Units.h:77
std::string filename_m
Definition: RFCavity.h:204
bool fast_m
Definition: RFCavity.h:212
virtual void setPhasem(double phase)
Definition: RFCavity.h:389