21 #include "libmesh/distributed_mesh.h" 24 #include "libmesh/boundary_info.h" 25 #include "libmesh/elem.h" 26 #include "libmesh/libmesh_logging.h" 27 #include "libmesh/mesh_communication.h" 28 #include "libmesh/mesh_tools.h" 29 #include "libmesh/partitioner.h" 30 #include "libmesh/string_to_enum.h" 45 _is_serial_on_proc_0(true),
46 _deleted_coarse_elements(false),
47 _n_nodes(0), _n_elem(0), _max_node_id(0), _max_elem_id(0),
48 _next_free_local_node_id(this->processor_id()),
49 _next_free_local_elem_id(this->processor_id()),
50 _next_free_unpartitioned_node_id(this->n_processors()),
51 _next_free_unpartitioned_elem_id(this->n_processors())
52 #ifdef LIBMESH_ENABLE_UNIQUE_ID
53 , _next_unpartitioned_unique_id(this->n_processors())
56 #ifdef LIBMESH_ENABLE_UNIQUE_ID 60 const std::string default_partitioner =
"parmetis";
61 const std::string my_partitioner =
65 (Utility::string_to_enum<PartitionerType>(my_partitioner));
70 LOG_SCOPE(
"operator=(&&)",
"DistributedMesh");
93 *
this = std::move(cast_ref<DistributedMesh&>(other_mesh));
124 !this->nodes_and_elements_equal(other_mesh))
170 #ifdef LIBMESH_ENABLE_UNIQUE_ID 186 _is_serial_on_proc_0(other_mesh.is_serial()),
187 _deleted_coarse_elements(true),
188 _n_nodes(0), _n_elem(0), _max_node_id(0), _max_elem_id(0),
189 _next_free_local_node_id(this->processor_id()),
190 _next_free_local_elem_id(this->processor_id()),
191 _next_free_unpartitioned_node_id(this->n_processors()),
192 _next_free_unpartitioned_elem_id(this->n_processors())
213 this_boundary_info = other_boundary_info;
217 #ifdef LIBMESH_ENABLE_UNIQUE_ID 228 DistributedMesh & other_mesh = cast_ref<DistributedMesh&>(other_meshbase);
248 #ifdef LIBMESH_ENABLE_UNIQUE_ID 260 parallel_object_only();
285 #ifdef LIBMESH_ENABLE_UNIQUE_ID 302 parallel_object_only();
315 parallel_object_only();
328 for (; rit != rend; ++rit)
334 max_local = d->
id() + 1;
345 #ifdef LIBMESH_ENABLE_UNIQUE_ID 349 parallel_object_only();
376 parallel_object_only();
389 parallel_object_only();
402 for (; rit != rend; ++rit)
408 max_local = d->
id() + 1;
429 libmesh_assert_equal_to (
_nodes[i]->
id(), i);
440 libmesh_assert_equal_to (
_nodes[i]->
id(), i);
450 if (
const auto it =
_nodes.find(i);
453 const Node * n = *it;
466 if (
auto it =
_nodes.find(i);
483 libmesh_assert_equal_to (
_elements[i]->
id(), i);
494 libmesh_assert_equal_to (
_elements[i]->
id(), i);
507 const Elem * e = *it;
566 static_cast<dof_id_type>(e->
id()+1));
596 #ifdef LIBMESH_ENABLE_UNIQUE_ID 661 #ifdef LIBMESH_ENABLE_UNIQUE_ID 752 if (old_id == new_id)
757 libmesh_assert_equal_to (el->
id(), old_id);
835 static_cast<dof_id_type>(n->
id()+1));
865 #ifdef LIBMESH_ENABLE_UNIQUE_ID 915 #ifdef LIBMESH_ENABLE_DEPRECATED 919 libmesh_deprecated();
925 libmesh_deprecated();
962 if (old_id == new_id)
967 libmesh_assert_equal_to (nd->
id(), old_id);
977 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 1008 for (
auto & node :
_nodes)
1089 template <
typename T>
1093 parallel_object_only();
1097 const dof_id_type pmax_id = std::max(pmax_node_id, pmax_elem_id);
1101 T * obj = objects[i];
1108 const dof_id_type dofid = obj && obj->valid_id() ?
1114 const dof_id_type procid = obj && obj->valid_processor_id() ?
1136 #if defined(LIBMESH_ENABLE_UNIQUE_ID) && !defined(NDEBUG) 1158 parallel_object_only();
1179 #if defined(LIBMESH_ENABLE_AMR) && !defined(NDEBUG) 1181 parallel_object_only();
1189 unsigned int refinement_flag = el ?
1191 unsigned int p_refinement_flag = el ?
1200 #endif // LIBMESH_ENABLE_AMR 1205 template <
typename T>
1210 parallel_object_only();
1218 std::unordered_map<processor_id_type, dof_id_type>
1219 ghost_objects_from_proc;
1221 object_iterator it = objects.
begin();
1222 object_iterator end = objects.
end();
1230 it = objects.
erase(it);
1235 unpartitioned_objects++;
1237 ghost_objects_from_proc[obj_procid]++;
1244 std::vector<dof_id_type> objects_on_proc(this->
n_processors(), 0);
1245 auto this_it = ghost_objects_from_proc.find(this->
processor_id());
1247 ((this_it == ghost_objects_from_proc.end()) ?
1248 dof_id_type(0) : this_it->second, objects_on_proc);
1253 if (ghost_objects_from_proc.count(p))
1254 libmesh_assert_less_equal (ghost_objects_from_proc[p], objects_on_proc[p]);
1256 libmesh_assert_less_equal (0, objects_on_proc[p]);
1260 std::vector<dof_id_type> first_object_on_proc(this->
n_processors());
1262 first_object_on_proc[i] = first_object_on_proc[i-1] +
1263 objects_on_proc[i-1];
1268 unpartitioned_objects;
1274 std::map<processor_id_type, std::vector<dof_id_type>>
1279 auto ghost_end = ghost_objects_from_proc.end();
1283 if (
const auto p_it = ghost_objects_from_proc.find(p);
1285 requested_ids[p].reserve(p_it->second);
1288 end = objects.
end();
1289 for (it = objects.
begin(); it != end; ++it)
1295 obj->set_id(next_id++);
1297 requested_ids[obj->processor_id()].push_back(obj->id());
1302 auto gather_functor =
1306 &first_object_on_proc,
1311 std::vector<dof_id_type> & new_ids)
1313 std::size_t ids_size = ids.size();
1314 new_ids.resize(ids_size);
1316 for (std::size_t i=0; i != ids_size; ++i)
1318 T * obj = objects[ids[i]];
1320 libmesh_assert_equal_to (obj->processor_id(), this->
processor_id());
1321 new_ids[i] = obj->id();
1323 libmesh_assert_greater_equal (new_ids[i],
1325 libmesh_assert_less (new_ids[i],
1331 auto action_functor =
1334 &first_object_on_proc,
1339 const std::vector<dof_id_type> & ids,
1340 const std::vector<dof_id_type> & data)
1345 T * obj = objects[ids[i]];
1347 libmesh_assert_equal_to (obj->processor_id(),
pid);
1348 libmesh_assert_greater_equal (data[i],
1349 first_object_on_proc[
pid]);
1350 libmesh_assert_less (data[i],
1351 first_object_on_proc[
pid] +
1352 objects_on_proc[
pid]);
1353 obj->set_id(data[i]);
1358 Parallel::pull_parallel_vector_data
1359 (this->
comm(), requested_ids, gather_functor, action_functor, ex);
1361 #ifdef LIBMESH_ENABLE_UNIQUE_ID 1362 auto unique_gather_functor =
1369 std::vector<unique_id_type> & data)
1371 std::size_t ids_size = ids.size();
1372 data.resize(ids_size);
1374 for (std::size_t i=0; i != ids_size; ++i)
1376 T * obj = objects[ids[i]];
1378 libmesh_assert_equal_to (obj->processor_id(), this->
processor_id());
1383 auto unique_action_functor =
1386 const std::vector<dof_id_type> & ids,
1387 const std::vector<unique_id_type> & data)
1391 T * obj = objects[ids[i]];
1393 libmesh_assert_equal_to (obj->processor_id(),
pid);
1395 obj->set_unique_id(data[i]);
1400 Parallel::pull_parallel_vector_data
1401 (this->
comm(), requested_ids, unique_gather_functor,
1402 unique_action_functor, unique_ex);
1408 next_id += objects_on_proc[i];
1409 for (it = objects.
begin(); it != end; ++it)
1415 obj->set_id(next_id++);
1420 it = objects.
begin();
1421 end = objects.
end();
1427 T *
next = objects[obj->id()];
1441 libmesh_assert_not_equal_to (
next->id(), obj->id());
1442 objects[obj->id()] = obj;
1444 next = objects[obj->id()];
1446 objects[obj->id()] = obj;
1452 it = objects.
erase(it);
1457 return first_free_id;
1463 parallel_object_only();
1472 LOG_SCOPE(
"renumber_nodes_and_elements()",
"DistributedMesh");
1483 std::set<dof_id_type> used_nodes;
1487 std::map<processor_id_type, std::map<dof_id_type, bool>>
1491 for (
auto & elem : this->element_ptr_range())
1492 for (
const Node & node : elem->node_ref_range())
1495 used_nodes.insert(n);
1501 auto & used_nodes_on_p = used_nodes_on_proc[p];
1503 used_nodes_on_p[n] =
true;
1505 if (!used_nodes_on_p.count(n))
1506 used_nodes_on_p[n] =
false;
1514 typedef unsigned char boolish;
1515 std::map<processor_id_type, std::vector<std::pair<dof_id_type, boolish>>>
1516 used_nodes_on_proc_vecs;
1517 for (
auto & [
pid, nodemap] : used_nodes_on_proc)
1518 used_nodes_on_proc_vecs[
pid].assign(nodemap.begin(), nodemap.end());
1520 std::map<dof_id_type,processor_id_type> repartitioned_node_pids;
1521 std::map<processor_id_type, std::set<dof_id_type>>
1522 repartitioned_node_sets_to_push;
1524 auto ids_action_functor =
1525 [&used_nodes, &repartitioned_node_pids,
1526 &repartitioned_node_sets_to_push]
1528 const std::vector<std::pair<dof_id_type, boolish>> & ids_and_bools)
1530 for (
auto [n, sender_could_become_owner] : ids_and_bools)
1534 if (!used_nodes.count(n))
1536 if (
auto it = repartitioned_node_pids.find(n);
1537 sender_could_become_owner)
1539 if (it != repartitioned_node_pids.end() &&
1543 repartitioned_node_pids[n] =
pid;
1546 if (it == repartitioned_node_pids.end())
1547 repartitioned_node_pids[n] =
1550 repartitioned_node_sets_to_push[
pid].insert(n);
1558 Parallel::push_parallel_vector_data
1559 (this->
comm(), used_nodes_on_proc_vecs, ids_action_functor);
1562 for (
auto & [n, p] : repartitioned_node_pids)
1572 std::map<processor_id_type, std::vector<std::pair<dof_id_type,processor_id_type>>>
1573 repartitioned_node_vecs;
1575 for (
auto & [p, nodeset] : repartitioned_node_sets_to_push)
1577 auto & rn_vec = repartitioned_node_vecs[p];
1578 for (
auto n : nodeset)
1579 rn_vec.emplace_back(n, repartitioned_node_pids[n]);
1582 auto repartition_node_functor =
1585 const std::vector<std::pair<dof_id_type, processor_id_type>> & ids_and_pids)
1587 for (
auto [n, p] : ids_and_pids)
1596 Parallel::push_parallel_vector_data
1597 (this->
comm(), repartitioned_node_vecs, repartition_node_functor);
1613 else if (!used_nodes.count(nd->
id()))
1653 libmesh_assert_equal_to (this->
max_node_id(), pmax_node_id);
1654 libmesh_assert_equal_to (this->
max_elem_id(), pmax_elem_id);
1675 for (
auto pr = this->_nodes.begin(),
1676 end = this->_nodes.end(); pr != end; ++pr)
1683 libmesh_assert_equal_to(this->
node_ptr(
id), n);
1689 end = this->
_elements.end(); pr != end; ++pr)
1696 libmesh_assert_equal_to(this->
elem_ptr(
id), e);
1705 parallel_object_only();
1710 this->active_local_elements_end()));
1711 this->
comm().
sum(active_elements);
1719 return active_elements;
1741 libmesh_assert_equal_to (this->
max_node_id(), pmax_node_id);
1742 libmesh_assert_equal_to (this->
max_elem_id(), pmax_elem_id);
1756 while (e_it != e_end)
1764 while (n_it != n_end)
1766 n_it =
_nodes.erase(n_it);
1811 std::set<Elem *> tmp;
1814 std::inserter(tmp, tmp.begin()));
1833 libmesh_assert_equal_to (this->
max_node_id(), pmax_node_id);
1834 libmesh_assert_equal_to (this->
max_elem_id(), pmax_elem_id);
UnstructuredMesh & operator=(const UnstructuredMesh &)=delete
Copy assignment is not allowed.
This mapvector templated class is intended to provide the performance characteristics of a std::map w...
RefinementState refinement_flag() const
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) override final
functions for adding /deleting nodes elements.
virtual void update_parallel_id_counts() override
Updates parallel caches so that methods like n_elem() accurately reflect changes on other processors...
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
unique_id_type & set_unique_id()
virtual dof_id_type parallel_n_nodes() const override
const Elem * parent() const
bool _skip_renumber_nodes_and_elements
If this is true then renumbering will be kept to a minimum.
virtual Elem * add_elem(Elem *e) override final
Add elem e to the end of the element array.
virtual void copy_nodes_and_elements(const MeshBase &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, std::unordered_map< subdomain_id_type, subdomain_id_type > *id_remapping=nullptr)
Deep copy of nodes and elements from another mesh object (used by subclass copy constructors and by m...
A Node is like a Point, but with more information.
virtual unique_id_type parallel_max_unique_id() const =0
dof_id_type n_unpartitioned_nodes() const
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
std::vector< std::string > _elem_integer_names
The array of names for integer data associated with each element in the mesh.
virtual void libmesh_assert_valid_parallel_ids() const override
Verify id and processor_id consistency of our elements and nodes containers.
virtual void fix_broken_node_and_element_numbering() override
There is no reason for a user to ever call this function.
void set_mapping_type(const ElemMappingType type)
Sets the value of the mapping type for the element.
void allow_renumbering(bool allow)
If false is passed in then this mesh will no longer be renumbered when being prepared for use...
virtual void renumber_elem(dof_id_type old_id, dof_id_type new_id) override final
Changes the id of element old_id, both by changing elem(old_id)->id() and by moving elem(old_id) in t...
void skip_partitioning(bool skip)
If true is passed in then nothing on this mesh will be (re)partitioned.
bool _is_serial_on_proc_0
A boolean remembering whether we're serialized to proc 0 or not.
void copy_cached_data(const MeshBase &other_mesh)
Helper class to copy cached data, to synchronize with a possibly unprepared other_mesh.
dof_id_type _n_nodes
Cached data from the last renumber_nodes_and_elements call.
virtual void clear() override
Clear all internal data.
virtual void renumber_nodes_and_elements() override
Remove nullptr elements from arrays.
RefinementState p_refinement_flag() const
virtual dof_id_type n_nodes() const override final
dof_id_type _next_free_local_node_id
Guaranteed globally unused IDs for use when adding new nodes or elements.
void remove(const Node *node)
Removes the boundary conditions associated with node node, if any exist.
virtual void allgather() override
Gathers all elements and nodes of the mesh onto every processor.
This is the base class from which all geometric element types are derived.
dof_id_type n_local_nodes() const
constraint_rows_type _constraint_rows
unique_id_type unique_id() const
void copy_constraint_rows(const MeshBase &other_mesh)
Copy the constraints from the other mesh to this mesh.
const Parallel::Communicator & comm() const
bool _is_serial
A boolean remembering whether we're serialized or not.
unsigned int p_level() const
void libmesh_assert_valid_parallel_flags() const
Verify refinement_flag and p_refinement_flag consistency of our elements containers.
The libMesh namespace provides an interface to certain functionality in the library.
virtual void delete_elem(Elem *e) override final
Removes element e from the mesh.
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
virtual void add_extra_ghost_elem(Elem *e)
Inserts the element and adds it to a list of elements that should not get deleted or have their desce...
dof_id_type n_unpartitioned_elem() const
std::vector< std::string > _node_integer_names
The array of names for integer data associated with each node in the mesh.
virtual Node * add_node(Node *n) override final
Add Node n to the end of the vertex array.
Real distance(const Point &p)
virtual const Point & point(const dof_id_type i) const override final
virtual unique_id_type parallel_max_unique_id() const override
dof_id_type n_local_elem() const
virtual void delete_remote_elements() override
Deletes all nonlocal elements of the mesh except for "ghosts" which touch a local element...
void libmesh_assert_valid_parallel_object_ids(const dofobject_container< T > &) const
Verify id, processor_id, and if applicable unique_id consistency of a parallel objects container...
uint8_t processor_id_type
This is the MeshBase class.
void libmesh_assert_valid_parallel_p_levels() const
Verify p_level consistency of our elements containers.
ElemMappingType default_mapping_type() const
Returns the default master space to physical space mapping basis functions to be used on newly added ...
unique_id_type _next_unique_id
The next available unique id for assigning ids to DOF objects.
virtual void clear() override
Free all new memory associated with the object, but restore its original state, with the mesh pointer...
processor_id_type pid unsigned int level std::set< subdomain_id_type > ss const DofMap &dof_map LIBMESH_COMMA unsigned int dof_map LIBMESH_COMMA var_num unsigned char rflag processor_id_type pid const DofMap &dof_map LIBMESH_COMMA unsigned int dof_map LIBMESH_COMMA var_num DECLARE_NODE_ITERATORS(multi_evaluable_, std::vector< const DofMap * > dof_maps, dof_maps) protected dofobject_container< Node > _nodes
Move node and elements from a DistributedMesh.
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 ...
processor_id_type n_processors() const
virtual const Elem * elem_ptr(const dof_id_type i) const override final
friend class MeshCommunication
Make the MeshCommunication class a friend so that it can directly broadcast *_integer_names.
virtual dof_id_type parallel_n_elem() const override
T command_line_value(const std::string &, T)
This is the MeshCommunication class.
static std::unique_ptr< Partitioner > build(const PartitionerType solver_package)
Builds a Partitioner of the type specified by partitioner_type.
void min(const T &r, T &o, Request &req) const
const std::map< subdomain_id_type, std::string > & get_subdomain_name_map() const
static const unique_id_type invalid_unique_id
An invalid unique_id to distinguish an uninitialized DofObject.
virtual void move_nodes_and_elements(MeshBase &&other_mesh)=0
Move node and elements from other_mesh to this mesh.
static const processor_id_type invalid_processor_id
An invalid processor_id to distinguish DoFs that have not been assigned to a processor.
std::set< Elem * > _extra_ghost_elems
These are extra ghost elements that we want to make sure not to delete when we call delete_remote_ele...
The UnstructuredMesh class is derived from the MeshBase class.
unsigned char default_mapping_data() const
Returns any default data value used by the master space to physical space mapping.
virtual bool is_serial_on_zero() const override final
std::unique_ptr< Partitioner > _partitioner
A partitioner to use at each prepare_for_use().
void set_mapping_data(const unsigned char data)
Sets the value of the mapping data for the element.
virtual void set_next_unique_id(unique_id_type id) override
Sets the next available unique id to be used.
virtual void clear_elems() override
Clear internal Elem data.
bool allow_find_neighbors() const
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
virtual void own_node(Node &n) override final
Takes ownership of node n on this partition of a distributed mesh, by setting n.processor_id() to thi...
virtual void clear_extra_ghost_elems()
Clears extra ghost elements.
const std::set< Elem * > & extra_ghost_elems() const
Const accessor to the ghosted elements.
bool valid_unique_id() const
virtual const Node * query_node_ptr(const dof_id_type i) const override final
void allow_find_neighbors(bool allow)
If false is passed then this mesh will no longer work to find element neighbors when being prepared f...
virtual bool subclass_locally_equals(const MeshBase &other_mesh) const override
Shim to allow operator == (&) to behave like a virtual function without having to be one...
dof_id_type parallel_max_node_id() const
bool allow_remote_element_removal() const
The DistributedMesh class is derived from the MeshBase class, and is intended to provide identical fu...
void regenerate_id_sets()
Clears and regenerates the cached sets of ids.
virtual void clear()
Deletes all the element and node data that is currently stored.
dof_id_type _next_free_unpartitioned_node_id
dofobject_container< Elem > _elements
The elements in the mesh.
virtual void delete_node(Node *n) override final
Removes the Node n from the mesh.
bool skip_partitioning() const
virtual void renumber_node(dof_id_type old_id, dof_id_type new_id) override final
Changes the id of node old_id, both by changing node(old_id)->id() and by moving node(old_id) in the ...
std::vector< dof_id_type > _node_integer_default_values
The array of default initialization values for integer data associated with each node in the mesh...
static std::unique_ptr< Node > build(const Node &n)
virtual void redistribute() override
Redistribute elements between processors.
std::vector< dof_id_type > _elem_integer_default_values
The array of default initialization values for integer data associated with each element in the mesh...
DistributedMesh & operator=(const DistributedMesh &)=delete
Copy assignment is not allowed.
virtual dof_id_type n_active_elem() const override final
dof_id_type _next_free_unpartitioned_elem_id
void max(const T &r, T &o, Request &req) const
DistributedMesh(const Parallel::Communicator &comm_in, unsigned char dim=1)
Constructor.
void post_dofobject_moves(MeshBase &&other_mesh)
Moves any superclass data (e.g.
virtual void gather_to_zero() override
Gathers all elements and nodes of the mesh onto processor zero.
virtual Elem * insert_elem(Elem *e) override final
Insert elem e to the element array, preserving its id and replacing/deleting any existing element wit...
virtual dof_id_type max_node_id() const override final
bool _is_prepared
Flag indicating if the mesh has been prepared for use.
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
The DofObject defines an abstract base class for objects that have degrees of freedom associated with...
void add_extra_integers(const unsigned int n_integers)
Assigns a set of extra integers to this DofObject.
virtual const Node & node_ref(const dof_id_type i) const
virtual void update_post_partitioning() override
Recalculate cached data after elements and nodes have been repartitioned.
bool allow_renumbering() const
unique_id_type _next_unpartitioned_unique_id
The next available unique id for assigning ids to unpartitioned DOF objects.
virtual MeshBase & assign(MeshBase &&other_mesh) override
Shim to call the move assignment operator for this class.
virtual dof_id_type n_elem() const override final
virtual ~DistributedMesh()
Destructor.
virtual Node * insert_node(Node *n) override final
These methods are deprecated.
processor_id_type processor_id() const
virtual bool is_serial() const override final
const DofMap &dof_map LIBMESH_COMMA unsigned int std::string & set_subdomain_name_map()
virtual dof_id_type max_elem_id() const override final
dof_id_type _next_free_local_elem_id
virtual void redistribute()
Redistribute elements between processors.
processor_id_type processor_id() const
bool _deleted_coarse_elements
A boolean remembering whether we've recently deleted top-level elements or not.
A Point defines a location in LIBMESH_DIM dimensional Real space.
dof_id_type renumber_dof_objects(dofobject_container< T > &)
Renumber a parallel objects container.
void redistribute(DistributedMesh &mesh, bool newly_coarsened_only=false) const
This method takes a parallel distributed mesh and redistributes the elements.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
dof_id_type parallel_max_elem_id() const
virtual const Node * node_ptr(const dof_id_type i) const override final
virtual const Elem * query_elem_ptr(const dof_id_type i) const override final