Skip to content

Commit

Permalink
MLEBNodeFDLaplacian: Make it work with AMREX_USE_EB but with no EB (#…
Browse files Browse the repository at this point in the history
…4083)

This will allow the use of the linear solver when AMReX is built with EB
support at compile time but no EB is built at runtime.

X-Ref: ECP-WarpX/WarpX#4865
  • Loading branch information
WeiqunZhang committed Aug 15, 2024
1 parent 8535675 commit b82296f
Showing 1 changed file with 48 additions and 34 deletions.
82 changes: 48 additions & 34 deletions Src/LinearSolvers/MLMG/AMReX_MLEBNodeFDLaplacian.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <AMReX_MultiFabUtil.H>

#ifdef AMREX_USE_EB
#include <AMReX_EB2.H>
#include <AMReX_EBMultiFabUtil.H>
#endif

Expand Down Expand Up @@ -151,10 +152,14 @@ MLEBNodeFDLaplacian::define (const Vector<Geometry>& a_geom,
std::unique_ptr<FabFactory<FArrayBox> >
MLEBNodeFDLaplacian::makeFactory (int amrlev, int mglev) const
{
return makeEBFabFactory(m_geom[amrlev][mglev],
m_grids[amrlev][mglev],
m_dmap[amrlev][mglev],
{1,1,1}, EBSupport::full);
if (EB2::TopIndexSpaceIfPresent()) {
return makeEBFabFactory(m_geom[amrlev][mglev],
m_grids[amrlev][mglev],
m_dmap[amrlev][mglev],
{1,1,1}, EBSupport::full);
} else {
return MLNodeLinOp::makeFactory(amrlev, mglev);
}
}
#endif

Expand Down Expand Up @@ -264,17 +269,19 @@ MLEBNodeFDLaplacian::prepareForSolve ()
for (int amrlev = 0; amrlev < m_num_amr_levels; ++amrlev) {
for (int mglev = 0; mglev < m_num_mg_levels[amrlev]; ++mglev) {
const auto *factory = dynamic_cast<EBFArrayBoxFactory const*>(m_factory[amrlev][mglev].get());
auto const& levset_mf = factory->getLevelSet();
auto const& levset_ar = levset_mf.const_arrays();
auto& dmask_mf = *m_dirichlet_mask[amrlev][mglev];
auto const& dmask_ar = dmask_mf.arrays();
amrex::ParallelFor(dmask_mf,
[=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k) noexcept
{
if (levset_ar[box_no](i,j,k) >= Real(0.0)) {
dmask_ar[box_no](i,j,k) = -1;
}
});
if (factory) {
auto const& levset_mf = factory->getLevelSet();
auto const& levset_ar = levset_mf.const_arrays();
auto& dmask_mf = *m_dirichlet_mask[amrlev][mglev];
auto const& dmask_ar = dmask_mf.arrays();
amrex::ParallelFor(dmask_mf,
[=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k) noexcept
{
if (levset_ar[box_no](i,j,k) >= Real(0.0)) {
dmask_ar[box_no](i,j,k) = -1;
}
});
}
}
}
#endif
Expand Down Expand Up @@ -359,8 +366,10 @@ MLEBNodeFDLaplacian::prepareForSolve ()
void
MLEBNodeFDLaplacian::scaleRHS (int amrlev, MultiFab& rhs) const
{
auto const& dmask = *m_dirichlet_mask[amrlev][0];
const auto *factory = dynamic_cast<EBFArrayBoxFactory const*>(m_factory[amrlev][0].get());
if (!factory) { return; }

auto const& dmask = *m_dirichlet_mask[amrlev][0];
auto const& edgecent = factory->getEdgeCent();

#ifdef AMREX_USE_OMP
Expand Down Expand Up @@ -407,9 +416,10 @@ MLEBNodeFDLaplacian::Fapply (int amrlev, int mglev, MultiFab& out, const MultiFa
#ifdef AMREX_USE_EB
const auto phieb = (m_in_solution_mode) ? m_s_phi_eb : Real(0.0);
const auto *factory = dynamic_cast<EBFArrayBoxFactory const*>(m_factory[amrlev][mglev].get());
auto const& edgecent = factory->getEdgeCent();
auto const& levset_mf = factory->getLevelSet();
auto const& volfrac = factory->getVolFrac();
Array<const MultiCutFab*,AMREX_SPACEDIM> edgecent {AMREX_D_DECL(nullptr,nullptr,nullptr)};
if (factory) {
edgecent = factory->getEdgeCent();
}
#endif

#ifdef AMREX_USE_OMP
Expand All @@ -422,12 +432,12 @@ MLEBNodeFDLaplacian::Fapply (int amrlev, int mglev, MultiFab& out, const MultiFa
Array4<Real> const& yarr = out.array(mfi);
Array4<int const> const& dmarr = dmask.const_array(mfi);
#ifdef AMREX_USE_EB
bool cutfab = edgecent[0]->ok(mfi);
if (cutfab) {
bool cutfab = edgecent[0] && edgecent[0]->ok(mfi);
if (cutfab && factory) { // clang-tidy is not that smart
AMREX_D_TERM(Array4<Real const> const& ecx = edgecent[0]->const_array(mfi);,
Array4<Real const> const& ecy = edgecent[1]->const_array(mfi);,
Array4<Real const> const& ecz = edgecent[2]->const_array(mfi));
auto const& levset = levset_mf.const_array(mfi);
auto const& levset = factory->getVolFrac().const_array(mfi);
if (phieb == std::numeric_limits<Real>::lowest()) {
auto const& phiebarr = m_phi_eb[amrlev].const_array(mfi);
#if (AMREX_SPACEDIM == 2)
Expand All @@ -441,7 +451,7 @@ MLEBNodeFDLaplacian::Fapply (int amrlev, int mglev, MultiFab& out, const MultiFa
#endif
if (m_has_sigma_mf) {
auto const& sigarr = m_sigma_mf[amrlev][mglev]->const_array(mfi);
auto const& vfrc = volfrac.const_array(mfi);
auto const& vfrc = factory->getVolFrac().const_array(mfi);
AMREX_HOST_DEVICE_FOR_3D(box, i, j, k,
{
mlebndfdlap_sig_adotx_eb(i,j,k,yarr,xarr,levset,dmarr,AMREX_D_DECL(ecx,ecy,ecz),
Expand All @@ -466,7 +476,7 @@ MLEBNodeFDLaplacian::Fapply (int amrlev, int mglev, MultiFab& out, const MultiFa
#endif
if (m_has_sigma_mf) {
auto const& sigarr = m_sigma_mf[amrlev][mglev]->const_array(mfi);
auto const& vfrc = volfrac.const_array(mfi);
auto const& vfrc = factory->getVolFrac().const_array(mfi);
AMREX_HOST_DEVICE_FOR_3D(box, i, j, k,
{
mlebndfdlap_sig_adotx_eb(i,j,k,yarr,xarr,levset,dmarr,AMREX_D_DECL(ecx,ecy,ecz),
Expand Down Expand Up @@ -533,9 +543,10 @@ MLEBNodeFDLaplacian::Fsmooth (int amrlev, int mglev, MultiFab& sol, const MultiF

#ifdef AMREX_USE_EB
const auto *factory = dynamic_cast<EBFArrayBoxFactory const*>(m_factory[amrlev][mglev].get());
auto const& edgecent = factory->getEdgeCent();
auto const& levset_mf = factory->getLevelSet();
auto const& volfrac = factory->getVolFrac();
Array<const MultiCutFab*,AMREX_SPACEDIM> edgecent {AMREX_D_DECL(nullptr,nullptr,nullptr)};
if (factory) {
edgecent = factory->getEdgeCent();
}
#endif

#ifdef AMREX_USE_OMP
Expand All @@ -548,12 +559,12 @@ MLEBNodeFDLaplacian::Fsmooth (int amrlev, int mglev, MultiFab& sol, const MultiF
Array4<Real const> const& rhsarr = rhs.const_array(mfi);
Array4<int const> const& dmskarr = dmask.const_array(mfi);
#ifdef AMREX_USE_EB
bool cutfab = edgecent[0]->ok(mfi);
if (cutfab) {
bool cutfab = edgecent[0] && edgecent[0]->ok(mfi);
if (cutfab && factory) { // clang-tidy is not that smart
AMREX_D_TERM(Array4<Real const> const& ecx = edgecent[0]->const_array(mfi);,
Array4<Real const> const& ecy = edgecent[1]->const_array(mfi);,
Array4<Real const> const& ecz = edgecent[2]->const_array(mfi));
auto const& levset = levset_mf.const_array(mfi);
auto const& levset = factory->getLevelSet().const_array(mfi);
#if (AMREX_SPACEDIM == 2)
if (m_rz) {
AMREX_HOST_DEVICE_FOR_3D(box, i, j, k,
Expand All @@ -565,7 +576,7 @@ MLEBNodeFDLaplacian::Fsmooth (int amrlev, int mglev, MultiFab& sol, const MultiF
#endif
if (m_has_sigma_mf) {
auto const& sigarr = m_sigma_mf[amrlev][mglev]->const_array(mfi);
auto const& vfrc = volfrac.const_array(mfi);
auto const& vfrc = factory->getVolFrac().const_array(mfi);
AMREX_HOST_DEVICE_FOR_3D(box, i, j, k,
{
mlebndfdlap_sig_gsrb_eb(i,j,k,solarr,rhsarr,levset,dmskarr,AMREX_D_DECL(ecx,ecy,ecz),
Expand Down Expand Up @@ -641,8 +652,10 @@ MLEBNodeFDLaplacian::compGrad (int amrlev, const Array<MultiFab*,AMREX_SPACEDIM>
auto const& dmask = *m_dirichlet_mask[amrlev][mglev];
const auto phieb = m_s_phi_eb;
const auto *factory = dynamic_cast<EBFArrayBoxFactory const*>(m_factory[amrlev][mglev].get());
AMREX_ASSERT(factory);
auto const& edgecent = factory->getEdgeCent();
Array<const MultiCutFab*,AMREX_SPACEDIM> edgecent {AMREX_D_DECL(nullptr,nullptr,nullptr)};
if (factory) {
edgecent = factory->getEdgeCent();
}
#endif

#ifdef AMREX_USE_OMP
Expand All @@ -659,7 +672,7 @@ MLEBNodeFDLaplacian::compGrad (int amrlev, const Array<MultiFab*,AMREX_SPACEDIM>
Array4<Real> const& gpz = grad[2]->array(mfi);)
#ifdef AMREX_USE_EB
Array4<int const> const& dmarr = dmask.const_array(mfi);
bool cutfab = edgecent[0]->ok(mfi);
bool cutfab = edgecent[0] && edgecent[0]->ok(mfi);
AMREX_D_TERM(Array4<Real const> const& ecx
= cutfab ? edgecent[0]->const_array(mfi) : Array4<Real const>{};,
Array4<Real const> const& ecy
Expand Down Expand Up @@ -741,6 +754,7 @@ MLEBNodeFDLaplacian::postSolve (Vector<MultiFab>& sol) const
for (int amrlev = 0; amrlev < m_num_amr_levels; ++amrlev) {
const auto phieb = m_s_phi_eb;
const auto *factory = dynamic_cast<EBFArrayBoxFactory const*>(m_factory[amrlev][0].get());
if (!factory) { return; }
auto const& levset_mf = factory->getLevelSet();
auto const& levset_ar = levset_mf.const_arrays();
MultiFab& mf = sol[amrlev];
Expand Down

0 comments on commit b82296f

Please sign in to comment.