1 #ifndef AMREX_FFT_POISSON_H_
2 #define AMREX_FFT_POISSON_H_
14 template <
typename MF = MultiFab>
19 template <
typename FA=MF, std::enable_if_t<IsFabArray_v<FA>,
int> = 0>
21 Array<std::pair<Boundary,Boundary>,AMREX_SPACEDIM>
const& bc)
24 bool all_periodic =
true;
25 for (
int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
26 all_periodic = all_periodic
27 && (bc[idim].first == Boundary::periodic)
28 && (bc[idim].
second == Boundary::periodic);
37 template <
typename FA=MF, std::enable_if_t<IsFabArray_v<FA>,
int> = 0>
41 std::make_pair(Boundary::periodic,Boundary::periodic),
42 std::make_pair(Boundary::periodic,Boundary::periodic))}
51 void solve (MF& soln, MF
const& rhs);
56 std::unique_ptr<R2X<typename MF::value_type>>
m_r2x;
57 std::unique_ptr<R2C<typename MF::value_type>>
m_r2c;
60 #if (AMREX_SPACEDIM == 3)
64 template <
typename MF = MultiFab>
69 template <
typename FA=MF, std::enable_if_t<IsFabArray_v<FA>,
int> = 0>
70 explicit PoissonOpenBC (
Geometry const& geom,
74 void solve (MF& soln, MF
const& rhs);
90 template <
typename MF = MultiFab>
94 using T =
typename MF::value_type;
96 template <
typename FA=MF, std::enable_if_t<IsFabArray_v<FA>,
int> = 0>
100 #if (AMREX_SPACEDIM == 3)
107 void solve (MF& soln, MF
const& rhs);
111 template <
typename DZ>
112 void solve_doit (MF& soln, MF
const& rhs, DZ
const& dz);
119 template <
typename MF>
124 using T =
typename MF::value_type;
127 {
AMREX_D_DECL(Math::pi<T>()/T(m_geom.Domain().length(0)),
128 Math::pi<T>()/T(m_geom.Domain().length(1)),
129 Math::pi<T>()/T(m_geom.Domain().length(2)))};
130 for (
int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
131 if (m_bc[idim].first == Boundary::periodic) {
136 {
AMREX_D_DECL(T(2)/T(m_geom.CellSize(0)*m_geom.CellSize(0)),
137 T(2)/T(m_geom.CellSize(1)*m_geom.CellSize(1)),
138 T(2)/T(m_geom.CellSize(2)*m_geom.CellSize(2)))};
139 auto scale = (m_r2x) ? m_r2x->scalingFactor() : m_r2c->scalingFactor();
143 for (
int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
144 if (m_bc[idim].first == Boundary::odd &&
145 m_bc[idim].
second == Boundary::odd)
149 else if ((m_bc[idim].first == Boundary::odd &&
150 m_bc[idim].
second == Boundary::even) ||
151 (m_bc[idim].first == Boundary::even &&
152 m_bc[idim].
second == Boundary::odd))
163 T c = fac[2]*(k+
offset[2]));
165 +dxfac[1]*(std::cos(
b)-T(1)),
166 +dxfac[2]*(std::cos(c)-T(1)));
170 spectral_data *=
scale;
174 m_r2x->forwardThenBackward(rhs, soln,
f);
176 m_r2c->forwardThenBackward(rhs, soln,
f);
180 #if (AMREX_SPACEDIM == 3)
182 template <
typename MF>
183 template <
typename FA, std::enable_if_t<IsFabArray_v<FA>,
int> FOO>
189 m_solver(m_grown_domain)
194 template <
typename MF>
195 void PoissonOpenBC<MF>::define_doit ()
197 using T =
typename MF::value_type;
198 auto const& lo = m_grown_domain.smallEnd();
199 auto const dx = T(m_geom.CellSize(0));
200 auto const dy = T(m_geom.CellSize(1));
201 auto const dz = T(m_geom.CellSize(2));
202 auto const gfac = T(1)/T(
std::sqrt(T(12)));
204 auto const fac = T(-0.125) * (dx*dy*dz) / (T(4)*Math::pi<T>());
207 auto x = (T(i-lo[0]) - gfac) * dx;
208 auto y = (T(j-lo[1]) - gfac) * dy;
209 auto z = (T(k-lo[2]) - gfac) * dz;
211 for (
int gx = 0; gx < 2; ++gx) {
212 for (
int gy = 0; gy < 2; ++gy) {
213 for (
int gz = 0; gz < 2; ++gz) {
214 auto xg =
x + 2*gx*gfac*dx;
215 auto yg = y + 2*gy*gfac*dy;
216 auto zg = z + 2*gz*gfac*dz;
223 template <
typename MF>
224 void PoissonOpenBC<MF>::solve (MF& soln, MF
const& rhs)
226 AMREX_ASSERT(m_grown_domain.ixType() == soln.ixType() && m_grown_domain.ixType() == rhs.ixType());
227 m_solver.solve(soln, rhs);
232 namespace fft_poisson_detail {
233 template <
typename T>
240 template <
typename MF>
243 auto delz =
T(m_geom.CellSize(AMREX_SPACEDIM-1));
247 template <
typename MF>
250 auto const* pdz = dz.
dataPtr();
251 solve_doit(soln, rhs, pdz);
254 template <
typename MF>
260 auto const* pdz = d_dz.
data();
262 auto const* pdz = dz.data();
264 solve_doit(soln, rhs, pdz);
267 template <
typename MF>
268 template <
typename DZ>
273 #if (AMREX_SPACEDIM < 3)
276 auto facx =
T(2)*Math::pi<T>()/
T(m_geom.ProbLength(0));
277 auto facy =
T(2)*Math::pi<T>()/
T(m_geom.ProbLength(1));
278 auto dx =
T(m_geom.CellSize(0));
279 auto dy =
T(m_geom.CellSize(1));
280 auto scale =
T(1.0)/(
T(m_geom.Domain().length(0)) *
281 T(m_geom.Domain().length(1)));
282 auto ny = m_geom.Domain().length(1);
283 auto nz = m_geom.Domain().length(2);
285 Box cdomain = m_geom.Domain();
292 m_r2c.forward(rhs, spmf);
296 auto const& spectral = spmf.
array(mfi);
297 auto const& box = mfi.validbox();
306 auto const& ald = tridiag_workspace.
array(0);
307 auto const& bd = tridiag_workspace.
array(1);
308 auto const& cud = tridiag_workspace.
array(2);
309 auto const& scratch = tridiag_workspace.
array(3);
314 T b = (j < ny/2) ? facy*j : facy*(ny-j);
316 T k2 =
T(2)*(std::cos(a*dx)-
T(1))/(dx*dx)
317 +
T(2)*(std::cos(
b*dy)-
T(1))/(dy*dy);
320 for(
int k=0; k < nz; k++) {
323 cud(i,j,k) = 2.0 /(dz[k]*(dz[k]+dz[k+1]));
324 bd(i,j,k) = k2 -ald(i,j,k)-cud(i,j,k);
325 }
else if (k == nz-1) {
326 ald(i,j,k) = 2.0 /(dz[k]*(dz[k]+dz[k-1]));
328 bd(i,j,k) = k2 -ald(i,j,k)-cud(i,j,k);
329 if (i == 0 && j == 0) {
333 ald(i,j,k) = 2.0 /(dz[k]*(dz[k]+dz[k-1]));
334 cud(i,j,k) = 2.0 /(dz[k]*(dz[k]+dz[k+1]));
335 bd(i,j,k) = k2 -ald(i,j,k)-cud(i,j,k);
339 scratch(i,j,0) = cud(i,j,0)/bd(i,j,0);
340 spectral(i,j,0) = spectral(i,j,0)/bd(i,j,0);
342 for (
int k = 1; k < nz; k++) {
344 scratch(i,j,k) = cud(i,j,k) / (bd(i,j,k) - ald(i,j,k) * scratch(i,j,k-1));
346 spectral(i,j,k) = (spectral(i,j,k) - ald(i,j,k) * spectral(i,j,k - 1))
347 / (bd(i,j,k) - ald(i,j,k) * scratch(i,j,k-1));
350 for (
int k = nz - 2; k >= 0; k--) {
351 spectral(i,j,k) -= scratch(i,j,k) * spectral(i,j,k + 1);
354 for (
int k = 0; k < nz; ++k) {
355 spectral(i,j,k) *=
scale;
370 T b = (j < ny/2) ? facy*j : facy*(ny-j);
372 T k2 =
T(2)*(std::cos(a*dx)-
T(1))/(dx*dx)
373 +
T(2)*(std::cos(
b*dy)-
T(1))/(dy*dy);
376 for(
int k=0; k < nz; k++) {
379 cud[k] = 2.0 /(dz[k]*(dz[k]+dz[k+1]));
380 bd[k] = k2 -ald[k]-cud[k];
381 }
else if (k == nz-1) {
382 ald[k] = 2.0 /(dz[k]*(dz[k]+dz[k-1]));
384 bd[k] = k2 -ald[k]-cud[k];
385 if (i == 0 && j == 0) {
389 ald[k] = 2.0 /(dz[k]*(dz[k]+dz[k-1]));
390 cud[k] = 2.0 /(dz[k]*(dz[k]+dz[k+1]));
391 bd[k] = k2 -ald[k]-cud[k];
395 scratch[0] = cud[0]/bd[0];
396 spectral(i,j,0) = spectral(i,j,0)/bd[0];
398 for (
int k = 1; k < nz; k++) {
400 scratch[k] = cud[k] / (bd[k] - ald[k] * scratch[k-1]);
402 spectral(i,j,k) = (spectral(i,j,k) - ald[k] * spectral(i,j,k - 1))
403 / (bd[k] - ald[k] * scratch[k-1]);
406 for (
int k = nz - 2; k >= 0; k--) {
407 spectral(i,j,k) -= scratch[k] * spectral(i,j,k + 1);
410 for (
int k = 0; k < nz; ++k) {
411 spectral(i,j,k) *=
scale;
417 m_r2c.backward(spmf, soln);
#define BL_PROFILE(a)
Definition: AMReX_BLProfiler.H:551
#define AMREX_ASSERT(EX)
Definition: AMReX_BLassert.H:38
#define AMREX_ALWAYS_ASSERT(EX)
Definition: AMReX_BLassert.H:50
#define AMREX_GPU_DEVICE
Definition: AMReX_GpuQualifiers.H:18
Array4< int const > offset
Definition: AMReX_HypreMLABecLap.cpp:1089
#define AMREX_D_TERM(a, b, c)
Definition: AMReX_SPACE.H:129
#define AMREX_D_DECL(a, b, c)
Definition: AMReX_SPACE.H:104
AMREX_FORCE_INLINE Array4< T const > array() const noexcept
Definition: AMReX_BaseFab.H:379
AMREX_GPU_HOST_DEVICE IntVectND< dim > length() const noexcept
Return the length of the BoxND.
Definition: AMReX_Box.H:146
AMREX_GPU_HOST_DEVICE BoxND & setBig(const IntVectND< dim > &bg) noexcept
Redefine the big end of the BoxND.
Definition: AMReX_Box.H:474
Calculates the distribution of FABs to MPI processes.
Definition: AMReX_DistributionMapping.H:41
A Fortran Array of REALs.
Definition: AMReX_FArrayBox.H:229
Definition: AMReX_FFT_OpenBCSolver.H:11
3D Poisson solver for periodic boundaries in the first two dimensions and Neumann in the last dimensi...
Definition: AMReX_FFT_Poisson.H:92
void solve(MF &soln, MF const &rhs)
Definition: AMReX_FFT_Poisson.H:241
typename MF::value_type T
Definition: AMReX_FFT_Poisson.H:94
Geometry m_geom
Definition: AMReX_FFT_Poisson.H:115
void solve_doit(MF &soln, MF const &rhs, DZ const &dz)
Definition: AMReX_FFT_Poisson.H:269
R2C< typename MF::value_type, Direction::both > m_r2c
Definition: AMReX_FFT_Poisson.H:116
PoissonHybrid(Geometry const &geom)
Definition: AMReX_FFT_Poisson.H:97
Poisson solver for periodic, Dirichlet & Neumann boundaries using FFT.
Definition: AMReX_FFT_Poisson.H:16
Poisson(Geometry const &geom, Array< std::pair< Boundary, Boundary >, AMREX_SPACEDIM > const &bc)
Definition: AMReX_FFT_Poisson.H:20
std::unique_ptr< R2X< typename MF::value_type > > m_r2x
Definition: AMReX_FFT_Poisson.H:56
Geometry m_geom
Definition: AMReX_FFT_Poisson.H:54
Array< std::pair< Boundary, Boundary >, AMREX_SPACEDIM > m_bc
Definition: AMReX_FFT_Poisson.H:55
Poisson(Geometry const &geom)
Definition: AMReX_FFT_Poisson.H:38
void solve(MF &soln, MF const &rhs)
Definition: AMReX_FFT_Poisson.H:120
std::unique_ptr< R2C< typename MF::value_type > > m_r2c
Definition: AMReX_FFT_Poisson.H:57
An Array of FortranArrayBox(FAB)-like Objects.
Definition: AMReX_FabArray.H:344
Array4< typename FabArray< FAB >::value_type const > array(const MFIter &mfi) const noexcept
Definition: AMReX_FabArray.H:1561
Rectangular problem domain geometry.
Definition: AMReX_Geometry.H:73
const Box & Domain() const noexcept
Returns our rectangular domain.
Definition: AMReX_Geometry.H:210
bool isAllPeriodic() const noexcept
Is domain periodic in all directions?
Definition: AMReX_Geometry.H:338
bool isPeriodic(int dir) const noexcept
Is the domain periodic in the specified direction?
Definition: AMReX_Geometry.H:331
AMREX_GPU_HOST_DEVICE static constexpr AMREX_FORCE_INLINE IndexTypeND< dim > TheCellType() noexcept
This static member function returns an IndexTypeND object of value IndexTypeND::CELL....
Definition: AMReX_IndexType.H:149
Definition: AMReX_MFIter.H:57
bool isValid() const noexcept
Is the iterator valid i.e. is it associated with a FAB?
Definition: AMReX_MFIter.H:141
Definition: AMReX_PODVector.H:246
T * data() noexcept
Definition: AMReX_PODVector.H:593
T * dataPtr() noexcept
Definition: AMReX_PODVector.H:597
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition: AMReX_Vector.H:27
Long size() const noexcept
Definition: AMReX_Vector.H:50
DistributionMapping make_iota_distromap(Long n)
Definition: AMReX_FFT.cpp:88
Definition: AMReX_FFT.cpp:7
void streamSynchronize() noexcept
Definition: AMReX_GpuDevice.H:237
void htod_memcpy_async(void *p_d, const void *p_h, const std::size_t sz) noexcept
Definition: AMReX_GpuDevice.H:251
int NProcsSub() noexcept
number of ranks in current frame
Definition: AMReX_ParallelContext.H:74
static int f(amrex::Real t, N_Vector y_data, N_Vector y_rhs, void *user_data)
Definition: AMReX_SundialsIntegrator.H:44
Definition: AMReX_Amr.cpp:49
std::enable_if_t< std::is_integral_v< T > > ParallelFor(TypeList< CTOs... > ctos, std::array< int, sizeof...(CTOs)> const &runtime_options, T N, F &&f)
Definition: AMReX_CTOParallelForImpl.H:200
AMREX_ATTRIBUTE_FLATTEN_FOR void LoopOnCpu(Dim3 lo, Dim3 hi, F const &f) noexcept
Definition: AMReX_Loop.H:355
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE BoxND< dim > grow(const BoxND< dim > &b, int i) noexcept
Grow BoxND in all directions by given amount.
Definition: AMReX_Box.H:1211
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE BoxND< dim > convert(const BoxND< dim > &b, const IntVectND< dim > &typ) noexcept
Returns a BoxND with different type.
Definition: AMReX_Box.H:1435
double second() noexcept
Definition: AMReX_Utility.cpp:922
IntVectND< AMREX_SPACEDIM > IntVect
Definition: AMReX_BaseFwd.H:30
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void ignore_unused(const Ts &...)
This shuts up the compiler about unused variables.
Definition: AMReX.H:111
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE IntVectND< dim > scale(const IntVectND< dim > &p, int s) noexcept
Returns a IntVectND obtained by multiplying each of the components of this IntVectND by s.
Definition: AMReX_IntVect.H:1006
BoxArray decompose(Box const &domain, int nboxes, Array< bool, AMREX_SPACEDIM > const &decomp={AMREX_D_DECL(true, true, true)}, bool no_overlap=false)
Decompose domain box into BoxArray.
void Abort(const std::string &msg)
Print out message to cerr and exit via abort().
Definition: AMReX.cpp:225
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE BoxND< dim > makeSlab(BoxND< dim > const &b, int direction, int slab_index) noexcept
Definition: AMReX_Box.H:1998
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE GpuComplex< T > sqrt(const GpuComplex< T > &a_z) noexcept
Return the square root of a complex number.
Definition: AMReX_GpuComplex.H:373
std::array< T, N > Array
Definition: AMReX_Array.H:24
Definition: AMReX_FFT_Helper.H:56
Definition: AMReX_FFT_Poisson.H:234
T m_delz
Definition: AMReX_FFT_Poisson.H:236
constexpr T operator[](int) const
Definition: AMReX_FFT_Poisson.H:235
Definition: AMReX_Array.H:34