1#ifndef AMREX_FFT_POISSON_H_
2#define AMREX_FFT_POISSON_H_
19void fill_physbc (MF& mf, Geometry
const& geom,
20 Array<std::pair<Boundary,Boundary>,AMREX_SPACEDIM>
const& bc);
30template <
typename MF = MultiFab>
42 Array<std::pair<Boundary,Boundary>,AMREX_SPACEDIM>
const& bc)
43 requires (IsFabArray_v<MF>)
44 : m_domain_lo(geom.Domain().smallEnd()),
45 m_geom(detail::shift_geom(geom)),
48 bool all_periodic =
true;
49 for (
int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
50 all_periodic = all_periodic
55 m_r2c = std::make_unique<R2C<typename MF::value_type>>(m_geom.
Domain());
57 m_r2x = std::make_unique<R2X<typename MF::value_type>> (m_geom.
Domain(), m_bc);
67 requires (IsFabArray_v<MF>)
68 : m_domain_lo(geom.Domain().smallEnd()),
69 m_geom(detail::shift_geom(geom)),
75 m_r2c = std::make_unique<R2C<typename MF::value_type>>(m_geom.
Domain());
91 void solve (MF& a_soln, MF
const& a_rhs);
97 std::unique_ptr<R2X<typename MF::value_type>> m_r2x;
98 std::unique_ptr<R2C<typename MF::value_type>> m_r2c;
101#if (AMREX_SPACEDIM == 3)
106template <
typename MF = MultiFab>
119 template <
typename FA=MF>
120 requires (IsFabArray_v<FA>)
132 void solve (MF& soln, MF
const& rhs);
147 static Info make_solver_info (
Info const& info);
162template <
typename MF = MultiFab>
166 using T =
typename MF::value_type;
175 Array<std::pair<Boundary,Boundary>,AMREX_SPACEDIM>
const& bc)
176 requires (IsFabArray_v<MF>)
177 : m_domain_lo(geom.Domain().smallEnd()),
178 m_geom(detail::shift_geom(geom)),
181#if (AMREX_SPACEDIM < 3)
185 bool periodic_xy =
true;
186 for (
int idim = 0; idim < 2; ++idim) {
203 m_r2c = std::make_unique<R2C<typename MF::value_type>>(m_geom.
Domain(),
206 m_r2x = std::make_unique<R2X<typename MF::value_type>> (m_geom.
Domain(),
221 void solve (MF& soln, MF
const& rhs);
245 void solve_2d (MF& a_soln, MF
const& a_rhs);
255 template <
typename TRIA,
typename TRIC>
256 void solve (MF& a_soln, MF
const& a_rhs, TRIA
const& tria, TRIC
const& tric);
266 template <
typename FA,
typename TRIA,
typename TRIC>
267 void solve_z (FA& spmf, TRIA
const& tria, TRIC
const& tric);
283 std::unique_ptr<R2X<typename MF::value_type>> m_r2x;
284 std::unique_ptr<R2C<typename MF::value_type>> m_r2c;
290template <
typename MF>
296 MF
const* rhs = &a_rhs;
298 if (m_domain_lo != 0) {
299 detail::shift_mfs(m_domain_lo, a_soln, a_rhs, solntmp, rhstmp);
304 AMREX_ASSERT(soln->is_cell_centered() && rhs->is_cell_centered());
306 using T =
typename MF::value_type;
312 for (
int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
321 for (
int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
326 auto scale = (m_r2x) ? m_r2x->scalingFactor() : m_r2c->scalingFactor();
329 for (
int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
348 T b = fac[1]*(j+
offset[1]);,
349 T c = fac[2]*(k+
offset[2]));
351 +dxfac[1]*(std::cos(b)-T(1)),
352 +dxfac[2]*(std::cos(c)-T(1)));
356 spectral_data *=
scale;
362 m_r2x->forwardThenBackward_doit_0(*rhs, *soln, f, ng, m_geom.
periodicity());
363 detail::fill_physbc(*soln, m_geom, m_bc);
365 m_r2c->forward(*rhs);
366 m_r2c->post_forward_doit_0(f);
367 m_r2c->backward_doit(*soln, ng, m_geom.
periodicity());
371#if (AMREX_SPACEDIM == 3)
373template <
typename MF>
374template <
typename FA>
375requires (IsFabArray_v<FA>)
381 m_solver(m_grown_domain, make_solver_info(info))
386template <
typename MF>
395template <
typename MF>
398 using T =
typename MF::value_type;
399 auto const& lo = m_grown_domain.smallEnd();
400 auto const dx = T(m_geom.
CellSize(0));
401 auto const dy = T(m_geom.
CellSize(1));
402 auto const dz = T(m_geom.
CellSize(2));
403 auto const gfac = T(1)/T(std::sqrt(T(12)));
405 auto const fac = T(-0.125) * (dx*dy*dz) / (T(4)*Math::pi<T>());
408 auto x = (T(i-lo[0]) - gfac) * dx;
409 auto y = (T(j-lo[1]) - gfac) * dy;
410 auto z = (T(k-lo[2]) - gfac) * dz;
412 for (
int gx = 0; gx < 2; ++gx) {
413 for (
int gy = 0; gy < 2; ++gy) {
414 for (
int gz = 0; gz < 2; ++gz) {
415 auto xg =
x + 2*gx*gfac*dx;
416 auto yg =
y + 2*gy*gfac*dy;
417 auto zg =
z + 2*gz*gfac*dz;
418 r += T(1)/std::sqrt(xg*xg+yg*yg+zg*zg);
424template <
typename MF>
427 AMREX_ASSERT(m_grown_domain.ixType() == soln.ixType() && m_grown_domain.ixType() == rhs.ixType());
428 m_solver.solve(soln, rhs);
434namespace fft_poisson_detail {
435 template <
typename T>
437 [[nodiscard]]
constexpr T operator() (
int,
int,
int)
const
443 template <
typename T>
446 T operator() (
int,
int,
int)
const
453 template <
typename T>
456 T operator() (
int,
int,
int k)
const
458 return (k > 0) ? T(2.0) / (m_dz[k]*(m_dz[k]+m_dz[k-1]))
459 : T(1.0) / (m_dz[k]* m_dz[k]);
464 template <
typename T>
467 T operator() (
int,
int,
int k)
const
469 return (k < m_size-1) ? T(2.0) / (m_dz[k]*(m_dz[k]+m_dz[k+1]))
470 : T(1.0) / (m_dz[k]* m_dz[k]);
478template <
typename MF>
479std::pair<BoxArray,DistributionMapping>
482 if (!m_spmf_r.empty()) {
483 return std::make_pair(m_spmf_r.boxArray(), m_spmf_r.DistributionMap());
485 return std::make_pair(m_spmf_c.boxArray(), m_spmf_c.DistributionMap());
489template <
typename MF>
492#if (AMREX_SPACEDIM == 3)
499 if (cdomain.
length(0) > 1) {
506 DistributionMapping dm = detail::make_iota_distromap(cba.size());
507 m_spmf_c.define(cba, dm, 1, 0);
510 if (m_r2x->m_cy.empty()) {
512 {AMREX_D_DECL(true,true,false)});
513 DistributionMapping dm = detail::make_iota_distromap(sba.size());
514 m_spmf_r.define(sba, dm, 1, 0);
518 cdomain.
setBig(0,cdomain.length(0)/2);
520 cdomain.
setBig(1,cdomain.length(1)/2);
524 DistributionMapping dm = detail::make_iota_distromap(cba.size());
525 m_spmf_c.define(cba, dm, 1, 0);
530 {AMREX_D_DECL(true,true,false)});
531 DistributionMapping dm = detail::make_iota_distromap(sba.size());
532 m_spmf_r.define(sba, dm, 1, 0);
539template <
typename MF>
542 auto delz =
T(m_geom.
CellSize(AMREX_SPACEDIM-1));
544 fft_poisson_detail::Tri_Uniform<T>{
T(1)/(delz*delz)},
545 fft_poisson_detail::Tri_Uniform<T>{
T(1)/(delz*delz)});
548template <
typename MF>
553 "FFT::PoissonHybrid: dz.size() must equal domain length in z");
555 auto const* pdz = dz.
dataPtr();
557 fft_poisson_detail::TriA<T>{pdz},
558 fft_poisson_detail::TriC<T>{pdz,
int(dz.
size())});
561template <
typename MF>
564 AMREX_ASSERT(soln.is_cell_centered() && rhs.is_cell_centered());
567 "FFT::PoissonHybrid: dz.size() must equal domain length in z");
572 auto const* pdz = d_dz.
data();
574 auto const* pdz = dz.data();
577 fft_poisson_detail::TriA<T>{pdz},
578 fft_poisson_detail::TriC<T>{pdz,
int(dz.
size())});
581template <
typename MF>
584 solve(soln, rhs, fft_poisson_detail::Tri_Zero<T>{}, fft_poisson_detail::Tri_Zero<T>{});
587template <
typename MF>
588template <
typename TRIA,
typename TRIC>
594 AMREX_ASSERT(a_soln.is_cell_centered() && a_rhs.is_cell_centered());
596#if (AMREX_SPACEDIM < 3)
601 MF
const* rhs = &a_rhs;
603 if (m_domain_lo != 0) {
604 detail::shift_mfs(m_domain_lo, a_soln, a_rhs, solntmp, rhstmp);
613 m_r2c->forward(*rhs, m_spmf_c);
614 solve_z(m_spmf_c, tria, tric);
615 m_r2c->backward_doit(m_spmf_c, *soln, ng, m_geom.
periodicity());
619 if (m_r2x->m_cy.empty()) {
620 m_r2x->forward(*rhs, m_spmf_r);
621 solve_z(m_spmf_r, tria, tric);
622 m_r2x->backward(m_spmf_r, *soln, ng, m_geom.
periodicity());
624 m_r2x->forward(*rhs, m_spmf_c);
625 solve_z(m_spmf_c, tria, tric);
626 m_r2x->backward(m_spmf_c, *soln, ng, m_geom.
periodicity());
630 detail::fill_physbc(*soln, m_geom, m_bc);
634template <
typename MF>
635template <
typename FA,
typename TRIA,
typename TRIC>
640#if (AMREX_SPACEDIM < 3)
649 auto scale = (m_r2x) ? m_r2x->scalingFactor() : m_r2c->scalingFactor();
655 for (
int idim = 0; idim < AMREX_SPACEDIM-1; ++idim) {
676 (std::is_same_v<TRIA,fft_poisson_detail::Tri_Zero<T>> &&
677 std::is_same_v<TRIC,fft_poisson_detail::Tri_Zero<T>>) {
679#if defined(AMREX_USE_OMP) && !defined(AMREX_USE_GPU)
684 auto const& spectral = spmf.array(mfi);
685 auto const& box = mfi.validbox();
690 T k2 = dxfac * (std::cos(a)-
T(1))
691 + dyfac * (std::cos(b)-
T(1));
693 spectral(i,j,k) /= k2;
695 spectral(i,j,k) *=
scale;
702 && zlo_neumann && zhi_neumann;
706#if defined(AMREX_USE_OMP) && !defined(AMREX_USE_GPU)
711 auto const& spectral = spmf.array(mfi);
712 auto const& box = mfi.validbox();
721 auto const& ald = tridiag_workspace.
array(0);
722 auto const& bd = tridiag_workspace.
array(1);
723 auto const& cud = tridiag_workspace.
array(2);
724 auto const& scratch = tridiag_workspace.
array(3);
730 T k2 = dxfac * (std::cos(a)-
T(1))
731 + dyfac * (std::cos(b)-
T(1));
734 for(
int k=0; k < nz; k++) {
737 cud(i,j,k) = tric(i,j,k);
739 bd(i,j,k) = k2 - cud(i,j,k);
741 bd(i,j,k) = k2 - cud(i,j,k) -
T(2.0)*tria(i,j,k);
743 }
else if (k == nz-1) {
744 ald(i,j,k) = tria(i,j,k);
747 bd(i,j,k) = k2 - ald(i,j,k);
748 if (i == 0 && j == 0 && is_singular) {
752 bd(i,j,k) = k2 - ald(i,j,k) -
T(2.0)*tric(i,j,k);
755 ald(i,j,k) = tria(i,j,k);
756 cud(i,j,k) = tric(i,j,k);
757 bd(i,j,k) = k2 -ald(i,j,k)-cud(i,j,k);
761 scratch(i,j,0) = cud(i,j,0)/bd(i,j,0);
762 spectral(i,j,0) = spectral(i,j,0)/bd(i,j,0);
764 for (
int k = 1; k < nz; k++) {
766 scratch(i,j,k) = cud(i,j,k) / (bd(i,j,k) - ald(i,j,k) * scratch(i,j,k-1));
768 spectral(i,j,k) = (spectral(i,j,k) - ald(i,j,k) * spectral(i,j,k - 1))
769 / (bd(i,j,k) - ald(i,j,k) * scratch(i,j,k-1));
772 for (
int k = nz - 2; k >= 0; k--) {
773 spectral(i,j,k) -= scratch(i,j,k) * spectral(i,j,k + 1);
776 for (
int k = 0; k < nz; ++k) {
777 spectral(i,j,k) *=
scale;
793 T k2 = dxfac * (std::cos(a)-
T(1))
794 + dyfac * (std::cos(b)-
T(1));
797 for(
int k=0; k < nz; k++) {
800 cud[k] = tric(i,j,k);
804 bd[k] = k2 - cud[k] -
T(2.0)*tria(i,j,k);
806 }
else if (k == nz-1) {
807 ald[k] = tria(i,j,k);
811 if (i == 0 && j == 0 && is_singular) {
815 bd[k] = k2 - ald[k] -
T(2.0)*tric(i,j,k);
818 ald[k] = tria(i,j,k);
819 cud[k] = tric(i,j,k);
820 bd[k] = k2 -ald[k]-cud[k];
824 scratch[0] = cud[0]/bd[0];
825 spectral(i,j,0) = spectral(i,j,0)/bd[0];
827 for (
int k = 1; k < nz; k++) {
829 scratch[k] = cud[k] / (bd[k] - ald[k] * scratch[k-1]);
831 spectral(i,j,k) = (spectral(i,j,k) - ald[k] * spectral(i,j,k - 1))
832 / (bd[k] - ald[k] * scratch[k-1]);
835 for (
int k = nz - 2; k >= 0; k--) {
836 spectral(i,j,k) -= scratch[k] * spectral(i,j,k + 1);
839 for (
int k = 0; k < nz; ++k) {
840 spectral(i,j,k) *=
scale;
860 Box const& box () const noexcept {
return dbox; }
863template <
typename MF>
864void fill_physbc (MF& mf, Geometry
const& geom,
865 Array<std::pair<Boundary,Boundary>,AMREX_SPACEDIM>
const& bc)
867 using T =
typename MF::value_type;
868 using Tag = FFTPhysBCTag<T>;
871 for (MFIter mfi(mf, MFItInfo{}.DisableDeviceSync()); mfi.isValid(); ++mfi)
873 auto const& box = mfi.fabbox();
874 auto const& arr = mf.array(mfi);
875 for (OrientationIter oit; oit; ++oit) {
876 Orientation face = oit();
877 int idim = face.coordDir();
878 Box b = geom.Domain();
881 b.setRange(idim,geom.Domain().smallEnd(idim)-1);
882 fbc = bc[idim].first;
884 b.setRange(idim,geom.Domain().bigEnd(idim)+1);
885 fbc = bc[idim].second;
888 if (b.ok() && fbc != Boundary::periodic) {
889 tags.push_back(Tag{.dfab = arr, .dbox = b, .bc = fbc, .face = face});
894#if defined(AMREX_USE_GPU)
896 Tag
const& tag)
noexcept
898 auto ntags =
int(tags.size());
900#pragma omp parallel for
902 for (
int itag = 0; itag < ntags; ++itag) {
903 Tag
const& tag = tags[itag];
907 int sgn = tag.face.isLow() ? 1 : -1;
908 IntVect siv = IntVect(AMREX_D_DECL(i,j,k))
909 + sgn * IntVect::TheDimensionVector(tag.face.coordDir());
910 if (tag.bc == Boundary::odd) {
911 tag.dfab(i,j,k) = -tag.dfab(siv);
913 tag.dfab(i,j,k) = tag.dfab(siv);
916#if !defined(AMREX_USE_GPU)
#define BL_PROFILE(a)
Definition AMReX_BLProfiler.H:551
#define AMREX_ALWAYS_ASSERT_WITH_MESSAGE(EX, MSG)
Definition AMReX_BLassert.H:49
#define AMREX_ASSERT(EX)
Definition AMReX_BLassert.H:38
#define AMREX_ALWAYS_ASSERT(EX)
Definition AMReX_BLassert.H:50
#define AMREX_FORCE_INLINE
Definition AMReX_Extension.H:119
#define AMREX_GPU_DEVICE
Definition AMReX_GpuQualifiers.H:18
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
Array4< int const > offset
Definition AMReX_HypreMLABecLap.cpp:1139
#define AMREX_D_TERM(a, b, c)
Definition AMReX_SPACE.H:172
#define AMREX_D_DECL(a, b, c)
Definition AMReX_SPACE.H:171
Array4< T const > array() const noexcept
Definition AMReX_BaseFab.H:387
__host__ __device__ BoxND & setBig(const IntVectND< dim > &bg) noexcept
Redefine the big end of the BoxND.
Definition AMReX_Box.H:495
__host__ __device__ IntVectND< dim > length() const noexcept
Return the length of the BoxND.
Definition AMReX_Box.H:155
const Real * CellSize() const noexcept
Returns the cellsize for each coordinate direction.
Definition AMReX_CoordSys.H:71
A Fortran Array of REALs.
Definition AMReX_FArrayBox.H:231
Convolution-based solver for open boundary conditions using Green's functions.
Definition AMReX_FFT_OpenBCSolver.H:26
IntVect const & PaddedLength() const
Access the one-sided padded length used to build the internal FFT domain.
Definition AMReX_FFT_OpenBCSolver.H:68
3D Poisson solver for periodic, Dirichlet & Neumann boundaries in the first two dimensions,...
Definition AMReX_FFT_Poisson.H:164
void solve(MF &soln, MF const &rhs)
Solve del dot grad soln = rhs for uniform spacing in all directions.
Definition AMReX_FFT_Poisson.H:540
typename MF::value_type T
Definition AMReX_FFT_Poisson.H:166
PoissonHybrid(Geometry const &geom, Array< std::pair< Boundary, Boundary >, 3 > const &bc)
Construct the hybrid Poisson solver (mixed BCs in z with optional nonuniform spacing).
Definition AMReX_FFT_Poisson.H:174
void solve_z(FA &spmf, TRIA const &tria, TRIC const &tric)
CUDA helper that applies the supplied tridiagonal operator along z.
Definition AMReX_FFT_Poisson.H:636
std::pair< BoxArray, DistributionMapping > getSpectralDataLayout() const
Layout information for spectral storage used by the hybrid solver.
Definition AMReX_FFT_Poisson.H:480
void solve_2d(MF &a_soln, MF const &a_rhs)
Solve an independent 2-D Poisson problem on every z-plane.
Definition AMReX_FFT_Poisson.H:582
Poisson solve for Open BC using FFT.
Definition AMReX_FFT_Poisson.H:108
void solve(MF &soln, MF const &rhs)
Solve the open-boundary Poisson problem.
Definition AMReX_FFT_Poisson.H:425
IntVect const & PaddedLength() const
Access the one-sided padded length used by the internal OpenBC solver.
Definition AMReX_FFT_Poisson.H:144
void define_doit()
Initialize the discretized Green's function cache (public for CUDA kernels).
Definition AMReX_FFT_Poisson.H:396
Poisson solver for periodic, Dirichlet & Neumann boundaries using FFT.
Definition AMReX_FFT_Poisson.H:32
Poisson(Geometry const &geom, Array< std::pair< Boundary, Boundary >, 3 > const &bc)
Construct a Poisson solver with explicit boundary types.
Definition AMReX_FFT_Poisson.H:41
Poisson(Geometry const &geom)
Construct a purely periodic Poisson solver.
Definition AMReX_FFT_Poisson.H:66
void solve(MF &a_soln, MF const &a_rhs)
Solve del dot grad soln = rhs.
Definition AMReX_FFT_Poisson.H:291
An Array of FortranArrayBox(FAB)-like Objects.
Definition AMReX_FabArray.H:344
Rectangular problem domain geometry.
Definition AMReX_Geometry.H:75
const Box & Domain() const noexcept
Returns our rectangular domain.
Definition AMReX_Geometry.H:216
Periodicity periodicity() const noexcept
Definition AMReX_Geometry.H:361
bool isAllPeriodic() const noexcept
Is domain periodic in all directions?
Definition AMReX_Geometry.H:344
__host__ static __device__ constexpr IndexTypeND< dim > TheCellType() noexcept
This static member function returns an IndexTypeND object of value IndexTypeND::CELL....
Definition AMReX_IndexType.H:150
Iterator for looping ever tiles and boxes of amrex::FabArray based containers.
Definition AMReX_MFIter.H:88
bool isValid() const noexcept
Is the iterator valid i.e. is it associated with a FAB?
Definition AMReX_MFIter.H:172
Encapsulation of the Orientation of the Faces of a Box.
Definition AMReX_Orientation.H:29
Dynamically allocated vector for trivially copyable data.
Definition AMReX_PODVector.H:308
size_type size() const noexcept
Definition AMReX_PODVector.H:648
T * dataPtr() noexcept
Definition AMReX_PODVector.H:670
T * data() noexcept
Definition AMReX_PODVector.H:666
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:29
Long size() const noexcept
Definition AMReX_Vector.H:54
__host__ __device__ BoxND< dim > grow(const BoxND< dim > &b, int i) noexcept
Grow BoxND in all directions by given amount.
Definition AMReX_Box.H:1289
std::array< T, N > Array
Definition AMReX_Array.H:26
Definition AMReX_FFT_Helper.H:53
Boundary
Definition AMReX_FFT_Helper.H:59
void streamSynchronize() noexcept
Definition AMReX_GpuDevice.H:310
void htod_memcpy_async(void *p_d, const void *p_h, const std::size_t sz) noexcept
Definition AMReX_GpuDevice.H:421
int NProcsSub() noexcept
number of ranks in current frame
Definition AMReX_ParallelContext.H:74
__host__ __device__ void ignore_unused(const Ts &...)
This shuts up the compiler about unused variables.
Definition AMReX.H:139
__host__ __device__ BoxND< dim > convert(const BoxND< dim > &b, const IntVectND< dim > &typ) noexcept
Return a BoxND with different type.
Definition AMReX_Box.H:1567
__host__ __device__ BoxND< dim > makeSlab(BoxND< dim > const &b, int direction, int slab_index) noexcept
Definition AMReX_Box.H:2140
void ParallelFor(TypeList< CTOs... > ctos, std::array< int, sizeof...(CTOs)> const &runtime_options, T N, F &&f)
Definition AMReX_CTOParallelForImpl.H:202
BoxND< 3 > Box
Box is an alias for amrex::BoxND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:30
double second() noexcept
Definition AMReX_Utility.cpp:940
BoxArray decompose(Box const &domain, int nboxes, Array< bool, 3 > const &decomp, bool no_overlap)
Decompose domain box into BoxArray.
Definition AMReX_BoxArray.cpp:1943
IntVectND< 3 > IntVect
IntVect is an alias for amrex::IntVectND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:33
__host__ __device__ constexpr 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:1102
bool TilingIfNotGPU() noexcept
Definition AMReX_MFIter.H:12
void Abort(const std::string &msg)
Print out message to cerr and exit via abort().
Definition AMReX.cpp:241
const int[]
Definition AMReX_BLProfiler.cpp:1664
void LoopOnCpu(Dim3 lo, Dim3 hi, F const &f) noexcept
Definition AMReX_Loop.H:365
__host__ __device__ constexpr T elemwiseMin(T const &a, T const &b) noexcept
Return the element-wise minimum of the given values for types like XDim3.
Definition AMReX_Algorithm.H:63
A multidimensional array accessor.
Definition AMReX_Array4.H:285
Definition AMReX_FFT_Helper.H:83
bool openbc_padding
Whether OpenBCSolver pads internal FFT lengths for better performance.
Definition AMReX_FFT_Helper.H:112
Info & setOneDMode(bool x)
Flag the degenerate 2-D mode (nx==1 or ny==1) that still batches along z.
Definition AMReX_FFT_Helper.H:149
int openbc_padding_nfactors
Definition AMReX_FFT_Helper.H:116
Info & setTwoDMode(bool x)
Restrict transforms to the first two dimensions (3-D problems only).
Definition AMReX_FFT_Helper.H:138
Fixed-size array that can be used on GPU.
Definition AMReX_Array.H:43