Block-Structured AMR Software Framework
 
Loading...
Searching...
No Matches
AMReX_FFT_R2X.H
Go to the documentation of this file.
1#ifndef AMREX_FFT_R2X_H_
2#define AMREX_FFT_R2X_H_
3#include <AMReX_Config.H>
4
5#include <AMReX_MultiFab.H>
6#include <AMReX_FFT_Helper.H>
7#include <algorithm>
8#include <numeric>
9#include <tuple>
10
11namespace amrex::FFT
12{
13
14template <typename T> class Poisson;
15template <typename T> class PoissonHybrid;
16
23template <typename T = Real>
24class R2X
25{
26public:
27 using MF = std::conditional_t<std::is_same_v<T,Real>,
30
31 template <typename U> friend class Poisson;
32 template <typename U> friend class PoissonHybrid;
33
34 R2X (Box const& domain,
35 Array<std::pair<Boundary,Boundary>,AMREX_SPACEDIM> const& bc,
36 Info const& info = Info{});
37
38 ~R2X ();
39
40 R2X (R2X const&) = delete;
41 R2X (R2X &&) = delete;
42 R2X& operator= (R2X const&) = delete;
43 R2X& operator= (R2X &&) = delete;
44
45 [[nodiscard]] T scalingFactor () const;
46
47 template <typename F>
48 void forwardThenBackward (MF const& inmf, MF& outmf, F const& post_forward);
49
50 // public for cuda
51 template <int dim, typename FAB, typename F>
52 void post_forward_doit (FAB* fab, F const& f);
53
54 // private function made public for cuda
55 template <typename F>
56 void forwardThenBackward_doit_0 (MF const& inmf, MF& outmf, F const& post_forward,
57 IntVect const& ngout = IntVect(0),
58 Periodicity const& period = Periodicity::NonPeriodic());
59 template <typename F>
60 void forwardThenBackward_doit_1 (MF const& inmf, MF& outmf, F const& post_forward,
61 IntVect const& ngout = IntVect(0),
62 Periodicity const& period = Periodicity::NonPeriodic());
63
64private:
65
66 void forward (MF const& inmf, MF& outmf);
67 void forward (MF const& inmf, cMF& outmf);
68 void forward (MF const& inmf);
69 void backward (MF const& inmf, MF& outmf, IntVect const& ngout,
70 Periodicity const& period);
71 void backward (cMF const& inmf, MF& outmf, IntVect const& ngout,
72 Periodicity const& period);
73 void backward ();
74
77
84
85 std::unique_ptr<MultiBlockCommMetaData> m_cmd_cx2cy;
86 std::unique_ptr<MultiBlockCommMetaData> m_cmd_rx2ry;
87 std::unique_ptr<MultiBlockCommMetaData> m_cmd_cy2cz;
88 std::unique_ptr<MultiBlockCommMetaData> m_cmd_ry2rz;
89
90 std::unique_ptr<MultiBlockCommMetaData> m_cmd_cy2cx;
91 std::unique_ptr<MultiBlockCommMetaData> m_cmd_ry2rx;
92 std::unique_ptr<MultiBlockCommMetaData> m_cmd_cz2cy;
93 std::unique_ptr<MultiBlockCommMetaData> m_cmd_rz2ry;
94
99
106
107 std::unique_ptr<char,DataDeleter> m_data_1;
108 std::unique_ptr<char,DataDeleter> m_data_2;
109
116
117 std::unique_ptr<R2X<T>> m_r2x_sub;
119
121};
122
123template <typename T>
124R2X<T>::R2X (Box const& domain,
125 Array<std::pair<Boundary,Boundary>,AMREX_SPACEDIM> const& bc,
126 Info const& info)
127 : m_dom_0(domain),
128 m_bc(bc),
129 m_sub_helper(domain),
130 m_info(info)
131{
132 BL_PROFILE("FFT::R2X");
133
134 static_assert(std::is_same_v<float,T> || std::is_same_v<double,T>);
135
137#if (AMREX_SPACEDIM == 2)
139#else
140 if (m_info.twod_mode) {
141 AMREX_ALWAYS_ASSERT((int(domain.length(0) > 1) +
142 int(domain.length(1) > 1) +
143 int(domain.length(2) > 1)) >= 2);
144 }
145#endif
146
147 for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
148 if (bc[idim].first == Boundary::periodic ||
149 bc[idim].second == Boundary::periodic) {
150 AMREX_ALWAYS_ASSERT(bc[idim].first == bc[idim].second);
151 }
152 }
153
154 {
156 if (subbox.size() != m_dom_0.size()) {
157 m_r2x_sub = std::make_unique<R2X<T>>
158 (subbox, m_sub_helper.make_array(bc), info);
159 return;
160 }
161 }
162
163 int myproc = ParallelContext::MyProcSub();
164 int nprocs = std::min(ParallelContext::NProcsSub(), m_info.nprocs);
165
166 //
167 // make data containers
168 //
169
171 auto bax = amrex::decompose(m_dom_rx, nprocs, {AMREX_D_DECL(false,true,true)});
173 m_rx.define(bax, dmx, 1, 0, MFInfo().SetAlloc(false));
174
175 // x-direction
176 if (bc[0].first == Boundary::periodic) {
177 // x-fft: r2c(m_rx->m_cx)
178 m_dom_cx = Box(IntVect(0), IntVect(AMREX_D_DECL(domain.length(0)/2,
179 domain.bigEnd(1),
180 domain.bigEnd(2))));
181 BoxList bl = bax.boxList();
182 for (auto & b : bl) {
183 b.setBig(0, m_dom_cx.bigEnd(0));
184 }
185 BoxArray cbax(std::move(bl));
186 m_cx.define(cbax, dmx, 1, 0, MFInfo().SetAlloc(false));
187 } // else: x-fft: r2r(m_rx)
188
189#if (AMREX_SPACEDIM >= 2)
190 if (domain.length(1) > 1 && !m_info.oned_mode) {
191 if (! m_cx.empty()) {
192 // copy(m_cx->m_cy)
194 m_dom_cx.bigEnd(0),
195 m_dom_cx.bigEnd(2))));
196 auto ba = amrex::decompose(m_dom_cy, nprocs, {AMREX_D_DECL(false,true,true)});
198 if (ba.size() == m_cx.size()) {
199 dm = m_cx.DistributionMap();
200 } else {
201 dm = detail::make_iota_distromap(ba.size());
202 }
203 m_cy.define(ba, dm, 1, 0, MFInfo().SetAlloc(false));
204 // if bc[1] is periodic:
205 // c2c(m_cy->m_cy)
206 // else:
207 // r2r(m_cy.re) & r2r(m_cy.im)
208 } else {
209 // copy(m_rx->m_ry)
211 m_dom_rx.bigEnd(0),
212 m_dom_rx.bigEnd(2))));
213 auto ba = amrex::decompose(m_dom_ry, nprocs, {AMREX_D_DECL(false,true,true)});
215 if (ba.size() == m_rx.size()) {
216 dm = m_rx.DistributionMap();
217 } else {
218 dm = detail::make_iota_distromap(ba.size());
219 }
220 m_ry.define(ba, dm, 1, 0, MFInfo().SetAlloc(false));
221 // if bc[1] is periodic:
222 // r2c(m_ry->m_cy)
223 // else:
224 // r2r(m_ry)
225 if (bc[1].first == Boundary::periodic) {
227 m_dom_ry.bigEnd(1),
228 m_dom_ry.bigEnd(2))));
229 BoxList bl = ba.boxList();
230 for (auto & b : bl) {
231 b.setBig(0, m_dom_cy.bigEnd(0));
232 }
233 BoxArray cba(std::move(bl));
234 m_cy.define(cba, dm, 1, 0, MFInfo().SetAlloc(false));
235 }
236 }
237 }
238#endif
239
240#if (AMREX_SPACEDIM == 3)
241 if (domain.length(2) > 1 && !m_info.twod_mode) {
242 if (! m_cy.empty()) {
243 // copy(m_cy, m_cz)
245 m_dom_cy.bigEnd(1),
246 m_dom_cy.bigEnd(0))));
247 auto ba = amrex::decompose(m_dom_cz, nprocs, {AMREX_D_DECL(false,true,true)});
249 if (ba.size() == m_cy.size()) {
250 dm = m_cy.DistributionMap();
251 } else {
252 dm = detail::make_iota_distromap(ba.size());
253 }
254 m_cz.define(ba, dm, 1, 0, MFInfo().SetAlloc(false));
255 // if bc[2] is periodic:
256 // c2c(m_cz->m_cz)
257 // else:
258 // r2r(m_cz.re) & r2r(m_cz.im)
259 } else {
260 // copy(m_ry, m_rz)
262 m_dom_ry.bigEnd(1),
263 m_dom_ry.bigEnd(0))));
264 auto ba = amrex::decompose(m_dom_rz, nprocs, {AMREX_D_DECL(false,true,true)});
266 if (ba.size() == m_ry.size()) {
267 dm = m_ry.DistributionMap();
268 } else {
269 dm = detail::make_iota_distromap(ba.size());
270 }
271 m_rz.define(ba, dm, 1, 0, MFInfo().SetAlloc(false));
272 // if bc[2] is periodic:
273 // r2c(m_rz->m_cz)
274 // else:
275 // r2r(m_rz)
276 if (bc[2].first == Boundary::periodic) {
278 m_dom_rz.bigEnd(1),
279 m_dom_rz.bigEnd(2))));
280 BoxList bl = ba.boxList();
281 for (auto & b : bl) {
282 b.setBig(0, m_dom_cz.bigEnd(0));
283 }
284 BoxArray cba(std::move(bl));
285 m_cz.define(cba, dm, 1, 0, MFInfo().SetAlloc(false));
286 }
287 }
288 }
289#endif
290
291 // There are several different execution paths.
292 //
293 // (1) x-r2c(m_rx->m_cx), copy(m_cx->m_cy), y-fft(m_cy),
294 // copy(m_cy->m_cz), z-fft(m_cz)
295 // In this case, we have m_rx, m_cx, m_cy, & m_cz.
296 // we can alias(m_rx,m_cy) and alias(m_cx,m_cz).
297 //
298 // (2) x_r2r(m_rx), copy(m_rx->m_ry), y-r2c(m_ry->m_cy),
299 // copy(m_cy->m_cz), z-fft(m_cz)
300 // In this case, we have m_rx, m_ry, m_cy, & m_cz.
301 // We can alias(m_rx,m_cy) and alias(m_ry,m_cz).
302 //
303 // (3) x_r2r(m_rx), copy(m_rx->m_ry), y-r2r(m_ry),
304 // copy(m_ry->m_rz), z-r2c(m_rz->m_rz)
305 // In this case, we have m_rx, m_ry, m_rz, & m_cz
306 // We can alias(m_rx,m_rz) and alias(m_ry,m_cz)
307 //
308 // (4) x_r2r(m_rx), copy(m_rx->m_ry), y-r2r(m_ry),
309 // copy(m_ry->m_rz), z-r2r(m_rz)
310 // In this case, we have m_rx, m_ry, & m_rz.
311 // We can alias(m_rx,m_rz).
312
313 if (! m_cx.empty()) {
316 } else if (! m_cy.empty()) {
319 } else if (! m_cz.empty()) {
322 } else {
324 m_data_2 = detail::make_mfs_share(m_ry, m_cz); // It's okay m_cz is empty.
325 }
326
327 //
328 // make copiers
329 //
330
331#if (AMREX_SPACEDIM >= 2)
332 if (!m_cy.empty() || !m_ry.empty()) {
333 if (! m_cx.empty()) {
334 // copy(m_cx->m_cy)
335 m_cmd_cx2cy = std::make_unique<MultiBlockCommMetaData>
337 m_cmd_cy2cx = std::make_unique<MultiBlockCommMetaData>
339 } else {
340 // copy(m_rx->m_ry)
341 m_cmd_rx2ry = std::make_unique<MultiBlockCommMetaData>
343 m_cmd_ry2rx = std::make_unique<MultiBlockCommMetaData>
345 }
346 }
347#endif
348
349#if (AMREX_SPACEDIM == 3)
350 if (!m_cz.empty() || !m_rz.empty()) {
351 if (! m_cy.empty()) {
352 // copy(m_cy, m_cz)
353 m_cmd_cy2cz = std::make_unique<MultiBlockCommMetaData>
355 m_cmd_cz2cy = std::make_unique<MultiBlockCommMetaData>
357 } else {
358 // copy(m_ry, m_rz)
359 m_cmd_ry2rz = std::make_unique<MultiBlockCommMetaData>
361 m_cmd_rz2ry = std::make_unique<MultiBlockCommMetaData>
363 }
364 }
365#endif
366
367 //
368 // make plans
369 //
370
371 using VendorComplex = typename Plan<T>::VendorComplex;
372
373 if (myproc < m_rx.size())
374 {
375 Box const& box = m_rx.box(myproc);
376 auto* pf = m_rx[myproc].dataPtr();
377 if (bc[0].first == Boundary::periodic) {
378 auto* pb = (VendorComplex*) m_cx[myproc].dataPtr();
379 m_fft_fwd_x.template init_r2c<Direction::forward>(box, pf, pb);
380#if defined(AMREX_USE_SYCL)
382#else
383 m_fft_bwd_x.template init_r2c<Direction::backward>(box, pf, pb);
384#endif
385 } else {
386 m_fft_fwd_x.template init_r2r<Direction::forward>(box, pf, bc[0]);
387#if defined(AMREX_USE_GPU)
388 if ((bc[0].first == Boundary::even && bc[0].second == Boundary::odd) ||
389 (bc[0].first == Boundary::odd && bc[0].second == Boundary::even)) {
391 } else
392#endif
393 {
394 m_fft_bwd_x.template init_r2r<Direction::backward>(box, pf, bc[0]);
395 }
396 }
397 }
398
399#if (AMREX_SPACEDIM >= 2)
400 if (m_ry.empty() && m_bc[1].first == Boundary::periodic) {
401 if (myproc < m_cy.size()) {
402 Box const& box = m_cy.box(myproc);
403 auto* p = (VendorComplex *)m_cy[myproc].dataPtr();
404 m_fft_fwd_y.template init_c2c<Direction::forward>(box, p);
405#if defined(AMREX_USE_SYCL)
407#else
408 m_fft_bwd_y.template init_c2c<Direction::backward>(box, p);
409#endif
410 }
411 } else if (!m_ry.empty() && m_bc[1].first == Boundary::periodic) {
412 if (myproc < m_ry.size()) {
413 Box const& box = m_ry.box(myproc);
414 auto* pr = m_ry[myproc].dataPtr();
415 auto* pc = (VendorComplex*)m_cy[myproc].dataPtr();
416 m_fft_fwd_y.template init_r2c<Direction::forward>(box, pr, pc);
417#if defined(AMREX_USE_SYCL)
419#else
420 m_fft_bwd_y.template init_r2c<Direction::backward>(box, pr, pc);
421#endif
422 }
423 } else if (!m_cy.empty()) {
424 if (myproc < m_cy.size()) {
425 Box const& box = m_cy.box(myproc);
426 auto* p = (VendorComplex*) m_cy[myproc].dataPtr();
427 m_fft_fwd_y.template init_r2r<Direction::forward>(box, p, bc[1]);
428#if defined(AMREX_USE_GPU)
429 if ((bc[1].first == Boundary::even && bc[1].second == Boundary::odd) ||
430 (bc[1].first == Boundary::odd && bc[1].second == Boundary::even)) {
432 } else
433#endif
434 {
435 m_fft_bwd_y.template init_r2r<Direction::backward>(box, p, bc[1]);
436 }
437 }
438 } else {
439 if (myproc < m_ry.size()) {
440 Box const& box = m_ry.box(myproc);
441 auto* p = m_ry[myproc].dataPtr();
442 m_fft_fwd_y.template init_r2r<Direction::forward>(box, p, bc[1]);
443#if defined(AMREX_USE_GPU)
444 if ((bc[1].first == Boundary::even && bc[1].second == Boundary::odd) ||
445 (bc[1].first == Boundary::odd && bc[1].second == Boundary::even)) {
447 } else
448#endif
449 {
450 m_fft_bwd_y.template init_r2r<Direction::backward>(box, p, bc[1]);
451 }
452 }
453 }
454#endif
455
456#if (AMREX_SPACEDIM == 3)
457 if (m_rz.empty() && m_bc[2].first == Boundary::periodic) {
458 if (myproc < m_cz.size()) {
459 Box const& box = m_cz.box(myproc);
460 auto* p = (VendorComplex*)m_cz[myproc].dataPtr();
461 m_fft_fwd_z.template init_c2c<Direction::forward>(box, p);
462#if defined(AMREX_USE_SYCL)
464#else
465 m_fft_bwd_z.template init_c2c<Direction::backward>(box, p);
466#endif
467 }
468 } else if (!m_rz.empty() && m_bc[2].first == Boundary::periodic) {
469 if (myproc < m_rz.size()) {
470 Box const& box = m_rz.box(myproc);
471 auto* pr = m_rz[myproc].dataPtr();
472 auto* pc = (VendorComplex*)m_cz[myproc].dataPtr();
473 m_fft_fwd_z.template init_r2c<Direction::forward>(box, pr, pc);
474#if defined(AMREX_USE_SYCL)
476#else
477 m_fft_bwd_z.template init_r2c<Direction::backward>(box, pr, pc);
478#endif
479 }
480 } else if (!m_cz.empty()) {
481 if (myproc < m_cz.size()) {
482 Box const& box = m_cz.box(myproc);
483 auto* p = (VendorComplex*) m_cz[myproc].dataPtr();
484 m_fft_fwd_z.template init_r2r<Direction::forward>(box, p, bc[2]);
485#if defined(AMREX_USE_GPU)
486 if ((bc[2].first == Boundary::even && bc[2].second == Boundary::odd) ||
487 (bc[2].first == Boundary::odd && bc[2].second == Boundary::even)) {
489 } else
490#endif
491 {
492 m_fft_bwd_z.template init_r2r<Direction::backward>(box, p, bc[2]);
493 }
494 }
495 } else {
496 if (myproc < m_rz.size()) {
497 Box const& box = m_rz.box(myproc);
498 auto* p = m_rz[myproc].dataPtr();
499 m_fft_fwd_z.template init_r2r<Direction::forward>(box, p, bc[2]);
500#if defined(AMREX_USE_GPU)
501 if ((bc[2].first == Boundary::even && bc[2].second == Boundary::odd) ||
502 (bc[2].first == Boundary::odd && bc[2].second == Boundary::even)) {
504 } else
505#endif
506 {
507 m_fft_bwd_z.template init_r2r<Direction::backward>(box, p, bc[2]);
508 }
509 }
510 }
511#endif
512}
513
514template <typename T>
516{
517 if (m_fft_bwd_x.plan != m_fft_fwd_x.plan) {
518 m_fft_bwd_x.destroy();
519 }
520 if (m_fft_bwd_y.plan != m_fft_fwd_y.plan) {
521 m_fft_bwd_y.destroy();
522 }
523 if (m_fft_bwd_z.plan != m_fft_fwd_z.plan) {
524 m_fft_bwd_z.destroy();
525 }
526 m_fft_fwd_x.destroy();
527 m_fft_fwd_y.destroy();
528 m_fft_fwd_z.destroy();
529}
530
531template <typename T>
533{
534 Long r = 1;
535 int ndims = m_info.twod_mode ? AMREX_SPACEDIM-1 : AMREX_SPACEDIM;
536#if (AMREX_SPACEDIM == 3)
537 if (m_info.twod_mode && m_dom_0.length(2) == 1) { ndims = 1; };
538#endif
539 for (int idim = 0; idim < ndims; ++idim) {
540 r *= m_dom_0.length(idim);
541 if (m_bc[idim].first != Boundary::periodic && (m_dom_0.length(idim) > 1)) {
542 r *= 2;
543 }
544 }
545 return T(1)/T(r);
546}
547
548template <typename T>
549template <typename F>
550void R2X<T>::forwardThenBackward (MF const& inmf, MF& outmf, F const& post_forward)
551{
552 forwardThenBackward_doit_0(inmf, outmf, post_forward);
553}
554
555template <typename T>
556template <typename F>
557void R2X<T>::forwardThenBackward_doit_0 (MF const& inmf, MF& outmf,
558 F const& post_forward,
559 IntVect const& ngout,
560 Periodicity const& period)
561{
562 BL_PROFILE("FFT::R2X::forwardbackward_0");
563
564 if (m_r2x_sub) {
565 bool inmf_safe = m_sub_helper.ghost_safe(inmf.nGrowVect());
566 MF inmf_sub, inmf_tmp;
567 if (inmf_safe) {
568 inmf_sub = m_sub_helper.make_alias_mf(inmf);
569 } else {
570 inmf_tmp.define(inmf.boxArray(), inmf.DistributionMap(), 1, 0);
571 inmf_tmp.LocalCopy(inmf, 0, 0, 1, IntVect(0));
572 inmf_sub = m_sub_helper.make_alias_mf(inmf_tmp);
573 }
574
575 bool outmf_safe = m_sub_helper.ghost_safe(outmf.nGrowVect());
576 MF outmf_sub, outmf_tmp;
577 if (outmf_safe) {
578 outmf_sub = m_sub_helper.make_alias_mf(outmf);
579 } else {
580 IntVect const& ngtmp = m_sub_helper.make_safe_ghost(outmf.nGrowVect());
581 outmf_tmp.define(outmf.boxArray(), outmf.DistributionMap(), 1, ngtmp);
582 outmf_sub = m_sub_helper.make_alias_mf(outmf_tmp);
583 }
584
585 IntVect const& subngout = m_sub_helper.make_iv(ngout);
586 Periodicity const& subperiod = m_sub_helper.make_periodicity(period);
587 GpuArray<int,3> const& order = m_sub_helper.xyz_order();
588 m_r2x_sub->forwardThenBackward_doit_1
589 (inmf_sub, outmf_sub,
590 [=] AMREX_GPU_DEVICE (int i, int j, int k, auto& sp)
591 {
592 GpuArray<int,3> idx{i,j,k};
593 post_forward(idx[order[0]], idx[order[1]], idx[order[2]], sp);
594 },
595 subngout, subperiod);
596
597 if (!outmf_safe) {
598 outmf.LocalCopy(outmf_tmp, 0, 0, 1, outmf_tmp.nGrowVect());
599 }
600 }
601 else
602 {
603 this->forwardThenBackward_doit_1(inmf, outmf, post_forward, ngout, period);
604 }
605}
606
607template <typename T>
608template <typename F>
609void R2X<T>::forwardThenBackward_doit_1 (MF const& inmf, MF& outmf,
610 F const& post_forward,
611 IntVect const& ngout,
612 Periodicity const& period)
613{
614 BL_PROFILE("FFT::R2X::forwardbackward_1");
615
616 if (m_r2x_sub) {
617 amrex::Abort("R2X::forwardThenBackward_doit_1: How did this happen?");
618 }
619 else
620 {
621 this->forward(inmf);
622
623 // post-forward
624
625 int actual_dim = AMREX_SPACEDIM;
626#if (AMREX_SPACEDIM >= 2)
627 if (m_dom_0.length(1) == 1) { actual_dim = 1; }
628#endif
629#if (AMREX_SPACEDIM == 3)
630 if ((m_dom_0.length(2) == 1) && (m_dom_0.length(1) > 1)) { actual_dim = 2; }
631#endif
632
633 if (actual_dim == 1) {
634 if (m_cx.empty()) {
635 post_forward_doit<0>(detail::get_fab(m_rx), post_forward);
636 } else {
637 post_forward_doit<0>(detail::get_fab(m_cx), post_forward);
638 }
639 }
640#if (AMREX_SPACEDIM >= 2)
641 else if (actual_dim == 2) {
642 if (m_cy.empty()) {
643 post_forward_doit<1>(detail::get_fab(m_ry), post_forward);
644 } else {
645 post_forward_doit<1>(detail::get_fab(m_cy), post_forward);
646 }
647 }
648#endif
649#if (AMREX_SPACEDIM == 3)
650 else if (actual_dim == 3) {
651 if (m_cz.empty()) {
652 post_forward_doit<2>(detail::get_fab(m_rz), post_forward);
653 } else {
654 post_forward_doit<2>(detail::get_fab(m_cz), post_forward);
655 }
656 }
657#endif
658
659 this->backward();
660
661 outmf.ParallelCopy(m_rx, 0, 0, 1, IntVect(0),
662 amrex::elemwiseMin(ngout,outmf.nGrowVect()), period);
663 }
664}
665
666template <typename T>
667void R2X<T>::forward (MF const& inmf)
668{
669 BL_PROFILE("FFT::R2X::forward");
670
671 if (m_r2x_sub) {
672 if (m_sub_helper.ghost_safe(inmf.nGrowVect())) {
673 m_r2x_sub->forward(m_sub_helper.make_alias_mf(inmf));
674 } else {
675 MF tmp(inmf.boxArray(), inmf.DistributionMap(), 1, 0);
676 tmp.LocalCopy(inmf, 0, 0, 1, IntVect(0));
677 m_r2x_sub->forward(m_sub_helper.make_alias_mf(tmp));
678 }
679 return;
680 }
681
682 m_rx.ParallelCopy(inmf, 0, 0, 1);
683 if (m_bc[0].first == Boundary::periodic) {
684 m_fft_fwd_x.template compute_r2c<Direction::forward>();
685 } else {
686 m_fft_fwd_x.template compute_r2r<Direction::forward>();
687 }
688
689#if (AMREX_SPACEDIM >= 2)
690 if ( m_cmd_cx2cy) {
691 ParallelCopy(m_cy, m_cx, *m_cmd_cx2cy, 0, 0, 1, m_dtos_x2y);
692 } else if ( m_cmd_rx2ry) {
693 ParallelCopy(m_ry, m_rx, *m_cmd_rx2ry, 0, 0, 1, m_dtos_x2y);
694 }
695 if (m_bc[1].first != Boundary::periodic)
696 {
697 m_fft_fwd_y.template compute_r2r<Direction::forward>();
698 }
699 else if (m_bc[0].first == Boundary::periodic)
700 {
701 m_fft_fwd_y.template compute_c2c<Direction::forward>();
702 }
703 else
704 {
705 m_fft_fwd_y.template compute_r2c<Direction::forward>();
706 }
707#endif
708
709#if (AMREX_SPACEDIM == 3)
710 if ( m_cmd_cy2cz) {
711 ParallelCopy(m_cz, m_cy, *m_cmd_cy2cz, 0, 0, 1, m_dtos_y2z);
712 } else if ( m_cmd_ry2rz) {
713 ParallelCopy(m_rz, m_ry, *m_cmd_ry2rz, 0, 0, 1, m_dtos_y2z);
714 }
715 if (m_bc[2].first != Boundary::periodic)
716 {
717 m_fft_fwd_z.template compute_r2r<Direction::forward>();
718 }
719 else if (m_bc[0].first == Boundary::periodic ||
720 m_bc[1].first == Boundary::periodic)
721 {
722 m_fft_fwd_z.template compute_c2c<Direction::forward>();
723 }
724 else
725 {
726 m_fft_fwd_z.template compute_r2c<Direction::forward>();
727 }
728#endif
729}
730
731template <typename T>
732void R2X<T>::forward (MF const& inmf, MF& outmf)
733{
734 if (m_r2x_sub)
735 {
736 bool inmf_safe = m_sub_helper.ghost_safe(inmf.nGrowVect());
737 MF inmf_sub, inmf_tmp;
738 if (inmf_safe) {
739 inmf_sub = m_sub_helper.make_alias_mf(inmf);
740 } else {
741 inmf_tmp.define(inmf.boxArray(), inmf.DistributionMap(), 1, 0);
742 inmf_tmp.LocalCopy(inmf, 0, 0, 1, IntVect(0));
743 inmf_sub = m_sub_helper.make_alias_mf(inmf_tmp);
744 }
745
746 bool outmf_safe = m_sub_helper.ghost_safe(outmf.nGrowVect());
747 MF outmf_sub, outmf_tmp;
748 if (outmf_safe) {
749 outmf_sub = m_sub_helper.make_alias_mf(outmf);
750 } else {
751 outmf_tmp.define(outmf.boxArray(), outmf.DistributionMap(), 1, 0);
752 outmf_sub = m_sub_helper.make_alias_mf(outmf_tmp);
753 }
754
755 m_r2x_sub->forward(inmf_sub, outmf_sub);
756
757 if (!outmf_safe) {
758 outmf.LocalCopy(outmf_tmp, 0, 0, 1, IntVect(0));
759 }
760 }
761 else
762 {
763 this->forward(inmf);
764
765#if (AMREX_SPACEDIM == 3)
766 if (m_info.twod_mode) {
767 if (m_cy.empty() && !m_ry.empty()) {
768 ParallelCopy(outmf, m_dom_rx, m_ry, 0, 0, 1, IntVect(0), Swap01{});
769 } else if (m_ry.empty() && m_cy.empty() && m_cx.empty()) {
770 outmf.ParallelCopy(m_rx, 0, 0, 1);
771 } else {
772 amrex::Abort("R2X::forward(MF,MF): How did this happen?");
773 }
774 } else
775#endif
776 {
778 amrex::Abort("R2X::forward(MF,MF): TODO");
779 }
780 }
781}
782
783template <typename T>
784void R2X<T>::forward (MF const& inmf, cMF& outmf)
785{
786 if (m_r2x_sub)
787 {
788 bool inmf_safe = m_sub_helper.ghost_safe(inmf.nGrowVect());
789 MF inmf_sub, inmf_tmp;
790 if (inmf_safe) {
791 inmf_sub = m_sub_helper.make_alias_mf(inmf);
792 } else {
793 inmf_tmp.define(inmf.boxArray(), inmf.DistributionMap(), 1, 0);
794 inmf_tmp.LocalCopy(inmf, 0, 0, 1, IntVect(0));
795 inmf_sub = m_sub_helper.make_alias_mf(inmf_tmp);
796 }
797
798 bool outmf_safe = m_sub_helper.ghost_safe(outmf.nGrowVect());
799 cMF outmf_sub, outmf_tmp;
800 if (outmf_safe) {
801 outmf_sub = m_sub_helper.make_alias_mf(outmf);
802 } else {
803 outmf_tmp.define(outmf.boxArray(), outmf.DistributionMap(), 1, 0);
804 outmf_sub = m_sub_helper.make_alias_mf(outmf_tmp);
805 }
806
807 m_r2x_sub->forward(inmf_sub, outmf_sub);
808
809 if (!outmf_safe) {
810 outmf.LocalCopy(outmf_tmp, 0, 0, 1, IntVect(0));
811 }
812 }
813 else
814 {
815 this->forward(inmf);
816
817#if (AMREX_SPACEDIM == 3)
818 if (m_info.twod_mode) {
819 if (!m_cy.empty()) {
820 auto lo = m_dom_cy.smallEnd();
821 auto hi = m_dom_cy.bigEnd();
822 std::swap(lo[0],lo[1]);
823 std::swap(hi[0],hi[1]);
824 Box dom(lo,hi);
825 ParallelCopy(outmf, dom, m_cy, 0, 0, 1, IntVect(0), Swap01{});
826 } else if (m_ry.empty() && m_cy.empty() && !m_cx.empty()) {
827 outmf.ParallelCopy(m_cx, 0, 0, 1);
828 } else {
829 amrex::Abort("R2X::forward(MF,cMF): How did this happen?");
830 }
831 } else
832#endif
833 {
835 amrex::Abort("R2X::forward(MF,cMF): TODO");
836 }
837 }
838}
839
840template <typename T>
842{
843 BL_PROFILE("FFT::R2X::backward");
844
845 AMREX_ALWAYS_ASSERT(m_r2x_sub == nullptr);
846
847#if (AMREX_SPACEDIM == 3)
848 if (m_bc[2].first != Boundary::periodic)
849 {
850 m_fft_bwd_z.template compute_r2r<Direction::backward>();
851 }
852 else if (m_bc[0].first == Boundary::periodic ||
853 m_bc[1].first == Boundary::periodic)
854 {
855 m_fft_bwd_z.template compute_c2c<Direction::backward>();
856 }
857 else
858 {
859 m_fft_bwd_z.template compute_r2c<Direction::backward>();
860 }
861 if ( m_cmd_cz2cy) {
862 ParallelCopy(m_cy, m_cz, *m_cmd_cz2cy, 0, 0, 1, m_dtos_z2y);
863 } else if ( m_cmd_rz2ry) {
864 ParallelCopy(m_ry, m_rz, *m_cmd_rz2ry, 0, 0, 1, m_dtos_z2y);
865 }
866#endif
867
868#if (AMREX_SPACEDIM >= 2)
869 if (m_bc[1].first != Boundary::periodic)
870 {
871 m_fft_bwd_y.template compute_r2r<Direction::backward>();
872 }
873 else if (m_bc[0].first == Boundary::periodic)
874 {
875 m_fft_bwd_y.template compute_c2c<Direction::backward>();
876 }
877 else
878 {
879 m_fft_bwd_y.template compute_r2c<Direction::backward>();
880 }
881 if ( m_cmd_cy2cx) {
882 ParallelCopy(m_cx, m_cy, *m_cmd_cy2cx, 0, 0, 1, m_dtos_y2x);
883 } else if ( m_cmd_ry2rx) {
884 ParallelCopy(m_rx, m_ry, *m_cmd_ry2rx, 0, 0, 1, m_dtos_y2x);
885 }
886#endif
887
888 if (m_bc[0].first == Boundary::periodic) {
889 m_fft_bwd_x.template compute_r2c<Direction::backward>();
890 } else {
891 m_fft_bwd_x.template compute_r2r<Direction::backward>();
892 }
893}
894
895template <typename T>
896void R2X<T>::backward (MF const& inmf, MF& outmf, IntVect const& ngout,
897 Periodicity const& period)
898{
899 if (m_r2x_sub)
900 {
901 bool inmf_safe = m_sub_helper.ghost_safe(inmf.nGrowVect());
902 MF inmf_sub, inmf_tmp;
903 if (inmf_safe) {
904 inmf_sub = m_sub_helper.make_alias_mf(inmf);
905 } else {
906 inmf_tmp.define(inmf.boxArray(), inmf.DistributionMap(), 1, 0);
907 inmf_tmp.LocalCopy(inmf, 0, 0, 1, IntVect(0));
908 inmf_sub = m_sub_helper.make_alias_mf(inmf_tmp);
909 }
910
911 bool outmf_safe = m_sub_helper.ghost_safe(outmf.nGrowVect());
912 MF outmf_sub, outmf_tmp;
913 if (outmf_safe) {
914 outmf_sub = m_sub_helper.make_alias_mf(outmf);
915 } else {
916 IntVect const& ngtmp = m_sub_helper.make_safe_ghost(outmf.nGrowVect());
917 outmf_tmp.define(outmf.boxArray(), outmf.DistributionMap(), 1, ngtmp);
918 outmf_sub = m_sub_helper.make_alias_mf(outmf_tmp);
919 }
920
921 IntVect const& subngout = m_sub_helper.make_iv(ngout);
922 Periodicity const& subperiod = m_sub_helper.make_periodicity(period);
923 m_r2x_sub->backward(inmf_sub, outmf_sub, subngout, subperiod);
924
925 if (!outmf_safe) {
926 outmf.LocalCopy(outmf_tmp, 0, 0, 1, outmf_tmp.nGrowVect());
927 }
928 }
929 else
930 {
931#if (AMREX_SPACEDIM == 3)
932 if (m_info.twod_mode) {
933 if (m_cy.empty() && !m_ry.empty()) {
934 ParallelCopy(m_ry, m_dom_ry, inmf, 0, 0, 1, IntVect(0), Swap01{});
935 } else if (m_ry.empty() && m_cy.empty() && m_cx.empty()) {
936 m_rx.ParallelCopy(inmf, 0, 0, 1);
937 } else {
938 amrex::Abort("R2X::backward(MF,MF): How did this happen?");
939 }
940 } else
941#endif
942 {
943 amrex::ignore_unused(inmf,outmf,ngout,period);
944 amrex::Abort("R2X::backward(MF,MF): TODO");
945 }
946
947 this->backward();
948
949 outmf.ParallelCopy(m_rx, 0, 0, 1, IntVect(0),
950 amrex::elemwiseMin(ngout,outmf.nGrowVect()), period);
951 }
952}
953
954template <typename T>
955void R2X<T>::backward (cMF const& inmf, MF& outmf, IntVect const& ngout,
956 Periodicity const& period)
957{
958 if (m_r2x_sub)
959 {
960 bool inmf_safe = m_sub_helper.ghost_safe(inmf.nGrowVect());
961 cMF inmf_sub, inmf_tmp;
962 if (inmf_safe) {
963 inmf_sub = m_sub_helper.make_alias_mf(inmf);
964 } else {
965 inmf_tmp.define(inmf.boxArray(), inmf.DistributionMap(), 1, 0);
966 inmf_tmp.LocalCopy(inmf, 0, 0, 1, IntVect(0));
967 inmf_sub = m_sub_helper.make_alias_mf(inmf_tmp);
968 }
969
970 bool outmf_safe = m_sub_helper.ghost_safe(outmf.nGrowVect());
971 MF outmf_sub, outmf_tmp;
972 if (outmf_safe) {
973 outmf_sub = m_sub_helper.make_alias_mf(outmf);
974 } else {
975 IntVect const& ngtmp = m_sub_helper.make_safe_ghost(outmf.nGrowVect());
976 outmf_tmp.define(outmf.boxArray(), outmf.DistributionMap(), 1, ngtmp);
977 outmf_sub = m_sub_helper.make_alias_mf(outmf_tmp);
978 }
979
980 IntVect const& subngout = m_sub_helper.make_iv(ngout);
981 Periodicity const& subperiod = m_sub_helper.make_periodicity(period);
982 m_r2x_sub->backward(inmf_sub, outmf_sub, subngout, subperiod);
983
984 if (!outmf_safe) {
985 outmf.LocalCopy(outmf_tmp, 0, 0, 1, outmf_tmp.nGrowVect());
986 }
987 }
988 else
989 {
990#if (AMREX_SPACEDIM == 3)
991 if (m_info.twod_mode) {
992 if (!m_cy.empty()) {
993 ParallelCopy(m_cy, m_dom_cy, inmf, 0, 0, 1, IntVect(0), Swap01{});
994 } else if (m_ry.empty() && m_cy.empty() && !m_cx.empty()) {
995 m_cx.ParallelCopy(inmf, 0, 0, 1);
996 } else {
997 amrex::Abort("R2X::backward(cMF,MF): How did this happen?");
998 }
999 } else
1000#endif
1001 {
1002 amrex::ignore_unused(inmf,outmf,ngout,period);
1003 amrex::Abort("R2X::backward(cMF,MF): TODO");
1004 }
1005
1006 this->backward();
1007
1008 outmf.ParallelCopy(m_rx, 0, 0, 1, IntVect(0),
1009 amrex::elemwiseMin(ngout,outmf.nGrowVect()), period);
1010 }
1011}
1012
1013template <typename T>
1014template <int dim, typename FAB, typename F>
1015void R2X<T>::post_forward_doit (FAB* fab, F const& f)
1016{
1017 if (m_info.twod_mode) {
1018 amrex::Abort("xxxxx post_forward_doit: todo");
1019 }
1020 if (fab) {
1021 auto const& a = fab->array();
1022 ParallelForOMP(fab->box(),
1023 [f=f,a=a] AMREX_GPU_DEVICE (int i, int j, int k)
1024 {
1025 if constexpr (dim == 0) {
1026 f(i,j,k,a(i,j,k));
1027 } else if constexpr (dim == 1) {
1028 f(j,i,k,a(i,j,k));
1029 } else {
1030 f(j,k,i,a(i,j,k));
1031 }
1032 });
1033 }
1034}
1035
1036}
1037
1038#endif
#define BL_PROFILE(a)
Definition AMReX_BLProfiler.H:551
#define AMREX_ALWAYS_ASSERT(EX)
Definition AMReX_BLassert.H:50
#define AMREX_GPU_DEVICE
Definition AMReX_GpuQualifiers.H:18
#define AMREX_D_DECL(a, b, c)
Definition AMReX_SPACE.H:171
A collection of Boxes stored in an Array.
Definition AMReX_BoxArray.H:551
A class for managing a List of Boxes that share a common IndexType. This class implements operations ...
Definition AMReX_BoxList.H:52
__host__ __device__ const IntVectND< dim > & bigEnd() const &noexcept
Get the bigend.
Definition AMReX_Box.H:119
__host__ __device__ Long numPts() const noexcept
Returns the number of points contained in the BoxND.
Definition AMReX_Box.H:349
__host__ __device__ IntVectND< dim > length() const noexcept
Return the length of the BoxND.
Definition AMReX_Box.H:149
__host__ __device__ IntVectND< dim > size() const noexcept
Return the length of the BoxND.
Definition AMReX_Box.H:142
Calculates the distribution of FABs to MPI processes.
Definition AMReX_DistributionMapping.H:41
3D Poisson solver for periodic, Dirichlet & Neumann boundaries in the first two dimensions,...
Definition AMReX_FFT_Poisson.H:146
Poisson solver for periodic, Dirichlet & Neumann boundaries using FFT.
Definition AMReX_FFT_Poisson.H:58
Discrete Fourier Transform.
Definition AMReX_FFT_R2X.H:25
MF m_rz
Definition AMReX_FFT_R2X.H:102
void post_forward_doit(FAB *fab, F const &f)
Definition AMReX_FFT_R2X.H:1015
Array< std::pair< Boundary, Boundary >, 3 > m_bc
Definition AMReX_FFT_R2X.H:76
Swap01 m_dtos_x2y
Definition AMReX_FFT_R2X.H:95
void backward(cMF const &inmf, MF &outmf, IntVect const &ngout, Periodicity const &period)
Definition AMReX_FFT_R2X.H:955
void backward(MF const &inmf, MF &outmf, IntVect const &ngout, Periodicity const &period)
Definition AMReX_FFT_R2X.H:896
std::conditional_t< std::is_same_v< T, Real >, MultiFab, FabArray< BaseFab< T > > > MF
Definition AMReX_FFT_R2X.H:28
std::unique_ptr< MultiBlockCommMetaData > m_cmd_rz2ry
Definition AMReX_FFT_R2X.H:93
MF m_ry
Definition AMReX_FFT_R2X.H:101
Box m_dom_cz
Definition AMReX_FFT_R2X.H:115
void forward(MF const &inmf)
Definition AMReX_FFT_R2X.H:667
Swap02 m_dtos_y2z
Definition AMReX_FFT_R2X.H:97
~R2X()
Definition AMReX_FFT_R2X.H:515
void forward(MF const &inmf, MF &outmf)
Definition AMReX_FFT_R2X.H:732
detail::SubHelper m_sub_helper
Definition AMReX_FFT_R2X.H:118
void forwardThenBackward(MF const &inmf, MF &outmf, F const &post_forward)
Definition AMReX_FFT_R2X.H:550
std::unique_ptr< MultiBlockCommMetaData > m_cmd_ry2rx
Definition AMReX_FFT_R2X.H:91
Info m_info
Definition AMReX_FFT_R2X.H:120
std::unique_ptr< MultiBlockCommMetaData > m_cmd_cz2cy
Definition AMReX_FFT_R2X.H:92
std::unique_ptr< MultiBlockCommMetaData > m_cmd_cy2cz
Definition AMReX_FFT_R2X.H:87
Plan< T > m_fft_fwd_y
Definition AMReX_FFT_R2X.H:80
void forward(MF const &inmf, cMF &outmf)
Definition AMReX_FFT_R2X.H:784
MF m_rx
Definition AMReX_FFT_R2X.H:100
std::unique_ptr< MultiBlockCommMetaData > m_cmd_ry2rz
Definition AMReX_FFT_R2X.H:88
Box m_dom_rx
Definition AMReX_FFT_R2X.H:110
R2X(Box const &domain, Array< std::pair< Boundary, Boundary >, 3 > const &bc, Info const &info=Info{})
Definition AMReX_FFT_R2X.H:124
std::unique_ptr< MultiBlockCommMetaData > m_cmd_rx2ry
Definition AMReX_FFT_R2X.H:86
Swap01 m_dtos_y2x
Definition AMReX_FFT_R2X.H:96
Box m_dom_cy
Definition AMReX_FFT_R2X.H:114
R2X(R2X &&)=delete
T scalingFactor() const
Definition AMReX_FFT_R2X.H:532
Box m_dom_ry
Definition AMReX_FFT_R2X.H:111
void backward()
Definition AMReX_FFT_R2X.H:841
Plan< T > m_fft_bwd_z
Definition AMReX_FFT_R2X.H:83
R2X(R2X const &)=delete
std::unique_ptr< char, DataDeleter > m_data_1
Definition AMReX_FFT_R2X.H:107
Plan< T > m_fft_fwd_x
Definition AMReX_FFT_R2X.H:78
std::unique_ptr< R2X< T > > m_r2x_sub
Definition AMReX_FFT_R2X.H:117
R2X & operator=(R2X const &)=delete
std::unique_ptr< MultiBlockCommMetaData > m_cmd_cy2cx
Definition AMReX_FFT_R2X.H:90
Box m_dom_0
Definition AMReX_FFT_R2X.H:75
std::unique_ptr< MultiBlockCommMetaData > m_cmd_cx2cy
Definition AMReX_FFT_R2X.H:85
std::unique_ptr< char, DataDeleter > m_data_2
Definition AMReX_FFT_R2X.H:108
Plan< T > m_fft_fwd_z
Definition AMReX_FFT_R2X.H:82
Plan< T > m_fft_bwd_y
Definition AMReX_FFT_R2X.H:81
void forwardThenBackward_doit_1(MF const &inmf, MF &outmf, F const &post_forward, IntVect const &ngout=IntVect(0), Periodicity const &period=Periodicity::NonPeriodic())
Definition AMReX_FFT_R2X.H:609
cMF m_cx
Definition AMReX_FFT_R2X.H:103
cMF m_cz
Definition AMReX_FFT_R2X.H:105
Swap02 m_dtos_z2y
Definition AMReX_FFT_R2X.H:98
void forwardThenBackward_doit_0(MF const &inmf, MF &outmf, F const &post_forward, IntVect const &ngout=IntVect(0), Periodicity const &period=Periodicity::NonPeriodic())
Definition AMReX_FFT_R2X.H:557
cMF m_cy
Definition AMReX_FFT_R2X.H:104
Box m_dom_cx
Definition AMReX_FFT_R2X.H:113
Plan< T > m_fft_bwd_x
Definition AMReX_FFT_R2X.H:79
Box m_dom_rz
Definition AMReX_FFT_R2X.H:112
IntVect nGrowVect() const noexcept
Definition AMReX_FabArrayBase.H:80
int size() const noexcept
Return the number of FABs in the FabArray.
Definition AMReX_FabArrayBase.H:110
const DistributionMapping & DistributionMap() const noexcept
Return constant reference to associated DistributionMapping.
Definition AMReX_FabArrayBase.H:131
bool empty() const noexcept
Definition AMReX_FabArrayBase.H:89
Box box(int K) const noexcept
Return the Kth Box in the BoxArray. That is, the valid region of the Kth grid.
Definition AMReX_FabArrayBase.H:101
const BoxArray & boxArray() const noexcept
Return a constant reference to the BoxArray that defines the valid region associated with this FabArr...
Definition AMReX_FabArrayBase.H:95
An Array of FortranArrayBox(FAB)-like Objects.
Definition AMReX_FabArray.H:345
void ParallelCopy(const FabArray< FAB > &src, const Periodicity &period=Periodicity::NonPeriodic(), CpOp op=FabArrayBase::COPY)
Definition AMReX_FabArray.H:845
void define(const BoxArray &bxs, const DistributionMapping &dm, int nvar, int ngrow, const MFInfo &info=MFInfo(), const FabFactory< FAB > &factory=DefaultFabFactory< FAB >())
Define this FabArray identically to that performed by the constructor having an analogous function si...
Definition AMReX_FabArray.H:2128
void LocalCopy(FabArray< SFAB > const &src, int scomp, int dcomp, int ncomp, IntVect const &nghost)
Perform local copy of FabArray data.
Definition AMReX_FabArray.H:1909
A collection (stored as an array) of FArrayBox objects.
Definition AMReX_MultiFab.H:38
This provides length of period for periodic domains. 0 means it is not periodic in that direction....
Definition AMReX_Periodicity.H:17
static const Periodicity & NonPeriodic() noexcept
Definition AMReX_Periodicity.cpp:52
std::unique_ptr< char, DataDeleter > make_mfs_share(FA1 &fa1, FA2 &fa2)
Definition AMReX_FFT_Helper.H:1387
FA::FABType::value_type * get_fab(FA &fa)
Definition AMReX_FFT_Helper.H:1376
DistributionMapping make_iota_distromap(Long n)
Definition AMReX_FFT.cpp:88
Definition AMReX_FFT.cpp:7
int MyProcSub() noexcept
my sub-rank in current frame
Definition AMReX_ParallelContext.H:76
int NProcsSub() noexcept
number of ranks in current frame
Definition AMReX_ParallelContext.H:74
void ParallelForOMP(T n, L const &f) noexcept
Definition AMReX_GpuLaunch.H:249
__host__ __device__ void ignore_unused(const Ts &...)
This shuts up the compiler about unused variables.
Definition AMReX.H:138
BoxND< 3 > Box
Definition AMReX_BaseFwd.H:27
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:1931
IntVectND< 3 > IntVect
Definition AMReX_BaseFwd.H:30
void Abort(const std::string &msg)
Print out message to cerr and exit via abort().
Definition AMReX.cpp:230
void ParallelCopy(MF &dst, MF const &src, int scomp, int dcomp, int ncomp, IntVect const &ng_src=IntVect(0), IntVect const &ng_dst=IntVect(0), Periodicity const &period=Periodicity::NonPeriodic())
dst = src w/ MPI communication
Definition AMReX_FabArrayUtility.H:1967
__host__ __device__ constexpr T elemwiseMin(T const &a, T const &b) noexcept
Definition AMReX_Algorithm.H:49
std::array< T, N > Array
Definition AMReX_Array.H:24
Definition AMReX_FFT_Helper.H:58
bool twod_mode
Definition AMReX_FFT_Helper.H:69
bool oned_mode
We might have a special twod_mode: nx or ny == 1 && nz > 1.
Definition AMReX_FFT_Helper.H:72
int batch_size
Batched FFT size. Only support in R2C, not R2X.
Definition AMReX_FFT_Helper.H:75
int nprocs
Max number of processes to use.
Definition AMReX_FFT_Helper.H:78
Definition AMReX_FFT_Helper.H:130
std::conditional_t< std::is_same_v< float, T >, cuComplex, cuDoubleComplex > VendorComplex
Definition AMReX_FFT_Helper.H:134
Definition AMReX_FFT_Helper.H:1428
Definition AMReX_FFT_Helper.H:1451
Definition AMReX_FFT_Helper.H:1526
T make_array(T const &a) const
Definition AMReX_FFT_Helper.H:1546
Box make_box(Box const &box) const
Definition AMReX_FFT.cpp:142
Definition AMReX_Array.H:34
FabArray memory allocation information.
Definition AMReX_FabArray.H:66