Reference documentation for deal.II version GIT relicensing-1062-gc06da148b8 2024-07-15 19:20:02+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: LGPL-2.1-or-later
4// Copyright (C) 2017 - 2024 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
17
21
23
24namespace GridTools
25{
26 template <int dim, int spacedim>
28 const Mapping<dim, spacedim> &mapping)
29 : update_flags(update_all)
30 , tria(&tria)
31 , mapping(&mapping)
32 {
34 tria.signals.any_change.connect([&]() { mark_for_update(update_all); });
35 }
36
37
38
39 template <int dim, int spacedim>
41 : update_flags(update_all)
42 , tria(&tria)
43 {
46
47 // Allow users to set this class up with an empty Triangulation and no
48 // Mapping argument by deferring Mapping assignment until after the
49 // Triangulation exists.
50 if (tria.get_reference_cells().size() == 0)
51 {
52 tria_create_signal = tria.signals.create.connect([&]() {
53 Assert(tria.get_reference_cells().size() > 0, ExcInternalError());
54 Assert(tria.get_reference_cells().size() == 1, ExcNotImplemented());
55 mapping = &tria.get_reference_cells()[0]
56 .template get_default_linear_mapping<dim, spacedim>();
57 });
58 }
59 else
60 {
61 Assert(tria.get_reference_cells().size() == 1, ExcNotImplemented());
62 mapping = &tria.get_reference_cells()[0]
63 .template get_default_linear_mapping<dim, spacedim>();
64 }
65 }
66
67 template <int dim, int spacedim>
69 {
70 if (tria_change_signal.connected())
71 tria_change_signal.disconnect();
72 if (tria_create_signal.connected())
73 tria_create_signal.disconnect();
74 }
75
76
77
78 template <int dim, int spacedim>
79 void
81 {
82 update_flags |= flags;
83 }
84
85
86
87 template <int dim, int spacedim>
88 const std::vector<
89 std::set<typename Triangulation<dim, spacedim>::active_cell_iterator>> &
91 {
92 // In the following, we will first check whether the data structure
93 // in question needs to be updated (in which case we update it, and
94 // reset the flag that indices that this needs to happen to zero), and
95 // then return it. Make this thread-safe by using a mutex to guard
96 // all of this:
97 std::lock_guard<std::mutex> lock(vertex_to_cells_mutex);
98
99 if (update_flags & update_vertex_to_cell_map)
100 {
101 vertex_to_cells = GridTools::vertex_to_cell_map(*tria);
102
103 // Atomically clear the flag that indicates that this data member
104 // needs to be updated:
105 update_flags &= ~update_vertex_to_cell_map;
106 }
107 return vertex_to_cells;
108 }
109
110
111
112 template <int dim, int spacedim>
113 const std::vector<std::vector<Tensor<1, spacedim>>> &
115 {
116 // In the following, we will first check whether the data structure
117 // in question needs to be updated (in which case we update it, and
118 // reset the flag that indices that this needs to happen to zero), and
119 // then return it. Make this thread-safe by using a mutex to guard
120 // all of this:
121 std::lock_guard<std::mutex> lock(vertex_to_cell_centers_mutex);
122
124 {
125 vertex_to_cell_centers = GridTools::vertex_to_cell_centers_directions(
126 *tria, get_vertex_to_cell_map());
127
128 // Atomically clear the flag that indicates that this data member
129 // needs to be updated:
130 update_flags &= ~update_vertex_to_cell_centers_directions;
131 }
132 return vertex_to_cell_centers;
133 }
134
136
137 template <int dim, int spacedim>
138 const std::map<unsigned int, Point<spacedim>> &
140 {
141 // In the following, we will first check whether the data structure
142 // in question needs to be updated (in which case we update it, and
143 // reset the flag that indices that this needs to happen to zero), and
144 // then return it. Make this thread-safe by using a mutex to guard
145 // all of this:
146 std::lock_guard<std::mutex> lock(used_vertices_mutex);
147
148 if (update_flags & update_used_vertices)
149 {
150 used_vertices = GridTools::extract_used_vertices(*tria, *mapping);
151
152 // Atomically clear the flag that indicates that this data member
153 // needs to be updated:
154 update_flags &= ~update_used_vertices;
155 }
156 return used_vertices;
157 }
158
159
160
161 template <int dim, int spacedim>
162 const RTree<std::pair<Point<spacedim>, unsigned int>> &
164 {
165 // In the following, we will first check whether the data structure
166 // in question needs to be updated (in which case we update it, and
167 // reset the flag that indices that this needs to happen to zero), and
168 // then return it. Make this thread-safe by using a mutex to guard
169 // all of this:
170 std::lock_guard<std::mutex> lock(used_vertices_rtree_mutex);
172 if (update_flags & update_used_vertices_rtree)
173 {
174 const auto &used_vertices = get_used_vertices();
175 std::vector<std::pair<Point<spacedim>, unsigned int>> vertices(
176 used_vertices.size());
177 unsigned int i = 0;
178 for (const auto &it : used_vertices)
179 vertices[i++] = std::make_pair(it.second, it.first);
180 used_vertices_rtree = pack_rtree(vertices);
181
182 // Atomically clear the flag that indicates that this data member
183 // needs to be updated:
184 update_flags &= ~update_used_vertices_rtree;
185 }
186 return used_vertices_rtree;
187 }
188
189
190
191 template <int dim, int spacedim>
192 const RTree<
193 std::pair<BoundingBox<spacedim>,
196 {
197 // In the following, we will first check whether the data structure
198 // in question needs to be updated (in which case we update it, and
199 // reset the flag that indices that this needs to happen to zero), and
200 // then return it. Make this thread-safe by using a mutex to guard
201 // all of this:
202 std::lock_guard<std::mutex> lock(cell_bounding_boxes_rtree_mutex);
203
204 if (update_flags & update_cell_bounding_boxes_rtree)
205 {
206 std::vector<std::pair<
209 boxes;
210 boxes.reserve(tria->n_active_cells());
211 for (const auto &cell : tria->active_cell_iterators())
212 boxes.emplace_back(mapping->get_bounding_box(cell), cell);
213
214 cell_bounding_boxes_rtree = pack_rtree(boxes);
215
216 // Atomically clear the flag that indicates that this data member
217 // needs to be updated:
218 update_flags &= ~update_cell_bounding_boxes_rtree;
219 }
220 return cell_bounding_boxes_rtree;
221 }
223
224
225 template <int dim, int spacedim>
226 const RTree<
227 std::pair<BoundingBox<spacedim>,
230 {
231 // In the following, we will first check whether the data structure
232 // in question needs to be updated (in which case we update it, and
233 // reset the flag that indices that this needs to happen to zero), and
234 // then return it. Make this thread-safe by using a mutex to guard
235 // all of this:
236 std::lock_guard<std::mutex> lock(
237 locally_owned_cell_bounding_boxes_rtree_mutex);
238
240 {
241 std::vector<std::pair<
244 boxes;
245 if (const parallel::TriangulationBase<dim, spacedim> *parallel_tria =
246 dynamic_cast<const parallel::TriangulationBase<dim, spacedim> *>(
247 &*tria))
248 boxes.reserve(parallel_tria->n_locally_owned_active_cells());
249 else
250 boxes.reserve(tria->n_active_cells());
251 for (const auto &cell : tria->active_cell_iterators() |
253 boxes.emplace_back(mapping->get_bounding_box(cell), cell);
254
255 locally_owned_cell_bounding_boxes_rtree = pack_rtree(boxes);
256
257 // Atomically clear the flag that indicates that this data member
258 // needs to be updated:
259 update_flags &= ~update_locally_owned_cell_bounding_boxes_rtree;
260 }
261 return locally_owned_cell_bounding_boxes_rtree;
262 }
263
264
265
266 template <int dim, int spacedim>
267 const RTree<std::pair<BoundingBox<spacedim>, unsigned int>> &
269 {
270 // In the following, we will first check whether the data structure
271 // in question needs to be updated (in which case we update it, and
272 // reset the flag that indices that this needs to happen to zero), and
273 // then return it. Make this thread-safe by using a mutex to guard
274 // all of this:
275 std::lock_guard<std::mutex> lock(covering_rtree_mutex);
276
277 if (update_flags & update_covering_rtree ||
278 covering_rtree.find(level) == covering_rtree.end())
279 {
280 const auto boxes =
281 extract_rtree_level(get_locally_owned_cell_bounding_boxes_rtree(),
282 level);
283
284 if (const auto tria_mpi =
285 dynamic_cast<const parallel::TriangulationBase<dim, spacedim> *>(
286 &(*tria)))
287 {
289 boxes, tria_mpi->get_communicator());
290 }
291 else
292 {
293 covering_rtree[level] =
294 GridTools::build_global_description_tree(boxes, MPI_COMM_SELF);
295 }
296
297 // Atomically clear the flag that indicates that this data member
298 // needs to be updated:
299 update_flags &= ~update_covering_rtree;
300 }
301
302 return covering_rtree[level];
303 }
304
305
306
307 template <int dim, int spacedim>
308 const std::vector<std::set<unsigned int>> &
310 {
311 // In the following, we will first check whether the data structure
312 // in question needs to be updated (in which case we update it, and
313 // reset the flag that indices that this needs to happen to zero), and
314 // then return it. Make this thread-safe by using a mutex to guard
315 // all of this:
316 std::lock_guard<std::mutex> lock(vertex_to_neighbor_subdomain_mutex);
317
318 if (update_flags & update_vertex_to_neighbor_subdomain)
319 {
320 vertex_to_neighbor_subdomain.clear();
321 vertex_to_neighbor_subdomain.resize(tria->n_vertices());
322 for (const auto &cell : tria->active_cell_iterators())
323 {
324 if (cell->is_ghost())
325 for (const unsigned int v : cell->vertex_indices())
326 vertex_to_neighbor_subdomain[cell->vertex_index(v)].insert(
327 cell->subdomain_id());
328 }
329 // Atomically clear the flag that indicates that this data member
330 // needs to be updated:
331 update_flags &= ~update_vertex_to_neighbor_subdomain;
332 }
333 return vertex_to_neighbor_subdomain;
334 }
335
336
337
338 template <int dim, int spacedim>
339 const std::map<unsigned int, std::set<types::subdomain_id>> &
341 {
342 // In the following, we will first check whether the data structure
343 // in question needs to be updated (in which case we update it, and
344 // reset the flag that indices that this needs to happen to zero), and
345 // then return it. Make this thread-safe by using a mutex to guard
346 // all of this:
347 std::lock_guard<std::mutex> lock(vertices_with_ghost_neighbors_mutex);
348
349 if (update_flags & update_vertex_with_ghost_neighbors)
350 {
353
354 // Atomically clear the flag that indicates that this data member
355 // needs to be updated:
356 update_flags &= ~update_vertex_with_ghost_neighbors;
357 }
358
360 }
361
362#include "grid_tools_cache.inst"
363
364} // namespace GridTools
365
SmartPointer< const Triangulation< dim, spacedim >, Cache< dim, spacedim > > tria
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
SmartPointer< 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
void mark_for_update(const CacheUpdateFlags &flags=update_all)
Abstract base class for mapping classes.
Definition mapping.h:318
Signals signals
Definition tria.h:2507
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:502
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:503
Point< 3 > vertices[4]
Point< 2 > second
Definition grid_out.cc:4624
Point< 2 > first
Definition grid_out.cc:4623
unsigned int level
Definition grid_out.cc:4626
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, Point< spacedim > > extract_used_vertices(const Triangulation< dim, spacedim > &container, const Mapping< dim, spacedim > &mapping=(ReferenceCells::get_hypercube< dim >() .template get_default_linear_mapping< dim, spacedim >()))
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)
STL namespace.
std::map< unsigned int, std::set<::types::subdomain_id > > * vertices_with_ghost_neighbors
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:145
RTree< typename LeafTypeIterator::value_type, IndexType, IndexableGetter > pack_rtree(const LeafTypeIterator &begin, const LeafTypeIterator &end)
boost::signals2::signal< void()> any_change
Definition tria.h:2379