9#include <range/v3/algorithm/count_if.hpp>
10#include <range/v3/numeric.hpp>
11#include <range/v3/range/conversion.hpp>
12#include <range/v3/view/enumerate.hpp>
13#include <range/v3/view/indirect.hpp>
14#include <range/v3/view/map.hpp>
15#include <unordered_map>
29 std::span<std::size_t const>
30 local_bulk_node_ids_for_subdomain,
31 std::size_t
const subdomain_node_id)
34 local_bulk_node_ids_for_subdomain[subdomain_node_id]));
41 std::vector<Element*>
const& input_elements)
46 std::unordered_map<std::size_t, Node*> id_node_hash_map;
47 id_node_hash_map.reserve(
50 for (
auto& e : elements)
53 unsigned const n_nodes = e->getNumberOfNodes();
54 for (
unsigned i = 0; i < n_nodes; ++i)
56 Node const* n = e->getNode(i);
57 auto const it = id_node_hash_map.find(n->
getID());
58 if (it == id_node_hash_map.end())
60 auto new_node_in_map = id_node_hash_map[n->
getID()] =
62 e->setNode(i, new_node_in_map);
66 e->setNode(i, it->second);
71 std::map<std::size_t, Node*> nodes_map;
72 for (
auto const& n : id_node_hash_map)
74 nodes_map[n.first] = n.second;
79 nodes_map | ranges::views::values | ranges::to<std::vector>;
81 return std::make_pair(element_nodes, elements);
85 Mesh const* subdomain_mesh)
87 auto const& subdomain_nodes = subdomain_mesh->
getNodes();
88 auto const& local_bulk_node_ids_for_subdomain =
90 unsigned long const number_of_regular_nodes = ranges::count_if(
92 [&](std::size_t
const id) {
93 return isRegularNode(*bulk_mesh,
94 {local_bulk_node_ids_for_subdomain}, id);
97 DBUG(
"[{}] number of regular nodes: {}", subdomain_mesh->
getName(),
98 number_of_regular_nodes);
99 return number_of_regular_nodes;
102std::vector<std::size_t>
107 auto const& subdomain_nodes = subdomain_mesh->
getNodes();
108 auto const& local_bulk_node_ids_for_subdomain =
122 std::size_t
const number_of_regular_nodes =
128 std::vector<std::size_t>
const gathered_number_of_regular_nodes =
132 std::vector<std::size_t>
const numbers_of_regular_nodes_at_rank =
136 std::vector<std::size_t> subdomain_global_node_ids;
137 subdomain_global_node_ids.reserve(subdomain_nodes.size());
138 auto const partition_offset = numbers_of_regular_nodes_at_rank[mpi.
rank];
139 DBUG(
"[{}] partition offset: {}", subdomain_mesh->
getName(),
144 if (isRegularNode(*bulk_mesh, {local_bulk_node_ids_for_subdomain}, id))
146 subdomain_global_node_ids.emplace_back(partition_offset +
id);
149 return subdomain_global_node_ids;
154 Mesh const* subdomain_mesh,
155 std::vector<std::size_t>
const& global_regular_base_node_ids)
160 auto const local_bulk_node_ids_for_subdomain =
164 std::vector<std::size_t> subdomain_node_id_to_bulk_node_id;
167 if (!isRegularNode(*bulk_mesh, {local_bulk_node_ids_for_subdomain}, id))
169 auto const bulk_node_id = local_bulk_node_ids_for_subdomain[id];
172 subdomain_node_id_to_bulk_node_id.push_back(
179 std::vector<std::size_t> ghost_node_ids_of_all_ranks;
180 std::vector<int>
const offsets =
182 ghost_node_ids_of_all_ranks, mpi);
184 std::size_t
const global_number_of_subdomain_node_id_to_bulk_node_id =
186 DBUG(
"[{}] global_number_of_subdomain_node_id_to_bulk_node_id: '{}' ",
188 global_number_of_subdomain_node_id_to_bulk_node_id);
191 std::map<std::size_t, std::size_t> global_to_local_bulk_node_ids;
201 std::map<std::size_t, std::size_t> local_subdomain_node_ids;
204 local_subdomain_node_ids[local_bulk_node_ids_for_subdomain[id]] = id;
207 std::vector<std::size_t> subdomain_node_ids_of_all_ranks(
208 global_number_of_subdomain_node_id_to_bulk_node_id,
209 std::numeric_limits<std::size_t>::max());
211 for (
int rank = 0; rank < mpi.
size; ++rank)
213 if (rank == mpi.
rank)
217 for (
int i = offsets[rank]; i < offsets[rank + 1]; ++i)
219 auto it = global_to_local_bulk_node_ids.find(
220 ghost_node_ids_of_all_ranks[i]);
221 if (it == global_to_local_bulk_node_ids.end())
225 auto const local_bulk_node_id = it->second;
226 subdomain_node_ids_of_all_ranks[i] = global_regular_base_node_ids
227 [local_subdomain_node_ids.find(local_bulk_node_id)->second];
229 "[{}] found global subdomain node id: '{}' for global bulk "
232 subdomain_node_ids_of_all_ranks[i],
233 ghost_node_ids_of_all_ranks[i]);
241 std::vector<std::size_t> global_ids_for_subdomain_ghost_nodes(
242 subdomain_node_ids_of_all_ranks.begin() + offsets[mpi.
rank],
243 subdomain_node_ids_of_all_ranks.begin() + offsets[mpi.
rank + 1]);
244 return global_ids_for_subdomain_ghost_nodes;
248 Mesh const* subdomain_mesh)
250 auto const number_of_regular_base_nodes =
255 std::vector<std::size_t>
const gathered_number_of_regular_base_nodes =
263 Mesh const* subdomain_mesh)
267 auto const number_of_regular_base_nodes =
270 auto const number_of_regular_higher_order_nodes =
272 std::vector<std::size_t> gathered_number_of_regular_higher_order_nodes =
276 gathered_number_of_regular_higher_order_nodes);
282 auto global_regular_base_node_ids =
285 auto const local_ids_for_subdomain_ghost_nodes =
287 bulk_mesh, subdomain_mesh, global_regular_base_node_ids);
301 std::vector<std::size_t> global_node_ids(
302 std::move(global_regular_base_node_ids));
303 global_node_ids.insert(global_node_ids.end(),
304 local_ids_for_subdomain_ghost_nodes.begin(),
305 local_ids_for_subdomain_ghost_nodes.end());
307 return global_node_ids;
315 DBUG(
"[{}] number_of_global_nodes: {}'", subdomain_mesh->
getName(),
316 number_of_global_nodes);
317 return number_of_global_nodes;
322 Mesh const*
const subdomain_mesh)
324 DBUG(
"Creating NodePartitionedMesh from '{}'", subdomain_mesh->
getName());
326 auto const subdomain_global_node_ids =
331 unsigned long number_of_global_base_nodes = 0;
333 unsigned long const number_of_global_nodes =
335 auto numbers_of_regular_base_nodes_at_rank =
337 auto numbers_of_regular_higher_order_nodes_at_rank =
340 auto const number_of_regular_nodes =
342 DBUG(
"[{}] number_of_regular_nodes: {}", subdomain_mesh->
getName(),
343 number_of_regular_nodes);
344 auto const [nodes, elements] =
347 return std::make_unique<NodePartitionedMesh>(
348 subdomain_mesh->
getName(), nodes, subdomain_global_node_ids, elements,
349 subdomain_mesh->
getProperties(), number_of_global_base_nodes,
350 number_of_global_nodes, number_of_regular_nodes,
351 std::move(numbers_of_regular_base_nodes_at_rank),
352 std::move(numbers_of_regular_higher_order_nodes_at_rank));
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
std::size_t getID() const
std::vector< Node * > const & getNodes() const
Get the nodes-vector for the mesh.
std::vector< Element * > const & getElements() const
Get the element-vector for the mesh.
std::size_t computeNumberOfBaseNodes() const
Get the number of base nodes.
Properties & getProperties()
const std::string getName() const
Get name of the mesh.
std::size_t getNumberOfNodes() const
Get the number of nodes.
bool isGhostNode(const std::size_t node_id) const
Check whether a node with ID of node_id is a ghost node.
std::size_t getGlobalNodeID(const std::size_t node_id) const
Get the global node ID of a node with its local ID.
static void allreduceInplace(std::vector< T > &vector, MPI_Op const &mpi_op, Mpi const &mpi)
static std::vector< int > allgatherv(std::span< T > const send_buffer, std::vector< std::remove_const_t< T > > &receive_buffer, Mpi const &mpi)
static T allreduce(T const &value, MPI_Op const &mpi_op, Mpi const &mpi)
static std::vector< T > allgather(T const &value, Mpi const &mpi)
std::vector< ranges::range_value_t< R > > sizesToOffsets(R const &sizes)
constexpr ranges::views::view_closure ids
For an element of a range view return its id.
std::pair< std::vector< Node * >, std::vector< Element * > > copyNodesAndElements(std::vector< Element * > const &input_elements)
unsigned long getNumberOfGlobalNodes(Mesh const *subdomain_mesh)
std::vector< std::size_t > computeNumberOfRegularHigherOrderNodesAtRank(Mesh const *subdomain_mesh)
std::vector< std::size_t > computeGlobalNodeIDsOfSubDomainPartition(NodePartitionedMesh const *bulk_mesh, Mesh const *subdomain_mesh)
std::vector< std::size_t > computeNumberOfRegularBaseNodesAtRank(Mesh const *subdomain_mesh)
std::vector< std::size_t > computeRegularBaseNodeGlobalNodeIDsOfSubDomainPartition(NodePartitionedMesh const *bulk_mesh, Mesh const *subdomain_mesh)
unsigned long computeNumberOfRegularNodes(NodePartitionedMesh const *bulk_mesh, Mesh const *subdomain_mesh)
std::vector< Element * > cloneElements(std::vector< Element * > const &elements)
Clones a vector of elements using the Element::clone() function.
std::vector< std::size_t > computeGhostBaseNodeGlobalNodeIDsOfSubDomainPartition(NodePartitionedMesh const *bulk_mesh, Mesh const *subdomain_mesh, std::vector< std::size_t > const &global_regular_base_node_ids)
PropertyVector< std::size_t > const * bulkNodeIDs(Mesh const &mesh)
std::unique_ptr< NodePartitionedMesh > transformMeshToNodePartitionedMesh(NodePartitionedMesh const *const bulk_mesh, Mesh const *const subdomain_mesh)