OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
MultipoleTBase.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017, Titus Dascalu
3 * Copyright (c) 2018, Martin Duy Tat
4 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * 3. Neither the name of STFC nor the names of its contributors may be used to
13 * endorse or promote products derived from this software without specific
14 * prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "MultipoleTBase.h"
30#include <gsl/gsl_sf_gamma.h>
32#include <cmath>
33
34using namespace endfieldmodel;
35
38{}
39
42 fringeField_l(endfieldmodel::Tanh()),
43 fringeField_r(endfieldmodel::Tanh()),
44 maxOrder_m(3),
45 transMaxOrder_m(0),
46 length_m(1.0),
47 entranceAngle_m(0.0),
48 rotation_m(0.0),
49 boundingBoxLength_m(0.0),
50 verticalApert_m(0.5),
51 horizontalApert_m(0.5) {
52}
53
55 Component(right),
56 fringeField_l(right.fringeField_l),
57 fringeField_r(right.fringeField_r),
58 maxOrder_m(right.maxOrder_m),
59 transMaxOrder_m(right.transMaxOrder_m),
60 transProfile_m(right.transProfile_m),
61 length_m(right.length_m),
62 entranceAngle_m(right.entranceAngle_m),
63 rotation_m(right.rotation_m),
64 boundingBoxLength_m(right.boundingBoxLength_m),
65 verticalApert_m(right.verticalApert_m),
66 horizontalApert_m(right.horizontalApert_m),
67 dummy() {
69}
70
72}
73
74bool MultipoleTBase::apply(const Vector_t &R, const Vector_t &/*P*/,
75 const double &/*t*/,Vector_t &/*E*/, Vector_t &B) {
77 Vector_t R_prime = rotateFrame(R);
79 R_prime[2] *= -1; //OPAL uses a different sign convention...
80 transformCoords(R_prime);
81 if (insideAperture(R_prime)) {
83 B[0] = getBx(R_prime);
84 B[1] = getBz(R_prime);
85 B[2] = getBs(R_prime);
87 transformBField(B, R_prime);
88 B[2] *= -1; //OPAL uses a different sign convention...
89 return false;
90 } else {
91 for(int i = 0; i < 3; i++) {
92 B[i] = 0.0;
93 }
95 }
96}
97
99 Vector_t R_prime(3), R_pprime(3);
104 // 1st rotation
105 R_prime[0] = R[0] * std::cos(rotation_m) + R[1] * std::sin(rotation_m);
106 R_prime[1] = - R[0] * std::sin(rotation_m) + R[1] * std::cos(rotation_m);
107 R_prime[2] = R[2];
108 // 2nd rotation
109 R_pprime[0] = R_prime[2] * std::sin(entranceAngle_m) +
110 R_prime[0] * std::cos(entranceAngle_m);
111 R_pprime[1] = R_prime[1];
112 R_pprime[2] = R_prime[2] * std::cos(entranceAngle_m) -
113 R_prime[0] * std::sin(entranceAngle_m);
114 return R_pprime;
115
116}
117
123 Vector_t B_prime(3);
124 B_prime[0] = B[0] * cos(rotation_m) + B[1] * sin(rotation_m);
125 B_prime[1] = - B[0] * sin(rotation_m) + B[1] * cos(rotation_m);
126 B_prime[2] = B[2];
127 return B_prime;
128}
129
130bool MultipoleTBase::setFringeField(const double &s0,
131 const double &lambda_l,
132 const double &lambda_r) {
133 fringeField_l.Tanh::setLambda(lambda_l);
134 fringeField_l.Tanh::setX0(s0);
135 fringeField_l.Tanh::setTanhDiffIndices(2 * maxOrder_m + 1);
136 fringeField_r.Tanh::setLambda(lambda_r);
137 fringeField_r.Tanh::setX0(s0);
138 fringeField_r.Tanh::setTanhDiffIndices(2 * maxOrder_m + 1);
139 return true;
140}
141
143 if (std::abs(getFringeDeriv(0, R[2])) < 1.0e-12) {
144 return 0.0;
145 }
146 double Bz = 0.0;
147 std::size_t n = getMaxOrder() + 1;
148 while (n != 0) {
149 n--;
150 Bz = Bz * R[1] * R[1] + getFn(n, R[0], R[2])
151 / gsl_sf_fact(2 * n);
152 }
153 return Bz;
154}
155
157 if (std::abs(getFringeDeriv(0, R[2])) < 1.0e-12) {
158 return 0.0;
159 }
160 double Bx = 0.0;
161 std::size_t n = getMaxOrder() + 1;
162 while (n != 0) {
163 n--;
164 Bx = Bx * R[1] * R[1] + getFnDerivX(n, R[0], R[2])
165 / gsl_sf_fact(2 * n + 1);
166 }
167 Bx *= R[1];
168 return Bx;
169}
170
172 if (std::abs(getFringeDeriv(0, R[2])) < 1.0e-12) {
173 return 0.0;
174 }
175 double Bs = 0.0;
176 std::size_t n = getMaxOrder() + 1;
177 while (n != 0) {
178 n--;
179 Bs = Bs * R[1] * R[1] + getFnDerivS(n, R[0], R[2])
180 / gsl_sf_fact(2 * n + 1);
181 }
182 Bs *= R[1] / getScaleFactor(R[0], R[2]);
183 return Bs;
184}
185
186double MultipoleTBase::getFringeDeriv(const std::size_t &n, const double &s) {
187 if (n <= 10) {
189 / 2;
190 } else {
191 return tanhderiv::integrate(s,
192 fringeField_l.Tanh::getX0(),
193 fringeField_l.Tanh::getLambda(),
194 fringeField_r.Tanh::getLambda(),
195 n);
196 }
197}
198
199double MultipoleTBase::getTransDeriv(const std::size_t &n, const double &x) {
200 double func = 0.0;
201 std::size_t transMaxOrder = getTransMaxOrder();
202 if (n > transMaxOrder) {
203 return func;
204 }
205 std::vector<double> temp = getTransProfile();
206 for(std::size_t i = 1; i <= n; i++) {
207 for(std::size_t j = 0; j <= transMaxOrder; j++) {
208 if (j <= transMaxOrder_m - i) {
209 temp[j] = temp[j + 1] * (j + 1);
210 } else {
211 temp[j] = 0.0;
212 }
213 }
214 }
215 std::size_t k = transMaxOrder - n + 1;
216 while (k != 0) {
217 k--;
218 func = func * x + temp[k];
219 }
220 return func;
221}
222
223double MultipoleTBase::getFnDerivX(const std::size_t &n,
224 const double &x,
225 const double &s) {
226 if (n == 0) {
227 return getTransDeriv(1, x) * getFringeDeriv(0, s);
228 }
229 double deriv = 0.0;
230 double stepSize = 1e-3;
231 deriv += 1. * getFn(n, x - 2. * stepSize, s);
232 deriv += -8. * getFn(n, x - stepSize, s);
233 deriv += 8. * getFn(n, x + stepSize, s);
234 deriv += -1. * getFn(n, x + 2. * stepSize, s);
235 deriv /= 12 * stepSize;
236 return deriv;
237}
238
239double MultipoleTBase::getFnDerivS(const std::size_t &n,
240 const double &x,
241 const double &s) {
242 if (n == 0) {
243 return getTransDeriv(0, x) * getFringeDeriv(1, s);
244 }
245 double deriv = 0.0;
246 double stepSize = 1e-3;
247 deriv += 1. * getFn(n, x, s - 2. * stepSize);
248 deriv += -8. * getFn(n, x, s - stepSize);
249 deriv += 8. * getFn(n, x, s + stepSize);
250 deriv += -1. * getFn(n, x, s + 2. * stepSize);
251 deriv /= 12 * stepSize;
252 return deriv;
253}
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
const std::string name
double integrate(const double &a, const double &s0, const double &lambdaleft, const double &lambdaright, const int &n)
Definition: tanhDeriv.cpp:66
constexpr double e
The value of.
Definition: Physics.h:39
Interface for a single beam element.
Definition: Component.h:50
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:191
bool getFlagDeleteOnTransverseExit() const
Definition: ElementBase.h:613
double getNegTanh(double x, int n) const
Definition: Tanh.cpp:61
double getTanh(double x, int n) const
Definition: Tanh.cpp:50
std::size_t getTransMaxOrder() const
virtual double getFn(const std::size_t &n, const double &x, const double &s)=0
endfieldmodel::Tanh fringeField_l
virtual void transformCoords(Vector_t &R)=0
std::size_t maxOrder_m
Vector_t rotateFrameInverse(Vector_t &B)
bool insideAperture(const Vector_t &R)
std::size_t getMaxOrder() const
endfieldmodel::Tanh fringeField_r
std::vector< double > getTransProfile() const
double getTransDeriv(const std::size_t &n, const double &x)
double getBz(const Vector_t &R)
double entranceAngle_m
virtual double getScaleFactor(const double &x, const double &s)=0
bool apply(const Vector_t &R, const Vector_t &P, const double &t, Vector_t &E, Vector_t &B)
virtual void transformBField(Vector_t &B, const Vector_t &R)=0
std::size_t transMaxOrder_m
double getFnDerivX(const std::size_t &n, const double &x, const double &s)
Vector_t rotateFrame(const Vector_t &R)
bool setFringeField(const double &s0, const double &lambda_left, const double &lambda_right)
virtual double getBx(const Vector_t &R)
double getFringeDeriv(const std::size_t &n, const double &s)
virtual double getBs(const Vector_t &R)
double getFnDerivS(const std::size_t &n, const double &x, const double &s)