OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
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 
34 using namespace endfieldmodel;
35 
37  MultipoleTBase("")
38 {}
39 
41  Component(name),
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 
74 bool 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  }
94  return true;
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 
130 bool 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 
186 double MultipoleTBase::getFringeDeriv(const std::size_t &n, const double &s) {
187  if (n <= 10) {
188  return (fringeField_l.getTanh(s, n) - fringeField_r.getNegTanh(s, n))
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 
199 double 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 
223 double 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 
239 double 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:194
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)