OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
ScalingFFAMagnet.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017, Chris Rogers
3  * All rights reserved.
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  * 1. Redistributions of source code must retain the above copyright notice,
7  * this list of conditions and the following disclaimer.
8  * 2. Redistributions in binary form must reproduce the above copyright notice,
9  * this list of conditions and the following disclaimer in the documentation
10  * and/or other materials provided with the distribution.
11  * 3. Neither the name of STFC nor the names of its contributors may be used to
12  * endorse or promote products derived from this software without specific
13  * prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <cmath>
29 
31 #include "Algorithms/PartBunch.h"
33 
35  : Component(name),
36  planarArcGeometry_m(1., 1.), dummy(), endField_m(NULL) {
37 }
38 
40  : Component(right),
41  planarArcGeometry_m(right.planarArcGeometry_m),
42  dummy(), maxOrder_m(right.maxOrder_m), tanDelta_m(right.tanDelta_m),
43  k_m(right.k_m), Bz_m(right.Bz_m), r0_m(right.r0_m),
44  rMin_m(right.rMin_m), rMax_m(right.rMax_m), phiStart_m(right.phiStart_m),
45  phiEnd_m(right.phiEnd_m), azimuthalExtent_m(right.azimuthalExtent_m),
46  verticalExtent_m(right.verticalExtent_m), centre_m(right.centre_m),
47  dfCoefficients_m(right.dfCoefficients_m) {
48  delete endField_m;
49  endField_m = right.endField_m->clone();
51  Bz_m = right.Bz_m;
52  r0_m = right.r0_m;
53 }
54 
56  delete endField_m;
57 }
58 
60  ScalingFFAMagnet* magnet = new ScalingFFAMagnet(*this);
61  magnet->initialise();
62  return magnet;
63 }
64 
66  return dummy;
67 }
68 
70  return dummy;
71 }
72 
73 bool ScalingFFAMagnet::apply(const size_t &i, const double &t,
74  Vector_t &E, Vector_t &B) {
75  return apply(RefPartBunch_m->R[i], RefPartBunch_m->P[i], t, E, B);
76 }
77 
82 }
83 
84 void ScalingFFAMagnet::initialise(PartBunchBase<double, 3> *bunch, double &/*startField*/, double &/*endField*/) {
85  RefPartBunch_m = bunch;
86  initialise();
87 }
88 
90  RefPartBunch_m = NULL;
91 }
92 
94  return true;
95 }
96 
98  return planarArcGeometry_m;
99 }
100 
102  return planarArcGeometry_m;
103 }
104 
106  visitor.visitScalingFFAMagnet(*this);
107 }
108 
109 
111  Vector_t pos = R - centre_m;
112  double r = std::sqrt(pos[0]*pos[0]+pos[2]*pos[2]);
113  double phi = -std::atan2(pos[0], pos[2]); // angle between y-axis and position vector in anticlockwise direction
114  Vector_t posCyl(r, pos[1], phi);
115  Vector_t bCyl(0., 0., 0.); //br bz bphi
116  bool outOfBounds = getFieldValueCylindrical(posCyl, bCyl);
117  // this is cartesian coordinates
118  B[1] += bCyl[1];
119  B[0] += -bCyl[2]*std::cos(phi) -bCyl[0]*std::sin(phi);
120  B[2] += +bCyl[0]*std::cos(phi) -bCyl[2]*std::sin(phi);
121  return outOfBounds;
122 
123 }
124 
125 
127 
128  double r = pos[0];
129  double z = pos[1];
130  double phi = pos[2];
131  if (r < rMin_m || r > rMax_m) {
132  return true;
133  }
134 
135  double normRadius = r/r0_m;
136  double g = tanDelta_m*std::log(normRadius);
137  double phiSpiral = phi - g - phiStart_m;
138  double h = std::pow(normRadius, k_m)*Bz_m;
139  if (phiSpiral < -azimuthalExtent_m || phiSpiral > azimuthalExtent_m) {
140  return true;
141  }
142  if (z < -verticalExtent_m || z > verticalExtent_m) {
143  return true;
144  }
145  std::vector<double> fringeDerivatives(maxOrder_m+1, 0.);
146  for (size_t i = 0; i < fringeDerivatives.size(); ++i) {
147  fringeDerivatives[i] = endField_m->function(phiSpiral, i); // d^i_phi f
148  }
149  for (size_t n = 0; n < dfCoefficients_m.size(); n += 2) {
150  double f2n = 0;
151  Vector_t deltaB;
152  for (size_t i = 0; i < dfCoefficients_m[n].size(); ++i) {
153  f2n += dfCoefficients_m[n][i]*fringeDerivatives[i];
154  }
155  deltaB[1] = f2n*h*std::pow(z/r, n); // Bz = sum(f_2n * h * (z/r)^2n
156  if (maxOrder_m >= n+1) {
157  double f2nplus1 = 0;
158  for (size_t i = 0; i < dfCoefficients_m[n+1].size() && n+1 < dfCoefficients_m.size(); ++i) {
159  f2nplus1 += dfCoefficients_m[n+1][i]*fringeDerivatives[i];
160  }
161  deltaB[0] = (f2n*(k_m-n)/(n+1) - tanDelta_m*f2nplus1)*h*std::pow(z/r, n+1); // Br
162  deltaB[2] = f2nplus1*h*std::pow(z/r, n+1); // Bphi = sum(f_2n+1 * h * (z/r)^2n+1
163  }
164  B += deltaB;
165  }
166  return false;
167 }
168 
169 
170 bool ScalingFFAMagnet::apply(const Vector_t &R, const Vector_t &/*P*/,
171  const double &/*t*/, Vector_t &/*E*/, Vector_t &B) {
172  return getFieldValue(R, B);
173 }
174 
176  dfCoefficients_m = std::vector<std::vector<double> >(maxOrder_m+1);
177  dfCoefficients_m[0] = std::vector<double>(1, 1.); // f_0 = 1.*0th derivative
178  for (size_t n = 0; n < maxOrder_m; n += 2) { // n indexes the power in z
179  dfCoefficients_m[n+1] = std::vector<double>(dfCoefficients_m[n].size()+1, 0);
180  for (size_t i = 0; i < dfCoefficients_m[n].size(); ++i) { // i indexes the derivative
181  dfCoefficients_m[n+1][i+1] = dfCoefficients_m[n][i]/(n+1);
182  }
183  if (n+1 == maxOrder_m) {
184  break;
185  }
186  dfCoefficients_m[n+2] = std::vector<double>(dfCoefficients_m[n].size()+2, 0);
187  for(size_t i = 0; i < dfCoefficients_m[n].size(); ++i) { // i indexes the derivative
188  dfCoefficients_m[n+2][i] = -(k_m-n)*(k_m-n)/(n+1)*dfCoefficients_m[n][i]/(n+2);
189  }
190  for(size_t i = 0; i < dfCoefficients_m[n+1].size(); ++i) { // i indexes the derivative
191  dfCoefficients_m[n+2][i] += 2*(k_m-n)*tanDelta_m*dfCoefficients_m[n+1][i]/(n+2);
192  dfCoefficients_m[n+2][i+1] -= (1+tanDelta_m*tanDelta_m)*dfCoefficients_m[n+1][i]/(n+2);
193  }
194  }
195 
196 }
197 
199  if (endField_m != NULL) {
200  delete endField_m;
201  }
202  endField_m = endField;
203 }
204 
Tps< T > log(const Tps< T > &x)
Natural logarithm.
Definition: TpsMath.h:182
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
Definition: TpsMath.h:76
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
PETE_TBTree< FnArcTan2, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > atan2(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
const std::string name
ParticlePos_t & R
ParticleAttrib< Vector_t > P
virtual void visitScalingFFAMagnet(const ScalingFFAMagnet &)=0
Apply the algorithm to a scaling FFA magnet.
Interface for a single beam element.
Definition: Component.h:50
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:194
virtual EndFieldModel * clone() const =0
virtual double function(double x, int n) const =0
bool getFieldValue(const Vector_t &R, Vector_t &B) const
bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) override
void accept(BeamlineVisitor &visitor) const override
void finalise() override
endfieldmodel::EndFieldModel * endField_m
ScalingFFAMagnet(const std::string &name)
bool getFieldValueCylindrical(const Vector_t &R, Vector_t &B) const
EMField & getField() override
ElementBase * clone() const override
void setEndField(endfieldmodel::EndFieldModel *endField)
BMultipoleField dummy
std::vector< std::vector< double > > dfCoefficients_m
void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField) override
BGeometryBase & getGeometry() override
bool bends() const override
PlanarArcGeometry planarArcGeometry_m
Abstract base class for accelerator geometry classes.
Definition: Geometry.h:43
void setCurvature(double)
Set curvature.
virtual void setElementLength(double)
Set length.
Abstract base class for electromagnetic fields.
Definition: EMField.h:188