Skip to content

Commit 8b2c4be

Browse files
jpdeanjorgensdgarth-wells
authored
Simplify mixed-domain interface (#3780)
* Add entity map c++ version * Fix segfault with empty entity map * Only use topology in `entitymap` * Update tests and demo to use new entity map * Fix type hint and docs * Fix list input * Update mesh independent form as well * Fix doc build errors * Update * Update test * Update * Reorder * Type * Type comarison * Reorder * Type conversion * Comments * Ruff * Update demo * Add checks to assembler * Same for sparsity pattern * Format * Add test * Format * format * Tidy * Docs * Get test passing * Remove constructor and get tests passing * Start replacing function * Replace function * Remove function * Remove function * Ruff * Ruff * Remove second list * Return type * Rename * Format * Use ranges * Use ranges * Simplify logic * Simplify logic * Tidy * Simplify * Tidy * Tidy * Format * Docs * Docs * Let the entity map do the map * Ruff * Tidy up * Update cpp/dolfinx/mesh/EntityMap.h Co-authored-by: Jørgen Schartum Dokken <dokken92@gmail.com> * Update cpp/dolfinx/mesh/EntityMap.h Co-authored-by: Jørgen Schartum Dokken <dokken92@gmail.com> * Start wrapping EntityMap * More wrapping * Wrapping * Ruff * Docs * Fix type * Docs * Update cpp/dolfinx/fem/Form.h Co-authored-by: Garth N. Wells <gnw20@cam.ac.uk> * Update cpp/dolfinx/fem/Form.h Co-authored-by: Garth N. Wells <gnw20@cam.ac.uk> * Update cpp/dolfinx/fem/Form.h Co-authored-by: Garth N. Wells <gnw20@cam.ac.uk> * Docs * Update cpp/dolfinx/fem/Form.h Co-authored-by: Garth N. Wells <gnw20@cam.ac.uk> * Docs * Improve docs * Use inline if * Improve docs * Change name * Remove static cast * Add curly braces * Don't pass shared pointer * Improve docs * Improve docs * Docs * Docs and improve names * int type * Improve docs * Pass const ref * Pass const ref not shared ptr * Use insert * Docs * Use insert * Docs * Typo * Docs * Improve docs * Docs * Fix bug * Start on create_submesh returning entity map * Scoping * Reorder * Improve comment * Update * Update python binding * Update test * Rename * Update tests * Update demo * Ruff * Fix tests * Get tests to pass * Temporary hack to get docs to build (what is going on here?) * Revert "Temporary hack to get docs to build (what is going on here?)" This reverts commit fcbe919. * Temporary hack to get the docs to build * Fix demo * Ruff * Mypy * Update test * Give entity map a dim * Fix docs * Use EntityMap for geom and vertex maps * Don't use EntityMap for the geometry * Fix type * Tidy * Docs * Simplify * Mention bidirectional * Split declaration and implementation * Docs * Improve docs * Improve docs * Remove static casts * Improve docs * DOcs * Remove unused includes * Docs * Docs * Start refactoring * Remove function * More refactoring * Refactor * More work * Add funcs to get topos * Add functions * Remove unused code * Change function * Replace funciton * Simplify code * More simplificaitons * Tidy * Remove func * Check form mesh is present * Remove contains * Docs * Docs * Remove functions * Format * Update * Update * Comment * Tidy * Docs * Bind dim * Bind topo and sub topo * Format * Small updates * Docs * Docs * Remove commented code * Use ref wrapper in place of shared_ptr * Work around for reference wrappers in nanobind * Minor edits * Restrict captures * Update assemble vector * Updates for apply lifting * Simplify * More updates * Change size * Fix size bug * Work on test * Fix bug in test * Work on test * Test matrix bc * Same for vector * Change space * Lint * Fix test * Change space * Test apply lifting * clang-tidy * Update test * Remove TODO * mypy fixes * Simplify typing * Fix merge * Fix import issue * Doc and typing fixes * Fix import * Simplify demo * Simplify * Small simplification --------- Co-authored-by: Jørgen S. Dokken <dokken@simula.no> Co-authored-by: Jørgen Schartum Dokken <dokken92@gmail.com> Co-authored-by: Garth N. Wells <gnw20@cam.ac.uk>
1 parent 89fb14a commit 8b2c4be

28 files changed

+990
-492
lines changed

cpp/demo/codim_0_assembly/main.cpp

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <dolfinx/fem/petsc.h>
1515
#include <dolfinx/la/MatrixCSR.h>
1616
#include <dolfinx/la/SparsityPattern.h>
17+
#include <dolfinx/mesh/EntityMap.h>
1718
#include <map>
1819
#include <memory>
1920
#include <ranges>
@@ -76,37 +77,25 @@ int main(int argc, char* argv[])
7677
mesh::MeshTags<std::int32_t> cell_marker(mesh->topology(), tdim, cells,
7778
values);
7879

79-
std::shared_ptr<mesh::Mesh<U>> submesh;
80-
std::vector<std::int32_t> submesh_to_mesh;
80+
// We create a submesh consisting of only cells with a given tag by
81+
// calling `create_submesh`. This function also returns an
82+
// `EntityMap` object, which relates entities in the submesh to
83+
// entities in the original mesh. We will need this to assemble our
84+
// mixed-domain form.
85+
auto submesh_data = [](auto& mesh, int tdim, auto&& subcells)
8186
{
82-
auto [_submesh, _submesh_to_mesh, v_map, g_map]
83-
= mesh::create_submesh(*mesh, tdim, cell_marker.find(2));
84-
submesh = std::make_shared<mesh::Mesh<U>>(std::move(_submesh));
85-
submesh_to_mesh = std::move(_submesh_to_mesh);
86-
}
87+
auto [submesh, emap, v_map, g_map]
88+
= mesh::create_submesh(mesh, tdim, subcells);
89+
return std::pair(std::make_shared<mesh::Mesh<U>>(std::move(submesh)),
90+
std::move(emap));
91+
};
92+
auto [submesh, entity_map] = submesh_data(*mesh, tdim, cell_marker.find(2));
8793

8894
// We create the function space used for the trial space
8995
auto W
9096
= std::make_shared<fem::FunctionSpace<U>>(fem::create_functionspace<U>(
9197
submesh, std::make_shared<fem::FiniteElement<U>>(element)));
9298

93-
// A mixed-domain form has functions defined over different meshes.
94-
// The mesh associated with the measure (dx, ds, etc.) is called the
95-
// integration domain. To assemble mixed-domain forms, maps must be
96-
// provided taking entities in the integration domain to entities on
97-
// each mesh in the form. Since one of our forms has a measure
98-
// defined over `mesh` and involves a function defined over
99-
// `submesh`, we must provide a map from entities in `mesh` to
100-
// entities in `submesh`. This is simply the "inverse" of
101-
// `submesh_to_mesh`.
102-
std::vector<std::int32_t> mesh_to_submesh(num_cells_local, -1);
103-
for (std::size_t i = 0; i < submesh_to_mesh.size(); ++i)
104-
mesh_to_submesh[submesh_to_mesh[i]] = i;
105-
106-
std::map<std::shared_ptr<const mesh::Mesh<U>>,
107-
std::span<const std::int32_t>>
108-
entity_maps = {{submesh, mesh_to_submesh}};
109-
11099
// Next we compute the integration entities on the integration
111100
// domain `mesh`
112101
std::vector<std::int32_t> integration_entities
@@ -118,10 +107,21 @@ int main(int argc, char* argv[])
118107
subdomain_data
119108
= {{fem::IntegralType::cell, {{3, integration_entities}}}};
120109

110+
// A mixed-domain form involves functions defined over multiple
111+
// meshes. The mesh passed to `create_form` is called the
112+
// *integration domain mesh*. To assemble a mixed-domain form, we
113+
// must supply an `EntityMap` for each additional mesh involved in
114+
// the form, relating entities in that mesh to the integration
115+
// domain mesh. In our case, `mesh` is the integration domain mesh,
116+
// and the only other mesh in our form is `submesh`. Hence, we must
117+
// provide the entity map object returned when we called
118+
// `create_submesh`, which relates entities in `submesh` to entities
119+
// in `mesh`.
120+
//
121121
// We can now create the bilinear form
122122
fem::Form<T> a_mixed
123123
= fem::create_form<T>(*form_mixed_codim0_a_mixed, {V, W}, {}, {},
124-
subdomain_data, entity_maps, V->mesh());
124+
subdomain_data, {entity_map}, V->mesh());
125125

126126
la::SparsityPattern sp_mixed = fem::create_sparsity_pattern(a_mixed);
127127
sp_mixed.finalize();

cpp/demo/mixed_poisson/main.cpp

Lines changed: 24 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -207,19 +207,20 @@ int main(int argc, char* argv[])
207207

208208
// We'd like to represent `u_0` using a function space defined only
209209
// on the facets in `dfacets`. To do so, we begin by calling
210-
// `create_submesh` to get a `submesh` of those facets. It also
211-
// returns a map `submesh_to_mesh` whose `i`th entry is the facet in
212-
// mesh corresponding to cell `i` in submesh.
210+
// `create_submesh` to get a `submesh` of those facets. It also returns an
211+
// `EntityMap` object, which relates entities in the submesh to entities in
212+
// the original mesh. We will need this to assemble our mixed-domain form.
213213
int tdim = mesh->topology()->dim();
214214
int fdim = tdim - 1;
215-
std::shared_ptr<mesh::Mesh<U>> submesh;
216-
std::vector<std::int32_t> submesh_to_mesh;
215+
216+
auto submesh_data = [](auto& mesh, int tdim, auto&& dfacets)
217217
{
218-
auto [_submesh, _submesh_to_mesh, v_map, g_map]
219-
= mesh::create_submesh(*mesh, fdim, dfacets);
220-
submesh = std::make_shared<mesh::Mesh<U>>(std::move(_submesh));
221-
submesh_to_mesh = std::move(_submesh_to_mesh);
222-
}
218+
auto [submesh, e_map, v_map, g_map]
219+
= mesh::create_submesh(mesh, tdim, dfacets);
220+
return std::pair(std::make_shared<mesh::Mesh<U>>(std::move(submesh)),
221+
std::move(e_map));
222+
};
223+
auto [submesh, entity_map] = submesh_data(*mesh, fdim, dfacets);
223224

224225
// Create an element for `u_0`
225226
basix::cell::type submesh_cell_type
@@ -283,35 +284,25 @@ int main(int argc, char* argv[])
283284
subdomain_data{{fem::IntegralType::exterior_facet, {{1, domains}}}};
284285

285286
// Since we are doing a `ds(1)` integral on mesh and `u0` is defined
286-
// on the `submesh`, we must provide an "entity map" relating cells
287-
// in `submesh` to entities in `mesh`. This is simply the "inverse"
288-
// of `submesh_to_mesh`:
289-
auto facet_imap = mesh->topology()->index_map(fdim);
290-
assert(facet_imap);
291-
std::size_t num_facets = mesh->topology()->index_map(fdim)->size_local()
292-
+ mesh->topology()->index_map(fdim)->num_ghosts();
293-
// Since not all facets in the mesh appear in the submesh, `submesh_to_mesh`
294-
// is only injective. We therefore map nonexistent facets to -1 when
295-
// creating the "inverse" map mesh_to_submesh
296-
std::vector<std::int32_t> mesh_to_submesh(num_facets, -1);
297-
for (std::size_t i = 0; i < submesh_to_mesh.size(); ++i)
298-
mesh_to_submesh[submesh_to_mesh[i]] = i;
299-
300-
// Create the entity map to pass to `create_form`
301-
std::map<std::shared_ptr<const mesh::Mesh<U>>,
302-
std::span<const std::int32_t>>
303-
entity_maps = {{submesh, mesh_to_submesh}};
287+
// on the `submesh`, our form involves more than one mesh. The mesh
288+
// used to define the measure and passed to `create_form` is called
289+
// the integration domain mesh (here, `mesh`). To assemble our
290+
// mixed-domain form, we must provide an `EntityMap` for each
291+
// additional mesh in the form. In this case, the only other mesh is
292+
// `submesh`. Hence, we supply the entity map returned from
293+
// `create_submesh`, which relates entities in `mesh` and `submesh`.
304294

305295
// Define variational forms and attach he required data
306296
fem::Form<T> a = fem::create_form<T>(*form_mixed_poisson_a, {V, V}, {}, {},
307297
subdomain_data, {});
308-
// Since this form involves multiple domains (i.e. both `mesh` and `submesh`
309-
// for the boundary condition), we must pass the entity maps just created.
310-
// We must also tell the form which domain to integrate with respect to (in
311-
// this case `mesh`)
298+
299+
// Since this form involves multiple domains (i.e. both `mesh` and
300+
// `submesh` for the boundary condition), we must pass the entity
301+
// maps just created. We must also tell the form which domain to
302+
// integrate with respect to (in this case `mesh`)
312303
fem::Form<T> L = fem::create_form<T>(
313304
*form_mixed_poisson_L, {V}, {{"f", f}, {"u0", u0}}, {}, subdomain_data,
314-
entity_maps, V->mesh());
305+
{entity_map}, V->mesh());
315306

316307
// Create solution finite element Function
317308
auto u = std::make_shared<fem::Function<T>>(V);

0 commit comments

Comments
 (0)