OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
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) {
38 }
39 
41  : Component(right),
42  planarArcGeometry_m(right.planarArcGeometry_m),
43  dummy(), maxOrder_m(right.maxOrder_m), tanDelta_m(right.tanDelta_m),
44  k_m(right.k_m), Bz_m(right.Bz_m), r0_m(right.r0_m),
45  rMin_m(right.rMin_m), rMax_m(right.rMax_m), phiStart_m(right.phiStart_m),
46  phiEnd_m(right.phiEnd_m), azimuthalExtent_m(right.azimuthalExtent_m),
47  verticalExtent_m(right.verticalExtent_m), centre_m(right.centre_m),
48  dfCoefficients_m(right.dfCoefficients_m) {
49  delete endField_m;
50  endField_m = right.endField_m->clone();
53  Bz_m = right.Bz_m;
54  r0_m = right.r0_m;
55 }
56 
58  delete endField_m;
59 }
60 
62  ScalingFFAMagnet* magnet = new ScalingFFAMagnet(*this);
63  magnet->initialise();
64  return magnet;
65 }
66 
68  return dummy;
69 }
70 
72  return dummy;
73 }
74 
75 bool ScalingFFAMagnet::apply(const size_t &i, const double &t,
76  Vector_t &E, Vector_t &B) {
77  return apply(RefPartBunch_m->R[i], RefPartBunch_m->P[i], t, E, B);
78 }
79 
84 }
85 
86 void ScalingFFAMagnet::initialise(PartBunchBase<double, 3> *bunch, double &startField, double &endField) {
87  RefPartBunch_m = bunch;
88  initialise();
89 }
90 
92  RefPartBunch_m = NULL;
93 }
94 
96  return true;
97 }
98 
100  return planarArcGeometry_m;
101 }
102 
104  return planarArcGeometry_m;
105 }
106 
108  visitor.visitScalingFFAMagnet(*this);
109 }
110 
111 
113  Vector_t pos = R - centre_m;
114  double r = sqrt(pos[0]*pos[0]+pos[2]*pos[2]);
115  double phi = -atan2(pos[0], pos[2]); // angle between y-axis and position vector in anticlockwise direction
116  Vector_t posCyl(r, pos[1], phi);
117  Vector_t bCyl(0., 0., 0.); //br bz bphi
118  bool outOfBounds = getFieldValueCylindrical(posCyl, bCyl);
119  // this is cartesian coordinates
120  B[1] += bCyl[1];
121  B[0] += -bCyl[2]*cos(phi) -bCyl[0]*sin(phi);
122  B[2] += +bCyl[0]*cos(phi) -bCyl[2]*sin(phi);
123  return outOfBounds;
124 
125 }
126 
127 
129 
130  double r = pos[0];
131  double z = pos[1];
132  double phi = pos[2];
133  if (r < rMin_m || r > rMax_m) {
134  return true;
135  }
136 
137  double normRadius = r/r0_m;
138  double g = tanDelta_m*log(normRadius);
139  double phiSpiral = phi - g - phiStart_m;
140  double h = pow(normRadius, k_m)*Bz_m;
141  if (phiSpiral < -azimuthalExtent_m || phiSpiral > azimuthalExtent_m) {
142  return true;
143  }
144  if (z < -verticalExtent_m || z > verticalExtent_m) {
145  return true;
146  }
147  std::vector<double> fringeDerivatives(maxOrder_m+1, 0.);
148  for (size_t i = 0; i < fringeDerivatives.size(); ++i) {
149  fringeDerivatives[i] = endField_m->function(phiSpiral, i); // d^i_phi f
150  }
151  for (size_t n = 0; n < dfCoefficients_m.size(); n += 2) {
152  double f2n = 0;
153  Vector_t deltaB;
154  for (size_t i = 0; i < dfCoefficients_m[n].size(); ++i) {
155  f2n += dfCoefficients_m[n][i]*fringeDerivatives[i];
156  }
157  deltaB[1] = f2n*h*pow(z/r, n); // Bz = sum(f_2n * h * (z/r)^2n
158  if (maxOrder_m >= n+1) {
159  double f2nplus1 = 0;
160  for (size_t i = 0; i < dfCoefficients_m[n+1].size() && n+1 < dfCoefficients_m.size(); ++i) {
161  f2nplus1 += dfCoefficients_m[n+1][i]*fringeDerivatives[i];
162  }
163  deltaB[0] = (f2n*(k_m-n)/(n+1) - tanDelta_m*f2nplus1)*h*pow(z/r, n+1); // Br
164  deltaB[2] = f2nplus1*h*pow(z/r, n+1); // Bphi = sum(f_2n+1 * h * (z/r)^2n+1
165  }
166  B += deltaB;
167  }
168  return false;
169 }
170 
171 
173  const double &t, Vector_t &E, Vector_t &B) {
174  return getFieldValue(R, B);
175 }
176 
178  dfCoefficients_m = std::vector<std::vector<double> >(maxOrder_m+1);
179  dfCoefficients_m[0] = std::vector<double>(1, 1.); // f_0 = 1.*0th derivative
180  for (size_t n = 0; n < maxOrder_m; n += 2) { // n indexes the power in z
181  dfCoefficients_m[n+1] = std::vector<double>(dfCoefficients_m[n].size()+1, 0);
182  for (size_t i = 0; i < dfCoefficients_m[n].size(); ++i) { // i indexes the derivative
183  dfCoefficients_m[n+1][i+1] = dfCoefficients_m[n][i]/(n+1);
184  }
185  if (n+1 == maxOrder_m) {
186  break;
187  }
188  dfCoefficients_m[n+2] = std::vector<double>(dfCoefficients_m[n].size()+2, 0);
189  for(size_t i = 0; i < dfCoefficients_m[n].size(); ++i) { // i indexes the derivative
190  dfCoefficients_m[n+2][i] = -(k_m-n)*(k_m-n)/(n+1)*dfCoefficients_m[n][i]/(n+2);
191  }
192  for(size_t i = 0; i < dfCoefficients_m[n+1].size(); ++i) { // i indexes the derivative
193  dfCoefficients_m[n+2][i] += 2*(k_m-n)*tanDelta_m*dfCoefficients_m[n+1][i]/(n+2);
194  dfCoefficients_m[n+2][i+1] -= (1+tanDelta_m*tanDelta_m)*dfCoefficients_m[n+1][i]/(n+2);
195  }
196  }
197 
198 }
199 
201  if (endField_m != NULL) {
202  delete endField_m;
203  }
204  endField_m = endField;
205 }
206 
ParticleAttrib< Vector_t > P
Interface for basic beam line object.
Definition: ElementBase.h:128
void setEndField(endfieldmodel::EndFieldModel *endField)
bool getFieldValueCylindrical(const Vector_t &R, Vector_t &B) const
void setCurvature(double)
Set curvature.
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
bool bends() const override
void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField) override
PlanarArcGeometry planarArcGeometry_m
void accept(BeamlineVisitor &visitor) const override
Tps< T > log(const Tps< T > &x)
Natural logarithm.
Definition: TpsMath.h:182
ScalingFFAMagnet(const std::string &name)
Abstract base class for accelerator geometry classes.
Definition: Geometry.h:43
virtual EndFieldModel * clone() const =0
void setElType(ElemType elt)
set the element type as enumeration needed in the envelope tracker
Definition: ElementBase.h:591
std::vector< std::vector< double > > dfCoefficients_m
virtual void visitScalingFFAMagnet(const ScalingFFAMagnet &)=0
Apply the algorithm to a solenoid.
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:200
PETE_TBTree< FnArcTan2, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > atan2(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
Definition: TpsMath.h:76
Abstract base class for electromagnetic fields.
Definition: EMField.h:188
EMField & getField() override
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) override
BGeometryBase & getGeometry() override
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
const std::string name
bool getFieldValue(const Vector_t &R, Vector_t &B) const
ParticlePos_t & R
endfieldmodel::EndFieldModel * endField_m
virtual double function(double x, int n) const =0
Interface for a single beam element.
Definition: Component.h:51
virtual void setElementLength(double)
Set length.
Abstract algorithm.
void finalise() override
ElementBase * clone() const override
BMultipoleField dummy