1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
|
// Copyright (C) 2006-2024 Anders Logg and Garth N. Wells
//
// This file is part of DOLFINx (https://www.fenicsproject.org)
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#pragma once
#include <array>
#include <cstdint>
#include <dolfinx/common/MPI.h>
#include <dolfinx/graph/AdjacencyList.h>
#include <map>
#include <memory>
#include <optional>
#include <span>
#include <tuple>
#include <utility>
#include <vector>
namespace dolfinx::common
{
class IndexMap;
}
namespace dolfinx::mesh
{
enum class CellType : std::int8_t;
/// @brief Topology stores the topology of a mesh, consisting of mesh
/// entities and connectivity (incidence relations for the mesh
/// entities).
///
/// A mesh entity e may be identified globally as a pair `e = (dim, i)`,
/// where dim is the topological dimension and i is the index of the
/// entity within that topological dimension.
///
/// @todo Rework memory management and associated API. Currently, the
/// caching policy is not clear.
class Topology
{
public:
/// @brief Create a mesh topology.
///
/// A Topology represents the connectivity of a mesh. Mesh entities,
/// i.e. vertices, edges, faces and cells, are defined in terms of
/// their vertices. Connectivity represents the relationships between
/// entities, e.g. the cells that are connected to a given edge in the
/// mesh.
///
/// @param[in] cell_types Types of cells.
/// @param[in] vertex_map Index map describing the distribution of
/// mesh vertices.
/// @param[in] cell_maps Index maps describing the distribution of
/// mesh cells for each cell type in `cell_types`.
/// @param[in] cells Cell-to-vertex connectivities for each cell type
/// in `cell_types`.
/// @param[in] original_cell_index Original indices for each cell in
/// `cells`.
Topology(
std::vector<CellType> cell_types,
std::shared_ptr<const common::IndexMap> vertex_map,
std::vector<std::shared_ptr<const common::IndexMap>> cell_maps,
std::vector<std::shared_ptr<graph::AdjacencyList<std::int32_t>>> cells,
const std::optional<std::vector<std::vector<std::int64_t>>>&
original_cell_index
= std::nullopt);
/// Copy constructor
Topology(const Topology& topology) = default;
/// Move constructor
Topology(Topology&& topology) = default;
/// Destructor
~Topology() = default;
/// Assignment
Topology& operator=(const Topology& topology) = delete;
/// Assignment
Topology& operator=(Topology&& topology) = default;
/// @brief Topological dimension of the mesh.
int dim() const noexcept;
/// @brief Entity types in the topology for a given dimension.
/// @param[in] dim Topological dimension.
/// @return Entity types.
const std::vector<CellType>& entity_types(int dim) const;
/// @brief Cell type.
///
/// This function is is for topologies with one cell type only.
///
/// @return Cell type that the topology is for.
CellType cell_type() const;
/// @brief Get the index maps that described the parallel distribution
/// of the mesh entities of a given topological dimension.
///
/// @param[in] dim Topological dimension.
/// @return Index maps, one for each cell type.
std::vector<std::shared_ptr<const common::IndexMap>>
index_maps(int dim) const;
/// @brief Get the IndexMap that described the parallel distribution
/// of the mesh entities.
///
/// @param[in] dim Topological dimension
/// @return Index map for the entities of dimension `dim`. Returns
/// `nullptr` if index map has not been set.
std::shared_ptr<const common::IndexMap> index_map(int dim) const;
/// @brief Get the connectivity from entities of topological dimension
/// `d0` to dimension `d1`.
///
/// The entity type and incident entity type are each described by a
/// pair `(dim, index)`. The index within a topological dimension
/// `dim`, is that of the cell type given in `entity_types(dim)`.
///
/// @param[in] d0 Pair of (topological dimension of entities, index of
/// "entity type" within topological dimension).
/// @param[in] d1 Pair of (topological dimension of entities, index of
/// incident "entity type" within topological dimension).
/// @return AdjacencyList of connectivity from entity type in `d0` to
/// entity types in `d1`, or `nullptr` if not yet computed.
std::shared_ptr<const graph::AdjacencyList<std::int32_t>>
connectivity(std::array<int, 2> d0, std::array<int, 2> d1) const;
/// @brief Return connectivity from entities of dimension `d0` to
/// entities of dimension `d1`. Assumes only one entity type per
/// dimension.
///
/// @param[in] d0 Topological dimension.
/// @param[in] d1 Topological dimension.
/// @return The adjacency list that for each entity of dimension `d0`
/// gives the list of incident entities of dimension `d1`. Returns
/// `nullptr` if connectivity has not been computed.
std::shared_ptr<const graph::AdjacencyList<std::int32_t>>
connectivity(int d0, int d1) const;
/// @brief Returns the permutation information.
const std::vector<std::uint32_t>& get_cell_permutation_info() const;
/// @brief Get the numbers that encode the number of permutations to
/// apply to facets.
///
/// The permutations are encoded so that:
///
/// - `n % 2` gives the number of reflections to apply
/// - `n // 2` gives the number of rotations to apply
///
/// The data is stored in a flattened 2D array, so that `data[cell_index *
/// facets_per_cell + facet_index]` contains the facet with index
/// `facet_index` of the cell with index `cell_index`.
/// @return The encoded permutation info
/// @note An exception is raised if the permutations have not been
/// computed
const std::vector<std::uint8_t>& get_facet_permutations() const;
/// @brief Get the types of cells in the topology
/// @return The cell types
std::vector<CellType> cell_types() const;
/// @brief List of inter-process facets of a given type.
///
/// "Inter-process" facets are facets that are connected (1) to a cell
/// that is owned by the calling process (rank) and (2) to a cell that
/// is owned by another process.
///
/// Facets must have been computed for inter-process facet data to be
/// available.
///
/// @param[in] index Index of facet type, following the order given
/// by ::entity_types.
/// @return Indices of the inter-process facets.
const std::vector<std::int32_t>& interprocess_facets(int index) const;
/// @brief List of inter-process facets.
///
/// "Inter-process" facets are facets that are connected (1) to a cell
/// that is owned by the calling process (rank) and (2) to a cell that
/// is owned by another process.
///
/// @pre Inter-process facets are available only if facet topology has
/// been computed.
const std::vector<std::int32_t>& interprocess_facets() const;
/// @brief Create entities of given topological dimension.
/// @param[in] dim Topological dimension of entities to compute.
/// @return True if entities are created, false if entities already
/// existed.
bool create_entities(int dim);
/// @brief Create connectivity between given pair of dimensions, `d0
/// -> d1`.
/// @param[in] d0 Topological dimension.
/// @param[in] d1 Topological dimension.
void create_connectivity(int d0, int d1);
/// @brief Compute entity permutations and reflections.
void create_entity_permutations();
/// Original cell index for each cell type
std::vector<std::vector<std::int64_t>> original_cell_index;
/// @brief Mesh MPI communicator.
/// @return Communicator on which the topology is distributed.
MPI_Comm comm() const;
private:
// Cell types for entities in Topology, where _entity_types_new[d][i]
// is the ith entity type of dimension d
std::vector<std::vector<CellType>> _entity_types;
// Parallel layout of entities for each dimension and cell type
// flattened in the same layout as _entity_types above.
// std::vector<std::shared_ptr<const common::IndexMap>> _index_map;
// _index_maps[(d, i) is the index map for the ith entity type of
// dimension d
std::map<std::array<int, 2>, std::shared_ptr<const common::IndexMap>>
_index_maps;
// Connectivity between cell types _connectivity_new[(dim0, i0),
// (dim1, i1)] is the connection from (dim0, i0) -> (dim1, i1),
// where dim0 and dim1 are topological dimensions and i0 and i1
// are the indices of cell types (following the order in _entity_types).
std::map<std::pair<std::array<int, 2>, std::array<int, 2>>,
std::shared_ptr<graph::AdjacencyList<std::int32_t>>>
_connectivity;
// The facet permutations (local facet, cell))
// [cell0_0, cell0_1, ,cell0_2, cell1_0, cell1_1, ,cell1_2, ...,
// celln_0, celln_1, ,celln_2,]
std::vector<std::uint8_t> _facet_permutations;
// Cell permutation info. See the documentation for
// get_cell_permutation_info for documentation of how this is encoded.
std::vector<std::uint32_t> _cell_permutations;
// List of facets that are on the inter-process boundary for each
// facet type. _interprocess_facets[i] is the inter-process facets of
// facet type i.
std::vector<std::vector<std::int32_t>> _interprocess_facets;
};
/// @brief Create a mesh topology.
///
/// This function creates a Topology from cells that have been already
/// distributed to the processes that own or ghost the cell.
///
/// @param[in] comm Communicator across which the topology will be
/// distributed.
/// @param[in] cell_types List of cell types in the topology.
/// @param[in] cells Cell topology (list of vertices for each cell) for
/// each cell type using global indices for the vertices. The cell type
/// for `cells[i]` is `cell_types[i]`, using row-major storage and where
/// the row `cells[i][j]` is the vertices for cell `j` of cell type `i`.
/// Each `cells[i]` contains cells that have been distributed to this
/// rank, e.g. via a graph partitioner. It must also contain all ghost
/// cells via facet, i.e. cells that are on a neighboring process and
/// which share a facet with a local cell. Ghost cells are the last `n`
/// entries in `cells[i]`, where `n` is given by the length of
/// `ghost_owners[i]`.
/// @param[in] original_cell_index Input cell index for each cell type,
/// e.g. the cell index in an input file. This index remains associated
/// with the cell after any re-ordering and parallel (re)distribution.
/// @param[in] ghost_owners Owning rank for ghost cells (ghost cells are
/// at end of each list of cells).
/// @param[in] boundary_vertices Vertices on the 'exterior' (boundary)
/// of the local topology. These vertices might appear on other
/// processes.
/// @return A distributed mesh topology.
Topology
create_topology(MPI_Comm comm, const std::vector<CellType>& cell_types,
std::vector<std::span<const std::int64_t>> cells,
std::vector<std::span<const std::int64_t>> original_cell_index,
std::vector<std::span<const int>> ghost_owners,
std::span<const std::int64_t> boundary_vertices);
/// @brief Create a mesh topology for a single cell type.
///
/// This function provides a simplified interface to ::create_topology
/// for the case that a mesh has one cell type only,
///
/// @param[in] comm Communicator across which the topology will be
/// distributed.
/// @param[in] cells Cell topology (list of vertices for each cell)
/// using global indices for the vertices. It contains cells that have
/// been distributed to this rank, e.g. via a graph partitioner. It must
/// also contain all ghost cells via facet, i.e. cells that are on a
/// neighboring process and which share a facet with a local cell. Ghost
/// cells are the last `n` entries in `cells`, where `n` is given by the
/// length of `ghost_owners`.
/// @param[in] original_cell_index Original global index associated with
/// each cell.
/// @param[in] ghost_owners Owning rank of each ghost cell (ghost cells
/// are always at the end of the list of `cells`).
/// @param[in] cell_type A vector with cell shapes.
/// @param[in] boundary_vertices Vertices on the 'exterior' (boundary)
/// of the local topology. These vertices might appear on other
/// processes.
/// @return A distributed mesh topology.
Topology create_topology(MPI_Comm comm, std::span<const std::int64_t> cells,
std::span<const std::int64_t> original_cell_index,
std::span<const int> ghost_owners, CellType cell_type,
std::span<const std::int64_t> boundary_vertices);
/// @brief Create a topology for a subset of entities of a given
/// topological dimension.
///
/// @param[in] topology Original (parent) topology.
/// @param[in] dim Topological dimension of the entities in the new
/// topology.
/// @param[in] entities Indices of entities in `topology` to include in
/// the new topology.
/// @return New topology of dimension `dim` with all entities in
/// `entities`, map from entities of dimension `dim` in new sub-topology
/// to entities in `topology`, and map from vertices in new sub-topology
/// to vertices in `topology`.
std::tuple<Topology, std::vector<int32_t>, std::vector<int32_t>>
create_subtopology(const Topology& topology, int dim,
std::span<const std::int32_t> entities);
/// @brief Get entity indices for entities defined by their vertices.
///
/// @warning This function may be removed in the future.
///
/// @param[in] topology Mesh topology.
/// @param[in] dim Topological dimension of the entities.
/// @param[in] entities Mesh entities defined by their vertices.
/// @return Index of the ith entity in `entities`, If an entity
/// cannot be found on this rank, -1 is returned as the index.
std::vector<std::int32_t>
entities_to_index(const Topology& topology, int dim,
std::span<const std::int32_t> entities);
/// @brief Compute a list of cell-cell connections for each possible combination
/// in the topology which have the same connecting facet type.
/// @param topology A mesh topology
/// @param facet_type Type of facet connection between cells
/// @return A list for each possible cell-cell connection, arranged
/// in the ordering given by `cell_types()` in the topology. i.e. if the cell
/// types are tet, prism, hex, and the facet_type is quadrilateral, then the
/// lists returned are: tet-tet (empty), tet-prism (empty), tet-hex (empty),
/// prism-tet (empty), prism-prism, prism-hex, hex-tet (empty), hex-prism,
/// hex-hex. Note there are empty lists for the invalid cases, and also that
/// there is currently redundant data, since the transpose is also computed,
/// i.e. prism-hex as well as hex-prism.
/// Each list contains a flattened array with data in the order (cell0, local
/// facet0, cell1, local facet1) for each connection between cells.
/// @note All facet-cell connectivity and cell-facet connectivity must be
/// computed beforehand in the topology.
/// @todo Remove redundant data.
std::vector<std::vector<std::int32_t>>
compute_mixed_cell_pairs(const Topology& topology, mesh::CellType facet_type);
} // namespace dolfinx::mesh
|