OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
TravelingWave.cpp
Go to the documentation of this file.
1//
2// Class TravelingWave
3// Defines the abstract interface for Traveling Wave.
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"
24
25#include "gsl/gsl_interp.h"
26#include "gsl/gsl_spline.h"
27
28#include <iostream>
29#include <fstream>
30
31extern Inform *gmsg;
32
35{}
36
37
39 RFCavity(right),
40 scaleCore_m(right.scaleCore_m),
41 scaleCoreError_m(right.scaleCoreError_m),
42 phaseCore1_m(right.phaseCore1_m),
43 phaseCore2_m(right.phaseCore2_m),
44 phaseExit_m(right.phaseExit_m),
45 startCoreField_m(right.startCoreField_m),
46 startExitField_m(right.startExitField_m),
47 mappedStartExitField_m(right.mappedStartExitField_m),
48 periodLength_m(right.periodLength_m),
49 numCells_m(right.numCells_m),
50 cellLength_m(right.cellLength_m),
51 mode_m(right.mode_m)
52{}
53
54
57 scaleCore_m(1.0),
58 scaleCoreError_m(0.0),
59 phaseCore1_m(0.0),
60 phaseCore2_m(0.0),
61 phaseExit_m(0.0),
62 startCoreField_m(0.0),
63 startExitField_m(0.0),
64 mappedStartExitField_m(0.0),
65 periodLength_m(0.0),
66 numCells_m(1),
67 cellLength_m(0.0),
68 mode_m(1)
69{}
70
71
73}
74
75
77 visitor.visitTravelingWave(*this);
78}
79
80bool TravelingWave::apply(const size_t& i, const double& t, Vector_t& E, Vector_t& B) {
81 return apply(RefPartBunch_m->R[i], RefPartBunch_m->P[i], t, E, B);
82}
83
85 const Vector_t& /*P*/,
86 const double& t,
87 Vector_t& E, Vector_t& B) {
88
89 if (R(2) < -0.5 * periodLength_m || R(2) + 0.5 * periodLength_m >= getElementLength()) return false;
90
91 Vector_t tmpR = Vector_t(R(0), R(1), R(2) + 0.5 * periodLength_m);
92 double tmpcos, tmpsin;
93 Vector_t tmpE(0.0, 0.0, 0.0), tmpB(0.0, 0.0, 0.0);
94
95 if (tmpR(2) < startCoreField_m) {
97
100
101 } else if (tmpR(2) < startExitField_m) {
102 Vector_t tmpE2(0.0, 0.0, 0.0), tmpB2(0.0, 0.0, 0.0);
103 tmpR(2) -= startCoreField_m;
104 const double z = tmpR(2);
105 tmpR(2) = tmpR(2) - periodLength_m * std::floor(tmpR(2) / periodLength_m);
106 tmpR(2) += startCoreField_m;
108
111 fieldmap_m->getFieldstrength(tmpR, tmpE, tmpB);
112 E += tmpcos * tmpE;
113 B += tmpsin * tmpB;
114
115 tmpE = 0.0;
116 tmpB = 0.0;
117
118 tmpR(2) = z + cellLength_m;
119 tmpR(2) = tmpR(2) - periodLength_m * std::floor(tmpR(2) / periodLength_m);
120 tmpR(2) += startCoreField_m;
121
124
125 } else {
126 tmpR(2) -= mappedStartExitField_m;
130 }
131
132 fieldmap_m->getFieldstrength(tmpR, tmpE, tmpB);
133
134 E += tmpcos * tmpE;
135 B += tmpsin * tmpB;
136
137 return false;
138}
139
141 const Vector_t& /*P*/,
142 const double& t, Vector_t& E,
143 Vector_t& B) {
144
145 if (R(2) < -0.5 * periodLength_m || R(2) + 0.5 * periodLength_m >= getElementLength()) return false;
146
147 Vector_t tmpR = Vector_t(R(0), R(1), R(2) + 0.5 * periodLength_m);
148 double tmpcos, tmpsin;
149 Vector_t tmpE(0.0, 0.0, 0.0), tmpB(0.0, 0.0, 0.0);
150
151 if (tmpR(2) < startCoreField_m) {
152 if (!fieldmap_m->isInside(tmpR)) return true;
153 tmpcos = scale_m * std::cos(frequency_m * t + phase_m);
154 tmpsin = -scale_m * std::sin(frequency_m * t + phase_m);
155
156 } else if (tmpR(2) < startExitField_m) {
157 Vector_t tmpE2(0.0, 0.0, 0.0), tmpB2(0.0, 0.0, 0.0);
158 tmpR(2) -= startCoreField_m;
159 const double z = tmpR(2);
160 tmpR(2) = tmpR(2) - periodLength_m * std::floor(tmpR(2) / periodLength_m);
161 tmpR(2) += startCoreField_m;
162 if (!fieldmap_m->isInside(tmpR)) return true;
163
165 tmpsin = -scaleCore_m * std::sin(frequency_m * t + phaseCore1_m);
166 fieldmap_m->getFieldstrength(tmpR, tmpE, tmpB);
167 E += tmpcos * tmpE;
168 B += tmpsin * tmpB;
169
170 tmpE = 0.0;
171 tmpB = 0.0;
172
173 tmpR(2) = z + cellLength_m;
174 tmpR(2) = tmpR(2) - periodLength_m * std::floor(tmpR(2) / periodLength_m);
175 tmpR(2) += startCoreField_m;
176
178 tmpsin = -scaleCore_m * std::sin(frequency_m * t + phaseCore2_m);
179
180 } else {
181 tmpR(2) -= mappedStartExitField_m;
182 if (!fieldmap_m->isInside(tmpR)) return true;
183
184 tmpcos = scale_m * std::cos(frequency_m * t + phaseExit_m);
185 tmpsin = -scale_m * std::sin(frequency_m * t + phaseExit_m);
186 }
187
188 fieldmap_m->getFieldstrength(tmpR, tmpE, tmpB);
189 E += tmpcos * tmpE;
190 B += tmpsin * tmpB;
191
192 return false;
193}
194
195void TravelingWave::initialise(PartBunchBase<double, 3>* bunch, double& startField, double& endField) {
196
197 if (bunch == nullptr) {
198 startField = - 0.5 * periodLength_m;
199 endField = startExitField_m;
200 return;
201 }
202
203 Inform msg("TravelingWave ", *gmsg);
204
205 RefPartBunch_m = bunch;
206 double zBegin = 0.0, zEnd = 0.0;
207 RFCavity::initialise(bunch, zBegin, zEnd);
208 if (std::abs(startField_m) > 0.0) {
209 throw GeneralClassicException("TravelingWave::initialise",
210 "The field map of a traveling wave structure has to begin at 0.0");
211 }
212
213 periodLength_m = (zEnd - zBegin) / 2.0;
216
220
221 startField = -periodLength_m / 2.0;
222 endField = startField + startExitField_m + periodLength_m / 2.0;
223 setElementLength(endField - startField);
224
230}
231
233{}
234
236 return false;
237}
238
239void TravelingWave::goOnline(const double&) {
241 online_m = true;
242}
243
246}
247
248void TravelingWave::getDimensions(double& zBegin, double& zEnd) const {
249 zBegin = -0.5 * periodLength_m;
250 zEnd = zBegin + getElementLength();
251}
252
253
254void TravelingWave::getElementDimensions(double& begin, double& end) const {
255 begin = -0.5 * periodLength_m;
257}
258
261}
262
264 const double& t0,
265 const double& q,
266 const double& mass) {
267 std::vector<double> t, E, t2, E2;
268 std::vector<std::pair<double, double> > F;
269 double phi = 0.0, tmp_phi, dphi = 0.5 * Units::deg2rad;
270 double phaseC1 = phaseCore1_m - phase_m;
271 double phaseC2 = phaseCore2_m - phase_m;
272 double phaseE = phaseExit_m - phase_m;
273
275 if (F.size() == 0) return 0.0;
276
277 int N1 = static_cast<int>(std::floor(F.size() / 4.)) + 1;
278 int N2 = F.size() - 2 * N1 + 1;
279 int N3 = 2 * N1 + static_cast<int>(std::floor((numCells_m - 1) * N2 * mode_m)) - 1;
280 int N4 = static_cast<int>(std::round(N2 * mode_m));
281 double Dz = F[N1 + N2].first - F[N1].first;
282
283 t.resize(N3, t0);
284 t2.resize(N3, t0);
285 E.resize(N3, E0);
286 E2.resize(N3, E0);
287 for (int i = 1; i < N1; ++ i) {
288 E[i] = E0 + (F[i].first + F[i - 1].first) / 2. * scale_m / mass;
289 E2[i] = E[i];
290 }
291 for (int i = N1; i < N3 - N1 + 1; ++ i) {
292 int I = (i - N1) % N2 + N1;
293 double Z = (F[I].first + F[I - 1].first) / 2. + std::floor((i - N1) / N2) * Dz;
294 E[i] = E0 + Z * scaleCore_m / mass;
295 E2[i] = E[i];
296 }
297 for (int i = N3 - N1 + 1; i < N3; ++ i) {
298 int I = i - N3 - 1 + 2 * N1 + N2;
299 double Z = (F[I].first + F[I - 1].first) / 2. + ((numCells_m - 1) * mode_m - 1) * Dz;
300 E[i] = E0 + Z * scale_m / mass;
301 E2[i] = E[i];
302 }
303
304 for (int iter = 0; iter < 10; ++ iter) {
305 double A = 0.0;
306 double B = 0.0;
307 for (int i = 1; i < N1; ++ i) {
308 t[i] = t[i - 1] + getdT(i, i, E, F, mass);
309 t2[i] = t2[i - 1] + getdT(i, i, E2, F, mass);
310 A += scale_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * getdA(i, i, t, 0.0, F);
311 B += scale_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * getdB(i, i, t, 0.0, F);
312 }
313 for (int i = N1; i < N3 - N1 + 1; ++ i) {
314 int I = (i - N1) % N2 + N1;
315 int J = (i - N1 + N4) % N2 + N1;
316 t[i] = t[i - 1] + getdT(i, I, E, F, mass);
317 t2[i] = t2[i - 1] + getdT(i, I, E2, F, mass);
318 A += scaleCore_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * (getdA(i, I, t, phaseC1, F) + getdA(i, J, t, phaseC2, F));
319 B += scaleCore_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * (getdB(i, I, t, phaseC1, F) + getdB(i, J, t, phaseC2, F));
320 }
321 for (int i = N3 - N1 + 1; i < N3; ++ i) {
322 int I = i - N3 - 1 + 2 * N1 + N2;
323 t[i] = t[i - 1] + getdT(i, I, E, F, mass);
324 t2[i] = t2[i - 1] + getdT(i, I, E2, F, mass);
325 A += scale_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * getdA(i, I, t, phaseE, F);
326 B += scale_m * (1. + frequency_m * (t2[i] - t[i]) / dphi) * getdB(i, I, t, phaseE, F);
327 }
328
329 if (std::abs(B) > 0.0000001) {
330 tmp_phi = std::atan(A / B);
331 } else {
332 tmp_phi = Physics::pi / 2;
333 }
334 if (q * (A * std::sin(tmp_phi) + B * std::cos(tmp_phi)) < 0) {
335 tmp_phi += Physics::pi;
336 }
337
338 if (std::abs(phi - tmp_phi) < frequency_m * (t[N3 - 1] - t[0]) / N3) {
339 for (int i = 1; i < N1; ++ i) {
340 E[i] = E[i - 1] + q * scale_m * getdE(i, i, t, phi, F);
341 }
342 for (int i = N1; i < N3 - N1 + 1; ++ i) {
343 int I = (i - N1) % N2 + N1;
344 int J = (i - N1 + N4) % N2 + N1;
345 E[i] = E[i - 1] + q * scaleCore_m * (getdE(i, I, t, phi + phaseC1, F) + getdE(i, J, t, phi + phaseC2, F));
346 }
347 for (int i = N3 - N1 + 1; i < N3; ++ i) {
348 int I = i - N3 - 1 + 2 * N1 + N2;
349 E[i] = E[i - 1] + q * scale_m * getdE(i, I, t, phi + phaseE, F);
350 }
351
352 const int prevPrecision = Ippl::Info->precision(8);
353 INFOMSG(level2 << "estimated phase= " << tmp_phi << " rad = "
354 << tmp_phi * Units::rad2deg << " deg,\n"
355 << "Ekin= " << E[N3 - 1] << " MeV" << std::setprecision(prevPrecision) << "\n" << endl);
356 return tmp_phi;
357 }
358 phi = tmp_phi - std::round(tmp_phi / Physics::two_pi) * Physics::two_pi;
359
360
361 for (int i = 1; i < N1; ++ i) {
362 E[i] = E[i - 1] + q * scale_m * getdE(i, i, t, phi, F);
363 E2[i] = E2[i - 1] + q * scale_m * getdE(i, i, t, phi + dphi, F); // should I use here t or t2?
364 t[i] = t[i - 1] + getdT(i, i, E, F, mass);
365 t2[i] = t2[i - 1] + getdT(i, i, E2, F, mass);
366 E[i] = E[i - 1] + q * scale_m * getdE(i, i, t, phi, F);
367 E2[i] = E2[i - 1] + q * scale_m * getdE(i, i, t2, phi + dphi, F);
368 }
369 for (int i = N1; i < N3 - N1 + 1; ++ i) {
370 int I = (i - N1) % N2 + N1;
371 int J = (i - N1 + N4) % N2 + N1;
372 E[i] = E[i - 1] + q * scaleCore_m * (getdE(i, I, t, phi + phaseC1, F) + getdE(i, J, t, phi + phaseC2, F));
373 E2[i] = E2[i - 1] + q * scaleCore_m * (getdE(i, I, t, phi + phaseC1 + dphi, F) + getdE(i, J, t, phi + phaseC2 + dphi, F)); //concerning t: see above
374 t[i] = t[i - 1] + getdT(i, I, E, F, mass);
375 t2[i] = t2[i - 1] + getdT(i, I, E2, F, mass);
376 E[i] = E[i - 1] + q * scaleCore_m * (getdE(i, I, t, phi + phaseC1, F) + getdE(i, J, t, phi + phaseC2, F));
377 E2[i] = E2[i - 1] + q * scaleCore_m * (getdE(i, I, t2, phi + phaseC1 + dphi, F) + getdE(i, J, t2, phi + phaseC2 + dphi, F));
378 }
379 for (int i = N3 - N1 + 1; i < N3; ++ i) {
380 int I = i - N3 - 1 + 2 * N1 + N2;
381 E[i] = E[i - 1] + q * scale_m * getdE(i, I, t, phi + phaseE, F);
382 E2[i] = E2[i - 1] + q * scale_m * getdE(i, I, t, phi + phaseE + dphi, F); //concerning t: see above
383 t[i] = t[i - 1] + getdT(i, I, E, F, mass);
384 t2[i] = t2[i - 1] + getdT(i, I, E2, F, mass);
385 E[i] = E[i - 1] + q * scale_m * getdE(i, I, t, phi + phaseE, F);
386 E2[i] = E2[i - 1] + q * scale_m * getdE(i, I, t2, phi + phaseE + dphi, F);
387 }
388 // msg << ", Ekin= " << E[N3-1] << " MeV" << endl;
389 }
390
391
392 const int prevPrecision = Ippl::Info->precision(8);
393 INFOMSG(level2 << "estimated phase= " << tmp_phi << " rad = "
394 << tmp_phi * Units::rad2deg << " deg,\n"
395 << "Ekin= " << E[N3 - 1] << " MeV" << std::setprecision(prevPrecision) << "\n" << endl);
396
397 return phi;
398}
399
400bool TravelingWave::isInside(const Vector_t& r) const {
401 return (isInsideTransverse(r)
402 && r(2) >= -0.5 * periodLength_m
403 && r(2) < startExitField_m);
404}
Inform * gmsg
Definition: Main.cpp:61
ElementType
Definition: ElementBase.h:88
PartBunchBase< T, Dim >::ConstIterator end(PartBunchBase< T, Dim > const &bunch)
PartBunchBase< T, Dim >::ConstIterator begin(PartBunchBase< T, Dim > const &bunch)
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
PETE_TUTree< FnArcTan, typename T::PETE_Expr_t > atan(const PETE_Expr< T > &l)
Definition: PETE.h:727
PETE_TUTree< FnFloor, typename T::PETE_Expr_t > floor(const PETE_Expr< T > &l)
Definition: PETE.h:733
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
Inform & level2(Inform &inf)
Definition: Inform.cpp:46
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
#define INFOMSG(msg)
Definition: IpplInfo.h:348
const std::string name
constexpr double two_pi
The value of.
Definition: Physics.h:33
constexpr double pi
The value of.
Definition: Physics.h:30
constexpr double rad2deg
Definition: Units.h:146
constexpr double deg2rad
Definition: Units.h:143
ParticlePos_t & R
ParticleAttrib< Vector_t > P
virtual void visitTravelingWave(const TravelingWave &)=0
Apply the algorithm to a traveling wave.
bool online_m
Definition: Component.h:192
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:191
bool getFlagDeleteOnTransverseExit() const
Definition: ElementBase.h:613
virtual void setElementLength(double length)
Set design length.
Definition: ElementBase.h:418
bool isInsideTransverse(const Vector_t &r) const
Fieldmap * fieldmap_m
Definition: RFCavity.h:218
std::string filename_m
Definition: RFCavity.h:205
double scale_m
Definition: RFCavity.h:207
double phaseError_m
Definition: RFCavity.h:210
virtual void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField) override
Definition: RFCavity.cpp:167
double frequency_m
Definition: RFCavity.h:211
double startField_m
Definition: RFCavity.h:219
double scaleError_m
Definition: RFCavity.h:208
virtual double getElementLength() const override
Get design length.
Definition: RFCavity.cpp:723
double phase_m
Definition: RFCavity.h:209
double periodLength_m
Definition: TravelingWave.h:99
double mappedStartExitField_m
Definition: TravelingWave.h:97
double getdA(const int &i, const int &I, const std::vector< double > &t, const double &phi, const std::vector< std::pair< double, double > > &F) const
virtual ElementType getType() const override
Get element type std::string.
double phaseCore2_m
Definition: TravelingWave.h:92
virtual bool bends() const override
virtual void accept(BeamlineVisitor &) const override
Apply visitor to TravelingWave.
virtual void getDimensions(double &zBegin, double &zEnd) const override
double phaseExit_m
Definition: TravelingWave.h:93
double getdB(const int &i, const int &I, const std::vector< double > &t, const double &phi, const std::vector< std::pair< double, double > > &F) const
virtual double getAutoPhaseEstimate(const double &E0, const double &t0, const double &q, const double &m) override
double startExitField_m
Definition: TravelingWave.h:96
virtual bool isInside(const Vector_t &r) const override
virtual void goOffline() override
double getdE(const int &i, const int &I, const std::vector< double > &t, const double &phi, const std::vector< std::pair< double, double > > &F) const
double cellLength_m
double scaleCore_m
Definition: TravelingWave.h:88
virtual bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) override
virtual void finalise() override
double scaleCoreError_m
Definition: TravelingWave.h:89
virtual ~TravelingWave()
virtual void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField) override
virtual void getElementDimensions(double &begin, double &end) const override
virtual bool applyToReferenceParticle(const Vector_t &R, const Vector_t &P, const double &t, Vector_t &E, Vector_t &B) override
double getdT(const int &i, const int &I, const std::vector< double > &E, const std::vector< std::pair< double, double > > &F, const double mass) const
double phaseCore1_m
Definition: TravelingWave.h:91
double startCoreField_m
Definition: TravelingWave.h:95
virtual void goOnline(const double &kineticEnergy) override
virtual bool isInside(const Vector_t &) const
Definition: Fieldmap.h:101
virtual void freeMap()=0
virtual void getOnaxisEz(std::vector< std::pair< double, double > > &onaxis)
Definition: Fieldmap.cpp:709
virtual bool getFieldstrength(const Vector_t &R, Vector_t &E, Vector_t &B) const =0
virtual void readMap()=0
Definition: Inform.h:42
int precision() const
Definition: Inform.h:112
static Inform * Info
Definition: IpplInfo.h:78
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6