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