Block-Structured AMR Software Framework
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
AMReX_FFT_OpenBCSolver.H
Go to the documentation of this file.
1#ifndef AMREX_FFT_OPENBC_SOLVER_H_
2#define AMREX_FFT_OPENBC_SOLVER_H_
3
4#include <AMReX_FFT_R2C.H>
5
6namespace amrex::FFT
7{
8
9template <typename T = Real>
11{
12public:
13 using MF = typename R2C<T>::MF;
14 using cMF = typename R2C<T>::cMF;
15
16 explicit OpenBCSolver (Box const& domain, Info const& info = Info{});
17
18 template <class F>
19 void setGreensFunction (F const& greens_function);
20
21 void solve (MF& phi, MF const& rho);
22
23 [[nodiscard]] Box const& Domain () const { return m_domain; }
24
25private:
26 static Box make_grown_domain (Box const& domain, Info const& info);
27
32 std::unique_ptr<R2C<T>> m_r2c_green;
33};
34
35template <typename T>
36Box OpenBCSolver<T>::make_grown_domain (Box const& domain, Info const& info)
37{
38 IntVect len = domain.length();
39#if (AMREX_SPACEDIM == 3)
40 if (info.twod_mode) { len[2] = 0; }
41#else
43#endif
44 return Box(domain.smallEnd(), domain.bigEnd()+len, domain.ixType());
45}
46
47template <typename T>
48OpenBCSolver<T>::OpenBCSolver (Box const& domain, Info const& info)
49 : m_domain(domain),
50 m_info(info),
51 m_r2c(OpenBCSolver<T>::make_grown_domain(domain,info),
52 m_info.setDomainStrategy(FFT::DomainStrategy::slab))
53{
54#if (AMREX_SPACEDIM == 3)
55 if (m_info.twod_mode) {
56 auto gdom = make_grown_domain(domain,m_info);
57 gdom.enclosedCells(2);
58 gdom.setSmall(2, 0);
59 int nprocs = std::min({ParallelContext::NProcsSub(),
61 m_domain.length(2)});
62 gdom.setBig(2, nprocs-1);
63 m_r2c_green = std::make_unique<R2C<T>>(gdom,m_info);
64 auto [sd, ord] = m_r2c_green->getSpectralData();
65 m_G_fft = cMF(*sd, amrex::make_alias, 0, 1);
66 } else
67#endif
68 {
70 auto [sd, ord] = m_r2c.getSpectralData();
72 m_G_fft.define(sd->boxArray(), sd->DistributionMap(), 1, 0);
73 }
74}
75
76template <typename T>
77template <class F>
78void OpenBCSolver<T>::setGreensFunction (F const& greens_function)
79{
80 BL_PROFILE("OpenBCSolver::setGreensFunction");
81
82 auto* infab = m_info.twod_mode ? detail::get_fab(m_r2c_green->m_rx)
83 : detail::get_fab(m_r2c.m_rx);
84 auto const& lo = m_domain.smallEnd();
85 auto const& lo3 = lo.dim3();
86 auto const& len = m_domain.length3d();
87 if (infab) {
88 auto const& a = infab->array();
89 auto box = infab->box();
90 GpuArray<int,3> nimages{1,1,1};
91 int ndims = m_info.twod_mode ? AMREX_SPACEDIM-1 : AMREX_SPACEDIM;
92 for (int idim = 0; idim < ndims; ++idim) {
93 if (box.smallEnd(idim) == lo[idim] && box.length(idim) == 2*len[idim]) {
94 box.growHi(idim, -len[idim]+1); // +1 to include the middle plane
95 nimages[idim] = 2;
96 }
97 }
98 AMREX_ASSERT(nimages[0] == 2);
99 box.shift(-lo);
100 amrex::ParallelFor(box, [=] AMREX_GPU_DEVICE (int i, int j, int k)
101 {
102 T G;
103 if (i == len[0] || j == len[1] || k == len[2]) {
104 G = 0;
105 } else {
106 auto ii = i;
107 auto jj = (j > len[1]) ? 2*len[1]-j : j;
108 auto kk = (k > len[2]) ? 2*len[2]-k : k;
109 G = greens_function(ii+lo3.x,jj+lo3.y,kk+lo3.z);
110 }
111 for (int koff = 0; koff < nimages[2]; ++koff) {
112 int k2 = (koff == 0) ? k : 2*len[2]-k;
113 if ((k2 == 2*len[2]) || (koff == 1 && k == len[2])) {
114 continue;
115 }
116 for (int joff = 0; joff < nimages[1]; ++joff) {
117 int j2 = (joff == 0) ? j : 2*len[1]-j;
118 if ((j2 == 2*len[1]) || (joff == 1 && j == len[1])) {
119 continue;
120 }
121 for (int ioff = 0; ioff < nimages[0]; ++ioff) {
122 int i2 = (ioff == 0) ? i : 2*len[0]-i;
123 if ((i2 == 2*len[0]) || (ioff == 1 && i == len[0])) {
124 continue;
125 }
126 a(i2+lo3.x,j2+lo3.y,k2+lo3.z) = G;
127 }
128 }
129 }
130 });
131 }
132
133 if (m_info.twod_mode) {
134 m_r2c_green->forward(m_r2c_green->m_rx);
135 } else {
136 m_r2c.forward(m_r2c.m_rx);
137 }
138
139 if (!m_info.twod_mode) {
140 auto [sd, ord] = m_r2c.getSpectralData();
142 auto const* srcfab = detail::get_fab(*sd);
143 if (srcfab) {
144 auto* dstfab = detail::get_fab(m_G_fft);
145 if (dstfab) {
146#if defined(AMREX_USE_GPU)
148#else
149 std::memcpy
150#endif
151 (dstfab->dataPtr(), srcfab->dataPtr(), dstfab->nBytes());
152 } else {
153 amrex::Abort("FFT::OpenBCSolver: how did this happen");
154 }
155 }
156
157 m_r2c.prepare_openbc();
158 }
159}
160
161template <typename T>
162void OpenBCSolver<T>::solve (MF& phi, MF const& rho)
163{
164 BL_PROFILE("OpenBCSolver::solve");
165
166 auto& inmf = m_r2c.m_rx;
167 inmf.setVal(T(0));
168 inmf.ParallelCopy(rho, 0, 0, 1);
169
170 m_r2c.m_openbc_half = !m_info.twod_mode;
171 m_r2c.forward(inmf);
172 m_r2c.m_openbc_half = false;
173
174 auto scaling_factor = m_r2c.scalingFactor();
175
176 auto const* gfab = detail::get_fab(m_G_fft);
177 if (gfab) {
178 auto [sd, ord] = m_r2c.getSpectralData();
180 auto* rhofab = detail::get_fab(*sd);
181 if (rhofab) {
182 auto* pdst = rhofab->dataPtr();
183 auto const* psrc = gfab->dataPtr();
184 Box const& rhobox = rhofab->box();
185#if (AMREX_SPACEDIM == 3)
186 Long leng = gfab->box().numPts();
187 if (m_info.twod_mode) {
188 AMREX_ASSERT(gfab->box().length(2) == 1 &&
189 leng == (rhobox.length(0) * rhobox.length(1)));
190 } else {
191 AMREX_ASSERT(leng == rhobox.numPts());
192 }
193#endif
194 amrex::ParallelFor(rhobox.numPts(), [=] AMREX_GPU_DEVICE (Long i)
195 {
196#if (AMREX_SPACEDIM == 3)
197 Long isrc = i % leng;
198#else
199 Long isrc = i;
200#endif
201 pdst[i] *= psrc[isrc] * scaling_factor;
202 });
203 } else {
204 amrex::Abort("FFT::OpenBCSolver::solve: how did this happen?");
205 }
206 }
207
208 m_r2c.m_openbc_half = !m_info.twod_mode;
209 m_r2c.backward_doit(phi, phi.nGrowVect());
210 m_r2c.m_openbc_half = false;
211}
212
213}
214
215#endif
#define BL_PROFILE(a)
Definition AMReX_BLProfiler.H:551
#define AMREX_ASSERT(EX)
Definition AMReX_BLassert.H:38
#define AMREX_GPU_DEVICE
Definition AMReX_GpuQualifiers.H:18
Real * pdst
Definition AMReX_HypreMLABecLap.cpp:1090
AMREX_GPU_HOST_DEVICE IndexTypeND< dim > ixType() const noexcept
Returns the indexing type.
Definition AMReX_Box.H:127
AMREX_GPU_HOST_DEVICE IntVectND< dim > length() const noexcept
Return the length of the BoxND.
Definition AMReX_Box.H:146
AMREX_GPU_HOST_DEVICE const IntVectND< dim > & smallEnd() const &noexcept
Get the smallend of the BoxND.
Definition AMReX_Box.H:105
AMREX_GPU_HOST_DEVICE Long numPts() const noexcept
Returns the number of points contained in the BoxND.
Definition AMReX_Box.H:346
AMREX_GPU_HOST_DEVICE const IntVectND< dim > & bigEnd() const &noexcept
Get the bigend.
Definition AMReX_Box.H:116
Definition AMReX_FFT_OpenBCSolver.H:11
Info m_info
Definition AMReX_FFT_OpenBCSolver.H:29
Box const & Domain() const
Definition AMReX_FFT_OpenBCSolver.H:23
cMF m_G_fft
Definition AMReX_FFT_OpenBCSolver.H:31
typename R2C< T >::MF MF
Definition AMReX_FFT_OpenBCSolver.H:13
void solve(MF &phi, MF const &rho)
Definition AMReX_FFT_OpenBCSolver.H:162
R2C< T > m_r2c
Definition AMReX_FFT_OpenBCSolver.H:30
void setGreensFunction(F const &greens_function)
Definition AMReX_FFT_OpenBCSolver.H:78
Box m_domain
Definition AMReX_FFT_OpenBCSolver.H:28
typename R2C< T >::cMF cMF
Definition AMReX_FFT_OpenBCSolver.H:14
std::unique_ptr< R2C< T > > m_r2c_green
Definition AMReX_FFT_OpenBCSolver.H:32
static Box make_grown_domain(Box const &domain, Info const &info)
Definition AMReX_FFT_OpenBCSolver.H:36
Parallel Discrete Fourier Transform.
Definition AMReX_FFT_R2C.H:40
std::conditional_t< C, cMF, std::conditional_t< std::is_same_v< T, Real >, MultiFab, FabArray< BaseFab< T > > > > MF
Definition AMReX_FFT_R2C.H:45
OpenBCSolver()=default
FA::FABType::value_type * get_fab(FA &fa)
Definition AMReX_FFT_Helper.H:1372
Definition AMReX_FFT.cpp:7
DomainStrategy
Definition AMReX_FFT_Helper.H:50
void dtod_memcpy_async(void *p_d_dst, const void *p_d_src, const std::size_t sz) noexcept
Definition AMReX_GpuDevice.H:279
int NProcsSub() noexcept
number of ranks in current frame
Definition AMReX_ParallelContext.H:74
@ make_alias
Definition AMReX_MakeType.H:7
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:191
BoxND< AMREX_SPACEDIM > Box
Definition AMReX_BaseFwd.H:27
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void ignore_unused(const Ts &...)
This shuts up the compiler about unused variables.
Definition AMReX.H:127
void Abort(const std::string &msg)
Print out message to cerr and exit via abort().
Definition AMReX.cpp:230
Definition AMReX_FFT_Helper.H:58
bool twod_mode
Definition AMReX_FFT_Helper.H:69
int nprocs
Max number of processes to use.
Definition AMReX_FFT_Helper.H:75
Definition AMReX_Array.H:34