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