Skip to content

Commit 1b3524d

Browse files
committed
Add spin push operator.
1 parent 5721e60 commit 1b3524d

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

src/elements/Quad.H

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "mixin/named.H"
1919
#include "mixin/nofinalize.H"
2020
#include "mixin/lineartransport.H"
21+
#include "mixin/spintransport.H"
2122

2223
#include <AMReX_Extension.H>
2324
#include <AMReX_Math.H>
@@ -36,6 +37,7 @@ namespace impactx::elements
3637
public mixin::Thick,
3738
public mixin::Alignment,
3839
public mixin::PipeAperture,
40+
public mixin::SpinTransport,
3941
public mixin::NoFinalize
4042
// At least on Intel AVX512, there is a small overhead to vectorize this element for DP and a gain for SP, see
4143
// https://github.com/BLAST-ImpactX/impactx/pull/1002
@@ -289,6 +291,84 @@ namespace impactx::elements
289291
return R;
290292
}
291293

294+
/** This operator pushes the particle spin.
295+
*
296+
* @param x particle position in x
297+
* @param y particle position in y
298+
* @param t particle position in t
299+
* @param px particle momentum in x
300+
* @param py particle momentum in y
301+
* @param pt particle momentum in t
302+
* @param sx particle spin x-component
303+
* @param sy particle spin y-component
304+
* @param sz particle spin z-component
305+
* @param idcpu particle global index
306+
* @param refpart reference particle (unused)
307+
*/
308+
template<typename T_Real=amrex::ParticleReal, typename T_IdCpu=uint64_t>
309+
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
310+
void operator() (
311+
T_Real & AMREX_RESTRICT x,
312+
T_Real & AMREX_RESTRICT y,
313+
T_Real & AMREX_RESTRICT t,
314+
T_Real & AMREX_RESTRICT px,
315+
T_Real & AMREX_RESTRICT py,
316+
T_Real & AMREX_RESTRICT pt,
317+
T_Real & AMREX_RESTRICT sx,
318+
T_Real & AMREX_RESTRICT sy,
319+
T_Real & AMREX_RESTRICT sz,
320+
T_IdCpu & AMREX_RESTRICT idcpu,
321+
[[maybe_unused]] RefPart const & AMREX_RESTRICT refpart
322+
) const
323+
{
324+
using namespace amrex::literals; // for _rt and _prt
325+
326+
// initialize the three components of the axis-angle vector
327+
T_Real lambdax = 0_prt;
328+
T_Real lambday = 0_prt;
329+
T_Real lambdaz = 0_prt;
330+
331+
// the value of the gyromagnetic anomaly (TO BE PASSED FROM USER INPUT)
332+
// currently, the default value for electrons is used
333+
amrex::ParticleReal G = 0.00115965218046;
334+
amrex::ParticleReal const gyro_const = 1_prt + G * refpart.gamma();
335+
336+
// length of the current slice
337+
amrex::ParticleReal const slice_ds = m_ds / nslice();
338+
339+
// compute phase advance per unit length in s (in rad/m)
340+
amrex::ParticleReal const omega = std::sqrt(std::abs(m_k));
341+
342+
// compute trigonometric quantities
343+
sin_omega_ds = std::sin(omega*m_slice_ds);
344+
cos_omega_ds = std::cos(omega*m_slice_ds);
345+
sinh_omega_ds = std::sinh(omega*m_slice_ds);
346+
cosh_omega_ds = std::cosh(omega*m_slice_ds);
347+
348+
if (m_k > 0.0_prt)
349+
{
350+
351+
// horizontally focusing quad case
352+
lambdax = -gyro_const * ( py*(cosh_omega_ds - 1_prt) + y*omega*sinh_omega_ds );
353+
lambday = -gyro_const * ( px*(1_prt - cos_omega_ds) + x*omega*sin_omega_ds );
354+
355+
} else if (m_k < 0.0_prt)
356+
{
357+
358+
// horizontally defocusing quad case
359+
lambdax = -gyro_const * ( px*(1_prt - cos_omega_ds) + x*omega*sin_omega_ds );
360+
lambday = -gyro_const * ( py*(cosh_omega_ds - 1_prt) + y*omega*sinh_omega_ds );
361+
362+
} else {
363+
// treat as a drift
364+
}
365+
366+
// push the spin vector using the generator just determined
367+
rotate_spin(lambdax,lambday,lambdaz,sx,sy,sz);
368+
369+
}
370+
371+
292372
/** This pushes the covariance matrix. */
293373
using LinearTransport::operator();
294374

0 commit comments

Comments
 (0)