OPALX (Object Oriented Parallel Accelerator Library for Exascal) MINIorX
OPALX
Astra1DMagnetoStatic.cpp
Go to the documentation of this file.
2#include "Fields/Fieldmap.hpp"
3#include "Physics/Physics.h"
5#include "Utilities/Util.h"
6
7#include "gsl/gsl_fft_real.h"
8#include "gsl/gsl_interp.h"
9#include "gsl/gsl_spline.h"
10
11#include <fstream>
12#include <ios>
13
15 : Fieldmap(aFilename), FourCoefs_m(nullptr) {
16 std::ifstream file;
17 int skippedValues = 0;
18 std::string tmpString;
19 double tmpDouble;
20
22
23 // open field map, parse it and disable element on error
24 file.open(Filename_m.c_str());
25 if (file.good()) {
26 bool parsing_passed = true;
27 try {
28 parsing_passed = interpretLine<std::string, int>(file, tmpString, accuracy_m);
29 } catch (GeneralClassicException& e) {
31 file, tmpString, accuracy_m, tmpString);
32
33 tmpString = Util::toUpper(tmpString);
34 if (tmpString != "TRUE" && tmpString != "FALSE")
36 "Astra1DMagnetoStatic::Astra1DMagnetoStatic",
37 "The third string on the first line of 1D field "
38 "maps has to be either TRUE or FALSE");
39
40 normalize_m = (tmpString == "TRUE");
41 }
42 parsing_passed = parsing_passed && interpretLine<double, double>(file, zbegin_m, tmpDouble);
43
44 double tmpDouble2 = zbegin_m;
45 while (!file.eof() && parsing_passed) {
46 parsing_passed = interpretLine<double, double>(file, zend_m, tmpDouble, false);
47 if (zend_m - tmpDouble2 > 1e-10) {
48 tmpDouble2 = zend_m;
49 } else if (parsing_passed) {
50 ++skippedValues;
51 }
52 }
53
54 file.close();
55 num_gridpz_m = lines_read_m - 2 - skippedValues;
56 lines_read_m = 0;
57
58 if (!parsing_passed && !file.eof()) {
60 zend_m = zbegin_m - 1e-3;
62 "Astra1DMagnetoStatic::Astra1DMagnetoStatic",
63 "An error occured when reading the fieldmap '" + Filename_m + "'");
64 }
65 length_m = 2.0 * num_gridpz_m * (zend_m - zbegin_m) / (num_gridpz_m - 1);
66 } else {
67 noFieldmapWarning();
68 zbegin_m = 0.0;
69 zend_m = -1e-3;
70 }
71}
72
76
78 if (FourCoefs_m == nullptr) {
79 // declare variables and allocate memory
80 std::ifstream in;
81
82 bool parsing_passed = true;
83
84 std::string tmpString;
85
86 double Bz_max = 0.0;
87 double dz = (zend_m - zbegin_m) / (num_gridpz_m - 1);
88 double tmpDouble = zbegin_m - dz;
89
90 double* RealValues = new double[2 * num_gridpz_m];
91 double* zvals = new double[num_gridpz_m];
92
93 gsl_spline* Bz_interpolant = gsl_spline_alloc(gsl_interp_cspline, num_gridpz_m);
94 gsl_interp_accel* Bz_accel = gsl_interp_accel_alloc();
95
96 gsl_fft_real_wavetable* real = gsl_fft_real_wavetable_alloc(2 * num_gridpz_m);
97 gsl_fft_real_workspace* work = gsl_fft_real_workspace_alloc(2 * num_gridpz_m);
98
99 FourCoefs_m = new double[2 * accuracy_m - 1];
100
101 // read in and parse field map
102 in.open(Filename_m.c_str());
103 getLine(in, tmpString);
104
105 for (int i = 0; i < num_gridpz_m && parsing_passed; /* skip increment on i here */) {
106 parsing_passed = interpretLine<double, double>(in, zvals[i], RealValues[i]);
107 // the sequence of z-position should be strictly increasing
108 // drop sampling points that don't comply to this
109 if (zvals[i] - tmpDouble > 1e-10) {
110 if (std::abs(RealValues[i]) > Bz_max) {
111 Bz_max = std::abs(RealValues[i]);
112 }
113 tmpDouble = zvals[i];
114 ++i; // increment i only if sampling point is accepted
115 }
116 }
117 in.close();
118
119 gsl_spline_init(Bz_interpolant, zvals, RealValues, num_gridpz_m);
120
121 // get equidistant sampling from the, possibly, non-equidistant sampling
122 // using cubic spline for this
123 int ii = num_gridpz_m;
124 for (int i = 0; i < num_gridpz_m - 1; ++i, ++ii) {
125 double z = zbegin_m + dz * i;
126 RealValues[ii] = gsl_spline_eval(Bz_interpolant, z, Bz_accel);
127 }
128 RealValues[ii++] = RealValues[num_gridpz_m - 1];
129 // prepend mirror sampling points such that field values are periodic for sure
130 --ii; // ii == 2*num_gridpz_m at the moment
131 for (int i = 0; i < num_gridpz_m; ++i, --ii) {
132 RealValues[i] = RealValues[ii];
133 }
134
135 gsl_fft_real_transform(RealValues, 1, 2 * num_gridpz_m, real, work);
136
137 if (!normalize_m) {
138 Bz_max = 1.0;
139 }
140 // normalize to Bz_max = 1 A/m
141 FourCoefs_m[0] = RealValues[0] / (Bz_max * 2. * num_gridpz_m);
142 for (int i = 1; i < 2 * accuracy_m - 1; i++) {
143 FourCoefs_m[i] = RealValues[i] / (Bz_max * num_gridpz_m);
144 }
145
146 gsl_spline_free(Bz_interpolant);
147 gsl_interp_accel_free(Bz_accel);
148
149 gsl_fft_real_workspace_free(work);
150 gsl_fft_real_wavetable_free(real);
151
152 delete[] zvals;
153 delete[] RealValues;
154
155 *ippl::Info << level3 << typeset_msg("read in fieldmap '" + Filename_m + "'", "info")
156 << endl;
157 }
158}
159
161 if (FourCoefs_m != nullptr) {
162 delete[] FourCoefs_m;
163 FourCoefs_m = nullptr;
164
165 *ippl::Info << level3 << typeset_msg("freed fieldmap '" + Filename_m + "'", "info") << endl;
166 }
167}
168
171 // do fourier interpolation in z-direction
172 const double RR2 = R(0) * R(0) + R(1) * R(1);
173
174 const double kz = Physics::two_pi * (R(2) - zbegin_m) / length_m + Physics::pi;
175
176 double ez = FourCoefs_m[0];
177 double ezp = 0.0;
178 double ezpp = 0.0;
179 double ezppp = 0.0;
180
181 int n = 1;
182 for (int l = 1; l < accuracy_m; l++, n += 2) {
183 double somefactor_base = Physics::two_pi / length_m * l; // = \frac{d(kz*l)}{dz}
184 double somefactor = 1.0;
185 double coskzl = cos(kz * l);
186 double sinkzl = sin(kz * l);
187 ez += (FourCoefs_m[n] * coskzl - FourCoefs_m[n + 1] * sinkzl);
188 somefactor *= somefactor_base;
189 ezp += somefactor * (-FourCoefs_m[n] * sinkzl - FourCoefs_m[n + 1] * coskzl);
190 somefactor *= somefactor_base;
191 ezpp += somefactor * (-FourCoefs_m[n] * coskzl + FourCoefs_m[n + 1] * sinkzl);
192 somefactor *= somefactor_base;
193 ezppp += somefactor * (FourCoefs_m[n] * sinkzl + FourCoefs_m[n + 1] * coskzl);
194 }
195 // expand the field off-axis
196 const double BfieldR = -ezp / 2. + ezppp / 16. * RR2;
197
198 B(0) += BfieldR * R(0);
199 B(1) += BfieldR * R(1);
200 B(2) += ez - ezpp * RR2 / 4.;
201
202 return false;
203}
204
207 const DiffDirection& /*dir*/) const {
208 return false;
209}
210
211void Astra1DMagnetoStatic::getFieldDimensions(double& zBegin, double& zEnd) const {
212 zBegin = zbegin_m;
213 zEnd = zend_m;
214}
216 double& /*xIni*/, double& /*xFinal*/, double& /*yIni*/, double& /*yFinal*/, double& /*zIni*/,
217 double& /*zFinal*/) const {
218}
219
222
224 (*msg) << Filename_m << " (1D magnetostatic); zini= " << zbegin_m << " m; zfinal= " << zend_m
225 << " m;" << endl;
226}
227
229 return 0.0;
230}
231
233}
ippl::Vector< T, Dim > Vector_t
@ TAstraMagnetoStatic
Definition Fieldmap.h:22
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
std::string toUpper(const std::string &str)
Definition Util.cpp:145
virtual void getInfo(Inform *)
virtual void setFrequency(double freq)
virtual void getFieldDimensions(double &zBegin, double &zEnd) const
virtual bool getFieldstrength(const Vector_t< double, 3 > &R, Vector_t< double, 3 > &E, Vector_t< double, 3 > &B) const
Astra1DMagnetoStatic(std::string aFilename)
virtual bool getFieldDerivative(const Vector_t< double, 3 > &R, Vector_t< double, 3 > &E, Vector_t< double, 3 > &B, const DiffDirection &dir) const
virtual double getFrequency() const
MapType Type
Definition Fieldmap.h:118
void disableFieldmapWarning()
Definition Fieldmap.cpp:569
bool normalize_m
Definition Fieldmap.h:123
int lines_read_m
Definition Fieldmap.h:121
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