Go to the documentation of this file.
24 #include <unordered_map>
27 #include <sys/types.h>
31 #include "libmesh/boundary_info.h"
32 #include "libmesh/ghosting_functor.h"
33 #include "libmesh/unstructured_mesh.h"
34 #include "libmesh/libmesh_logging.h"
35 #include "libmesh/elem.h"
36 #include "libmesh/mesh_tools.h"
37 #include "libmesh/parallel.h"
38 #include "libmesh/remote_elem.h"
39 #include "libmesh/namebased_io.h"
40 #include "libmesh/partitioner.h"
41 #include "libmesh/enum_order.h"
42 #include "libmesh/mesh_communication.h"
62 const bool skip_find_neighbors,
66 #ifdef LIBMESH_ENABLE_UNIQUE_ID
71 LOG_SCOPE(
"copy_nodes_and_elements()",
"UnstructuredMesh");
73 std::pair<std::vector<unsigned int>, std::vector<unsigned int>>
76 const unsigned int n_old_node_ints = extra_int_maps.second.size(),
78 n_old_elem_ints = extra_int_maps.first.size(),
95 MeshTools::libmesh_assert_valid_procids<Node>(other_mesh);
106 (wrap_proc_ids ? oldn->processor_id() %
_n_parts : oldn->processor_id());
111 oldn->id() + node_id_offset,
115 for (
unsigned int i = 0; i != n_old_node_ints; ++i)
116 newn->set_extra_integer(extra_int_maps.second[i],
117 oldn->get_extra_integer(i));
119 #ifdef LIBMESH_ENABLE_UNIQUE_ID
120 newn->set_unique_id() =
121 oldn->unique_id() + unique_id_offset;
132 typedef std::unordered_map<const Elem *, Elem *> map_type;
133 map_type old_elems_to_new_elems;
140 this->
elem_ptr(old->parent()->id() + element_id_offset) :
142 std::unique_ptr<Elem> ap =
Elem::build(old->type(), newparent);
143 Elem * el = ap.release();
147 #ifdef LIBMESH_ENABLE_AMR
148 if (old->has_children())
149 for (
unsigned int c = 0, nc = old->n_children(); c != nc; ++c)
151 el->add_child(const_cast<RemoteElem *>(
remote_elem), c);
156 unsigned int oldc = old->parent()->which_child_am_i(old);
161 el->set_refinement_flag(old->refinement_flag());
165 el->hack_p_level(old->p_level());
167 el->set_p_refinement_flag(old->p_refinement_flag());
168 #endif // #ifdef LIBMESH_ENABLE_AMR
171 for (
auto i : el->node_index_range())
173 this->
node_ptr(old->node_id(i) + node_id_offset);
177 (wrap_proc_ids ? old->processor_id() %
_n_parts : old->processor_id());
180 el->set_id(old->id() + element_id_offset);
182 el->add_extra_integers(n_new_elem_ints);
183 for (
unsigned int i = 0; i != n_old_elem_ints; ++i)
184 el->set_extra_integer(extra_int_maps.first[i],
185 old->get_extra_integer(i));
187 #ifdef LIBMESH_ENABLE_UNIQUE_ID
188 el->set_unique_id() =
189 old->unique_id() + unique_id_offset;
193 if (!skip_find_neighbors)
195 for (
auto s : old->side_index_range())
197 el->set_neighbor(s, const_cast<RemoteElem *>(
remote_elem));
203 old_elems_to_new_elems[old] = new_el;
208 if (skip_find_neighbors)
214 Elem * new_elem = old_elems_to_new_elems[old_elem];
215 for (
auto s : old_elem->side_index_range())
218 Elem * new_neighbor = old_elems_to_new_elems[old_neighbor];
258 const bool reset_current_list)
266 parallel_object_only();
268 LOG_SCOPE(
"find_neighbors()",
"Mesh");
271 if (reset_current_list)
273 for (
auto s : e->side_index_range())
274 if (e->neighbor_ptr(s) !=
remote_elem || reset_remote_elements)
275 e->set_neighbor(s,
nullptr);
282 typedef unsigned int key_type;
283 typedef std::pair<Elem *, unsigned char> val_type;
284 typedef std::pair<key_type, val_type> key_val_pair;
286 typedef std::unordered_multimap<key_type, val_type> map_type;
289 map_type side_to_elem_map;
292 std::unique_ptr<Elem> my_side, their_side;
296 for (
auto ms : element->side_index_range())
302 if (element->neighbor_ptr(ms) ==
nullptr ||
306 const unsigned int key = element->key(ms);
309 auto bounds = side_to_elem_map.equal_range(key);
313 if (bounds.first != bounds.second)
316 element->side_ptr(my_side, ms);
319 while (bounds.first != bounds.second)
322 Elem * neighbor = bounds.first->second.first;
325 const unsigned int ns = bounds.first->second.second;
338 if ((*my_side == *their_side) &&
339 (element->level() == neighbor->
level()) &&
340 ((element->dim() != 1) || (ns != ms)))
348 if (element->subactive() ==
353 element->set_neighbor (ms,neighbor);
356 else if (element->subactive())
358 element->set_neighbor(ms,neighbor);
364 side_to_elem_map.erase (bounds.first);
379 kvp.second.first = element;
380 kvp.second.second = cast_int<unsigned char>(ms);
381 side_to_elem_map.insert (kvp);
387 #ifdef LIBMESH_ENABLE_AMR
417 for (
unsigned int level = 1; level <
n_levels; ++level)
427 for (
auto s : current_elem->side_index_range())
429 if (current_elem->neighbor_ptr(s) ==
nullptr ||
446 (neigh->
level()+1) == current_elem->level())))
452 bool neigh_has_remote_children =
false;
455 neigh_has_remote_children =
true;
460 if (current_elem->active())
461 libmesh_assert_not_equal_to (current_elem->processor_id(),
469 else if (neigh && (current_elem->subactive() &&
482 bool found_neigh =
false;
483 for (
unsigned int c = 0, nc = neigh->
n_children();
484 !found_neigh && c != nc; ++c)
504 current_elem->set_neighbor(s, neigh);
509 if ((!neigh->
active()) && (!current_elem->subactive()))
513 libMesh::err <<
"Bad element ID = " << current_elem->id()
514 <<
", Side " << s <<
", Bad neighbor ID = " << neigh->
id() << std::endl;
515 libMesh::err <<
"Bad element proc_ID = " << current_elem->processor_id()
516 <<
", Bad neighbor proc_ID = " << neigh->
processor_id() << std::endl;
517 libMesh::err <<
"Bad element size = " << current_elem->hmin()
518 <<
", Bad neighbor size = " << neigh->
hmin() << std::endl;
519 libMesh::err <<
"Bad element center = " << current_elem->centroid()
520 <<
", Bad neighbor center = " << neigh->
centroid() << std::endl;
522 << (current_elem->active()?
"Active":
"Ancestor")
523 <<
" Element at level "
524 << current_elem->level() << std::endl;
526 << (parent->
active()?
"active":
527 (parent->
subactive()?
"subactive":
"ancestor"))
529 << (neigh->
subactive()?
"subactive":
"ancestor")
530 <<
" neighbor at level " << neigh->
level()
533 libmesh_error_msg(
"Problematic mesh written to bad_mesh.gmv.");
541 if (current_elem->dim() >= LIBMESH_DIM)
545 current_elem->set_interior_parent(
nullptr);
573 current_elem->set_interior_parent
578 bool child_contains_our_nodes =
true;
579 for (
auto & n : current_elem->node_ref_range())
581 bool child_contains_this_node =
false;
582 for (
auto & cn : child.node_ref_range())
583 if (cn.absolute_fuzzy_equals
586 child_contains_this_node =
true;
589 if (!child_contains_this_node)
591 child_contains_our_nodes =
false;
595 if (child_contains_our_nodes)
597 current_elem->set_interior_parent(&child);
613 !reset_remote_elements);
622 bool skip_renumber_nodes_and_elements,
623 bool skip_find_neighbors)
631 if (
name.rfind(
".gmv") + 4 ==
name.size())
636 if (skip_renumber_nodes_and_elements)
639 libmesh_deprecated();
645 skip_find_neighbors);
652 LOG_SCOPE(
"write()",
"Mesh");
660 const std::vector<Number> & v,
661 const std::vector<std::string> & vn)
663 LOG_SCOPE(
"write()",
"Mesh");
685 <<
"mesh for a processor id (="
688 <<
"the number of processors available for "
689 <<
"the calculation. (="
725 libmesh_assert_not_equal_to (this->
n_nodes(), 0);
726 libmesh_assert_not_equal_to (this->
n_elem(), 0);
729 std::vector<boundary_id_type> bc_ids;
736 for (
const auto & old_elem :
as_range(it, it_end))
741 new_elem->
set_id() = old_elem->id();
742 #ifdef LIBMESH_ENABLE_UNIQUE_ID
749 for (
unsigned int i = 0; i != n_elem_ints; ++i)
757 for (
auto n : old_elem->node_index_range())
759 const dof_id_type this_node_id = old_elem->node_id(n);
767 old_elem->node_ptr(n)->processor_id());
770 for (
unsigned int i = 0; i != n_node_ints; ++i)
773 #ifdef LIBMESH_ENABLE_UNIQUE_ID
783 for (
auto s : old_elem->side_index_range())
796 #ifdef LIBMESH_ENABLE_AMR
799 LOG_SCOPE (
"contract()",
"Mesh");
802 bool mesh_changed =
false;
856 #endif // #ifdef LIBMESH_ENABLE_AMR
871 START_LOG(
"all_first_order()",
"Mesh");
876 std::vector<bool> node_touched_by_me(this->
max_node_id(),
false);
891 (so_elem->type()), so_elem->parent()).release();
893 const unsigned short n_sides = so_elem->n_sides();
895 for (
unsigned short s=0; s != n_sides; ++s)
899 #ifdef LIBMESH_ENABLE_AMR
903 if (so_elem->has_children())
904 for (
unsigned int c = 0, nc = so_elem->n_children(); c != nc; ++c)
915 if (so_elem->parent())
918 so_elem->parent()->which_child_am_i(so_elem);
930 libmesh_assert_equal_to (lo_elem->
n_vertices(), so_elem->n_vertices());
937 for (
unsigned int v=0, snv=so_elem->n_vertices(); v < snv; v++)
939 lo_elem->
set_node(v) = so_elem->node_ptr(v);
940 node_touched_by_me[lo_elem->
node_id(v)] =
true;
947 for (
unsigned short s=0; s != n_sides; s++)
967 lo_elem->
set_id(so_elem->id());
968 #ifdef LIBMESH_ENABLE_UNIQUE_ID
978 if (!node_touched_by_me[
node->
id()])
986 STOP_LOG(
"all_first_order()",
"Mesh");
1001 parallel_object_only();
1026 bool already_second_order =
false;
1029 already_second_order =
true;
1030 this->
comm().max(already_second_order);
1031 if (already_second_order)
1034 START_LOG(
"all_second_order()",
"Mesh");
1048 std::map<std::vector<dof_id_type>,
Node *> adj_vertices_to_so_nodes;
1064 (1.5*static_cast<double>(this->
n_nodes())));
1073 (2*static_cast<double>(this->
n_nodes())));
1085 (2.5*static_cast<double>(this->
n_nodes())));
1090 libmesh_error_msg(
"Unknown mesh dimension " << this->
mesh_dimension());
1102 std::vector<dof_id_type> adjacent_vertices_ids;
1111 n_partitioned_elem = 0;
1124 for (; it != endit; ++it)
1127 Elem * lo_elem = *it;
1133 libmesh_error_msg(
"ERROR: This is not a linear element: type=" << lo_elem->
type());
1136 libmesh_assert_equal_to (lo_elem->
level (), 0);
1143 ++n_partitioned_elem;
1155 full_ordered) ).release();
1165 for (
unsigned int v=0, lnv=lo_elem->
n_vertices(); v < lnv; v++)
1176 const unsigned int son_begin = so_elem->
n_vertices();
1177 const unsigned int son_end = so_elem->
n_nodes();
1180 for (
unsigned int son=son_begin; son<son_end; son++)
1182 const unsigned int n_adjacent_vertices =
1185 adjacent_vertices_ids.resize(n_adjacent_vertices);
1187 for (
unsigned int v=0; v<n_adjacent_vertices; v++)
1188 adjacent_vertices_ids[v] =
1197 std::sort(adjacent_vertices_ids.begin(),
1198 adjacent_vertices_ids.end());
1202 auto pos = adj_vertices_to_so_nodes.equal_range (adjacent_vertices_ids);
1205 if (pos.first == pos.second)
1214 Point new_location = this->
point(adjacent_vertices_ids[0]);
1215 for (
unsigned int v=1; v<n_adjacent_vertices; v++)
1216 new_location += this->
point(adjacent_vertices_ids[v]);
1218 new_location /= static_cast<Real>(n_adjacent_vertices);
1240 adj_vertices_to_so_nodes.insert(pos.first,
1241 std::make_pair(adjacent_vertices_ids,
1249 Node * so_node = pos.first->second;
1267 chosen_pid == my_pid)
1304 #ifdef LIBMESH_ENABLE_UNIQUE_ID
1313 adj_vertices_to_so_nodes.clear();
1316 STOP_LOG(
"all_second_order()",
"Mesh");
1327 this->
comm().max(max_unpartitioned_elem);
1328 if (max_unpartitioned_elem)
1334 !this->
comm().verify(n_partitioned_elem) ||
1336 libmesh_not_implemented();
friend class MeshCommunication
Make the MeshCommunication class a friend so that it can directly broadcast *_integer_names.
bool _is_prepared
Flag indicating if the mesh has been prepared for use.
std::set< GhostingFunctor * >::const_iterator ghosting_functors_begin() const
Beginning of range of ghosting functors.
std::vector< boundary_id_type > boundary_ids(const Node *node) const
const Elem * child_ptr(unsigned int i) const
std::set< GhostingFunctor * >::const_iterator ghosting_functors_end() const
End of range of ghosting functors.
bool allow_renumbering() const
The definition of the element_iterator struct.
virtual unsigned int n_second_order_adjacent_vertices(const unsigned int n) const
virtual void delete_node(Node *n)=0
Removes the Node n from the mesh.
virtual void reserve_nodes(const dof_id_type nn)=0
Reserves space for a known number of nodes.
void replace_child(Elem *elem, unsigned int c)
Replaces the child pointer at the specified index in the child array.
void set_p_refinement_flag(const RefinementState pflag)
Sets the value of the p-refinement flag for the element.
virtual void write(const std::string &mesh_file) override
This method implements writing a mesh to a specified file.
std::pair< std::vector< unsigned int >, std::vector< unsigned int > > merge_extra_integer_names(const MeshBase &other)
Merge extra-integer arrays from an other mesh.
virtual void find_neighbors(const bool reset_remote_elements=false, const bool reset_current_list=true) override
Other functions from MeshBase requiring re-definition.
void set_parent(Elem *p)
Sets the pointer to the element's parent.
virtual element_iterator active_pid_elements_end(processor_id_type proc_id)=0
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
void set_interior_parent(Elem *p)
Sets the pointer to the element's interior_parent.
virtual bool is_serial() const
unsigned int level() const
SimpleRange< ChildRefIter > child_ref_range()
Returns a range with all children of a parent element, usable in range-based for loops.
virtual unsigned int n_nodes() const =0
void create_pid_mesh(UnstructuredMesh &pid_mesh, const processor_id_type pid) const
Generates a new mesh containing all the elements which are assigned to processor pid.
virtual const Point & point(const dof_id_type i) const =0
virtual void delete_elem(Elem *e)=0
Removes element e from the mesh.
void contract()
Contract an active element, i.e.
virtual dof_id_type n_elem() const =0
virtual void copy_nodes_and_elements(const UnstructuredMesh &other_mesh, const bool skip_find_neighbors=false, dof_id_type element_id_offset=0, dof_id_type node_id_offset=0, unique_id_type unique_id_offset=0)
Deep copy of nodes and elements from another unstructured mesh class (used by subclass copy construct...
The libMesh namespace provides an interface to certain functionality in the library.
void set_p_level(const unsigned int p)
Sets the value of the p-refinement level for the element.
bool _skip_all_partitioning
If this is true then no partitioning should be done.
void add_child(Elem *elem)
Adds a child pointer to the array of children of this element.
unsigned int _n_parts
The number of partitions the mesh has.
static const Real TOLERANCE
void add_extra_integers(const unsigned int n_integers)
Assigns a set of extra integers to this DofObject.
const Parallel::Communicator & comm() const
void set_neighbor(const unsigned int i, Elem *n)
Assigns n as the neighbor.
SimpleRange< NeighborPtrIter > neighbor_ptr_range()
Returns a range with all neighbors of an element, usable in range-based for loops.
virtual const Node * node_ptr(const dof_id_type i) const =0
unsigned int mesh_dimension() const
unique_id_type & set_unique_id()
virtual dof_id_type max_node_id() const =0
virtual element_iterator active_pid_elements_begin(processor_id_type proc_id)=0
processor_id_type processor_id() const
virtual const Elem * elem_ptr(const dof_id_type i) const =0
virtual element_iterator elements_begin()=0
Iterate over all the elements in the Mesh.
virtual Point centroid() const
void copy_boundary_ids(const BoundaryInfo &old_boundary_info, const Elem *const old_elem, const Elem *const new_elem)
virtual void all_first_order() override
Converts a mesh with higher-order elements into a mesh with linear elements.
virtual ~UnstructuredMesh()
Destructor.
virtual void write(const std::string &name) override
Write the file specified by name.
virtual unsigned short int second_order_adjacent_vertex(const unsigned int n, const unsigned int v) const
virtual SimpleRange< element_iterator > element_ptr_range()=0
virtual void own_node(Node &)
Takes ownership of node n on this partition of a distributed mesh, by setting n.processor_id() to thi...
This is the MeshBase class.
virtual element_iterator level_elements_begin(unsigned int level)=0
Iterate over elements of a given level.
std::vector< std::string > _elem_integer_names
The array of names for integer data associated with each element in the mesh.
processor_id_type n_processors() const
virtual SimpleRange< node_iterator > node_ptr_range()=0
virtual bool contract() override
Delete subactive (i.e.
virtual const Elem * elem(const dof_id_type i) const
void clear_point_locator()
Releases the current PointLocator object.
static ElemType first_order_equivalent_type(const ElemType et)
virtual void read(const std::string &mesh_file) override
This method implements reading a mesh from a specified file.
processor_id_type processor_id() const
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
A Point defines a location in LIBMESH_DIM dimensional Real space.
virtual std::unique_ptr< Elem > side_ptr(unsigned int i)=0
virtual void read(const std::string &name, void *mesh_data=nullptr, bool skip_renumber_nodes_and_elements=false, bool skip_find_neighbors=false) override
Reads the file specified by name.
uint8_t processor_id_type
bool skip_noncritical_partitioning() const
virtual Elem * insert_elem(Elem *e)=0
Insert elem e to the element array, preserving its id and replacing/deleting any existing element wit...
virtual unsigned int n_vertices() const =0
A Node is like a Point, but with more information.
virtual Order default_order() const =0
virtual const Node & node(const dof_id_type i) const
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
virtual bool is_child_on_side(const unsigned int c, const unsigned int s) const =0
unique_id_type unique_id() const
void regenerate_id_sets()
Clears and regenerates the cached sets of ids.
The definition of the const_element_iterator struct.
UnstructuredMesh(const Parallel::Communicator &comm_in, unsigned char dim=1)
Constructor.
std::vector< std::string > _node_integer_names
The array of names for integer data associated with each node in the mesh.
virtual void delete_remote_elements()
When supported, deletes all nonlocal elements of the mesh except for "ghosts" which touch a local ele...
virtual Node *& set_node(const unsigned int i)
The UnstructuredMesh class is derived from the MeshBase class.
virtual void renumber_nodes_and_elements()=0
After partitioning a mesh it is useful to renumber the nodes and elements so that they lie in contigu...
const Elem * parent() const
virtual dof_id_type n_nodes() const =0
bool initialized()
Checks that library initialization has been done.
const Elem * interior_parent() const
virtual unsigned int n_children() const =0
bool is_ancestor_of(const Elem *descendant) const
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
virtual Real hmin() const
static void set_node_processor_ids(MeshBase &mesh)
This function is called after partitioning to set the processor IDs for the nodes.
dof_id_type n_unpartitioned_elem() const
subdomain_id_type subdomain_id() const
virtual element_iterator elements_end()=0
virtual void all_second_order(const bool full_ordered=true) override
Converts a (conforming, non-refined) mesh with linear elements into a mesh with second-order elements...
bool has_children() const
IntRange< unsigned short > side_index_range() const
static const processor_id_type invalid_processor_id
An invalid processor_id to distinguish DoFs that have not been assigned to a processor.
This is the base class from which all geometric element types are derived.
static ElemType second_order_equivalent_type(const ElemType et, const bool full_ordered=true)
void create_submesh(UnstructuredMesh &new_mesh, const const_element_iterator &it, const const_element_iterator &it_end) const
Constructs a mesh called "new_mesh" from the current mesh by iterating over the elements between it a...
bool allow_remote_element_removal() const
void allow_remote_element_removal(bool allow)
If false is passed in then this mesh will no longer have remote elements deleted when being prepared ...
void set_refinement_flag(const RefinementState rflag)
Sets the value of the refinement flag for the element.
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id)=0
Add a new Node at Point p to the end of the vertex array, with processor_id procid.
This class supports simple reads and writes in any libMesh-supported format, by dispatching to one of...
virtual element_iterator level_elements_end(unsigned int level)=0
const Elem * neighbor_ptr(unsigned int i) const
void allow_renumbering(bool allow)
If false is passed in then this mesh will no longer be renumbered when being prepared for use.
dof_id_type node_id(const unsigned int i) const
void set_extra_integer(const unsigned int index, const dof_id_type value)
Sets the value on this object of the extra integer associated with index, which should have been obta...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void prepare_for_use(const bool skip_renumber_nodes_and_elements=false, const bool skip_find_neighbors=false)
Prepare a newly ecreated (or read) mesh for use.
virtual void clear()
Deletes all the element and node data that is currently stored.
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
virtual const Node * query_node_ptr(const dof_id_type i) const =0
const Node * node_ptr(const unsigned int i) const
bool _skip_noncritical_partitioning
If this is true then no partitioning should be done with the possible exception of orphaned nodes.
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
Add side side of element number elem with boundary id id to the boundary information data structure.
virtual ElemType type() const =0
bool skip_partitioning() const
const RemoteElem * remote_elem
virtual void reserve_elem(const dof_id_type ne)=0
Reserves space for a known number of elements.
unsigned int which_child_am_i(const Elem *e) const
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
virtual bool is_replicated() const
virtual void write_nodal_data(const std::string &, const std::vector< Number > &, const std::vector< std::string > &) override
This method implements writing a mesh with nodal data to a specified file where the nodal data and va...
bool closed()
Checks that the library has been closed.