151 std::span<const std::int8_t> marked_edges)
154 std::shared_ptr<const common::IndexMap> edge_index_map
155 =
mesh.topology()->index_map(1);
159 std::vector<std::int32_t> marked_edge_list;
160 for (
int local_i = 0; local_i < edge_index_map->size_local(); ++local_i)
162 if (marked_edges[local_i])
163 marked_edge_list.push_back(local_i);
165 spdlog::info(
"Marked edge list has {} entries", marked_edge_list.size());
168 auto [new_vertex_coords, xshape]
169 = impl::create_new_geometry(
mesh, marked_edge_list);
171 const std::int64_t num_local = marked_edge_list.size();
172 std::int64_t global_offset = 0;
173 MPI_Exscan(&num_local, &global_offset, 1, MPI_INT64_T, MPI_SUM,
mesh.comm());
174 global_offset +=
mesh.topology()->index_map(0)->local_range()[1];
175 std::vector<std::int64_t> local_edge_to_new_vertex(marked_edge_list.size());
176 std::iota(local_edge_to_new_vertex.begin(), local_edge_to_new_vertex.end(),
179 spdlog::info(
"Marked edge global offset = {}", global_offset);
185 int indegree(-1), outdegree(-2), weighted(-1);
186 MPI_Dist_graph_neighbors_count(comm, &indegree, &outdegree, &weighted);
187 assert(indegree == outdegree);
188 const int num_neighbors = indegree;
190 std::vector<std::vector<std::int64_t>> values_to_send(num_neighbors);
191 for (std::size_t i = 0; i < marked_edge_list.size(); ++i)
194 for (
int remote_process : shared_edges.
links(marked_edge_list[i]))
197 values_to_send[remote_process].push_back(
198 impl::local_to_global(marked_edge_list[i], *edge_index_map));
199 values_to_send[remote_process].push_back(local_edge_to_new_vertex[i]);
205 std::vector<std::int64_t> received_values;
207 int indegree(-1), outdegree(-2), weighted(-1);
208 MPI_Dist_graph_neighbors_count(comm, &indegree, &outdegree, &weighted);
209 assert(indegree == outdegree);
211 std::vector<std::int64_t> send_buffer;
212 std::vector<int> send_sizes;
213 for (
auto& x : values_to_send)
215 send_sizes.push_back(x.size());
216 send_buffer.insert(send_buffer.end(), x.begin(), x.end());
218 assert((
int)send_sizes.size() == outdegree);
220 std::vector<int> recv_sizes(outdegree);
221 send_sizes.reserve(1);
222 recv_sizes.reserve(1);
223 MPI_Neighbor_alltoall(send_sizes.data(), 1, MPI_INT, recv_sizes.data(), 1,
227 std::vector<int> send_disp = {0};
228 std::partial_sum(send_sizes.begin(), send_sizes.end(),
229 std::back_inserter(send_disp));
230 std::vector<int> recv_disp = {0};
231 std::partial_sum(recv_sizes.begin(), recv_sizes.end(),
232 std::back_inserter(recv_disp));
234 received_values.resize(recv_disp.back());
235 MPI_Neighbor_alltoallv(send_buffer.data(), send_sizes.data(),
236 send_disp.data(), MPI_INT64_T,
237 received_values.data(), recv_sizes.data(),
238 recv_disp.data(), MPI_INT64_T, comm);
243 assert(received_values.size() % 2 == 0);
244 std::vector<std::int64_t> recv_global_edge(received_values.size() / 2);
245 for (std::size_t i = 0; i < recv_global_edge.size(); ++i)
246 recv_global_edge[i] = received_values[i * 2];
247 std::vector<std::int32_t> recv_local_edge(recv_global_edge.size());
248 mesh.topology()->index_map(1)->global_to_local(recv_global_edge,
250 for (std::size_t i = 0; i < recv_global_edge.size(); ++i)
252 assert(recv_local_edge[i] != -1);
253 marked_edge_list.push_back(recv_local_edge[i]);
254 local_edge_to_new_vertex.push_back(received_values[i * 2 + 1]);
261 std::vector<std::int32_t> perm(marked_edge_list.size());
262 std::iota(perm.begin(), perm.end(), 0);
263 std::ranges::sort(perm, std::less{},
264 [&marked_edge_list](
int i) {
return marked_edge_list[i]; });
265 std::vector<std::int64_t> data(local_edge_to_new_vertex.size());
266 for (std::size_t i = 0; i < perm.size(); ++i)
267 data[i] = local_edge_to_new_vertex[perm[i]];
270 std::vector<std::int32_t> offset(
271 edge_index_map->size_local() + edge_index_map->num_ghosts() + 1, 0);
272 for (
auto m : marked_edge_list)
274 std::partial_sum(offset.begin(), offset.end(), offset.begin());
277 return {std::move(local_edge_to_new_vertex_adj), std::move(new_vertex_coords),