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