DOLFINx 0.12.0.0
DOLFINx C++
Loading...
Searching...
No Matches
EntityMap.h
1// Copyright (C) 2025-2026 Jørgen S. Dokken and Joseph P. Dean
2//
3// This file is part of DOLFINx (https://www.fenicsproject.org)
4//
5// SPDX-License-Identifier: LGPL-3.0-or-later
6
7#pragma once
8
9#include "Topology.h"
10#include <algorithm>
11#include <cstdint>
12#include <dolfinx/common/IndexMap.h>
13#include <iterator>
14#include <memory>
15#include <ranges>
16#include <stdexcept>
17#include <type_traits>
18#include <unordered_map>
19#include <utility>
20#include <vector>
21
22namespace dolfinx::mesh
23{
27{
28public:
42 template <typename U>
43 requires std::is_convertible_v<std::remove_cvref_t<U>,
44 std::vector<std::int32_t>>
45 EntityMap(std::shared_ptr<const Topology> topology,
46 std::shared_ptr<const Topology> sub_topology, int dim,
48 : _dim(dim), _topology(topology),
49 _sub_topology_to_topology(std::forward<U>(sub_topology_to_topology)),
50 _sub_topology(sub_topology)
51 {
52 if (!topology)
53 throw std::invalid_argument("topology must not be null.");
54 if (!sub_topology)
55 throw std::invalid_argument("sub_topology must not be null.");
56 if (dim < 0 or dim > topology->dim() or dim > sub_topology->dim())
57 {
58 throw std::invalid_argument(
59 "dim out of range for topology/sub_topology.");
60 }
61
62 auto e_imap = sub_topology->index_map(_dim);
63 std::size_t num_ents = e_imap->size_local() + e_imap->num_ghosts();
64 if (num_ents != _sub_topology_to_topology.size())
65 {
66 throw std::invalid_argument(
67 "Size mismatch between `sub_topology_to_topology` and index map.");
68 }
69 }
70
72 EntityMap(const EntityMap& map) = default;
73
75 EntityMap(EntityMap&& map) = default;
76
78 ~EntityMap() = default;
79
80 // Copy assignment (deleted)
81 EntityMap& operator=(const EntityMap& map) = delete;
82
84 EntityMap& operator=(EntityMap&& map) = default;
85
89 int dim() const;
90
93 std::shared_ptr<const Topology> topology() const;
94
97 std::shared_ptr<const Topology> sub_topology() const;
98
119 std::vector<std::int32_t> sub_topology_to_topology(CellRange auto&& entities,
120 bool inverse) const
121 {
122 std::size_t num_entities = std::ranges::size(entities);
123 if (!inverse)
124 {
125 // In this case, we want to map from entity indices in
126 // `_sub_topology` to corresponding entities in `_topology`. Hence,
127 // for each index in `entities`, we get the corresponding index in
128 // `_topology` using `_sub_topology_to_topology`
129 auto mapped
130 = std::forward<decltype(entities)>(entities)
131 | std::views::transform([this](std::int32_t i)
132 { return _sub_topology_to_topology[i]; });
133 std::vector<std::int32_t> mapped_v;
134 mapped_v.reserve(num_entities);
135 std::ranges::copy(mapped, std::back_inserter(mapped_v));
136 return mapped_v;
137 }
138 else
139 {
140 // In this case, we are mapping from entity indices in `_topology`
141 // to entity indices in `_sub_topology`. Hence, we first need to
142 // construct the "inverse" of `_sub_topology_to_topology`
143 std::unordered_map<std::int32_t, std::int32_t> topology_to_sub_topology;
144 topology_to_sub_topology.reserve(_sub_topology_to_topology.size());
145 for (std::size_t i = 0; i < _sub_topology_to_topology.size(); ++i)
146 {
147 topology_to_sub_topology.insert(
148 {_sub_topology_to_topology[i], static_cast<std::int32_t>(i)});
149 }
150
151 // For each entity index in `entities` (which are indices in
152 // `_topology`), get the corresponding entity in `_sub_topology`.
153 // Since `_sub_topology` consists of a subset of entities in
154 // `_topology`, there are entities in topology that may not exist in
155 // `_sub_topology`. If this is the case, mark those entities with
156 // -1.
157
158 auto mapped = std::forward<decltype(entities)>(entities)
159 | std::views::transform(
160 [&topology_to_sub_topology](std::int32_t i)
161 {
162 // Map the entity if it exists. If it doesn't, mark
163 // with -1.
164 auto it = topology_to_sub_topology.find(i);
165 return (it != topology_to_sub_topology.end())
166 ? it->second
167 : -1;
168 });
169 std::vector<std::int32_t> mapped_v;
170 mapped_v.reserve(num_entities);
171 std::ranges::copy(mapped, std::back_inserter(mapped_v));
172 return mapped_v;
173 }
174 }
175
176private:
177 // Dimension of the entities
178 int _dim;
179
180 // A topology
181 std::shared_ptr<const Topology> _topology;
182
183 // A list of `_dim`-dimensional entities in _topology, where
184 // `_sub_topology_to_topology[i]` is the index in `_topology` of the
185 // `i`th entity in `_sub_topology`
186 std::vector<std::int32_t> _sub_topology_to_topology;
187
188 // A second topology, consisting of a subset of entities in
189 // `_topology`
190 std::shared_ptr<const Topology> _sub_topology;
191};
192} // namespace dolfinx::mesh
EntityMap(EntityMap &&map)=default
Move constructor.
std::vector< std::int32_t > sub_topology_to_topology(CellRange auto &&entities, bool inverse) const
Map entities between the sub-topology and the parent topology.
Definition EntityMap.h:119
~EntityMap()=default
Destructor.
EntityMap(std::shared_ptr< const Topology > topology, std::shared_ptr< const Topology > sub_topology, int dim, U &&sub_topology_to_topology)
Constructor of a bidirectional map relating entities of dimension dim in topology and sub_topology.
Definition EntityMap.h:45
EntityMap(const EntityMap &map)=default
Copy constructor.
int dim() const
Get the topological dimension of the entities related by this EntityMap.
Definition EntityMap.cpp:13
std::shared_ptr< const Topology > sub_topology() const
Get the sub-topology.
Definition EntityMap.cpp:20
std::shared_ptr< const Topology > topology() const
Get the (parent) topology.
Definition EntityMap.cpp:15
EntityMap & operator=(EntityMap &&map)=default
Move assignment.
Requirement on range of cell indices.
Definition Topology.h:32
Mesh data structures and algorithms on meshes.
Definition DofMap.h:32