Skip to content

Commit 8602239

Browse files
committed
Add spin sampling algorithm.
1 parent 37d09ba commit 8602239

File tree

2 files changed

+126
-1
lines changed

2 files changed

+126
-1
lines changed

src/particles/distribution/All.H

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "Thermal.H"
2020
#include "Triangle.H"
2121
#include "Waterbag.H"
22+
#include "SpinvMF.H"
2223

2324
#include <variant>
2425

@@ -34,7 +35,8 @@ namespace impactx::distribution
3435
Thermal,
3536
Triangle,
3637
Semigaussian,
37-
Waterbag
38+
Waterbag,
39+
SpinvMF
3840
>;
3941

4042
} // namespace impactx::distribution
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
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, Axel Huebl
8+
* License: BSD-3-Clause-LBNL
9+
*/
10+
#ifndef IMPACTX_DISTRIBUTION_SPINVMF
11+
#define IMPACTX_DISTRIBUTION_SPINVMF
12+
13+
#include <ablastr/constant.H>
14+
15+
#include <AMReX_Math.H>
16+
#include <AMReX_Random.H>
17+
#include <AMReX_REAL.H>
18+
19+
#include <cmath>
20+
21+
22+
namespace impactx::distribution
23+
{
24+
struct SpinvMF
25+
{
26+
/** A von Mises-Fisher (vMF) distribution on the unit 2-sphere.
27+
* This is used for initializing particle spin. There is a natural
28+
* bijective correspondence between vMF distributions and mean
29+
* (polarization) vectors.
30+
*
31+
* Return sampling from a vMF distribution.
32+
*
33+
* @param mux,muy,muz components of a unit vector specifying the mean direction
34+
* @param kappa concentration parameter
35+
*/
36+
SpinvMF (
37+
amrex::ParticleReal mux,
38+
amrex::ParticleReal muy,
39+
amrex::ParticleReal muz,
40+
amrex::ParticleReal kappa
41+
)
42+
: m_muX(mux), m_muY(muy), m_muZ(muz), m_kappa(kappa)
43+
{
44+
}
45+
46+
/** Initialize the distribution.
47+
*
48+
* Nothing to do here.
49+
*
50+
* @param bunch_charge charge of the beam in C
51+
* @param ref the reference particle
52+
*/
53+
void initialize ([[maybe_unused]] amrex::ParticleReal bunch_charge, [[maybe_unused]] RefPart const & ref)
54+
{
55+
}
56+
57+
/** Close and deallocate all data and handles.
58+
*
59+
* Nothing to do here.
60+
*/
61+
void
62+
finalize ()
63+
{
64+
}
65+
66+
/** Return 1 3D spin (unit) vector
67+
*
68+
* @param sx particle spin component in x
69+
* @param sy particle spin component in y
70+
* @param sz particle spin component in z
71+
* @param engine a random number engine (with associated state)
72+
*/
73+
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
74+
void operator() (
75+
amrex::ParticleReal & AMREX_RESTRICT sx,
76+
amrex::ParticleReal & AMREX_RESTRICT sy,
77+
amrex::ParticleReal & AMREX_RESTRICT sz,
78+
amrex::RandomEngine const & engine
79+
) const
80+
{
81+
using namespace amrex::literals;
82+
using amrex::Math::powi;
83+
using ablastr::constant::math::pi;
84+
85+
// Normalize the mean direction vector just in case:
86+
amrex::ParticleReal mu_norm = std::sqrt(powi<2>(m_muX)+powi<2>(m_muY)+powi<2>(m_muZ));
87+
amrex::ParticleReal mux = m_muX/mu_norm;
88+
amrex::ParticleReal muy = m_muY/mu_norm;
89+
amrex::ParticleReal muz = m_muZ/mu_norm;
90+
91+
// Evaluate constants independent of particle:
92+
amrex::ParticleReal const muperp = std::sqrt(powi<2>(mux)+powi<2>(muy));
93+
amrex::ParticleReal const a = (muperp==0) ? 0_prt : mux/muperp;
94+
amrex::ParticleReal const b = (muperp==0) ? 1_prt : muy/muperp;
95+
96+
// Sample two iid random variables:
97+
amrex::ParticleReal x1 = amrex::Random(engine);
98+
amrex::ParticleReal x2 = amrex::Random(engine);
99+
100+
// Basic transformation of the random variables:
101+
amrex::ParticleReal c = std::cos(2_prt*pi*x1);
102+
amrex::ParticleReal s = std::sin(2_prt*pi*x1);
103+
amrex::ParticleReal t;
104+
if(m_kappa > 0) {
105+
t = 1_prt + std::log1p(x2 * std::expm1(-2*m_kappa))/m_kappa;
106+
} else {
107+
t = 1_prt - 2_prt * x2;
108+
}
109+
110+
// Evaluation of the spin components
111+
amrex::ParticleReal u=std::sqrt(1_prt-powi<2>(t));
112+
sx = u * (b*c + a*muz*s) + t*mux;
113+
sy = u * (-a*c + b*muz*s) + t*muy;
114+
sz = u * (-muperp*s) + t*muz;
115+
116+
}
117+
118+
amrex::ParticleReal m_muX, m_muY, m_muZ, m_kappa; //! parameters specifying the vMF distribution
119+
};
120+
121+
} // namespace impactx::distribution
122+
123+
#endif // IMPACTX_DISTRIBUTION_SPINVMF

0 commit comments

Comments
 (0)