Skip to content

Commit cf4c20b

Browse files
cemitch99pre-commit-ci[bot]ax3l
authored
Spin push for TaperedPL (#1433)
* Add TaperedPL spin push. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Delete unused commented lines. * Apply suggestions from review. * Apply suggestions from code review Co-authored-by: Axel Huebl <axel.huebl@plasma.ninja> --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Axel Huebl <axel.huebl@plasma.ninja>
1 parent ba130b6 commit cf4c20b

1 file changed

Lines changed: 105 additions & 0 deletions

File tree

src/elements/TaperedPL.H

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "mixin/beamoptic.H"
1616
#include "mixin/thin.H"
1717
#include "mixin/lineartransport.H"
18+
#include "mixin/spintransport.H"
1819
#include "mixin/named.H"
1920
#include "mixin/nofinalize.H"
2021

@@ -35,6 +36,7 @@ namespace impactx::elements
3536
public mixin::LinearTransport<TaperedPL>,
3637
public mixin::Thin,
3738
public mixin::Alignment,
39+
public mixin::SpinTransport,
3840
public mixin::NoFinalize
3941
// At least on Intel AVX512, there is a small overhead to vectorize this element, see
4042
// https://github.com/BLAST-ImpactX/impactx/pull/1002
@@ -76,6 +78,28 @@ namespace impactx::elements
7678
/** Reverse the element (negate strength) */
7779
void reverse () { m_k = -m_k; }
7880

81+
/** Compute and cache the constants for the push.
82+
*
83+
* In particular, used to pre-compute and cache variables that are
84+
* independent of the individually tracked particle.
85+
*
86+
* @param refpart reference particle
87+
*/
88+
void compute_constants (RefPart const & refpart)
89+
{
90+
using namespace amrex::literals; // for _rt and _prt
91+
92+
Alignment::compute_constants(refpart);
93+
94+
// normalize focusing strength units to MAD-X convention if needed
95+
m_g = m_unit == 1 ? m_k / refpart.rigidity_Tm() : m_k;
96+
97+
// additional constants needed for spin push
98+
m_beta = refpart.beta();
99+
m_ibeta = 1_prt / m_beta;
100+
101+
}
102+
79103
/** Push all particles */
80104
using BeamOptic::operator();
81105

@@ -150,6 +174,81 @@ namespace impactx::elements
150174
/** This pushes the reference particle. */
151175
using Thin::operator();
152176

177+
178+
/** This operator pushes the particle spin.
179+
*
180+
* @param x particle position in x
181+
* @param y particle position in y
182+
* @param t particle position in t
183+
* @param px particle momentum in x
184+
* @param py particle momentum in y
185+
* @param pt particle momentum in t
186+
* @param sx particle spin x-component
187+
* @param sy particle spin y-component
188+
* @param sz particle spin z-component
189+
* @param idcpu particle global index
190+
* @param refpart reference particle
191+
*/
192+
template<typename T_Real=amrex::ParticleReal, typename T_IdCpu=uint64_t>
193+
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
194+
void spin_and_phasespace_push (
195+
T_Real & AMREX_RESTRICT x,
196+
T_Real & AMREX_RESTRICT y,
197+
T_Real & AMREX_RESTRICT t,
198+
T_Real & AMREX_RESTRICT px,
199+
T_Real & AMREX_RESTRICT py,
200+
T_Real & AMREX_RESTRICT pt,
201+
T_Real & AMREX_RESTRICT sx,
202+
T_Real & AMREX_RESTRICT sy,
203+
T_Real & AMREX_RESTRICT sz,
204+
[[maybe_unused]] T_IdCpu & AMREX_RESTRICT idcpu,
205+
RefPart const & AMREX_RESTRICT refpart
206+
) const
207+
{
208+
using namespace amrex::literals; // for _rt and _prt
209+
using amrex::Math::powi;
210+
211+
// initialize the three components of the axis-angle vector
212+
T_Real lambdax = 0_prt;
213+
T_Real lambday = 0_prt;
214+
T_Real lambdaz = 0_prt;
215+
216+
// compute multipole magnetic field normalized by q/mc:
217+
amrex::ParticleReal gamma_ref = refpart.gamma();
218+
T_Real const Bx = m_g * ( y + m_taper * x * y ) * gamma_ref * m_beta;
219+
T_Real const By = -m_g * ( x + m_taper*0.5_prt * (powi<2>(x) + powi<2>(y)) ) * gamma_ref * m_beta;
220+
T_Real const Bz = 0_prt;
221+
222+
// Electric field normalized by q/mc^2:
223+
T_Real const Ex = 0.0_prt;
224+
T_Real const Ey = 0.0_prt;
225+
T_Real const Ez = 0.0_prt;
226+
227+
// Quantities required to evaluate the full Thomas-BMT precession vector.
228+
T_Real const Pnorm = sqrt(1_prt - 2_prt * pt * m_ibeta + pt*pt);
229+
T_Real const iPnorm = 1_prt/Pnorm;
230+
T_Real const Ps = sqrt(Pnorm*Pnorm - px*px - py*py);
231+
T_Real const gamma = gamma_ref * (1_prt - pt*m_beta);
232+
T_Real const ux = px * iPnorm;
233+
T_Real const uy = py * iPnorm;
234+
T_Real const uz = Ps * iPnorm;
235+
236+
// Zero curvature in a quadrupole
237+
amrex::ParticleReal const h = 0.0_prt;
238+
239+
// Evaluation of the full Thomas-BMT precession vector.
240+
amrex::ParticleReal gyro_anomaly = refpart.gyromagnetic_anomaly;
241+
tbmt_precession_vector(x, ux, uy, uz, gamma, h, gyro_anomaly, Bx, By, Bz, Ex, Ey, Ez, lambdax, lambday, lambdaz);
242+
243+
// push the spin vector using the generator just determined
244+
rotate_spin(lambdax, lambday, lambdaz, sx, sy, sz);
245+
246+
// phase space push
247+
(*this)(x, y, t, px, py, pt, idcpu, refpart);
248+
249+
}
250+
251+
153252
/** This pushes the covariance matrix. */
154253
using LinearTransport::operator();
155254

@@ -209,6 +308,12 @@ for beam-quality preservation between plasma-accelerator stages",
209308
amrex::ParticleReal m_k; //! linear focusing strength (field gradient)
210309
amrex::ParticleReal m_taper; //! horizontal taper parameter
211310
int m_unit; //! units for linear focusing strength (field gradient)
311+
312+
private:
313+
// constants that are independent of the individually tracked particle
314+
amrex::ParticleReal m_beta; //! relativistic beta
315+
amrex::ParticleReal m_ibeta; //! inverse of beta
316+
amrex::ParticleReal m_g; //! quadrupole strength
212317
};
213318

214319
} // namespace impactx

0 commit comments

Comments
 (0)