Distributed grid#

Data type mpl::distributed_grid in action.

#include <cstdlib>
#include <iostream>
#include <mpl/mpl.hpp>

template<std::size_t dim, typename T, typename A>
void update_overlap(const mpl::cartesian_communicator &cartesian_communicator,
                    mpl::distributed_grid<dim, T, A> &grid, mpl::tag_t tag = mpl::tag_t()) {
  for (std::size_t i{0}; i < dim; ++i) {
    // send to left
    auto [source_l, destination_l] = cartesian_communicator.shift(i, -1);
    cartesian_communicator.sendrecv(grid.data(), grid.left_border_layout(i), destination_l,
                                    tag, grid.data(), grid.right_mirror_layout(i), source_l,
                                    tag);
    // send to right
    auto [source_r, destination_r] = cartesian_communicator.shift(i, +1);
    cartesian_communicator.sendrecv(grid.data(), grid.right_border_layout(i), destination_r,
                                    tag, grid.data(), grid.left_mirror_layout(i), source_r,
                                    tag);
  }
}


int main() {
  const mpl::communicator &comm_world{mpl::environment::comm_world()};
  {
    // build a one-dimensional Cartesian communicator
    // Cartesian is non-cyclic
    mpl::cartesian_communicator::dimensions size{mpl::cartesian_communicator::non_periodic};
    mpl::cartesian_communicator comm_c{comm_world, mpl::dims_create(comm_world.size(), size)};
    // create a distributed grid of 31 total grid points and 2 shadow grid points
    // to mirror data between adjacent processes
    mpl::distributed_grid<1, int> grid{comm_c, {{31, 2}}};
    // fill local grid including shadow grid points
    for (auto i{grid.obegin(0)}, i_end{grid.oend(0)}; i < i_end; ++i)
      grid(i) = comm_c.rank();
    // get shadow data from adjacent processes
    update_overlap(comm_c, grid);
    // print local grid including shadow grid points
    for (int k{0}; k < comm_c.size(); ++k) {
      if (k == comm_c.rank()) {
        for (auto i{grid.obegin(0)}, i_end{grid.oend(0)}; i < i_end; ++i)
          std::cout << grid(i);
        std::cout << std::endl;
      }
      comm_c.barrier();  // barrier may avoid overlapping output
    }
  }
  {
    // build a two-dimensional Cartesian communicator
    // Cartesian is cyclic along 1st dimension, non-cyclic along 2nd dimension
    mpl::cartesian_communicator::dimensions size{mpl::cartesian_communicator::periodic,
                                                 mpl::cartesian_communicator::non_periodic};
    mpl::cartesian_communicator comm_c{comm_world, mpl::dims_create(comm_world.size(), size)};
    // create a distributed grid of 11x13 total grid points and 2 respectively 1
    // shadow grid points to mirror data between adjacent processes
    mpl::distributed_grid<2, int> grid{comm_c, {{11, 2}, {13, 1}}};
    // fill local grid including shadow grid points
    for (auto j{grid.obegin(1)}, j_end{grid.oend(1)}; j < j_end; ++j)
      for (auto i{grid.obegin(0)}, i_end{grid.oend(0)}; i < i_end; ++i)
        grid(i, j) = comm_c.rank();
    // get shadow data from adjacent processes
    update_overlap(comm_c, grid);
    // print local grid including shadow grid points
    for (int k{0}; k < comm_c.size(); ++k) {
      if (k == comm_c.rank()) {
        std::cout << std::endl;
        for (auto j{grid.obegin(1)}, j_end{grid.oend(1)}; j < j_end; ++j) {
          for (auto i{grid.obegin(0)}, i_end{grid.oend(0)}; i < i_end; ++i)
            std::cout << grid(i, j);
          std::cout << std::endl;
        }
      }
      comm_c.barrier();  // barrier may avoid overlapping output
    }
  }
  return EXIT_SUCCESS;
}