25 #include "libmesh/libmesh_config.h" 26 #include "libmesh/tree_node.h" 27 #include "libmesh/mesh_base.h" 28 #include "libmesh/elem.h" 35 template <
unsigned int N>
42 if (!this->bounds_node(nd))
51 if (nodes.size() == tgt_bin_size)
59 libmesh_assert_equal_to (children.size(), N);
61 bool was_inserted =
false;
62 for (
unsigned int c=0; c<N; c++)
63 if (children[c]->insert (nd))
70 template <
unsigned int N>
82 bool bboxes_intersect =
false;
85 bboxes_intersect = this->bounding_box.
intersects(bbox);
94 #define IS_BETWEEN(min, check, max) \ 95 ((min) <= (check) && (check) <= (max)) 98 const Real & elem_min_x = bbox.first(0);
99 const Real & elem_max_x = bbox.second(0);
100 const Real & tree_min_x = this->bounding_box.first(0);
101 const Real & tree_max_x = this->bounding_box.second(0);
103 const Real & elem_min_y = bbox.first(1);
104 const Real & elem_max_y = bbox.second(1);
105 const Real & tree_min_y = this->bounding_box.first(1);
106 const Real & tree_max_y = this->bounding_box.second(1);
109 IS_BETWEEN(elem_min_x, tree_min_x, elem_max_x) ||
110 IS_BETWEEN(elem_min_x, tree_max_x, elem_max_x) ||
111 IS_BETWEEN(tree_min_x, elem_min_x, tree_max_x) ||
112 IS_BETWEEN(tree_min_x, elem_max_x, tree_max_x);
115 IS_BETWEEN(elem_min_y, tree_min_y, elem_max_y) ||
116 IS_BETWEEN(elem_min_y, tree_max_y, elem_max_y) ||
117 IS_BETWEEN(tree_min_y, elem_min_y, tree_max_y) ||
118 IS_BETWEEN(tree_min_y, elem_max_y, tree_max_y);
125 if (LIBMESH_DIM == 3)
127 const Real & elem_min_z = bbox.first(2);
128 const Real & elem_max_z = bbox.second(2);
129 const Real & tree_min_z = this->bounding_box.first(2);
130 const Real & tree_max_z = this->bounding_box.second(2);
133 (std::abs(elem_min_z - elem_max_z) <
TOLERANCE) &&
134 (std::abs(tree_min_z - tree_max_z) <
TOLERANCE) &&
135 (std::abs(elem_min_z - tree_max_z) <
TOLERANCE);
138 bboxes_intersect = z_match && x_int && y_int;
143 libmesh_not_implemented();
150 if (!bboxes_intersect)
156 elements.push_back (elem);
158 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 163 this->contains_ifems =
true;
167 unsigned int element_count = cast_int<unsigned int>(elements.size());
171 if (elem_dimensions.size() > 1)
174 unsigned char highest_dim_elem = *elem_dimensions.rbegin();
175 for (
const Elem * other_elem : elements)
176 if (other_elem->dim() == highest_dim_elem)
182 if (element_count == tgt_bin_size)
190 libmesh_assert_equal_to (children.size(), N);
192 bool was_inserted =
false;
193 for (
unsigned int c=0; c<N; c++)
194 if (children[c]->insert (elem))
201 template <
unsigned int N>
213 unsigned int new_target_bin_size = tgt_bin_size;
214 if (level() >= target_bin_size_increase_level)
216 new_target_bin_size *= 2;
219 for (
unsigned int c=0; c<N; c++)
222 children[c] = std::make_unique<TreeNode<N>>(
mesh, new_target_bin_size,
this);
226 for (
const Node * node : nodes)
227 children[c]->insert(node);
230 for (
const Elem * elem : elements)
231 children[c]->insert(elem);
237 std::vector<const Node *>().swap(nodes);
238 std::vector<const Elem *>().swap(elements);
240 libmesh_assert_equal_to (nodes.capacity(), 0);
241 libmesh_assert_equal_to (elements.capacity(), 0);
246 template <
unsigned int N>
254 template <
unsigned int N>
256 Real relative_tol)
const 259 return bounds_point(*nd, relative_tol);
264 template <
unsigned int N>
266 Real relative_tol)
const 268 const Point & min = bounding_box.first;
269 const Point & max = bounding_box.second;
271 const Real tol = (max - min).
norm() * relative_tol;
273 if ((p(0) >= min(0) - tol)
274 && (p(0) <= max(0) + tol)
276 && (p(1) >= min(1) - tol)
277 && (p(1) <= max(1) + tol)
280 && (p(2) >= min(2) - tol)
281 && (p(2) <= max(2) + tol)
291 template <
unsigned int N>
300 const Real xmin = bounding_box.first(0);
301 const Real ymin = bounding_box.first(1);
302 const Real zmin = bounding_box.first(2);
304 const Real xmax = bounding_box.second(0);
305 const Real ymax = bounding_box.second(1);
306 const Real zmax = bounding_box.second(2);
308 const Real xc = .5*(xmin + xmax);
309 const Real yc = .5*(ymin + ymax);
310 const Real zc = .5*(zmin + zmax);
319 Point(xmax, yc, zc));
322 Point(xc, ymax, zc));
325 Point(xmax, ymax, zc));
328 Point(xc, yc, zmax));
331 Point(xmax, yc, zmax));
334 Point(xc, ymax, zmax));
337 Point(xmax, ymax, zmax));
339 libmesh_error_msg(
"c >= N! : " << c);
348 const Real xmin = bounding_box.first(0);
349 const Real ymin = bounding_box.first(1);
351 const Real xmax = bounding_box.second(0);
352 const Real ymax = bounding_box.second(1);
354 const Real xc = .5*(xmin + xmax);
355 const Real yc = .5*(ymin + ymax);
372 libmesh_error_msg(
"c >= N!");
381 const Real xmin = bounding_box.first(0);
383 const Real xmax = bounding_box.second(0);
385 const Real xc = .5*(xmin + xmax);
396 libmesh_error_msg(
"c >= N!");
403 libmesh_error_msg(
"Only implemented for Octrees, QuadTrees, and Binary Trees!");
409 template <
unsigned int N>
414 out_stream <<
"TreeNode Level: " << this->level() << std::endl;
416 for (
const Node * node : nodes)
417 out_stream <<
" " << node->id();
419 out_stream << std::endl << std::endl;
422 for (
const auto & child : children)
423 child->print_nodes();
428 template <
unsigned int N>
433 out_stream <<
"TreeNode Level: " << this->level() << std::endl;
435 for (
const auto & elem : elements)
436 out_stream <<
" " << elem;
438 out_stream << std::endl << std::endl;
441 for (
const auto & child : children)
442 child->print_elements();
447 template <
unsigned int N>
457 std::set<const Elem *> elements_set;
459 for (
const Node * node : nodes)
466 libmesh_assert_less (node_number, nodes_to_elem.size());
468 for (
const Elem * elem : nodes_to_elem[node_number])
469 elements_set.insert(elem);
473 std::vector<const Node *>().swap(nodes);
479 elements.reserve(elements_set.size());
481 for (
const auto & elem : elements_set)
483 elements.push_back(elem);
485 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 489 if (elem->infinite())
490 this->contains_ifems =
true;
496 for (
auto & child : children)
497 child->transform_nodes_to_elements (nodes_to_elem);
502 template <
unsigned int N>
512 std::set<const Elem *> elements_set;
514 for (
const Node * node : nodes)
522 auto & my_elems = nodes_to_elem[node_number];
523 elements_set.insert(my_elems.begin(), my_elems.end());
527 std::vector<const Node *>().swap(nodes);
533 elements.reserve(elements_set.size());
535 for (
const auto & elem : elements_set)
537 elements.push_back(elem);
539 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 543 if (elem->infinite())
544 this->contains_ifems =
true;
550 for (
auto & child : children)
551 child->transform_nodes_to_elements (nodes_to_elem);
556 template <
unsigned int N>
566 for (
const auto & child : children)
567 sum += child->n_active_bins();
575 template <
unsigned int N>
578 const std::set<subdomain_id_type> * allowed_subdomains,
579 Real relative_tol)
const 585 if (this->bounds_point(p, relative_tol) || this->contains_ifems)
587 for (
const auto & elem : elements)
588 if (!allowed_subdomains || allowed_subdomains->count(elem->subdomain_id()))
592 ? elem->close_to_point(p, relative_tol)
593 : elem->contains_point(p);
603 return this->find_element_in_children(p,allowed_subdomains,
609 template <
unsigned int N>
612 std::set<const Elem *> & candidate_elements,
613 const std::set<subdomain_id_type> * allowed_subdomains,
614 Real relative_tol)
const 620 if (this->bounds_point(p, relative_tol) || this->contains_ifems)
622 for (
const auto & elem : elements)
623 if (!allowed_subdomains || allowed_subdomains->count(elem->subdomain_id()))
627 ? elem->close_to_point(p, relative_tol)
628 : elem->contains_point(p);
631 candidate_elements.insert(elem);
635 this->find_elements_in_children(p, candidate_elements,
636 allowed_subdomains, relative_tol);
641 template <
unsigned int N>
643 const std::set<subdomain_id_type> * allowed_subdomains,
644 Real relative_tol)
const 649 auto searched_child = std::array<bool, N>();
654 if (children[c]->bounds_point(p, relative_tol))
657 children[c]->find_element(p,allowed_subdomains,
668 searched_child[c] =
true;
677 if (!searched_child[c])
680 children[c]->find_element(p,allowed_subdomains,
697 template <
unsigned int N>
699 std::set<const Elem *> & candidate_elements,
700 const std::set<subdomain_id_type> * allowed_subdomains,
701 Real relative_tol)
const 707 for (std::size_t c=0; c<children.size(); c++)
708 if (children[c]->bounds_point(p, relative_tol))
709 children[c]->find_elements(p, candidate_elements,
710 allowed_subdomains, relative_tol);
BoundingBox create_bounding_box(unsigned int c) const
Constructs the bounding box for child c.
A Node is like a Point, but with more information.
void refine()
Refine the tree node into N children if it contains more than tol nodes.
static constexpr Real TOLERANCE
bool intersects(const BoundingBox &) const
bool bounds_point(const Point &p, Real relative_tol=0) const
unsigned int n_active_bins() const
bool get_count_lower_dim_elems_in_point_locator() const
Get the current value of _count_lower_dim_elems_in_point_locator.
This is the base class from which all geometric element types are derived.
virtual BoundingBox loose_bounding_box() const
void transform_nodes_to_elements(std::vector< std::vector< const Elem *>> &nodes_to_elem)
Transforms node numbers to element pointers.
bool bounds_node(const Node *nd, Real relative_tol=0) const
The libMesh namespace provides an interface to certain functionality in the library.
bool insert(const Node *nd)
Tries to insert Node nd into the TreeNode.
const Elem * find_element_in_children(const Point &p, const std::set< subdomain_id_type > *allowed_subdomains, Real relative_tol) const
Look for point p in our children, optionally restricted to a set of allowed subdomains.
void find_elements(const Point &p, std::set< const Elem *> &candidate_elements, const std::set< subdomain_id_type > *allowed_subdomains=nullptr, Real relative_tol=TOLERANCE) const
Adds to candidate_elements any elements containing the specified point p, optionally restricted to a ...
void print_nodes(std::ostream &out_stream=libMesh::out) const
Prints the contents of the node_numbers vector if we are active.
const std::set< unsigned char > & elem_dimensions() const
This class defines a node on a tree.
void find_elements_in_children(const Point &p, std::set< const Elem *> &candidate_elements, const std::set< subdomain_id_type > *allowed_subdomains, Real relative_tol) const
Look for points in our children, optionally restricted to a set of allowed subdomains.
Defines a Cartesian bounding box by the two corner extremum.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const Elem * find_element(const Point &p, const std::set< subdomain_id_type > *allowed_subdomains=nullptr, Real relative_tol=TOLERANCE) const
void print_elements(std::ostream &out_stream=libMesh::out) const
Prints the contents of the elements set if we are active.
virtual bool infinite() const =0
void set_bounding_box(const std::pair< Point, Point > &bbox)
Sets the bounding box;.
A Point defines a location in LIBMESH_DIM dimensional Real space.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
virtual dof_id_type n_nodes() const =0