OPAL (Object Oriented Parallel Accelerator Library)  2024.1
OPAL
FM1DProfile2.cpp
Go to the documentation of this file.
1 #include "Fields/FM1DProfile2.h"
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),
17  cosExitRotation_m(1.0),
18  sinExitRotation_m(0.0) {
19 
20  int tmpInt;
21  std::string tmpString;
22  double tmpDouble;
23  int num_gridpz = -1;
24 
25  Type = T1DProfile2;
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,
34  gapHeight_m);
35  parsing_passed = parsing_passed &&
36  interpretLine<double, double, double, int>(file,
40  num_gridpz);
41  parsing_passed = parsing_passed &&
42  interpretLine<double, double, double, int>(file,
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) {
60  zend_exit_m = zbegin_entry_m - 1e-3;
61  zend_entry_m = zbegin_entry_m - 1e-3;
62  zbegin_exit_m = zbegin_entry_m - 1e-3;
63  } else {
64  // conversion cm to m
65  zbegin_entry_m *= Units::cm2m;
66  zend_entry_m *= Units::cm2m;
67  polynomialOrigin_entry_m *= Units::cm2m;
68  zbegin_exit_m *= Units::cm2m;
69  zend_exit_m *= Units::cm2m;
70  polynomialOrigin_exit_m *= Units::cm2m;
72  }
73  length_m = zend_exit_m - zbegin_entry_m;
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 
90 FM1DProfile2 _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 
120  EngeCoefs_entry_m = new double[polynomialOrder_entry_m + 1];
121  EngeCoefs_exit_m = new double[polynomialOrder_exit_m + 1];
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);
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 
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 
327 bool _FM1DProfile2::getFieldDerivative(const Vector_t &/*R*/, Vector_t &/*E*/, Vector_t &/*B*/, const DiffDirection &/*dir*/) const {
328  return false;
329 }
330 
331 void _FM1DProfile2::getFieldDimensions(double &zBegin, double &zEnd) const {
332  zBegin = zbegin_entry_m;
333  zEnd = zend_exit_m;
334 }
335 void _FM1DProfile2::getFieldDimensions(double &/*xIni*/, double &/*xFinal*/, double &/*yIni*/, double &/*yFinal*/, double &/*zIni*/, double &/*zFinal*/) const {}
336 
338 {}
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 
348 void _FM1DProfile2::setFrequency(double /*freq*/)
349 {}
350 
351 void _FM1DProfile2::setExitFaceSlope(const double &m) {
352  exit_slope_m = m;
353 }
354 
355 void _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 
366 namespace QRDecomposition {
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 }
double * EngeCoefs_entry_m
Definition: FM1DProfile2.h:30
virtual void setFrequency(double freq)
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
void solve(double *Matrix, double *Solution, double *rightHandSide, const int &M, const int &N)
MapType Type
Definition: Fieldmap.h:115
virtual double getFrequency() const
DiffDirection
Definition: Fieldmap.h:55
virtual void getInfo(Inform *)
double cosExitRotation_m
Cos and sin of the exit edge rotation with respect to the local coordinates.
Definition: FM1DProfile2.h:58
void noFieldmapWarning()
Definition: Fieldmap.cpp:618
double gapHeight_m
Definition: FM1DProfile2.h:47
virtual void setExitFaceSlope(const double &)
Matrix.
Definition: Matrix.h:39
double * EngeCoefs_exit_m
Definition: FM1DProfile2.h:31
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6
constexpr double cm2m
Definition: Units.h:35
double polynomialOrigin_entry_m
Definition: FM1DProfile2.h:35
int lines_read_m
Definition: Fieldmap.h:119
double xExit_m
Definition: FM1DProfile2.h:51
static std::string typeset_msg(const std::string &msg, const std::string &title)
Definition: Fieldmap.cpp:649
Tps< T > exp(const Tps< T > &x)
Exponential.
Definition: TpsMath.h:165
double zend_entry_m
Definition: FM1DProfile2.h:34
bool info
Info flag.
Definition: Options.cpp:28
#define INFOMSG(msg)
Definition: IpplInfo.h:348
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
bool interpreteEOF(std::ifstream &in)
Definition: Fieldmap.cpp:555
virtual void readMap()
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:84
double sinExitRotation_m
Definition: FM1DProfile2.h:59
double zend_exit_m
Definition: FM1DProfile2.h:40
static FM1DProfile2 create(const std::string &filename)
virtual void swap()
int polynomialOrder_exit_m
Definition: FM1DProfile2.h:42
Definition: Inform.h:42
int polynomialOrder_entry_m
Definition: FM1DProfile2.h:36
std::shared_ptr< _FM1DProfile2 > FM1DProfile2
Definition: Definitions.h:48
double zbegin_entry_m
Definition: FM1DProfile2.h:33
void disableFieldmapWarning()
Definition: Fieldmap.cpp:610
double polynomialOrigin_exit_m
Definition: FM1DProfile2.h:41
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
Tps< T > log(const Tps< T > &x)
Natural logarithm.
Definition: TpsMath.h:182
virtual void freeMap()
double exit_slope_m
Definition: FM1DProfile2.h:38
_FM1DProfile2(const std::string &filename)
Inform & level3(Inform &inf)
Definition: Inform.cpp:47
virtual ~_FM1DProfile2()
virtual bool getFieldDerivative(const Vector_t &X, Vector_t &E, Vector_t &B, const DiffDirection &dir) const
constexpr double e
The value of .
Definition: Physics.h:39
std::string Filename_m
Definition: Fieldmap.h:118
virtual void setEdgeConstants(const double &bendAngle, const double &entranceAngle, const double &exitAngle)
double zExit_m
Definition: FM1DProfile2.h:55
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
virtual void getFieldDimensions(double &zBegin, double &zEnd) const
virtual bool getFieldstrength(const Vector_t &X, Vector_t &strength, Vector_t &info) const
double length_m
Definition: FM1DProfile2.h:46
double zbegin_exit_m
Definition: FM1DProfile2.h:39