Block-Structured AMR Software Framework
Loading...
Searching...
No Matches
AMReX_FFT_CrossProj.H
Go to the documentation of this file.
1#ifndef AMREX_FFT_CROSSPROJ_H_
2#define AMREX_FFT_CROSSPROJ_H_
3
4#include <AMReX_FFT.H>
5#include <AMReX_Geometry.H>
6
7namespace amrex::FFT
8{
9
15
27template <typename MF = MultiFab>
29{
30 static_assert(AMREX_SPACEDIM >= 2, "FFT::CrossProj requires AMREX_SPACEDIM >= 2");
31public:
32
38 explicit CrossProj (Geometry const& geom)
39 requires (IsFabArray_v<MF>)
40 : m_domain_lo(geom.Domain().smallEnd()),
41 m_geom(detail::shift_geom(geom))
42 {
43 if (!m_geom.isAllPeriodic()) {
44 amrex::Abort("FFT::CrossProj: only supports periodic BC");
45 }
46 if (m_geom.Domain().shortside() < 2) {
47 amrex::Abort("FFT::CrossProj: domain must have at least 2 cells in each direction");
48 }
49 Info info{};
50 info.setBatchSize(AMREX_SPACEDIM);
51 m_r2c = std::make_unique<R2C<typename MF::value_type>>(m_geom.Domain(), info);
52 }
53
62 CrossProj (Geometry const& geom,
63 Array<std::pair<Boundary,Boundary>,AMREX_SPACEDIM> const& bc)
64 requires (IsFabArray_v<MF>)
65 : CrossProj(geom)
66 {
67 for (auto const& b : bc) {
68 if (b.first != Boundary::periodic || b.second != Boundary::periodic) {
69 amrex::Abort("FFT::CrossProj: only supports periodic BC");
70 }
71 }
72 }
73
83 void solve (MF& a_soln, MF const& a_rhs);
84
85private:
86 IntVect m_domain_lo;
87 Geometry m_geom;
88 std::unique_ptr<R2C<typename MF::value_type>> m_r2c;
89};
90
91template <typename MF>
92void CrossProj<MF>::solve (MF& a_soln, MF const& a_rhs)
93{
94 BL_PROFILE("FFT::CrossProj::solve");
95
96 AMREX_ALWAYS_ASSERT(a_soln.is_cell_centered() && a_rhs.is_cell_centered() &&
97 a_soln.nComp() >= AMREX_SPACEDIM &&
98 a_rhs.nComp() >= AMREX_SPACEDIM);
99
100 MF* soln = &a_soln;
101 MF const* rhs = &a_rhs;
102 MF solntmp, rhstmp;
103 if (m_domain_lo != 0) {
104 detail::shift_mfs(m_domain_lo, a_soln, a_rhs, solntmp, rhstmp);
105 soln = &solntmp;
106 rhs = &rhstmp;
107 }
108
109 using T = typename MF::value_type;
110
112 {AMREX_D_DECL(Math::pi<T>()/(T(m_geom.Domain().length(0))),
113 Math::pi<T>()/(T(m_geom.Domain().length(1))),
114 Math::pi<T>()/(T(m_geom.Domain().length(2))))};
116 {AMREX_D_DECL(T(1)/T(m_geom.CellSize(0)),
117 T(1)/T(m_geom.CellSize(1)),
118 T(1)/T(m_geom.CellSize(2)))};
119 auto scale = m_r2c->scalingFactor();
120
121 GpuArray<int,AMREX_SPACEDIM> len{AMREX_D_DECL(m_geom.Domain().length(0),
122 m_geom.Domain().length(1),
123 m_geom.Domain().length(2))};
124
125 auto f = [=] AMREX_GPU_DEVICE (int i, int j, int k, CellData < GpuComplex < T >> spectral_data)
126 {
128 AMREX_D_TERM(T a = fac[0]*T(i);,
129 T b = fac[1]*T(j);,
130 T c = fac[2]*T(k));
131 // Use exact cos(pi/2) = 0 so that null modes get a zero symbol.
132 AMREX_D_TERM(T ca = (2*i == len[0]) ? T(0) : std::cos(a);,
133 T cb = (2*j == len[1]) ? T(0) : std::cos(b);,
134 T cc = (2*k == len[2]) ? T(0) : std::cos(c));
135
136 // Fourier symbol of the node-centered cross-stencil divergence, up
137 // to a common factor that cancels in the projection.
138#if (AMREX_SPACEDIM == 2)
139 T const sx = std::sin(a)*cb*dxfac[0];
140 T const sy = ca*std::sin(b)*dxfac[1];
141
142 T const s2 = sx*sx + sy*sy;
143 // Select the denominator instead of guarding the division (see Poisson).
144 T const s2d = (s2 != T(0)) ? s2 : T(1);
145 auto cdiv = (sx * spectral_data[0] + sy * spectral_data[1]) / s2d;
146 spectral_data[0] -= sx * cdiv;
147 spectral_data[1] -= sy * cdiv;
148#else
149 T const sx = std::sin(a)*cb*cc*dxfac[0];
150 T const sy = ca*std::sin(b)*cc*dxfac[1];
151 T const sz = ca*cb*std::sin(c)*dxfac[2];
152
153 T const s2 = sx*sx + sy*sy + sz*sz;
154 // Select the denominator instead of guarding the division (see Poisson).
155 T const s2d = (s2 != T(0)) ? s2 : T(1);
156 auto cdiv = (sx * spectral_data[0] + sy * spectral_data[1]
157 + sz * spectral_data[2]) / s2d;
158 spectral_data[0] -= sx * cdiv;
159 spectral_data[1] -= sy * cdiv;
160 spectral_data[2] -= sz * cdiv;
161#endif
162 for (int n = 0; n < AMREX_SPACEDIM; ++n) {
163 spectral_data[n] *= scale;
164 }
165 };
166
167 IntVect const& ng = amrex::elemwiseMin(soln->nGrowVect(), IntVect(1));
168
169 m_r2c->forward(*rhs);
170 m_r2c->post_forward_doit_0(f);
171 m_r2c->backward_doit(*soln, ng, m_geom.periodicity());
172}
173
174}
175
176#endif
#define BL_PROFILE(a)
Definition AMReX_BLProfiler.H:593
#define AMREX_ALWAYS_ASSERT(EX)
Definition AMReX_BLassert.H:50
Problem-domain geometry: maps between index space and physical space.
#define AMREX_GPU_DEVICE
Definition AMReX_GpuQualifiers.H:18
#define AMREX_D_TERM(a, b, c)
Definition AMReX_SPACE.H:172
#define AMREX_D_DECL(a, b, c)
Definition AMReX_SPACE.H:171
void solve(MF &a_soln, MF const &a_rhs)
Project the velocity in a_rhs and store the result in a_soln.
Definition AMReX_FFT_CrossProj.H:92
CrossProj(Geometry const &geom, Array< std::pair< Boundary, Boundary >, 3 > const &bc)
Construct a CrossProj solver with explicit boundary types.
Definition AMReX_FFT_CrossProj.H:62
CrossProj(Geometry const &geom)
Construct a periodic CrossProj solver.
Definition AMReX_FFT_CrossProj.H:38
Parallel Discrete Fourier Transform.
Definition AMReX_FFT_R2C.H:48
Rectangular problem domain geometry.
Definition AMReX_Geometry.H:87
std::array< T, N > Array
Definition AMReX_Array.H:31
__host__ __device__ constexpr T elemwiseMin(T const &a, T const &b) noexcept
Definition AMReX_Algorithm.H:75
Definition AMReX_FFT_CrossProj.H:8
@ periodic
Definition AMReX_FFT_Helper.H:59
constexpr T pi()
Definition AMReX_Math.H:211
__host__ __device__ void ignore_unused(const Ts &...)
No-op helper that marks variables as intentionally unused.
Definition AMReX.H:273
constexpr bool IsFabArray_v
Definition AMReX_TypeTraits.H:34
__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:1128
IntVectND< 3 > IntVect
IntVect is an alias for amrex::IntVectND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:38
void Abort(const std::string &msg)
Print a fatal-error message to stderr and abort execution.
Definition AMReX.cpp:244
Lightweight accessor for data associated with a single cell.
Definition AMReX_Array4.H:47
Definition AMReX_FFT_Helper.H:83
Info & setBatchSize(int bsize)
Specify the batch size for FFT.
Definition AMReX_FFT_Helper.H:156
Fixed-size array that can be used on GPU.
Definition AMReX_Array.H:52