Add mixed-topology support to locate_dofs_topological#4167
Add mixed-topology support to locate_dofs_topological#4167
locate_dofs_topological#4167Conversation
| throw std::runtime_error("Cell-to-entity connectivity of dimension " | ||
| + std::to_string(tdim) + "->" | ||
| + std::to_string(dim) + " doesn't exist"); |
There was a problem hiding this comment.
| throw std::runtime_error("Cell-to-entity connectivity of dimension " | |
| + std::to_string(tdim) + "->" | |
| + std::to_string(dim) + " doesn't exist"); | |
| throw std::runtime_error(std::format("Cell-to-entity connectivity of dimension {}->{} doesn't exist", tdim, dim)); |
| /// `topology.entity_types(dim)` | ||
| /// @returns A list of `(cell_index, entity_index, cell_type_index)` tuples | ||
| /// for each input entity. `cell_type_index` is the index of the cell type in | ||
| /// `topology.cell_types()`. |
There was a problem hiding this comment.
Heads up, @chrisrichardson is rewriting all of these to have i inputs, as in: #4169
There was a problem hiding this comment.
but not in Topology just yet, so get this merged first!
| const int tdim = topology.dim(); | ||
| auto e_to_c = topology.connectivity(dim, tdim); | ||
| if (!e_to_c) | ||
| std::vector<mesh::CellType> cell_types = topology.cell_types(); |
There was a problem hiding this comment.
| std::vector<mesh::CellType> cell_types = topology.cell_types(); | |
| const std::vector<mesh::CellType>& cell_types = topology.cell_types(); |
| c_to_e_connectivities[i] | ||
| = topology.connectivity({tdim, i}, {dim, entity_type_index}); | ||
|
|
||
| // NOTE: If e_to_c exists, c_to_e should also exist. |
There was a problem hiding this comment.
Is this assumption always true? I didn't think that was the case, i.e. (tdim, 0) exists at construction of a topology, but (0, tdim) does not.
There was a problem hiding this comment.
true - maybe just reword this comment to state that both are required.
There was a problem hiding this comment.
I think, with the current connectivity implementation in FEniCSx, this statement is always true because of the direction I stated it in. Your example, Jørgen, is assuming that the reverse statement also holds, which is not the case. However, I am happy to clarify the comment! The code doesn't actually rely on it anyway, I've included a check just in case!
| // Get connectivities for each cell type. | ||
| std::int32_t num_entities_local = 0; | ||
| bool any_connectivity = false; | ||
| std::vector<std::shared_ptr<const dolfinx::graph::AdjacencyList<int32_t>>> |
There was a problem hiding this comment.
Should we rather use a reserve and pushback?
| { | ||
| auto e_to_c = e_to_c_connectivities[i]; | ||
|
|
||
| if (e_to_c and e_to_c->num_links(e) > 0) |
There was a problem hiding this comment.
Can it happen that an entity is not connected to a cell?, i.e. e_to_c->num_links(e) == 0?
| { | ||
| throw std::runtime_error( | ||
| "Entity " + std::to_string(e) | ||
| + " is not connected to any cells or is out of bounds."); |
There was a problem hiding this comment.
Out of bounds is covered in Line 93 to 99?
| throw std::runtime_error( | ||
| "Entity " + std::to_string(e) | ||
| + " is not connected to any cells or is out of bounds."); |
There was a problem hiding this comment.
| throw std::runtime_error( | |
| "Entity " + std::to_string(e) | |
| + " is not connected to any cells or is out of bounds."); | |
| throw std::runtime_error(std::format("Entity {} is not connected to any cells or is out of bounds.", e)); |
| const std::size_t num_cell_types = topology.cell_types().size(); | ||
| if (num_cell_types != 1) |
There was a problem hiding this comment.
| const std::size_t num_cell_types = topology.cell_types().size(); | |
| if (num_cell_types != 1) | |
| if (topology.cell_types().size() != 1) |
| throw std::runtime_error( | ||
| "Cell-to-entity connectivity has not been computed. Missing dims " | ||
| + std::to_string(tdim) + "->" + std::to_string(dim)); | ||
| throw std::runtime_error("No connectivity from entities of dimension " |
| // the index map into account as they can differ | ||
| const int bs = dofmap.bs(); | ||
| const int element_bs = dofmap.element_dof_layout().block_size(); | ||
| const int bs = dofmaps.front().get().bs(); |
There was a problem hiding this comment.
We should probably add a comment here that the block size of either dofmap should be the same, as pointed out by @chrisrichardson in #4165
| std::span<const std::int32_t> entities, int entity_type_index, bool remote) | ||
| { | ||
| std::vector<mesh::CellType> cell_types = topology.cell_types(); | ||
| const int num_cell_types = cell_types.size(); |
| { | ||
| // Work with blocks | ||
| for (auto [cell, entity_local_index] : entity_indices) | ||
| for (auto [cell, entity_local_index, cell_type_idx] : entity_indices) |
There was a problem hiding this comment.
Should we use c rather than cell to avoid the shadowing warning?
| // dofs | ||
| std::span<const std::int32_t> cell_dofs = dofmap.cell_dofs(cell); | ||
| for (int index : entity_dofs[entity_local_index]) | ||
| std::span<const std::int32_t> cell_dofs |
There was a problem hiding this comment.
Seems like we should call dofmaps[cell_type+idx].get() once rather than twice.
| // found by other processes, e.g. a vertex dof on this process that | ||
| // has no connected facets on the boundary. | ||
| auto map = dofmap.index_map; | ||
| auto map = dofmaps.front().get().index_map; |
There was a problem hiding this comment.
Same here and below, call dofmaps.front().get() once as a separate variable?
jorgensd
left a comment
There was a problem hiding this comment.
Some minor things. In general it looks good!:)
This PR adds mixed-topology support to
locate_dofs_topological.