Skip to content

Commit 9570c1c

Browse files
authored
EB: First batch of Marching Cubes (#4778)
This adds the marching cubes algorithm of "Efficient implementation of Marching Cubes' cases with topological guarantees" by Lewiner, Lopes, Vieira & Tavares, Journal of Graphics Tools 8(2): pp. 1-15 (2003). The implementation is adapted from the source code available at http://thomas.lewiner.org/publication_page.php%EF%B9%96pubkey=marching_cubes_jgt.html. Given a signed distance function (e.g., from our STL tools), this generates a list of topologically consistent triangles. Every cut cell's EB surfaces are decomposed into up to 9 triangles. There could be multiple cuts and/or volumes in a cell. The cuts are shared faces and edges between neighbor cells are consistent. For debugging purpose, we have also added a function that can save these triangles into a STL file. Future work involves the computation of EB information such as volume fraction, area faction, etc. based on the triangles.
1 parent fde4d98 commit 9570c1c

20 files changed

Lines changed: 3785 additions & 63 deletions

Src/Base/AMReX.H

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,8 @@ namespace amrex
315315
// be moved to the top.
316316
static void push (AMReX* pamrex);
317317

318+
static void push (std::unique_ptr<AMReX> pamrex);
319+
318320
// This erases `pamrex` from the stack.
319321
static void erase (AMReX* pamrex);
320322

Src/Base/AMReX.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,7 @@ amrex::Initialize (int& argc, char**& argv, bool build_parm_parse,
772772

773773
BL_TINY_PROFILE_INITIALIZE();
774774

775-
AMReX::push(new AMReX()); // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
775+
AMReX::push(std::make_unique<AMReX>());
776776
return AMReX::top(); // NOLINT
777777
}
778778

@@ -981,6 +981,12 @@ AMReX::push (AMReX* pamrex)
981981
}
982982
}
983983

984+
void
985+
AMReX::push (std::unique_ptr<AMReX> pamrex)
986+
{
987+
m_instance.push_back(std::move(pamrex));
988+
}
989+
984990
void
985991
AMReX::erase (AMReX* pamrex)
986992
{

Src/EB/AMReX_EB2.H

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ public:
4141
// moved to the top.
4242
static void push (IndexSpace* ispace);
4343

44+
static void push (std::unique_ptr<IndexSpace> ispace);
45+
4446
// This erases `ispace` from the stack.
4547
static void erase (IndexSpace* ispace);
4648

@@ -133,13 +135,11 @@ Build (const G& gshop, const Geometry& geom,
133135
int num_coarsen_opt = NumCoarsenOpt())
134136
{
135137
BL_PROFILE("EB2::Initialize()");
136-
IndexSpace::push(new IndexSpaceImp<G>(gshop, geom,
137-
required_coarsening_level,
138-
max_coarsening_level,
139-
ngrow, build_coarse_level_by_coarsening,
140-
extend_domain_face,
141-
num_coarsen_opt));
142-
} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
138+
IndexSpace::push(std::make_unique<IndexSpaceImp<G>>
139+
(gshop, geom, required_coarsening_level, max_coarsening_level,
140+
ngrow, build_coarse_level_by_coarsening,extend_domain_face,
141+
num_coarsen_opt));
142+
}
143143

144144
/// \ingroup amrex_eb
145145
template <typename G>
@@ -151,11 +151,9 @@ Build (const G& gshop, Vector<Geometry> geom,
151151
{
152152
BL_PROFILE("EB2::Initialize()");
153153
std::sort(geom.begin(), geom.end(), [] (Geometry const& a, Geometry const& b) { return a.Domain().numPts() > b.Domain().numPts(); });
154-
IndexSpace::push(new IndexSpaceImp<G>(gshop, geom,
155-
ngrow,
156-
extend_domain_face,
157-
num_coarsen_opt));
158-
} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
154+
IndexSpace::push(std::make_unique<IndexSpaceImp<G>>
155+
(gshop, geom, ngrow, extend_domain_face, num_coarsen_opt));
156+
}
159157

160158
/// \ingroup amrex_eb
161159
void Build (const Geometry& geom,
@@ -164,7 +162,16 @@ void Build (const Geometry& geom,
164162
int ngrow = 4,
165163
bool build_coarse_level_by_coarsening = true,
166164
bool extend_domain_face = ExtendDomainFace(),
167-
int num_coarsen_opt = NumCoarsenOpt());
165+
int num_coarsen_opt = NumCoarsenOpt(),
166+
bool support_mvmc = false);
167+
168+
void BuildMultiValuedMultiCut (const Geometry& geom,
169+
int required_coarsening_level,
170+
int max_coarsening_level,
171+
int ngrow = 4,
172+
bool build_coarse_level_by_coarsening = true,
173+
bool extend_domain_face = ExtendDomainFace(),
174+
int num_coarsen_opt = NumCoarsenOpt());
168175

169176
void BuildFromChkptFile (std::string const& fname,
170177
const Geometry& geom,

Src/EB/AMReX_EB2.cpp

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
#include <AMReX_EB2.H>
1313
#include <AMReX_EB2_IndexSpace_STL.H>
1414
#include <AMReX_EB2_IndexSpace_chkpt_file.H>
15+
#if (AMREX_SPACEDIM == 3)
16+
# include <AMReX_MarchingCubes.H>
17+
#endif
1518
#include <AMReX_ParmParse.H>
1619
#include <AMReX.H>
1720
#include <algorithm>
@@ -42,6 +45,9 @@ void Initialize ()
4245
void Finalize ()
4346
{
4447
IndexSpace::clear();
48+
#if (AMREX_SPACEDIM == 3)
49+
amrex::MC::Finalize();
50+
#endif
4551
}
4652

4753
bool ExtendDomainFace ()
@@ -67,6 +73,12 @@ IndexSpace::push (IndexSpace* ispace)
6773
}
6874
}
6975

76+
void
77+
IndexSpace::push (std::unique_ptr<IndexSpace> ispace)
78+
{
79+
m_instance.push_back(std::move(ispace));
80+
}
81+
7082
void
7183
IndexSpace::erase (IndexSpace* ispace)
7284
{
@@ -88,12 +100,16 @@ const IndexSpace* TopIndexSpaceIfPresent() noexcept {
88100
void
89101
Build (const Geometry& geom, int required_coarsening_level,
90102
int max_coarsening_level, int ngrow, bool build_coarse_level_by_coarsening,
91-
bool a_extend_domain_face, int a_num_coarsen_opt)
103+
bool a_extend_domain_face, int a_num_coarsen_opt, bool support_mvmc)
92104
{
93105
ParmParse pp("eb2");
94106
std::string geom_type;
95107
pp.get("geom_type", geom_type);
96108

109+
if (amrex::Verbose() && support_mvmc && geom_type != "stl") {
110+
amrex::Warning("EB2:Build: support_mvmc = true is ignored if eb2.geom_type is not stl.");
111+
}
112+
97113
if (geom_type == "all_regular")
98114
{
99115
EB2::AllRegularIF rif;
@@ -223,15 +239,12 @@ Build (const Geometry& geom, int required_coarsening_level,
223239
pp.queryAdd("stl_reverse_normal", stl_reverse_normal);
224240
bool stl_use_bvh = true;
225241
pp.queryAdd("stl_use_bvh", stl_use_bvh);
226-
IndexSpace::push(new IndexSpaceSTL(stl_file, stl_scale, // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
227-
{stl_center[0], stl_center[1], stl_center[2]},
228-
int(stl_reverse_normal),
229-
geom, required_coarsening_level,
230-
max_coarsening_level, ngrow,
231-
build_coarse_level_by_coarsening,
232-
a_extend_domain_face,
233-
a_num_coarsen_opt,
234-
stl_use_bvh));
242+
IndexSpace::push(std::make_unique<IndexSpaceSTL>
243+
(stl_file, stl_scale,
244+
Array<Real,3>{stl_center[0], stl_center[1], stl_center[2]},
245+
int(stl_reverse_normal), geom, required_coarsening_level,
246+
max_coarsening_level, ngrow, build_coarse_level_by_coarsening,
247+
a_extend_domain_face, a_num_coarsen_opt, stl_use_bvh, support_mvmc));
235248
}
236249
else
237250
{
@@ -263,12 +276,10 @@ BuildFromChkptFile (std::string const& fname,
263276
bool a_extend_domain_face)
264277
{
265278
ChkptFile chkpt_file(fname);
266-
IndexSpace::push(new IndexSpaceChkptFile(chkpt_file, // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
267-
geom, required_coarsening_level,
268-
max_coarsening_level, ngrow,
269-
build_coarse_level_by_coarsening,
270-
a_extend_domain_face));
271-
} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
279+
IndexSpace::push(std::make_unique<IndexSpaceChkptFile>
280+
(chkpt_file, geom, required_coarsening_level, max_coarsening_level,
281+
ngrow, build_coarse_level_by_coarsening, a_extend_domain_face));
282+
}
272283

273284
namespace {
274285
int comp_max_crse_level (Box cdomain, const Box& domain)
@@ -299,4 +310,15 @@ maxCoarseningLevel (IndexSpace const* ebis, const Geometry& geom)
299310
return comp_max_crse_level(cdomain,domain);
300311
}
301312

313+
void
314+
BuildMultiValuedMultiCut (const Geometry& geom, int required_coarsening_level,
315+
int max_coarsening_level, int ngrow,
316+
bool build_coarse_level_by_coarsening,
317+
bool a_extend_domain_face, int a_num_coarsen_opt)
318+
{
319+
EB2::Build(geom, required_coarsening_level, max_coarsening_level, ngrow,
320+
build_coarse_level_by_coarsening, a_extend_domain_face,
321+
a_num_coarsen_opt, true);
322+
}
323+
302324
}

Src/EB/AMReX_EB2_IndexSpace_STL.H

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ public:
1919
const Geometry& geom, int required_coarsening_level,
2020
int max_coarsening_level, int ngrow,
2121
bool build_coarse_level_by_coarsening,
22-
bool extend_domain_face, int num_coarsen_opt, bool bvh_optimization);
22+
bool extend_domain_face, int num_coarsen_opt,
23+
bool bvh_optimization, bool support_mvmc);
2324

2425
IndexSpaceSTL (IndexSpaceSTL const&) = delete;
2526
IndexSpaceSTL (IndexSpaceSTL &&) = delete;

Src/EB/AMReX_EB2_IndexSpace_STL.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ IndexSpaceSTL::IndexSpaceSTL (const std::string& stl_file, Real stl_scale,
88
int max_coarsening_level, int ngrow,
99
bool build_coarse_level_by_coarsening,
1010
bool extend_domain_face, int num_coarsen_opt,
11-
bool bvh_optimization)
11+
bool bvh_optimization, bool support_mvmc)
1212
{
1313
Gpu::LaunchSafeGuard lsg(true); // Always use GPU
1414

@@ -31,7 +31,10 @@ IndexSpaceSTL::IndexSpaceSTL (const std::string& stl_file, Real stl_scale,
3131
m_ngrow.push_back(ngrow_finest);
3232
m_stllevel.reserve(max_coarsening_level+1);
3333
m_stllevel.emplace_back(this, stl_tools, geom, EB2::max_grid_size, ngrow_finest,
34-
extend_domain_face, num_coarsen_opt);
34+
extend_domain_face, num_coarsen_opt, support_mvmc);
35+
36+
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(max_coarsening_level == 0 || support_mvmc == false,
37+
"We don't support multiple levels when multi-valued and multi-cut are enabled.");
3538

3639
for (int ilev = 1; ilev <= max_coarsening_level; ++ilev)
3740
{
@@ -56,7 +59,7 @@ IndexSpaceSTL::IndexSpaceSTL (const std::string& stl_file, Real stl_scale,
5659
amrex::Abort("Failed to build required coarse EB level "+std::to_string(ilev));
5760
} else {
5861
m_stllevel.emplace_back(this, stl_tools, cgeom, EB2::max_grid_size, ng,
59-
extend_domain_face, num_coarsen_opt-ilev);
62+
extend_domain_face, num_coarsen_opt-ilev, support_mvmc);
6063
}
6164
} else {
6265
break;

0 commit comments

Comments
 (0)