OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
MultipoleTCurvedConstRadius.h
Go to the documentation of this file.
1//
2// Cubic Spline Interpolation to replace GSL spline
3//
4// Copyright (c) 2023, Paul Scherrer Institute, Villigen PSI, Switzerland
5// All rights reserved
6//
7// This file is part of OPAL.
8//
9// OPAL is free software: you can redistribute it and/or modify
10// it under the terms of the GNU General Public License as published by
11// the Free Software Foundation, either version 3 of the License, or
12// (at your option) any later version.
13//
14// You should have received a copy of the GNU General License
15// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
16//
17
18#ifndef ABSBEAMLINE_MULTIPOLET_CURVED_CONST_RADIUS_H
19#define ABSBEAMLINE_MULTIPOLET_CURVED_CONST_RADIUS_H
20
68
70public:
72 explicit MultipoleTCurvedConstRadius(MultipoleT* element);
74 void initialise() override;
78 // Container-agnostic: R/E/B views come from the caller's particle container.
80 Kokkos::View<Vector_t<double, 3>*> R, Kokkos::View<Vector_t<double, 3>*> E,
81 Kokkos::View<Vector_t<double, 3>*> B, double scaling, size_t count) override;
82 bool getField(
84 double scaling) override;
85
86private:
89
90 // Helpers
91 KOKKOS_INLINE_FUNCTION static Vector_t<double, 3> toMagnetCoords(
92 const Vector_t<double, 3>& R, const MultipoleTConfig& config);
93 template <class ViewType>
94 KOKKOS_INLINE_FUNCTION static bool computeBField(
95 const Vector_t<double, 3>& R, Vector_t<double, 3>& B, double scaling,
96 const MultipoleTConfig& config, const ViewType& tanhCoefficients);
97};
98
100 const Vector_t<double, 3>& R, const MultipoleTConfig& config) {
101 // Skew and entry angle
102 Vector_t<double, 3> result = rotateFrame(R, config);
103 // Go to local Frenet-Serret coordinates
104 // Note: if the bend angle is zero, this object is not constructed
105 const double radius = config.length_m / config.bendAngle_m;
106 const double rMinusX = radius - R[0];
107 const double alpha = Kokkos::hypot(rMinusX, R[2]);
108 result[0] = alpha - radius;
109 result[1] = R[1];
110 result[2] = radius * Kokkos::atan2(R[2], rMinusX);
111 // Magnet origin at the center rather than entry
112 result[2] -= config.length_m / 2.0;
113 return result;
114}
115
116template <class ViewType>
118 const Vector_t<double, 3>& R, Vector_t<double, 3>& B, const double scaling,
119 const MultipoleTConfig& config, const ViewType& tanhCoefficients) {
120 const Vector_t<double, 3> RPrime = toMagnetCoords(R, config);
121 const bool insideAperture = Kokkos::abs(RPrime[1]) <= config.verticalAperture_m / 2.0
122 && Kokkos::abs(RPrime[0]) <= config.horizontalAperture_m / 2.0;
123 const bool insideBoundingBox = config.boundingBoxLength_m == 0.0
124 || Kokkos::abs(RPrime[2]) <= config.boundingBoxLength_m / 2.0;
125 if (insideAperture && insideBoundingBox) {
127 Kokkos::Array<double, MaxDerivatives> dt{};
128 Kokkos::Array<double, MaxDerivatives> ds{};
129 Kokkos::Array<double, MaxPowerInteger> rhoPowers{};
130 Kokkos::Array<double, MaxPowerInteger> hsPowers{};
132 config.transverseProfile_m, config.maxFOrder_m * 2 + 2, RPrime[0], dt);
134 config.fringeS0_m, config.fringeLambdaLeft_m, config.fringeLambdaRight_m, RPrime[2],
135 tanhCoefficients, ds);
136 const double rho = config.length_m / config.bendAngle_m;
137 calcPowers(rho, config.maxFOrder_m, rhoPowers);
138 const double hs = 1 + RPrime[0] / rho;
139 calcPowers(hs, 2 * config.maxFOrder_m, hsPowers);
140 for (unsigned int n = 0; n <= config.maxFOrder_m; n++) {
141 double innerSumX{};
142 double innerSumZ{};
143 double innerSumS{};
144 for (unsigned int i = 0; i <= n; i++) {
145 for (unsigned int j = 0; j <= n - i; j++) {
146 const double k =
147 factorial(n) / (factorial(i) * factorial(j) * factorial(n - i - j));
148 const double rhoHs = 1.0 / rhoPowers[i] / hsPowers[2 * n - i - 2 * j];
149 const double dtx =
150 dt[i + 2 * j + 1] - (2 * n - i - 2 * j) / rho / hs * dt[i + 2 * j];
151 innerSumX += k * rhoHs * dtx * ds[2 * n - 2 * i - 2 * j];
152 innerSumZ += k * rhoHs * dt[i + 2 * j] * ds[2 * n - 2 * i - 2 * j];
153 innerSumS += k * rhoHs * dt[i + 2 * j] * ds[2 * n - 2 * i - 2 * j + 1];
154 }
155 }
156 const double negOnePowN = powerInteger(-1.0, n);
157 const double xszk =
158 powerInteger(RPrime[1], 2 * n + 1) / factorial(2 * n + 1) * negOnePowN;
159 const double zzk = powerInteger(RPrime[1], 2 * n) / factorial(2 * n) * negOnePowN;
160 myB[0] += innerSumX * xszk;
161 myB[1] += innerSumZ * zzk;
162 myB[2] += innerSumS * xszk;
163 }
164 B += myB * scaling;
165 }
166 return !insideAperture;
167}
168
169#endif
ippl::Vector< T, Dim > Vector_t
Abstract base class for accelerator geometry classes.
Definition Geometry.h:42
static KOKKOS_INLINE_FUNCTION Vector_t< double, 3 > rotateFrame(const Vector_t< double, 3 > &R, const MultipoleTConfig &config)
static KOKKOS_INLINE_FUNCTION double powerInteger(double x, unsigned int n)
static KOKKOS_INLINE_FUNCTION void calcTransverseDerivatives(const Kokkos::Array< double, MultipoleTConfig::NumPoles > &poles, unsigned int numDerivatives, double x, Kokkos::Array< double, MaxDerivatives > &derivatives)
static KOKKOS_INLINE_FUNCTION void calcPowers(double value, unsigned int maxPower, Kokkos::Array< double, MaxPowerInteger > &powers)
static KOKKOS_INLINE_FUNCTION void calcFringeDerivatives(const double &s0, const double &lambdaLeft, const double &lambdaRight, double s, const ViewType &tanhCoefficients, Kokkos::Array< double, MaxDerivatives > &derivatives)
static KOKKOS_INLINE_FUNCTION double factorial(unsigned int n)
void getField(Kokkos::View< Vector_t< double, 3 > * > R, Kokkos::View< Vector_t< double, 3 > * > E, Kokkos::View< Vector_t< double, 3 > * > B, double scaling, size_t count) override
static KOKKOS_INLINE_FUNCTION bool computeBField(const Vector_t< double, 3 > &R, Vector_t< double, 3 > &B, double scaling, const MultipoleTConfig &config, const ViewType &tanhCoefficients)
static KOKKOS_INLINE_FUNCTION Vector_t< double, 3 > toMagnetCoords(const Vector_t< double, 3 > &R, const MultipoleTConfig &config)
BGeometryBase * getGeometry() override
A simple arc in the XZ plane.
unsigned int maxFOrder_m
Kokkos::Array< double, NumPoles > transverseProfile_m