OPAL (Object Oriented Parallel Accelerator Library)  2024.1
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 
18  Type = T1DDynamic;
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 
45  freeMap();
46 }
47 
48 FM1DDynamic_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 
59  onAxisField_m = new double[numberOfGridPoints_m];
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 
122 void _FM1DDynamic_fast::getFieldDimensions(double &zBegin, double &zEnd) const {
123  zBegin = zBegin_m;
124  zEnd = zEnd_m;
125 }
126 
127 void _FM1DDynamic_fast::getFieldDimensions(double &/*xIni*/, double &/*xFinal*/,
128  double &/*yIni*/, double &/*yFinal*/,
129  double &/*zIni*/, double &/*zFinal*/) const {}
130 
132 { }
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 
149 void _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 
160 bool _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 
172 void _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,
237  z, onAxisFieldAccel_m));
238  fieldComponents.push_back(gsl_spline_eval(onAxisFieldPInterpolants_m,
239  z, onAxisFieldPAccel_m));
240  fieldComponents.push_back(gsl_spline_eval(onAxisFieldPPInterpolants_m,
242  fieldComponents.push_back(gsl_spline_eval(onAxisFieldPPPInterpolants_m,
244 }
245 
246 std::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,
295  onAxisField_m, numberOfGridPoints_m);
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.
318  rEnd_m *= Units::cm2m;
320  zEnd_m *= Units::cm2m;
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 
337 double _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 
353 double _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 
371 bool _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) {
382  parsingPassed = interpretLine<std::string, unsigned int, std::string>(fieldFile,
383  tempString,
384  accuracy_m,
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 &&
397  interpretLine<double, double, unsigned int>(fieldFile,
398  zBegin_m,
399  zEnd_m,
401  parsingPassed = parsingPassed &&
402  interpretLine<double>(fieldFile, frequency_m);
403  parsingPassed = parsingPassed &&
404  interpretLine<double, double, int>(fieldFile,
405  rBegin_m,
406  rEnd_m,
407  tempInt);
408 
410 
411  if (accuracy_m > numberOfGridPoints_m)
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 
425 void _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 
435 void _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 }
virtual double getFrequency() const
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:45
virtual void setFrequency(double freq)
gsl_interp_accel * onAxisFieldPAccel_m
MapType Type
Definition: Fieldmap.h:115
virtual bool getFieldstrength(const Vector_t &R, Vector_t &E, Vector_t &B) const
DiffDirection
Definition: Fieldmap.h:55
constexpr double two_pi
The value of .
Definition: Physics.h:33
void noFieldmapWarning()
Definition: Fieldmap.cpp:618
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
gsl_spline * onAxisFieldPPInterpolants_m
On axis field first derivative interpolation structure.
double deltaZ_m
Number of grid points in field input file.
static FM1DDynamic_fast create(const std::string &filename)
constexpr double cm2m
Definition: Units.h:35
gsl_spline * onAxisFieldPPPInterpolants_m
On axis field second derivative interpolation structure.
static std::string typeset_msg(const std::string &msg, const std::string &title)
Definition: Fieldmap.cpp:649
void stripFileHeader(std::ifstream &fieldFile)
virtual void getInfo(Inform *)
double rBegin_m
2 Pi divided by the field RF wavelength squared.
constexpr double pi
The value of .
Definition: Physics.h:30
std::string toUpper(const std::string &str)
Definition: Util.cpp:147
constexpr double Vpm2MVpm
Definition: Units.h:125
#define INFOMSG(msg)
Definition: IpplInfo.h:348
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
void computeFieldOffAxis(const Vector_t &R, Vector_t &E, Vector_t &B, std::vector< double > fieldComponents) const
bool interpreteEOF(std::ifstream &in)
Definition: Fieldmap.cpp:555
void computeFieldDerivatives(std::vector< double > fourierCoefs, double onAxisFieldP[], double onAxisFieldPP[], double onAxisFieldPPP[])
bool readFileHeader(std::ifstream &fieldFile)
double readFileData(std::ifstream &fieldFile, double fieldData[])
std::string::iterator iterator
Definition: MSLang.h:15
gsl_interp_accel * onAxisFieldPPPAccel_m
std::shared_ptr< _FM1DDynamic_fast > FM1DDynamic_fast
Definition: Definitions.h:30
virtual ~_FM1DDynamic_fast()
virtual void readMap()
double twoPiOverLambdaSq_m
Field angular frequency (Hz).
virtual bool getFieldDerivative(const Vector_t &R, Vector_t &E, Vector_t &B, const DiffDirection &dir) const
bool normalize_m
Definition: Fieldmap.h:121
Definition: Inform.h:42
void normalizeField(double maxEz, std::vector< double > &fourierCoefs)
_FM1DDynamic_fast(const std::string &filename)
double rEnd_m
Minimum radius of field.
double zEnd_m
Longitudinal start of field.
void disableFieldmapWarning()
Definition: Fieldmap.cpp:610
unsigned int accuracy_m
Field grid point spacing.
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
constexpr double MHz2Hz
Definition: Units.h:113
void prepareForMapCheck(std::vector< double > &fourierCoefs)
gsl_interp_accel * onAxisFieldAccel_m
On axis field third derivative interpolation structure.
gsl_interp_accel * onAxisFieldPPAccel_m
void getLine(std::ifstream &in, std::string &buffer)
Definition: Fieldmap.h:122
virtual void getFieldDimensions(double &zBegin, double &zEnd) const
constexpr double e
The value of .
Definition: Physics.h:39
std::string Filename_m
Definition: Fieldmap.h:118
unsigned int numberOfGridPoints_m
Field length.
virtual void freeMap()
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
void computeInterpolationVectors(double onAxisFieldP[], double onAxisFieldPP[], double onAxisFieldPPP[])
virtual void getOnaxisEz(std::vector< std::pair< double, double >> &eZ)
double length_m
Longitudinal end of field.
std::vector< double > computeFourierCoefficients(double fieldData[])
gsl_spline * onAxisFieldPInterpolants_m
On axis field interpolation structure.
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
double zBegin_m
Maximum radius of field.
bool checkFileData(std::ifstream &fieldFile, bool parsingPassed)
void computeFieldOnAxis(double z, std::vector< double > &fieldComponents) const
gsl_spline * onAxisFieldInterpolants_m
On axis field data.
void scaleField(double maxEz, std::vector< std::pair< double, double >> &eZ)