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