Skip to content

Commit 08e3eaa

Browse files
WeiqunZhangajnonaka
authored andcommitted
MLNodeABecLaplacian (AMReX-Codes#3559)
Add a new Linear Opearator class MLNodeABecLaplacian. It solves `(alpha * a - beta * (del dot b grad)) phi = rhs`, where a, phi and rhs are nodal MultiFabs and b is cell-centered. It works in 2D and 3D, CPU and GPU. So far it works only for single level. There is an example of using it at Tests/LinearSolvers/ABecLaplacian_C as prob_type=4. The test problem converges at the second order. --------- Co-authored-by: Andy Nonaka <[email protected]>
1 parent b81cc0e commit 08e3eaa

17 files changed

+836
-12
lines changed

Src/LinearSolvers/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ foreach(D IN LISTS AMReX_SPACEDIM)
4949
MLMG/AMReX_MLEBNodeFDLaplacian.cpp
5050
MLMG/AMReX_MLEBNodeFDLap_K.H
5151
MLMG/AMReX_MLEBNodeFDLap_${D}D_K.H
52+
MLMG/AMReX_MLNodeABecLaplacian.H
53+
MLMG/AMReX_MLNodeABecLaplacian.cpp
54+
MLMG/AMReX_MLNodeABecLap_K.H
55+
MLMG/AMReX_MLNodeABecLap_${D}D_K.H
5256
)
5357

5458
if (D EQUAL 3)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#ifndef AMREX_MLNODEABECLAP_1D_K_H_
2+
#define AMREX_MLNODEABECLAP_1D_K_H_
3+
4+
namespace amrex {
5+
6+
inline void
7+
mlndabeclap_gauss_seidel_aa (Box const& /*bx*/, Array4<Real> const& /*sol*/,
8+
Array4<Real const> const& /*rhs*/,
9+
Real /*alpha*/, Real /*beta*/,
10+
Array4<Real const> const& /*acf*/,
11+
Array4<Real const> const& /*bcf*/,
12+
Array4<int const> const& /*msk*/,
13+
GpuArray<Real,AMREX_SPACEDIM> const& /*dxinv*/) noexcept
14+
{}
15+
16+
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void
17+
mlndabeclap_jacobi_aa (int /*i*/, int /*j*/, int /*k*/,
18+
Array4<Real> const& /*sol*/,
19+
Real /*lap*/,
20+
Array4<Real const> const& /*rhs*/,
21+
Real /*alpha*/, Real /*beta*/,
22+
Array4<Real const> const& /*acf*/,
23+
Array4<Real const> const& /*bcf*/,
24+
Array4<int const> const& /*msk*/,
25+
GpuArray<Real,AMREX_SPACEDIM> const& /*dxinv*/) noexcept
26+
{}
27+
28+
}
29+
30+
#endif
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#ifndef AMREX_MLNODEABECLAP_2D_K_H_
2+
#define AMREX_MLNODEABECLAP_2D_K_H_
3+
4+
namespace amrex {
5+
6+
inline void
7+
mlndabeclap_gauss_seidel_aa (Box const& bx, Array4<Real> const& sol,
8+
Array4<Real const> const& rhs,
9+
Real alpha, Real beta,
10+
Array4<Real const> const& acf,
11+
Array4<Real const> const& bcf,
12+
Array4<int const> const& msk,
13+
GpuArray<Real,AMREX_SPACEDIM> const& dxinv) noexcept
14+
{
15+
Real facx = Real(1.0/6.0)*dxinv[0]*dxinv[0];
16+
Real facy = Real(1.0/6.0)*dxinv[1]*dxinv[1];
17+
Real fxy = facx + facy;
18+
Real f2xmy = Real(2.0)*facx - facy;
19+
Real fmx2y = Real(2.0)*facy - facx;
20+
21+
amrex::Loop(bx, [=] (int i, int j, int k) noexcept
22+
{
23+
if (msk(i,j,k)) {
24+
sol(i,j,k) = Real(0.0);
25+
} else {
26+
Real s0 = (-Real(2.0))*fxy*(bcf(i-1,j-1,k)+bcf(i,j-1,k)+bcf(i-1,j,k)+bcf(i,j,k));
27+
Real lap = sol(i-1,j-1,k)*fxy*bcf(i-1,j-1,k)
28+
+ sol(i+1,j-1,k)*fxy*bcf(i ,j-1,k)
29+
+ sol(i-1,j+1,k)*fxy*bcf(i-1,j ,k)
30+
+ sol(i+1,j+1,k)*fxy*bcf(i ,j ,k)
31+
+ sol(i-1,j,k)*f2xmy*(bcf(i-1,j-1,k)+bcf(i-1,j,k))
32+
+ sol(i+1,j,k)*f2xmy*(bcf(i ,j-1,k)+bcf(i ,j,k))
33+
+ sol(i,j-1,k)*fmx2y*(bcf(i-1,j-1,k)+bcf(i,j-1,k))
34+
+ sol(i,j+1,k)*fmx2y*(bcf(i-1,j ,k)+bcf(i,j ,k))
35+
+ sol(i,j,k)*s0;
36+
Real Ax = alpha*acf(i,j,k)*sol(i,j,k) - beta*lap;
37+
38+
sol(i,j,k) += (rhs(i,j,k) - Ax) / (alpha*acf(i,j,k)-beta*s0);
39+
}
40+
});
41+
}
42+
43+
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void
44+
mlndabeclap_jacobi_aa (int i, int j, int k, Array4<Real> const& sol,
45+
Real lap, Array4<Real const> const& rhs,
46+
Real alpha, Real beta,
47+
Array4<Real const> const& acf,
48+
Array4<Real const> const& bcf,
49+
Array4<int const> const& msk,
50+
GpuArray<Real,AMREX_SPACEDIM> const& dxinv) noexcept
51+
{
52+
if (msk(i,j,k)) {
53+
sol(i,j,k) = Real(0.0);
54+
} else {
55+
Real fac = -Real(2.0/6.0)*(dxinv[0]*dxinv[0] + dxinv[1]*dxinv[1]);
56+
Real s0 = fac*(bcf(i-1,j-1,k)+bcf(i,j-1,k)+bcf(i-1,j,k)+bcf(i,j,k));
57+
Real Ax = alpha*acf(i,j,k)*sol(i,j,k) - beta*lap;
58+
59+
sol(i,j,k) += Real(2.0/3.0) * (rhs(i,j,k) - Ax)
60+
/ (alpha*acf(i,j,k)-beta*s0);
61+
}
62+
63+
}
64+
65+
}
66+
67+
#endif
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#ifndef AMREX_MLNODEABECLAP_3D_K_H_
2+
#define AMREX_MLNODEABECLAP_3D_K_H_
3+
4+
namespace amrex {
5+
6+
inline void
7+
mlndabeclap_gauss_seidel_aa (Box const& bx, Array4<Real> const& sol,
8+
Array4<Real const> const& rhs,
9+
Real alpha, Real beta,
10+
Array4<Real const> const& acf,
11+
Array4<Real const> const& bcf,
12+
Array4<int const> const& msk,
13+
GpuArray<Real,AMREX_SPACEDIM> const& dxinv) noexcept
14+
{
15+
Real facx = Real(1.0/36.0)*dxinv[0]*dxinv[0];
16+
Real facy = Real(1.0/36.0)*dxinv[1]*dxinv[1];
17+
Real facz = Real(1.0/36.0)*dxinv[2]*dxinv[2];
18+
Real fxyz = facx + facy + facz;
19+
Real fmx2y2z = -facx + Real(2.0)*facy + Real(2.0)*facz;
20+
Real f2xmy2z = Real(2.0)*facx - facy + Real(2.0)*facz;
21+
Real f2x2ymz = Real(2.0)*facx + Real(2.0)*facy - facz;
22+
Real f4xm2ym2z = Real(4.0)*facx - Real(2.0)*facy - Real(2.0)*facz;
23+
Real fm2x4ym2z = -Real(2.0)*facx + Real(4.0)*facy - Real(2.0)*facz;
24+
Real fm2xm2y4z = -Real(2.0)*facx - Real(2.0)*facy + Real(4.0)*facz;
25+
26+
amrex::LoopOnCpu(bx, [=] (int i, int j, int k) noexcept
27+
{
28+
if (msk(i,j,k)) {
29+
sol(i,j,k) = Real(0.0);
30+
} else {
31+
Real s0 = Real(-4.0)*fxyz*(bcf(i-1,j-1,k-1)+bcf(i,j-1,k-1)+bcf(i-1,j,k-1)+bcf(i,j,k-1)
32+
+bcf(i-1,j-1,k )+bcf(i,j-1,k )+bcf(i-1,j,k )+bcf(i,j,k ));
33+
Real lap = sol(i,j,k)*s0
34+
+ fxyz*(sol(i-1,j-1,k-1)*bcf(i-1,j-1,k-1)
35+
+ sol(i+1,j-1,k-1)*bcf(i ,j-1,k-1)
36+
+ sol(i-1,j+1,k-1)*bcf(i-1,j ,k-1)
37+
+ sol(i+1,j+1,k-1)*bcf(i ,j ,k-1)
38+
+ sol(i-1,j-1,k+1)*bcf(i-1,j-1,k )
39+
+ sol(i+1,j-1,k+1)*bcf(i ,j-1,k )
40+
+ sol(i-1,j+1,k+1)*bcf(i-1,j ,k )
41+
+ sol(i+1,j+1,k+1)*bcf(i ,j ,k ))
42+
+ fmx2y2z*(sol(i ,j-1,k-1)*(bcf(i-1,j-1,k-1)+bcf(i,j-1,k-1))
43+
+ sol(i ,j+1,k-1)*(bcf(i-1,j ,k-1)+bcf(i,j ,k-1))
44+
+ sol(i ,j-1,k+1)*(bcf(i-1,j-1,k )+bcf(i,j-1,k ))
45+
+ sol(i ,j+1,k+1)*(bcf(i-1,j ,k )+bcf(i,j ,k )))
46+
+ f2xmy2z*(sol(i-1,j ,k-1)*(bcf(i-1,j-1,k-1)+bcf(i-1,j,k-1))
47+
+ sol(i+1,j ,k-1)*(bcf(i ,j-1,k-1)+bcf(i ,j,k-1))
48+
+ sol(i-1,j ,k+1)*(bcf(i-1,j-1,k )+bcf(i-1,j,k ))
49+
+ sol(i+1,j ,k+1)*(bcf(i ,j-1,k )+bcf(i ,j,k )))
50+
+ f2x2ymz*(sol(i-1,j-1,k )*(bcf(i-1,j-1,k-1)+bcf(i-1,j-1,k))
51+
+ sol(i+1,j-1,k )*(bcf(i ,j-1,k-1)+bcf(i ,j-1,k))
52+
+ sol(i-1,j+1,k )*(bcf(i-1,j ,k-1)+bcf(i-1,j ,k))
53+
+ sol(i+1,j+1,k )*(bcf(i ,j ,k-1)+bcf(i ,j ,k)))
54+
+ f4xm2ym2z*(sol(i-1,j,k)*(bcf(i-1,j-1,k-1)+bcf(i-1,j,k-1)+bcf(i-1,j-1,k)+bcf(i-1,j,k))
55+
+ sol(i+1,j,k)*(bcf(i ,j-1,k-1)+bcf(i ,j,k-1)+bcf(i ,j-1,k)+bcf(i ,j,k)))
56+
+ fm2x4ym2z*(sol(i,j-1,k)*(bcf(i-1,j-1,k-1)+bcf(i,j-1,k-1)+bcf(i-1,j-1,k)+bcf(i,j-1,k))
57+
+ sol(i,j+1,k)*(bcf(i-1,j ,k-1)+bcf(i,j ,k-1)+bcf(i-1,j ,k)+bcf(i,j ,k)))
58+
+ fm2xm2y4z*(sol(i,j,k-1)*(bcf(i-1,j-1,k-1)+bcf(i,j-1,k-1)+bcf(i-1,j,k-1)+bcf(i,j,k-1))
59+
+ sol(i,j,k+1)*(bcf(i-1,j-1,k )+bcf(i,j-1,k )+bcf(i-1,j,k )+bcf(i,j,k )));
60+
Real Ax = alpha*acf(i,j,k)*sol(i,j,k) - beta*lap;
61+
62+
sol(i,j,k) += (rhs(i,j,k) - Ax) / (alpha*acf(i,j,k)-beta*s0);
63+
}
64+
});
65+
}
66+
67+
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void
68+
mlndabeclap_jacobi_aa (int i, int j, int k, Array4<Real> const& sol,
69+
Real lap, Array4<Real const> const& rhs,
70+
Real alpha, Real beta,
71+
Array4<Real const> const& acf,
72+
Array4<Real const> const& bcf,
73+
Array4<int const> const& msk,
74+
GpuArray<Real,AMREX_SPACEDIM> const& dxinv) noexcept
75+
{
76+
if (msk(i,j,k)) {
77+
sol(i,j,k) = Real(0.0);
78+
} else {
79+
Real fxyz = Real(-4.0 / 36.0)*(dxinv[0]*dxinv[0] +
80+
dxinv[1]*dxinv[1] +
81+
dxinv[2]*dxinv[2]);
82+
Real s0 = fxyz*(bcf(i-1,j-1,k-1)+bcf(i,j-1,k-1)+bcf(i-1,j,k-1)+bcf(i,j,k-1)
83+
+bcf(i-1,j-1,k )+bcf(i,j-1,k )+bcf(i-1,j,k )+bcf(i,j,k));
84+
Real Ax = alpha*acf(i,j,k)*sol(i,j,k) - beta*lap;
85+
86+
sol(i,j,k) += Real(2.0/3.0) * (rhs(i,j,k) - Ax)
87+
/ (alpha*acf(i,j,k)-beta*s0);
88+
}
89+
}
90+
91+
}
92+
93+
#endif
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#ifndef AMREX_MLNODEABECLAP_K_H_
2+
#define AMREX_MLNODEABECLAP_K_H_
3+
#include <AMReX_Config.H>
4+
5+
#if (AMREX_SPACEDIM == 1)
6+
#include <AMReX_MLNodeABecLap_1D_K.H>
7+
#elif (AMREX_SPACEDIM == 2)
8+
#include <AMReX_MLNodeABecLap_2D_K.H>
9+
#else
10+
#include <AMReX_MLNodeABecLap_3D_K.H>
11+
#endif
12+
13+
#endif
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#ifndef AMREX_MLNODEABECLAPLACIAN_H_
2+
#define AMREX_MLNODEABECLAPLACIAN_H_
3+
#include <AMReX_Config.H>
4+
5+
#include <AMReX_MLNodeLinOp.H>
6+
7+
namespace amrex {
8+
9+
// (alpha * a - beta * (del dot b grad)) phi = rhs
10+
// a, phi and rhs are nodal. b is cell-centered.
11+
12+
class MLNodeABecLaplacian
13+
: public MLNodeLinOp
14+
{
15+
public:
16+
17+
MLNodeABecLaplacian () = default;
18+
MLNodeABecLaplacian (const Vector<Geometry>& a_geom,
19+
const Vector<BoxArray>& a_grids,
20+
const Vector<DistributionMapping>& a_dmap,
21+
const LPInfo& a_info = LPInfo(),
22+
const Vector<FabFactory<FArrayBox> const*>& a_factory = {});
23+
~MLNodeABecLaplacian () override = default;
24+
25+
MLNodeABecLaplacian (const MLNodeABecLaplacian&) = delete;
26+
MLNodeABecLaplacian (MLNodeABecLaplacian&&) = delete;
27+
MLNodeABecLaplacian& operator= (const MLNodeABecLaplacian&) = delete;
28+
MLNodeABecLaplacian& operator= (MLNodeABecLaplacian&&) = delete;
29+
30+
void define (const Vector<Geometry>& a_geom,
31+
const Vector<BoxArray>& a_grids,
32+
const Vector<DistributionMapping>& a_dmap,
33+
const LPInfo& a_info = LPInfo(),
34+
const Vector<FabFactory<FArrayBox> const*>& a_factory = {});
35+
36+
std::string name () const override { return std::string("MLNodeABecLaplacian"); }
37+
38+
void setScalars (Real a, Real b) {
39+
m_a_scalar = a;
40+
m_b_scalar = b;
41+
}
42+
43+
void setACoeffs (int amrlev, Real a_acoef);
44+
void setACoeffs (int amrlev, const MultiFab& a_acoef);
45+
46+
void setBCoeffs (int amrlev, Real a_bcoef);
47+
void setBCoeffs (int amrlev, const MultiFab& a_bcoef);
48+
49+
void Fapply (int amrlev, int mglev, MultiFab& out, const MultiFab& in) const final;
50+
void Fsmooth (int amrlev, int mglev, MultiFab& sol, const MultiFab& rhs) const final;
51+
52+
void fixUpResidualMask (int amrlev, iMultiFab& resmsk) final;
53+
54+
bool isSingular (int /*amrlev*/) const final { return false; }
55+
bool isBottomSingular () const final { return false; }
56+
57+
void restriction (int amrlev, int cmglev, MultiFab& crse, MultiFab& fine) const final;
58+
void interpolation (int amrlev, int fmglev, MultiFab& fine, const MultiFab& crse) const final;
59+
void averageDownSolutionRHS (int camrlev, MultiFab& crse_sol, MultiFab& crse_rhs,
60+
const MultiFab& fine_sol, const MultiFab& fine_rhs) final;
61+
62+
void reflux (int crse_amrlev,
63+
MultiFab& res, const MultiFab& crse_sol, const MultiFab& crse_rhs,
64+
MultiFab& fine_res, MultiFab& fine_sol, const MultiFab& fine_rhs) const final;
65+
66+
void prepareForSolve () final;
67+
68+
void averageDownCoeffs ();
69+
void averageDownCoeffsToCoarseAmrLevel (int flev);
70+
void averageDownCoeffsSameAmrLevel (int amrlev);
71+
72+
private:
73+
74+
Real m_a_scalar = std::numeric_limits<Real>::quiet_NaN();
75+
Real m_b_scalar = std::numeric_limits<Real>::quiet_NaN();
76+
Vector<Vector<MultiFab> > m_a_coeffs;
77+
Vector<Vector<MultiFab> > m_b_coeffs;
78+
};
79+
80+
}
81+
82+
#endif

0 commit comments

Comments
 (0)