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
191#if (AMREX_SPACEDIM == 2)
192 bool batch_on_y = false;
193#else
194 bool batch_on_y = m_info.twod_mode && (m_dom_0.length(2) == 1);
195#endif
196
197 if ((domain.length(1) > 1) && !batch_on_y) {
198 if (! m_cx.empty()) {
199 // copy(m_cx->m_cy)
201 m_dom_cx.bigEnd(0),
202 m_dom_cx.bigEnd(2))));
203 auto ba = amrex::decompose(m_dom_cy, nprocs, {AMREX_D_DECL(false,true,true)});
205 if (ba.size() == m_cx.size()) {
206 dm = m_cx.DistributionMap();
207 } else {
208 dm = detail::make_iota_distromap(ba.size());
209 }
210 m_cy.define(ba, dm, 1, 0, MFInfo().SetAlloc(false));
211 // if bc[1] is periodic:
212 // c2c(m_cy->m_cy)
213 // else:
214 // r2r(m_cy.re) & r2r(m_cy.im)
215 } else {
216 // copy(m_rx->m_ry)
218 m_dom_rx.bigEnd(0),
219 m_dom_rx.bigEnd(2))));
220 auto ba = amrex::decompose(m_dom_ry, nprocs, {AMREX_D_DECL(false,true,true)});
222 if (ba.size() == m_rx.size()) {
223 dm = m_rx.DistributionMap();
224 } else {
225 dm = detail::make_iota_distromap(ba.size());
226 }
227 m_ry.define(ba, dm, 1, 0, MFInfo().SetAlloc(false));
228 // if bc[1] is periodic:
229 // r2c(m_ry->m_cy)
230 // else:
231 // r2r(m_ry)
232 if (bc[1].first == Boundary::periodic) {
234 m_dom_ry.bigEnd(1),
235 m_dom_ry.bigEnd(2))));
236 BoxList bl = ba.boxList();
237 for (auto & b : bl) {
238 b.setBig(0, m_dom_cy.bigEnd(0));
239 }
240 BoxArray cba(std::move(bl));
241 m_cy.define(cba, dm, 1, 0, MFInfo().SetAlloc(false));
242 }
243 }
244 }
245#endif
246
247#if (AMREX_SPACEDIM == 3)
248 if (domain.length(2) > 1 && !m_info.twod_mode) {
249 if (! m_cy.empty()) {
250 // copy(m_cy, m_cz)
252 m_dom_cy.bigEnd(1),
253 m_dom_cy.bigEnd(0))));
254 auto ba = amrex::decompose(m_dom_cz, nprocs, {AMREX_D_DECL(false,true,true)});
256 if (ba.size() == m_cy.size()) {
257 dm = m_cy.DistributionMap();
258 } else {
259 dm = detail::make_iota_distromap(ba.size());
260 }
261 m_cz.define(ba, dm, 1, 0, MFInfo().SetAlloc(false));
262 // if bc[2] is periodic:
263 // c2c(m_cz->m_cz)
264 // else:
265 // r2r(m_cz.re) & r2r(m_cz.im)
266 } else {
267 // copy(m_ry, m_rz)
269 m_dom_ry.bigEnd(1),
270 m_dom_ry.bigEnd(0))));
271 auto ba = amrex::decompose(m_dom_rz, nprocs, {AMREX_D_DECL(false,true,true)});
273 if (ba.size() == m_ry.size()) {
274 dm = m_ry.DistributionMap();
275 } else {
276 dm = detail::make_iota_distromap(ba.size());
277 }
278 m_rz.define(ba, dm, 1, 0, MFInfo().SetAlloc(false));
279 // if bc[2] is periodic:
280 // r2c(m_rz->m_cz)
281 // else:
282 // r2r(m_rz)
283 if (bc[2].first == Boundary::periodic) {
285 m_dom_rz.bigEnd(1),
286 m_dom_rz.bigEnd(2))));
287 BoxList bl = ba.boxList();
288 for (auto & b : bl) {
289 b.setBig(0, m_dom_cz.bigEnd(0));
290 }
291 BoxArray cba(std::move(bl));
292 m_cz.define(cba, dm, 1, 0, MFInfo().SetAlloc(false));
293 }
294 }
295 }
296#endif
297
298 // There are several different execution paths.
299 //
300 // (1) x-r2c(m_rx->m_cx), copy(m_cx->m_cy), y-fft(m_cy),
301 // copy(m_cy->m_cz), z-fft(m_cz)
302 // In this case, we have m_rx, m_cx, m_cy, & m_cz.
303 // we can alias(m_rx,m_cy) and alias(m_cx,m_cz).
304 //
305 // (2) x_r2r(m_rx), copy(m_rx->m_ry), y-r2c(m_ry->m_cy),
306 // copy(m_cy->m_cz), z-fft(m_cz)
307 // In this case, we have m_rx, m_ry, m_cy, & m_cz.
308 // We can alias(m_rx,m_cy) and alias(m_ry,m_cz).
309 //
310 // (3) x_r2r(m_rx), copy(m_rx->m_ry), y-r2r(m_ry),
311 // copy(m_ry->m_rz), z-r2c(m_rz->m_rz)
312 // In this case, we have m_rx, m_ry, m_rz, & m_cz
313 // We can alias(m_rx,m_rz) and alias(m_ry,m_cz)
314 //
315 // (4) x_r2r(m_rx), copy(m_rx->m_ry), y-r2r(m_ry),
316 // copy(m_ry->m_rz), z-r2r(m_rz)
317 // In this case, we have m_rx, m_ry, & m_rz.
318 // We can alias(m_rx,m_rz).
319
320 if (! m_cx.empty()) {
323 } else if (! m_cy.empty()) {
326 } else if (! m_cz.empty()) {
329 } else {
331 m_data_2 = detail::make_mfs_share(m_ry, m_cz); // It's okay m_cz is empty.
332 }
333
334 //
335 // make copiers
336 //
337
338#if (AMREX_SPACEDIM >= 2)
339 if (!m_cy.empty() || !m_ry.empty()) {
340 if (! m_cx.empty()) {
341 // copy(m_cx->m_cy)
342 m_cmd_cx2cy = std::make_unique<MultiBlockCommMetaData>
344 m_cmd_cy2cx = std::make_unique<MultiBlockCommMetaData>
346 } else {
347 // copy(m_rx->m_ry)
348 m_cmd_rx2ry = std::make_unique<MultiBlockCommMetaData>
350 m_cmd_ry2rx = std::make_unique<MultiBlockCommMetaData>
352 }
353 }
354#endif
355
356#if (AMREX_SPACEDIM == 3)
357 if (!m_cz.empty() || !m_rz.empty()) {
358 if (! m_cy.empty()) {
359 // copy(m_cy, m_cz)
360 m_cmd_cy2cz = std::make_unique<MultiBlockCommMetaData>
362 m_cmd_cz2cy = std::make_unique<MultiBlockCommMetaData>
364 } else {
365 // copy(m_ry, m_rz)
366 m_cmd_ry2rz = std::make_unique<MultiBlockCommMetaData>
368 m_cmd_rz2ry = std::make_unique<MultiBlockCommMetaData>
370 }
371 }
372#endif
373
374 //
375 // make plans
376 //
377
378 using VendorComplex = typename Plan<T>::VendorComplex;
379
380 if (myproc < m_rx.size())
381 {
382 Box const& box = m_rx.box(myproc);
383 auto* pf = m_rx[myproc].dataPtr();
384 if (bc[0].first == Boundary::periodic) {
385 auto* pb = (VendorComplex*) m_cx[myproc].dataPtr();
386 m_fft_fwd_x.template init_r2c<Direction::forward>(box, pf, pb);
387#if defined(AMREX_USE_SYCL)
389#else
390 m_fft_bwd_x.template init_r2c<Direction::backward>(box, pf, pb);
391#endif
392 } else {
393 m_fft_fwd_x.template init_r2r<Direction::forward>(box, pf, bc[0]);
394#if defined(AMREX_USE_GPU)
395 if ((bc[0].first == Boundary::even && bc[0].second == Boundary::odd) ||
396 (bc[0].first == Boundary::odd && bc[0].second == Boundary::even)) {
398 } else
399#endif
400 {
401 m_fft_bwd_x.template init_r2r<Direction::backward>(box, pf, bc[0]);
402 }
403 }
404 }
405
406#if (AMREX_SPACEDIM >= 2)
407 if (m_ry.empty() && m_bc[1].first == Boundary::periodic) {
408 if (myproc < m_cy.size()) {
409 Box const& box = m_cy.box(myproc);
410 auto* p = (VendorComplex *)m_cy[myproc].dataPtr();
411 m_fft_fwd_y.template init_c2c<Direction::forward>(box, p);
412#if defined(AMREX_USE_SYCL)
414#else
415 m_fft_bwd_y.template init_c2c<Direction::backward>(box, p);
416#endif
417 }
418 } else if (!m_ry.empty() && m_bc[1].first == Boundary::periodic) {
419 if (myproc < m_ry.size()) {
420 Box const& box = m_ry.box(myproc);
421 auto* pr = m_ry[myproc].dataPtr();
422 auto* pc = (VendorComplex*)m_cy[myproc].dataPtr();
423 m_fft_fwd_y.template init_r2c<Direction::forward>(box, pr, pc);
424#if defined(AMREX_USE_SYCL)
426#else
427 m_fft_bwd_y.template init_r2c<Direction::backward>(box, pr, pc);
428#endif
429 }
430 } else if (!m_cy.empty()) {
431 if (myproc < m_cy.size()) {
432 Box const& box = m_cy.box(myproc);
433 auto* p = (VendorComplex*) m_cy[myproc].dataPtr();
434 m_fft_fwd_y.template init_r2r<Direction::forward>(box, p, bc[1]);
435#if defined(AMREX_USE_GPU)
436 if ((bc[1].first == Boundary::even && bc[1].second == Boundary::odd) ||
437 (bc[1].first == Boundary::odd && bc[1].second == Boundary::even)) {
439 } else
440#endif
441 {
442 m_fft_bwd_y.template init_r2r<Direction::backward>(box, p, bc[1]);
443 }
444 }
445 } else {
446 if (myproc < m_ry.size()) {
447 Box const& box = m_ry.box(myproc);
448 auto* p = m_ry[myproc].dataPtr();
449 m_fft_fwd_y.template init_r2r<Direction::forward>(box, p, bc[1]);
450#if defined(AMREX_USE_GPU)
451 if ((bc[1].first == Boundary::even && bc[1].second == Boundary::odd) ||
452 (bc[1].first == Boundary::odd && bc[1].second == Boundary::even)) {
454 } else
455#endif
456 {
457 m_fft_bwd_y.template init_r2r<Direction::backward>(box, p, bc[1]);
458 }
459 }
460 }
461#endif
462
463#if (AMREX_SPACEDIM == 3)
464 if (m_rz.empty() && m_bc[2].first == Boundary::periodic) {
465 if (myproc < m_cz.size()) {
466 Box const& box = m_cz.box(myproc);
467 auto* p = (VendorComplex*)m_cz[myproc].dataPtr();
468 m_fft_fwd_z.template init_c2c<Direction::forward>(box, p);
469#if defined(AMREX_USE_SYCL)
471#else
472 m_fft_bwd_z.template init_c2c<Direction::backward>(box, p);
473#endif
474 }
475 } else if (!m_rz.empty() && m_bc[2].first == Boundary::periodic) {
476 if (myproc < m_rz.size()) {
477 Box const& box = m_rz.box(myproc);
478 auto* pr = m_rz[myproc].dataPtr();
479 auto* pc = (VendorComplex*)m_cz[myproc].dataPtr();
480 m_fft_fwd_z.template init_r2c<Direction::forward>(box, pr, pc);
481#if defined(AMREX_USE_SYCL)
483#else
484 m_fft_bwd_z.template init_r2c<Direction::backward>(box, pr, pc);
485#endif
486 }
487 } else if (!m_cz.empty()) {
488 if (myproc < m_cz.size()) {
489 Box const& box = m_cz.box(myproc);
490 auto* p = (VendorComplex*) m_cz[myproc].dataPtr();
491 m_fft_fwd_z.template init_r2r<Direction::forward>(box, p, bc[2]);
492#if defined(AMREX_USE_GPU)
493 if ((bc[2].first == Boundary::even && bc[2].second == Boundary::odd) ||
494 (bc[2].first == Boundary::odd && bc[2].second == Boundary::even)) {
496 } else
497#endif
498 {
499 m_fft_bwd_z.template init_r2r<Direction::backward>(box, p, bc[2]);
500 }
501 }
502 } else {
503 if (myproc < m_rz.size()) {
504 Box const& box = m_rz.box(myproc);
505 auto* p = m_rz[myproc].dataPtr();
506 m_fft_fwd_z.template init_r2r<Direction::forward>(box, p, bc[2]);
507#if defined(AMREX_USE_GPU)
508 if ((bc[2].first == Boundary::even && bc[2].second == Boundary::odd) ||
509 (bc[2].first == Boundary::odd && bc[2].second == Boundary::even)) {
511 } else
512#endif
513 {
514 m_fft_bwd_z.template init_r2r<Direction::backward>(box, p, bc[2]);
515 }
516 }
517 }
518#endif
519}
520
521template <typename T>
523{
524 if (m_fft_bwd_x.plan != m_fft_fwd_x.plan) {
525 m_fft_bwd_x.destroy();
526 }
527 if (m_fft_bwd_y.plan != m_fft_fwd_y.plan) {
528 m_fft_bwd_y.destroy();
529 }
530 if (m_fft_bwd_z.plan != m_fft_fwd_z.plan) {
531 m_fft_bwd_z.destroy();
532 }
533 m_fft_fwd_x.destroy();
534 m_fft_fwd_y.destroy();
535 m_fft_fwd_z.destroy();
536}
537
538template <typename T>
540{
541 Long r = 1;
542 int ndims = m_info.twod_mode ? AMREX_SPACEDIM-1 : AMREX_SPACEDIM;
543#if (AMREX_SPACEDIM == 3)
544 if (m_info.twod_mode && m_dom_0.length(2) == 1) { ndims = 1; };
545#endif
546 for (int idim = 0; idim < ndims; ++idim) {
547 r *= m_dom_0.length(idim);
548 if (m_bc[idim].first != Boundary::periodic && (m_dom_0.length(idim) > 1)) {
549 r *= 2;
550 }
551 }
552 return T(1)/T(r);
553}
554
555template <typename T>
556template <typename F>
557void R2X<T>::forwardThenBackward (MF const& inmf, MF& outmf, F const& post_forward)
558{
559 forwardThenBackward_doit_0(inmf, outmf, post_forward);
560}
561
562template <typename T>
563template <typename F>
564void R2X<T>::forwardThenBackward_doit_0 (MF const& inmf, MF& outmf,
565 F const& post_forward,
566 IntVect const& ngout,
567 Periodicity const& period)
568{
569 BL_PROFILE("FFT::R2X::forwardbackward_0");
570
571 if (m_r2x_sub) {
572 bool inmf_safe = m_sub_helper.ghost_safe(inmf.nGrowVect());
573 MF inmf_sub, inmf_tmp;
574 if (inmf_safe) {
575 inmf_sub = m_sub_helper.make_alias_mf(inmf);
576 } else {
577 inmf_tmp.define(inmf.boxArray(), inmf.DistributionMap(), 1, 0);
578 inmf_tmp.LocalCopy(inmf, 0, 0, 1, IntVect(0));
579 inmf_sub = m_sub_helper.make_alias_mf(inmf_tmp);
580 }
581
582 bool outmf_safe = m_sub_helper.ghost_safe(outmf.nGrowVect());
583 MF outmf_sub, outmf_tmp;
584 if (outmf_safe) {
585 outmf_sub = m_sub_helper.make_alias_mf(outmf);
586 } else {
587 IntVect const& ngtmp = m_sub_helper.make_safe_ghost(outmf.nGrowVect());
588 outmf_tmp.define(outmf.boxArray(), outmf.DistributionMap(), 1, ngtmp);
589 outmf_sub = m_sub_helper.make_alias_mf(outmf_tmp);
590 }
591
592 IntVect const& subngout = m_sub_helper.make_iv(ngout);
593 Periodicity const& subperiod = m_sub_helper.make_periodicity(period);
594 GpuArray<int,3> const& order = m_sub_helper.xyz_order();
595 m_r2x_sub->forwardThenBackward_doit_1
596 (inmf_sub, outmf_sub,
597 [=] AMREX_GPU_DEVICE (int i, int j, int k, auto& sp)
598 {
599 GpuArray<int,3> idx{i,j,k};
600 post_forward(idx[order[0]], idx[order[1]], idx[order[2]], sp);
601 },
602 subngout, subperiod);
603
604 if (!outmf_safe) {
605 outmf.LocalCopy(outmf_tmp, 0, 0, 1, outmf_tmp.nGrowVect());
606 }
607 }
608 else
609 {
610 this->forwardThenBackward_doit_1(inmf, outmf, post_forward, ngout, period);
611 }
612}
613
614template <typename T>
615template <typename F>
616void R2X<T>::forwardThenBackward_doit_1 (MF const& inmf, MF& outmf,
617 F const& post_forward,
618 IntVect const& ngout,
619 Periodicity const& period)
620{
621 BL_PROFILE("FFT::R2X::forwardbackward_1");
622
623 if (m_r2x_sub) {
624 amrex::Abort("R2X::forwardThenBackward_doit_1: How did this happen?");
625 }
626 else
627 {
628 this->forward(inmf);
629
630 // post-forward
631
632 int actual_dim = AMREX_SPACEDIM;
633#if (AMREX_SPACEDIM >= 2)
634 if (m_dom_0.length(1) == 1) { actual_dim = 1; }
635#endif
636#if (AMREX_SPACEDIM == 3)
637 if ((m_dom_0.length(2) == 1) && (m_dom_0.length(1) > 1)) { actual_dim = 2; }
638#endif
639
640 if (actual_dim == 1) {
641 if (m_cx.empty()) {
642 post_forward_doit<0>(detail::get_fab(m_rx), post_forward);
643 } else {
644 post_forward_doit<0>(detail::get_fab(m_cx), post_forward);
645 }
646 }
647#if (AMREX_SPACEDIM >= 2)
648 else if (actual_dim == 2) {
649 if (m_cy.empty()) {
650 post_forward_doit<1>(detail::get_fab(m_ry), post_forward);
651 } else {
652 post_forward_doit<1>(detail::get_fab(m_cy), post_forward);
653 }
654 }
655#endif
656#if (AMREX_SPACEDIM == 3)
657 else if (actual_dim == 3) {
658 if (m_cz.empty()) {
659 post_forward_doit<2>(detail::get_fab(m_rz), post_forward);
660 } else {
661 post_forward_doit<2>(detail::get_fab(m_cz), post_forward);
662 }
663 }
664#endif
665
666 this->backward();
667
668 outmf.ParallelCopy(m_rx, 0, 0, 1, IntVect(0),
669 amrex::elemwiseMin(ngout,outmf.nGrowVect()), period);
670 }
671}
672
673template <typename T>
674void R2X<T>::forward (MF const& inmf)
675{
676 BL_PROFILE("FFT::R2X::forward");
677
678 if (m_r2x_sub) {
679 if (m_sub_helper.ghost_safe(inmf.nGrowVect())) {
680 m_r2x_sub->forward(m_sub_helper.make_alias_mf(inmf));
681 } else {
682 MF tmp(inmf.boxArray(), inmf.DistributionMap(), 1, 0);
683 tmp.LocalCopy(inmf, 0, 0, 1, IntVect(0));
684 m_r2x_sub->forward(m_sub_helper.make_alias_mf(tmp));
685 }
686 return;
687 }
688
689 m_rx.ParallelCopy(inmf, 0, 0, 1);
690 if (m_bc[0].first == Boundary::periodic) {
691 m_fft_fwd_x.template compute_r2c<Direction::forward>();
692 } else {
693 m_fft_fwd_x.template compute_r2r<Direction::forward>();
694 }
695
696#if (AMREX_SPACEDIM >= 2)
697 if ( m_cmd_cx2cy) {
698 ParallelCopy(m_cy, m_cx, *m_cmd_cx2cy, 0, 0, 1, m_dtos_x2y);
699 } else if ( m_cmd_rx2ry) {
700 ParallelCopy(m_ry, m_rx, *m_cmd_rx2ry, 0, 0, 1, m_dtos_x2y);
701 }
702 if (m_bc[1].first != Boundary::periodic)
703 {
704 m_fft_fwd_y.template compute_r2r<Direction::forward>();
705 }
706 else if (m_bc[0].first == Boundary::periodic)
707 {
708 m_fft_fwd_y.template compute_c2c<Direction::forward>();
709 }
710 else
711 {
712 m_fft_fwd_y.template compute_r2c<Direction::forward>();
713 }
714#endif
715
716#if (AMREX_SPACEDIM == 3)
717 if ( m_cmd_cy2cz) {
718 ParallelCopy(m_cz, m_cy, *m_cmd_cy2cz, 0, 0, 1, m_dtos_y2z);
719 } else if ( m_cmd_ry2rz) {
720 ParallelCopy(m_rz, m_ry, *m_cmd_ry2rz, 0, 0, 1, m_dtos_y2z);
721 }
722 if (m_bc[2].first != Boundary::periodic)
723 {
724 m_fft_fwd_z.template compute_r2r<Direction::forward>();
725 }
726 else if (m_bc[0].first == Boundary::periodic ||
727 m_bc[1].first == Boundary::periodic)
728 {
729 m_fft_fwd_z.template compute_c2c<Direction::forward>();
730 }
731 else
732 {
733 m_fft_fwd_z.template compute_r2c<Direction::forward>();
734 }
735#endif
736}
737
738template <typename T>
739void R2X<T>::forward (MF const& inmf, MF& outmf)
740{
741 if (m_r2x_sub)
742 {
743 bool inmf_safe = m_sub_helper.ghost_safe(inmf.nGrowVect());
744 MF inmf_sub, inmf_tmp;
745 if (inmf_safe) {
746 inmf_sub = m_sub_helper.make_alias_mf(inmf);
747 } else {
748 inmf_tmp.define(inmf.boxArray(), inmf.DistributionMap(), 1, 0);
749 inmf_tmp.LocalCopy(inmf, 0, 0, 1, IntVect(0));
750 inmf_sub = m_sub_helper.make_alias_mf(inmf_tmp);
751 }
752
753 bool outmf_safe = m_sub_helper.ghost_safe(outmf.nGrowVect());
754 MF outmf_sub, outmf_tmp;
755 if (outmf_safe) {
756 outmf_sub = m_sub_helper.make_alias_mf(outmf);
757 } else {
758 outmf_tmp.define(outmf.boxArray(), outmf.DistributionMap(), 1, 0);
759 outmf_sub = m_sub_helper.make_alias_mf(outmf_tmp);
760 }
761
762 m_r2x_sub->forward(inmf_sub, outmf_sub);
763
764 if (!outmf_safe) {
765 outmf.LocalCopy(outmf_tmp, 0, 0, 1, IntVect(0));
766 }
767 }
768 else
769 {
770 this->forward(inmf);
771
772#if (AMREX_SPACEDIM == 3)
773 if (m_info.twod_mode) {
774 if (m_cy.empty() && !m_ry.empty()) {
775 ParallelCopy(outmf, m_dom_rx, m_ry, 0, 0, 1, IntVect(0), Swap01{});
776 } else if (m_ry.empty() && m_cy.empty() && m_cx.empty()) {
777 outmf.ParallelCopy(m_rx, 0, 0, 1);
778 } else {
779 amrex::Abort("R2X::forward(MF,MF): How did this happen?");
780 }
781 } else
782#endif
783 {
785 amrex::Abort("R2X::forward(MF,MF): TODO");
786 }
787 }
788}
789
790template <typename T>
791void R2X<T>::forward (MF const& inmf, cMF& outmf)
792{
793 if (m_r2x_sub)
794 {
795 bool inmf_safe = m_sub_helper.ghost_safe(inmf.nGrowVect());
796 MF inmf_sub, inmf_tmp;
797 if (inmf_safe) {
798 inmf_sub = m_sub_helper.make_alias_mf(inmf);
799 } else {
800 inmf_tmp.define(inmf.boxArray(), inmf.DistributionMap(), 1, 0);
801 inmf_tmp.LocalCopy(inmf, 0, 0, 1, IntVect(0));
802 inmf_sub = m_sub_helper.make_alias_mf(inmf_tmp);
803 }
804
805 bool outmf_safe = m_sub_helper.ghost_safe(outmf.nGrowVect());
806 cMF outmf_sub, outmf_tmp;
807 if (outmf_safe) {
808 outmf_sub = m_sub_helper.make_alias_mf(outmf);
809 } else {
810 outmf_tmp.define(outmf.boxArray(), outmf.DistributionMap(), 1, 0);
811 outmf_sub = m_sub_helper.make_alias_mf(outmf_tmp);
812 }
813
814 m_r2x_sub->forward(inmf_sub, outmf_sub);
815
816 if (!outmf_safe) {
817 outmf.LocalCopy(outmf_tmp, 0, 0, 1, IntVect(0));
818 }
819 }
820 else
821 {
822 this->forward(inmf);
823
824#if (AMREX_SPACEDIM == 3)
825 if (m_info.twod_mode) {
826 if (!m_cy.empty()) {
827 auto lo = m_dom_cy.smallEnd();
828 auto hi = m_dom_cy.bigEnd();
829 std::swap(lo[0],lo[1]);
830 std::swap(hi[0],hi[1]);
831 Box dom(lo,hi);
832 ParallelCopy(outmf, dom, m_cy, 0, 0, 1, IntVect(0), Swap01{});
833 } else if (m_ry.empty() && m_cy.empty() && !m_cx.empty()) {
834 outmf.ParallelCopy(m_cx, 0, 0, 1);
835 } else {
836 amrex::Abort("R2X::forward(MF,cMF): How did this happen?");
837 }
838 } else
839#endif
840 {
842 amrex::Abort("R2X::forward(MF,cMF): TODO");
843 }
844 }
845}
846
847template <typename T>
849{
850 BL_PROFILE("FFT::R2X::backward");
851
852 AMREX_ALWAYS_ASSERT(m_r2x_sub == nullptr);
853
854#if (AMREX_SPACEDIM == 3)
855 if (m_bc[2].first != Boundary::periodic)
856 {
857 m_fft_bwd_z.template compute_r2r<Direction::backward>();
858 }
859 else if (m_bc[0].first == Boundary::periodic ||
860 m_bc[1].first == Boundary::periodic)
861 {
862 m_fft_bwd_z.template compute_c2c<Direction::backward>();
863 }
864 else
865 {
866 m_fft_bwd_z.template compute_r2c<Direction::backward>();
867 }
868 if ( m_cmd_cz2cy) {
869 ParallelCopy(m_cy, m_cz, *m_cmd_cz2cy, 0, 0, 1, m_dtos_z2y);
870 } else if ( m_cmd_rz2ry) {
871 ParallelCopy(m_ry, m_rz, *m_cmd_rz2ry, 0, 0, 1, m_dtos_z2y);
872 }
873#endif
874
875#if (AMREX_SPACEDIM >= 2)
876 if (m_bc[1].first != Boundary::periodic)
877 {
878 m_fft_bwd_y.template compute_r2r<Direction::backward>();
879 }
880 else if (m_bc[0].first == Boundary::periodic)
881 {
882 m_fft_bwd_y.template compute_c2c<Direction::backward>();
883 }
884 else
885 {
886 m_fft_bwd_y.template compute_r2c<Direction::backward>();
887 }
888 if ( m_cmd_cy2cx) {
889 ParallelCopy(m_cx, m_cy, *m_cmd_cy2cx, 0, 0, 1, m_dtos_y2x);
890 } else if ( m_cmd_ry2rx) {
891 ParallelCopy(m_rx, m_ry, *m_cmd_ry2rx, 0, 0, 1, m_dtos_y2x);
892 }
893#endif
894
895 if (m_bc[0].first == Boundary::periodic) {
896 m_fft_bwd_x.template compute_r2c<Direction::backward>();
897 } else {
898 m_fft_bwd_x.template compute_r2r<Direction::backward>();
899 }
900}
901
902template <typename T>
903void R2X<T>::backward (MF const& inmf, MF& outmf, IntVect const& ngout,
904 Periodicity const& period)
905{
906 if (m_r2x_sub)
907 {
908 bool inmf_safe = m_sub_helper.ghost_safe(inmf.nGrowVect());
909 MF inmf_sub, inmf_tmp;
910 if (inmf_safe) {
911 inmf_sub = m_sub_helper.make_alias_mf(inmf);
912 } else {
913 inmf_tmp.define(inmf.boxArray(), inmf.DistributionMap(), 1, 0);
914 inmf_tmp.LocalCopy(inmf, 0, 0, 1, IntVect(0));
915 inmf_sub = m_sub_helper.make_alias_mf(inmf_tmp);
916 }
917
918 bool outmf_safe = m_sub_helper.ghost_safe(outmf.nGrowVect());
919 MF outmf_sub, outmf_tmp;
920 if (outmf_safe) {
921 outmf_sub = m_sub_helper.make_alias_mf(outmf);
922 } else {
923 IntVect const& ngtmp = m_sub_helper.make_safe_ghost(outmf.nGrowVect());
924 outmf_tmp.define(outmf.boxArray(), outmf.DistributionMap(), 1, ngtmp);
925 outmf_sub = m_sub_helper.make_alias_mf(outmf_tmp);
926 }
927
928 IntVect const& subngout = m_sub_helper.make_iv(ngout);
929 Periodicity const& subperiod = m_sub_helper.make_periodicity(period);
930 m_r2x_sub->backward(inmf_sub, outmf_sub, subngout, subperiod);
931
932 if (!outmf_safe) {
933 outmf.LocalCopy(outmf_tmp, 0, 0, 1, outmf_tmp.nGrowVect());
934 }
935 }
936 else
937 {
938#if (AMREX_SPACEDIM == 3)
939 if (m_info.twod_mode) {
940 if (m_cy.empty() && !m_ry.empty()) {
941 ParallelCopy(m_ry, m_dom_ry, inmf, 0, 0, 1, IntVect(0), Swap01{});
942 } else if (m_ry.empty() && m_cy.empty() && m_cx.empty()) {
943 m_rx.ParallelCopy(inmf, 0, 0, 1);
944 } else {
945 amrex::Abort("R2X::backward(MF,MF): How did this happen?");
946 }
947 } else
948#endif
949 {
950 amrex::ignore_unused(inmf,outmf,ngout,period);
951 amrex::Abort("R2X::backward(MF,MF): TODO");
952 }
953
954 this->backward();
955
956 outmf.ParallelCopy(m_rx, 0, 0, 1, IntVect(0),
957 amrex::elemwiseMin(ngout,outmf.nGrowVect()), period);
958 }
959}
960
961template <typename T>
962void R2X<T>::backward (cMF const& inmf, MF& outmf, IntVect const& ngout,
963 Periodicity const& period)
964{
965 if (m_r2x_sub)
966 {
967 bool inmf_safe = m_sub_helper.ghost_safe(inmf.nGrowVect());
968 cMF inmf_sub, inmf_tmp;
969 if (inmf_safe) {
970 inmf_sub = m_sub_helper.make_alias_mf(inmf);
971 } else {
972 inmf_tmp.define(inmf.boxArray(), inmf.DistributionMap(), 1, 0);
973 inmf_tmp.LocalCopy(inmf, 0, 0, 1, IntVect(0));
974 inmf_sub = m_sub_helper.make_alias_mf(inmf_tmp);
975 }
976
977 bool outmf_safe = m_sub_helper.ghost_safe(outmf.nGrowVect());
978 MF outmf_sub, outmf_tmp;
979 if (outmf_safe) {
980 outmf_sub = m_sub_helper.make_alias_mf(outmf);
981 } else {
982 IntVect const& ngtmp = m_sub_helper.make_safe_ghost(outmf.nGrowVect());
983 outmf_tmp.define(outmf.boxArray(), outmf.DistributionMap(), 1, ngtmp);
984 outmf_sub = m_sub_helper.make_alias_mf(outmf_tmp);
985 }
986
987 IntVect const& subngout = m_sub_helper.make_iv(ngout);
988 Periodicity const& subperiod = m_sub_helper.make_periodicity(period);
989 m_r2x_sub->backward(inmf_sub, outmf_sub, subngout, subperiod);
990
991 if (!outmf_safe) {
992 outmf.LocalCopy(outmf_tmp, 0, 0, 1, outmf_tmp.nGrowVect());
993 }
994 }
995 else
996 {
997#if (AMREX_SPACEDIM == 3)
998 if (m_info.twod_mode) {
999 if (!m_cy.empty()) {
1000 ParallelCopy(m_cy, m_dom_cy, inmf, 0, 0, 1, IntVect(0), Swap01{});
1001 } else if (m_ry.empty() && m_cy.empty() && !m_cx.empty()) {
1002 m_cx.ParallelCopy(inmf, 0, 0, 1);
1003 } else {
1004 amrex::Abort("R2X::backward(cMF,MF): How did this happen?");
1005 }
1006 } else
1007#endif
1008 {
1009 amrex::ignore_unused(inmf,outmf,ngout,period);
1010 amrex::Abort("R2X::backward(cMF,MF): TODO");
1011 }
1012
1013 this->backward();
1014
1015 outmf.ParallelCopy(m_rx, 0, 0, 1, IntVect(0),
1016 amrex::elemwiseMin(ngout,outmf.nGrowVect()), period);
1017 }
1018}
1019
1020template <typename T>
1021template <int dim, typename FAB, typename F>
1022void R2X<T>::post_forward_doit (FAB* fab, F const& f)
1023{
1024 if (m_info.twod_mode) {
1025 amrex::Abort("xxxxx post_forward_doit: todo");
1026 }
1027 if (fab) {
1028 auto const& a = fab->array();
1029 ParallelFor(fab->box(),
1030 [f=f,a=a] AMREX_GPU_DEVICE (int i, int j, int k)
1031 {
1032 if constexpr (dim == 0) {
1033 f(i,j,k,a(i,j,k));
1034 } else if constexpr (dim == 1) {
1035 f(j,i,k,a(i,j,k));
1036 } else {
1037 f(j,k,i,a(i,j,k));
1038 }
1039 });
1040 }
1041}
1042
1043}
1044
1045#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
A collection of Boxes stored in an Array.
Definition AMReX_BoxArray.H:550
A class for managing a List of Boxes that share a common IndexType. This class implements operations ...
Definition AMReX_BoxList.H:52
AMREX_GPU_HOST_DEVICE IntVectND< dim > size() const noexcept
Return the length of the BoxND.
Definition AMReX_Box.H:139
AMREX_GPU_HOST_DEVICE IntVectND< dim > length() const noexcept
Return the length of the BoxND.
Definition AMReX_Box.H:146
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
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:106
Poisson solver for periodic, Dirichlet & Neumann boundaries using FFT.
Definition AMReX_FFT_Poisson.H:22
Discrete Fourier Transform.
Definition AMReX_FFT_R2X.H:25
MF m_rz
Definition AMReX_FFT_R2X.H:102
Array< std::pair< Boundary, Boundary >, AMREX_SPACEDIM > m_bc
Definition AMReX_FFT_R2X.H:76
void post_forward_doit(FAB *fab, F const &f)
Definition AMReX_FFT_R2X.H:1022
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:962
void backward(MF const &inmf, MF &outmf, IntVect const &ngout, Periodicity const &period)
Definition AMReX_FFT_R2X.H:903
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:674
Swap02 m_dtos_y2z
Definition AMReX_FFT_R2X.H:97
~R2X()
Definition AMReX_FFT_R2X.H:522
void forward(MF const &inmf, MF &outmf)
Definition AMReX_FFT_R2X.H:739
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:557
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:791
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
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:539
Box m_dom_ry
Definition AMReX_FFT_R2X.H:111
void backward()
Definition AMReX_FFT_R2X.H:848
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
R2X(Box const &domain, Array< std::pair< Boundary, Boundary >, AMREX_SPACEDIM > const &bc, Info const &info=Info{})
Definition AMReX_FFT_R2X.H:124
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:616
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:564
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:79
int size() const noexcept
Return the number of FABs in the FabArray.
Definition AMReX_FabArrayBase.H:109
const DistributionMapping & DistributionMap() const noexcept
Return constant reference to associated DistributionMapping.
Definition AMReX_FabArrayBase.H:130
bool empty() const noexcept
Definition AMReX_FabArrayBase.H:88
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:100
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:94
An Array of FortranArrayBox(FAB)-like Objects.
Definition AMReX_FabArray.H:344
void ParallelCopy(const FabArray< FAB > &src, const Periodicity &period=Periodicity::NonPeriodic(), CpOp op=FabArrayBase::COPY)
Definition AMReX_FabArray.H:840
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:1942
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:1733
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:1383
FA::FABType::value_type * get_fab(FA &fa)
Definition AMReX_FFT_Helper.H:1372
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
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 constexpr T elemwiseMin(T const &a, T const &b) noexcept
Definition AMReX_Algorithm.H:49
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
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
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:1873
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
int batch_size
Batched FFT size. Only support in R2C, not R2X.
Definition AMReX_FFT_Helper.H:72
int nprocs
Max number of processes to use.
Definition AMReX_FFT_Helper.H:75
Definition AMReX_FFT_Helper.H:126
std::conditional_t< std::is_same_v< float, T >, cuComplex, cuDoubleComplex > VendorComplex
Definition AMReX_FFT_Helper.H:130
Definition AMReX_FFT_Helper.H:1424
Definition AMReX_FFT_Helper.H:1447
Definition AMReX_FFT_Helper.H:1522
T make_array(T const &a) const
Definition AMReX_FFT_Helper.H:1542
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