OPALX (Object Oriented Parallel Accelerator Library for Exascal) MINIorX
OPALX
FM1DProfile2.cpp
Go to the documentation of this file.
2#include "Fields/Fieldmap.hpp"
3#include "Physics/Physics.h"
4#include "Physics/Units.h"
5
6#include <cmath>
7#include <fstream>
8#include <ios>
9
10FM1DProfile2::FM1DProfile2(std::string aFilename)
11 : Fieldmap(aFilename),
12 EngeCoefs_entry_m(nullptr),
13 EngeCoefs_exit_m(nullptr),
14 exit_slope_m(0.0),
15 xExit_m(0.0),
16 zExit_m(0.0),
19 int tmpInt;
20 std::string tmpString;
21 double tmpDouble;
22 int num_gridpz = -1;
23
25 std::ifstream file(Filename_m.c_str());
26
27 if (file.good()) {
30 parsing_passed =
31 parsing_passed
34 parsing_passed = parsing_passed
37 for (int i = 0; (i < num_gridpz + 1) && parsing_passed; ++i) {
38 parsing_passed = parsing_passed && interpretLine<double>(file, tmpDouble);
39 }
40
41 parsing_passed = parsing_passed && interpreteEOF(file);
42
43 file.close();
44 lines_read_m = 0;
45
46 if (!parsing_passed) {
51 } else {
52 // conversion cm to m
60 }
62 } else {
64 zbegin_entry_m = 0.0;
68 }
69}
70
72 if (EngeCoefs_entry_m != nullptr) {
73 delete[] EngeCoefs_entry_m;
74 delete[] EngeCoefs_exit_m;
75 }
76}
77
79 if (EngeCoefs_entry_m == nullptr) {
80 double tolerance = 1e-8;
81
82 std::ifstream in(Filename_m.c_str());
83
84 int tmpInt;
85 std::string tmpString;
86 double tmpDouble;
87
88 double minValue = 99999999.99, maxValue = -99999999.99;
89 int num_gridpz;
90 int num_gridp_fringe_entry, num_gridp_fringe_exit;
91 int num_gridp_before_fringe_entry, num_gridp_before_fringe_exit;
92 double* RealValues;
93 double* rightHandSide;
94 double* leastSquareMatrix;
95 double dZ;
96
97 interpretLine<std::string, int, int, double>(in, tmpString, tmpInt, tmpInt, tmpDouble);
98 interpretLine<double, double, double, int>(in, tmpDouble, tmpDouble, tmpDouble, num_gridpz);
99 interpretLine<double, double, double, int>(in, tmpDouble, tmpDouble, tmpDouble, tmpInt);
100
101 dZ = length_m / num_gridpz;
102
105
106 RealValues = new double[num_gridpz + 1];
107
108 for (int i = 0; i < num_gridpz + 1; ++i) {
109 interpretLine<double>(in, RealValues[i]);
110 if (RealValues[i] > maxValue)
111 maxValue = RealValues[i];
112 else if (RealValues[i] < minValue)
113 minValue = RealValues[i];
114 }
115 in.close();
116
117 // normalise the values //
118 for (int i = 0; i < num_gridpz + 1; ++i)
119 RealValues[i] = (RealValues[i] - minValue) / (maxValue - minValue);
120
121 // find begin of entry fringe field //
122 int i = 0;
123 while (i < num_gridpz + 1 && RealValues[i] < tolerance)
124 ++i;
125 num_gridp_before_fringe_entry = i - 1;
126
127 // find end of entry fringe field //
128 while (i < num_gridpz + 1 && RealValues[i] < 1. - tolerance)
129 ++i;
130 num_gridp_fringe_entry = i - 1 - num_gridp_before_fringe_entry;
131
132 // find begin of exit fringe field //
133 while (i < num_gridpz + 1 && RealValues[i] >= 1. - tolerance)
134 ++i;
135 num_gridp_before_fringe_exit = i - 1;
136
137 while (i < num_gridpz + 1 && RealValues[i] > tolerance)
138 ++i;
139 num_gridp_fringe_exit = i - 1 - num_gridp_before_fringe_exit;
140
141 // set the origin of the polynomials
142
143 int num_gridp_fringe = std::max(num_gridp_fringe_entry, num_gridp_fringe_exit);
144 int polynomialOrder = std::max(polynomialOrder_entry_m, polynomialOrder_exit_m);
145 leastSquareMatrix = new double[(polynomialOrder + 1) * num_gridp_fringe];
146 rightHandSide = new double[num_gridp_fringe];
147
148 double first =
149 polynomialOrigin_entry_m - zbegin_entry_m - dZ * (num_gridp_before_fringe_entry + 1);
150 for (int i = 0; i < num_gridp_fringe_entry; ++i) {
151 double powerOfZ = 1.;
152 double Z = (first - dZ * i) / gapHeight_m;
153 rightHandSide[i] = log(1. / RealValues[num_gridp_before_fringe_entry + i + 1] - 1.);
154 for (int j = 0; j < polynomialOrder_entry_m + 1; ++j) {
155 leastSquareMatrix[i * (polynomialOrder_entry_m + 1) + j] = powerOfZ;
156 powerOfZ *= Z;
157 }
158 }
159
161 leastSquareMatrix, EngeCoefs_entry_m, rightHandSide, num_gridp_fringe_entry,
163
164 first = polynomialOrigin_exit_m - zbegin_entry_m - dZ * (num_gridp_before_fringe_exit + 1);
165 for (int i = 0; i < num_gridp_fringe_exit; ++i) {
166 double powerOfZ = 1.;
167 double Z = (dZ * i - first) / gapHeight_m;
168 rightHandSide[i] = log(1. / RealValues[num_gridp_before_fringe_exit + i + 1] - 1.);
169 for (int j = 0; j < polynomialOrder_exit_m + 1; ++j) {
170 leastSquareMatrix[i * (polynomialOrder_exit_m + 1) + j] = powerOfZ;
171 powerOfZ *= Z;
172 }
173 }
175 leastSquareMatrix, EngeCoefs_exit_m, rightHandSide, num_gridp_fringe_exit,
177
178 zbegin_exit_m = zbegin_entry_m + num_gridp_before_fringe_exit * dZ;
179 zend_exit_m = zbegin_exit_m + num_gridp_fringe_exit * dZ;
180 zbegin_entry_m += num_gridp_before_fringe_entry * dZ;
181 zend_entry_m = zbegin_entry_m + num_gridp_fringe_entry * dZ;
182
183 delete[] RealValues;
184 delete[] leastSquareMatrix;
185 delete[] rightHandSide;
186
187 *ippl::Info << level3 << typeset_msg("read in fieldmap '" + Filename_m + "'", "info")
188 << "\n"
189 << endl;
190 }
191}
192
194 if (EngeCoefs_entry_m != nullptr) {
195 delete[] EngeCoefs_entry_m;
196 delete[] EngeCoefs_exit_m;
197
198 *ippl::Info << level3 << typeset_msg("freed fieldmap '" + Filename_m + "'", "info") << "\n"
199 << endl;
200 }
201}
202
204 const Vector_t<double, 3>& R, Vector_t<double, 3>& strength, Vector_t<double, 3>& info) const {
205 info = Vector_t<double, 3>(0.0);
206
207 // Find coordinates in the entrance frame.
208 Vector_t<double, 3> REntrance(R(0), 0.0, R(2) + zbegin_entry_m);
209
210 // Find coordinates in the exit frame.
211 Vector_t<double, 3> RExit(0.0, R(1), 0.0);
212
213 RExit(0) = (R(0) - xExit_m) * cosExitRotation_m
215 RExit(2) = (R(0) - xExit_m) * sinExitRotation_m
217
218 if (REntrance(2) >= zend_entry_m && RExit(2) <= zbegin_exit_m) {
219 strength = Vector_t<double, 3>(1.0, 0.0, 0.0);
220 } else {
221 double d2Sdz2 = 0.0;
222 double z;
223 double* EngeCoefs;
224 int polynomialOrder;
225 info(0) = 1.0;
226 if (REntrance(2) >= zbegin_entry_m && REntrance(2) < zend_entry_m) {
227 z = -(REntrance(2) - polynomialOrigin_entry_m) / gapHeight_m;
228 EngeCoefs = EngeCoefs_entry_m;
229 polynomialOrder = polynomialOrder_entry_m;
230 } else if (RExit(2) > zbegin_exit_m && RExit(2) <= zend_exit_m) {
231 z = (RExit(2) - polynomialOrigin_exit_m) / gapHeight_m;
232 EngeCoefs = EngeCoefs_exit_m;
233 polynomialOrder = polynomialOrder_exit_m;
234 info(1) = 1.0;
235 } else {
236 return true;
237 }
238
239 double S = EngeCoefs[polynomialOrder] * z;
240 S += EngeCoefs[polynomialOrder - 1];
241 double dSdz = polynomialOrder * EngeCoefs[polynomialOrder];
242
243 for (int i = polynomialOrder - 2; i >= 0; i--) {
244 S = S * z + EngeCoefs[i];
245 dSdz = dSdz * z + (i + 1) * EngeCoefs[i + 1];
246 d2Sdz2 = d2Sdz2 * z + (i + 2) * (i + 1) * EngeCoefs[i + 2];
247 }
248 double expS = std::exp(S);
249 double f = 1.0 / (1.0 + expS);
250 if (f > 1.e-30) {
251 // First derivative of Enge function, f.
252 double dfdz = -f * ((f * expS) * dSdz);
253
254 // Second derivative of Enge functioin, f.
255 double d2fdz2 = ((-d2Sdz2 - dSdz * dSdz * (1. - 2. * (expS * f))) * (f * expS) * f)
257
258 strength(0) = f;
259 strength(1) = dfdz / gapHeight_m;
260 strength(2) = d2fdz2;
261 } else {
262 strength = Vector_t<double, 3>(0.0);
263 }
264 }
265 info(2) = exit_slope_m;
266
267 return true;
268
269 // info = Vector_t<double, 3>(0.0);
270 // const Vector_t<double, 3> tmpR(R(0), R(1), R(2) + zbegin_entry_m);
271 //
272 // if (tmpR(2) >= zend_entry_m && tmpR(2) <= exit_slope_m * tmpR(0) + zbegin_exit_m) {
273 // strength = Vector_t<double, 3>(1.0, 0.0, 0.0);
274 // info(0) = 3.0;
275 // } else {
276 // double S, dSdz, d2Sdz2 = 0.0;
277 // double expS, f, dfdz, d2fdz2;
278 // double z;
279 // double *EngeCoefs;
280 // int polynomialOrder;
281 // if (tmpR(2) >= zbegin_entry_m && tmpR(2) < zend_entry_m) {
282 // z = -(tmpR(2) - polynomialOrigin_entry_m) / gapHeight_m;
283 // EngeCoefs = EngeCoefs_entry_m;
284 // polynomialOrder = polynomialOrder_entry_m;
285 // info(0) = 1.0;
286 // } else if (tmpR(2) > exit_slope_m * tmpR(0) + zbegin_exit_m && tmpR(2) <= exit_slope_m
287 // * tmpR(0) + zend_exit_m) {
288 // z = (tmpR(2) - exit_slope_m * tmpR(0) - polynomialOrigin_exit_m) /
289 // sqrt(exit_slope_m * exit_slope_m + 1) / gapHeight_m; EngeCoefs = EngeCoefs_exit_m;
290 // polynomialOrder = polynomialOrder_exit_m;
291 // info(0) = 2.0;
292 // } else {
293 // return true;
294 // }
295 //
296 // S = EngeCoefs[polynomialOrder] * z;
297 // S += EngeCoefs[polynomialOrder - 1];
298 // dSdz = polynomialOrder * EngeCoefs[polynomialOrder];
299 //
300 // for (int i = polynomialOrder - 2; i >= 0; i--) {
301 // S = S * z + EngeCoefs[i];
302 // dSdz = dSdz * z + (i + 1) * EngeCoefs[i+1];
303 // d2Sdz2 = d2Sdz2 * z + (i + 2) * (i + 1) * EngeCoefs[i+2];
304 // }
305 // expS = exp(S);
306 // f = 1.0 / (1.0 + expS);
307 // if (f > 1.e-30) {
308 // dfdz = - f * ((f * expS) * dSdz); // first derivative of f
309 // d2fdz2 = ((-d2Sdz2 - dSdz * dSdz * (1. - 2. * (expS * f))) * (f * expS) * f) /
310 // (gapHeight_m * gapHeight_m); // second derivative of f
311 //
312 // strength(0) = f;
313 // strength(1) = dfdz / gapHeight_m;
314 // strength(2) = d2fdz2;
315 // } else {
316 // strength = Vector_t<double, 3>(0.0);
317 // }
318 //
319 // }
320 // info(1) = exit_slope_m;
321 // return true;
322}
323
326 const DiffDirection& /*dir*/) const {
327 return false;
328}
329
330void FM1DProfile2::getFieldDimensions(double& zBegin, double& zEnd) const {
331 zBegin = zbegin_entry_m;
332 zEnd = zend_exit_m;
333}
335 double& /*xIni*/, double& /*xFinal*/, double& /*yIni*/, double& /*yFinal*/, double& /*zIni*/,
336 double& /*zFinal*/) const {
337}
338
340}
341
342void FM1DProfile2::getInfo(Inform* msg) {
343 (*msg) << Filename_m << " (1D Profile type 2); zini= " << zbegin_entry_m
344 << " m; zfinal= " << zend_exit_m << " m;" << endl;
345}
346
348 return 0.0;
349}
350
351void FM1DProfile2::setFrequency(double /*freq*/) {
352}
353
354void FM1DProfile2::setExitFaceSlope(const double& m) {
355 exit_slope_m = m;
356}
357
359 const double& bendAngle, const double& entranceAngle, const double& exitAngle) {
361
362 zExit_m = polynomialOrigin_entry_m + deltaZ * std::cos(bendAngle / 2.0);
363 xExit_m = -deltaZ * std::sin(bendAngle / 2.0);
364
365 cosExitRotation_m = std::cos(-bendAngle + entranceAngle + exitAngle);
366 sinExitRotation_m = std::sin(-bendAngle + entranceAngle + exitAngle);
367}
368
370 void solve(
371 double* Matrix, double* Solution, double* rightHandSide, const int& M, const int& N) {
372 double sinphi;
373 double cosphi;
374 double tempValue;
375 double len;
376 double* R = new double[M * N];
377 double* tempVector = new double[M];
378 double* residuum = new double[M];
379
380 for (int i = 0; i < M; ++i) {
381 for (int j = 0; j < N; ++j)
382 R[i * N + j] = Matrix[i * N + j];
383 tempVector[i] = rightHandSide[i];
384 }
385
386 /* using Givens rotations */
387 for (int i = 0; i < N; ++i) {
388 for (int j = i + 1; j < M; ++j) {
389 len = std::sqrt(R[j * N + i] * R[j * N + i] + R[i * (N + 1)] * R[i * (N + 1)]);
390 sinphi = -R[j * N + i] / len;
391 cosphi = R[i * (N + 1)] / len;
392
393 for (int k = 0; k < N; ++k) {
394 tempValue = cosphi * R[i * N + k] - sinphi * R[j * N + k];
395 R[j * N + k] = sinphi * R[i * N + k] + cosphi * R[j * N + k];
396 R[i * N + k] = tempValue;
397 }
398 }
399 }
400
401 /* one step of iterative refinement */
402
403 // cout << "A^T*b" << endl;
404 for (int i = 0; i < N; ++i) { /* A^T*b */
405 tempValue = 0.0;
406 for (int j = 0; j < M; ++j) {
407 tempValue += Matrix[j * N + i] * rightHandSide[j];
408 }
409 Solution[i] = tempValue;
410 }
411 // cout << "R^-TA^T*b" << endl;
412 for (int i = 0; i < N; ++i) { /* R^-T*A^T*b */
413 tempValue = 0.0;
414 for (int j = 0; j < i; ++j)
415 tempValue += R[j * N + i] * residuum[j];
416 residuum[i] = (Solution[i] - tempValue) / R[i * (N + 1)];
417 }
418 // cout << "R^-1R^-TA^T*b" << endl;
419 for (int i = N - 1; i >= 0; --i) { /* R^-1*R^-T*A^T*b */
420 tempValue = 0.0;
421 for (int j = N - 1; j > i; --j)
422 tempValue += R[i * N + j] * Solution[j];
423 Solution[i] = (residuum[i] - tempValue) / R[i * (N + 1)];
424 }
425 // cout << "b - A*x" << endl;
426 for (int i = 0; i < M; ++i) {
427 tempValue = 0.0;
428 for (int j = 0; j < N; ++j)
429 tempValue += Matrix[i * N + j] * Solution[j];
430 residuum[i] = rightHandSide[i] - tempValue;
431 }
432 // cout << "A^T*r" << endl;
433 for (int i = 0; i < N; ++i) {
434 tempValue = 0.0;
435 for (int j = 0; j < M; ++j)
436 tempValue += Matrix[j * N + i] * residuum[j];
437 tempVector[i] = tempValue;
438 }
439 // cout << "R^-TA^T*r" << endl;
440 for (int i = 0; i < N; ++i) {
441 tempValue = 0.0;
442 for (int j = 0; j < i; ++j)
443 tempValue += R[j * N + i] * residuum[j];
444 residuum[i] = (tempVector[i] - tempValue) / R[i * (N + 1)];
445 }
446 // cout << "R^-1R^-TA^T*r" << endl;
447 for (int i = N - 1; i >= 0; --i) {
448 tempValue = 0.0;
449 for (int j = N - 1; j > i; --j)
450 tempValue += R[i * N + j] * tempVector[j];
451 tempVector[i] = (residuum[i] - tempValue) / R[i * (N + 1)];
452 Solution[i] += tempVector[i];
453 }
454
455 // for (int i = 0; i < N; ++i)
456 // cout << Solution[i] << endl;
457 // cout << endl;
458
459 delete[] residuum;
460 delete[] tempVector;
461 delete[] R;
462 }
463
464} // namespace QRDecomposition
ippl::Vector< T, Dim > Vector_t
@ T1DProfile2
Definition Fieldmap.h:24
DiffDirection
Definition Fieldmap.h:55
void solve(double *Matrix, double *Solution, double *rightHandSide, const int &M, const int &N)
constexpr double cm2m
Definition Units.h:35
MapType Type
Definition Fieldmap.h:118
bool interpreteEOF(std::ifstream &in)
Definition Fieldmap.cpp:516
void disableFieldmapWarning()
Definition Fieldmap.cpp:569
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 noFieldmapWarning()
Definition Fieldmap.cpp:576
double zend_entry_m
double cosExitRotation_m
Cos and sin of the exit edge rotation with respect to the local coordinates.
double zend_exit_m
double polynomialOrigin_entry_m
virtual bool getFieldstrength(const Vector_t< double, 3 > &X, Vector_t< double, 3 > &strength, Vector_t< double, 3 > &info) const
virtual bool getFieldDerivative(const Vector_t< double, 3 > &X, Vector_t< double, 3 > &E, Vector_t< double, 3 > &B, const DiffDirection &dir) const
double * EngeCoefs_entry_m
virtual double getFrequency() const
double polynomialOrigin_exit_m
double sinExitRotation_m
FM1DProfile2(std::string aFilename)
double zbegin_entry_m
friend class Fieldmap
double zbegin_exit_m
int polynomialOrder_entry_m
virtual void setFrequency(double freq)
double * EngeCoefs_exit_m
int polynomialOrder_exit_m
virtual void swap()
double gapHeight_m
double exit_slope_m
virtual void readMap()
virtual void setEdgeConstants(const double &bendAngle, const double &entranceAngle, const double &exitAngle)
virtual void getFieldDimensions(double &zBegin, double &zEnd) const
virtual void setExitFaceSlope(const double &)
double length_m
virtual void freeMap()
virtual void getInfo(Inform *)