Exemple #1
0
Mesh build_mesh(const std::vector<unsigned int>& cells, const std::vector<double>& vertices, int dim)
{
    // vertices and cells are flattened
    unsigned int vlen = vertices.size() / dim;
    unsigned int clen = cells.size() / (dim + 1);

    Mesh mesh;
    
    MeshEditor editor;
    editor.open(mesh, dim, dim);
    editor.init_vertices(vlen);
    editor.init_cells(clen);
    if (dim==3)
    {
        for (int i=0; i<vlen; i++)
	    editor.add_vertex(i, vertices[3*i], vertices[3*i+1], vertices[3*i+2]);
    	for (int i=0; i<clen; i++)
	    editor.add_cell(i, cells[4*i], cells[4*i+1], cells[4*i+2], cells[4*i+3]);
    }
    else
    {
        for (int i=0; i<vlen; i++)
	    editor.add_vertex(i, vertices[2*i], vertices[2*i+1]);
    	for (int i=0; i<clen; i++)
	    editor.add_cell(i, cells[3*i], cells[3*i+1], cells[3*i+2]);
    }
    editor.close();

    return mesh;
}
//-----------------------------------------------------------------------------
void DynamicMeshEditor::close(bool order)
{
  dolfin_assert(_mesh);
  dolfin_assert(_cell_type);

  // Open default mesh editor
  MeshEditor editor;
  editor.open(*_mesh, _cell_type->cell_type(), _tdim, _gdim);

  // Set number of vertices
  const std::size_t num_vertices = vertex_coordinates.size()/_gdim;
  editor.init_vertices(num_vertices);

  // Set number of cells
  const std::size_t vertices_per_cell = _cell_type->num_vertices(_gdim);
  const std::size_t num_cells = cell_vertices.size()/vertices_per_cell;
  editor.init_cells(num_cells);

  // Add vertices
  std::vector<double> p(_gdim);
  for (std::size_t v = 0; v < num_vertices; v++)
  {
    const std::size_t offset = v*_gdim;
    for (std::size_t i = 0; i < _gdim; i++)
      p[i] = vertex_coordinates[offset + i];
    editor.add_vertex(v, p);
  }

  // Add cells
  std::vector<std::size_t> vertices(vertices_per_cell);
  for (std::size_t c = 0; c < num_cells; c++)
  {
    const std::size_t offset = c*vertices_per_cell;
    for (std::size_t i = 0; i < vertices_per_cell; i++)
      vertices[i] = cell_vertices[offset + i];
    editor.add_cell(c, vertices);
  }

  // Close editor
  editor.close(order);

  // Clear data
  clear();
}
//-----------------------------------------------------------------------------
void ParallelRefinement::build_local(Mesh& new_mesh) const
{
  MeshEditor ed;
  const std::size_t tdim = _mesh.topology().dim();
  const std::size_t gdim = _mesh.geometry().dim();
  dolfin_assert(new_vertex_coordinates.size()%gdim == 0);
  const std::size_t num_vertices = new_vertex_coordinates.size()/gdim;

  const std::size_t num_cell_vertices = tdim + 1;
  dolfin_assert(new_cell_topology.size()%num_cell_vertices == 0);
  const std::size_t num_cells = new_cell_topology.size()/num_cell_vertices;

  ed.open(new_mesh, tdim, gdim);
  ed.init_vertices(num_vertices);
  std::size_t i = 0;
  for (auto p = new_vertex_coordinates.begin();
       p != new_vertex_coordinates.end(); p += gdim)
  {
    std::vector<double> vertex(p, p + gdim);
    ed.add_vertex(i, vertex);
    ++i;
  }

  ed.init_cells(num_cells);
  i = 0;
  std::vector<std::size_t> cell(num_cell_vertices);
  for (auto p = new_cell_topology.begin(); p != new_cell_topology.end();
       p += num_cell_vertices)
  {
    std::copy(p, p + num_cell_vertices, cell.begin());
    ed.add_cell(i, cell);
    ++i;
  }
  ed.close();

}
Exemple #4
0
//-----------------------------------------------------------------------------
UnitDiscMesh::UnitDiscMesh(MPI_Comm comm, std::size_t n,
                           std::size_t degree, std::size_t gdim)
  : Mesh(comm)
{
  dolfin_assert(n > 0);
  dolfin_assert(gdim == 2 or gdim == 3);
  dolfin_assert(degree == 1 or degree == 2);

  MeshEditor editor;
  editor.open(*this, 2, gdim, degree);
  editor.init_vertices_global(1 + 3*n*(n + 1),
                              1 + 3*n*(n + 1));

  std::size_t c = 0;
  editor.add_vertex(c, Point(0,0,0));
  ++c;

  for (std::size_t i = 1; i <= n; ++i)
    for (std::size_t j = 0; j < 6*i; ++j)
    {
      double r = (double)i/(double)n;
      double th = 2*M_PI*(double)j/(double)(6*i);
      double x = r*cos(th);
      double y = r*sin(th);
      editor.add_vertex(c, Point(x, y, 0));
      ++c;
    }

  editor.init_cells(6*n*n);

  c = 0;
  std::size_t base_i = 0;
  std::size_t row_i = 1;
  for (std::size_t i = 1; i <= n; ++i)
  {
    std::size_t base_m = base_i;
    base_i = 1 + 3*i*(i - 1);
    std::size_t row_m = row_i;
    row_i = 6*i;

    for (std::size_t k = 0; k != 6; ++k)
      for (std::size_t j = 0; j < (i*2 - 1); ++j)
      {
        std::size_t i0, i1, i2;
        if (j%2 == 0)
        {
          i0 = base_i + (k*i + j/2)%row_i;
          i1 = base_i + (k*i + j/2 + 1)%row_i;
          i2 = base_m + (k*(i-1) + j/2)%row_m;
        }
        else
        {
          i0 = base_m + (k*(i-1) + j/2)%row_m;
          i1 = base_m + (k*(i-1) + j/2 + 1)%row_m;
          i2 = base_i + (k*i + j/2 + 1)%row_i;
        }

        editor.add_cell(c, i0, i1, i2);
        ++c;
      }
  }

  // Initialise entities required for this degree polynomial mesh
  // and allocate space for the point coordinate data

  if (degree == 2)
  {
    editor.init_entities();

    for (EdgeIterator e(*this); !e.end(); ++e)
    {
      Point v0 = Vertex(*this, e->entities(0)[0]).point();
      Point v1 = Vertex(*this, e->entities(0)[1]).point();
      Point pt = e->midpoint();

      if (std::abs(v0.norm() - 1.0) < 1e-6 and
          std::abs(v1.norm() - 1.0) < 1e-6)
        pt *= v0.norm()/pt.norm();

      // Add Edge-based point
      editor.add_entity_point(1, 0, e->index(), pt);
    }
  }

  editor.close();
}
//-----------------------------------------------------------------------------
dolfin::Mesh MeshRenumbering::renumber_by_color(const Mesh& mesh,
                                 const std::vector<std::size_t> coloring_type)
{
  // Start timer
  Timer timer("Renumber mesh by color");

  // Get some some mesh
  const std::size_t tdim = mesh.topology().dim();
  const std::size_t gdim = mesh.geometry().dim();
  const std::size_t num_vertices = mesh.num_vertices();
  const std::size_t num_cells = mesh.num_cells();

  // Check that requested coloring is a cell coloring
  if (coloring_type[0] != tdim)
  {
    dolfin_error("MeshRenumbering.cpp",
                 "renumber mesh by color",
                 "Coloring is not a cell coloring: only cell colorings are supported");
  }

  // Compute renumbering
  std::vector<double> new_coordinates;
  std::vector<std::size_t> new_connections;
  MeshRenumbering::compute_renumbering(mesh, coloring_type, new_coordinates,
                                       new_connections);

  // Create new mesh
  Mesh new_mesh;

  // Create mesh editor
  MeshEditor editor;
  editor.open(new_mesh, mesh.type().cell_type(), tdim, gdim);
  editor.init_cells(num_cells);
  editor.init_vertices(num_vertices);

  // Add vertices
  dolfin_assert(new_coordinates.size() == num_vertices*gdim);
  for (std::size_t i = 0; i < num_vertices; ++i)
  {
    std::vector<double> x(gdim);
    for (std::size_t j = 0; j < gdim; ++j)
      x[j] = new_coordinates[i*gdim + j];
    editor.add_vertex(i, x);
  }

  cout << "Done adding vertices" << endl;

  // Add cells
  dolfin_assert(new_coordinates.size() == num_vertices*gdim);
  const std::size_t vertices_per_cell = mesh.type().num_entities(0);
  for (std::size_t i = 0; i < num_cells; ++i)
  {
    std::vector<std::size_t> c(vertices_per_cell);
    std::copy(new_connections.begin() + i*vertices_per_cell,
              new_connections.begin() + i*vertices_per_cell + vertices_per_cell,
              c.begin());
    editor.add_cell(i, c);
  }

  editor.close();

  cout << "Close editor" << endl;

  // Initialise coloring data
  typedef std::map<const std::vector<std::size_t>, std::pair<std::vector<std::size_t>,
           std::vector<std::vector<std::size_t> > > >::const_iterator ConstMeshColoringData;

  // Get old coloring
  ConstMeshColoringData mesh_coloring
    = mesh.topology().coloring.find(coloring_type);
  if (mesh_coloring == mesh.topology().coloring.end())
  {
    dolfin_error("MeshRenumbering.cpp",
                 "renumber mesh by color",
                 "Requested mesh coloring has not been computed");
  }

  // Get old coloring data
  const std::vector<std::size_t>& colors = mesh_coloring->second.first;
  const std::vector<std::vector<std::size_t> >&
    entities_of_color = mesh_coloring->second.second;
  dolfin_assert(colors.size() == num_cells);
  dolfin_assert(!entities_of_color.empty());
  const std::size_t num_colors = entities_of_color.size();

  // New coloring data
  dolfin_assert(new_mesh.topology().coloring.empty());
  std::vector<std::size_t> new_colors(colors.size());
  std::vector<std::vector<std::size_t> > new_entities_of_color(num_colors);

  std::size_t current_cell = 0;
  for (std::size_t color = 0; color < num_colors; color++)
  {
    // Get the array of cell indices of current color
    const std::vector<std::size_t>& colored_cells = entities_of_color[color];
    std::vector<std::size_t>& new_colored_cells = new_entities_of_color[color];

    // Update cell color data
    for (std::size_t i = 0; i < colored_cells.size(); i++)
    {
      new_colored_cells.push_back(current_cell);
      new_colors[current_cell] = color;
      current_cell++;
    }
  }

  // Set new coloring mesh data
  std::pair<ConstMeshColoringData, bool> insert
    = new_mesh.topology().coloring.insert(std::make_pair(coloring_type,
                          std::make_pair(new_colors, new_entities_of_color)));
  dolfin_assert(insert.second);

  cout << "Return new mesh" << endl;

  return new_mesh;
}
//-----------------------------------------------------------------------------
void RegularCutRefinement::refine_marked(Mesh& refined_mesh,
                                  const Mesh& mesh,
                                  const std::vector<int>& refinement_markers,
                                  const IndexSet& marked_edges)
{
  // Count the number of cells in refined mesh
  std::size_t num_cells = 0;

  // Data structure to hold a cell
  std::vector<std::size_t> cell_data(3);

  for (CellIterator cell(mesh); !cell.end(); ++cell)
  {
    const int marker = refinement_markers[cell->index()];
    switch (marker)
    {
    case no_refinement:
      num_cells += 1;
      break;
    case regular_refinement:
      num_cells += 4;
      break;
    case backtrack_bisection:
      num_cells += 2;
      break;
    case backtrack_bisection_refine:
      num_cells += 3;
      break;
    default:
      num_cells += 2;
    }
  }

  // Initialize mesh editor
  const std::size_t num_vertices = mesh.num_vertices() + marked_edges.size();
  MeshEditor editor;
  editor.open(refined_mesh, mesh.topology().dim(), mesh.geometry().dim());
  editor.init_vertices(num_vertices);
  editor.init_cells(num_cells);

  // Set vertex coordinates
  std::size_t current_vertex = 0;
  for (VertexIterator vertex(mesh); !vertex.end(); ++vertex)
  {
    editor.add_vertex(current_vertex, vertex->point());
    current_vertex++;
  }
  for (std::size_t i = 0; i < marked_edges.size(); i++)
  {
    Edge edge(mesh, marked_edges[i]);
    editor.add_vertex(current_vertex, edge.midpoint());
    current_vertex++;
  }

  // Get bisection data for old mesh
  const std::size_t D = mesh.topology().dim();
  const std::vector<std::size_t>*  bisection_twins = NULL;
  if (mesh.data().exists("bisection_twins", D))
    bisection_twins = &(mesh.data().array("bisection_twins", D));

  // Markers for bisected cells pointing to their bisection twins in
  // refined mesh
  std::vector<std::size_t>& refined_bisection_twins
    = refined_mesh.data().create_array("bisection_twins", D);
  refined_bisection_twins.resize(num_cells);
  for (std::size_t i = 0; i < num_cells; i++)
    refined_bisection_twins[i] = i;

  // Mapping from old to new unrefined cells (-1 means refined or not
  // yet processed)
  std::vector<int> unrefined_cells(mesh.num_cells());
  std::fill(unrefined_cells.begin(), unrefined_cells.end(), -1);

  // Iterate over all cells and add new cells
  std::size_t current_cell = 0;
  std::vector<std::vector<std::size_t> > cells(4, std::vector<std::size_t>(3));
  for (CellIterator cell(mesh); !cell.end(); ++cell)
  {
    // Get marker
    const int marker = refinement_markers[cell->index()];

    if (marker == no_refinement)
    {
      // No refinement: just copy cell to new mesh

      std::vector<std::size_t> vertices;
      for (VertexIterator vertex(*cell); !vertex.end(); ++vertex)
        vertices.push_back(vertex->index());
      editor.add_cell(current_cell++, vertices);

      // Store mapping to new cell index
      unrefined_cells[cell->index()] = current_cell - 1;

      // Remember unrefined bisection twins
      if (bisection_twins)
      {
        const std::size_t bisection_twin = (*bisection_twins)[cell->index()];
        const int twin_marker = refinement_markers[bisection_twin];
        dolfin_assert(twin_marker == no_refinement);
        if (unrefined_cells[bisection_twin] >= 0)
        {
          const std::size_t i = current_cell - 1;
          const std::size_t j = unrefined_cells[bisection_twin];
          refined_bisection_twins[i] = j;
          refined_bisection_twins[j] = i;
        }
      }
    }
    else if (marker == regular_refinement)
    {
      // Regular refinement: divide into subsimplicies
      dolfin_assert(unrefined_cells[cell->index()] == -1);

      // Get vertices and edges
      const unsigned int* v = cell->entities(0);
      const unsigned int* e = cell->entities(1);
      dolfin_assert(v);
      dolfin_assert(e);

      // Get offset for new vertex indices
      const std::size_t offset = mesh.num_vertices();

      // Compute indices for the six new vertices
      const std::size_t v0 = v[0];
      const std::size_t v1 = v[1];
      const std::size_t v2 = v[2];
      const std::size_t e0 = offset + marked_edges.find(e[0]);
      const std::size_t e1 = offset + marked_edges.find(e[1]);
      const std::size_t e2 = offset + marked_edges.find(e[2]);

      // Create four new cells
      cells[0][0] = v0; cells[0][1] = e2; cells[0][2] = e1;
      cells[1][0] = v1; cells[1][1] = e0; cells[1][2] = e2;
      cells[2][0] = v2; cells[2][1] = e1; cells[2][2] = e0;
      cells[3][0] = e0; cells[3][1] = e1; cells[3][2] = e2;

      // Add cells
      std::vector<std::vector<std::size_t> >::const_iterator _cell;
      for (_cell = cells.begin(); _cell != cells.end(); ++_cell)
        editor.add_cell(current_cell++, *_cell);
    }
    else if (marker == backtrack_bisection || marker == backtrack_bisection_refine)
    {
      // Special case: backtrack bisected cells
      dolfin_assert(unrefined_cells[cell->index()] == -1);

      // Get index for bisection twin
      dolfin_assert(bisection_twins);
      const std::size_t bisection_twin = (*bisection_twins)[cell->index()];
      dolfin_assert(bisection_twin != cell->index());

      // Let lowest number twin handle refinement
      if (bisection_twin < cell->index())
        continue;

      // Get marker for twin
      const int twin_marker = refinement_markers[bisection_twin];

      // Find common edge(s) and bisected edge(s)
      const std::pair<std::size_t, std::size_t> common_edges
        = find_common_edges(*cell, mesh, bisection_twin);
      const std::pair<std::size_t, std::size_t> bisection_edges
        = find_bisection_edges(*cell, mesh, bisection_twin);
      const std::pair<std::size_t, std::size_t> bisection_vertices
        = find_bisection_vertices(*cell, mesh, bisection_twin, bisection_edges);

      // Get list of vertices and edges for both cells
      const Cell twin(mesh, bisection_twin);
      const unsigned int* vertices_0 = cell->entities(0);
      const unsigned int* vertices_1 = twin.entities(0);
      const unsigned int* edges_0 = cell->entities(1);
      const unsigned int* edges_1 = twin.entities(1);
      dolfin_assert(vertices_0);
      dolfin_assert(vertices_1);
      dolfin_assert(edges_0);
      dolfin_assert(edges_1);

      // Get offset for new vertex indices
      const std::size_t offset = mesh.num_vertices();

      // Locate vertices such that v_i is the vertex opposite to
      // the edge e_i on the parent triangle
      const std::size_t v0 = vertices_0[common_edges.first];
      const std::size_t v1 = vertices_1[common_edges.second];
      const std::size_t v2 = vertices_0[bisection_edges.first];
      const std::size_t e0 = offset + marked_edges.find(edges_1[bisection_vertices.second]);
      const std::size_t e1 = offset + marked_edges.find(edges_0[bisection_vertices.first]);
      const std::size_t e2 = vertices_0[bisection_vertices.first];

      // Locate new vertices on bisected edge (if any)
      std::size_t E0 = 0;
      std::size_t E1 = 0;
      if (marker == backtrack_bisection_refine)
        E0 = offset + marked_edges.find(edges_0[bisection_edges.first]);
      if (twin_marker == backtrack_bisection_refine)
        E1 = offset + marked_edges.find(edges_1[bisection_edges.second]);

      // Add middle two cells (always)
      dolfin_assert(cell_data.size() == 3);
      cell_data[0] = e0; cell_data[1] = e1; cell_data[2] = e2;
      editor.add_cell(current_cell++, cell_data);

      cell_data[0] = v2; cell_data[1] = e1; cell_data[2] = e0;
      editor.add_cell(current_cell++, cell_data);

      // Add one or two remaining cells in current cell (left)
      if (marker == backtrack_bisection)
      {
        cell_data[0] = v0; cell_data[1] = e2; cell_data[2] = e1;
        editor.add_cell(current_cell++, cell_data);
      }
      else
      {
        // Add the two cells
        cell_data[0] = v0; cell_data[1] = E0; cell_data[2] = e1;
        editor.add_cell(current_cell++, cell_data);

        cell_data[0] = E0; cell_data[1] = e2; cell_data[2] = e1;
        editor.add_cell(current_cell++, cell_data);

        // Set bisection twins
        refined_bisection_twins[current_cell - 2] = current_cell - 1;
        refined_bisection_twins[current_cell - 1] = current_cell - 2;
      }

      // Add one or two remaining cells in twin cell (right)
      if (twin_marker == backtrack_bisection)
      {
        cell_data[0] = v1; cell_data[1] = e0; cell_data[2] = e2;
        editor.add_cell(current_cell++, cell_data);
      }
      else
      {
        // Add the two cells
        cell_data[0] = v1; cell_data[1] = e0; cell_data[2] = E1;
        editor.add_cell(current_cell++, cell_data);

        cell_data[0] = e0; cell_data[1] = e2; cell_data[2] = E1;
        editor.add_cell(current_cell++, cell_data);

        // Set bisection twins
        refined_bisection_twins[current_cell - 2] = current_cell - 1;
        refined_bisection_twins[current_cell - 1] = current_cell - 2;
      }
    }
    else
    {
      // One edge marked for refinement: do bisection

      dolfin_assert(unrefined_cells[cell->index()] == -1);

      // Get vertices and edges
      const unsigned int* v = cell->entities(0);
      const unsigned int* e = cell->entities(1);
      dolfin_assert(v);
      dolfin_assert(e);

      // Get edge number (equal to marker)
      dolfin_assert(marker >= 0);
      const std::size_t local_edge_index = static_cast<std::size_t>(marker);
      const std::size_t global_edge_index = e[local_edge_index];
      const std::size_t ee = mesh.num_vertices() + marked_edges.find(global_edge_index);

      // Add the two new cells
      if (local_edge_index == 0)
      {
        cell_data[0] = v[0]; cell_data[1] = ee; cell_data[2] = v[1];
        editor.add_cell(current_cell++, cell_data);

        cell_data[0] = v[0]; cell_data[1] = ee; cell_data[2] = v[2];
        editor.add_cell(current_cell++, cell_data);
      }
      else if (local_edge_index == 1)
      {
        cell_data[0] = v[1]; cell_data[1] = ee; cell_data[2] = v[0];
        editor.add_cell(current_cell++, cell_data);

        cell_data[0] = v[1]; cell_data[1] = ee; cell_data[2] = v[2];
        editor.add_cell(current_cell++, cell_data);
      }
      else
      {
        cell_data[0] = v[2]; cell_data[1] = ee; cell_data[2] = v[0];
        editor.add_cell(current_cell++, cell_data);

        cell_data[0] = v[2]; cell_data[1] = ee; cell_data[2] = v[1];
        editor.add_cell(current_cell++, cell_data);
      }

      // Set bisection twins
      refined_bisection_twins[current_cell - 2] = current_cell - 1;
      refined_bisection_twins[current_cell - 1] = current_cell - 2;
    }
  }

  // Close mesh editor
  dolfin_assert(num_cells == current_cell);
  editor.close();
}
//-----------------------------------------------------------------------------
void MeshPartitioning::build_mesh(Mesh& mesh,
              const std::vector<std::size_t>& global_cell_indices,
              const boost::multi_array<std::size_t, 2>& cell_global_vertices,
              const std::vector<std::size_t>& vertex_indices,
              const boost::multi_array<double, 2>& vertex_coordinates,
              const std::map<std::size_t, std::size_t>& vertex_global_to_local,
              std::size_t tdim, std::size_t gdim, std::size_t num_global_cells,
              std::size_t num_global_vertices)
{
  Timer timer("PARALLEL 3: Build mesh (from local mesh data)");

  // Get number of processes and process number
  const std::size_t num_processes = MPI::num_processes();
  const std::size_t process_number = MPI::process_number();

  // Open mesh for editing
  mesh.clear();
  MeshEditor editor;
  editor.open(mesh, tdim, gdim);

  // Add vertices
  editor.init_vertices(vertex_coordinates.size());
  Point point(gdim);
  dolfin_assert(vertex_indices.size() == vertex_coordinates.size());
  for (std::size_t i = 0; i < vertex_coordinates.size(); ++i)
  {
    for (std::size_t j = 0; j < gdim; ++j)
      point[j] = vertex_coordinates[i][j];
    editor.add_vertex_global(i, vertex_indices[i], point);
  }

  // Add cells
  editor.init_cells(cell_global_vertices.size());
  const std::size_t num_cell_vertices = tdim + 1;
  std::vector<std::size_t> cell(num_cell_vertices);
  for (std::size_t i = 0; i < cell_global_vertices.size(); ++i)
  {
    for (std::size_t j = 0; j < num_cell_vertices; ++j)
    {
      // Get local cell vertex
      std::map<std::size_t, std::size_t>::const_iterator iter
          = vertex_global_to_local.find(cell_global_vertices[i][j]);
      dolfin_assert(iter != vertex_global_to_local.end());
      cell[j] = iter->second;
    }
    editor.add_cell(i, global_cell_indices[i], cell);
  }

  // Close mesh: Note that this must be done after creating the global
  // vertex map or otherwise the ordering in mesh.close() will be wrong
  // (based on local numbers).
  editor.close();

  // Set global number of cells and vertices
  mesh.topology().init_global(0, num_global_vertices);
  mesh.topology().init_global(tdim,  num_global_cells);

  // Construct boundary mesh
  BoundaryMesh bmesh(mesh, "exterior");

  const MeshFunction<std::size_t>& boundary_vertex_map = bmesh.entity_map(0);
  const std::size_t boundary_size = boundary_vertex_map.size();

  // Build sorted array of global boundary vertex indices (global
  // numbering)
  std::vector<std::size_t> global_vertex_send(boundary_size);
  for (std::size_t i = 0; i < boundary_size; ++i)
    global_vertex_send[i] = vertex_indices[boundary_vertex_map[i]];
  std::sort(global_vertex_send.begin(), global_vertex_send.end());

  // Receive buffer
  std::vector<std::size_t> global_vertex_recv;

  // Create shared_vertices data structure: mapping from shared vertices
  // to list of neighboring processes
  std::map<unsigned int, std::set<unsigned int> >& shared_vertices
        = mesh.topology().shared_entities(0);
  shared_vertices.clear();

  // FIXME: Remove computation from inside communication loop

  // Build shared vertex to sharing processes map
  for (std::size_t i = 1; i < num_processes; ++i)
  {
    // We send data to process p - i (i steps to the left)
    const int p = (process_number - i + num_processes) % num_processes;

    // We receive data from process p + i (i steps to the right)
    const int q = (process_number + i) % num_processes;

    // Send and receive
    MPI::send_recv(global_vertex_send, p, global_vertex_recv, q);

    // Compute intersection of global indices
    std::vector<std::size_t> intersection(std::min(global_vertex_send.size(),
                                                   global_vertex_recv.size()));
    std::vector<std::size_t>::iterator intersection_end
      = std::set_intersection(global_vertex_send.begin(),
                              global_vertex_send.end(),
                              global_vertex_recv.begin(),
                              global_vertex_recv.end(),
                              intersection.begin());

    // Fill shared vertices information
    std::vector<std::size_t>::const_iterator global_index;
    for (global_index = intersection.begin(); global_index != intersection_end;
         ++global_index)
    {
      // Get local index
      std::map<std::size_t, std::size_t>::const_iterator local_index;
      local_index = vertex_global_to_local.find(*global_index);
      dolfin_assert(local_index != vertex_global_to_local.end());

      // Insert (local index, [proc])
      shared_vertices[local_index->second].insert(q);
    }
  }
}