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