OPALX (Object Oriented Parallel Accelerator Library for Exascal) MINIorX
OPALX
FM1DMagnetoStatic_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
13FM1DMagnetoStatic_fast::FM1DMagnetoStatic_fast(std::string aFilename) : Fieldmap(aFilename) {
15 onAxisField_m = nullptr;
16
17 std::ifstream fieldFile(Filename_m.c_str());
18 if (fieldFile.good()) {
19 bool parsingPassed = readFileHeader(fieldFile);
20 parsingPassed = checkFileData(fieldFile, parsingPassed);
21 fieldFile.close();
22
23 if (!parsingPassed) {
25 zEnd_m = zBegin_m - 1.0e-3;
26 } else
28
31
32 } else {
34 zBegin_m = 0.0;
35 zEnd_m = -1.0e-3;
36 }
37}
38
42
44 if (onAxisField_m == nullptr) {
45 std::ifstream fieldFile(Filename_m.c_str());
46 stripFileHeader(fieldFile);
47
49 double maxBz = readFileData(fieldFile, onAxisField_m);
50 fieldFile.close();
51
52 std::vector<double> fourierCoefs = computeFourierCoefficients(onAxisField_m);
53 normalizeField(maxBz, fourierCoefs);
54
55 double* onAxisFieldP = new double[numberOfGridPoints_m];
56 double* onAxisFieldPP = new double[numberOfGridPoints_m];
57 double* onAxisFieldPPP = new double[numberOfGridPoints_m];
58 computeFieldDerivatives(fourierCoefs, onAxisFieldP, onAxisFieldPP, onAxisFieldPPP);
59 computeInterpolationVectors(onAxisFieldP, onAxisFieldPP, onAxisFieldPPP);
60
61 prepareForMapCheck(fourierCoefs);
62
63 delete[] onAxisFieldP;
64 delete[] onAxisFieldPP;
65 delete[] onAxisFieldPPP;
66
67 *ippl::Info << level3 << typeset_msg("read in fieldmap '" + Filename_m + "'", "info")
68 << endl;
69 }
70}
71
73 if (onAxisField_m != nullptr) {
74 delete[] onAxisField_m;
75 onAxisField_m = nullptr;
76
77 gsl_spline_free(onAxisFieldInterpolants_m);
78 gsl_spline_free(onAxisFieldPInterpolants_m);
79 gsl_spline_free(onAxisFieldPPInterpolants_m);
80 gsl_spline_free(onAxisFieldPPPInterpolants_m);
81 gsl_interp_accel_free(onAxisFieldAccel_m);
82 gsl_interp_accel_free(onAxisFieldPAccel_m);
83 gsl_interp_accel_free(onAxisFieldPPAccel_m);
84 gsl_interp_accel_free(onAxisFieldPPPAccel_m);
85
86 *ippl::Info << level3 << typeset_msg("freed fieldmap '" + Filename_m + "'", "info") << endl;
87 }
88}
89
92 std::vector<double> fieldComponents;
93 computeFieldOnAxis(R(2) - zBegin_m, fieldComponents);
94 computeFieldOffAxis(R, E, B, fieldComponents);
95
96 return false;
97}
98
101 const DiffDirection& /*dir*/) const {
102 B(2) += gsl_spline_eval(onAxisFieldPInterpolants_m, R(2) - zBegin_m, onAxisFieldPAccel_m);
103
104 return false;
105}
106
107void FM1DMagnetoStatic_fast::getFieldDimensions(double& zBegin, double& zEnd) const {
108 zBegin = zBegin_m;
109 zEnd = zEnd_m;
110}
111
113 double& /*xIni*/, double& /*xFinal*/, double& /*yIni*/, double& /*yFinal*/, double& /*zIni*/,
114 double& /*zFinal*/) const {
115}
116
119
121 (*msg) << Filename_m << " (1D magnetostatic); zini= " << zBegin_m << " m; zfinal= " << zEnd_m
122 << " m;" << endl;
123}
124
126 return 0.0;
127}
128
130}
131
132bool FM1DMagnetoStatic_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 transverseBFactor =
179 -fieldComponents.at(1) / 2.0 + radiusSq * fieldComponents.at(3) / 16.0;
180
181 B(0) += R(0) * transverseBFactor;
182 B(1) += R(1) * transverseBFactor;
183 B(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> FM1DMagnetoStatic_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 if (dataIndex != 0)
206 fieldDataReflected[numberOfGridPoints_m - 1 - dataIndex] = fieldData[dataIndex];
207 }
208
209 gsl_fft_real_transform(fieldDataReflected, 1, totalSize, waveTable, workSpace);
210
211 std::vector<double> fourierCoefs;
212 fourierCoefs.push_back(fieldDataReflected[0] / totalSize);
213 for (unsigned int coefIndex = 1; coefIndex + 1 < 2 * accuracy_m; ++coefIndex)
214 fourierCoefs.push_back(2.0 * fieldDataReflected[coefIndex] / totalSize);
215
216 delete[] fieldDataReflected;
217 gsl_fft_real_workspace_free(workSpace);
218 gsl_fft_real_wavetable_free(waveTable);
219
220 return fourierCoefs;
221}
222
224 double onAxisFieldP[], double onAxisFieldPP[], double onAxisFieldPPP[]) {
225 onAxisFieldInterpolants_m = gsl_spline_alloc(gsl_interp_cspline, numberOfGridPoints_m);
226 onAxisFieldPInterpolants_m = gsl_spline_alloc(gsl_interp_cspline, numberOfGridPoints_m);
227 onAxisFieldPPInterpolants_m = gsl_spline_alloc(gsl_interp_cspline, numberOfGridPoints_m);
228 onAxisFieldPPPInterpolants_m = gsl_spline_alloc(gsl_interp_cspline, numberOfGridPoints_m);
229
230 double* z = new double[numberOfGridPoints_m];
231 for (unsigned int zStepIndex = 0; zStepIndex < numberOfGridPoints_m; ++zStepIndex)
232 z[zStepIndex] = deltaZ_m * zStepIndex;
233
235 gsl_spline_init(onAxisFieldPInterpolants_m, z, onAxisFieldP, numberOfGridPoints_m);
236 gsl_spline_init(onAxisFieldPPInterpolants_m, z, onAxisFieldPP, numberOfGridPoints_m);
237 gsl_spline_init(onAxisFieldPPPInterpolants_m, z, onAxisFieldPPP, numberOfGridPoints_m);
238
239 onAxisFieldAccel_m = gsl_interp_accel_alloc();
240 onAxisFieldPAccel_m = gsl_interp_accel_alloc();
241 onAxisFieldPPAccel_m = gsl_interp_accel_alloc();
242 onAxisFieldPPPAccel_m = gsl_interp_accel_alloc();
243
244 delete[] z;
245}
246
254
255void FM1DMagnetoStatic_fast::normalizeField(double maxBz, std::vector<double>& fourierCoefs) {
256 if (!normalize_m)
257 return;
258
259 for (unsigned int dataIndex = 0; dataIndex < numberOfGridPoints_m; ++dataIndex)
260 onAxisField_m[dataIndex] /= maxBz;
261
262 for (std::vector<double>::iterator fourierIterator = fourierCoefs.begin();
263 fourierIterator < fourierCoefs.end(); ++fourierIterator)
264 *fourierIterator /= maxBz;
265}
266
267double FM1DMagnetoStatic_fast::readFileData(std::ifstream& fieldFile, double fieldData[]) {
268 double maxBz = 0.0;
269 for (unsigned int dataIndex = 0; dataIndex < numberOfGridPoints_m; ++dataIndex) {
270 interpretLine<double>(fieldFile, fieldData[dataIndex]);
271 if (std::abs(fieldData[dataIndex]) > maxBz)
272 maxBz = std::abs(fieldData[dataIndex]);
273 }
274
275 return maxBz;
276}
277
278bool FM1DMagnetoStatic_fast::readFileHeader(std::ifstream& fieldFile) {
279 std::string tempString;
280 int tempInt;
281
282 bool parsingPassed = true;
283
284 try {
285 parsingPassed = interpretLine<std::string, unsigned int>(fieldFile, tempString, accuracy_m);
286 } catch (GeneralClassicException& e) {
288 fieldFile, tempString, accuracy_m, tempString);
289
290 tempString = Util::toUpper(tempString);
291 if (tempString != "TRUE" && tempString != "FALSE")
293 "FM1DMagnetoStatic_fast::readFileHeader",
294 "The third string on the first line of 1D field "
295 "maps has to be either TRUE or FALSE");
296
297 normalize_m = (tempString == "TRUE");
298 }
299
300 parsingPassed = parsingPassed
303 parsingPassed =
304 parsingPassed && interpretLine<double, double, int>(fieldFile, rBegin_m, rEnd_m, tempInt);
305
307
310
311 return parsingPassed;
312}
313
314void FM1DMagnetoStatic_fast::stripFileHeader(std::ifstream& fieldFile) {
315 std::string tempString;
316
317 getLine(fieldFile, tempString);
318 getLine(fieldFile, tempString);
319 getLine(fieldFile, tempString);
320}
321
322void FM1DMagnetoStatic_fast::prepareForMapCheck(std::vector<double>& fourierCoefs) {
323 std::vector<double> zSampling(numberOfGridPoints_m);
324 for (unsigned int zStepIndex = 0; zStepIndex < numberOfGridPoints_m; ++zStepIndex)
325 zSampling[zStepIndex] = deltaZ_m * zStepIndex;
326
327 checkMap(
328 accuracy_m, length_m, zSampling, fourierCoefs, onAxisFieldInterpolants_m,
330}
ippl::Vector< T, Dim > Vector_t
@ T1DMagnetoStatic
Definition Fieldmap.h:21
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
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
virtual double getFrequency() const
void computeFieldDerivatives(std::vector< double > fourierCoefs, double onAxisFieldP[], double onAxisFieldPP[], double onAxisFieldPPP[])
void computeInterpolationVectors(double onAxisFieldP[], double onAxisFieldPP[], double onAxisFieldPPP[])
gsl_interp_accel * onAxisFieldAccel_m
On axis field third derivative interpolation structure.
void stripFileHeader(std::ifstream &fieldFile)
std::vector< double > computeFourierCoefficients(double fieldData[])
bool readFileHeader(std::ifstream &fieldFile)
unsigned int accuracy_m
Field grid point spacing.
FM1DMagnetoStatic_fast(std::string aFilename)
void computeFieldOnAxis(double z, std::vector< double > &fieldComponents) const
gsl_spline * onAxisFieldPPInterpolants_m
On axis field first derivative interpolation structure.
gsl_spline * onAxisFieldPInterpolants_m
On axis field interpolation structure.
gsl_spline * onAxisFieldPPPInterpolants_m
On axis field second derivative interpolation structure.
unsigned int numberOfGridPoints_m
Field length.
double rEnd_m
Minimum radius of field.
void prepareForMapCheck(std::vector< double > &fourierCoefs)
virtual void getInfo(Inform *)
double deltaZ_m
Number of grid points in field input file.
void normalizeField(double maxBz, std::vector< double > &fourierCoefs)
double readFileData(std::ifstream &fieldFile, double fieldData[])
double zEnd_m
Longitudinal start of field.
gsl_interp_accel * onAxisFieldPAccel_m
virtual bool getFieldstrength(const Vector_t< double, 3 > &R, Vector_t< double, 3 > &E, Vector_t< double, 3 > &B) const
double length_m
Longitudinal end of field.
virtual void setFrequency(double freq)
virtual bool getFieldDerivative(const Vector_t< double, 3 > &R, Vector_t< double, 3 > &E, Vector_t< double, 3 > &B, const DiffDirection &dir) const
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
virtual void getFieldDimensions(double &zBegin, double &zEnd) const
gsl_interp_accel * onAxisFieldPPAccel_m
gsl_spline * onAxisFieldInterpolants_m
On axis field data.
gsl_interp_accel * onAxisFieldPPPAccel_m
double zBegin_m
Maximum radius of field.