OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
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
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
37
39 VerticalFFAMagnet* magnet = new VerticalFFAMagnet(*this);
40 magnet->initialise();
41 return magnet;
42}
43
45
46const EMField& VerticalFFAMagnet::getField() const { return dummy; }
47
52
54 PartBunch_t* bunch, double& /*startField*/, double& /*endField*/) {
55 RefPartBunch_m = bunch;
56 initialise();
57}
58
60
62
64
66 visitor.visitVerticalFFAMagnet(*this);
67}
68
70 if (std::abs(R[0]) > halfWidth_m || R[2] < 0. || R[2] > bbLength_m || R[1] < -zNegExtent_m
71 || R[1] > zPosExtent_m) {
72 return true;
73 }
74 std::vector<double> fringeDerivatives(maxOrder_m + 2, 0.);
75 double zRel = R[2] - bbLength_m / 2.; // z relative to centre of magnet
76 for (size_t i = 0; i < fringeDerivatives.size(); ++i) {
77 fringeDerivatives[i] = endField_m->function(zRel, i); // d^i_phi f
78 }
79
80 std::vector<double> x_n(maxOrder_m + 1); // x^n
81 x_n[0] = 1.; // x^0
82 for (size_t i = 1; i < x_n.size(); ++i) {
83 x_n[i] = x_n[i - 1] * R[0];
84 }
85
86 // note that the last element is always 0, because dfCoefficients_m is
87 // of size maxOrder_m+1. This leads to better Maxwellianness in testing.
88 std::vector<double> f_n(maxOrder_m + 2, 0.);
89 std::vector<double> dz_f_n(maxOrder_m + 1, 0.);
90 for (size_t n = 0; n < dfCoefficients_m.size(); ++n) {
91 const std::vector<double>& coefficients = dfCoefficients_m[n];
92 for (size_t i = 0; i < coefficients.size(); ++i) {
93 f_n[n] += coefficients[i] * fringeDerivatives[i];
94 dz_f_n[n] += coefficients[i] * fringeDerivatives[i + 1];
95 }
96 }
97 double bref = Bz_m * exp(k_m * R[1]);
98 B[0] = 0.;
99 B[1] = 0.;
100 B[2] = 0.;
101 for (size_t n = 0; n < x_n.size(); ++n) {
102 B[0] += bref * f_n[n + 1] * (n + 1) / k_m * x_n[n];
103 B[1] += bref * f_n[n] * x_n[n];
104 B[2] += bref * dz_f_n[n] / k_m * x_n[n];
105 }
106 return false;
107}
108
110 dfCoefficients_m = std::vector<std::vector<double> >(maxOrder_m + 1);
111 dfCoefficients_m[0] = std::vector<double>(1, 1.);
112 if (maxOrder_m > 0) {
113 dfCoefficients_m[1] = std::vector<double>();
114 }
115 // n indexes like the polynomial order of the midplane expansion
116 // e.g. Bz = exp(mz) f_n y^n
117 // where y is distance from the midplane and z is height
118 for (size_t n = 2; n < dfCoefficients_m.size(); n += 2) {
119 const std::vector<double>& oldCoefficients = dfCoefficients_m[n - 2];
120 std::vector<double> coefficients(oldCoefficients.size() + 2, 0);
121 // j indexes the derivative of f_0
122 for (size_t j = 0; j < oldCoefficients.size(); ++j) {
123 coefficients[j] += -1. / (n) / (n - 1) * k_m * k_m * oldCoefficients[j];
124 coefficients[j + 2] += -1. / (n) / (n - 1) * oldCoefficients[j];
125 }
126 dfCoefficients_m[n] = coefficients;
127 }
128}
129
131 endField_m.reset(endField);
132 endField_m->setMaximumDerivative(maxOrder_m);
133}
134
135void VerticalFFAMagnet::setMaxOrder(size_t maxOrder) {
136 if (endField_m.get()) {
137 endField_m->setMaximumDerivative(maxOrder);
138 }
139 maxOrder_m = maxOrder;
140}
ippl::Vector< T, Dim > Vector_t
Abstract base class for accelerator geometry classes.
Definition Geometry.h:42
virtual void visitVerticalFFAMagnet(const VerticalFFAMagnet &)=0
Apply the algorithm to a vertical FFA magnet.
PartBunch_t * RefPartBunch_m
Definition Component.h:225
Abstract base class for electromagnetic fields.
Definition EMField.h:171
virtual void setElementLength(double length)
Set design length.
ElementBase * clone() const
void accept(BeamlineVisitor &visitor) const
void initialise(PartBunch_t *bunch, double &startField, double &endField)
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)
bool getFieldValue(const Vector_t< double, 3 > &R, Vector_t< double, 3 > &B) const
void setEndField(endfieldmodel::EndFieldModel *endField)