Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix create_submesh by generalising sub index map creation #2890

Merged
merged 110 commits into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from 97 commits
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
d6fa63a
Add function to compute submap indices
jpdean Nov 1, 2023
07fcad6
Compute submap offset
jpdean Nov 1, 2023
1e2e827
Compute submap sources
jpdean Nov 1, 2023
8ab92f2
Fix type
jpdean Nov 1, 2023
5343edb
Compute submap dest ranks
jpdean Nov 1, 2023
6cda53f
Document
jpdean Nov 1, 2023
21f5da9
Compute submap ghost indices
jpdean Nov 1, 2023
027be30
Simplify
jpdean Nov 1, 2023
8965bc2
Compute sub imap to imap
jpdean Nov 1, 2023
9bf0137
Return imap and map
jpdean Nov 1, 2023
ed08b5d
Merge branch 'main' into jpdean/fix_submesh
jpdean Nov 6, 2023
cbf36d0
Fix typos
jpdean Nov 6, 2023
2654251
Add test
jpdean Nov 6, 2023
53648ba
Use new create submap in topology creation
jpdean Nov 7, 2023
b6723c9
Use new create submap in geometry creation
jpdean Nov 7, 2023
6fcdaba
format
jpdean Nov 7, 2023
b14939b
Start on posisble fix
jpdean Nov 7, 2023
490efe1
Fix computation of global index when vertices change owner
jpdean Nov 7, 2023
ff8426a
Mention indices must be sorted
jpdean Nov 7, 2023
e105934
Fix computaion of local indices
jpdean Nov 8, 2023
070f995
Add temporary fix
jpdean Nov 8, 2023
f36d0d8
Comment cout
jpdean Nov 8, 2023
5f0d043
Add TODO
jpdean Nov 8, 2023
4b54e1c
Sort submap owned
jpdean Nov 9, 2023
69bb7db
Debugging
jpdean Nov 10, 2023
06dab30
Fix bug where ghosts ordering got the wrong submap index
jpdean Nov 13, 2023
b19baff
Merge branch 'main' into jpdean/fix_submesh
jpdean Nov 13, 2023
d11f184
Tidy
jpdean Nov 14, 2023
4bf992b
Improve test
jpdean Nov 14, 2023
ce5ecaf
Remove TODO
jpdean Nov 15, 2023
083ab0e
Don't move
jpdean Nov 15, 2023
2973b08
Add back moves for now
jpdean Nov 15, 2023
beb86f7
Update cpp/dolfinx/common/IndexMap.cpp
jpdean Nov 15, 2023
04b88b5
Improve docs
jpdean Nov 15, 2023
f5123fc
Use span
jpdean Nov 15, 2023
87e3ea9
Get comm from imap
jpdean Nov 15, 2023
fecf9e2
Improve docs
jpdean Nov 15, 2023
af0fbbe
Use std::for_each
jpdean Nov 15, 2023
c10ff3a
Use std::size_t
jpdean Nov 15, 2023
a8ec0cd
Style change
jpdean Nov 15, 2023
5631300
Fix spacing
jpdean Nov 15, 2023
57a6539
Move initialisation
jpdean Nov 15, 2023
0de942b
Initialise in if statement
jpdean Nov 15, 2023
8df44a1
Use span
jpdean Nov 15, 2023
c67d22a
Improve clarity
jpdean Nov 15, 2023
b4c2569
Start working on scoping
jpdean Nov 15, 2023
aa0b113
More scoping
jpdean Nov 15, 2023
8c298d2
More scoping
jpdean Nov 15, 2023
87fc43f
Merge branch 'main' into jpdean/fix_submesh
jpdean Nov 15, 2023
37a3ae0
More scoping
jpdean Nov 15, 2023
d3f52d4
Rename comms
jpdean Nov 15, 2023
532ee95
comm names
jpdean Nov 17, 2023
3dbcb97
Make free function
jpdean Nov 17, 2023
ed4bb6e
Update docs
jpdean Nov 17, 2023
3c9df33
Extract function
jpdean Nov 17, 2023
287e735
Use function
jpdean Nov 17, 2023
104bf22
Use function
jpdean Nov 17, 2023
76a8077
Start work on replacing old version
jpdean Nov 20, 2023
2e3e6b0
Merge branch 'main' into jpdean/fix_submesh
jpdean Nov 20, 2023
eec7b96
Start work on removing old version
jpdean Nov 23, 2023
9fd6f03
More work
jpdean Nov 23, 2023
c25a931
Add todo
jpdean Nov 23, 2023
a284e70
Comment some things
jpdean Dec 4, 2023
491661e
Merge branch 'main' into jpdean/fix_submesh
jpdean Dec 4, 2023
da0884a
Fix for bs > 1
jpdean Dec 5, 2023
ff58871
Tidy
jpdean Dec 5, 2023
b0ac774
Tidy
jpdean Dec 5, 2023
c971174
Merge branch 'main' into jpdean/fix_submesh
jpdean Dec 5, 2023
c0f4d70
Use different approach
jpdean Dec 5, 2023
bac7d03
Revert "Tidy"
jpdean Dec 5, 2023
de5c7b3
Fix array size
jpdean Dec 5, 2023
4cc5dc3
Try using map
jpdean Dec 7, 2023
c0b72e7
Fix array size
jpdean Dec 7, 2023
0072d06
Revert "Fix array size"
jpdean Dec 7, 2023
712f441
Revert "Try using map"
jpdean Dec 7, 2023
fdf26f0
Tidy
jpdean Dec 8, 2023
0f0beb3
Merge branch 'main' into jpdean/fix_submesh
jpdean Dec 8, 2023
12607cb
Tidy
jpdean Dec 8, 2023
d18a2e6
Tidy
jpdean Dec 8, 2023
c589ffe
Add option to allow owner to change
jpdean Dec 8, 2023
93f131d
Remove create submap
jpdean Dec 8, 2023
d4fbd43
Remove unused import
jpdean Dec 8, 2023
0c037cf
Remove shrink_to_fit
jpdean Dec 8, 2023
6b4b1ed
Add param
jpdean Dec 8, 2023
d49884f
Rename
jpdean Dec 8, 2023
0f75497
Use non-blocking comm
jpdean Dec 15, 2023
f3967c3
Remove NBX
jpdean Dec 15, 2023
49ff4ff
Tidy
jpdean Dec 15, 2023
3aad608
Tidy
jpdean Dec 15, 2023
7384371
Tidy
jpdean Dec 15, 2023
1c0d032
Tidy
jpdean Dec 15, 2023
10a97f7
Use more efficient constructor for index map
jpdean Dec 15, 2023
382f229
Merge branch 'main' into jpdean/fix_submesh
jpdean Dec 15, 2023
79f5f8b
Add docs
jpdean Dec 15, 2023
82fa3a8
Change name
jpdean Dec 15, 2023
3683712
Improve description
jpdean Dec 15, 2023
f1645a9
Work on docs
garth-wells Dec 18, 2023
8cd900c
Consistency fix
garth-wells Dec 19, 2023
16fe9a6
Remove std::map
garth-wells Dec 19, 2023
e906b0c
Tidy up
garth-wells Dec 19, 2023
6aae46a
Remove a map
garth-wells Dec 19, 2023
3640a3c
Simplifications and fixes
garth-wells Dec 19, 2023
60c50b3
Simplify
garth-wells Dec 19, 2023
3b761cd
Improvements
garth-wells Dec 19, 2023
66c05ad
Small fix for docs
garth-wells Dec 19, 2023
5fab0e1
Updates
garth-wells Dec 19, 2023
a56c51f
Doc improvements
garth-wells Dec 26, 2023
add4f4d
Merge branch 'main' into jpdean/fix_submesh
garth-wells Jan 1, 2024
8a102ae
Improve docs
jpdean Jan 2, 2024
9faa926
Improve comments
jpdean Jan 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
600 changes: 429 additions & 171 deletions cpp/dolfinx/common/IndexMap.cpp

Large diffs are not rendered by default.

37 changes: 21 additions & 16 deletions cpp/dolfinx/common/IndexMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,27 @@ stack_index_maps(
const std::vector<
std::pair<std::reference_wrapper<const common::IndexMap>, int>>& maps);

/// @brief Create a new index map from a subset of indices in an
/// existing index map.
///
/// @param[in] imap Parent map to create a new sub-map from.
/// @param[in] indices Local indices in `imap` (owned and ghost) to
/// include in the new index map.
/// @param[in] allow_owner_change If `true`, indices that are not
/// included in `indices` by their owning process can be included in
/// `indices` by processes that ghost the indices to be included in the
/// new submap. These indices will be owned by one of the sharing
/// processes in the submap. If `false`, and exception is raised if an
/// index is included by a sharing process and not by the owning
/// process.
/// @return The (i) new index map and (ii) a map from local indices in
/// the submap to local indices in the original (this) map.
/// @pre `indices` must be sorted and must not contain duplicates.
std::pair<IndexMap, std::vector<std::int32_t>>
create_sub_index_map(const IndexMap& imap,
std::span<const std::int32_t> indices,
bool allow_owner_change = false);

/// This class represents the distribution index arrays across
/// processes. An index array is a contiguous collection of N+1 indices
/// [0, 1, . . ., N] that are distributed across M processes. On a given
Expand Down Expand Up @@ -173,22 +194,6 @@ class IndexMap
/// index is `owners()[i]`.
const std::vector<int>& owners() const { return _owners; }

/// @brief Create new index map from a subset of indices in this index
/// map.
///
/// The order of the owned indices is preserved, with new map
/// effectively a 'compressed' map.
///
/// @param[in] indices Local indices in the map that should appear in
/// the new index map. All indices must be owned, i.e. indices must be
/// less than `this->size_local()`.
/// @pre `indices` must be sorted and contain no duplicates.
/// @return The (i) new index map and (ii) a map from the ghost
/// position in the new map to the ghost position in the original
/// (this) map
std::pair<IndexMap, std::vector<std::int32_t>>
create_submap(std::span<const std::int32_t> indices) const;

/// @todo Aim to remove this function?
///
/// @brief Compute map from each local (owned) index to the set of
Expand Down
50 changes: 17 additions & 33 deletions cpp/dolfinx/fem/DofMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,59 +50,43 @@ fem::DofMap build_collapsed_dofmap(const DofMap& dofmap_view,
dofs_view.erase(std::unique(dofs_view.begin(), dofs_view.end()),
dofs_view.end());

// Compute sizes
const std::int32_t num_owned_view = dofmap_view.index_map->size_local();

// Get block size
int bs_view = dofmap_view.index_map_bs();

const auto it = std::lower_bound(dofs_view.begin(), dofs_view.end(),
bs_view * num_owned_view);

// Create sub-index map
std::shared_ptr<common::IndexMap> index_map;
std::vector<std::int32_t> ghost_new_to_old;
// Map from indices in the sub-index map to indices in the original
// index map
std::vector<std::int32_t> sub_imap_to_imap;
if (bs_view == 1)
{
std::span<std::int32_t> indices(dofs_view.data(),
std::distance(dofs_view.begin(), it));
auto [_index_map, gmap] = dofmap_view.index_map->create_submap(indices);
auto [_index_map, _sub_imap_to_imap] = dolfinx::common::create_sub_index_map(
*dofmap_view.index_map, dofs_view);
index_map = std::make_shared<common::IndexMap>(std::move(_index_map));
ghost_new_to_old = std::move(gmap);
sub_imap_to_imap = std::move(_sub_imap_to_imap);
}
else
{
std::vector<std::int32_t> indices;
indices.reserve(dofs_view.size());
std::transform(dofs_view.begin(), it, std::back_inserter(indices),
std::transform(dofs_view.begin(), dofs_view.end(),
std::back_inserter(indices),
[bs_view](auto idx) { return idx / bs_view; });
indices.erase(std::unique(indices.begin(), indices.end()), indices.end());
auto [_index_map, gmap] = dofmap_view.index_map->create_submap(indices);
auto [_index_map, _sub_imap_to_imap]
= dolfinx::common::create_sub_index_map(*dofmap_view.index_map, indices);
index_map = std::make_shared<common::IndexMap>(std::move(_index_map));
ghost_new_to_old = std::move(gmap);
sub_imap_to_imap = std::move(_sub_imap_to_imap);
}

// Create map from dof in view to new dof index
// Create a map from old dofs to new dofs
std::vector<std::int32_t> old_to_new(dofs_view.back() + bs_view, -1);
for (std::size_t new_idx = 0; new_idx < sub_imap_to_imap.size(); ++new_idx)
{
// old-to-new map for owned dofs
std::int32_t count = 0;
for (auto dof_old = dofs_view.begin(); dof_old != it; ++dof_old)
old_to_new[*dof_old] = count++;

// old-to-new map for ghost dofs
const std::int32_t local_size_new = index_map->size_local();
for (auto itp_old = ghost_new_to_old.begin();
itp_old != ghost_new_to_old.end(); ++itp_old)
for (int k = 0; k < bs_view; ++k)
{
std::int32_t map_pos_new
= local_size_new + std::distance(ghost_new_to_old.begin(), itp_old);
std::int32_t idx = bs_view * (num_owned_view + *itp_old);
for (int k = 0; k < bs_view; ++k)
{
assert(idx + k < (int)old_to_new.size());
old_to_new[idx + k] = map_pos_new;
}
std::int32_t old_idx = sub_imap_to_imap[new_idx] * bs_view + k;
assert(old_idx < (int)old_to_new.size());
old_to_new[old_idx] = new_idx;
}
}

Expand Down
15 changes: 4 additions & 11 deletions cpp/dolfinx/mesh/Geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -328,22 +328,15 @@ create_subgeometry(const Topology& topology, const Geometry<T>& geometry,
// Get the sub-geometry dofs owned by this process
auto x_index_map = geometry.index_map();
assert(x_index_map);
std::vector<std::int32_t> subx_to_x_dofmap
= common::compute_owned_indices(sub_x_dofs, *x_index_map);

std::shared_ptr<common::IndexMap> sub_x_dof_index_map;
std::vector<std::int32_t> subx_to_x_dofmap;
{
std::pair<common::IndexMap, std::vector<int32_t>> map_data
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could std::tie make this code easier to read and avoid the std::move at the end of the scope?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, unless I'm missing something

= x_index_map->create_submap(subx_to_x_dofmap);
= dolfinx::common::create_sub_index_map(*x_index_map, sub_x_dofs, true);
sub_x_dof_index_map
= std::make_shared<common::IndexMap>(std::move(map_data.first));

// Create a map from the dofs in the sub-geometry to the geometry
subx_to_x_dofmap.reserve(sub_x_dof_index_map->size_local()
+ sub_x_dof_index_map->num_ghosts());
std::transform(map_data.second.begin(), map_data.second.end(),
std::back_inserter(subx_to_x_dofmap),
[offset = x_index_map->size_local()](auto x_dof_index)
{ return offset + x_dof_index; });
subx_to_x_dofmap = std::move(map_data.second);
}

// Create sub-geometry coordinates
Expand Down
46 changes: 14 additions & 32 deletions cpp/dolfinx/mesh/Topology.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1160,32 +1160,23 @@ mesh::create_subtopology(const Topology& topology, int dim,
// TODO Call common::get_owned_indices here? Do we want to
// support `entities` possibly having a ghost on one process that is
// not in `entities` on the owning process?
// TODO: Should entities still be ghosted in the sub-topology even if
// they are not in the `entities` list? If this is not desirable,
// create_submap needs to be changed

// Create a map from an entity in the sub-topology to the
// corresponding entity in the topology, and create an index map
std::vector<int32_t> subentities;
std::shared_ptr<common::IndexMap> submap;
std::vector<int32_t> subentities;
{
// Entities in the sub-topology that are owned by this process
auto entity_map = topology.index_map(dim);
assert(entity_map);
std::copy_if(
entities.begin(), entities.end(), std::back_inserter(subentities),
[size = entity_map->size_local()](std::int32_t e) { return e < size; });

// FIXME Make this an input requirement?
std::vector<std::int32_t> unique_entities(entities.begin(), entities.end());
std::sort(unique_entities.begin(), unique_entities.end());
unique_entities.erase(
std::unique(unique_entities.begin(), unique_entities.end()),
unique_entities.end());
std::pair<common::IndexMap, std::vector<int32_t>> map_data
= entity_map->create_submap(subentities);
= dolfinx::common::create_sub_index_map(*topology.index_map(dim),
unique_entities);
submap = std::make_shared<common::IndexMap>(std::move(map_data.first));

// Add ghost entities to subentities
subentities.reserve(submap->size_local() + submap->num_ghosts());
std::transform(map_data.second.begin(), map_data.second.end(),
std::back_inserter(subentities),
[offset = entity_map->size_local()](auto entity_index)
{ return offset + entity_index; });
subentities = std::move(map_data.second);
}

// Get the vertices in the sub-topology. Use subentities
Expand All @@ -1195,26 +1186,17 @@ mesh::create_subtopology(const Topology& topology, int dim,
// Get the vertices in the sub-topology owned by this process
auto map0 = topology.index_map(0);
assert(map0);
std::vector<std::int32_t> indices
= compute_incident_entities(topology, subentities, dim, 0);
std::sort(indices.begin(), indices.end());
std::vector<std::int32_t> subvertices0
= common::compute_owned_indices(indices, *map0);

// Create map from the vertices in the sub-topology to the vertices in the
// parent topology, and an index map
std::shared_ptr<common::IndexMap> submap0;
std::vector<int32_t> subvertices0;
{
std::pair<common::IndexMap, std::vector<int32_t>> map_data
garth-wells marked this conversation as resolved.
Show resolved Hide resolved
= map0->create_submap(subvertices0);
= dolfinx::common::create_sub_index_map(
*map0, compute_incident_entities(topology, subentities, dim, 0), true);
submap0 = std::make_shared<common::IndexMap>(std::move(map_data.first));

// Add ghost vertices to the map
subvertices0.reserve(submap0->size_local() + submap0->num_ghosts());
std::transform(map_data.second.begin(), map_data.second.end(),
std::back_inserter(subvertices0),
[offset = map0->size_local()](std::int32_t vertex_index)
{ return offset + vertex_index; });
subvertices0 = std::move(map_data.second);
}

// Sub-topology vertex-to-vertex connectivity (identity)
Expand Down
27 changes: 14 additions & 13 deletions python/dolfinx/wrappers/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,19 +133,7 @@ void common(nb::module_& m)
std::span<std::int64_t>(global.data(), global.size()));
return global;
},
nb::arg("local"))
.def(
"create_submap",
[](const dolfinx::common::IndexMap& self,
nb::ndarray<const std::int32_t, nb::ndim<1>, nb::c_contig>
entities)
{
auto [map, ghosts] = self.create_submap(
std::span(entities.data(), entities.size()));
return std::pair(std::move(map),
dolfinx_wrappers::as_nbarray(std::move(ghosts)));
},
nb::arg("entities"));
nb::arg("local"));

// dolfinx::common::Timer
nb::class_<dolfinx::common::Timer>(m, "Timer", "Timer class")
Expand Down Expand Up @@ -184,5 +172,18 @@ void common(nb::module_& m)
dolfinx::init_logging(args.size(), argv.data());
},
nb::arg("args"));

m.def(
"create_sub_index_map",
[](const dolfinx::common::IndexMap& imap,
nb::ndarray<const std::int32_t, nb::ndim<1>, nb::c_contig> indices,
bool allow_owner_change)
{
auto [map, submap_to_map] = dolfinx::common::create_sub_index_map(
imap, std::span(indices.data(), indices.size()), allow_owner_change);
return std::pair(std::move(map), dolfinx_wrappers::as_nbarray(
std::move(submap_to_map)));
},
nb::arg("index_map"), nb::arg("indices"), nb::arg("allow_owner_change"));
}
} // namespace dolfinx_wrappers
Loading
Loading