Skip to content

Commit c6625cd

Browse files
committed
Refactor AmrMesh::MakeNewGrids
The refactor addresses two issues. First, there was a bug when projecting grids during regrid. TagBoxArray might not have enough ghost cells to guarantee proper nesting when the new fine level grows by a lot. Second, it could be very inefficient to use the previous approach of adding extra ghost cells to TagBoxArray for proper nesting. In some users' cases, it may need more than 30 ghost cells. In the new approach, instead of using extra ghost cells, we explicitly add the projected tags outside the TagBoxArray's domain.
1 parent ed0f36a commit c6625cd

File tree

1 file changed

+88
-24
lines changed

1 file changed

+88
-24
lines changed

Src/AmrCore/AMReX_AmrMesh.cpp

Lines changed: 88 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -645,28 +645,8 @@ AmrMesh::MakeNewGrids (int lbase, Real time, int& new_finest, Vector<BoxArray>&
645645
for (int levc = max_crse; levc >= lbase; levc--)
646646
{
647647
int levf = levc+1;
648-
//
649-
// Construct TagBoxArray with sufficient grow factor to contain
650-
// new levels projected down to this level.
651-
//
652-
IntVect ngt = n_error_buf[levc];
653-
BoxArray ba_proj;
654-
if (levf < new_finest)
655-
{
656-
ba_proj = new_grids[levf+1].simplified();
657-
ba_proj.coarsen(ref_ratio[levf]);
658-
ba_proj.growcoarsen(n_proper, ref_ratio[levc]);
659648

660-
BoxArray levcBA = grids[levc].simplified();
661-
int ngrow = 0;
662-
while (!levcBA.contains(ba_proj))
663-
{
664-
levcBA.grow(1);
665-
++ngrow;
666-
}
667-
ngt.max(IntVect(ngrow));
668-
}
669-
TagBoxArray tags(grids[levc],dmap[levc],ngt);
649+
TagBoxArray tags(grids[levc],dmap[levc],n_error_buf[levc]);
670650

671651
//
672652
// Only use error estimation to tag cells for the creation of new grids
@@ -713,12 +693,92 @@ AmrMesh::MakeNewGrids (int lbase, Real time, int& new_finest, Vector<BoxArray>&
713693
ManualTagsPlacement(levc, tags, bf_lev);
714694
//
715695
// If new grids have been constructed above this level, project
716-
// those grids down and tag cells on intersections to ensure
717-
// proper nesting.
696+
// those grids down and tag cells on intersections to ensure proper
697+
// nesting. Note that the projected BoxArray may contain cells
698+
// outside the TagBoxArray's domain. For those, we collect them in
699+
// Vector tag_proj.
718700
//
701+
Vector<IntVect> tags_proj;
719702
if (levf < new_finest) {
720-
ba_proj.coarsen(bf_lev[levc]);
703+
BoxArray ba_tags = tags.boxArray();
704+
BoxList bl_proj = new_grids[levf+1].simplified_list();
705+
auto& bxs = bl_proj.data();
706+
Long nbxs = bl_proj.size();
707+
Vector<Vector<IntVect>> tags_proj_priv(OpenMP::get_max_threads());
708+
Box domain = Geom(levc).Domain();
709+
domain.coarsen(bf_lev[levc]);
710+
auto const& domain_lo = domain.smallEnd();
711+
auto const& domain_hi = domain.bigEnd();
712+
auto const& domain_len = domain.length();
713+
auto const& is_periodic = Geom(levc).isPeriodicArray();
714+
#ifdef AMREX_USE_OMP
715+
#pragma omp parallel
716+
#endif
717+
{
718+
auto& tv = tags_proj_priv[OpenMP::get_thread_num()];
719+
std::vector<std::pair<int,Box>> isects;
720+
BoxList bl(ba_tags.ixType());
721+
BoxList bl2(ba_tags.ixType());
722+
BoxList bltmp;
723+
#ifdef AMREX_USE_OMP
724+
#pragma omp for
725+
#endif
726+
for (Long ibx = 0; ibx < nbxs; ++ibx) {
727+
Box& b = bxs[ibx];
728+
b.coarsen(ref_ratio[levf]);
729+
b.grow(bf_lev[levf]*n_proper);
730+
b.coarsen(ref_ratio[levc]);
731+
b.coarsen(bf_lev[levc]);
732+
733+
ba_tags.intersections(b, isects, false, tags.nGrowVect());
734+
bl.clear();
735+
bl.push_back(b);
736+
for (auto const& kv : isects) {
737+
bl2.clear();
738+
for (auto & btmp : bl) {
739+
amrex::boxDiff(bltmp, btmp, kv.second);
740+
bl2.join(bltmp);
741+
}
742+
std::swap(bl,bl2);
743+
}
744+
for (auto const& bleft : bl) {
745+
amrex::LoopOnCpu(bleft, [&] (IntVect iv)
746+
{
747+
for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
748+
if (iv[idim] < domain_lo[idim]) {
749+
if (is_periodic[idim]) {
750+
iv[idim] += domain_len[idim];
751+
} else {
752+
return;
753+
}
754+
} else if (iv[idim] > domain_hi[idim]) {
755+
if (is_periodic[idim]) {
756+
iv[idim] -= domain_len[idim];
757+
} else {
758+
return;
759+
}
760+
}
761+
}
762+
tv.push_back(iv);
763+
});
764+
}
765+
}
766+
}
767+
768+
BoxArray ba_proj(std::move(bl_proj));
721769
tags.setVal(ba_proj,TagBox::SET);
770+
771+
Long nextra = 0;
772+
for (auto const& tv : tags_proj_priv) {
773+
nextra += tv.size();
774+
}
775+
if (nextra > 0) {
776+
tags_proj.reserve(nextra);
777+
for (auto const& tv : tags_proj_priv) {
778+
tags_proj.insert(std::end(tags_proj), std::begin(tv), std::end(tv));
779+
}
780+
amrex::RemoveDuplicates(tags_proj);
781+
}
722782
}
723783
//
724784
// Map tagged points through periodic boundaries, if any.
@@ -739,6 +799,10 @@ AmrMesh::MakeNewGrids (int lbase, Real time, int& new_finest, Vector<BoxArray>&
739799
tags.collate(tagvec);
740800
tags.clear();
741801

802+
if (!tags_proj.empty()) {
803+
tagvec.insert(tagvec.end(), tags_proj.data(), tags_proj.data()+tags_proj.size());
804+
}
805+
742806
if (!tagvec.empty())
743807
{
744808
//

0 commit comments

Comments
 (0)