12#include <dolfinx/common/MPI.h> 
   13#include <dolfinx/graph/AdjacencyList.h> 
   14#include <dolfinx/mesh/Mesh.h> 
   43std::int64_t local_to_global(std::int32_t local_index,
 
   44                             const common::IndexMap& map);
 
   55template <std::
floating_po
int T>
 
   56std::pair<std::vector<T>, std::array<std::size_t, 2>> create_new_geometry(
 
   57    const mesh::Mesh<T>& mesh,
 
   58    const std::map<std::int32_t, std::int64_t>& local_edge_to_new_vertex)
 
   61  auto x_dofmap = mesh.geometry().dofmap();
 
   62  const int tdim = mesh.topology()->dim();
 
   63  auto c_to_v = mesh.topology()->connectivity(tdim, 0);
 
   65  auto map_v = mesh.topology()->index_map(0);
 
   67  std::vector<std::int32_t> vertex_to_x(map_v->size_local()
 
   68                                        + map_v->num_ghosts());
 
   69  auto map_c = mesh.topology()->index_map(tdim);
 
   72  auto dof_layout = mesh.geometry().cmap().create_dof_layout();
 
   73  auto entity_dofs_all = dof_layout.entity_dofs_all();
 
   74  for (
int c = 0; c < map_c->size_local() + map_c->num_ghosts(); ++c)
 
   76    auto vertices = c_to_v->links(c);
 
   77    auto dofs = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
 
   78        x_dofmap, c, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
 
   79    for (std::size_t i = 0; i < vertices.size(); ++i)
 
   81      auto vertex_pos = entity_dofs_all[0][i][0];
 
   82      vertex_to_x[vertices[i]] = dofs[vertex_pos];
 
   87  std::span<const T> x_g = mesh.geometry().x();
 
   88  const std::size_t gdim = mesh.geometry().dim();
 
   89  const std::size_t num_vertices = map_v->size_local();
 
   90  const std::size_t num_new_vertices = local_edge_to_new_vertex.size();
 
   92  std::array<std::size_t, 2> shape = {num_vertices + num_new_vertices, gdim};
 
   93  std::vector<T> new_vertex_coords(shape[0] * shape[1]);
 
   94  for (std::size_t v = 0; v < num_vertices; ++v)
 
   96    std::size_t pos = 3 * vertex_to_x[v];
 
   97    for (std::size_t j = 0; j < gdim; ++j)
 
   98      new_vertex_coords[gdim * v + j] = x_g[pos + j];
 
  102  if (num_new_vertices > 0)
 
  104    std::vector<int> edges(num_new_vertices);
 
  106    for (
auto& e : local_edge_to_new_vertex)
 
  107      edges[i++] = e.first;
 
  111    for (std::size_t i = 0; i < num_new_vertices; ++i)
 
  112      for (std::size_t j = 0; j < gdim; ++j)
 
  113        new_vertex_coords[gdim * (num_vertices + i) + j] = midpoints[3 * i + j];
 
  116  return {std::move(new_vertex_coords), shape};
 
  132    const std::vector<std::vector<std::int32_t>>& marked_for_update,
 
  133    std::vector<std::int8_t>& marked_edges, 
const common::IndexMap& map);
 
  149template <std::
floating_po
int T>
 
  150std::tuple<std::map<std::int32_t, std::int64_t>, std::vector<T>,
 
  151           std::array<std::size_t, 2>>
 
  155                    std::span<const std::int8_t> marked_edges)
 
  158  std::shared_ptr<const common::IndexMap> edge_index_map
 
  159      = mesh.topology()->index_map(1);
 
  164  std::map<std::int32_t, std::int64_t> local_edge_to_new_vertex;
 
  165  for (
int local_i = 0; local_i < edge_index_map->size_local(); ++local_i)
 
  167    if (marked_edges[local_i])
 
  169      [[maybe_unused]] 
auto it = local_edge_to_new_vertex.insert({local_i, n});
 
  175  const std::int64_t num_local = n;
 
  176  std::int64_t global_offset = 0;
 
  177  MPI_Exscan(&num_local, &global_offset, 1, MPI_INT64_T, MPI_SUM, mesh.comm());
 
  178  global_offset += mesh.topology()->index_map(0)->local_range()[1];
 
  179  std::for_each(local_edge_to_new_vertex.begin(),
 
  180                local_edge_to_new_vertex.end(),
 
  181                [global_offset](
auto& e) { e.second += global_offset; });
 
  184  auto [new_vertex_coords, xshape]
 
  185      = impl::create_new_geometry(mesh, local_edge_to_new_vertex);
 
  191  int indegree(-1), outdegree(-2), weighted(-1);
 
  192  MPI_Dist_graph_neighbors_count(comm, &indegree, &outdegree, &weighted);
 
  193  assert(indegree == outdegree);
 
  194  const int num_neighbors = indegree;
 
  196  std::vector<std::vector<std::int64_t>> values_to_send(num_neighbors);
 
  197  for (
auto& local_edge : local_edge_to_new_vertex)
 
  199    const std::size_t local_i = local_edge.first;
 
  202    for (
int remote_process : shared_edges.
links(local_i))
 
  205      values_to_send[remote_process].push_back(
 
  206          impl::local_to_global(local_i, *edge_index_map));
 
  207      values_to_send[remote_process].push_back(local_edge.second);
 
  213  std::vector<std::int64_t> received_values;
 
  215    int indegree(-1), outdegree(-2), weighted(-1);
 
  216    MPI_Dist_graph_neighbors_count(comm, &indegree, &outdegree, &weighted);
 
  217    assert(indegree == outdegree);
 
  219    std::vector<std::int64_t> send_buffer;
 
  220    std::vector<int> send_sizes;
 
  221    for (
auto& x : values_to_send)
 
  223      send_sizes.push_back(x.size());
 
  224      send_buffer.insert(send_buffer.end(), x.begin(), x.end());
 
  226    assert((
int)send_sizes.size() == outdegree);
 
  228    std::vector<int> recv_sizes(outdegree);
 
  229    send_sizes.reserve(1);
 
  230    recv_sizes.reserve(1);
 
  231    MPI_Neighbor_alltoall(send_sizes.data(), 1, MPI_INT, recv_sizes.data(), 1,
 
  235    std::vector<int> send_disp = {0};
 
  236    std::partial_sum(send_sizes.begin(), send_sizes.end(),
 
  237                     std::back_inserter(send_disp));
 
  238    std::vector<int> recv_disp = {0};
 
  239    std::partial_sum(recv_sizes.begin(), recv_sizes.end(),
 
  240                     std::back_inserter(recv_disp));
 
  242    received_values.resize(recv_disp.back());
 
  243    MPI_Neighbor_alltoallv(send_buffer.data(), send_sizes.data(),
 
  244                           send_disp.data(), MPI_INT64_T,
 
  245                           received_values.data(), recv_sizes.data(),
 
  246                           recv_disp.data(), MPI_INT64_T, comm);
 
  250  std::vector<std::int64_t> recv_global_edge;
 
  251  assert(received_values.size() % 2 == 0);
 
  252  for (std::size_t i = 0; i < received_values.size() / 2; ++i)
 
  253    recv_global_edge.push_back(received_values[i * 2]);
 
  254  std::vector<std::int32_t> recv_local_edge(recv_global_edge.size());
 
  255  mesh.topology()->index_map(1)->global_to_local(recv_global_edge,
 
  257  for (std::size_t i = 0; i < received_values.size() / 2; ++i)
 
  259    assert(recv_local_edge[i] != -1);
 
  260    [[maybe_unused]] 
auto it = local_edge_to_new_vertex.insert(
 
  261        {recv_local_edge[i], received_values[i * 2 + 1]});
 
  265  return {std::move(local_edge_to_new_vertex), std::move(new_vertex_coords),
 
 
  278template <std::
floating_po
int T>
 
  281                        std::span<const T> new_coords,
 
  282                        std::array<std::size_t, 2> xshape, 
bool redistribute,
 
  288                             old_mesh.
geometry().cmap(), new_coords, xshape,
 
  298      const int num_cells = cell_topology.
num_nodes();
 
  299      std::vector<std::int32_t> destinations(num_cells, mpi_rank);
 
  300      std::vector<std::int32_t> dest_offsets(num_cells + 1);
 
  301      std::iota(dest_offsets.begin(), dest_offsets.end(), 0);
 
  303                                  std::move(dest_offsets));
 
  308                             old_mesh.
comm(), new_coords, xshape, partitioner);
 
 
  334    std::span<const std::int32_t> cell, std::span<const std::int8_t> facet);
 
  346std::array<std::vector<std::int32_t>, 2>
 
  349                      std::span<const std::int32_t> parent_cell);
 
Definition AdjacencyList.h:28
std::span< T > links(std::size_t node)
Definition AdjacencyList.h:112
const std::vector< T > & array() const
Return contiguous array of links for all nodes (const version)
Definition AdjacencyList.h:129
std::int32_t num_nodes() const
Definition AdjacencyList.h:97
A Mesh consists of a set of connected and numbered mesh topological entities, and geometry data.
Definition Mesh.h:23
Geometry< T > & geometry()
Get mesh geometry.
Definition Mesh.h:76
MPI_Comm comm() const
Mesh MPI communicator.
Definition Mesh.h:84
Topology stores the topology of a mesh, consisting of mesh entities and connectivity (incidence relat...
Definition Topology.h:44
Functions supporting mesh operations.
int rank(MPI_Comm comm)
Return process rank for the communicator.
Definition MPI.cpp:64
Miscellaneous classes, functions and types.
Definition dolfinx_common.h:8
Mesh data structures and algorithms on meshes.
Definition DofMap.h:32
GhostMode
Enum for different partitioning ghost modes.
Definition utils.h:35
Mesh< typename std::remove_reference_t< typename U::value_type > > create_mesh(MPI_Comm comm, MPI_Comm commt, std::span< const std::int64_t > cells, const fem::CoordinateElement< typename std::remove_reference_t< typename U::value_type > > &element, MPI_Comm commg, const U &x, std::array< std::size_t, 2 > xshape, const CellPartitionFunction &partitioner)
Create a distributed mesh from mesh data using a provided graph partitioning function for determining...
Definition utils.h:785
CellType
Cell type identifier.
Definition cell_types.h:22
std::vector< T > compute_midpoints(const Mesh< T > &mesh, int dim, std::span< const std::int32_t > entities)
Compute the midpoints for mesh entities of a given dimension.
Definition utils.h:380
Mesh refinement algorithms.
Definition dolfinx_refinement.h:8
std::array< std::vector< std::int32_t >, 2 > transfer_facet_meshtag(const mesh::MeshTags< std::int32_t > &tags0, const mesh::Topology &topology1, std::span< const std::int32_t > cell, std::span< const std::int8_t > facet)
Transfer facet MeshTags from coarse mesh to refined mesh.
Definition utils.cpp:152
void update_logical_edgefunction(MPI_Comm comm, const std::vector< std::vector< std::int32_t > > &marked_for_update, std::vector< std::int8_t > &marked_edges, const common::IndexMap &map)
Communicate edge markers between processes that share edges.
Definition utils.cpp:46
mesh::Mesh< T > partition(const mesh::Mesh< T > &old_mesh, const graph::AdjacencyList< std::int64_t > &cell_topology, std::span< const T > new_coords, std::array< std::size_t, 2 > xshape, bool redistribute, mesh::GhostMode ghost_mode)
Definition utils.h:279
std::tuple< std::map< std::int32_t, std::int64_t >, std::vector< T >, std::array< std::size_t, 2 > > create_new_vertices(MPI_Comm comm, const graph::AdjacencyList< int > &shared_edges, const mesh::Mesh< T > &mesh, std::span< const std::int8_t > marked_edges)
Add new vertex for each marked edge, and create new_vertex_coordinates and global_edge->new_vertex ma...
Definition utils.h:152
std::vector< std::int64_t > adjust_indices(const common::IndexMap &map, std::int32_t n)
Given an index map, add "n" extra indices at the end of local range.
Definition utils.cpp:102
std::array< std::vector< std::int32_t >, 2 > transfer_cell_meshtag(const mesh::MeshTags< std::int32_t > &tags0, const mesh::Topology &topology1, std::span< const std::int32_t > parent_cell)
Transfer cell MeshTags from coarse mesh to refined mesh.
Definition utils.cpp:272