Skip to content

Commit e92641d

Browse files
authored
Add Build with Explicit Multi-Level Geometry for EB (#4714)
This PR adds a new `EB2::Build` variant that accepts a `Vector<Geometry>` to explicitly specify the geometry at each AMR level. Unlike the existing Build function that generates coarse levels through automatic coarsening, this version constructs EB data directly from the provided geometries at each level. This is useful for applications that need precise control over domain specification at each AMR level or when coarse levels are not simple coarsenings of the finest level.
1 parent 2a50fc9 commit e92641d

File tree

3 files changed

+102
-5
lines changed

3 files changed

+102
-5
lines changed

Docs/sphinx_documentation/source/EB.rst

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -141,17 +141,23 @@ Given an implicit function object, say :cpp:`f`, we can make a
141141
:cpp:`EB2::IndexSpace`
142142
----------------------
143143

144-
We build :cpp:`EB2::IndexSpace` with a template function
144+
We build :cpp:`EB2::IndexSpace` with one of several functions depending
145+
on the application needs.
145146

146-
.. highlight: c++
147+
**Standard Build with Automatic Coarsening**
148+
149+
.. highlight:: c++
147150

148151
::
149152

150153
template <typename G>
151154
void EB2::Build (const G& gshop, const Geometry& geom,
152155
int required_coarsening_level,
153156
int max_coarsening_level,
154-
int ngrow = 4);
157+
int ngrow = 4,
158+
bool build_coarse_level_by_coarsening = true,
159+
bool extend_domain_face = ExtendDomainFace(),
160+
int num_coarsen_opt = NumCoarsenOpt());
155161

156162
Here the template parameter is a :cpp:`EB2::GeometryShop`. :cpp:`Geometry` (see
157163
section :ref:`sec:basics:geom`) describes the rectangular problem domain and the
@@ -173,12 +179,58 @@ ngrow` parameter specifies the number of ghost cells outside the domain on
173179
required levels. For levels coarser than the required level, no EB data are
174180
generated for ghost cells outside the domain.
175181

176-
The newly built :cpp:`EB2::IndexSpace` is pushed on to a stack. Static function
182+
**Build with Explicit Multi-Level Geometry**
183+
184+
For applications requiring explicit control over the geometry at each AMR level:
185+
186+
.. highlight:: c++
187+
188+
::
189+
190+
template <typename G>
191+
void EB2::Build (const G& gshop, Vector<Geometry> geom,
192+
int ngrow = 4,
193+
bool extend_domain_face = ExtendDomainFace(),
194+
int num_coarsen_opt = NumCoarsenOpt());
195+
196+
This version takes a :cpp:`Vector<Geometry>` where each element corresponds to
197+
the geometry of a specific AMR level. The Vector can be unordered, as it will be
198+
sorted based on :cpp:`numPts`.
199+
Unlike the standard :cpp:`Build` function, coarse level EB data is generated
200+
directly from the provided geometries rather than through automatic coarsening.
201+
This is useful when coarse level domains are not simple coarsenings of the fine
202+
level, or when you need precise control over the domain and mesh spacing at each
203+
level.
204+
205+
**Build from STL File**
206+
207+
As mentioned earlier, the EB information can alternatively be initialized from
208+
an STL file using:
209+
210+
.. highlight:: c++
211+
212+
::
213+
214+
void EB2::Build (const Geometry& geom,
215+
int required_coarsening_level,
216+
int max_coarsening_level,
217+
int ngrow = 4,
218+
bool build_coarse_level_by_coarsening = true,
219+
bool extend_domain_face = ExtendDomainFace(),
220+
int num_coarsen_opt = NumCoarsenOpt());
221+
222+
This requires setting :cpp:`ParmParse` parameters ``eb2.geom_type = stl`` and
223+
``eb2.stl_file`` to specify the STL file path.
224+
225+
**Managing IndexSpace Objects**
226+
227+
Regardless of which :cpp:`Build` variant is used, the newly built
228+
:cpp:`EB2::IndexSpace` is pushed on to a stack. Static function
177229
:cpp:`EB2::IndexSpace::top()` returns a :cpp:`const &` to the new
178230
:cpp:`EB2::IndexSpace` object. We usually only need to build one
179231
:cpp:`EB2::IndexSpace` object. However, if your application needs multiple
180232
:cpp:`EB2::IndexSpace` objects, you can save the pointers for later use. For
181-
simplicity, we assume there is only one `EB2::IndexSpace` object for the rest of
233+
simplicity, we assume there is only one :cpp:`EB2::IndexSpace` object for the rest of
182234
this chapter.
183235

184236
EBFArrayBoxFactory

Src/EB/AMReX_EB2.H

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ public:
8080
int ngrow, bool build_coarse_level_by_coarsening,
8181
bool extend_domain_face, int num_coarsen_opt);
8282

83+
IndexSpaceImp (const G& gshop, const Vector<Geometry>& geom,
84+
int ngrow,
85+
bool extend_domain_face, int num_coarsen_opt);
86+
8387
IndexSpaceImp (IndexSpaceImp<G> const&) = delete;
8488
IndexSpaceImp (IndexSpaceImp<G> &&) = delete;
8589
void operator= (IndexSpaceImp<G> const&) = delete;
@@ -134,6 +138,21 @@ Build (const G& gshop, const Geometry& geom,
134138
num_coarsen_opt));
135139
} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
136140

141+
template <typename G>
142+
void
143+
Build (const G& gshop, Vector<Geometry> geom,
144+
int ngrow = 4,
145+
bool extend_domain_face = ExtendDomainFace(),
146+
int num_coarsen_opt = NumCoarsenOpt())
147+
{
148+
BL_PROFILE("EB2::Initialize()");
149+
std::sort(geom.begin(), geom.end(), [] (Geometry const& a, Geometry const& b) { return a.Domain().numPts() > b.Domain().numPts(); });
150+
IndexSpace::push(new IndexSpaceImp<G>(gshop, geom,
151+
ngrow,
152+
extend_domain_face,
153+
num_coarsen_opt));
154+
} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
155+
137156
void Build (const Geometry& geom,
138157
int required_coarsening_level,
139158
int max_coarsening_level,

Src/EB/AMReX_EB2_IndexSpaceI.H

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,32 @@ IndexSpaceImp<G>::IndexSpaceImp (const G& gshop, const Geometry& geom,
6363
}
6464

6565

66+
template <typename G>
67+
IndexSpaceImp<G>::IndexSpaceImp (const G& gshop, const Vector<Geometry>& geom,
68+
int ngrow,
69+
bool extend_domain_face, int num_coarsen_opt)
70+
: m_gshop(gshop),
71+
m_build_coarse_level_by_coarsening(false),
72+
m_extend_domain_face(extend_domain_face),
73+
m_num_coarsen_opt(num_coarsen_opt)
74+
{
75+
76+
auto nlevels = int(geom.size());
77+
m_gslevel.reserve(nlevels);
78+
79+
for (int ilev = 0; ilev < nlevels; ++ilev)
80+
{
81+
int ng = ngrow;
82+
Geometry cgeom = geom[ilev];
83+
Box cdomain = cgeom.Domain();
84+
m_gslevel.emplace_back(this, gshop, cgeom, EB2::max_grid_size, ng, extend_domain_face,
85+
num_coarsen_opt-ilev);
86+
m_geom.push_back(cgeom);
87+
m_domain.push_back(cdomain);
88+
m_ngrow.push_back(ng);
89+
}
90+
}
91+
6692
template <typename G>
6793
const Level&
6894
IndexSpaceImp<G>::getLevel (const Geometry& geom) const

0 commit comments

Comments
 (0)