OPAL (Object Oriented Parallel Accelerator Library) 2024.2
OPAL
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"
5#include "Utilities/Util.h"
7
8#include "gsl/gsl_fft_real.h"
9
10#include <fstream>
11#include <ios>
12
14 _Fieldmap(filename) {
15
17 onAxisField_m = nullptr;
18
19 std::ifstream fieldFile(Filename_m.c_str());
20 if(fieldFile.good()) {
21
22 bool parsingPassed = readFileHeader(fieldFile);
23 parsingPassed = checkFileData(fieldFile, parsingPassed);
24 fieldFile.close();
25
26 if(!parsingPassed) {
28 zEnd_m = zBegin_m - 1.0e-3;
29 } else
31
34
35 } else {
37 zBegin_m = 0.0;
38 zEnd_m = -1.0e-3;
39 }
40}
41
45
50
52
53 if(onAxisField_m == nullptr) {
54
55 std::ifstream fieldFile(Filename_m.c_str());
56 stripFileHeader(fieldFile);
57
59 double maxBz = readFileData(fieldFile, onAxisField_m);
60 fieldFile.close();
61
62 std::vector<double> fourierCoefs
64 normalizeField(maxBz, 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(level3 << 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}
111
113 Vector_t &/*E*/,
114 Vector_t &B,
115 const DiffDirection &/*dir*/) const {
116
117 B(2) += gsl_spline_eval(onAxisFieldPInterpolants_m, R(2) - zBegin_m,
119
120 return false;
121
122}
123
124void _FM1DMagnetoStatic_fast::getFieldDimensions(double &zBegin, double &zEnd) const {
125 zBegin = zBegin_m;
126 zEnd = zEnd_m;
127}
128
129void _FM1DMagnetoStatic_fast::getFieldDimensions(double &/*xIni*/, double &/*xFinal*/,
130 double &/*yIni*/, double &/*yFinal*/,
131 double &/*zIni*/, double &/*zFinal*/) const {}
132
135
137 (*msg) << Filename_m
138 << " (1D magnetostatic); zini= "
139 << zBegin_m << " m; zfinal= "
140 << zEnd_m << " m;" << endl;
141}
142
144 return 0.0;
145}
146
148{ }
149
150bool _FM1DMagnetoStatic_fast::checkFileData(std::ifstream &fieldFile,
151 bool parsingPassed) {
152
153 double tempDouble;
154 for (unsigned int dataIndex = 0; dataIndex < numberOfGridPoints_m; ++ dataIndex)
155 parsingPassed = parsingPassed
156 && interpretLine<double>(fieldFile, tempDouble);
157
158 return parsingPassed && interpreteEOF(fieldFile);
159
160}
161
162void _FM1DMagnetoStatic_fast::computeFieldDerivatives(std::vector<double> fourierCoefs,
163 double onAxisFieldP[],
164 double onAxisFieldPP[],
165 double onAxisFieldPPP[]) {
166
167 for (unsigned int zStepIndex = 0; zStepIndex < numberOfGridPoints_m; ++ zStepIndex) {
168
169 double z = deltaZ_m * zStepIndex;
170 double kz = Physics::two_pi * z / length_m + Physics::pi;
171 onAxisFieldP[zStepIndex] = 0.0;
172 onAxisFieldPP[zStepIndex] = 0.0;
173 onAxisFieldPPP[zStepIndex] = 0.0;
174
175 int coefIndex = 1;
176 for (unsigned int n = 1; n < accuracy_m; ++ n) {
177
178 double kn = n * Physics::two_pi / length_m;
179 double coskzn = cos(kz * n);
180 double sinkzn = sin(kz * n);
181
182 onAxisFieldP[zStepIndex] += kn * (-fourierCoefs.at(coefIndex) * sinkzn
183 - fourierCoefs.at(coefIndex + 1) * coskzn);
184
185 double derivCoeff = pow(kn, 2.0);
186 onAxisFieldPP[zStepIndex] += derivCoeff * (-fourierCoefs.at(coefIndex) * coskzn
187 + fourierCoefs.at(coefIndex + 1) * sinkzn);
188 derivCoeff *= kn;
189 onAxisFieldPPP[zStepIndex] += derivCoeff * (fourierCoefs.at(coefIndex) * sinkzn
190 + fourierCoefs.at(coefIndex + 1) * coskzn);
191
192 coefIndex += 2;
193 }
194 }
195}
196
198 Vector_t &/*E*/,
199 Vector_t &B,
200 std::vector<double> fieldComponents) const {
201
202 double radiusSq = pow(R(0), 2.0) + pow(R(1), 2.0);
203 double transverseBFactor = -fieldComponents.at(1) / 2.0
204 + radiusSq * fieldComponents.at(3) / 16.0;
205
206 B(0) += R(0) * transverseBFactor;
207 B(1) += R(1) * transverseBFactor;
208 B(2) += fieldComponents.at(0) - fieldComponents.at(2) * radiusSq / 4.0;
209
210}
211
213 std::vector<double> &fieldComponents) const {
214
215 fieldComponents.push_back(gsl_spline_eval(onAxisFieldInterpolants_m,
217 fieldComponents.push_back(gsl_spline_eval(onAxisFieldPInterpolants_m,
219 fieldComponents.push_back(gsl_spline_eval(onAxisFieldPPInterpolants_m,
221 fieldComponents.push_back(gsl_spline_eval(onAxisFieldPPPInterpolants_m,
223}
224
225std::vector<double> _FM1DMagnetoStatic_fast::computeFourierCoefficients(double fieldData[]) {
226
227 const unsigned int totalSize = 2 * numberOfGridPoints_m - 1;
228 gsl_fft_real_wavetable *waveTable = gsl_fft_real_wavetable_alloc(totalSize);
229 gsl_fft_real_workspace *workSpace = gsl_fft_real_workspace_alloc(totalSize);
230
231 // Reflect field about minimum z value to ensure that it is periodic.
232 double *fieldDataReflected = new double[totalSize];
233 for (unsigned int dataIndex = 0; dataIndex < numberOfGridPoints_m; ++ dataIndex) {
234 fieldDataReflected[numberOfGridPoints_m - 1 + dataIndex]
235 = fieldData[dataIndex];
236 if(dataIndex != 0)
237 fieldDataReflected[numberOfGridPoints_m - 1 - dataIndex]
238 = fieldData[dataIndex];
239 }
240
241 gsl_fft_real_transform(fieldDataReflected, 1, totalSize, waveTable, workSpace);
242
243 std::vector<double> fourierCoefs;
244 fourierCoefs.push_back(fieldDataReflected[0] / totalSize);
245 for (unsigned int coefIndex = 1; coefIndex + 1 < 2 * accuracy_m; ++ coefIndex)
246 fourierCoefs.push_back(2.0 * fieldDataReflected[coefIndex] / totalSize);
247
248 delete [] fieldDataReflected;
249 gsl_fft_real_workspace_free(workSpace);
250 gsl_fft_real_wavetable_free(waveTable);
251
252 return fourierCoefs;
253
254}
255
257 double onAxisFieldPP[],
258 double onAxisFieldPPP[]) {
259
260 onAxisFieldInterpolants_m = gsl_spline_alloc(gsl_interp_cspline,
262 onAxisFieldPInterpolants_m = gsl_spline_alloc(gsl_interp_cspline,
264 onAxisFieldPPInterpolants_m = gsl_spline_alloc(gsl_interp_cspline,
266 onAxisFieldPPPInterpolants_m = gsl_spline_alloc(gsl_interp_cspline,
268
269 double *z = new double[numberOfGridPoints_m];
270 for (unsigned int zStepIndex = 0; zStepIndex < numberOfGridPoints_m; ++ zStepIndex)
271 z[zStepIndex] = deltaZ_m * zStepIndex;
272
273 gsl_spline_init(onAxisFieldInterpolants_m, z,
275 gsl_spline_init(onAxisFieldPInterpolants_m, z,
276 onAxisFieldP, numberOfGridPoints_m);
277 gsl_spline_init(onAxisFieldPPInterpolants_m, z,
278 onAxisFieldPP, numberOfGridPoints_m);
279 gsl_spline_init(onAxisFieldPPPInterpolants_m, z,
280 onAxisFieldPPP, numberOfGridPoints_m);
281
282 onAxisFieldAccel_m = gsl_interp_accel_alloc();
283 onAxisFieldPAccel_m = gsl_interp_accel_alloc();
284 onAxisFieldPPAccel_m = gsl_interp_accel_alloc();
285 onAxisFieldPPPAccel_m = gsl_interp_accel_alloc();
286
287 delete [] z;
288}
289
291
292 // Convert to m.
297}
298
299void _FM1DMagnetoStatic_fast::normalizeField(double maxBz, std::vector<double> &fourierCoefs) {
300 if (!normalize_m) return;
301
302 for (unsigned int dataIndex = 0; dataIndex < numberOfGridPoints_m; ++ dataIndex)
303 onAxisField_m[dataIndex] /= maxBz;
304
305 for (std::vector<double>::iterator fourierIterator = fourierCoefs.begin();
306 fourierIterator < fourierCoefs.end(); ++ fourierIterator)
307 *fourierIterator /= maxBz;
308
309}
310
311double _FM1DMagnetoStatic_fast::readFileData(std::ifstream &fieldFile,
312 double fieldData[]) {
313
314 double maxBz = 0.0;
315 for (unsigned int dataIndex = 0; dataIndex < numberOfGridPoints_m; ++ dataIndex) {
316 interpretLine<double>(fieldFile, fieldData[dataIndex]);
317 if(std::abs(fieldData[dataIndex]) > maxBz)
318 maxBz = std::abs(fieldData[dataIndex]);
319 }
320
321 return maxBz;
322}
323
324bool _FM1DMagnetoStatic_fast::readFileHeader(std::ifstream &fieldFile) {
325
326 std::string tempString;
327 int tempInt;
328
329 bool parsingPassed = true;
330
331 try {
332 parsingPassed = interpretLine<std::string, unsigned int>(fieldFile,
333 tempString,
334 accuracy_m);
335 } catch (GeneralClassicException &e) {
337 tempString,
339 tempString);
340
341 tempString = Util::toUpper(tempString);
342 if (tempString != "TRUE" &&
343 tempString != "FALSE")
344 throw GeneralClassicException("_FM1DMagnetoStatic_fast::readFileHeader",
345 "The third string on the first line of 1D field "
346 "maps has to be either TRUE or FALSE");
347
348 normalize_m = (tempString == "TRUE");
349 }
350
351 parsingPassed = parsingPassed &&
353 zBegin_m,
354 zEnd_m,
356 parsingPassed = parsingPassed &&
358 rBegin_m,
359 rEnd_m,
360 tempInt);
361
363
366
367 return parsingPassed;
368}
369
370void _FM1DMagnetoStatic_fast::stripFileHeader(std::ifstream &fieldFile) {
371
372 std::string tempString;
373
374 getLine(fieldFile, tempString);
375 getLine(fieldFile, tempString);
376 getLine(fieldFile, tempString);
377}
378
379void _FM1DMagnetoStatic_fast::prepareForMapCheck(std::vector<double> &fourierCoefs) {
380 std::vector<double> zSampling(numberOfGridPoints_m);
381 for (unsigned int zStepIndex = 0; zStepIndex < numberOfGridPoints_m; ++ zStepIndex)
382 zSampling[zStepIndex] = deltaZ_m * zStepIndex;
383
385 length_m,
386 zSampling,
387 fourierCoefs,
390}
std::shared_ptr< _FM1DMagnetoStatic_fast > FM1DMagnetoStatic_fast
@ T1DMagnetoStatic
Definition Fieldmap.h:21
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
Inform & level3(Inform &inf)
Definition Inform.cpp:47
#define INFOMSG(msg)
Definition IpplInfo.h:348
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: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
double zEnd_m
Longitudinal start of field.
gsl_interp_accel * onAxisFieldAccel_m
On axis field third derivative interpolation structure.
gsl_spline * onAxisFieldPPInterpolants_m
On axis field first derivative interpolation structure.
std::vector< double > computeFourierCoefficients(double fieldData[])
bool checkFileData(std::ifstream &fieldFile, bool parsingPassed)
void computeFieldDerivatives(std::vector< double > fourierCoefs, double onAxisFieldP[], double onAxisFieldPP[], double onAxisFieldPPP[])
double readFileData(std::ifstream &fieldFile, double fieldData[])
gsl_interp_accel * onAxisFieldPPPAccel_m
virtual double getFrequency() const
unsigned int numberOfGridPoints_m
Field length.
double deltaZ_m
Number of grid points in field input file.
_FM1DMagnetoStatic_fast(const std::string &filename)
void computeFieldOnAxis(double z, std::vector< double > &fieldComponents) const
void stripFileHeader(std::ifstream &fieldFile)
gsl_interp_accel * onAxisFieldPAccel_m
static FM1DMagnetoStatic_fast create(const std::string &filename)
void normalizeField(double maxBz, std::vector< double > &fourierCoefs)
unsigned int accuracy_m
Field grid point spacing.
virtual void setFrequency(double freq)
void computeFieldOffAxis(const Vector_t &R, Vector_t &E, Vector_t &B, std::vector< double > fieldComponents) const
gsl_spline * onAxisFieldPPPInterpolants_m
On axis field second derivative interpolation structure.
gsl_spline * onAxisFieldPInterpolants_m
On axis field interpolation structure.
double rEnd_m
Minimum radius of field.
double zBegin_m
Maximum radius of field.
double length_m
Longitudinal end of field.
virtual void getFieldDimensions(double &zBegin, double &zEnd) const
virtual bool getFieldstrength(const Vector_t &R, Vector_t &E, Vector_t &B) const
void prepareForMapCheck(std::vector< double > &fourierCoefs)
gsl_interp_accel * onAxisFieldPPAccel_m
virtual bool getFieldDerivative(const Vector_t &R, Vector_t &E, Vector_t &B, const DiffDirection &dir) const
bool readFileHeader(std::ifstream &fieldFile)
gsl_spline * onAxisFieldInterpolants_m
On axis field data.
void computeInterpolationVectors(double onAxisFieldP[], double onAxisFieldPP[], double onAxisFieldPPP[])
Vektor< double, 3 > Vector_t