|
| 1 | +/* Copyright 2022-2023 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 |
| 8 | + * License: BSD-3-Clause-LBNL |
| 9 | + */ |
| 10 | +#ifndef IMPACTX_ELEMENTS_MIXIN_SPIN_TRANSPORT_H |
| 11 | +#define IMPACTX_ELEMENTS_MIXIN_SPIN_TRANSPORT_H |
| 12 | + |
| 13 | +#include "particles/ImpactXParticleContainer.H" |
| 14 | + |
| 15 | +#include <ablastr/constant.H> |
| 16 | + |
| 17 | +#include <AMReX_Math.H> |
| 18 | +#include <AMReX_Extension.H> |
| 19 | +#include <AMReX_REAL.H> |
| 20 | + |
| 21 | +namespace impactx::elements::mixin |
| 22 | +{ |
| 23 | + /** This is a helper class for applying a spin map generated by a three-component vector |
| 24 | + * lambda, whose magnitude defines the angle of rotation and whose direction defines |
| 25 | + * the axis of rotation. |
| 26 | + */ |
| 27 | + struct SpinTransport |
| 28 | + { |
| 29 | + /** Rotate the spin vector (sx,sy,sz). |
| 30 | + * |
| 31 | + * @param[in] lambdax generator x-component |
| 32 | + * @param[in] lambday generator y-component |
| 33 | + * @param[in] lambdaz generator z-component |
| 34 | + * @param[inout] sx spin vector x-component |
| 35 | + * @param[inout] sy spin vector y-component |
| 36 | + * @param[inout] sz spin vector z-component |
| 37 | + */ |
| 38 | + template<typename T_Real> |
| 39 | + AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE |
| 40 | + void rotate_spin ( |
| 41 | + amrex::ParticleReal lambdax, |
| 42 | + amrex::ParticleReal lambday, |
| 43 | + amrex::ParticleReal lambdaz, |
| 44 | + amrex::ParticleReal sx, |
| 45 | + amrex::ParticleReal sy, |
| 46 | + amrex::ParticleReal sz |
| 47 | + ) const |
| 48 | + { |
| 49 | + using namespace amrex::literals; // for _prt |
| 50 | + |
| 51 | + // Compute quaternion coefficients |
| 52 | + amrex::ParticleReal angle = std::sqrt(lambdax*lambdax+lambday*lambday+lambdaz*lambdaz); |
| 53 | + auto const [sin_half_angle, cos_half_angle] = amrex::Math::sincos(angle/2_prt); |
| 54 | + amrex::ParticleReal w0 = cos_half_angle; |
| 55 | + amrex::ParticleReal w1 = (theta==0_prt) ? 0_prt : (lambdax/theta)*sin_half_angle; |
| 56 | + amrex::ParticleReal w2 = (theta==0_prt) ? 0_prt : (lambday/theta)*sin_half_angle; |
| 57 | + amrex::ParticleReal w3 = (theta==0_prt) ? 0_prt : (lambdaz/theta)*sin_half_angle; |
| 58 | + |
| 59 | + // Apply rotation |
| 60 | + amrex::ParticleReal sxout = (1_prt-2_prt*(w2*w2+w3*w3))*sx + 2_prt*(w1*w2+w0*w3)*sy + 2_prt*(w1*w3-w0*w2)*sz; |
| 61 | + amrex::ParticleReal syout = 2_prt*(w1*w2-w0*w3)*sx + (1_prt-2_prt*(w1*w1+w3*w3))*sy + 2_prt*(w0*w1+w2*w3)*sz; |
| 62 | + amrex::ParticleReal szout = 2_prt*(w0*w2+w1*w3)*sx + 2_prt*(w2*w3-w0*w1)*sy + (1_prt-2_prt*(w1*w1+w2*w2))*sz; |
| 63 | + |
| 64 | + // Update spin vector |
| 65 | + sx = sxout; |
| 66 | + sy = syout; |
| 67 | + sz = szout; |
| 68 | + } |
| 69 | + |
| 70 | + }; |
| 71 | + |
| 72 | +} // namespace impactx::elements::mixin |
| 73 | + |
| 74 | +#endif // IMPACTX_ELEMENTS_MIXIN_SPIN_TRANSPORT_H |
0 commit comments