OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
Astra1DMagnetoStatic.cpp
Go to the documentation of this file.
2#include "Fields/Fieldmap.hpp"
4#include "Physics/Physics.h"
7#include "Utilities/Util.h"
8
9#include <algorithm>
10#include <cmath>
11#include <fstream>
12#include <sstream>
13
28Astra1DMagnetoStatic::Astra1DMagnetoStatic(const std::string& filename) : Fieldmap(filename) {
29 std::ifstream file;
30 std::string tmpString;
31 double tmpDouble;
32 // int skippedValues = 0;
33
35
36 // open field map, parse it and disable element on error
37 file.open(Filename_m.c_str());
38 if (file.good()) {
39 bool parsing_passed = true;
40 try {
41 parsing_passed = interpretLine<std::string, int>(file, tmpString, accuracy_m);
42 } catch (GeneralOpalException& e) {
43 parsing_passed = interpretLine<std::string, int, std::string>(
44 file, tmpString, accuracy_m, tmpString);
45
46 tmpString = Util::toUpper(tmpString);
47 if (tmpString != "TRUE" && tmpString != "FALSE")
49 "Astra1DMagnetoStatic::Astra1DMagnetoStatic",
50 "The third string on the first line of 1D field maps "
51 "has to be either TRUE or FALSE");
52
53 normalize_m = (tmpString == "TRUE");
54 }
55
56 int acceptedValues = 0;
57
58 parsing_passed = parsing_passed && interpretLine<double, double>(file, zbegin_m, tmpDouble);
59
60 double lastAcceptedZ = zbegin_m;
61
62 if (parsing_passed) {
63 ++acceptedValues;
65 }
66
67 while (true) {
68 const bool line_ok = interpretLine<double, double>(file, zend_m, tmpDouble, false);
69 if (!line_ok) {
70 break;
71 }
72
73 if (zend_m - lastAcceptedZ > 1e-10) {
74 lastAcceptedZ = zend_m;
75 ++acceptedValues;
76 }
77 }
78
79 num_gridpz_m = acceptedValues;
80 lines_read_m = 0;
81
82 if (!parsing_passed && !file.eof()) {
84 zend_m = zbegin_m - 1e-3;
86 "Astra1DMagnetoStatic::Astra1DMagnetoStatic",
87 "Error reading fieldmap '" + Filename_m + "'");
88 }
89
90 if (num_gridpz_m < 2) {
92 "Astra1DMagnetoStatic::Astra1DMagnetoStatic",
93 "Fieldmap must contain at least two valid sampling points");
94 }
95 length_m = 2.0 * num_gridpz_m * (zend_m - zbegin_m) / (num_gridpz_m - 1);
96
97 file.close();
98 } else {
100 zbegin_m = 0.0;
101 zend_m = -1e-3;
102 }
103}
104
106
108 if (FourCoefs_m.extent(0) != 0) {
109 return;
110 }
111
112 if (num_gridpz_m < 2) {
114 "Astra1DMagnetoStatic::readMap",
115 "Fieldmap must contain at least two valid sampling points");
116 }
117
118 std::ifstream in(Filename_m.c_str());
119 if (!in.good()) {
121 "Astra1DMagnetoStatic::readMap", "Cannot open fieldmap '" + Filename_m + "'");
122 }
123
124 const double dz = (zend_m - zbegin_m) / (num_gridpz_m - 1);
125
126 // CPU arrays - GSL (FFT + spline) is CPU-only
127 double* RealValues = new double[2 * num_gridpz_m];
128 double* zvals = new double[num_gridpz_m];
129
130 for (int i = 0; i < 2 * num_gridpz_m; ++i) {
131 RealValues[i] = 0.0;
132 }
133
134 for (int i = 0; i < num_gridpz_m; ++i) {
135 zvals[i] = 0.0;
136 }
137
140
141 const int size = 2 * accuracy_m - 1;
142 FourCoefs_m = Kokkos::DualView<double*>("FourCoefs", size);
143 auto coefs = FourCoefs_m.view_host();
144
145 std::string tmpString;
146 getLine(in, tmpString);
147
148 double Bz_max = 0.0;
149 double lastAcceptedZ = zbegin_m - dz;
150 int accepted = 0;
151
152 while (accepted < num_gridpz_m) {
153 double ztmp = 0.0;
154 double bztmp = 0.0;
155
156 const bool ok = interpretLine<double, double>(in, ztmp, bztmp, false);
157 if (!ok) {
158 break;
159 }
160
161 if (ztmp - lastAcceptedZ > 1e-10) {
162 zvals[accepted] = ztmp;
163 RealValues[accepted] = bztmp;
164 Bz_max = std::max(Bz_max, std::abs(bztmp));
165 lastAcceptedZ = ztmp;
166 ++accepted;
167 }
168 }
169 in.close();
170
171 if (accepted != num_gridpz_m) {
172 gsl_spline_free(Bz_interpolant);
173 gsl_interp_accel_free(Bz_accel);
174 delete[] zvals;
175 delete[] RealValues;
176
177 std::ostringstream os;
178 os << "Mismatch between counted and parsed fieldmap points in '" << Filename_m
179 << "': expected " << num_gridpz_m << ", got " << accepted;
180 throw GeneralOpalException("Astra1DMagnetoStatic::readMap", os.str());
181 }
182
183 if (Bz_max == 0.0) {
184 gsl_spline_free(Bz_interpolant);
185 gsl_interp_accel_free(Bz_accel);
186 delete[] zvals;
187 delete[] RealValues;
188
190 "Astra1DMagnetoStatic::readMap",
191 "Maximum on-axis magnetic field is zero in fieldmap '" + Filename_m + "'");
192 }
193
194 gsl_spline_init(Bz_interpolant, zvals, RealValues, num_gridpz_m);
195
196 int ii = num_gridpz_m;
197 for (int i = 0; i < num_gridpz_m - 1; ++i, ++ii) {
198 const double z = zbegin_m + dz * i;
199 RealValues[ii] = gsl_spline_eval(Bz_interpolant, z, Bz_accel);
200 }
201
202 // Ensure periodicity by mirroring
203 RealValues[ii++] = RealValues[num_gridpz_m - 1];
204 --ii;
205 for (int i = 0; i < num_gridpz_m; ++i, --ii) {
206 RealValues[i] = RealValues[ii];
207 }
208
209 // Disable normalization if requested
210 const double norm = normalize_m ? Bz_max : 1.0;
211
212 // Compute Fourier coefficients explicitly from the mirrored periodic samples.
213 const int M = 2 * num_gridpz_m;
214
215 double a0 = 0.0;
216 for (int j = 0; j < M; ++j) {
217 a0 += RealValues[j];
218 }
219 coefs(0) = a0 / (norm * M);
220
221 for (int l = 1; l < accuracy_m; ++l) {
222 double a_l = 0.0;
223 double b_l = 0.0;
224
225 for (int j = 0; j < M; ++j) {
226 const double theta = Physics::two_pi * double(j) / double(M);
227 a_l += RealValues[j] * std::cos(l * theta);
228 b_l += RealValues[j] * std::sin(l * theta);
229 }
230
231 a_l *= 2.0 / double(M);
232 b_l *= 2.0 / double(M);
233
234 const int n = 2 * l - 1;
235
236 coefs(n) = a_l / norm;
237 coefs(n + 1) = -b_l / norm;
238 }
239
240 gsl_spline_free(Bz_interpolant);
241 gsl_interp_accel_free(Bz_accel);
242
243 delete[] zvals;
244 delete[] RealValues;
245
246 FourCoefs_m.modify<Kokkos::HostSpace>();
247 FourCoefs_m.sync<Kokkos::DefaultExecutionSpace>();
248
249 Inform m("Astra1DMagnetoStatic::readMap");
250 m << level3 << "Read in fieldmap '" << Filename_m << "'" << endl;
251}
252
254 if (FourCoefs_m.extent(0) != 0) {
255 FourCoefs_m = Kokkos::DualView<double*>();
256
257 Inform m("Astra1DMagnetoStatic::freeMap");
258 m << level3 << "Freed fieldmap '" << Filename_m << "'" << endl;
259 }
260}
261
267void Astra1DMagnetoStatic::applyField(std::shared_ptr<ParticleContainer_t> pc, double scale) {
268 const double zbegin = zbegin_m;
269 const double zend = zend_m;
270 const double length = length_m;
271 const int accuracy = accuracy_m;
272 const size_t nLocal = pc->getLocalNum();
273
274 auto FourCoefs_device = FourCoefs_m.view_device();
275
276 auto Rview = pc->R.getView();
277 auto Eview = pc->E.getView();
278 auto Bview = pc->B.getView();
279
280 Kokkos::parallel_for(
281 "Astra1DMagnetoStatic::applyField", nLocal, KOKKOS_LAMBDA(const size_t i) {
282 const auto& R = Rview(i);
283
284 if (R(2) >= zbegin && R(2) < zend) {
285 Vector_t<double, 3> localE(0.0);
286 Vector_t<double, 3> localB(0.0);
287
288 computeField(R, localE, localB, FourCoefs_device, zbegin, length, accuracy);
289
290 Eview(i) += scale * localE;
291 Bview(i) += scale * localB;
292 }
293 });
294}
295
307 if (isInside(R)) {
308 computeField(R, E, B, FourCoefs_m.view_host(), zbegin_m, length_m, accuracy_m);
309
310 return false;
311 }
312
313 return true;
314}
315
328 const DiffDirection& /*dir*/) const {
329 return false;
330}
331
332void Astra1DMagnetoStatic::getFieldDimensions(double& zBegin, double& zEnd) const {
333 zBegin = zbegin_m;
334 zEnd = zend_m;
335}
336
338 double& /*xIni*/, double& /*xFinal*/, double& /*yIni*/, double& /*yFinal*/,
339 double& /*zIni*/, double& /*zFinal*/) const {
340 throw GeneralOpalException("Astra1DMagnetoStatic::getFieldDimensions", "not implemented");
341}
342
344
346 (*msg) << Filename_m << " (1D magnetostatic); zini= " << zbegin_m << " m; zfinal= " << zend_m
347 << " m;" << endl;
348}
349
351 throw GeneralOpalException("Astra1DMagnetoStatic::getFrequency", "not implemented");
352}
353
355 throw GeneralOpalException("Astra1DMagnetoStatic::setFrequency", "not implemented");
356}
ippl::Vector< T, Dim > Vector_t
@ TAstraMagnetoStatic
Definition Fieldmap.h:21
DiffDirection
Definition Fieldmap.h:54
constexpr int gsl_interp_cspline
Definition GSLSpline.h:26
double gsl_spline_eval(const gsl_spline *spline, const double x, gsl_interp_accel *accel)
Evaluate a spline at x using an accelerator.
Definition GSLSpline.h:66
gsl_interp_accel * gsl_interp_accel_alloc()
Allocate an interpolation accelerator.
Definition GSLSpline.h:50
void gsl_spline_init(gsl_spline *spline, const double *x, const double *y, const size_t n)
Initialize a spline with tabulated data.
Definition GSLSpline.h:57
void gsl_spline_free(const gsl_spline *spline)
Free a spline instance.
Definition GSLSpline.h:83
void gsl_interp_accel_free(const gsl_interp_accel *accel)
Free an accelerator instance.
Definition GSLSpline.h:87
gsl_spline * gsl_spline_alloc(const int type, size_t)
Allocate a spline instance (size ignored).
Definition GSLSpline.h:38
Template PIC bunch: IPPL PicManager, shared field mesh/solver, and multiple particle containers.
Accelerator caching last interval indices.
Base class for the linear and cubic interpolation spline classes.
bool isInside(const Vector_t< double, 3 > &r) const override
Check if a point is inside the field map.
Astra1DMagnetoStatic(const std::string &filename)
Constructor for 1D magnetostatic field map.
double getFrequency() const override
Get the frequency.
static KOKKOS_INLINE_FUNCTION void computeField(const Vector_t< double, 3 > &R, Vector_t< double, 3 > &, Vector_t< double, 3 > &B, const ViewType &FourCoefs, double zbegin, double length, int accuracy)
Kokkos::DualView< double * > FourCoefs_m
void swap() override
Swap coordinates (implementation dependent).
void freeMap() override
Pure virtual method to free the map data.
void applyField(std::shared_ptr< ParticleContainer_t > pc, double scale) override
Apply the FM to all the particles.
void getInfo(Inform *msg) override
Print info about the field map.
void getFieldDimensions(double &zBegin, double &zEnd) const override
Get the longitudinal dimensions of the field.
bool getFieldstrength(const Vector_t< double, 3 > &R, Vector_t< double, 3 > &E, Vector_t< double, 3 > &B) const override
Get the fieldstrength at position R.
bool getFieldDerivative(const Vector_t< double, 3 > &R, Vector_t< double, 3 > &E, Vector_t< double, 3 > &B, const DiffDirection &dir) const override
Get the derivative of the field at position R.
void setFrequency(double freq) override
Set the frequency.
void readMap() override
Pure virtual method to read the map data. Called by the public static readMap().
Abstract base class for all field maps. It acts as a factory for creating specific field map types ba...
Definition Fieldmap.h:62
MapType Type
Definition Fieldmap.h:231
void disableFieldmapWarning()
Definition Fieldmap.cpp:489
bool normalize_m
Definition Fieldmap.h:236
int lines_read_m
Definition Fieldmap.h:234
std::string Filename_m
Definition Fieldmap.h:233
void getLine(std::ifstream &in, std::string &buffer)
Definition Fieldmap.h:237
void noFieldmapWarning()
Definition Fieldmap.cpp:496
constexpr double two_pi
The value of.
Definition Physics.h:40
std::string toUpper(const std::string &str)
Definition Util.cpp:141