OPAL (Object Oriented Parallel Accelerator Library) 2022.1
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
15#include <cmath>
16
18 : Component(name), straightGeometry_m(1.) {
19}
20
22 : Component(right),
23 straightGeometry_m(right.straightGeometry_m),
24 dummy(right.dummy),
25 maxOrder_m(right.maxOrder_m),
26 k_m(right.k_m),
27 Bz_m(right.Bz_m),
28 zNegExtent_m(right.zNegExtent_m),
29 zPosExtent_m(right.zPosExtent_m),
30 halfWidth_m(right.halfWidth_m),
31 bbLength_m(right.bbLength_m),
32 endField_m(right.endField_m->clone()),
33 dfCoefficients_m(right.dfCoefficients_m) {
35}
36
37
39}
40
42 VerticalFFAMagnet* magnet = new VerticalFFAMagnet(*this);
43 magnet->initialise();
44 return magnet;
45}
46
48 return dummy;
49}
50
52 return dummy;
53}
54
58}
59
60void VerticalFFAMagnet::initialise(PartBunchBase<double, 3> *bunch, double &/*startField*/, double &/*endField*/) {
61 RefPartBunch_m = bunch;
62 initialise();
63}
64
66 RefPartBunch_m = nullptr;
67}
68
70 return straightGeometry_m;
71}
72
74 return straightGeometry_m;
75}
76
78 visitor.visitVerticalFFAMagnet(*this);
79}
80
81
83 if (std::abs(R[0]) > halfWidth_m ||
84 R[2] < 0. || R[2] > bbLength_m ||
85 R[1] < -zNegExtent_m || R[1] > zPosExtent_m) {
86 return true;
87 }
88 std::vector<double> fringeDerivatives(maxOrder_m+2, 0.);
89 double zRel = R[2]-bbLength_m/2.; // z relative to centre of magnet
90 for (size_t i = 0; i < fringeDerivatives.size(); ++i) {
91 fringeDerivatives[i] = endField_m->function(zRel, i); // d^i_phi f
92 }
93
94 std::vector<double> x_n(maxOrder_m+1); // x^n
95 x_n[0] = 1.; // x^0
96 for (size_t i = 1; i < x_n.size(); ++i) {
97 x_n[i] = x_n[i-1]*R[0];
98 }
99
100 // note that the last element is always 0, because dfCoefficients_m is
101 // of size maxOrder_m+1. This leads to better Maxwellianness in testing.
102 std::vector<double> f_n(maxOrder_m+2, 0.);
103 std::vector<double> dz_f_n(maxOrder_m+1, 0.);
104 for (size_t n = 0; n < dfCoefficients_m.size(); ++n) {
105 const std::vector<double>& coefficients = dfCoefficients_m[n];
106 for (size_t i = 0; i < coefficients.size(); ++i) {
107 f_n[n] += coefficients[i]*fringeDerivatives[i];
108 dz_f_n[n] += coefficients[i]*fringeDerivatives[i+1];
109 }
110 }
111 double bref = Bz_m*exp(k_m*R[1]);
112 B[0] = 0.;
113 B[1] = 0.;
114 B[2] = 0.;
115 for (size_t n = 0; n < x_n.size(); ++n) {
116 B[0] += bref*f_n[n+1]*(n+1)/k_m*x_n[n];
117 B[1] += bref*f_n[n]*x_n[n];
118 B[2] += bref*dz_f_n[n]/k_m*x_n[n];
119 }
120 return false;
121}
122
124 dfCoefficients_m = std::vector< std::vector<double> >(maxOrder_m+1);
125 dfCoefficients_m[0] = std::vector<double>(1, 1.);
126 if (maxOrder_m > 0) {
127 dfCoefficients_m[1] = std::vector<double>();
128 }
129 // n indexes like the polynomial order of the midplane expansion
130 // e.g. Bz = exp(mz) f_n y^n
131 // where y is distance from the midplane and z is height
132 for (size_t n = 2; n < dfCoefficients_m.size(); n+=2) {
133 const std::vector<double>& oldCoefficients = dfCoefficients_m[n-2];
134 std::vector<double> coefficients(oldCoefficients.size()+2, 0);
135 // j indexes the derivative of f_0
136 for (size_t j = 0; j < oldCoefficients.size(); ++j) {
137 coefficients[j] += -1./(n)/(n-1)*k_m*k_m*oldCoefficients[j];
138 coefficients[j+2] += -1./(n)/(n-1)*oldCoefficients[j];
139 }
140 dfCoefficients_m[n] = coefficients;
141 }
142}
143
145 endField_m.reset(endField);
146 endField_m->setMaximumDerivative(maxOrder_m);
147}
148
149void VerticalFFAMagnet::setMaxOrder(size_t maxOrder) {
150 if (endField_m.get()) {
151 endField_m->setMaximumDerivative(maxOrder);
152 }
153 maxOrder_m = maxOrder;
154}
Tps< T > exp(const Tps< T > &x)
Exponential.
Definition: TpsMath.h:165
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
const std::string name
virtual void visitVerticalFFAMagnet(const VerticalFFAMagnet &)=0
Apply the algorithm to a vertical FFA magnet.
Interface for a single beam element.
Definition: Component.h:50
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:191
ElementBase * clone() const
void accept(BeamlineVisitor &visitor) const
bool getFieldValue(const Vector_t &R, Vector_t &B) const
std::unique_ptr< endfieldmodel::EndFieldModel > endField_m
BGeometryBase & getGeometry()
BMultipoleField dummy
void setMaxOrder(size_t maxOrder)
std::vector< std::vector< double > > dfCoefficients_m
StraightGeometry straightGeometry_m
VerticalFFAMagnet(const std::string &name)
void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField)
void setEndField(endfieldmodel::EndFieldModel *endField)
Abstract base class for accelerator geometry classes.
Definition: Geometry.h:43
virtual void setElementLength(double length)
Set design length.
Abstract base class for electromagnetic fields.
Definition: EMField.h:188