OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
TrimCoilMirrored.cpp
Go to the documentation of this file.
2 
3 #include "Utility/IpplInfo.h"
5 
6 #include <cmath>
7 
9  double rmin,
10  double rmax,
11  double bslope):
12  TrimCoil(bmax, rmin, rmax)
13 {
14  // convert to m
15  const double mm2m = 0.001;
16  bslope_m = bslope / mm2m;
17 }
18 
19 void TrimCoilMirrored::doApplyField(const double r, const double z, const double phi_rad, double *br, double *bz)
20 {
22  // for some discussion on the formulas see
23  // http://doi.org/10.1103/PhysRevSTAB.14.054402
24  // https://gitlab.psi.ch/OPAL/src/issues/157
25  // https://gitlab.psi.ch/OPAL/src/issues/110
26 
27  // unitless constants
28  const double Amax1 = 1;
29  const double Amax2 = 3;
30  const double Amin = -2;
31  const double x01 = 4;
32  const double x02 = 8;
33  const double h1 = 0.03;
34  const double h2 = 0.2;
35  const double justAnotherFudgeFactor = 1 / 2.78;
36  // helper variables
37  const double log10 = std::log(10);
38  const double const3 = -(Amax1 - Amin) * h1 * log10;
39  const double const4 = (Amax2 - Amin) * h2 * log10;
40 
41  const double &tcr1 = rmin_m;
42  const double &tcr2 = rmax_m;
43  const double &slope = bslope_m;
44  const double &magnitude = bmax_m;
45 
46  double part1;
47  double part2;
48 
49  if (2 * r < (tcr2 + tcr1)) {
50  part1 = std::pow(10.0, ((r - tcr1) * slope - x01) * h1);
51  part2 = std::pow(10.0, -((r - tcr1) * slope - x02) * h2);
52  } else {
53  part1 = std::pow(10.0, ((tcr2 - r) * slope - x01) * h1);
54  part2 = std::pow(10.0, -((tcr2 - r) * slope - x02) * h2);
55  }
56 
57  const double part1plusinv = 1 / (1 + part1);
58  const double part2plusinv = 1 / (1 + part2);
59 
60  double part3 = const3 * slope * part1 * part1plusinv * part1plusinv;
61  double part4 = const4 * slope * part2 * part2plusinv * part2plusinv;
62 
63  const double constmag = magnitude * justAnotherFudgeFactor;
64 
65  double dr = constmag * (part3 + part4);
66  double btr = constmag * (Amin - 1 +
67  (Amax1 - Amin) * part1plusinv +
68  (Amax2 - Amin) * part2plusinv);
69 
70  if (std::isnan(dr) || std::isinf(dr) ||
71  std::isnan(btr) || std::isinf(btr)) {
72  ERRORMSG("r = " << r << " m, tcr1 = " << tcr1 << " m, tcr2 = " << tcr2 << " m\n");
73  ERRORMSG("slope = " << slope << ", magnitude = " << magnitude << " kG\n");
74  ERRORMSG("part1 = " << part1 << ", part2 = " << part2 << "\n");
75  ERRORMSG("part3 = " << part3 << ", part4 = " << part4 << endl);
76  throw GeneralClassicException("TrimCoilMirrored::doApplyField",
77  "dr or btr yield results that are either nan or inf");
78  }
79 
80  *bz -= btr;
81  *br -= dr * z;
82 }
double bmax_m
Maximum B field (kG)
Definition: TrimCoil.h:18
TrimCoilMirrored()=delete
#define ERRORMSG(msg)
Definition: IpplInfo.h:399
Tps< T > log(const Tps< T > &x)
Natural logarithm.
Definition: TpsMath.h:182
double rmax_m
Maximum radius (m)
Definition: TrimCoil.h:27
double bslope_m
Slope in (1 / mm)
Abstract TrimCoil class.
Definition: TrimCoil.h:8
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
Definition: TpsMath.h:76
double rmin_m
Minimum radius (m)
Definition: TrimCoil.h:25
T isnan(T x)
isnan function with adjusted return type
Definition: matheval.hpp:74
virtual void doApplyField(const double r, const double z, const double phi_rad, double *br, double *bz)
virtual implementation of applyField
PETE_TUTree< FnLog10, typename T::PETE_Expr_t > log10(const PETE_Expr< T > &l)
Definition: PETE.h:818
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
T isinf(T x)
isinf function with adjusted return type
Definition: matheval.hpp:78