deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
grid_tools_cache.cc
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2017 - 2026 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
15
19
21
22namespace GridTools
23{
24 template <int dim, int spacedim>
26 const Mapping<dim, spacedim> &mapping)
27 : update_flags(update_all)
28 , tria(&tria)
29 , mapping(&mapping)
30 {
32 tria.signals.any_change.connect([&]() { mark_for_update(update_all); });
33 }
34
35
36
37 template <int dim, int spacedim>
39 : update_flags(update_all)
40 , tria(&tria)
41 {
44
45 // Allow users to set this class up with an empty Triangulation and no
46 // Mapping argument by deferring Mapping assignment until after the
47 // Triangulation exists.
48 if (tria.get_reference_cells().size() == 0)
49 {
50 tria_create_signal = tria.signals.create.connect([&]() {
51 Assert(tria.get_reference_cells().size() > 0, ExcInternalError());
52 Assert(tria.get_reference_cells().size() == 1, ExcNotImplemented());
53 mapping = &tria.get_reference_cells()[0]
54 .template get_default_linear_mapping<spacedim>();
55 });
56 }
57 else
58 {
59 Assert(tria.get_reference_cells().size() == 1, ExcNotImplemented());
60 mapping = &tria.get_reference_cells()[0]
61 .template get_default_linear_mapping<spacedim>();
62 }
63 }
64
65 template <int dim, int spacedim>
67 {
68 if (tria_change_signal.connected())
69 tria_change_signal.disconnect();
70 if (tria_create_signal.connected())
71 tria_create_signal.disconnect();
72 }
73
74
75
76 template <int dim, int spacedim>
77 void
79 {
80 update_flags |= flags;
81 }
82
83
84
85 template <int dim, int spacedim>
86 const std::vector<
87 std::set<typename Triangulation<dim, spacedim>::active_cell_iterator>> &
89 {
90 // In the following, we will first check whether the data structure
91 // in question needs to be updated (in which case we update it, and
92 // reset the flag that indices that this needs to happen to zero), and
93 // then return it. Make this thread-safe by using a mutex to guard
94 // all of this:
95 std::scoped_lock lock(vertex_to_cells_mutex);
96
97 if (update_flags & update_vertex_to_cell_map)
98 {
99 vertex_to_cells = GridTools::vertex_to_cell_map(*tria);
100
101 // Atomically clear the flag that indicates that this data member
102 // needs to be updated:
103 update_flags &= ~update_vertex_to_cell_map;
105 return vertex_to_cells;
106 }
107
108
109
110 template <int dim, int spacedim>
111 const std::vector<std::vector<Tensor<1, spacedim>>> &
114 // In the following, we will first check whether the data structure
115 // in question needs to be updated (in which case we update it, and
116 // reset the flag that indices that this needs to happen to zero), and
117 // then return it. Make this thread-safe by using a mutex to guard
118 // all of this:
119 std::scoped_lock lock(vertex_to_cell_centers_mutex);
122 {
123 vertex_to_cell_centers = GridTools::vertex_to_cell_centers_directions(
124 *tria, get_vertex_to_cell_map());
125
126 // Atomically clear the flag that indicates that this data member
127 // needs to be updated:
128 update_flags &= ~update_vertex_to_cell_centers_directions;
129 }
130 return vertex_to_cell_centers;
131 }
132
133
135 template <int dim, int spacedim>
136 const std::map<unsigned int, Point<spacedim>> &
138 {
139 // In the following, we will first check whether the data structure
140 // in question needs to be updated (in which case we update it, and
141 // reset the flag that indices that this needs to happen to zero), and
142 // then return it. Make this thread-safe by using a mutex to guard
143 // all of this:
144 std::scoped_lock lock(used_vertices_mutex);
146 if (update_flags & update_used_vertices)
147 {
148 used_vertices = GridTools::extract_used_vertices(*tria, *mapping);
149
150 // Atomically clear the flag that indicates that this data member
151 // needs to be updated:
152 update_flags &= ~update_used_vertices;
153 }
154 return used_vertices;
155 }
156
157
158
159 template <int dim, int spacedim>
160 const RTree<std::pair<Point<spacedim>, unsigned int>> &
162 {
163 // In the following, we will first check whether the data structure
164 // in question needs to be updated (in which case we update it, and
165 // reset the flag that indices that this needs to happen to zero), and
166 // then return it. Make this thread-safe by using a mutex to guard
167 // all of this:
168 std::scoped_lock lock(used_vertices_rtree_mutex);
169
170 if (update_flags & update_used_vertices_rtree)
171 {
172 const auto &used_vertices = get_used_vertices();
173 std::vector<std::pair<Point<spacedim>, unsigned int>> vertices(
174 used_vertices.size());
175 unsigned int i = 0;
176 for (const auto &it : used_vertices)
177 vertices[i++] = std::make_pair(it.second, it.first);
178 used_vertices_rtree = pack_rtree(vertices);
179
180 // Atomically clear the flag that indicates that this data member
181 // needs to be updated:
182 update_flags &= ~update_used_vertices_rtree;
183 }
184 return used_vertices_rtree;
185 }
186
187
188
189 template <int dim, int spacedim>
190 const RTree<
191 std::pair<BoundingBox<spacedim>,
194 {
195 // In the following, we will first check whether the data structure
196 // in question needs to be updated (in which case we update it, and
197 // reset the flag that indices that this needs to happen to zero), and
198 // then return it. Make this thread-safe by using a mutex to guard
199 // all of this:
200 std::scoped_lock lock(cell_bounding_boxes_rtree_mutex);
201
202 if (update_flags & update_cell_bounding_boxes_rtree)
203 {
204 std::vector<std::pair<
207 boxes;
208 boxes.reserve(tria->n_active_cells());
209 for (const auto &cell : tria->active_cell_iterators())
210 boxes.emplace_back(mapping->get_bounding_box(cell), cell);
211
212 cell_bounding_boxes_rtree = pack_rtree(boxes);
213
214 // Atomically clear the flag that indicates that this data member
215 // needs to be updated:
216 update_flags &= ~update_cell_bounding_boxes_rtree;
217 }
218 return cell_bounding_boxes_rtree;
219 }
220
222
223 template <int dim, int spacedim>
224 const RTree<
225 std::pair<BoundingBox<spacedim>,
228 {
229 // In the following, we will first check whether the data structure
230 // in question needs to be updated (in which case we update it, and
231 // reset the flag that indices that this needs to happen to zero), and
232 // then return it. Make this thread-safe by using a mutex to guard
233 // all of this:
234 std::scoped_lock lock(locally_owned_cell_bounding_boxes_rtree_mutex);
235
237 {
238 std::vector<std::pair<
241 boxes;
242 if (const parallel::TriangulationBase<dim, spacedim> *parallel_tria =
243 dynamic_cast<const parallel::TriangulationBase<dim, spacedim> *>(
244 &*tria))
245 boxes.reserve(parallel_tria->n_locally_owned_active_cells());
246 else
247 boxes.reserve(tria->n_active_cells());
248 for (const auto &cell : tria->active_cell_iterators() |
250 boxes.emplace_back(mapping->get_bounding_box(cell), cell);
251
252 locally_owned_cell_bounding_boxes_rtree = pack_rtree(boxes);
253
254 // Atomically clear the flag that indicates that this data member
255 // needs to be updated:
256 update_flags &= ~update_locally_owned_cell_bounding_boxes_rtree;
257 }
258 return locally_owned_cell_bounding_boxes_rtree;
259 }
260
261
262
263 template <int dim, int spacedim>
264 const RTree<std::pair<BoundingBox<spacedim>, unsigned int>> &
266 {
267 // In the following, we will first check whether the data structure
268 // in question needs to be updated (in which case we update it, and
269 // reset the flag that indices that this needs to happen to zero), and
270 // then return it. Make this thread-safe by using a mutex to guard
271 // all of this:
272 std::scoped_lock lock(covering_rtree_mutex);
273
274 if (update_flags & update_covering_rtree ||
275 covering_rtree.find(level) == covering_rtree.end())
276 {
277 const auto boxes =
278 extract_rtree_level(get_locally_owned_cell_bounding_boxes_rtree(),
279 level);
280
281 if (const auto tria_mpi =
282 dynamic_cast<const parallel::TriangulationBase<dim, spacedim> *>(
283 &(*tria)))
284 {
286 boxes, tria_mpi->get_mpi_communicator());
287 }
288 else
289 {
290 covering_rtree[level] =
291 GridTools::build_global_description_tree(boxes, MPI_COMM_SELF);
292 }
293
294 // Atomically clear the flag that indicates that this data member
295 // needs to be updated:
296 update_flags &= ~update_covering_rtree;
297 }
298
299 return covering_rtree[level];
300 }
301
302
303
304 template <int dim, int spacedim>
305 const std::vector<std::set<unsigned int>> &
307 {
308 // In the following, we will first check whether the data structure
309 // in question needs to be updated (in which case we update it, and
310 // reset the flag that indices that this needs to happen to zero), and
311 // then return it. Make this thread-safe by using a mutex to guard
312 // all of this:
313 std::scoped_lock lock(vertex_to_neighbor_subdomain_mutex);
314
315 if (update_flags & update_vertex_to_neighbor_subdomain)
316 {
317 vertex_to_neighbor_subdomain.clear();
318 vertex_to_neighbor_subdomain.resize(tria->n_vertices());
319 for (const auto &cell : tria->active_cell_iterators())
320 {
321 if (cell->is_ghost())
322 for (const unsigned int v : cell->vertex_indices())
323 vertex_to_neighbor_subdomain[cell->vertex_index(v)].insert(
324 cell->subdomain_id());
325 }
326 // Atomically clear the flag that indicates that this data member
327 // needs to be updated:
328 update_flags &= ~update_vertex_to_neighbor_subdomain;
329 }
330 return vertex_to_neighbor_subdomain;
331 }
332
333
334
335 template <int dim, int spacedim>
336 const std::map<unsigned int, std::set<types::subdomain_id>> &
338 {
339 // In the following, we will first check whether the data structure
340 // in question needs to be updated (in which case we update it, and
341 // reset the flag that indices that this needs to happen to zero), and
342 // then return it. Make this thread-safe by using a mutex to guard
343 // all of this:
344 std::scoped_lock lock(vertices_with_ghost_neighbors_mutex);
345
346 if (update_flags & update_vertex_with_ghost_neighbors)
347 {
348 vertices_with_ghost_neighbors =
350
351 // Atomically clear the flag that indicates that this data member
352 // needs to be updated:
353 update_flags &= ~update_vertex_with_ghost_neighbors;
354 }
355
356 return vertices_with_ghost_neighbors;
357 }
358
359#include "grid/grid_tools_cache.inst"
360
361} // namespace GridTools
362
const std::vector< std::set< typename Triangulation< dim, spacedim >::active_cell_iterator > > & get_vertex_to_cell_map() const
const RTree< std::pair< BoundingBox< spacedim >, unsigned int > > & get_covering_rtree(const unsigned int level=0) const
ObserverPointer< const Mapping< dim, spacedim >, Cache< dim, spacedim > > mapping
const std::vector< std::vector< Tensor< 1, spacedim > > > & get_vertex_to_cell_centers_directions() const
boost::signals2::connection tria_change_signal
Cache(const Triangulation< dim, spacedim > &tria, const Mapping< dim, spacedim > &mapping)
boost::signals2::connection tria_create_signal
const std::vector< std::set< unsigned int > > & get_vertex_to_neighbor_subdomain() const
const std::map< unsigned int, std::set< types::subdomain_id > > & get_vertices_with_ghost_neighbors() const
const RTree< std::pair< BoundingBox< spacedim >, typename Triangulation< dim, spacedim >::active_cell_iterator > > & get_locally_owned_cell_bounding_boxes_rtree() const
const RTree< std::pair< Point< spacedim >, unsigned int > > & get_used_vertices_rtree() const
const RTree< std::pair< BoundingBox< spacedim >, typename Triangulation< dim, spacedim >::active_cell_iterator > > & get_cell_bounding_boxes_rtree() const
const std::map< unsigned int, Point< spacedim > > & get_used_vertices() const
ObserverPointer< const Triangulation< dim, spacedim >, Cache< dim, spacedim > > tria
void mark_for_update(const CacheUpdateFlags &flags=update_all)
Abstract base class for mapping classes.
Definition mapping.h:318
Signals signals
Definition tria.h:2588
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
unsigned int level
Definition grid_out.cc:4642
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
static ::ExceptionBase & ExcInternalError()
RTree< std::pair< BoundingBox< spacedim >, unsigned int > > build_global_description_tree(const std::vector< BoundingBox< spacedim > > &local_description, const MPI_Comm mpi_communicator)
std::map< unsigned int, std::set<::types::subdomain_id > > compute_vertices_with_ghost_neighbors(const Triangulation< dim, spacedim > &tria)
std::vector< std::set< typename Triangulation< dim, spacedim >::active_cell_iterator > > vertex_to_cell_map(const Triangulation< dim, spacedim > &triangulation)
std::vector< std::vector< Tensor< 1, spacedim > > > vertex_to_cell_centers_directions(const Triangulation< dim, spacedim > &mesh, const std::vector< std::set< typename Triangulation< dim, spacedim >::active_cell_iterator > > &vertex_to_cells)
std::map< unsigned int, Point< spacedim > > extract_used_vertices(const Triangulation< dim, spacedim > &container, const Mapping< dim, spacedim > &mapping=(ReferenceCells::get_hypercube< dim >() .template get_default_linear_mapping< spacedim >()))
std::vector< BoundingBox< boost::geometry::dimension< typename Rtree::indexable_type >::value > > extract_rtree_level(const Rtree &tree, const unsigned int level)
boost::geometry::index::rtree< LeafType, IndexType, IndexableGetter > RTree
Definition rtree.h:159
RTree< typename LeafTypeIterator::value_type, IndexType, IndexableGetter > pack_rtree(const LeafTypeIterator &begin, const LeafTypeIterator &end)
boost::signals2::signal< void()> any_change
Definition tria.h:2460