OPALX (Object Oriented Parallel Accelerator Library for Exascal) MINIorX
OPALX
FM1DElectroStatic_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
14 : Fieldmap(aFilename), accuracy_m(0) {
16 onAxisField_m = nullptr;
17
18 std::ifstream fieldFile(Filename_m.c_str());
19 if (fieldFile.good()) {
20 bool parsingPassed = readFileHeader(fieldFile);
21 parsingPassed = checkFileData(fieldFile, parsingPassed);
22 fieldFile.close();
23
24 if (!parsingPassed) {
26 zEnd_m = zBegin_m - 1.0e-3;
27 } else
29
32
33 } else {
35 zBegin_m = 0.0;
36 zEnd_m = -1.0e-3;
37 }
38}
39
43
45 if (onAxisField_m == nullptr) {
46 std::ifstream fieldFile(Filename_m.c_str());
47 stripFileHeader(fieldFile);
48
50 double maxEz = readFileData(fieldFile, onAxisField_m);
51 fieldFile.close();
52
53 std::vector<double> fourierCoefs = computeFourierCoefficients(onAxisField_m);
54 normalizeField(maxEz, fourierCoefs);
55
56 double* onAxisFieldP = new double[numberOfGridPoints_m];
57 double* onAxisFieldPP = new double[numberOfGridPoints_m];
58 double* onAxisFieldPPP = new double[numberOfGridPoints_m];
59 computeFieldDerivatives(fourierCoefs, onAxisFieldP, onAxisFieldPP, onAxisFieldPPP);
60 computeInterpolationVectors(onAxisFieldP, onAxisFieldPP, onAxisFieldPPP);
61
62 prepareForMapCheck(fourierCoefs);
63
64 delete[] onAxisFieldP;
65 delete[] onAxisFieldPP;
66 delete[] onAxisFieldPPP;
67
68 *ippl::Info << level3 << typeset_msg("read in fieldmap '" + Filename_m + "'", "info")
69 << endl;
70 }
71}
72
74 if (onAxisField_m != nullptr) {
75 delete[] onAxisField_m;
76 onAxisField_m = nullptr;
77
78 gsl_spline_free(onAxisFieldInterpolants_m);
79 gsl_spline_free(onAxisFieldPInterpolants_m);
80 gsl_spline_free(onAxisFieldPPInterpolants_m);
81 gsl_spline_free(onAxisFieldPPPInterpolants_m);
82 gsl_interp_accel_free(onAxisFieldAccel_m);
83 gsl_interp_accel_free(onAxisFieldPAccel_m);
84 gsl_interp_accel_free(onAxisFieldPPAccel_m);
85 gsl_interp_accel_free(onAxisFieldPPPAccel_m);
86
87 *ippl::Info << level3 << typeset_msg("freed fieldmap '" + Filename_m + "'", "info") << endl;
88 }
89}
90
93 std::vector<double> fieldComponents;
94 computeFieldOnAxis(R(2) - zBegin_m, fieldComponents);
95 computeFieldOffAxis(R, E, B, fieldComponents);
96
97 return false;
98}
99
102 const DiffDirection& /*dir*/) const {
103 E(2) += gsl_spline_eval(onAxisFieldPInterpolants_m, R(2) - zBegin_m, onAxisFieldPAccel_m);
104
105 return false;
106}
107
108void FM1DElectroStatic_fast::getFieldDimensions(double& zBegin, double& zEnd) const {
109 zBegin = zBegin_m;
110 zEnd = zEnd_m;
111}
113 double& /*xIni*/, double& /*xFinal*/, double& /*yIni*/, double& /*yFinal*/, double& /*zIni*/,
114 double& /*zFinal*/) const {
115}
116
119
121 (*msg) << Filename_m << " (1D electrotostatic); zini= " << zBegin_m << " m; zfinal= " << zEnd_m
122 << " m;" << endl;
123}
124
126 return 0.0;
127}
128
130}
131
132bool FM1DElectroStatic_fast::checkFileData(std::ifstream& fieldFile, bool parsingPassed) {
133 double tempDouble;
134 for (unsigned int dataIndex = 0; dataIndex < numberOfGridPoints_m; ++dataIndex)
135 parsingPassed = parsingPassed && interpretLine<double>(fieldFile, tempDouble);
136
137 return parsingPassed && interpreteEOF(fieldFile);
138}
139
141 std::vector<double> fourierCoefs, double onAxisFieldP[], double onAxisFieldPP[],
142 double onAxisFieldPPP[]) {
143 for (unsigned int zStepIndex = 0; zStepIndex < numberOfGridPoints_m; ++zStepIndex) {
144 double z = deltaZ_m * zStepIndex;
145 double kz = Physics::two_pi * z / length_m + Physics::pi;
146 onAxisFieldP[zStepIndex] = 0.0;
147 onAxisFieldPP[zStepIndex] = 0.0;
148 onAxisFieldPPP[zStepIndex] = 0.0;
149
150 int coefIndex = 1;
151 for (unsigned int n = 1; n < accuracy_m; ++n) {
152 double kn = n * Physics::two_pi / length_m;
153 double coskzn = cos(kz * n);
154 double sinkzn = sin(kz * n);
155
156 onAxisFieldP[zStepIndex] +=
157 kn
158 * (-fourierCoefs.at(coefIndex) * sinkzn - fourierCoefs.at(coefIndex + 1) * coskzn);
159
160 double derivCoeff = pow(kn, 2.0);
161 onAxisFieldPP[zStepIndex] +=
162 derivCoeff
163 * (-fourierCoefs.at(coefIndex) * coskzn + fourierCoefs.at(coefIndex + 1) * sinkzn);
164 derivCoeff *= kn;
165 onAxisFieldPPP[zStepIndex] +=
166 derivCoeff
167 * (fourierCoefs.at(coefIndex) * sinkzn + fourierCoefs.at(coefIndex + 1) * coskzn);
168
169 coefIndex += 2;
170 }
171 }
172}
173
176 std::vector<double> fieldComponents) const {
177 double radiusSq = pow(R(0), 2.0) + pow(R(1), 2.0);
178 double transverseEFactor =
179 -fieldComponents.at(1) / 2.0 + radiusSq * fieldComponents.at(3) / 16.0;
180
181 E(0) += R(0) * transverseEFactor;
182 E(1) += R(1) * transverseEFactor;
183 E(2) += fieldComponents.at(0) - fieldComponents.at(2) * radiusSq / 4.0;
184}
185
187 double z, std::vector<double>& fieldComponents) const {
188 fieldComponents.push_back(gsl_spline_eval(onAxisFieldInterpolants_m, z, onAxisFieldAccel_m));
189 fieldComponents.push_back(gsl_spline_eval(onAxisFieldPInterpolants_m, z, onAxisFieldPAccel_m));
190 fieldComponents.push_back(
192 fieldComponents.push_back(
194}
195
196std::vector<double> FM1DElectroStatic_fast::computeFourierCoefficients(double fieldData[]) {
197 const unsigned int totalSize = 2 * numberOfGridPoints_m - 1;
198 gsl_fft_real_wavetable* waveTable = gsl_fft_real_wavetable_alloc(totalSize);
199 gsl_fft_real_workspace* workSpace = gsl_fft_real_workspace_alloc(totalSize);
200
201 // Reflect field about minimum z value to ensure that it is periodic.
202 double* fieldDataReflected = new double[totalSize];
203 for (unsigned int dataIndex = 0; dataIndex < numberOfGridPoints_m; ++dataIndex) {
204 fieldDataReflected[numberOfGridPoints_m - 1 + dataIndex] = fieldData[dataIndex];
205 fieldDataReflected[numberOfGridPoints_m - 1 - dataIndex] = fieldData[dataIndex];
206 }
207
208 gsl_fft_real_transform(fieldDataReflected, 1, totalSize, waveTable, workSpace);
209
210 std::vector<double> fourierCoefs;
211 fourierCoefs.push_back(fieldDataReflected[0] / totalSize);
212 for (unsigned int coefIndex = 1; coefIndex + 1 < 2 * accuracy_m; ++coefIndex)
213 fourierCoefs.push_back(2.0 * fieldDataReflected[coefIndex] / totalSize);
214
215 delete[] fieldDataReflected;
216 gsl_fft_real_workspace_free(workSpace);
217 gsl_fft_real_wavetable_free(waveTable);
218
219 return fourierCoefs;
220}
221
223 double onAxisFieldP[], double onAxisFieldPP[], double onAxisFieldPPP[]) {
224 onAxisFieldInterpolants_m = gsl_spline_alloc(gsl_interp_cspline, numberOfGridPoints_m);
225 onAxisFieldPInterpolants_m = gsl_spline_alloc(gsl_interp_cspline, numberOfGridPoints_m);
226 onAxisFieldPPInterpolants_m = gsl_spline_alloc(gsl_interp_cspline, numberOfGridPoints_m);
227 onAxisFieldPPPInterpolants_m = gsl_spline_alloc(gsl_interp_cspline, numberOfGridPoints_m);
228
229 double* z = new double[numberOfGridPoints_m];
230 for (unsigned int zStepIndex = 0; zStepIndex < numberOfGridPoints_m; ++zStepIndex)
231 z[zStepIndex] = deltaZ_m * zStepIndex;
232
234 gsl_spline_init(onAxisFieldPInterpolants_m, z, onAxisFieldP, numberOfGridPoints_m);
235 gsl_spline_init(onAxisFieldPPInterpolants_m, z, onAxisFieldPP, numberOfGridPoints_m);
236 gsl_spline_init(onAxisFieldPPPInterpolants_m, z, onAxisFieldPPP, numberOfGridPoints_m);
237
238 onAxisFieldAccel_m = gsl_interp_accel_alloc();
239 onAxisFieldPAccel_m = gsl_interp_accel_alloc();
240 onAxisFieldPPAccel_m = gsl_interp_accel_alloc();
241 onAxisFieldPPPAccel_m = gsl_interp_accel_alloc();
242
243 delete[] z;
244}
245
253
254void FM1DElectroStatic_fast::normalizeField(double maxEz, std::vector<double>& fourierCoefs) {
255 for (unsigned int dataIndex = 0; dataIndex < numberOfGridPoints_m; ++dataIndex)
256 onAxisField_m[dataIndex] /= (maxEz * Units::Vpm2MVpm);
257
258 for (auto fourierIt = fourierCoefs.begin(); fourierIt < fourierCoefs.end(); ++fourierIt)
259 *fourierIt /= (maxEz * Units::Vpm2MVpm);
260}
261
262double FM1DElectroStatic_fast::readFileData(std::ifstream& fieldFile, double fieldData[]) {
263 double maxEz = 0.0;
264 for (unsigned int dataIndex = 0; dataIndex < numberOfGridPoints_m; ++dataIndex) {
265 interpretLine<double>(fieldFile, fieldData[dataIndex]);
266 if (std::abs(fieldData[dataIndex]) > maxEz)
267 maxEz = std::abs(fieldData[dataIndex]);
268 }
269
270 if (!normalize_m)
271 maxEz = 1.0;
272
273 return maxEz;
274}
275
276bool FM1DElectroStatic_fast::readFileHeader(std::ifstream& fieldFile) {
277 std::string tempString;
278 int tempInt;
279
280 bool parsingPassed = true;
281 try {
282 parsingPassed = interpretLine<std::string, unsigned int>(fieldFile, tempString, accuracy_m);
283 } catch (GeneralClassicException& e) {
285 fieldFile, tempString, accuracy_m, tempString);
286
287 tempString = Util::toUpper(tempString);
288 if (tempString != "TRUE" && tempString != "FALSE")
290 "FM1DElectroStatic_fast::readFileHeader",
291 "The third string on the first line of 1D field "
292 "maps has to be either TRUE or FALSE");
293
294 normalize_m = (tempString == "TRUE");
295 }
296 parsingPassed = parsingPassed
299 parsingPassed =
300 parsingPassed && interpretLine<double, double, int>(fieldFile, rBegin_m, rEnd_m, tempInt);
301
305
306 return parsingPassed;
307}
308
309void FM1DElectroStatic_fast::stripFileHeader(std::ifstream& fieldFile) {
310 std::string tempString;
311
312 getLine(fieldFile, tempString);
313 getLine(fieldFile, tempString);
314 getLine(fieldFile, tempString);
315}
316
317void FM1DElectroStatic_fast::prepareForMapCheck(std::vector<double>& fourierCoefs) {
318 std::vector<double> zSampling(numberOfGridPoints_m);
319 for (unsigned int zStepIndex = 0; zStepIndex < numberOfGridPoints_m; ++zStepIndex)
320 zSampling[zStepIndex] = deltaZ_m * zStepIndex;
321
322 checkMap(
323 accuracy_m, length_m, zSampling, fourierCoefs, onAxisFieldInterpolants_m,
325}
ippl::Vector< T, Dim > Vector_t
@ T1DElectroStatic
Definition Fieldmap.h:19
DiffDirection
Definition Fieldmap.h:55
constexpr double two_pi
The value of.
Definition Physics.h:33
constexpr double pi
The value of.
Definition Physics.h:30
constexpr double cm2m
Definition Units.h:35
constexpr double Vpm2MVpm
Definition Units.h:125
std::string toUpper(const std::string &str)
Definition Util.cpp:145
MapType Type
Definition Fieldmap.h:118
bool interpreteEOF(std::ifstream &in)
Definition Fieldmap.cpp:516
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:413
void disableFieldmapWarning()
Definition Fieldmap.cpp:569
bool normalize_m
Definition Fieldmap.h:123
static std::string typeset_msg(const std::string &msg, const std::string &title)
Definition Fieldmap.cpp:607
std::string Filename_m
Definition Fieldmap.h:120
bool interpretLine(std::ifstream &in, S &value, const bool &file_length_known=true)
void getLine(std::ifstream &in, std::string &buffer)
Definition Fieldmap.h:124
void noFieldmapWarning()
Definition Fieldmap.cpp:576
gsl_spline * onAxisFieldPInterpolants_m
On axis field interpolation structure.
std::vector< double > computeFourierCoefficients(double fieldData[])
void computeFieldDerivatives(std::vector< double > fourierCoefs, double onAxisFieldP[], double onAxisFieldPP[], double onAxisFieldPPP[])
void normalizeField(double maxEz, std::vector< double > &fourierCoefs)
gsl_interp_accel * onAxisFieldPAccel_m
void computeFieldOnAxis(double z, std::vector< double > &fieldComponents) const
void stripFileHeader(std::ifstream &fieldFile)
unsigned int numberOfGridPoints_m
Field length.
virtual void getInfo(Inform *)
unsigned int accuracy_m
Field grid point spacing.
FM1DElectroStatic_fast(std::string aFilename)
virtual void getFieldDimensions(double &zBegin, double &zEnd) const
double zEnd_m
Longitudinal start of field.
gsl_spline * onAxisFieldInterpolants_m
On axis field data.
virtual double getFrequency() const
virtual bool getFieldstrength(const Vector_t< double, 3 > &R, Vector_t< double, 3 > &E, Vector_t< double, 3 > &B) const
double readFileData(std::ifstream &fieldFile, double fieldData[])
virtual bool getFieldDerivative(const Vector_t< double, 3 > &R, Vector_t< double, 3 > &E, Vector_t< double, 3 > &B, const DiffDirection &dir) const
gsl_interp_accel * onAxisFieldPPPAccel_m
gsl_spline * onAxisFieldPPInterpolants_m
On axis field first derivative interpolation structure.
gsl_interp_accel * onAxisFieldAccel_m
On axis field third derivative interpolation structure.
double rEnd_m
Minimum radius of field.
virtual void setFrequency(double freq)
bool readFileHeader(std::ifstream &fieldFile)
double length_m
Longitudinal end of field.
double zBegin_m
Maximum radius of field.
bool checkFileData(std::ifstream &fieldFile, bool parsingPassed)
void computeFieldOffAxis(const Vector_t< double, 3 > &R, Vector_t< double, 3 > &E, Vector_t< double, 3 > &B, std::vector< double > fieldComponents) const
double deltaZ_m
Number of grid points in field input file.
gsl_spline * onAxisFieldPPPInterpolants_m
On axis field second derivative interpolation structure.
void computeInterpolationVectors(double onAxisFieldP[], double onAxisFieldPP[], double onAxisFieldPPP[])
gsl_interp_accel * onAxisFieldPPAccel_m
void prepareForMapCheck(std::vector< double > &fourierCoefs)