ImpactX
Loading...
Searching...
No Matches
TaperedPL.H
Go to the documentation of this file.
1/* Copyright 2022-2026 The Regents of the University of California, through Lawrence
2 * Berkeley National Laboratory (subject to receipt of any required
3 * approvals from the U.S. Dept. of Energy). All rights reserved.
4 *
5 * This file is part of ImpactX.
6 *
7 * Authors: Chad Mitchell, Axel Huebl
8 * License: BSD-3-Clause-LBNL
9 */
10#ifndef IMPACTX_TAPEREDPL_H
11#define IMPACTX_TAPEREDPL_H
12
14#include "mixin/alignment.H"
15#include "mixin/beamoptic.H"
16#include "mixin/thin.H"
18#include "mixin/spintransport.H"
19#include "mixin/named.H"
20#include "mixin/nofinalize.H"
21
22#include <AMReX_Extension.H>
23#include <AMReX_Math.H>
24#include <AMReX_REAL.H>
25#include <AMReX_SIMD.H>
26
27#include <cmath>
28#include <stdexcept>
29
30namespace impactx::elements
31{
32 struct TaperedPL
33 : public mixin::Named,
34 public mixin::BeamOptic<TaperedPL>,
35 public mixin::LinearTransport<TaperedPL>,
36 public mixin::Thin,
37 public mixin::Alignment,
39 public mixin::NoFinalize,
40 // At least on Intel AVX512, there is a small overhead to vectorize this element
41 // for pure phase-space pushes. But a win for spin-tracking. See:
42 // https://github.com/BLAST-ImpactX/impactx/pull/1002
43 // https://github.com/BLAST-ImpactX/impactx/pull/1499
44 public amrex::simd::Vectorized<amrex::simd::native_simd_size_particlereal>
45 {
46 static constexpr auto type = "TaperedPL";
48
49 static constexpr int DEFAULT_unit = 0;
50
69 int unit = DEFAULT_unit,
73 std::optional<std::string> name = DEFAULT_name
74 )
75 : Named(std::move(name)),
76 Alignment(dx, dy, rotation_degree),
77 m_k(k), m_taper(taper), m_unit(unit)
78 {
79 }
80
82 void reverse () { m_k = -m_k; }
83
91 void compute_constants (RefPart const & refpart)
92 {
93 using namespace amrex::literals; // for _rt and _prt
94
95 Alignment::compute_constants(refpart);
96
97 // normalize focusing strength units to MAD-X convention if needed
98 m_g = m_unit == 1 ? m_k / refpart.rigidity_Tm() : m_k;
99
100 // additional constants needed for spin push
101 m_beta = refpart.beta();
102 m_ibeta = 1_prt / m_beta;
103
104 }
105
107 using BeamOptic::operator();
108
121 template<typename T_Real=amrex::ParticleReal, typename T_IdCpu=uint64_t>
124 T_Real const & AMREX_RESTRICT x,
125 T_Real const & AMREX_RESTRICT y,
126 [[maybe_unused]] T_Real const & AMREX_RESTRICT t,
127 T_Real & AMREX_RESTRICT px,
128 T_Real & AMREX_RESTRICT py,
129 [[maybe_unused]] T_Real const & AMREX_RESTRICT pt,
130 [[maybe_unused]] T_IdCpu const & AMREX_RESTRICT idcpu,
131 [[maybe_unused]] RefPart const & AMREX_RESTRICT refpart
132 ) const
133 {
134 using namespace amrex::literals; // for _rt and _prt
135 using amrex::Math::powi;
136 using namespace std; // for cmath(float)
137
138 // initialize output values
139 // T_Real xout = x;
140 // T_Real yout = y;
141 // T_Real tout = t;
142 T_Real pxout = px;
143 T_Real pyout = py;
144 // T_Real ptout = pt;
145
146 // advance position and momentum
147 // xout = x;
148 pxout = px - m_g * ( x + m_taper*0.5_prt * (powi<2>(x) + powi<2>(y)) );
149
150 // yout = y;
151 pyout = py - m_g * ( y + m_taper * x * y );
152
153 // tout = t;
154 // ptout = pt;
155
156 // assign updated values
157 // x = xout;
158 // y = yout;
159 // t = tout;
160 px = pxout;
161 py = pyout;
162 // pt = ptout;
163 }
164
166 using Thin::operator();
167
168
183 template<typename T_Real=amrex::ParticleReal, typename T_IdCpu=uint64_t>
186 T_Real const & AMREX_RESTRICT x,
187 T_Real const & AMREX_RESTRICT y,
188 T_Real const & AMREX_RESTRICT t,
189 T_Real & AMREX_RESTRICT px,
190 T_Real & AMREX_RESTRICT py,
191 T_Real const & AMREX_RESTRICT pt,
192 T_Real & AMREX_RESTRICT sx,
193 T_Real & AMREX_RESTRICT sy,
194 T_Real & AMREX_RESTRICT sz,
195 T_IdCpu const & AMREX_RESTRICT idcpu,
196 RefPart const & AMREX_RESTRICT refpart
197 ) const
198 {
199 using namespace amrex::literals; // for _rt and _prt
200 using namespace std; // for cmath(float)
201 using amrex::Math::powi;
202
203 // The Thomas-BMT generator is evaluated at the transverse momentum
204 // halfway through the kick, so that reversing the element (negating
205 // the strength) produces the exact inverse rotation.
206 T_Real const px_in = px;
207 T_Real const py_in = py;
208
209 // pure phase-space push (shared with the non-spin operator())
210 (*this)(x, y, t, px, py, pt, idcpu, refpart);
211
212 // transverse momenta at the kick midpoint
213 T_Real const px_mid = 0.5_prt * (px_in + px);
214 T_Real const py_mid = 0.5_prt * (py_in + py);
215
216 // initialize the three components of the axis-angle vector
217 T_Real lambdax = 0_prt;
218 T_Real lambday = 0_prt;
219 T_Real lambdaz = 0_prt;
220
221 // compute multipole magnetic field normalized by q/mc:
222 amrex::ParticleReal const gamma_ref = refpart.gamma();
223 T_Real const Bx = -m_g * ( y + m_taper * x * y ) * gamma_ref * m_beta;
224 T_Real const By = m_g * ( x + m_taper*0.5_prt * (powi<2>(x) + powi<2>(y)) ) * gamma_ref * m_beta;
225 T_Real const Bz = 0_prt;
226
227 // Electric field normalized by q/mc^2:
228 T_Real const Ex = 0.0_prt;
229 T_Real const Ey = 0.0_prt;
230 T_Real const Ez = 0.0_prt;
231
232 // Quantities required to evaluate the full Thomas-BMT precession
233 // vector, at the midpoint transverse momentum.
234 T_Real const Pnorm = sqrt(1_prt - 2_prt * pt * m_ibeta + pt*pt);
235 T_Real const iPnorm = 1_prt/Pnorm;
236 T_Real const Ps = sqrt(Pnorm*Pnorm - px_mid*px_mid - py_mid*py_mid);
237 T_Real const gamma = gamma_ref * (1_prt - pt*m_beta);
238 T_Real const ux = px_mid * iPnorm;
239 T_Real const uy = py_mid * iPnorm;
240 T_Real const uz = Ps * iPnorm;
241
242 // Zero curvature in a quadrupole
243 amrex::ParticleReal const h = 0.0_prt;
244
245 // Evaluation of the full Thomas-BMT precession vector.
246 amrex::ParticleReal const gyro_anomaly = refpart.gyromagnetic_anomaly;
247 tbmt_precession_vector(x, ux, uy, uz, gamma, h, gyro_anomaly, Bx, By, Bz, Ex, Ey, Ez, lambdax, lambday, lambdaz);
248
249 // push the spin vector using the generator just determined
250 rotate_spin(lambdax, lambday, lambdaz, sx, sy, sz);
251
252 }
253
254
256 using LinearTransport::operator();
257
292 Map6x6
293 transport_map (RefPart const & AMREX_RESTRICT refpart) const
294 {
295 using namespace amrex::literals; // for _rt and _prt
296
297 // Normalize focusing strength to MAD-X convention if needed.
298 amrex::ParticleReal const g = (m_unit == 1)
299 ? m_k / refpart.rigidity_Tm()
300 : m_k;
301
302 // Linearized axisymmetric focusing kick; taper is quadratic
303 // and therefore absent from the linear map.
305 R(2,1) = -g;
306 R(4,3) = -g;
307
308 // apply the transverse rotation (roll) alignment error
309 return rotate_aligned_map(R);
310 }
311
314 int m_unit;
315
316 private:
317 // constants that are independent of the individually tracked particle
321 };
322
323} // namespace impactx
324
326
327#endif // IMPACTX_TAPEREDPL_H
#define AMREX_FORCE_INLINE
#define AMREX_RESTRICT
#define AMREX_GPU_HOST_DEVICE
#define AMREX_GPU_HOST
#define IMPACTX_PUSH_EXTERN_TEMPLATE(ElementType)
Definition PushAll.H:78
amrex_particle_real ParticleReal
constexpr T powi(T x) noexcept
__host__ __device__ GpuComplex< T > sqrt(const GpuComplex< T > &a_z) noexcept
Definition All.H:55
@ t
fixed t as the independent variable
Definition ImpactXParticleContainer.H:38
amrex::SmallMatrix< amrex::ParticleReal, 6, 6, amrex::Order::F, 1 > Map6x6
Definition CovarianceMatrix.H:20
static constexpr __host__ __device__ SmallMatrix< T, NRows, NCols, ORDER, StartIndex > Identity() noexcept
Definition ReferenceParticle.H:33
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::ParticleReal rigidity_Tm() const
Definition ReferenceParticle.H:260
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::ParticleReal beta() const
Definition ReferenceParticle.H:151
Definition TaperedPL.H:45
amrex::ParticleReal m_k
Definition TaperedPL.H:312
amrex::ParticleReal m_ibeta
relativistic beta
Definition TaperedPL.H:319
static constexpr auto type
Definition TaperedPL.H:46
ImpactXParticleContainer::ParticleType PType
Definition TaperedPL.H:47
void compute_constants(RefPart const &refpart)
Definition TaperedPL.H:91
TaperedPL(amrex::ParticleReal k, amrex::ParticleReal taper, int unit=DEFAULT_unit, amrex::ParticleReal dx=DEFAULT_dx, amrex::ParticleReal dy=DEFAULT_dy, amrex::ParticleReal rotation_degree=DEFAULT_rotation_degree, std::optional< std::string > name=DEFAULT_name)
Definition TaperedPL.H:66
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void spin_and_phasespace_push(T_Real const &AMREX_RESTRICT x, T_Real const &AMREX_RESTRICT y, T_Real const &AMREX_RESTRICT t, T_Real &AMREX_RESTRICT px, T_Real &AMREX_RESTRICT py, T_Real const &AMREX_RESTRICT pt, T_Real &AMREX_RESTRICT sx, T_Real &AMREX_RESTRICT sy, T_Real &AMREX_RESTRICT sz, T_IdCpu const &AMREX_RESTRICT idcpu, RefPart const &AMREX_RESTRICT refpart) const
Definition TaperedPL.H:185
AMREX_GPU_HOST AMREX_FORCE_INLINE Map6x6 transport_map(RefPart const &AMREX_RESTRICT refpart) const
Definition TaperedPL.H:293
static constexpr int DEFAULT_unit
Definition TaperedPL.H:49
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void operator()(T_Real const &AMREX_RESTRICT x, T_Real const &AMREX_RESTRICT y, T_Real const &AMREX_RESTRICT t, T_Real &AMREX_RESTRICT px, T_Real &AMREX_RESTRICT py, T_Real const &AMREX_RESTRICT pt, T_IdCpu const &AMREX_RESTRICT idcpu, RefPart const &AMREX_RESTRICT refpart) const
Definition TaperedPL.H:123
amrex::ParticleReal m_g
inverse of beta
Definition TaperedPL.H:320
void reverse()
Definition TaperedPL.H:82
amrex::ParticleReal m_beta
units for linear focusing strength (field gradient)
Definition TaperedPL.H:318
amrex::ParticleReal m_taper
linear focusing strength (field gradient)
Definition TaperedPL.H:313
int m_unit
horizontal taper parameter
Definition TaperedPL.H:314
Definition alignment.H:29
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::ParticleReal dy() const
Definition alignment.H:193
static constexpr amrex::ParticleReal DEFAULT_dy
Definition alignment.H:34
static constexpr amrex::ParticleReal DEFAULT_dx
Definition alignment.H:33
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::ParticleReal dx() const
Definition alignment.H:183
AMREX_GPU_HOST AMREX_FORCE_INLINE Map6x6 rotate_aligned_map(Map6x6 const &R) const
Definition alignment.H:267
Alignment(amrex::ParticleReal dx, amrex::ParticleReal dy, amrex::ParticleReal rotation_degree)
Definition alignment.H:43
static constexpr amrex::ParticleReal DEFAULT_rotation_degree
Definition alignment.H:35
Definition beamoptic.H:567
Definition lineartransport.H:50
Definition named.H:29
static constexpr std::nullopt_t DEFAULT_name
Definition named.H:30
AMREX_GPU_HOST Named(std::optional< std::string > name)
Definition named.H:59
AMREX_FORCE_INLINE std::string name() const
Definition named.H:124
Definition nofinalize.H:22
Definition spintransport.H:36
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void tbmt_precession_vector(T_Real const &AMREX_RESTRICT x, T_Real const &AMREX_RESTRICT ux, T_Real const &AMREX_RESTRICT uy, T_Real const &AMREX_RESTRICT uz, T_Real const &AMREX_RESTRICT gamma, amrex::ParticleReal const &AMREX_RESTRICT h, amrex::ParticleReal const &AMREX_RESTRICT gyro_anomaly, T_Real const &AMREX_RESTRICT Bx, T_Real const &AMREX_RESTRICT By, T_Real const &AMREX_RESTRICT Bz, T_Real const &AMREX_RESTRICT Ex, T_Real const &AMREX_RESTRICT Ey, T_Real const &AMREX_RESTRICT Ez, T_Real &AMREX_RESTRICT Omegax, T_Real &AMREX_RESTRICT Omegay, T_Real &AMREX_RESTRICT Omegaz) const
Definition spintransport.H:121
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void rotate_spin(T_Real const &AMREX_RESTRICT lambdax, T_Real const &AMREX_RESTRICT lambday, T_Real const &AMREX_RESTRICT lambdaz, T_Real &AMREX_RESTRICT sx, T_Real &AMREX_RESTRICT sy, T_Real &AMREX_RESTRICT sz) const
Definition spintransport.H:48
Definition thin.H:24