OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
VerticalFFAMagnet.cpp
Go to the documentation of this file.
1 //
2 // Source file for VerticalFFAMagnet Component
3 //
4 // Copyright (c) 2019 Chris Rogers
5 // All rights reserved.
6 //
7 // OPAL is licensed under GNU GPL version 3.
8 //
9 
12 
14 
16  : Component(name), straightGeometry_m(1.) {
18 }
19 
21  : Component(right),
22  straightGeometry_m(right.straightGeometry_m),
23  dummy(right.dummy),
24  maxOrder_m(right.maxOrder_m),
25  k_m(right.k_m),
26  Bz_m(right.Bz_m),
27  zNegExtent_m(right.zNegExtent_m),
28  zPosExtent_m(right.zPosExtent_m),
29  halfWidth_m(right.halfWidth_m),
30  bbLength_m(right.bbLength_m),
31  endField_m(right.endField_m->clone()),
32  dfCoefficients_m(right.dfCoefficients_m) {
34 }
35 
36 
38 }
39 
41  VerticalFFAMagnet* magnet = new VerticalFFAMagnet(*this);
42  magnet->initialise();
43  return magnet;
44 }
45 
47  return dummy;
48 }
49 
51  return dummy;
52 }
53 
57 }
58 
59 void VerticalFFAMagnet::initialise(PartBunchBase<double, 3> *bunch, double &startField, double &endField) {
60  RefPartBunch_m = bunch;
61  initialise();
62 }
63 
65  RefPartBunch_m = NULL;
66 }
67 
69  return straightGeometry_m;
70 }
71 
73  return straightGeometry_m;
74 }
75 
77  visitor.visitVerticalFFAMagnet(*this);
78 }
79 
80 
82  if (abs(R[0]) > halfWidth_m ||
83  R[2] < 0. || R[2] > bbLength_m ||
84  R[1] < -zNegExtent_m || R[1] > zPosExtent_m) {
85  return true;
86  }
87  std::vector<double> fringeDerivatives(maxOrder_m+2, 0.);
88  double zRel = R[2]-bbLength_m/2.; // z relative to centre of magnet
89  for (size_t i = 0; i < fringeDerivatives.size(); ++i) {
90  fringeDerivatives[i] = endField_m->function(zRel, i); // d^i_phi f
91  }
92 
93  std::vector<double> x_n(maxOrder_m+1); // x^n
94  x_n[0] = 1.; // x^0
95  for (size_t i = 1; i < x_n.size(); ++i) {
96  x_n[i] = x_n[i-1]*R[0];
97  }
98 
99  // note that the last element is always 0, because dfCoefficients_m is
100  // of size maxOrder_m+1. This leads to better Maxwellianness in testing.
101  std::vector<double> f_n(maxOrder_m+2, 0.);
102  std::vector<double> dz_f_n(maxOrder_m+1, 0.);
103  for (size_t n = 0; n < dfCoefficients_m.size(); ++n) {
104  const std::vector<double>& coefficients = dfCoefficients_m[n];
105  for (size_t i = 0; i < coefficients.size(); ++i) {
106  f_n[n] += coefficients[i]*fringeDerivatives[i];
107  dz_f_n[n] += coefficients[i]*fringeDerivatives[i+1];
108  }
109  }
110  double bref = Bz_m*exp(k_m*R[1]);
111  B[0] = 0.;
112  B[1] = 0.;
113  B[2] = 0.;
114  for (size_t n = 0; n < x_n.size(); ++n) {
115  B[0] += bref*f_n[n+1]*(n+1)/k_m*x_n[n];
116  B[1] += bref*f_n[n]*x_n[n];
117  B[2] += bref*dz_f_n[n]/k_m*x_n[n];
118  }
119  return false;
120 }
121 
123  dfCoefficients_m = std::vector< std::vector<double> >(maxOrder_m+1);
124  dfCoefficients_m[0] = std::vector<double>(1, 1.);
125  if (maxOrder_m > 0) {
126  dfCoefficients_m[1] = std::vector<double>();
127  }
128  // n indexes like the polynomial order of the midplane expansion
129  // e.g. Bz = exp(mz) f_n y^n
130  // where y is distance from the midplane and z is height
131  for (size_t n = 2; n < dfCoefficients_m.size(); n+=2) {
132  const std::vector<double>& oldCoefficients = dfCoefficients_m[n-2];
133  std::vector<double> coefficients(oldCoefficients.size()+2, 0);
134  // j indexes the derivative of f_0
135  for (size_t j = 0; j < oldCoefficients.size(); ++j) {
136  coefficients[j] += -1./(n)/(n-1)*k_m*k_m*oldCoefficients[j];
137  coefficients[j+2] += -1./(n)/(n-1)*oldCoefficients[j];
138  }
139  dfCoefficients_m[n] = coefficients;
140  }
141 }
142 
144  endField_m.reset(endField);
145 }
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
Interface for basic beam line object.
Definition: ElementBase.h:128
BGeometryBase & getGeometry()
void setEndField(endfieldmodel::EndFieldModel *endField)
Tps< T > exp(const Tps< T > &x)
Exponential.
Definition: TpsMath.h:165
Abstract base class for accelerator geometry classes.
Definition: Geometry.h:43
void setElType(ElemType elt)
set the element type as enumeration needed in the envelope tracker
Definition: ElementBase.h:591
virtual void setElementLength(double length)
Set design length.
VerticalFFAMagnet(const std::string &name)
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:200
Abstract base class for electromagnetic fields.
Definition: EMField.h:188
StraightGeometry straightGeometry_m
bool getFieldValue(const Vector_t &R, Vector_t &B) const
const std::string name
void accept(BeamlineVisitor &visitor) const
std::vector< std::vector< double > > dfCoefficients_m
ElementBase * clone() const
virtual void visitVerticalFFAMagnet(const VerticalFFAMagnet &)=0
Apply the algorithm to a vertical FFA magnet.
Interface for a single beam element.
Definition: Component.h:51
Abstract algorithm.
void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField)
std::unique_ptr< endfieldmodel::EndFieldModel > endField_m
BMultipoleField dummy