WarpX
Loading...
Searching...
No Matches
ParticleBoundaries_K.H
Go to the documentation of this file.
1/* Copyright 2021 David Grote, Remi Lehe, Revathi Jambunathan
2 *
3 * This file is part of WarpX.
4 *
5 * License: BSD-3-Clause-LBNL
6 */
7#ifndef WARPX_PARTICLEBOUNDARIES_K_H_
8#define WARPX_PARTICLEBOUNDARIES_K_H_
9
10#include "ParticleBoundaries.H"
12
13#include <AMReX_AmrCore.H>
14
16 using namespace amrex::literals;
17 /* \brief Applies the boundary condition on a specific axis
18 * This is called by apply_boundaries.
19 */
21 void
22 apply_boundary (amrex::ParticleReal& x, amrex::Real xmin, amrex::Real xmax,
23 bool& change_sign_ux, bool& rethermalize_x, bool& particle_lost,
25 amrex::Real refl_probability_xmin, amrex::Real refl_probability_xmax,
26 amrex::RandomEngine const& engine )
27 {
28 if (x < xmin) {
29 if (xmin_bc == ParticleBoundaryType::Open) {
30 particle_lost = true;
31 }
32 else if (xmin_bc == ParticleBoundaryType::Absorbing) {
33 if (refl_probability_xmin == 0 || amrex::Random(engine) > refl_probability_xmin) {
34 particle_lost = true;
35 }
36 else
37 {
38 x = 2*xmin - x;
39 change_sign_ux = true;
40 }
41 }
42 else if (xmin_bc == ParticleBoundaryType::Reflecting) {
43 x = 2*xmin - x;
44 change_sign_ux = true;
45 }
46 else if (xmin_bc == ParticleBoundaryType::Thermal) {
47 x = 2*xmin - x;
48 rethermalize_x = true;
49 }
50 }
51 else if (x > xmax) {
52 if (xmax_bc == ParticleBoundaryType::Open) {
53 particle_lost = true;
54 }
55 else if (xmax_bc == ParticleBoundaryType::Absorbing) {
56 if (refl_probability_xmax == 0 || amrex::Random(engine) > refl_probability_xmax) {
57 particle_lost = true;
58 }
59 else
60 {
61 x = 2*xmax - x;
62 change_sign_ux = true;
63 }
64 }
65 else if (xmax_bc == ParticleBoundaryType::Reflecting) {
66 x = 2*xmax - x;
67 change_sign_ux = true;
68 }
69 else if (xmax_bc == ParticleBoundaryType::Thermal) {
70 x = 2*xmax - x;
71 rethermalize_x = true;
72 }
73 }
74 }
75
76 /* \brief Thermalize particles that have been identified to cross the boundary.
77 * The normal component samples from a half-Maxwellian,
78 * and the two tangential components will sample from full Maxwellian disbutions
79 * with thermal velocity uth
80 */
82 void thermalize_boundary_particle (amrex::ParticleReal& u_norm, amrex::ParticleReal& u_tang1,
83 amrex::ParticleReal& u_tang2, amrex::Real uth,
84 amrex::RandomEngine const& engine)
85 {
86 u_tang1 = (uth > 0._rt) ? PhysConst::c * amrex::RandomNormal(0._rt, uth, engine) : 0._rt;
87 u_tang2 = (uth > 0._rt) ? PhysConst::c * amrex::RandomNormal(0._rt, uth, engine) : 0._rt;
88 u_norm = (uth > 0._rt) ? std::copysign(1._prt, -u_norm) * PhysConst::c * generateGaussianFluxDist(0._rt, uth, engine) : 0._rt;
89 }
90
91
92 /* \brief Applies absorbing, reflecting or thermal boundary condition to the input particles, along all axis.
93 * For reflecting boundaries, the position of the particle is changed appropriately and
94 * the sign of the velocity is changed (depending on the reflect_all_velocities flag).
95 * For absorbing, a flag is set whether the particle has been lost (it is up to the calling
96 * code to take appropriate action to remove any lost particles). Absorbing boundaries can
97 * be given a reflection coefficient for stochastic reflection of particles, this
98 * coefficient is zero by default.
99 * For thermal boundaries, the particle is first reflected and the position of the particle
100 * is changed appropriately.
101 * Note that periodic boundaries are handled in AMReX code.
102 *
103 * \param x, xmin, xmax: particle x position, location of x boundary
104 * \param y, ymin, ymax: particle y position, location of y boundary (3D only)
105 * \param z, zmin, zmax: particle z position, location of z boundary
106 * \param ux, uy, uz: particle momenta
107 * \param particle_lost: output, flags whether the particle was lost
108 * \param boundaries: object with boundary condition settings
109 */
111 void
112 apply_boundaries ([[maybe_unused]] amrex::ParticleReal& x,
113 [[maybe_unused]] amrex::ParticleReal& y,
114 [[maybe_unused]] amrex::ParticleReal& z,
115 amrex::XDim3 gridmin, amrex::XDim3 gridmax,
116 amrex::ParticleReal& ux, amrex::ParticleReal& uy, amrex::ParticleReal& uz,
117 bool& particle_lost,
119 amrex::RandomEngine const& engine)
120 {
121 bool change_sign_ux = false;
122 bool change_sign_uy = false;
123 bool change_sign_uz = false;
124
125#ifndef WARPX_DIM_1D_Z
126 bool rethermalize_x = false; // stores if particle crosses x boundary and needs to be thermalized
127 apply_boundary(x, gridmin.x, gridmax.x, change_sign_ux, rethermalize_x, particle_lost,
128 boundaries.xmin_bc, boundaries.xmax_bc,
129 boundaries.reflection_model_xlo(-ux), boundaries.reflection_model_xhi(ux),
130 engine);
131 if (rethermalize_x) {
132 thermalize_boundary_particle(ux, uy, uz, boundaries.m_uth, engine);
133 }
134#endif
135#ifdef WARPX_DIM_3D
136 bool rethermalize_y = false; // stores if particle crosses y boundary and needs to be thermalized
137 apply_boundary(y, gridmin.y, gridmax.y, change_sign_uy, rethermalize_y, particle_lost,
138 boundaries.ymin_bc, boundaries.ymax_bc,
139 boundaries.reflection_model_ylo(-uy), boundaries.reflection_model_yhi(uy),
140 engine);
141 if (rethermalize_y) {
142 thermalize_boundary_particle(uy, uz, ux, boundaries.m_uth, engine);
143 }
144#endif
145#if defined(WARPX_ZINDEX)
146 bool rethermalize_z = false; // stores if particle crosses z boundary and needs to be thermalized
147 apply_boundary(z, gridmin.z, gridmax.z, change_sign_uz, rethermalize_z, particle_lost,
148 boundaries.zmin_bc, boundaries.zmax_bc,
149 boundaries.reflection_model_zlo(-uz), boundaries.reflection_model_zhi(uz),
150 engine);
151 if (rethermalize_z) {
152 thermalize_boundary_particle(uz, ux, uy, boundaries.m_uth, engine);
153 }
154#endif
155
156 if (boundaries.reflect_all_velocities && (change_sign_ux | change_sign_uy | change_sign_uz)) {
157 change_sign_ux = true;
158 change_sign_uy = true;
159 change_sign_uz = true;
160 }
161
162#if defined(WARPX_DIM_RZ) || defined(WARPX_DIM_RCYLINDER)
163 // Note that the reflection of the position does "r = 2*rmax - r", but this is only approximate.
164 // The exact calculation requires the position at the start of the step.
165 if (change_sign_ux && change_sign_uy) {
166 ux = -ux;
167 uy = -uy;
168 } else if (change_sign_ux) {
169 // Reflect only ur
170 // Note that y is theta
171 amrex::Real ur = ux*std::cos(y) + uy*std::sin(y);
172 const amrex::Real ut = -ux*std::sin(y) + uy*std::cos(y);
173 ur = -ur;
174 ux = ur*std::cos(y) - ut*std::sin(y);
175 uy = ur*std::sin(y) + ut*std::cos(y);
176 }
177 if (change_sign_uz) { uz = -uz; }
178#elif defined(WARPX_DIM_RSPHERE)
179 // "y" is theta
180 // "z" is phi
181 const amrex::Real costheta = std::cos(y);
182 const amrex::Real sintheta = std::sin(y);
183 const amrex::Real cosphi = std::cos(z);
184 const amrex::Real sinphi = std::sin(z);
185 amrex::Real ur = +ux*costheta*sinphi + uy*sintheta*sinphi + uz*cosphi;
186 amrex::Real ut = -ux*sintheta + uy*costheta;
187 amrex::Real up = -ux*costheta*cosphi - uy*sintheta*cosphi + uz*sinphi;
188 if (change_sign_ux) { ur = -ur; }
189 if (change_sign_uy) { ut = -ut; }
190 if (change_sign_uz) { up = -up; }
191 ux = sinphi*costheta*ur - sintheta*ut - cosphi*costheta*up;
192 uy = sinphi*sintheta*ur + costheta*ut - cosphi*sintheta*up;
193 uz = cosphi*ur + sinphi*up;
194#else
195 if (change_sign_ux) { ux = -ux; }
196 if (change_sign_uy) { uy = -uy; }
197 if (change_sign_uz) { uz = -uz; }
198#endif
199 }
200
201}
202#endif //WARPX_PARTICLEBOUNDARIES_K_H_
#define AMREX_FORCE_INLINE
#define AMREX_GPU_HOST_DEVICE
ParticleBoundaryType
Definition WarpXAlgorithmSelection.H:146
@ Absorbing
Definition WarpXAlgorithmSelection.H:146
@ Reflecting
Definition WarpXAlgorithmSelection.H:148
@ Open
Definition WarpXAlgorithmSelection.H:147
@ Thermal
Definition WarpXAlgorithmSelection.H:150
Definition ParticleBoundaries_K.H:15
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void thermalize_boundary_particle(amrex::ParticleReal &u_norm, amrex::ParticleReal &u_tang1, amrex::ParticleReal &u_tang2, amrex::Real uth, amrex::RandomEngine const &engine)
Definition ParticleBoundaries_K.H:82
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void apply_boundary(amrex::ParticleReal &x, amrex::Real xmin, amrex::Real xmax, bool &change_sign_ux, bool &rethermalize_x, bool &particle_lost, ParticleBoundaryType xmin_bc, ParticleBoundaryType xmax_bc, amrex::Real refl_probability_xmin, amrex::Real refl_probability_xmax, amrex::RandomEngine const &engine)
Definition ParticleBoundaries_K.H:22
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void apply_boundaries(amrex::ParticleReal &x, amrex::ParticleReal &y, amrex::ParticleReal &z, amrex::XDim3 gridmin, amrex::XDim3 gridmax, amrex::ParticleReal &ux, amrex::ParticleReal &uy, amrex::ParticleReal &uz, bool &particle_lost, ParticleBoundaries::ParticleBoundariesData const &boundaries, amrex::RandomEngine const &engine)
Definition ParticleBoundaries_K.H:112
static constexpr auto c
vacuum speed of light [m/s]
Definition constant.H:44
Real Random()
Real RandomNormal(Real mean, Real stddev)
Definition ParticleBoundaries.H:74
bool reflect_all_velocities
Definition ParticleBoundaries.H:91
amrex::ParserExecutor< 1 > reflection_model_ylo
Definition ParticleBoundaries.H:86
ParticleBoundaryType ymax_bc
Definition ParticleBoundaries.H:79
amrex::Real m_uth
Definition ParticleBoundaries.H:82
ParticleBoundaryType xmin_bc
Definition ParticleBoundaries.H:76
amrex::ParserExecutor< 1 > reflection_model_zhi
Definition ParticleBoundaries.H:89
ParticleBoundaryType xmax_bc
Definition ParticleBoundaries.H:77
amrex::ParserExecutor< 1 > reflection_model_xhi
Definition ParticleBoundaries.H:85
ParticleBoundaryType zmax_bc
Definition ParticleBoundaries.H:81
amrex::ParserExecutor< 1 > reflection_model_zlo
Definition ParticleBoundaries.H:88
ParticleBoundaryType ymin_bc
Definition ParticleBoundaries.H:78
amrex::ParserExecutor< 1 > reflection_model_xlo
Definition ParticleBoundaries.H:84
ParticleBoundaryType zmin_bc
Definition ParticleBoundaries.H:80
amrex::ParserExecutor< 1 > reflection_model_yhi
Definition ParticleBoundaries.H:87