OPAL (Object Oriented Parallel Accelerator Library) 2024.2
OPAL
FM1DDynamic_fast.cpp
Go to the documentation of this file.
2#include "Fields/Fieldmap.hpp"
3#include "Physics/Physics.h"
4#include "Physics/Units.h"
6#include "Utilities/Util.h"
7
8#include "gsl/gsl_fft_real.h"
9
10#include <fstream>
11#include <ios>
12
13_FM1DDynamic_fast::_FM1DDynamic_fast(const std::string& filename):
14 _Fieldmap(filename),
15 accuracy_m(0)
16{
17
19 onAxisField_m = nullptr;
20
21 std::ifstream fieldFile(Filename_m.c_str());
22 if (fieldFile.good()) {
23
24 bool parsingPassed = readFileHeader(fieldFile);
25 parsingPassed = checkFileData(fieldFile, parsingPassed);
26 fieldFile.close();
27
28 if (!parsingPassed) {
30 zEnd_m = zBegin_m - 1.0e-3;
31 } else
33
36
37 } else {
39 zBegin_m = 0.0;
40 zEnd_m = -1.0e-3;
41 }
42}
43
47
48FM1DDynamic_fast _FM1DDynamic_fast::create(const std::string& filename) {
49 return FM1DDynamic_fast(new _FM1DDynamic_fast(filename));
50}
51
53
54 if (onAxisField_m == nullptr) {
55
56 std::ifstream fieldFile(Filename_m.c_str());
57 stripFileHeader(fieldFile);
58
60 double maxEz = readFileData(fieldFile, onAxisField_m);
61 fieldFile.close();
62
63 std::vector<double> fourierCoefs = computeFourierCoefficients(onAxisField_m);
64 normalizeField(maxEz, fourierCoefs);
65
66 double *onAxisFieldP = new double[numberOfGridPoints_m];
67 double *onAxisFieldPP = new double[numberOfGridPoints_m];
68 double *onAxisFieldPPP = new double[numberOfGridPoints_m];
69 computeFieldDerivatives(fourierCoefs, onAxisFieldP,
70 onAxisFieldPP, onAxisFieldPPP);
71 computeInterpolationVectors(onAxisFieldP, onAxisFieldPP,
72 onAxisFieldPPP);
73
74 prepareForMapCheck(fourierCoefs);
75
76 delete [] onAxisFieldP;
77 delete [] onAxisFieldPP;
78 delete [] onAxisFieldPPP;
79
80 INFOMSG(typeset_msg("Read in fieldmap '" + Filename_m + "'", "info")
81 << endl);
82 }
83}
84
86 if (onAxisField_m != nullptr) {
87 delete [] onAxisField_m;
88 onAxisField_m = nullptr;
89
90 gsl_spline_free(onAxisFieldInterpolants_m);
91 gsl_spline_free(onAxisFieldPInterpolants_m);
92 gsl_spline_free(onAxisFieldPPInterpolants_m);
93 gsl_spline_free(onAxisFieldPPPInterpolants_m);
94 gsl_interp_accel_free(onAxisFieldAccel_m);
95 gsl_interp_accel_free(onAxisFieldPAccel_m);
96 gsl_interp_accel_free(onAxisFieldPPAccel_m);
97 gsl_interp_accel_free(onAxisFieldPPPAccel_m);
98 }
99}
100
102 Vector_t &B) const {
103
104 std::vector<double> fieldComponents;
105 computeFieldOnAxis(R(2) - zBegin_m, fieldComponents);
106 computeFieldOffAxis(R, E, B, fieldComponents);
107
108 return false;
109}
110
112 Vector_t &E,
113 Vector_t &/*B*/,
114 const DiffDirection &/*dir*/) const {
115
116 E(2) += gsl_spline_eval(onAxisFieldPInterpolants_m, R(2) - zBegin_m,
118
119 return false;
120}
121
122void _FM1DDynamic_fast::getFieldDimensions(double &zBegin, double &zEnd) const {
123 zBegin = zBegin_m;
124 zEnd = zEnd_m;
125}
126
127void _FM1DDynamic_fast::getFieldDimensions(double &/*xIni*/, double &/*xFinal*/,
128 double &/*yIni*/, double &/*yFinal*/,
129 double &/*zIni*/, double &/*zFinal*/) const {}
130
133
135 (*msg) << Filename_m
136 << " (1D dynamic); zini= "
137 << zBegin_m << " m; zfinal= "
138 << zEnd_m << " m;" << endl;
139}
140
142 return frequency_m;
143}
144
146 frequency_m = freq;
147}
148
149void _FM1DDynamic_fast::getOnaxisEz(std::vector<std::pair<double, double>> &eZ) {
150
151 eZ.resize(numberOfGridPoints_m);
152 std::ifstream fieldFile(Filename_m.c_str());
153 stripFileHeader(fieldFile);
154 double maxEz = readFileData(fieldFile, eZ);
155 fieldFile.close();
156 scaleField(maxEz, eZ);
157
158}
159
160bool _FM1DDynamic_fast::checkFileData(std::ifstream &fieldFile,
161 bool parsingPassed) {
162
163 double tempDouble;
164 for (unsigned int dataIndex = 0; dataIndex < numberOfGridPoints_m; ++ dataIndex)
165 parsingPassed = parsingPassed
166 && interpretLine<double>(fieldFile, tempDouble);
167
168 return parsingPassed && interpreteEOF(fieldFile);
169
170}
171
172void _FM1DDynamic_fast::computeFieldDerivatives(std::vector<double> fourierCoefs,
173 double onAxisFieldP[],
174 double onAxisFieldPP[],
175 double onAxisFieldPPP[]) {
176
177 for (unsigned int zStepIndex = 0; zStepIndex < numberOfGridPoints_m; ++ zStepIndex) {
178
179 double z = deltaZ_m * zStepIndex;
180 double kz = Physics::two_pi * z / length_m + Physics::pi;
181 onAxisFieldP[zStepIndex] = 0.0;
182 onAxisFieldPP[zStepIndex] = 0.0;
183 onAxisFieldPPP[zStepIndex] = 0.0;
184
185 int coefIndex = 1;
186 for (unsigned int n = 1; n < accuracy_m; ++ n) {
187
188 double kn = n * Physics::two_pi / length_m;
189 double coskzn = cos(kz * n);
190 double sinkzn = sin(kz * n);
191
192 onAxisFieldP[zStepIndex] += kn * (-fourierCoefs.at(coefIndex) * sinkzn
193 - fourierCoefs.at(coefIndex + 1) * coskzn);
194
195 double derivCoeff = pow(kn, 2.0);
196 onAxisFieldPP[zStepIndex] += derivCoeff * (-fourierCoefs.at(coefIndex) * coskzn
197 + fourierCoefs.at(coefIndex + 1) * sinkzn);
198 derivCoeff *= kn;
199 onAxisFieldPPP[zStepIndex] += derivCoeff * (fourierCoefs.at(coefIndex) * sinkzn
200 + fourierCoefs.at(coefIndex + 1) * coskzn);
201
202 coefIndex += 2;
203 }
204 }
205
206}
207
209 Vector_t &E,
210 Vector_t &B,
211 std::vector<double> fieldComponents) const {
212
213 double radiusSq = pow(R(0), 2.0) + pow(R(1), 2.0);
214 double transverseEFactor = (fieldComponents.at(1)
215 * (0.5 - radiusSq * twoPiOverLambdaSq_m / 16.0)
216 - radiusSq * fieldComponents.at(3) / 16.0);
217 double transverseBFactor = ((fieldComponents.at(0)
218 * (0.5 - radiusSq * twoPiOverLambdaSq_m / 16.0)
219 - radiusSq * fieldComponents.at(2) / 16.0)
221
222 E(0) += - R(0) * transverseEFactor;
223 E(1) += - R(1) * transverseEFactor;
224 E(2) += (fieldComponents.at(0) * (1.0 - radiusSq * twoPiOverLambdaSq_m / 4.0)
225 - radiusSq * fieldComponents.at(2) / 4.0);
226
227 B(0) += - R(1) * transverseBFactor;
228 B(1) += R(0) * transverseBFactor;
229
230}
231
233 std::vector<double> &fieldComponents)
234 const {
235
236 fieldComponents.push_back(gsl_spline_eval(onAxisFieldInterpolants_m,
238 fieldComponents.push_back(gsl_spline_eval(onAxisFieldPInterpolants_m,
240 fieldComponents.push_back(gsl_spline_eval(onAxisFieldPPInterpolants_m,
242 fieldComponents.push_back(gsl_spline_eval(onAxisFieldPPPInterpolants_m,
244}
245
246std::vector<double> _FM1DDynamic_fast::computeFourierCoefficients(double fieldData[]) {
247 const unsigned int totalSize = 2 * numberOfGridPoints_m - 1;
248 gsl_fft_real_wavetable *waveTable = gsl_fft_real_wavetable_alloc(totalSize);
249 gsl_fft_real_workspace *workSpace = gsl_fft_real_workspace_alloc(totalSize);
250
251 // Reflect field about minimum z value to ensure that it is periodic.
252 double *fieldDataReflected = new double[totalSize];
253 for (unsigned int dataIndex = 0; dataIndex < numberOfGridPoints_m; ++ dataIndex) {
254 fieldDataReflected[numberOfGridPoints_m - 1 + dataIndex]
255 = fieldData[dataIndex];
256 if (dataIndex != 0)
257 fieldDataReflected[numberOfGridPoints_m - 1 - dataIndex]
258 = fieldData[dataIndex];
259 }
260
261 gsl_fft_real_transform(fieldDataReflected, 1,
262 totalSize,
263 waveTable, workSpace);
264
265 std::vector<double> fourierCoefs;
266 fourierCoefs.push_back(fieldDataReflected[0] / totalSize);
267 for (unsigned int coefIndex = 1; coefIndex < 2 * accuracy_m - 1; ++ coefIndex)
268 fourierCoefs.push_back(2.0 * fieldDataReflected[coefIndex] / totalSize);
269
270 delete [] fieldDataReflected;
271 gsl_fft_real_workspace_free(workSpace);
272 gsl_fft_real_wavetable_free(waveTable);
273
274 return fourierCoefs;
275
276}
277
279 double onAxisFieldPP[],
280 double onAxisFieldPPP[]) {
281
282 onAxisFieldInterpolants_m = gsl_spline_alloc(gsl_interp_cspline,
284 onAxisFieldPInterpolants_m = gsl_spline_alloc(gsl_interp_cspline,
286 onAxisFieldPPInterpolants_m = gsl_spline_alloc(gsl_interp_cspline,
288 onAxisFieldPPPInterpolants_m = gsl_spline_alloc(gsl_interp_cspline,
290
291 double *z = new double[numberOfGridPoints_m];
292 for (unsigned int zStepIndex = 0; zStepIndex < numberOfGridPoints_m; ++ zStepIndex)
293 z[zStepIndex] = deltaZ_m * zStepIndex;
294 gsl_spline_init(onAxisFieldInterpolants_m, z,
296 gsl_spline_init(onAxisFieldPInterpolants_m, z,
297 onAxisFieldP, numberOfGridPoints_m);
298 gsl_spline_init(onAxisFieldPPInterpolants_m, z,
299 onAxisFieldPP, numberOfGridPoints_m);
300 gsl_spline_init(onAxisFieldPPPInterpolants_m, z,
301 onAxisFieldPPP, numberOfGridPoints_m);
302
303 onAxisFieldAccel_m = gsl_interp_accel_alloc();
304 onAxisFieldPAccel_m = gsl_interp_accel_alloc();
305 onAxisFieldPPAccel_m = gsl_interp_accel_alloc();
306 onAxisFieldPPPAccel_m = gsl_interp_accel_alloc();
307
308 delete [] z;
309}
310
312
313 // Convert to angular frequency in Hz.
315
316 // Convert to m.
321
323}
324
326 std::vector<double> &fourierCoefs) {
327
328 for (unsigned int dataIndex = 0; dataIndex < numberOfGridPoints_m; ++ dataIndex)
329 onAxisField_m[dataIndex] /= (maxEz * Units::Vpm2MVpm);
330
331 for (std::vector<double>::iterator fourierIterator = fourierCoefs.begin();
332 fourierIterator < fourierCoefs.end(); ++ fourierIterator)
333 *fourierIterator/= (maxEz * Units::Vpm2MVpm);
334
335}
336
337double _FM1DDynamic_fast::readFileData(std::ifstream &fieldFile,
338 double fieldData[]) {
339
340 double maxEz = 0.0;
341 for (unsigned int dataIndex = 0; dataIndex < numberOfGridPoints_m; ++ dataIndex) {
342 interpretLine<double>(fieldFile, fieldData[dataIndex]);
343 if (std::abs(fieldData[dataIndex]) > maxEz)
344 maxEz = std::abs(fieldData[dataIndex]);
345 }
346
347 if (!normalize_m)
348 maxEz = 1.0;
349
350 return maxEz;
351}
352
353double _FM1DDynamic_fast::readFileData(std::ifstream &fieldFile,
354 std::vector<std::pair<double, double>> &eZ) {
355
356 double maxEz = 0.0;
357 double deltaZ = (zEnd_m - zBegin_m) / (numberOfGridPoints_m - 1);
358 for (unsigned int dataIndex = 0; dataIndex < numberOfGridPoints_m; ++ dataIndex) {
359 eZ.at(dataIndex).first = deltaZ * dataIndex;
360 interpretLine<double>(fieldFile, eZ.at(dataIndex).second);
361 if (std::abs(eZ.at(dataIndex).second) > maxEz)
362 maxEz = std::abs(eZ.at(dataIndex).second);
363 }
364
365 if (!normalize_m)
366 maxEz = 1.0;
367
368 return maxEz;
369}
370
371bool _FM1DDynamic_fast::readFileHeader(std::ifstream &fieldFile) {
372
373 std::string tempString;
374 int tempInt;
375
376 bool parsingPassed = true;
377 try {
378 parsingPassed = interpretLine<std::string, unsigned int>(fieldFile,
379 tempString,
380 accuracy_m);
381 } catch (GeneralClassicException &e) {
383 tempString,
385 tempString);
386
387 tempString = Util::toUpper(tempString);
388 if (tempString != "TRUE" &&
389 tempString != "FALSE")
390 throw GeneralClassicException("_FM1DDynamic_fast::readFileHeader",
391 "The third string on the first line of 1D field "
392 "maps has to be either TRUE or FALSE");
393
394 normalize_m = (tempString == "TRUE");
395 }
396 parsingPassed = parsingPassed &&
398 zBegin_m,
399 zEnd_m,
401 parsingPassed = parsingPassed &&
403 parsingPassed = parsingPassed &&
405 rBegin_m,
406 rEnd_m,
407 tempInt);
408
410
413
414 return parsingPassed;
415}
416
418 std::vector<std::pair<double, double>> &eZ) {
419 if (!normalize_m) return;
420
421 for (unsigned int dataIndex = 0; dataIndex < numberOfGridPoints_m; ++ dataIndex)
422 eZ.at(dataIndex).second /= maxEz;
423}
424
425void _FM1DDynamic_fast::stripFileHeader(std::ifstream &fieldFile) {
426
427 std::string tempString;
428
429 getLine(fieldFile, tempString);
430 getLine(fieldFile, tempString);
431 getLine(fieldFile, tempString);
432 getLine(fieldFile, tempString);
433}
434
435void _FM1DDynamic_fast::prepareForMapCheck(std::vector<double> &fourierCoefs) {
436 std::vector<double> zSampling(numberOfGridPoints_m);
437 for (unsigned int zStepIndex = 0; zStepIndex < numberOfGridPoints_m; ++ zStepIndex)
438 zSampling[zStepIndex] = deltaZ_m * zStepIndex;
439
441 length_m,
442 zSampling,
443 fourierCoefs,
446}
std::shared_ptr< _FM1DDynamic_fast > FM1DDynamic_fast
@ T1DDynamic
Definition Fieldmap.h:17
DiffDirection
Definition Fieldmap.h:55
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition TpsMath.h:129
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
Inform & endl(Inform &inf)
Definition Inform.cpp:42
#define INFOMSG(msg)
Definition IpplInfo.h:348
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 MHz2Hz
Definition Units.h:113
constexpr double cm2m
Definition Units.h:35
constexpr double Vpm2MVpm
Definition Units.h:125
std::string toUpper(const std::string &str)
Definition Util.cpp:147
bool interpreteEOF(std::ifstream &in)
Definition Fieldmap.cpp:555
bool normalize_m
Definition Fieldmap.h:121
static std::string typeset_msg(const std::string &msg, const std::string &title)
Definition Fieldmap.cpp:649
void disableFieldmapWarning()
Definition Fieldmap.cpp:610
void getLine(std::ifstream &in, std::string &buffer)
Definition Fieldmap.h:122
void noFieldmapWarning()
Definition Fieldmap.cpp:618
bool interpretLine(std::ifstream &in, S &value, const bool &file_length_known=true)
std::string Filename_m
Definition Fieldmap.h:118
void checkMap(unsigned int accuracy, std::pair< double, double > fieldDimensions, double deltaZ, const std::vector< double > &fourierCoefficients, gsl_spline *splineCoefficients, gsl_interp_accel *splineAccelerator)
Definition Fieldmap.cpp:448
MapType Type
Definition Fieldmap.h:116
virtual bool getFieldDerivative(const Vector_t &R, Vector_t &E, Vector_t &B, const DiffDirection &dir) const
friend class _Fieldmap
double length_m
Longitudinal end of field.
virtual void getOnaxisEz(std::vector< std::pair< double, double > > &eZ)
void scaleField(double maxEz, std::vector< std::pair< double, double > > &eZ)
double twoPiOverLambdaSq_m
Field angular frequency (Hz).
static FM1DDynamic_fast create(const std::string &filename)
void computeFieldOffAxis(const Vector_t &R, Vector_t &E, Vector_t &B, std::vector< double > fieldComponents) const
gsl_interp_accel * onAxisFieldAccel_m
On axis field third derivative interpolation structure.
double rEnd_m
Minimum radius of field.
void prepareForMapCheck(std::vector< double > &fourierCoefs)
virtual double getFrequency() const
_FM1DDynamic_fast(const std::string &filename)
void computeInterpolationVectors(double onAxisFieldP[], double onAxisFieldPP[], double onAxisFieldPPP[])
double deltaZ_m
Number of grid points in field input file.
double zEnd_m
Longitudinal start of field.
gsl_spline * onAxisFieldPInterpolants_m
On axis field interpolation structure.
std::vector< double > computeFourierCoefficients(double fieldData[])
unsigned int accuracy_m
Field grid point spacing.
virtual void getFieldDimensions(double &zBegin, double &zEnd) const
virtual void setFrequency(double freq)
gsl_spline * onAxisFieldPPInterpolants_m
On axis field first derivative interpolation structure.
bool checkFileData(std::ifstream &fieldFile, bool parsingPassed)
virtual bool getFieldstrength(const Vector_t &R, Vector_t &E, Vector_t &B) const
gsl_interp_accel * onAxisFieldPAccel_m
bool readFileHeader(std::ifstream &fieldFile)
gsl_spline * onAxisFieldPPPInterpolants_m
On axis field second derivative interpolation structure.
void computeFieldOnAxis(double z, std::vector< double > &fieldComponents) const
double rBegin_m
2 Pi divided by the field RF wavelength squared.
gsl_interp_accel * onAxisFieldPPAccel_m
virtual void readMap()
void normalizeField(double maxEz, std::vector< double > &fourierCoefs)
gsl_interp_accel * onAxisFieldPPPAccel_m
virtual void getInfo(Inform *)
gsl_spline * onAxisFieldInterpolants_m
On axis field data.
double zBegin_m
Maximum radius of field.
virtual void freeMap()
double readFileData(std::ifstream &fieldFile, double fieldData[])
unsigned int numberOfGridPoints_m
Field length.
void computeFieldDerivatives(std::vector< double > fourierCoefs, double onAxisFieldP[], double onAxisFieldPP[], double onAxisFieldPPP[])
void stripFileHeader(std::ifstream &fieldFile)
Vektor< double, 3 > Vector_t