PolyDEAL
 
Loading...
Searching...
No Matches
agglomerator.h
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) XXXX - YYYY by the polyDEAL authors
5//
6// This file is part of the polyDEAL library.
7//
8// Detailed license information governing the source code
9// can be found in LICENSE.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13
14#ifndef agglomerator_h
15#define agglomerator_h
16
17
18#include <deal.II/base/config.h>
19
21
22#include <boost/geometry/algorithms/distance.hpp>
23#include <boost/geometry/index/rtree.hpp>
24#include <boost/geometry/strategies/strategies.hpp>
25
26template <int dim, int spacedim>
28
29namespace dealii
30{
31 namespace internal
32 {
33 template <typename Value,
34 typename Options,
35 typename Translator,
36 typename Box,
37 typename Allocators>
39 : public boost::geometry::index::detail::rtree::visitor<
40 Value,
41 typename Options::parameters_type,
42 Box,
43 Allocators,
44 typename Options::node_tag,
45 true>::type
46 {
47 inline Rtree_visitor(
48 const Translator &translator,
49 const unsigned int target_level,
50 std::vector<std::vector<typename Triangulation<
51 boost::geometry::dimension<Box>::value>::active_cell_iterator>>
52 &agglomerates_,
53 std::vector<types::global_cell_index> &n_nodes_per_level,
54 std::map<std::pair<types::global_cell_index, types::global_cell_index>,
55 std::vector<types::global_cell_index>> &parent_to_children);
56
61 typename boost::geometry::index::detail::rtree::internal_node<
62 Value,
63 typename Options::parameters_type,
64 Box,
65 Allocators,
66 typename Options::node_tag>::type;
67
71 using Leaf = typename boost::geometry::index::detail::rtree::leaf<
72 Value,
73 typename Options::parameters_type,
74 Box,
75 Allocators,
76 typename Options::node_tag>::type;
77
83 inline void
84 operator()(const InternalNode &node);
85
89 inline void
90 operator()(const Leaf &);
91
96 const Translator &translator;
97
101 size_t level;
102
108
113 const size_t target_level;
114
120 std::vector<std::vector<typename Triangulation<
121 boost::geometry::dimension<Box>::value>::active_cell_iterator>>
123
127 std::vector<types::global_cell_index> &n_nodes_per_level;
128
133 std::map<std::pair<types::global_cell_index, types::global_cell_index>,
134 std::vector<types::global_cell_index>>
136 };
137
138
139
140 template <typename Value,
141 typename Options,
142 typename Translator,
143 typename Box,
144 typename Allocators>
146 const Translator &translator,
147 const unsigned int target_level,
148 std::vector<std::vector<typename Triangulation<
149 boost::geometry::dimension<Box>::value>::active_cell_iterator>>
150 &agglomerates_,
151 std::vector<types::global_cell_index> &n_nodes_per_level_,
152 std::map<std::pair<types::global_cell_index, types::global_cell_index>,
153 std::vector<types::global_cell_index>> &parent_to_children)
154 : translator(translator)
155 , level(0)
156 , node_counter(0)
157 , target_level(target_level)
158 , agglomerates(agglomerates_)
159 , n_nodes_per_level(n_nodes_per_level_)
160 , parent_node_to_children_nodes(parent_to_children)
161 {}
162
163
164
165 template <typename Value,
166 typename Options,
167 typename Translator,
168 typename Box,
169 typename Allocators>
170 void
172 const Rtree_visitor::InternalNode &node)
173 {
174 using elements_type =
175 typename boost::geometry::index::detail::rtree::elements_type<
176 InternalNode>::type; // pairs of bounding box and pointer to child
177 // node
178 const elements_type &elements =
179 boost::geometry::index::detail::rtree::elements(node);
180
181 if (level < target_level)
182 {
183 size_t level_backup = level;
184 ++level;
185
186 for (typename elements_type::const_iterator it = elements.begin();
187 it != elements.end();
188 ++it)
189 {
190 boost::geometry::index::detail::rtree::apply_visitor(*this,
191 *it->second);
192 }
193
194 level = level_backup;
195 }
196 else if (level == target_level)
197 {
198 const auto offset = agglomerates.size();
199 agglomerates.resize(offset + 1);
200 size_t level_backup = level;
201
202 ++level;
203 for (const auto &entry : elements)
204 {
205 boost::geometry::index::detail::rtree::apply_visitor(
206 *this, *entry.second);
207 }
208 // Done with node number 'node_counter' on level target_level.
209
210 ++node_counter; // visited all children of an internal node
211 n_nodes_per_level[target_level]++;
212
213 level = level_backup;
214 }
215 else if (level > target_level)
216 {
217 // I am on a child (internal) node on a deeper level.
218
219 // Keep visiting until you go to the leafs.
220 size_t level_backup = level;
221
222 ++level;
223
224 // looping through entries of node
225 for (const auto &entry : elements)
226 {
227 boost::geometry::index::detail::rtree::apply_visitor(
228 *this, *entry.second);
229 }
230 // done with node on level l > target_level (not just
231 // "target_level+1).
232 n_nodes_per_level[level_backup]++;
233 const types::global_cell_index node_idx =
234 n_nodes_per_level[level_backup] - 1; // so to start from 0
235
236 parent_node_to_children_nodes[{n_nodes_per_level[level_backup - 1],
237 level_backup - 1}]
238 .push_back(node_idx);
239
240 level = level_backup;
241 }
242 }
243
244
245
246 template <typename Value,
247 typename Options,
248 typename Translator,
249 typename Box,
250 typename Allocators>
251 void
253 const Rtree_visitor::Leaf &leaf)
254 {
255 using elements_type =
256 typename boost::geometry::index::detail::rtree::elements_type<
257 Leaf>::type; // pairs of bounding box and pointer to child node
258 const elements_type &elements =
259 boost::geometry::index::detail::rtree::elements(leaf);
260
261 if (level == target_level)
262 {
263 // If I want to extract from leaf node, i.e. the target_level is the
264 // last one where leafs are grouped together.
265 const auto offset = agglomerates.size();
266 agglomerates.resize(offset + 1);
267
268 for (const auto &it : elements)
269 agglomerates[node_counter].push_back(it.second);
270
271 ++node_counter;
272 n_nodes_per_level[target_level]++;
273 }
274 else
275 {
276 for (const auto &it : elements)
277 agglomerates[node_counter].push_back(it.second);
278
279
280 if (level == target_level + 1)
281 {
282 const unsigned int node_idx = n_nodes_per_level[level];
283
284 parent_node_to_children_nodes[{n_nodes_per_level[level - 1],
285 level - 1}]
286 .push_back(node_idx);
287 n_nodes_per_level[level]++;
288 }
289 }
290 }
291 } // namespace internal
292
293
294
299 template <int dim, typename RtreeType>
301 {
302 public:
303 template <int, int>
304 friend class ::AgglomerationHandler;
305
310 CellsAgglomerator(const RtreeType &rtree,
311 const unsigned int extraction_level);
312
317 const std::vector<
318 std::vector<typename Triangulation<dim>::active_cell_iterator>> &
320
324 inline unsigned int
325 get_n_levels() const;
326
331 get_n_nodes_per_level(const unsigned int level) const;
332
337 inline const std::map<
338 std::pair<types::global_cell_index, types::global_cell_index>,
339 std::vector<types::global_cell_index>> &
340 get_hierarchy() const;
341
342 private:
346 RtreeType *rtree;
347
351 const unsigned int extraction_level;
352
357 std::vector<std::vector<typename Triangulation<dim>::active_cell_iterator>>
359
364 std::vector<types::global_cell_index> n_nodes_per_level;
365
370 std::map<std::pair<types::global_cell_index, types::global_cell_index>,
371 std::vector<types::global_cell_index>>
373 };
374
375
376
377 template <int dim, typename RtreeType>
379 const RtreeType &tree,
380 const unsigned int extraction_level_)
381 : extraction_level(extraction_level_)
382 {
383 rtree = const_cast<RtreeType *>(&tree);
384 Assert(n_levels(*rtree), ExcMessage("At least two levels are needed."));
385 }
386
387
388
389 template <int dim, typename RtreeType>
390 const std::vector<
391 std::vector<typename Triangulation<dim>::active_cell_iterator>> &
393 {
394 AssertThrow(extraction_level <= n_levels(*rtree),
395 ExcInternalError("You are trying to extract level " +
396 std::to_string(extraction_level) +
397 " of the tree, but it only has a total of " +
398 std::to_string(n_levels(*rtree)) +
399 " levels."));
400 using RtreeView =
401 boost::geometry::index::detail::rtree::utilities::view<RtreeType>;
402 RtreeView rtv(*rtree);
403
404 n_nodes_per_level.resize(rtv.depth() +
405 1); // store how many nodes we have for each level.
406
407 if (rtv.depth() == 0)
408 {
409 // The below algorithm does not work for `rtv.depth()==0`, which might
410 // happen if the number entries in the tree is too small.
411 agglomerates_on_level.resize(1);
412 agglomerates_on_level[0].resize(1);
413 }
414 else
415 {
416 const unsigned int target_level =
417 std::min<unsigned int>(extraction_level, rtv.depth());
418
419 internal::Rtree_visitor<typename RtreeView::value_type,
420 typename RtreeView::options_type,
421 typename RtreeView::translator_type,
422 typename RtreeView::box_type,
423 typename RtreeView::allocators_type>
424 extractor_visitor(rtv.translator(),
425 target_level,
426 agglomerates_on_level,
427 n_nodes_per_level,
428 parent_node_to_children_nodes);
429
430
431 rtv.apply_visitor(extractor_visitor);
432 }
433 return agglomerates_on_level;
434 }
435
436
437
438 // ------------------------------ inline functions -------------------------
439
440
441 template <int dim, typename RtreeType>
442 inline unsigned int
444 {
445 return n_levels(*rtree);
446 }
447
448
449
450 template <int dim, typename RtreeType>
453 const unsigned int level) const
454 {
455 return n_nodes_per_level[level];
456 }
457
458
459
460 template <int dim, typename RtreeType>
461 inline const std::map<
462 std::pair<types::global_cell_index, types::global_cell_index>,
463 std::vector<types::global_cell_index>> &
465 {
466 Assert(parent_node_to_children_nodes.size(),
467 ExcMessage(
468 "The hierarchy has not been computed. Did you forget to call"
469 " extract_agglomerates() first?"));
470 return parent_node_to_children_nodes;
471 }
472} // namespace dealii
473#endif
std::vector< std::vector< typename Triangulation< dim >::active_cell_iterator > > agglomerates_on_level
const unsigned int extraction_level
const std::map< std::pair< types::global_cell_index, types::global_cell_index >, std::vector< types::global_cell_index > > & get_hierarchy() const
std::map< std::pair< types::global_cell_index, types::global_cell_index >, std::vector< types::global_cell_index > > parent_node_to_children_nodes
types::global_cell_index get_n_nodes_per_level(const unsigned int level) const
unsigned int get_n_levels() const
CellsAgglomerator(const RtreeType &rtree, const unsigned int extraction_level)
const std::vector< std::vector< typename Triangulation< dim >::active_cell_iterator > > & extract_agglomerates()
std::vector< types::global_cell_index > n_nodes_per_level
unsigned int level
#define Assert(cond, exc)
#define AssertThrow(cond, exc)
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
unsigned int global_cell_index
typename boost::geometry::index::detail::rtree::internal_node< Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag >::type InternalNode
std::map< std::pair< types::global_cell_index, types::global_cell_index >, std::vector< types::global_cell_index > > & parent_node_to_children_nodes
const Translator & translator
void operator()(const InternalNode &node)
std::vector< types::global_cell_index > & n_nodes_per_level
std::vector< std::vector< typename Triangulation< boost::geometry::dimension< Box >::value >::active_cell_iterator > > & agglomerates
Rtree_visitor(const Translator &translator, const unsigned int target_level, std::vector< std::vector< typename Triangulation< boost::geometry::dimension< Box >::value >::active_cell_iterator > > &agglomerates_, std::vector< types::global_cell_index > &n_nodes_per_level, std::map< std::pair< types::global_cell_index, types::global_cell_index >, std::vector< types::global_cell_index > > &parent_to_children)
typename boost::geometry::index::detail::rtree::leaf< Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag >::type Leaf