Block-Structured AMR Software Framework
Loading...
Searching...
No Matches
AMReX_MLPoisson.H
Go to the documentation of this file.
1#ifndef AMREX_MLPOISSON_H_
2#define AMREX_MLPOISSON_H_
3#include <AMReX_Config.H>
4
5#include <AMReX_iMultiFab.H>
7#include <AMReX_MLPoisson_K.H>
9#include <AMReX_MultiFab.H>
10
11namespace amrex {
12
19// del dot grad phi
20
29template <typename MF>
31 : public MLCellABecLapT<MF>
32{
33public:
34
35 using FAB = typename MF::fab_type;
36 using RT = typename MF::value_type;
37
40
42 MLPoissonT () = default;
52 MLPoissonT (const Vector<Geometry>& a_geom,
53 const Vector<BoxArray>& a_grids,
54 const Vector<DistributionMapping>& a_dmap,
55 const LPInfo& a_info = LPInfo(),
56 const Vector<FabFactory<FAB> const*>& a_factory = {});
60 MLPoissonT (const Vector<Geometry>& a_geom,
61 const Vector<BoxArray>& a_grids,
62 const Vector<DistributionMapping>& a_dmap,
63 const Vector<iMultiFab const*>& a_overset_mask, // 1: unknown, 0: known
64 const LPInfo& a_info = LPInfo(),
65 const Vector<FabFactory<FAB> const*>& a_factory = {});
66 ~MLPoissonT () override;
67
68 MLPoissonT (const MLPoissonT<MF>&) = delete;
72
82 void define (const Vector<Geometry>& a_geom,
83 const Vector<BoxArray>& a_grids,
84 const Vector<DistributionMapping>& a_dmap,
85 const LPInfo& a_info = LPInfo(),
86 const Vector<FabFactory<FAB> const*>& a_factory = {});
87
98 void define (const Vector<Geometry>& a_geom,
99 const Vector<BoxArray>& a_grids,
100 const Vector<DistributionMapping>& a_dmap,
101 const Vector<iMultiFab const*>& a_overset_mask,
102 const LPInfo& a_info = LPInfo(),
103 const Vector<FabFactory<FAB> const*>& a_factory = {});
104
106 void prepareForSolve () final;
108 [[nodiscard]] bool isSingular (int amrlev) const final { return m_is_singular[amrlev]; }
110 [[nodiscard]] bool isBottomSingular () const final { return m_is_singular[0]; }
112 void Fapply (int amrlev, int mglev, MF& out, const MF& in) const final;
114 void Fsmooth (int amrlev, int mglev, MF& sol, const MF& rhs, int redblack) const final;
119 void FFlux (int amrlev, const MFIter& mfi,
120 const Array<FAB*,AMREX_SPACEDIM>& flux,
121 const FAB& sol, Location loc, int face_only=0) const final;
122
124 void normalize (int amrlev, int mglev, MF& mf) const final;
125
127 [[nodiscard]] RT getAScalar () const final { return RT(0.0); }
129 [[nodiscard]] RT getBScalar () const final { return RT(-1.0); }
131 [[nodiscard]] MF const* getACoeffs (int /*amrlev*/, int /*mglev*/) const final { return nullptr; }
133 [[nodiscard]] Array<MF const*,AMREX_SPACEDIM> getBCoeffs (int /*amrlev*/, int /*mglev*/) const final
134 { return {{ AMREX_D_DECL(nullptr,nullptr,nullptr)}}; }
135
137 [[nodiscard]] std::unique_ptr<MLLinOpT<MF>> makeNLinOp (int grid_size) const final;
138
140 [[nodiscard]] bool supportNSolve () const final;
141
143 void copyNSolveSolution (MF& dst, MF const& src) const final;
144
151 void get_dpdn_on_domain_faces (Array<MF*,AMREX_SPACEDIM> const& dpdn,
152 MF const& phi);
153
154private:
155
156 Vector<int> m_is_singular;
157};
158
159template <typename MF>
161 const Vector<BoxArray>& a_grids,
162 const Vector<DistributionMapping>& a_dmap,
163 const LPInfo& a_info,
164 const Vector<FabFactory<FAB> const*>& a_factory)
165{
166 define(a_geom, a_grids, a_dmap, a_info, a_factory);
167}
168
169template <typename MF>
171 const Vector<BoxArray>& a_grids,
172 const Vector<DistributionMapping>& a_dmap,
173 const Vector<iMultiFab const*>& a_overset_mask,
174 const LPInfo& a_info,
175 const Vector<FabFactory<FAB> const*>& a_factory)
176{
177 define(a_geom, a_grids, a_dmap, a_overset_mask, a_info, a_factory);
178}
179
180template <typename MF>
181void
183 const Vector<BoxArray>& a_grids,
184 const Vector<DistributionMapping>& a_dmap,
185 const LPInfo& a_info,
186 const Vector<FabFactory<FAB> const*>& a_factory)
187{
188 BL_PROFILE("MLPoisson::define()");
189 MLCellABecLapT<MF>::define(a_geom, a_grids, a_dmap, a_info, a_factory);
190}
191
192template <typename MF>
193void
195 const Vector<BoxArray>& a_grids,
196 const Vector<DistributionMapping>& a_dmap,
197 const Vector<iMultiFab const*>& a_overset_mask,
198 const LPInfo& a_info,
199 const Vector<FabFactory<FAB> const*>& a_factory)
200{
201 BL_PROFILE("MLPoisson::define(overset)");
202 MLCellABecLapT<MF>::define(a_geom, a_grids, a_dmap, a_overset_mask, a_info, a_factory);
204 "MLPoisson: overset mask does not support metric terms. Use MLABecLaplacian or LPInfo::setMetricTerm(false).");
205}
206
207template <typename MF>
208MLPoissonT<MF>::~MLPoissonT () = default;
209
210template <typename MF>
211void
213{
214 BL_PROFILE("MLPoisson::prepareForSolve()");
215
217
218 m_is_singular.clear();
219 m_is_singular.resize(this->m_num_amr_levels, false);
220 auto itlo = std::ranges::find(this->m_lobc[0], BCType::Dirichlet);
221 auto ithi = std::ranges::find(this->m_hibc[0], BCType::Dirichlet);
222 if (itlo == this->m_lobc[0].end() && ithi == this->m_hibc[0].end())
223 { // No Dirichlet
224 for (int alev = 0; alev < this->m_num_amr_levels; ++alev)
225 {
226 // For now this assumes that overset regions are treated as Dirichlet bc's
227 if (this->m_domain_covered[alev] && !this->m_overset_mask[alev][0])
228 {
229 m_is_singular[alev] = true;
230 }
231 }
232 }
233 if (!m_is_singular[0] && this->m_needs_coarse_data_for_bc &&
235 {
236 AMREX_ASSERT(this->m_overset_mask[0][0] == nullptr);
237 auto bbox = this->m_grids[0][0].minimalBox();
238 for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
239 if (this->m_lobc[0][idim] == LinOpBCType::Dirichlet) {
240 bbox.growLo(idim,1);
241 }
242 if (this->m_hibc[0][idim] == LinOpBCType::Dirichlet) {
243 bbox.growHi(idim,1);
244 }
245 }
246 if (this->m_geom[0][0].Domain().contains(bbox)) {
247 m_is_singular[0] = true;
248 }
249 }
250}
251
252template <typename MF>
253void
254MLPoissonT<MF>::Fapply (int amrlev, int mglev, MF& out, const MF& in) const
255{
256 BL_PROFILE("MLPoisson::Fapply()");
257
258 const Real* dxinv = this->m_geom[amrlev][mglev].InvCellSize();
259
260 AMREX_D_TERM(const RT dhx = RT(dxinv[0]*dxinv[0]);,
261 const RT dhy = RT(dxinv[1]*dxinv[1]);,
262 const RT dhz = RT(dxinv[2]*dxinv[2]););
263
264#if (AMREX_SPACEDIM == 3)
265 RT dh0 = this->get_d0(dhx, dhy, dhz);
266 RT dh1 = this->get_d1(dhx, dhy, dhz);
267#endif
268
269#if (AMREX_SPACEDIM < 3)
270 const RT dx = RT(this->m_geom[amrlev][mglev].CellSize(0));
271 const RT probxlo = RT(this->m_geom[amrlev][mglev].ProbLo(0));
272#endif
273
274#ifdef AMREX_USE_GPU
275 if (Gpu::inLaunchRegion() && out.isFusingCandidate() && !this->hasHiddenDimension()) {
276 auto const& xma = in.const_arrays();
277 auto const& yma = out.arrays();
278 if (this->m_overset_mask[amrlev][mglev]) {
280 const auto& osmma = this->m_overset_mask[amrlev][mglev]->const_arrays();
281 ParallelFor(out,
282 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k) noexcept
283 {
285 mlpoisson_adotx_os(AMREX_D_DECL(i,j,k), yma[box_no], xma[box_no], osmma[box_no],
286 AMREX_D_DECL(dhx,dhy,dhz));
287 });
288 } else {
289#if (AMREX_SPACEDIM < 3)
290 if (this->m_has_metric_term) {
291 ParallelFor(out,
292 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k) noexcept
293 {
295 mlpoisson_adotx_m(AMREX_D_DECL(i,j,k), yma[box_no], xma[box_no],
296 AMREX_D_DECL(dhx,dhy,dhz), dx, probxlo);
297 });
298 } else
299#endif
300 {
301 ParallelFor(out,
302 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k) noexcept
303 {
305 mlpoisson_adotx(AMREX_D_DECL(i,j,k), yma[box_no], xma[box_no],
306 AMREX_D_DECL(dhx,dhy,dhz));
307 });
308 }
309 }
310 if (!Gpu::inNoSyncRegion()) {
312 }
313 } else
314#endif
315 {
316#ifdef AMREX_USE_OMP
317#pragma omp parallel if (Gpu::notInLaunchRegion())
318#endif
319 for (MFIter mfi(out, TilingIfNotGPU()); mfi.isValid(); ++mfi)
320 {
321 const Box& bx = mfi.tilebox();
322 const auto& xfab = in.array(mfi);
323 const auto& yfab = out.array(mfi);
324
325 if (this->m_overset_mask[amrlev][mglev]) {
327 const auto& osm = this->m_overset_mask[amrlev][mglev]->const_array(mfi);
329 {
331 mlpoisson_adotx_os(AMREX_D_DECL(i,j,k), yfab, xfab, osm,
332 AMREX_D_DECL(dhx,dhy,dhz));
333 });
334 } else {
335#if (AMREX_SPACEDIM == 3)
336 if (this->hasHiddenDimension()) {
337 Box const& bx2d = this->compactify(bx);
338 const auto& xfab2d = this->compactify(xfab);
339 const auto& yfab2d = this->compactify(yfab);
341 {
343 TwoD::mlpoisson_adotx(i, j, yfab2d, xfab2d, dh0, dh1);
344 });
345 } else {
347 {
348 mlpoisson_adotx(i, j, k, yfab, xfab, dhx, dhy, dhz);
349 });
350 }
351#elif (AMREX_SPACEDIM == 2)
352 if (this->m_has_metric_term) {
354 {
356 mlpoisson_adotx_m(i, j, yfab, xfab, dhx, dhy, dx, probxlo);
357 });
358 } else {
360 {
362 mlpoisson_adotx(i, j, yfab, xfab, dhx, dhy);
363 });
364 }
365#elif (AMREX_SPACEDIM == 1)
366 if (this->m_has_metric_term) {
368 {
370 mlpoisson_adotx_m(i, yfab, xfab, dhx, dx, probxlo);
371 });
372 } else {
374 {
376 mlpoisson_adotx(i, yfab, xfab, dhx);
377 });
378 }
379#endif
380 }
381 }
382 }
383}
384
385template <typename MF>
386void
387MLPoissonT<MF>::normalize (int amrlev, int mglev, MF& mf) const
388{
389 amrex::ignore_unused(amrlev,mglev,mf);
390#if (AMREX_SPACEDIM != 3)
391 BL_PROFILE("MLPoisson::normalize()");
392
393 if (!this->m_has_metric_term) { return; }
394
395 const Real* dxinv = this->m_geom[amrlev][mglev].InvCellSize();
396 AMREX_D_TERM(const RT dhx = RT(dxinv[0]*dxinv[0]);,
397 const RT dhy = RT(dxinv[1]*dxinv[1]);,
398 const RT dhz = RT(dxinv[2]*dxinv[2]););
399 const RT dx = RT(this->m_geom[amrlev][mglev].CellSize(0));
400 const RT probxlo = RT(this->m_geom[amrlev][mglev].ProbLo(0));
401
402#ifdef AMREX_USE_GPU
403 if (Gpu::inLaunchRegion() && mf.isFusingCandidate()) {
404 auto const& ma = mf.arrays();
405 ParallelFor(mf,
406 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k) noexcept
407 {
408 mlpoisson_normalize(i,j,k, ma[box_no], AMREX_D_DECL(dhx,dhy,dhz), dx, probxlo);
409 });
410 if (!Gpu::inNoSyncRegion()) {
412 }
413 } else
414#endif
415 {
416#ifdef AMREX_USE_OMP
417#pragma omp parallel if (Gpu::notInLaunchRegion())
418#endif
419 for (MFIter mfi(mf, TilingIfNotGPU()); mfi.isValid(); ++mfi)
420 {
421 const Box& bx = mfi.tilebox();
422 const auto& fab = mf.array(mfi);
423
424#if (AMREX_SPACEDIM == 2)
426 {
427 mlpoisson_normalize(i,j,k, fab, dhx, dhy, dx, probxlo);
428 });
429#else
431 {
432 mlpoisson_normalize(i,j,k, fab, dhx, dx, probxlo);
433 });
434#endif
435 }
436 }
437#endif
438}
439
440template <typename MF>
441void
442MLPoissonT<MF>::Fsmooth (int amrlev, int mglev, MF& sol, const MF& rhs, int redblack) const
443{
444 BL_PROFILE("MLPoisson::Fsmooth()");
445
446 MF Ax;
447 if (! this->m_use_gauss_seidel) { // jacobi
448 Ax.define(sol.boxArray(), sol.DistributionMap(), sol.nComp(), 0,
449 MFInfo().SetArena(The_Async_Arena()));
450 Fapply(amrlev, mglev, Ax, sol);
451 }
452
453 const auto& undrrelxr = this->m_undrrelxr[amrlev][mglev];
454 const auto& maskvals = this->m_maskvals [amrlev][mglev];
455
456 OrientationIter oitr;
457
458 const auto& f0 = undrrelxr[oitr()]; ++oitr;
459 const auto& f1 = undrrelxr[oitr()]; ++oitr;
460#if (AMREX_SPACEDIM > 1)
461 const auto& f2 = undrrelxr[oitr()]; ++oitr;
462 const auto& f3 = undrrelxr[oitr()]; ++oitr;
463#if (AMREX_SPACEDIM > 2)
464 const auto& f4 = undrrelxr[oitr()]; ++oitr;
465 const auto& f5 = undrrelxr[oitr()]; ++oitr;
466#endif
467#endif
468
469 const MultiMask& mm0 = maskvals[0];
470 const MultiMask& mm1 = maskvals[1];
471#if (AMREX_SPACEDIM > 1)
472 const MultiMask& mm2 = maskvals[2];
473 const MultiMask& mm3 = maskvals[3];
474#if (AMREX_SPACEDIM > 2)
475 const MultiMask& mm4 = maskvals[4];
476 const MultiMask& mm5 = maskvals[5];
477#endif
478#endif
479
480 const Real* dxinv = this->m_geom[amrlev][mglev].InvCellSize();
481 AMREX_D_TERM(const RT dhx = RT(dxinv[0]*dxinv[0]);,
482 const RT dhy = RT(dxinv[1]*dxinv[1]);,
483 const RT dhz = RT(dxinv[2]*dxinv[2]););
484
485#if (AMREX_SPACEDIM == 3)
486 RT dh0 = RT(this->get_d0(dhx, dhy, dhz));
487 RT dh1 = RT(this->get_d1(dhx, dhy, dhz));
488#endif
489
490#if (AMREX_SPACEDIM < 3)
491 const RT dx = RT(this->m_geom[amrlev][mglev].CellSize(0));
492 const RT probxlo = RT(this->m_geom[amrlev][mglev].ProbLo(0));
493#endif
494
495 MFItInfo mfi_info;
496 if (Gpu::notInLaunchRegion()) { mfi_info.EnableTiling().SetDynamic(true); }
497
498#ifdef AMREX_USE_GPU
499 if (Gpu::inLaunchRegion() && sol.isFusingCandidate()
500 && ! this->hasHiddenDimension())
501 {
502 const auto& m0ma = mm0.const_arrays();
503 const auto& m1ma = mm1.const_arrays();
504#if (AMREX_SPACEDIM > 1)
505 const auto& m2ma = mm2.const_arrays();
506 const auto& m3ma = mm3.const_arrays();
507#if (AMREX_SPACEDIM > 2)
508 const auto& m4ma = mm4.const_arrays();
509 const auto& m5ma = mm5.const_arrays();
510#endif
511#endif
512
513 const auto& solnma = sol.arrays();
514 const auto& rhsma = rhs.const_arrays();
515
516 AMREX_ALWAYS_ASSERT(rhs.nGrowVect() == 0);
517
518 const auto& f0ma = f0.const_arrays();
519 const auto& f1ma = f1.const_arrays();
520#if (AMREX_SPACEDIM > 1)
521 const auto& f2ma = f2.const_arrays();
522 const auto& f3ma = f3.const_arrays();
523#if (AMREX_SPACEDIM > 2)
524 const auto& f4ma = f4.const_arrays();
525 const auto& f5ma = f5.const_arrays();
526#endif
527#endif
528
529 if (this->m_overset_mask[amrlev][mglev]) {
531 const auto& osmma = this->m_overset_mask[amrlev][mglev]->const_arrays();
532 if (this->m_use_gauss_seidel) {
533 ParallelFor(sol,
534 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k) noexcept
535 {
536 Box vbx(rhsma[box_no]);
537 mlpoisson_gsrb_os(i, j, k, solnma[box_no], rhsma[box_no],
538 osmma[box_no], AMREX_D_DECL(dhx, dhy, dhz),
539 f0ma[box_no], m0ma[box_no],
540 f1ma[box_no], m1ma[box_no],
541#if (AMREX_SPACEDIM > 1)
542 f2ma[box_no], m2ma[box_no],
543 f3ma[box_no], m3ma[box_no],
544#if (AMREX_SPACEDIM > 2)
545 f4ma[box_no], m4ma[box_no],
546 f5ma[box_no], m5ma[box_no],
547#endif
548#endif
549 vbx, redblack);
550 });
551 } else {
552 const auto& axma = Ax.const_arrays();
553 ParallelFor(sol,
554 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k) noexcept
555 {
556 Box vbx(rhsma[box_no]);
557 mlpoisson_jacobi_os(i, j, k, solnma[box_no], rhsma[box_no],
558 axma[box_no], osmma[box_no],
559 AMREX_D_DECL(dhx, dhy, dhz),
560 f0ma[box_no], m0ma[box_no],
561 f1ma[box_no], m1ma[box_no],
562#if (AMREX_SPACEDIM > 1)
563 f2ma[box_no], m2ma[box_no],
564 f3ma[box_no], m3ma[box_no],
565#if (AMREX_SPACEDIM > 2)
566 f4ma[box_no], m4ma[box_no],
567 f5ma[box_no], m5ma[box_no],
568#endif
569#endif
570 vbx);
571 });
572 }
573 }
574#if (AMREX_SPACEDIM < 3)
575 else if (this->m_has_metric_term) {
576 if (this->m_use_gauss_seidel) {
577 ParallelFor(sol,
578 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k) noexcept
579 {
580 Box vbx(rhsma[box_no]);
581 mlpoisson_gsrb_m(i, j, k, solnma[box_no], rhsma[box_no],
582 AMREX_D_DECL(dhx, dhy, dhz),
583 f0ma[box_no], m0ma[box_no],
584 f1ma[box_no], m1ma[box_no],
585#if (AMREX_SPACEDIM > 1)
586 f2ma[box_no], m2ma[box_no],
587 f3ma[box_no], m3ma[box_no],
588#endif
589 vbx, redblack,
590 dx, probxlo);
591 });
592 } else {
593 const auto& axma = Ax.const_arrays();
594 ParallelFor(sol,
595 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k) noexcept
596 {
597 Box vbx(rhsma[box_no]);
598 mlpoisson_jacobi_m(i, j, k, solnma[box_no], rhsma[box_no],
599 axma[box_no], AMREX_D_DECL(dhx, dhy, dhz),
600 f0ma[box_no], m0ma[box_no],
601 f1ma[box_no], m1ma[box_no],
602#if (AMREX_SPACEDIM > 1)
603 f2ma[box_no], m2ma[box_no],
604 f3ma[box_no], m3ma[box_no],
605#endif
606 vbx, dx, probxlo);
607 });
608 }
609 }
610#endif
611 else {
612 if (this->m_use_gauss_seidel) {
613 ParallelFor(sol,
614 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k) noexcept
615 {
616 Box vbx(rhsma[box_no]);
617 mlpoisson_gsrb(i, j, k, solnma[box_no], rhsma[box_no],
618 AMREX_D_DECL(dhx, dhy, dhz),
619 f0ma[box_no], m0ma[box_no],
620 f1ma[box_no], m1ma[box_no],
621#if (AMREX_SPACEDIM > 1)
622 f2ma[box_no], m2ma[box_no],
623 f3ma[box_no], m3ma[box_no],
624#if (AMREX_SPACEDIM > 2)
625 f4ma[box_no], m4ma[box_no],
626 f5ma[box_no], m5ma[box_no],
627#endif
628#endif
629 vbx, redblack);
630 });
631 } else {
632 const auto& axma = Ax.const_arrays();
633 ParallelFor(sol,
634 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k) noexcept
635 {
636 Box vbx(rhsma[box_no]);
637 mlpoisson_jacobi(i, j, k, solnma[box_no], rhsma[box_no],
638 axma[box_no], AMREX_D_DECL(dhx, dhy, dhz),
639 f0ma[box_no], m0ma[box_no],
640 f1ma[box_no], m1ma[box_no],
641#if (AMREX_SPACEDIM > 1)
642 f2ma[box_no], m2ma[box_no],
643 f3ma[box_no], m3ma[box_no],
644#if (AMREX_SPACEDIM > 2)
645 f4ma[box_no], m4ma[box_no],
646 f5ma[box_no], m5ma[box_no],
647#endif
648#endif
649 vbx);
650 });
651 }
652 }
653 if (!Gpu::inNoSyncRegion()) {
655 }
656 } else
657#endif
658 {
659#ifdef AMREX_USE_OMP
660#pragma omp parallel if (Gpu::notInLaunchRegion())
661#endif
662 for (MFIter mfi(sol,mfi_info); mfi.isValid(); ++mfi)
663 {
664 const auto& m0 = mm0.array(mfi);
665 const auto& m1 = mm1.array(mfi);
666#if (AMREX_SPACEDIM > 1)
667 const auto& m2 = mm2.array(mfi);
668 const auto& m3 = mm3.array(mfi);
669#if (AMREX_SPACEDIM > 2)
670 const auto& m4 = mm4.array(mfi);
671 const auto& m5 = mm5.array(mfi);
672#endif
673#endif
674
675 const Box& tbx = mfi.tilebox();
676 const Box& vbx = mfi.validbox();
677 const auto& solnfab = sol.array(mfi);
678 const auto& rhsfab = rhs.array(mfi);
679
680 const auto& f0fab = f0.array(mfi);
681 const auto& f1fab = f1.array(mfi);
682#if (AMREX_SPACEDIM > 1)
683 const auto& f2fab = f2.array(mfi);
684 const auto& f3fab = f3.array(mfi);
685#if (AMREX_SPACEDIM > 2)
686 const auto& f4fab = f4.array(mfi);
687 const auto& f5fab = f5.array(mfi);
688#endif
689#endif
690
691#if (AMREX_SPACEDIM == 1)
692 if (this->m_overset_mask[amrlev][mglev]) {
694 const auto& osm = this->m_overset_mask[amrlev][mglev]->const_array(mfi);
695 if (this->m_use_gauss_seidel) {
697 {
698 mlpoisson_gsrb_os(i, j, k, solnfab, rhsfab, osm, dhx,
699 f0fab, m0,
700 f1fab, m1,
701 vbx, redblack);
702 });
703 } else {
704 const auto& axfab = Ax.const_array(mfi);
706 {
707 mlpoisson_jacobi_os(i, j, k, solnfab, rhsfab, axfab,
708 osm, dhx,
709 f0fab, m0,
710 f1fab, m1,
711 vbx);
712 });
713 }
714 } else if (this->m_has_metric_term) {
715 if (this->m_use_gauss_seidel) {
717 {
718 mlpoisson_gsrb_m(i, j, k, solnfab, rhsfab, dhx,
719 f0fab, m0,
720 f1fab, m1,
721 vbx, redblack,
722 dx, probxlo);
723 });
724 } else {
725 const auto& axfab = Ax.const_array(mfi);
727 {
728 mlpoisson_jacobi_m(i, j, k, solnfab, rhsfab, axfab, dhx,
729 f0fab, m0,
730 f1fab, m1,
731 vbx, dx, probxlo);
732 });
733 }
734 } else {
735 if (this->m_use_gauss_seidel) {
737 {
738 mlpoisson_gsrb(i, j, k, solnfab, rhsfab, dhx,
739 f0fab, m0,
740 f1fab, m1,
741 vbx, redblack);
742 });
743 } else {
744 const auto& axfab = Ax.const_array(mfi);
746 {
747 mlpoisson_jacobi(i, j, k, solnfab, rhsfab, axfab, dhx,
748 f0fab, m0,
749 f1fab, m1,
750 vbx);
751 });
752 }
753 }
754#endif
755
756#if (AMREX_SPACEDIM == 2)
757 if (this->m_overset_mask[amrlev][mglev]) {
759 const auto& osm = this->m_overset_mask[amrlev][mglev]->const_array(mfi);
760 if (this->m_use_gauss_seidel) {
762 {
763 mlpoisson_gsrb_os(i, j, k, solnfab, rhsfab, osm, dhx, dhy,
764 f0fab, m0,
765 f1fab, m1,
766 f2fab, m2,
767 f3fab, m3,
768 vbx, redblack);
769 });
770 } else {
771 const auto& axfab = Ax.const_array(mfi);
773 {
774 mlpoisson_jacobi_os(i, j, k, solnfab, rhsfab, axfab,
775 osm, dhx, dhy,
776 f0fab, m0,
777 f1fab, m1,
778 f2fab, m2,
779 f3fab, m3,
780 vbx);
781 });
782 }
783 } else if (this->m_has_metric_term) {
784 if (this->m_use_gauss_seidel) {
786 {
787 mlpoisson_gsrb_m(i, j, k, solnfab, rhsfab, dhx, dhy,
788 f0fab, m0,
789 f1fab, m1,
790 f2fab, m2,
791 f3fab, m3,
792 vbx, redblack,
793 dx, probxlo);
794 });
795 } else {
796 const auto& axfab = Ax.const_array(mfi);
798 {
799 mlpoisson_jacobi_m(i, j, k, solnfab, rhsfab, axfab, dhx, dhy,
800 f0fab, m0,
801 f1fab, m1,
802 f2fab, m2,
803 f3fab, m3,
804 vbx, dx, probxlo);
805 });
806 }
807 } else {
808 if (this->m_use_gauss_seidel) {
810 {
811 mlpoisson_gsrb(i, j, k, solnfab, rhsfab, dhx, dhy,
812 f0fab, m0,
813 f1fab, m1,
814 f2fab, m2,
815 f3fab, m3,
816 vbx, redblack);
817 });
818 } else {
819 const auto& axfab = Ax.const_array(mfi);
821 {
822 mlpoisson_jacobi(i, j, k, solnfab, rhsfab, axfab, dhx, dhy,
823 f0fab, m0,
824 f1fab, m1,
825 f2fab, m2,
826 f3fab, m3,
827 vbx);
828 });
829 }
830 }
831#endif
832
833#if (AMREX_SPACEDIM == 3)
834 if (this->m_overset_mask[amrlev][mglev]) {
836 const auto& osm = this->m_overset_mask[amrlev][mglev]->const_array(mfi);
837 if (this->m_use_gauss_seidel) {
839 {
840 mlpoisson_gsrb_os(i, j, k, solnfab, rhsfab, osm, dhx, dhy, dhz,
841 f0fab, m0,
842 f1fab, m1,
843 f2fab, m2,
844 f3fab, m3,
845 f4fab, m4,
846 f5fab, m5,
847 vbx, redblack);
848 });
849 } else {
850 const auto& axfab = Ax.const_array(mfi);
852 {
853 mlpoisson_jacobi_os(i, j, k, solnfab, rhsfab, axfab,
854 osm, dhx, dhy, dhz,
855 f0fab, m0,
856 f1fab, m1,
857 f2fab, m2,
858 f3fab, m3,
859 f4fab, m4,
860 f5fab, m5,
861 vbx);
862 });
863 }
864 } else if (this->hasHiddenDimension()) {
865 Box const& tbx_2d = this->compactify(tbx);
866 Box const& vbx_2d = this->compactify(vbx);
867 const auto& solnfab_2d = this->compactify(solnfab);
868 const auto& rhsfab_2d = this->compactify(rhsfab);
869 const auto& f0fab_2d = this->compactify(this->get_d0(f0fab,f1fab,f2fab));
870 const auto& f1fab_2d = this->compactify(this->get_d1(f0fab,f1fab,f2fab));
871 const auto& f2fab_2d = this->compactify(this->get_d0(f3fab,f4fab,f5fab));
872 const auto& f3fab_2d = this->compactify(this->get_d1(f3fab,f4fab,f5fab));
873 const auto& m0_2d = this->compactify(this->get_d0(m0,m1,m2));
874 const auto& m1_2d = this->compactify(this->get_d1(m0,m1,m2));
875 const auto& m2_2d = this->compactify(this->get_d0(m3,m4,m5));
876 const auto& m3_2d = this->compactify(this->get_d1(m3,m4,m5));
877 if (this->m_use_gauss_seidel) {
878 AMREX_HOST_DEVICE_PARALLEL_FOR_3D ( tbx_2d, i, j, k,
879 {
880 TwoD::mlpoisson_gsrb(i, j, k, solnfab_2d, rhsfab_2d, dh0, dh1,
881 f0fab_2d, m0_2d,
882 f1fab_2d, m1_2d,
883 f2fab_2d, m2_2d,
884 f3fab_2d, m3_2d,
885 vbx_2d, redblack);
886 });
887 } else {
888 const auto& axfab = Ax.const_array(mfi);
889 const auto& axfab_2d = this->compactify(axfab);
890 AMREX_HOST_DEVICE_PARALLEL_FOR_3D ( tbx_2d, i, j, k,
891 {
892 TwoD::mlpoisson_jacobi(i, j, k, solnfab_2d, rhsfab_2d,
893 axfab_2d, dh0, dh1,
894 f0fab_2d, m0_2d,
895 f1fab_2d, m1_2d,
896 f2fab_2d, m2_2d,
897 f3fab_2d, m3_2d,
898 vbx_2d);
899 });
900 }
901 } else {
902 if (this->m_use_gauss_seidel) {
904 {
905 mlpoisson_gsrb(i, j, k, solnfab, rhsfab, dhx, dhy, dhz,
906 f0fab, m0,
907 f1fab, m1,
908 f2fab, m2,
909 f3fab, m3,
910 f4fab, m4,
911 f5fab, m5,
912 vbx, redblack);
913 });
914 } else {
915 const auto& axfab = Ax.const_array(mfi);
917 {
918 mlpoisson_jacobi(i, j, k, solnfab, rhsfab, axfab,
919 dhx, dhy, dhz,
920 f0fab, m0,
921 f1fab, m1,
922 f2fab, m2,
923 f3fab, m3,
924 f4fab, m4,
925 f5fab, m5,
926 vbx);
927 });
928 }
929 }
930#endif
931 }
932 }
933}
934
935template <typename MF>
936void
937MLPoissonT<MF>::FFlux (int amrlev, const MFIter& mfi,
938 const Array<FAB*,AMREX_SPACEDIM>& flux,
939 const FAB& sol, Location, const int face_only) const
940{
941 BL_PROFILE("MLPoisson::FFlux()");
942
943 const int mglev = 0;
944 const Box& box = mfi.tilebox();
945 const Real* dxinv = this->m_geom[amrlev][mglev].InvCellSize();
946
947 AMREX_D_TERM(const auto& fxarr = flux[0]->array();,
948 const auto& fyarr = flux[1]->array();,
949 const auto& fzarr = flux[2]->array(););
950 const auto& solarr = sol.array();
951
952#if (AMREX_SPACEDIM != 3)
953 const RT dx = RT(this->m_geom[amrlev][mglev].CellSize(0));
954 const RT probxlo = RT(this->m_geom[amrlev][mglev].ProbLo(0));
955#endif
956
957#if (AMREX_SPACEDIM == 3)
958 if (face_only) {
959 if (this->hiddenDirection() != 0) {
960 RT fac = RT(dxinv[0]);
961 Box blo = amrex::bdryLo(box, 0);
962 int blen = box.length(0);
964 {
965 mlpoisson_flux_xface(tbox, fxarr, solarr, fac, blen);
966 });
967 } else {
968 flux[0]->template setVal<RunOn::Device>(RT(0.0));
969 }
970 if (this->hiddenDirection() != 1) {
971 RT fac = RT(dxinv[1]);
972 Box blo = amrex::bdryLo(box, 1);
973 int blen = box.length(1);
975 {
976 mlpoisson_flux_yface(tbox, fyarr, solarr, fac, blen);
977 });
978 } else {
979 flux[1]->template setVal<RunOn::Device>(RT(0.0));
980 }
981 if (this->hiddenDirection() != 2) {
982 RT fac = RT(dxinv[2]);
983 Box blo = amrex::bdryLo(box, 2);
984 int blen = box.length(2);
986 {
987 mlpoisson_flux_zface(tbox, fzarr, solarr, fac, blen);
988 });
989 } else {
990 flux[2]->template setVal<RunOn::Device>(RT(0.0));
991 }
992 } else {
993 if (this->hiddenDirection() != 0) {
994 RT fac = RT(dxinv[0]);
995 Box bflux = amrex::surroundingNodes(box, 0);
997 {
998 mlpoisson_flux_x(tbox, fxarr, solarr, fac);
999 });
1000 } else {
1001 flux[0]->template setVal<RunOn::Device>(RT(0.0));
1002 }
1003 if (this->hiddenDirection() != 1) {
1004 RT fac = RT(dxinv[1]);
1005 Box bflux = amrex::surroundingNodes(box, 1);
1007 {
1008 mlpoisson_flux_y(tbox, fyarr, solarr, fac);
1009 });
1010 } else {
1011 flux[1]->template setVal<RunOn::Device>(RT(0.0));
1012 }
1013 if (this->hiddenDirection() != 2) {
1014 RT fac = RT(dxinv[2]);
1015 Box bflux = amrex::surroundingNodes(box, 2);
1017 {
1018 mlpoisson_flux_z(tbox, fzarr, solarr, fac);
1019 });
1020 } else {
1021 flux[2]->template setVal<RunOn::Device>(RT(0.0));
1022 }
1023 }
1024#elif (AMREX_SPACEDIM == 2)
1025 if (face_only) {
1026 if (this->hiddenDirection() != 0) {
1027 RT fac = RT(dxinv[0]);
1028 Box blo = amrex::bdryLo(box, 0);
1029 int blen = box.length(0);
1030 if (this->m_has_metric_term) {
1032 {
1033 mlpoisson_flux_xface_m(tbox, fxarr, solarr, fac, blen, dx, probxlo);
1034 });
1035 } else {
1037 {
1038 mlpoisson_flux_xface(tbox, fxarr, solarr, fac, blen);
1039 });
1040 }
1041 } else {
1042 flux[0]->template setVal<RunOn::Device>(RT(0.0));
1043 }
1044 if (this->hiddenDirection() != 1) {
1045 RT fac = RT(dxinv[1]);
1046 Box blo = amrex::bdryLo(box, 1);
1047 int blen = box.length(1);
1048 if (this->m_has_metric_term) {
1050 {
1051 mlpoisson_flux_yface_m(tbox, fyarr, solarr, fac, blen, dx, probxlo);
1052 });
1053 } else {
1055 {
1056 mlpoisson_flux_yface(tbox, fyarr, solarr, fac, blen);
1057 });
1058 }
1059 } else {
1060 flux[1]->template setVal<RunOn::Device>(RT(0.0));
1061 }
1062 } else {
1063 if (this->hiddenDirection() != 0) {
1064 RT fac = RT(dxinv[0]);
1065 Box bflux = amrex::surroundingNodes(box, 0);
1066 if (this->m_has_metric_term) {
1068 {
1069 mlpoisson_flux_x_m(tbox, fxarr, solarr, fac, dx, probxlo);
1070 });
1071 } else {
1073 {
1074 mlpoisson_flux_x(tbox, fxarr, solarr, fac);
1075 });
1076 }
1077 } else {
1078 flux[0]->template setVal<RunOn::Device>(RT(0.0));
1079 }
1080 if (this->hiddenDirection() != 1) {
1081 RT fac = RT(dxinv[1]);
1082 Box bflux = amrex::surroundingNodes(box, 1);
1083 if (this->m_has_metric_term) {
1085 {
1086 mlpoisson_flux_y_m(tbox, fyarr, solarr, fac, dx, probxlo);
1087 });
1088 } else {
1090 {
1091 mlpoisson_flux_y(tbox, fyarr, solarr, fac);
1092 });
1093 }
1094 } else {
1095 flux[1]->template setVal<RunOn::Device>(RT(0.0));
1096 }
1097 }
1098#else
1099 if (face_only) {
1100 RT fac = RT(dxinv[0]);
1101 Box blo = amrex::bdryLo(box, 0);
1102 int blen = box.length(0);
1103 if (this->m_has_metric_term) {
1105 {
1106 mlpoisson_flux_xface_m(tbox, fxarr, solarr, fac, blen, dx, probxlo);
1107 });
1108 } else {
1110 {
1111 mlpoisson_flux_xface(tbox, fxarr, solarr, fac, blen);
1112 });
1113 }
1114 } else {
1115 RT fac = RT(dxinv[0]);
1116 Box bflux = amrex::surroundingNodes(box, 0);
1117 if (this->m_has_metric_term) {
1119 {
1120 mlpoisson_flux_x_m(tbox, fxarr, solarr, fac, dx, probxlo);
1121 });
1122 } else {
1124 {
1125 mlpoisson_flux_x(tbox, fxarr, solarr, fac);
1126 });
1127 }
1128 }
1129#endif
1130}
1131
1132template <typename MF>
1133bool
1135{
1136 bool support = true;
1137 if (this->m_domain_covered[0]) { support = false; }
1138 if (this->doAgglomeration()) { support = false; }
1139 if (AMREX_SPACEDIM != 3) { support = false; }
1140 return support;
1141}
1142
1143template <typename MF>
1144std::unique_ptr<MLLinOpT<MF>>
1145MLPoissonT<MF>::makeNLinOp (int grid_size) const
1146{
1147 const Geometry& geom = this->m_geom[0].back();
1148 const BoxArray& ba = this->makeNGrids(grid_size);
1149
1151 {
1152 const std::vector<std::vector<int> >& sfc = DistributionMapping::makeSFC(ba);
1153 Vector<int> pmap(ba.size());
1155 const int nprocs = ParallelDescriptor::NProcs();
1156 for (int iproc = 0; iproc < nprocs; ++iproc) {
1157 for (int ibox : sfc[iproc]) {
1158 pmap[ibox] = iproc;
1159 }
1160 }
1161 dm.define(std::move(pmap));
1162 }
1163
1164 LPInfo minfo{};
1165 minfo.has_metric_term = this->info.has_metric_term;
1166
1167 std::unique_ptr<MLLinOpT<MF>> r{new MLALaplacianT<MF>({geom}, {ba}, {dm}, minfo)};
1168 auto nop = dynamic_cast<MLALaplacianT<MF>*>(r.get());
1169 if (!nop) {
1170 return nullptr;
1171 }
1172
1173 nop->m_parent = this;
1174
1175 nop->setMaxOrder(this->maxorder);
1176 nop->setVerbose(this->verbose);
1177
1178 nop->setDomainBC(this->m_lobc, this->m_hibc);
1179
1180 if (this->needsCoarseDataForBC())
1181 {
1182 const Real* dx0 = this->m_geom[0][0].CellSize();
1184 fac *= Real(0.5);
1185 RealVect cbloc {AMREX_D_DECL(dx0[0]*fac[0], dx0[1]*fac[1], dx0[2]*fac[2])};
1186 nop->setCoarseFineBCLocation(cbloc);
1187 }
1188
1189 nop->setScalars(1.0, -1.0);
1190
1191 const Real* dxinv = geom.InvCellSize();
1192 RT dxscale = RT(dxinv[0]);
1193#if (AMREX_SPACEDIM >= 2)
1194 dxscale = std::max(dxscale,RT(dxinv[1]));
1195#endif
1196#if (AMREX_SPACEDIM == 3)
1197 dxscale = std::max(dxscale,RT(dxinv[2]));
1198#endif
1199
1200 MF alpha(ba, dm, 1, 0, MFInfo().SetArena(The_Async_Arena()));
1201 alpha.setVal(RT(1.e30)*dxscale*dxscale);
1202
1203 MF foo(this->m_grids[0].back(), this->m_dmap[0].back(), 1, 0, MFInfo().SetAlloc(false));
1204 const FabArrayBase::CPC& cpc = alpha.getCPC(IntVect(0),foo,IntVect(0),Periodicity::NonPeriodic());
1205 alpha.setVal(RT(0.0), cpc, 0, 1);
1206
1207 nop->setACoeffs(0, alpha);
1208
1209 return r;
1210}
1211
1212template <typename MF>
1213void
1214MLPoissonT<MF>::copyNSolveSolution (MF& dst, MF const& src) const
1215{
1216 dst.ParallelCopy(src);
1217}
1218
1219template <typename MF>
1220void
1222 MF const& phi)
1223{
1224 BL_PROFILE("MLPoisson::dpdn_faces()");
1225
1226 // We do not need to call applyBC because this function is used by the
1227 // OpenBC solver after solver has converged. That means the BC has been
1228 // filled to check the residual.
1229
1230 Box const& domain0 = this->m_geom[0][0].Domain();
1231 AMREX_D_TERM(const RT dxi = RT(this->m_geom[0][0].InvCellSize(0));,
1232 const RT dyi = RT(this->m_geom[0][0].InvCellSize(1));,
1233 const RT dzi = RT(this->m_geom[0][0].InvCellSize(2));)
1234
1235#ifdef AMREX_USE_OMP
1236#pragma omp parallel if (Gpu::notInLaunchRegion())
1237#endif
1238 for (MFIter mfi(phi); mfi.isValid(); ++mfi)
1239 {
1240 Box const& vbx = mfi.validbox();
1241 for (OrientationIter oit; oit.isValid(); ++oit) {
1242 Orientation face = oit();
1243 if (vbx[face] == domain0[face]) {
1244 int dir = face.coordDir();
1245 auto const& p = phi.const_array(mfi);
1246 auto const& gp = dpdn[dir]->array(mfi);
1247 Box const& b2d = amrex::bdryNode(vbx,face);
1248 if (dir == 0) {
1249 // because it's dphi/dn, not dphi/dx.
1250 RT fac = dxi * (face.isLow() ? RT(-1.0) : RT(1.));
1252 {
1253 gp(i,j,k) = fac * (p(i,j,k) - p(i-1,j,k));
1254 });
1255 }
1256#if (AMREX_SPACEDIM > 1)
1257 else if (dir == 1) {
1258 RT fac = dyi * (face.isLow() ? RT(-1.0) : RT(1.));
1260 {
1261 gp(i,j,k) = fac * (p(i,j,k) - p(i,j-1,k));
1262 });
1263 }
1264#if (AMREX_SPACEDIM > 2)
1265 else {
1266 RT fac = dzi * (face.isLow() ? RT(-1.0) : RT(1.));
1268 {
1269 gp(i,j,k) = fac * (p(i,j,k) - p(i,j,k-1));
1270 });
1271 }
1272#endif
1273#endif
1274 }
1275 }
1276 }
1277}
1278
1279extern template class MLPoissonT<MultiFab>;
1280
1283
1284}
1285
1286#endif
#define BL_PROFILE(a)
Definition AMReX_BLProfiler.H:562
#define AMREX_ALWAYS_ASSERT_WITH_MESSAGE(EX, MSG)
Definition AMReX_BLassert.H:49
#define AMREX_ASSERT(EX)
Definition AMReX_BLassert.H:38
#define AMREX_ALWAYS_ASSERT(EX)
Definition AMReX_BLassert.H:50
#define AMREX_HOST_DEVICE_PARALLEL_FOR_3D(...)
Definition AMReX_GpuLaunchMacrosC.nolint.H:110
#define AMREX_GPU_LAUNCH_HOST_DEVICE_LAMBDA_RANGE(TN, TI, block)
Definition AMReX_GpuLaunchMacrosC.nolint.H:4
#define AMREX_GPU_DEVICE
Definition AMReX_GpuQualifiers.H:18
#define AMREX_D_TERM(a, b, c)
Definition AMReX_SPACE.H:172
#define AMREX_D_DECL(a, b, c)
Definition AMReX_SPACE.H:171
Reference-counted collection of Boxes.
Definition AMReX_BoxArray.H:681
Long size() const noexcept
Return the number of boxes in the BoxArray.
Definition AMReX_BoxArray.H:758
__host__ __device__ IntVectND< dim > length() const noexcept
Return the length of the BoxND.
Definition AMReX_Box.H:167
const Real * InvCellSize() const noexcept
Returns the inverse cellsize for each coordinate direction.
Definition AMReX_CoordSys.H:91
Calculates the distribution of FABs to MPI processes.
Definition AMReX_DistributionMapping.H:51
void define(const BoxArray &boxes, int nprocs=ParallelDescriptor::NProcs())
Build a mapping from a BoxArray using the current strategy.
Definition AMReX_DistributionMapping.cpp:347
static DistributionMapping makeSFC(const MultiFab &weight, bool sort=true)
Build an SFC map weighted by the sum of component 0 over each valid box of weight; sort enables load-...
Definition AMReX_DistributionMapping.cpp:1770
Abstract factory interface for creating, aliasing, and destroying FAB objects.
Definition AMReX_FabFactory.H:73
Rectangular problem domain geometry.
Definition AMReX_Geometry.H:85
Iterator for looping ever tiles and boxes of amrex::FabArray based containers.
Definition AMReX_MFIter.H:88
Box tilebox() const noexcept
Return the tile Box at the current index.
Definition AMReX_MFIter.cpp:389
bool isValid() const noexcept
Is the iterator valid i.e. is it associated with a FAB?
Definition AMReX_MFIter.H:176
Multi-component ALaplacian (a scalar plus optional spatial a coeffs).
Definition AMReX_MLALaplacian.H:22
Cell-centered operator that exposes ABec Laplacian helpers to derived classes.
Definition AMReX_MLCellABecLap.H:22
Vector< Vector< std::unique_ptr< iMultiFab > > > m_overset_mask
Definition AMReX_MLCellABecLap.H:141
void define(const Vector< Geometry > &a_geom, const Vector< BoxArray > &a_grids, const Vector< DistributionMapping > &a_dmap, const LPInfo &a_info=LPInfo(), const Vector< FabFactory< FAB > const * > &a_factory={})
Describe the AMR hierarchy when overset masks are not required.
Definition AMReX_MLCellABecLap.H:150
void prepareForSolve() override
Standard hook called before MLMG iterates (fixes BC data, etc.).
Definition AMReX_MLCellABecLap.H:309
BoxArray makeNGrids(int grid_size) const
Helper that builds a BoxArray for NSolve with boxes no larger than the requested grid_size.
Definition AMReX_MLCellLinOp.H:1203
Vector< Vector< BndryRegisterT< MF > > > m_undrrelxr
Definition AMReX_MLCellLinOp.H:489
bool m_has_metric_term
Definition AMReX_MLCellLinOp.H:434
bool m_use_gauss_seidel
Definition AMReX_MLCellLinOp.H:498
Vector< Vector< Array< MultiMask, 2 *3 > > > m_maskvals
Definition AMReX_MLCellLinOp.H:492
T get_d0(T const &dx, T const &dy, T const &) const noexcept
Definition AMReX_MLLinOp.H:1046
bool doAgglomeration() const noexcept
Definition AMReX_MLLinOp.H:987
Vector< Array< BCType, 3 > > m_hibc
Definition AMReX_MLLinOp.H:870
Vector< Vector< BoxArray > > m_grids
Definition AMReX_MLLinOp.H:906
Vector< Vector< DistributionMapping > > m_dmap
Definition AMReX_MLLinOp.H:907
int verbose
Definition AMReX_MLLinOp.H:884
IntVect m_coarse_data_crse_ratio
Definition AMReX_MLLinOp.H:935
bool needsCoarseDataForBC() const noexcept
Needs coarse data for bc?
Definition AMReX_MLLinOp.H:228
bool hasHiddenDimension() const noexcept
Definition AMReX_MLLinOp.H:1027
int hiddenDirection() const noexcept
Definition AMReX_MLLinOp.H:1028
Vector< Array< BCType, 3 > > m_lobc
Definition AMReX_MLLinOp.H:869
Vector< int > m_domain_covered
Definition AMReX_MLLinOp.H:909
const MLLinOpT< MF > * m_parent
Definition AMReX_MLLinOp.H:894
Vector< Vector< Geometry > > m_geom
first Vector is for amr level and second is mg level
Definition AMReX_MLLinOp.H:905
Box compactify(Box const &b) const noexcept
Definition AMReX_MLLinOp.H:1615
bool m_needs_coarse_data_for_bc
Definition AMReX_MLLinOp.H:933
int maxorder
Definition AMReX_MLLinOp.H:886
LPInfo info
Definition AMReX_MLLinOp.H:882
T get_d1(T const &, T const &dy, T const &dz) const noexcept
Definition AMReX_MLLinOp.H:1056
LinOpBCType m_coarse_fine_bc_type
Definition AMReX_MLLinOp.H:934
int m_num_amr_levels
Definition AMReX_MLLinOp.H:890
Cell-centered Laplacian operator \nabla^2 \phi.
Definition AMReX_MLPoisson.H:32
typename MF::value_type RT
Definition AMReX_MLPoisson.H:36
MLPoissonT< MF > & operator=(const MLPoissonT< MF > &)=delete
void copyNSolveSolution(MF &dst, MF const &src) const final
Copy an NSolve solution from src to dst.
Definition AMReX_MLPoisson.H:1214
void get_dpdn_on_domain_faces(Array< MF *, 3 > const &dpdn, MF const &phi)
Compute dphi/dn on domain faces after the solve.
Definition AMReX_MLPoisson.H:1221
bool isBottomSingular() const final
True if the coarsest level is singular (e.g., pure Neumann BCs).
Definition AMReX_MLPoisson.H:110
void prepareForSolve() final
Prepare coefficients and singularity flags before entering MLMG.
Definition AMReX_MLPoisson.H:212
void Fapply(int amrlev, int mglev, MF &out, const MF &in) const final
Apply the discrete Laplacian to in at (amrlev,mglev), storing the result in out.
Definition AMReX_MLPoisson.H:254
void normalize(int amrlev, int mglev, MF &mf) const final
Divide mf by the diagonal of the operator (used by CG-family bottom solvers).
Definition AMReX_MLPoisson.H:387
typename MF::fab_type FAB
Definition AMReX_MLPoisson.H:35
Array< MF const *, 3 > getBCoeffs(int, int) const final
Poisson never supplies explicit b Multifabs, so this always returns null pointers.
Definition AMReX_MLPoisson.H:133
bool isSingular(int amrlev) const final
True if the operator is singular on AMR level amrlev.
Definition AMReX_MLPoisson.H:108
~MLPoissonT() override
MLPoissonT(const MLPoissonT< MF > &)=delete
bool supportNSolve() const final
Report whether this operator has nodal-solve support.
Definition AMReX_MLPoisson.H:1134
MLPoissonT(MLPoissonT< MF > &&)=delete
void define(const Vector< Geometry > &a_geom, const Vector< BoxArray > &a_grids, const Vector< DistributionMapping > &a_dmap, const LPInfo &a_info=LPInfo(), const Vector< FabFactory< FAB > const * > &a_factory={})
Define the hierarchy for standard cell-centered data.
Definition AMReX_MLPoisson.H:182
RT getAScalar() const final
Return the constant a coefficient (identically zero for Poisson).
Definition AMReX_MLPoisson.H:127
RT getBScalar() const final
Return the constant b coefficient (-1, cancelling the minus in the ABec form to give \nabla^2).
Definition AMReX_MLPoisson.H:129
MF const * getACoeffs(int, int) const final
Poisson never supplies explicit a coefficients, so this always returns nullptr.
Definition AMReX_MLPoisson.H:131
MLPoissonT()=default
Construct an empty operator; call define() before using it.
void FFlux(int amrlev, const MFIter &mfi, const Array< FAB *, 3 > &flux, const FAB &sol, Location loc, int face_only=0) const final
Compute per-face fluxes from sol on the tilebox described by mfi and write them to flux with location...
Definition AMReX_MLPoisson.H:937
typename MLLinOpT< MF >::Location Location
Definition AMReX_MLPoisson.H:39
void Fsmooth(int amrlev, int mglev, MF &sol, const MF &rhs, int redblack) const final
Perform a smoothing sweep on (amrlev,mglev). redblack selects the red (0) or black (1) half of the gr...
Definition AMReX_MLPoisson.H:442
std::unique_ptr< MLLinOpT< MF > > makeNLinOp(int grid_size) const final
Build the NSolve counterpart with tile size grid_size.
Definition AMReX_MLPoisson.H:1145
Definition AMReX_MultiMask.H:23
MultiArray4< int const > const_arrays() const noexcept
Return const multi-array views (alias of arrays()).
Definition AMReX_MultiMask.H:86
Array4< int const > array(const MFIter &mfi) const noexcept
Return an Array4 view (const) for iterator mfi.
Definition AMReX_MultiMask.H:69
An Iterator over the Orientation of Faces of a Box.
Definition AMReX_Orientation.H:135
__host__ __device__ bool isValid() const noexcept
Is the iterator valid?
Definition AMReX_Orientation.H:156
Encapsulation of the Orientation of the Faces of a Box.
Definition AMReX_Orientation.H:29
__host__ __device__ bool isLow() const noexcept
Returns true if Orientation is low.
Definition AMReX_Orientation.H:89
__host__ __device__ int coordDir() const noexcept
Returns the coordinate direction.
Definition AMReX_Orientation.H:83
static const Periodicity & NonPeriodic() noexcept
Definition AMReX_Periodicity.cpp:52
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:29
amrex_real Real
Floating Point Type for Fields.
Definition AMReX_REAL.H:80
__host__ __device__ BoxND< dim > surroundingNodes(const BoxND< dim > &b, int dir) noexcept
Return a BoxND with NODE based coordinates in direction dir that encloses BoxND b.
Definition AMReX_Box.H:1582
__host__ __device__ BoxND< dim > bdryLo(const BoxND< dim > &b, int dir, int len=1) noexcept
Return the BoxND of length len on the low boundary of b along coordinate direction dir.
Definition AMReX_Box.H:1715
__host__ __device__ BoxND< dim > bdryNode(const BoxND< dim > &b, Orientation face, int len=1) noexcept
Similar to bdryLo and bdryHi except that it operates on the given face of BoxND b.
Definition AMReX_Box.H:1776
std::array< T, N > Array
Definition AMReX_Array.H:31
Arena * The_Async_Arena()
Definition AMReX_Arena.cpp:825
int NProcs() noexcept
Definition AMReX_ParallelDescriptor.H:255
void streamSynchronize() noexcept
Definition AMReX_GpuDevice.H:310
bool inLaunchRegion() noexcept
Definition AMReX_GpuControl.H:88
bool notInLaunchRegion() noexcept
Definition AMReX_GpuControl.H:89
bool inNoSyncRegion() noexcept
Definition AMReX_GpuControl.H:148
MPI_Comm CommunicatorSub() noexcept
sub-communicator for current frame
Definition AMReX_ParallelContext.H:70
MPI_Comm Communicator() noexcept
Definition AMReX_ParallelDescriptor.H:223
Definition AMReX_Amr.cpp:50
__host__ __device__ void ignore_unused(const Ts &...)
No-op helper that marks variables as intentionally unused.
Definition AMReX.H:259
void ParallelFor(TypeList< CTOs... > ctos, std::array< int, sizeof...(CTOs)> const &runtime_options, T N, F &&f)
Definition AMReX_CTOParallelForImpl.H:202
LinOpBCType
Definition AMReX_LO_BCTYPES.H:27
IntVectND< 3 > IntVect
IntVect is an alias for amrex::IntVectND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:38
bool TilingIfNotGPU() noexcept
Definition AMReX_MFIter.H:12
__host__ __device__ Dim3 end(BoxND< dim > const &box) noexcept
Return the iterator end coordinate of box as Dim3.
Definition AMReX_Box.H:2257
parallel copy or add
Definition AMReX_FabArrayBase.H:630
Configuration knobs for multilevel linear operators (grid agglomeration, metrics, etc....
Definition AMReX_MLLinOp.H:51
bool has_metric_term
Definition AMReX_MLLinOp.H:59
Location
Definition AMReX_MLLinOp.H:119
FabArray memory allocation information.
Definition AMReX_FabArray.H:73
Definition AMReX_MFIter.H:20
MFItInfo & SetDynamic(bool f) noexcept
Definition AMReX_MFIter.H:43
MFItInfo & EnableTiling(const IntVect &ts=FabArrayBase::mfiter_tile_size) noexcept
Definition AMReX_MFIter.H:31