WarpX
Loading...
Searching...
No Matches
NodalFieldGather.H
Go to the documentation of this file.
1/* Copyright 2019-2022 Modern Electron, Axel Huebl, Remi Lehe
2 *
3 * This file is part of WarpX.
4 *
5 * License: BSD-3-Clause-LBNL
6 */
7#ifndef ABLASTR_NODALFIELDGATHER_H_
8#define ABLASTR_NODALFIELDGATHER_H_
9
11
12#include <AMReX_Array.H>
13#include <AMReX_Extension.H>
14#include <AMReX_GpuQualifiers.H>
15#include <AMReX_IndexType.H>
16#include <AMReX_Math.H>
17#include <AMReX_REAL.H>
18
19
20namespace ablastr::particles
21{
22
35template <amrex::IndexType::CellIndex IdxType>
37void compute_weights (const amrex::ParticleReal xp,
38 const amrex::ParticleReal yp,
39 const amrex::ParticleReal zp,
42 int& i, int& j, int& k, amrex::Real W[AMREX_SPACEDIM][2]) noexcept
43{
44 using namespace amrex::literals;
45
46 constexpr auto half_if_cell_centered = [](){
47 if constexpr (IdxType == amrex::IndexType::CellIndex::NODE){
48 return 0.0_rt;
49 }
50 else{
51 return 0.5_rt;
52 }
53 }();
54
55#if (defined WARPX_DIM_3D)
56 const amrex::Real x = (xp - plo[0]) * dxi[0] - half_if_cell_centered;
57 const amrex::Real y = (yp - plo[1]) * dxi[1] - half_if_cell_centered;
58 const amrex::Real z = (zp - plo[2]) * dxi[2] - half_if_cell_centered;
59
60 i = static_cast<int>(amrex::Math::floor(x));
61 j = static_cast<int>(amrex::Math::floor(y));
62 k = static_cast<int>(amrex::Math::floor(z));
63
64 W[0][1] = x - i;
65 W[1][1] = y - j;
66 W[2][1] = z - k;
67
68 W[0][0] = 1.0_rt - W[0][1];
69 W[1][0] = 1.0_rt - W[1][1];
70 W[2][0] = 1.0_rt - W[2][1];
71
72#elif defined(WARPX_DIM_XZ) || defined(WARPX_DIM_RZ)
73
74# if (defined WARPX_DIM_XZ)
75 const amrex::Real x = (xp - plo[0]) * dxi[0] - half_if_cell_centered;
77 i = static_cast<int>(amrex::Math::floor(x));
78 W[0][1] = x - i;
79# elif (defined WARPX_DIM_RZ)
80 const amrex::Real r = (std::sqrt(xp*xp+yp*yp) - plo[0]) * dxi[0] - half_if_cell_centered;
81 i = static_cast<int>(amrex::Math::floor(r));
82 W[0][1] = r - i;
83# endif
84
85 const amrex::Real z = (zp - plo[1]) * dxi[1] - half_if_cell_centered;
86 j = static_cast<int>(amrex::Math::floor(z));
87 W[1][1] = z - j;
88
89 W[0][0] = 1.0_rt - W[0][1];
90 W[1][0] = 1.0_rt - W[1][1];
91
92 k = 0;
93
94#elif defined(WARPX_DIM_RCYLINDER)
95
97 const amrex::Real r = (std::sqrt(xp*xp+yp*yp) - plo[0]) * dxi[0] - half_if_cell_centered;
98 i = static_cast<int>(amrex::Math::floor(r));
99 W[0][1] = r - i;
100
101 W[0][0] = 1.0_rt - W[0][1];
102
103 j = 0;
104 k = 0;
105
106#elif defined(WARPX_DIM_RSPHERE)
107
108 const amrex::Real r = (std::sqrt(xp*xp+yp*yp+zp*zp) - plo[0]) * dxi[0] - half_if_cell_centered;
109 i = static_cast<int>(amrex::Math::floor(r));
110 W[0][1] = r - i;
111
112 W[0][0] = 1.0_rt - W[0][1];
113
114 j = 0;
115 k = 0;
116
117#elif (defined WARPX_DIM_1D_Z)
118 const amrex::Real z = (zp - plo[0]) * dxi[0] - half_if_cell_centered;
119 amrex::ignore_unused(xp, yp);
120 i = static_cast<int>(amrex::Math::floor(z));
121
122 W[0][1] = z - i;
123 W[0][0] = 1.0_rt - W[0][1];
124
125 j = 0;
126 k = 0;
127#endif
128}
129
137template<int DIMS = AMREX_SPACEDIM>
139amrex::Real interp_field_nodal (int i, int j, int k,
140 const amrex::Real W[AMREX_SPACEDIM][2],
141 amrex::Array4<const amrex::Real> const& scalar_field) noexcept
142{
143 amrex::Real value = 0;
144 if constexpr (DIMS == 3) {
145 value += scalar_field(i, j , k ) * W[0][0] * W[1][0] * W[2][0];
146 value += scalar_field(i+1, j , k ) * W[0][1] * W[1][0] * W[2][0];
147 value += scalar_field(i, j+1, k ) * W[0][0] * W[1][1] * W[2][0];
148 value += scalar_field(i+1, j+1, k ) * W[0][1] * W[1][1] * W[2][0];
149 value += scalar_field(i, j , k+1) * W[0][0] * W[1][0] * W[2][1];
150 value += scalar_field(i+1, j , k+1) * W[0][1] * W[1][0] * W[2][1];
151 value += scalar_field(i , j+1, k+1) * W[0][0] * W[1][1] * W[2][1];
152 value += scalar_field(i+1, j+1, k+1) * W[0][1] * W[1][1] * W[2][1];
153 } else if constexpr (DIMS == 2) {
154 value += scalar_field(i, j , k) * W[0][0] * W[1][0];
155 value += scalar_field(i+1, j , k) * W[0][1] * W[1][0];
156 value += scalar_field(i, j+1, k) * W[0][0] * W[1][1];
157 value += scalar_field(i+1, j+1, k) * W[0][1] * W[1][1];
158 } else {
159 value += scalar_field(i, j , k) * W[0][0];
160 value += scalar_field(i+1, j , k) * W[0][1];
161 }
162 return value;
163}
164
174template<int DIMS = AMREX_SPACEDIM>
176amrex::Real doGatherScalarFieldNodal (const amrex::ParticleReal xp,
177 const amrex::ParticleReal yp,
178 const amrex::ParticleReal zp,
179 amrex::Array4<const amrex::Real> const& scalar_field,
182{
183 // first find the weight of surrounding nodes to use during interpolation
184 int ii, jj, kk;
185 amrex::Real W[AMREX_SPACEDIM][2];
186 compute_weights<amrex::IndexType::NODE>(xp, yp, zp, lo, dxi, ii, jj, kk, W);
187
188 return interp_field_nodal<DIMS>(ii, jj, kk, W, scalar_field);
189}
190
200template<int DIMS = AMREX_SPACEDIM>
203doGatherVectorFieldNodal (const amrex::ParticleReal xp,
204 const amrex::ParticleReal yp,
205 const amrex::ParticleReal zp,
206 amrex::Array4<const amrex::Real> const& vector_field_x,
207 amrex::Array4<const amrex::Real> const& vector_field_y,
208 amrex::Array4<const amrex::Real> const& vector_field_z,
211{
212 // first find the weight of surrounding nodes to use during interpolation
213 int ii, jj, kk;
214 amrex::Real W[AMREX_SPACEDIM][2];
215 compute_weights<amrex::IndexType::NODE>(xp, yp, zp, lo, dxi, ii, jj, kk, W);
216
217 amrex::GpuArray<amrex::Real, 3> const field_interp = {
218 interp_field_nodal<DIMS>(ii, jj, kk, W, vector_field_x),
219 interp_field_nodal<DIMS>(ii, jj, kk, W, vector_field_y),
220 interp_field_nodal<DIMS>(ii, jj, kk, W, vector_field_z)
221 };
222
223 return field_interp;
224}
225
226} // namespace ablastr::particles
227
228#endif // ABLASTR_NODALFIELDGATHER_H_
#define AMREX_INLINE
#define AMREX_GPU_HOST_DEVICE
Definition DepositCharge.H:21
AMREX_GPU_HOST_DEVICE AMREX_INLINE amrex::Real interp_field_nodal(int i, int j, int k, const amrex::Real W[3][2], amrex::Array4< const amrex::Real > const &scalar_field) noexcept
Interpolate nodal field value based on surrounding indices and weights.
Definition NodalFieldGather.H:139
AMREX_GPU_HOST_DEVICE AMREX_INLINE void compute_weights(const amrex::ParticleReal xp, const amrex::ParticleReal yp, const amrex::ParticleReal zp, amrex::GpuArray< amrex::Real, 3 > const &plo, amrex::GpuArray< amrex::Real, 3 > const &dxi, int &i, int &j, int &k, amrex::Real W[3][2]) noexcept
Compute weight of each surrounding node (or cell-centered nodes) in interpolating a nodal ((or a cell...
Definition NodalFieldGather.H:37
AMREX_GPU_HOST_DEVICE AMREX_INLINE amrex::GpuArray< amrex::Real, 3 > doGatherVectorFieldNodal(const amrex::ParticleReal xp, const amrex::ParticleReal yp, const amrex::ParticleReal zp, amrex::Array4< const amrex::Real > const &vector_field_x, amrex::Array4< const amrex::Real > const &vector_field_y, amrex::Array4< const amrex::Real > const &vector_field_z, amrex::GpuArray< amrex::Real, 3 > const &dxi, amrex::GpuArray< amrex::Real, 3 > const &lo) noexcept
Vector field gather for a single particle. The field has to be defined at the cell nodes (see https:/...
Definition NodalFieldGather.H:203
AMREX_GPU_HOST_DEVICE AMREX_INLINE amrex::Real doGatherScalarFieldNodal(const amrex::ParticleReal xp, const amrex::ParticleReal yp, const amrex::ParticleReal zp, amrex::Array4< const amrex::Real > const &scalar_field, amrex::GpuArray< amrex::Real, 3 > const &dxi, amrex::GpuArray< amrex::Real, 3 > const &lo) noexcept
Scalar field gather for a single particle. The field has to be defined at the cell nodes (see https:/...
Definition NodalFieldGather.H:176
__host__ __device__ void ignore_unused(const Ts &...)