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