Block-Structured AMR Software Framework
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 
11 namespace amrex::FFT
12 {
13 
20 template <typename T = Real>
21 class R2X
22 {
23 public:
24  using MF = std::conditional_t<std::is_same_v<T,Real>,
27 
28  R2X (Box const& domain,
29  Array<std::pair<Boundary,Boundary>,AMREX_SPACEDIM> const& bc,
30  Info const& info = Info{});
31 
32  ~R2X ();
33 
34  R2X (R2X const&) = delete;
35  R2X (R2X &&) = delete;
36  R2X& operator= (R2X const&) = delete;
37  R2X& operator= (R2X &&) = delete;
38 
39  [[nodiscard]] T scalingFactor () const;
40 
41  template <typename F>
42  void forwardThenBackward (MF const& inmf, MF& outmf, F const& post_forward);
43 
44  // public for cuda
45  template <int dim, typename FAB, typename F>
46  void post_forward_doit (FAB* fab, F const& f);
47 
48 private:
51 
58 
59  std::unique_ptr<MultiBlockCommMetaData> m_cmd_cx2cy;
60  std::unique_ptr<MultiBlockCommMetaData> m_cmd_rx2ry;
61  std::unique_ptr<MultiBlockCommMetaData> m_cmd_cy2cz;
62  std::unique_ptr<MultiBlockCommMetaData> m_cmd_ry2rz;
63 
64  std::unique_ptr<MultiBlockCommMetaData> m_cmd_cy2cx;
65  std::unique_ptr<MultiBlockCommMetaData> m_cmd_ry2rx;
66  std::unique_ptr<MultiBlockCommMetaData> m_cmd_cz2cy;
67  std::unique_ptr<MultiBlockCommMetaData> m_cmd_rz2ry;
68 
73 
80 
81  std::unique_ptr<char,DataDeleter> m_data_1;
82  std::unique_ptr<char,DataDeleter> m_data_2;
83 
90 
92 };
93 
94 template <typename T>
95 R2X<T>::R2X (Box const& domain,
96  Array<std::pair<Boundary,Boundary>,AMREX_SPACEDIM> const& bc,
97  Info const& info)
98  : m_dom_0(domain),
99  m_bc(bc),
100  m_info(info)
101 {
102  BL_PROFILE("FFT::R2X");
103 
104  static_assert(std::is_same_v<float,T> || std::is_same_v<double,T>);
105  AMREX_ALWAYS_ASSERT(domain.smallEnd() == 0 &&
106  domain.length(0) > 1 &&
107  domain.cellCentered());
108 #if (AMREX_SPACEDIM == 3)
109  AMREX_ALWAYS_ASSERT(domain.length(1) > 1 || domain.length(2) == 1);
110 #endif
111  for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
112  AMREX_ALWAYS_ASSERT(domain.length(idim) > 1);
113  if (bc[idim].first == Boundary::periodic ||
114  bc[idim].second == Boundary::periodic) {
115  AMREX_ALWAYS_ASSERT(bc[idim].first == bc[idim].second);
116  }
117  }
118 
119  int myproc = ParallelContext::MyProcSub();
121 
122  //
123  // make data containers
124  //
125 
126  m_dom_rx = m_dom_0;
127  auto bax = amrex::decompose(m_dom_rx, nprocs, {AMREX_D_DECL(false,true,true)});
129  m_rx.define(bax, dmx, 1, 0, MFInfo().SetAlloc(false));
130 
131  // x-direction
132  if (bc[0].first == Boundary::periodic) {
133  // x-fft: r2c(m_rx->m_cx)
134  m_dom_cx = Box(IntVect(0), IntVect(AMREX_D_DECL(domain.length(0)/2,
135  domain.bigEnd(1),
136  domain.bigEnd(2))));
137  BoxList bl = bax.boxList();
138  for (auto & b : bl) {
139  b.setBig(0, m_dom_cx.bigEnd(0));
140  }
141  BoxArray cbax(std::move(bl));
142  m_cx.define(cbax, dmx, 1, 0, MFInfo().SetAlloc(false));
143  } // else: x-fft: r2r(m_rx)
144 
145 #if (AMREX_SPACEDIM >= 2)
146  if (domain.length(1) > 1) {
147  if (! m_cx.empty()) {
148  // copy(m_cx->m_cy)
150  m_dom_cx.bigEnd(0),
151  m_dom_cx.bigEnd(2))));
152  auto ba = amrex::decompose(m_dom_cy, nprocs, {AMREX_D_DECL(false,true,true)});
154  if (ba.size() == m_cx.size()) {
155  dm = m_cx.DistributionMap();
156  } else {
157  dm = detail::make_iota_distromap(ba.size());
158  }
159  m_cy.define(ba, dm, 1, 0, MFInfo().SetAlloc(false));
160  // if bc[1] is periodic:
161  // c2c(m_cy->m_cy)
162  // else:
163  // r2r(m_cy.re) & r2r(m_cy.im)
164  } else {
165  // copy(m_rx->m_ry)
167  m_dom_rx.bigEnd(0),
168  m_dom_rx.bigEnd(2))));
169  auto ba = amrex::decompose(m_dom_ry, nprocs, {AMREX_D_DECL(false,true,true)});
171  if (ba.size() == m_rx.size()) {
172  dm = m_rx.DistributionMap();
173  } else {
174  dm = detail::make_iota_distromap(ba.size());
175  }
176  m_ry.define(ba, dm, 1, 0, MFInfo().SetAlloc(false));
177  // if bc[1] is periodic:
178  // r2c(m_ry->m_cy)
179  // else:
180  // r2r(m_ry)
181  if (bc[1].first == Boundary::periodic) {
183  m_dom_ry.bigEnd(1),
184  m_dom_ry.bigEnd(2))));
185  BoxList bl = ba.boxList();
186  for (auto & b : bl) {
187  b.setBig(0, m_dom_cy.bigEnd(0));
188  }
189  BoxArray cba(std::move(bl));
190  m_cy.define(cba, dm, 1, 0, MFInfo().SetAlloc(false));
191  }
192  }
193  }
194 #endif
195 
196 #if (AMREX_SPACEDIM == 3)
197  if (domain.length(2) > 1) {
198  if (! m_cy.empty()) {
199  // copy(m_cy, m_cz)
201  m_dom_cy.bigEnd(1),
202  m_dom_cy.bigEnd(0))));
203  auto ba = amrex::decompose(m_dom_cz, nprocs, {AMREX_D_DECL(false,true,true)});
205  if (ba.size() == m_cy.size()) {
206  dm = m_cy.DistributionMap();
207  } else {
208  dm = detail::make_iota_distromap(ba.size());
209  }
210  m_cz.define(ba, dm, 1, 0, MFInfo().SetAlloc(false));
211  // if bc[2] is periodic:
212  // c2c(m_cz->m_cz)
213  // else:
214  // r2r(m_cz.re) & r2r(m_cz.im)
215  } else {
216  // copy(m_ry, m_rz)
218  m_dom_ry.bigEnd(1),
219  m_dom_ry.bigEnd(0))));
220  auto ba = amrex::decompose(m_dom_rz, nprocs, {AMREX_D_DECL(false,true,true)});
222  if (ba.size() == m_ry.size()) {
223  dm = m_ry.DistributionMap();
224  } else {
225  dm = detail::make_iota_distromap(ba.size());
226  }
227  m_rz.define(ba, dm, 1, 0, MFInfo().SetAlloc(false));
228  // if bc[2] is periodic:
229  // r2c(m_rz->m_cz)
230  // else:
231  // r2r(m_rz)
232  if (bc[2].first == Boundary::periodic) {
234  m_dom_rz.bigEnd(1),
235  m_dom_rz.bigEnd(2))));
236  BoxList bl = ba.boxList();
237  for (auto & b : bl) {
238  b.setBig(0, m_dom_cz.bigEnd(0));
239  }
240  BoxArray cba(std::move(bl));
241  m_cz.define(cba, dm, 1, 0, MFInfo().SetAlloc(false));
242  }
243  }
244  }
245 #endif
246 
247  // There are several different execution paths.
248  //
249  // (1) x-r2c(m_rx->m_cx), copy(m_cx->m_cy), y-fft(m_cy),
250  // copy(m_cy->m_cz), z-fft(m_cz)
251  // In this case, we have m_rx, m_cx, m_cy, & m_cz.
252  // we can alias(m_rx,m_cy) and alias(m_cx,m_cz).
253  //
254  // (2) x_r2r(m_rx), copy(m_rx->m_ry), y-r2c(m_ry->m_cy),
255  // copy(m_cy->m_cz), z-fft(m_cz)
256  // In this case, we have m_rx, m_ry, m_cy, & m_cz.
257  // We can alias(m_rx,m_cy) and alias(m_ry,m_cz).
258  //
259  // (3) x_r2r(m_rx), copy(m_rx->m_ry), y-r2r(m_ry),
260  // copy(m_ry->m_rz), z-r2c(m_rz->m_rz)
261  // In this case, we have m_rx, m_ry, m_rz, & m_cz
262  // We can alias(m_rx,m_rz) and alias(m_ry,m_cz)
263  //
264  // (4) x_r2r(m_rx), copy(m_rx->m_ry), y-r2r(m_ry),
265  // copy(m_ry->m_rz), z-r2r(m_rz)
266  // In this case, we have m_rx, m_ry, & m_rz.
267  // We can alias(m_rx,m_rz).
268 
269  if (! m_cx.empty()) {
272  } else if (! m_cy.empty()) {
275  } else if (! m_cz.empty()) {
278  } else {
280  m_data_2 = detail::make_mfs_share(m_ry, m_cz); // It's okay m_cz is empty.
281  }
282 
283  //
284  // make copiers
285  //
286 
287 #if (AMREX_SPACEDIM >= 2)
288  if (domain.length(1) > 1) {
289  if (! m_cx.empty()) {
290  // copy(m_cx->m_cy)
291  m_cmd_cx2cy = std::make_unique<MultiBlockCommMetaData>
293  m_cmd_cy2cx = std::make_unique<MultiBlockCommMetaData>
295  } else {
296  // copy(m_rx->m_ry)
297  m_cmd_rx2ry = std::make_unique<MultiBlockCommMetaData>
299  m_cmd_ry2rx = std::make_unique<MultiBlockCommMetaData>
301  }
302  }
303 #endif
304 
305 #if (AMREX_SPACEDIM == 3)
306  if (domain.length(2) > 1) {
307  if (! m_cy.empty()) {
308  // copy(m_cy, m_cz)
309  m_cmd_cy2cz = std::make_unique<MultiBlockCommMetaData>
311  m_cmd_cz2cy = std::make_unique<MultiBlockCommMetaData>
313  } else {
314  // copy(m_ry, m_rz)
315  m_cmd_ry2rz = std::make_unique<MultiBlockCommMetaData>
317  m_cmd_rz2ry = std::make_unique<MultiBlockCommMetaData>
319  }
320  }
321 #endif
322 
323  //
324  // make plans
325  //
326 
327  using VendorComplex = typename Plan<T>::VendorComplex;
328 
329  if (myproc < m_rx.size())
330  {
331  Box const& box = m_rx.box(myproc);
332  auto* pf = m_rx[myproc].dataPtr();
333  if (bc[0].first == Boundary::periodic) {
334  auto* pb = (VendorComplex*) m_cx[myproc].dataPtr();
335  m_fft_fwd_x.template init_r2c<Direction::forward>(box, pf, pb);
336 #if defined(AMREX_USE_SYCL)
338 #else
339  m_fft_bwd_x.template init_r2c<Direction::backward>(box, pf, pb);
340 #endif
341  } else {
342  m_fft_fwd_x.template init_r2r<Direction::forward>(box, pf, bc[0]);
343 #if defined(AMREX_USE_GPU)
344  if ((bc[0].first == Boundary::even && bc[0].second == Boundary::odd) ||
345  (bc[0].first == Boundary::odd && bc[0].second == Boundary::even)) {
347  } else
348 #endif
349  {
350  m_fft_bwd_x.template init_r2r<Direction::backward>(box, pf, bc[0]);
351  }
352  }
353  }
354 
355 #if (AMREX_SPACEDIM >= 2)
356  if (m_ry.empty() && m_bc[1].first == Boundary::periodic) {
357  if (myproc < m_cy.size()) {
358  Box const& box = m_cy.box(myproc);
359  auto* p = (VendorComplex *)m_cy[myproc].dataPtr();
360  m_fft_fwd_y.template init_c2c<Direction::forward>(box, p);
361 #if defined(AMREX_USE_SYCL)
363 #else
364  m_fft_bwd_y.template init_c2c<Direction::backward>(box, p);
365 #endif
366  }
367  } else if (!m_ry.empty() && m_bc[1].first == Boundary::periodic) {
368  if (myproc < m_ry.size()) {
369  Box const& box = m_ry.box(myproc);
370  auto* pr = m_ry[myproc].dataPtr();
371  auto* pc = (VendorComplex*)m_cy[myproc].dataPtr();
372  m_fft_fwd_y.template init_r2c<Direction::forward>(box, pr, pc);
373 #if defined(AMREX_USE_SYCL)
375 #else
376  m_fft_bwd_y.template init_r2c<Direction::backward>(box, pr, pc);
377 #endif
378  }
379  } else if (!m_cy.empty()) {
380  if (myproc < m_cy.size()) {
381  Box const& box = m_cy.box(myproc);
382  auto* p = (VendorComplex*) m_cy[myproc].dataPtr();
383  m_fft_fwd_y.template init_r2r<Direction::forward>(box, p, bc[1]);
384 #if defined(AMREX_USE_GPU)
385  if ((bc[1].first == Boundary::even && bc[1].second == Boundary::odd) ||
386  (bc[1].first == Boundary::odd && bc[1].second == Boundary::even)) {
388  } else
389 #endif
390  {
391  m_fft_bwd_y.template init_r2r<Direction::backward>(box, p, bc[1]);
392  }
393  }
394  } else {
395  if (myproc < m_ry.size()) {
396  Box const& box = m_ry.box(myproc);
397  auto* p = m_ry[myproc].dataPtr();
398  m_fft_fwd_y.template init_r2r<Direction::forward>(box, p, bc[1]);
399 #if defined(AMREX_USE_GPU)
400  if ((bc[1].first == Boundary::even && bc[1].second == Boundary::odd) ||
401  (bc[1].first == Boundary::odd && bc[1].second == Boundary::even)) {
403  } else
404 #endif
405  {
406  m_fft_bwd_y.template init_r2r<Direction::backward>(box, p, bc[1]);
407  }
408  }
409  }
410 #endif
411 
412 #if (AMREX_SPACEDIM == 3)
413  if (m_rz.empty() && m_bc[2].first == Boundary::periodic) {
414  if (myproc < m_cz.size()) {
415  Box const& box = m_cz.box(myproc);
416  auto* p = (VendorComplex*)m_cz[myproc].dataPtr();
417  m_fft_fwd_z.template init_c2c<Direction::forward>(box, p);
418 #if defined(AMREX_USE_SYCL)
420 #else
421  m_fft_bwd_z.template init_c2c<Direction::backward>(box, p);
422 #endif
423  }
424  } else if (!m_rz.empty() && m_bc[2].first == Boundary::periodic) {
425  if (myproc < m_rz.size()) {
426  Box const& box = m_rz.box(myproc);
427  auto* pr = m_rz[myproc].dataPtr();
428  auto* pc = (VendorComplex*)m_cz[myproc].dataPtr();
429  m_fft_fwd_z.template init_r2c<Direction::forward>(box, pr, pc);
430 #if defined(AMREX_USE_SYCL)
432 #else
433  m_fft_bwd_z.template init_r2c<Direction::backward>(box, pr, pc);
434 #endif
435  }
436  } else if (!m_cz.empty()) {
437  if (myproc < m_cz.size()) {
438  Box const& box = m_cz.box(myproc);
439  auto* p = (VendorComplex*) m_cz[myproc].dataPtr();
440  m_fft_fwd_z.template init_r2r<Direction::forward>(box, p, bc[2]);
441 #if defined(AMREX_USE_GPU)
442  if ((bc[2].first == Boundary::even && bc[2].second == Boundary::odd) ||
443  (bc[2].first == Boundary::odd && bc[2].second == Boundary::even)) {
445  } else
446 #endif
447  {
448  m_fft_bwd_z.template init_r2r<Direction::backward>(box, p, bc[2]);
449  }
450  }
451  } else {
452  if (myproc < m_rz.size()) {
453  Box const& box = m_rz.box(myproc);
454  auto* p = m_rz[myproc].dataPtr();
455  m_fft_fwd_z.template init_r2r<Direction::forward>(box, p, bc[2]);
456 #if defined(AMREX_USE_GPU)
457  if ((bc[2].first == Boundary::even && bc[2].second == Boundary::odd) ||
458  (bc[2].first == Boundary::odd && bc[2].second == Boundary::even)) {
460  } else
461 #endif
462  {
463  m_fft_bwd_z.template init_r2r<Direction::backward>(box, p, bc[2]);
464  }
465  }
466  }
467 #endif
468 }
469 
470 template <typename T>
472 {
473  if (m_fft_bwd_x.plan != m_fft_fwd_x.plan) {
474  m_fft_bwd_x.destroy();
475  }
476  if (m_fft_bwd_y.plan != m_fft_fwd_y.plan) {
477  m_fft_bwd_y.destroy();
478  }
479  if (m_fft_bwd_z.plan != m_fft_fwd_z.plan) {
480  m_fft_bwd_z.destroy();
481  }
482  m_fft_fwd_x.destroy();
483  m_fft_fwd_y.destroy();
484  m_fft_fwd_z.destroy();
485 }
486 
487 template <typename T>
489 {
490  auto r = m_dom_0.numPts();
491  for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
492  if (m_bc[idim].first != Boundary::periodic
493  && m_dom_0.length(idim) > 1)
494  {
495  r *= 2;
496  }
497  }
498  return T(1)/T(r);
499 }
500 
501 template <typename T>
502 template <typename F>
503 void R2X<T>::forwardThenBackward (MF const& inmf, MF& outmf, F const& post_forward)
504 {
505  BL_PROFILE("FFT::R2X::forwardbackward");
506 
507  // forward
508 
509  m_rx.ParallelCopy(inmf, 0, 0, 1);
510  if (m_bc[0].first == Boundary::periodic) {
511  m_fft_fwd_x.template compute_r2c<Direction::forward>();
512  } else {
513  m_fft_fwd_x.template compute_r2r<Direction::forward>();
514  }
515 
516 #if (AMREX_SPACEDIM >= 2)
517  if ( m_cmd_cx2cy) {
518  ParallelCopy(m_cy, m_cx, *m_cmd_cx2cy, 0, 0, 1, m_dtos_x2y);
519  } else if ( m_cmd_rx2ry) {
520  ParallelCopy(m_ry, m_rx, *m_cmd_rx2ry, 0, 0, 1, m_dtos_x2y);
521  }
522  if (m_bc[1].first != Boundary::periodic)
523  {
524  m_fft_fwd_y.template compute_r2r<Direction::forward>();
525  }
526  else if (m_bc[0].first == Boundary::periodic)
527  {
528  m_fft_fwd_y.template compute_c2c<Direction::forward>();
529  }
530  else
531  {
532  m_fft_fwd_y.template compute_r2c<Direction::forward>();
533  }
534 #endif
535 
536 #if (AMREX_SPACEDIM == 3)
537  if ( m_cmd_cy2cz) {
538  ParallelCopy(m_cz, m_cy, *m_cmd_cy2cz, 0, 0, 1, m_dtos_y2z);
539  } else if ( m_cmd_ry2rz) {
540  ParallelCopy(m_rz, m_ry, *m_cmd_ry2rz, 0, 0, 1, m_dtos_y2z);
541  }
542  if (m_bc[2].first != Boundary::periodic)
543  {
544  m_fft_fwd_z.template compute_r2r<Direction::forward>();
545  }
546  else if (m_bc[0].first == Boundary::periodic ||
547  m_bc[1].first == Boundary::periodic)
548  {
549  m_fft_fwd_z.template compute_c2c<Direction::forward>();
550  }
551  else
552  {
553  m_fft_fwd_z.template compute_r2c<Direction::forward>();
554  }
555 #endif
556 
557  // post-forward
558 
559  int actual_dim = AMREX_SPACEDIM;
560 #if (AMREX_SPACEDIM >= 2)
561  if (m_dom_0.length(1) == 1) { actual_dim = 1; }
562 #endif
563 #if (AMREX_SPACEDIM == 3)
564  if ((m_dom_0.length(2) == 1) && (m_dom_0.length(1) > 1)) { actual_dim = 2; }
565 #endif
566 
567  if (actual_dim == 1) {
568  if (m_cx.empty()) {
569  post_forward_doit<0>(detail::get_fab(m_rx), post_forward);
570  } else {
571  post_forward_doit<0>(detail::get_fab(m_cx), post_forward);
572  }
573  }
574 #if (AMREX_SPACEDIM >= 2)
575  else if (actual_dim == 2) {
576  if (m_cy.empty()) {
577  post_forward_doit<1>(detail::get_fab(m_ry), post_forward);
578  } else {
579  post_forward_doit<1>(detail::get_fab(m_cy), post_forward);
580  }
581  }
582 #endif
583 #if (AMREX_SPACEDIM == 3)
584  else if (actual_dim == 3) {
585  if (m_cz.empty()) {
586  post_forward_doit<2>(detail::get_fab(m_rz), post_forward);
587  } else {
588  post_forward_doit<2>(detail::get_fab(m_cz), post_forward);
589  }
590  }
591 #endif
592 
593  // backward
594 
595 #if (AMREX_SPACEDIM == 3)
596  if (m_bc[2].first != Boundary::periodic)
597  {
598  m_fft_bwd_z.template compute_r2r<Direction::backward>();
599  }
600  else if (m_bc[0].first == Boundary::periodic ||
601  m_bc[1].first == Boundary::periodic)
602  {
603  m_fft_bwd_z.template compute_c2c<Direction::backward>();
604  }
605  else
606  {
607  m_fft_bwd_z.template compute_r2c<Direction::backward>();
608  }
609  if ( m_cmd_cz2cy) {
610  ParallelCopy(m_cy, m_cz, *m_cmd_cz2cy, 0, 0, 1, m_dtos_z2y);
611  } else if ( m_cmd_rz2ry) {
612  ParallelCopy(m_ry, m_rz, *m_cmd_rz2ry, 0, 0, 1, m_dtos_z2y);
613  }
614 #endif
615 
616 #if (AMREX_SPACEDIM >= 2)
617  if (m_bc[1].first != Boundary::periodic)
618  {
619  m_fft_bwd_y.template compute_r2r<Direction::backward>();
620  }
621  else if (m_bc[0].first == Boundary::periodic)
622  {
623  m_fft_bwd_y.template compute_c2c<Direction::backward>();
624  }
625  else
626  {
627  m_fft_bwd_y.template compute_r2c<Direction::backward>();
628  }
629  if ( m_cmd_cy2cx) {
630  ParallelCopy(m_cx, m_cy, *m_cmd_cy2cx, 0, 0, 1, m_dtos_y2x);
631  } else if ( m_cmd_ry2rx) {
632  ParallelCopy(m_rx, m_ry, *m_cmd_ry2rx, 0, 0, 1, m_dtos_y2x);
633  }
634 #endif
635 
636  if (m_bc[0].first == Boundary::periodic) {
637  m_fft_bwd_x.template compute_r2c<Direction::backward>();
638  } else {
639  m_fft_bwd_x.template compute_r2r<Direction::backward>();
640  }
641  outmf.ParallelCopy(m_rx, 0, 0, 1);
642 }
643 
644 template <typename T>
645 template <int dim, typename FAB, typename F>
646 void R2X<T>::post_forward_doit (FAB* fab, F const& f)
647 {
648  if (fab) {
649  auto const& a = fab->array();
650  ParallelFor(fab->box(),
651  [f=f,a=a] AMREX_GPU_DEVICE (int i, int j, int k)
652  {
653  if constexpr (dim == 0) {
654  f(i,j,k,a(i,j,k));
655  } else if constexpr (dim == 1) {
656  f(j,i,k,a(i,j,k));
657  } else {
658  f(j,k,i,a(i,j,k));
659  }
660  });
661  }
662 }
663 
664 }
665 
666 #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:104
A collection of Boxes stored in an Array.
Definition: AMReX_BoxArray.H:549
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 const IntVectND< dim > & smallEnd() const &noexcept
Get the smallend of the BoxND.
Definition: AMReX_Box.H:105
AMREX_GPU_HOST_DEVICE const IntVectND< dim > & bigEnd() const &noexcept
Get the bigend.
Definition: AMReX_Box.H:116
AMREX_GPU_HOST_DEVICE IntVectND< dim > length() const noexcept
Return the length of the BoxND.
Definition: AMReX_Box.H:146
AMREX_GPU_HOST_DEVICE bool cellCentered() const noexcept
Returns true if BoxND is cell-centered in all indexing directions.
Definition: AMReX_Box.H:319
Calculates the distribution of FABs to MPI processes.
Definition: AMReX_DistributionMapping.H:41
Discrete Fourier Transform.
Definition: AMReX_FFT_R2X.H:22
MF m_rz
Definition: AMReX_FFT_R2X.H:76
Array< std::pair< Boundary, Boundary >, AMREX_SPACEDIM > m_bc
Definition: AMReX_FFT_R2X.H:50
void post_forward_doit(FAB *fab, F const &f)
Definition: AMReX_FFT_R2X.H:646
Swap01 m_dtos_x2y
Definition: AMReX_FFT_R2X.H:69
std::conditional_t< std::is_same_v< T, Real >, MultiFab, FabArray< BaseFab< T > > > MF
Definition: AMReX_FFT_R2X.H:25
std::unique_ptr< MultiBlockCommMetaData > m_cmd_rz2ry
Definition: AMReX_FFT_R2X.H:67
MF m_ry
Definition: AMReX_FFT_R2X.H:75
Box m_dom_cz
Definition: AMReX_FFT_R2X.H:89
Swap02 m_dtos_y2z
Definition: AMReX_FFT_R2X.H:71
~R2X()
Definition: AMReX_FFT_R2X.H:471
void forwardThenBackward(MF const &inmf, MF &outmf, F const &post_forward)
Definition: AMReX_FFT_R2X.H:503
std::unique_ptr< MultiBlockCommMetaData > m_cmd_ry2rx
Definition: AMReX_FFT_R2X.H:65
Info m_info
Definition: AMReX_FFT_R2X.H:91
std::unique_ptr< MultiBlockCommMetaData > m_cmd_cz2cy
Definition: AMReX_FFT_R2X.H:66
std::unique_ptr< MultiBlockCommMetaData > m_cmd_cy2cz
Definition: AMReX_FFT_R2X.H:61
Plan< T > m_fft_fwd_y
Definition: AMReX_FFT_R2X.H:54
MF m_rx
Definition: AMReX_FFT_R2X.H:74
std::unique_ptr< MultiBlockCommMetaData > m_cmd_ry2rz
Definition: AMReX_FFT_R2X.H:62
Box m_dom_rx
Definition: AMReX_FFT_R2X.H:84
std::unique_ptr< MultiBlockCommMetaData > m_cmd_rx2ry
Definition: AMReX_FFT_R2X.H:60
Swap01 m_dtos_y2x
Definition: AMReX_FFT_R2X.H:70
Box m_dom_cy
Definition: AMReX_FFT_R2X.H:88
R2X(R2X &&)=delete
T scalingFactor() const
Definition: AMReX_FFT_R2X.H:488
Box m_dom_ry
Definition: AMReX_FFT_R2X.H:85
Plan< T > m_fft_bwd_z
Definition: AMReX_FFT_R2X.H:57
R2X(R2X const &)=delete
std::unique_ptr< char, DataDeleter > m_data_1
Definition: AMReX_FFT_R2X.H:81
Plan< T > m_fft_fwd_x
Definition: AMReX_FFT_R2X.H:52
R2X(Box const &domain, Array< std::pair< Boundary, Boundary >, AMREX_SPACEDIM > const &bc, Info const &info=Info{})
Definition: AMReX_FFT_R2X.H:95
std::unique_ptr< MultiBlockCommMetaData > m_cmd_cy2cx
Definition: AMReX_FFT_R2X.H:64
Box m_dom_0
Definition: AMReX_FFT_R2X.H:49
std::unique_ptr< MultiBlockCommMetaData > m_cmd_cx2cy
Definition: AMReX_FFT_R2X.H:59
std::unique_ptr< char, DataDeleter > m_data_2
Definition: AMReX_FFT_R2X.H:82
Plan< T > m_fft_fwd_z
Definition: AMReX_FFT_R2X.H:56
Plan< T > m_fft_bwd_y
Definition: AMReX_FFT_R2X.H:55
cMF m_cx
Definition: AMReX_FFT_R2X.H:77
cMF m_cz
Definition: AMReX_FFT_R2X.H:79
R2X & operator=(R2X const &)=delete
Swap02 m_dtos_z2y
Definition: AMReX_FFT_R2X.H:72
cMF m_cy
Definition: AMReX_FFT_R2X.H:78
Box m_dom_cx
Definition: AMReX_FFT_R2X.H:87
Plan< T > m_fft_bwd_x
Definition: AMReX_FFT_R2X.H:53
Box m_dom_rz
Definition: AMReX_FFT_R2X.H:86
int size() const noexcept
Return the number of FABs in the FabArray.
Definition: AMReX_FabArrayBase.H:109
bool empty() const noexcept
Definition: AMReX_FabArrayBase.H:88
const DistributionMapping & DistributionMap() const noexcept
Return constant reference to associated DistributionMapping.
Definition: AMReX_FabArrayBase.H:130
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
An Array of FortranArrayBox(FAB)-like Objects.
Definition: AMReX_FabArray.H:344
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:2027
A collection (stored as an array) of FArrayBox objects.
Definition: AMReX_MultiFab.H:38
@ FAB
Definition: AMReX_AmrvisConstants.H:86
FA::FABType::value_type * get_fab(FA &fa)
Definition: AMReX_FFT_Helper.H:1303
std::unique_ptr< char, DataDeleter > make_mfs_share(FA1 &fa1, FA2 &fa2)
Definition: AMReX_FFT_Helper.H:1314
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
static int f(amrex::Real t, N_Vector y_data, N_Vector y_rhs, void *user_data)
Definition: AMReX_SundialsIntegrator.H:44
@ min
Definition: AMReX_ParallelReduce.H:18
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:200
BoxND< AMREX_SPACEDIM > Box
Definition: AMReX_BaseFwd.H:27
double second() noexcept
Definition: AMReX_Utility.cpp:922
IntVectND< AMREX_SPACEDIM > IntVect
Definition: AMReX_BaseFwd.H:30
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 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:1672
std::array< T, N > Array
Definition: AMReX_Array.H:24
Definition: AMReX_FFT_Helper.H:56
int nprocs
Max number of processes to use.
Definition: AMReX_FFT_Helper.H:63
Definition: AMReX_FFT_Helper.H:111
std::conditional_t< std::is_same_v< float, T >, cuComplex, cuDoubleComplex > VendorComplex
Definition: AMReX_FFT_Helper.H:115
Definition: AMReX_FFT_Helper.H:1355
Definition: AMReX_FFT_Helper.H:1378
FabArray memory allocation information.
Definition: AMReX_FabArray.H:66