// Copyright Alain Miniussi 2014. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // Authors: Alain Miniussi #include #include namespace boost { namespace mpi { std::ostream& operator<<(std::ostream& out, cartesian_dimension const& d) { out << '(' << d.size << ','; if (d.periodic) { out << "periodic"; } else { out << "bounded"; } out << ')'; return out; } std::ostream& operator<<(std::ostream& out, cartesian_topology const& topo) { out << '{'; int const sz = topo.size(); for (int i = 0; i < sz; ++i) { out << topo[i]; if ( i < (sz-1) ) { out << ','; } } out << '}'; return out; } cartesian_communicator::cartesian_communicator(const communicator& comm, const cartesian_topology& topology, bool reorder ) : communicator(MPI_COMM_NULL, comm_attach) { std::vector dims(topology.size()); std::vector periodic(topology.size()); int tsz = topology.size(); for(int i = 0; i < tsz; ++i) { dims[i] = topology[i].size; periodic[i] = topology[i].periodic; } // Fill the gaps, if any if (std::count(dims.begin(), dims.end(), 0) > 0) { cartesian_dimensions(comm, dims); } MPI_Comm newcomm; BOOST_MPI_CHECK_RESULT(MPI_Cart_create, ((MPI_Comm)comm, dims.size(), dims.data(), periodic.data(), int(reorder), &newcomm)); if(newcomm != MPI_COMM_NULL) { comm_ptr.reset(new MPI_Comm(newcomm), comm_free()); } } cartesian_communicator::cartesian_communicator(const cartesian_communicator& comm, const std::vector& keep ) : communicator(MPI_COMM_NULL, comm_attach) { int const max_dims = comm.ndims(); int const nbkept = keep.size(); BOOST_ASSERT(nbkept <= max_dims); std::vector bitset(max_dims, int(false)); for(int i = 0; i < nbkept; ++i) { BOOST_ASSERT(keep[i] < max_dims); bitset[keep[i]] = true; } MPI_Comm newcomm; BOOST_MPI_CHECK_RESULT(MPI_Cart_sub, ((MPI_Comm)comm, bitset.data(), &newcomm)); if(newcomm != MPI_COMM_NULL) { comm_ptr.reset(new MPI_Comm(newcomm), comm_free()); } } int cartesian_communicator::ndims() const { int n = -1; BOOST_MPI_CHECK_RESULT(MPI_Cartdim_get, (MPI_Comm(*this), &n)); return n; } int cartesian_communicator::rank(const std::vector& coords ) const { int r = -1; BOOST_ASSERT(int(coords.size()) == ndims()); BOOST_MPI_CHECK_RESULT(MPI_Cart_rank, (MPI_Comm(*this), const_cast&>(coords).data(), &r)); return r; } std::pair cartesian_communicator::shifted_ranks(int dim, int disp) const { std::pair r(-1,-1); assert((0 <= dim && dim < ndims()) || (std::abort(), false)); BOOST_ASSERT(0 <= dim && dim < ndims()); BOOST_MPI_CHECK_RESULT(MPI_Cart_shift, (MPI_Comm(*this), dim, disp, &(r.first), &(r.second))); return r; } std::vector& cartesian_communicator::coords(int rk, std::vector& cbuf) const { cbuf.resize(ndims()); BOOST_MPI_CHECK_RESULT(MPI_Cart_coords, (MPI_Comm(*this), rk, cbuf.size(), cbuf.data() )); return cbuf; } std::vector cartesian_communicator::coords(int rk) const { std::vector coords; this->coords(rk, coords); return coords; } void cartesian_communicator::topology( cartesian_topology& topo, std::vector& coords ) const { int ndims = this->ndims(); topo.resize(ndims); coords.resize(ndims); std::vector cdims(ndims); std::vector cperiods(ndims); BOOST_MPI_CHECK_RESULT(MPI_Cart_get, (MPI_Comm(*this), ndims, cdims.data(), cperiods.data(), coords.data())); cartesian_topology res(cdims.begin(), cperiods.begin(), ndims); topo.swap(res); } cartesian_topology cartesian_communicator::topology() const { cartesian_topology topo(ndims()); std::vector coords; topology(topo, coords); return topo; } void cartesian_topology::split(std::vector& dims, std::vector& periodics) const { int ndims = size(); dims.resize(ndims); periodics.resize(ndims); for(int i = 0; i < ndims; ++i) { cartesian_dimension const& d = (*this)[i]; dims[i] = d.size; periodics[i] = d.periodic; } } std::vector& cartesian_dimensions(int sz, std::vector& dims) { int min = 1; int const dimsz = dims.size(); for(int i = 0; i < dimsz; ++i) { if (dims[i] > 0) { min *= dims[i]; } } int leftover = sz % min; BOOST_MPI_CHECK_RESULT(MPI_Dims_create, (sz-leftover, dims.size(), dims.data())); return dims; } } } // end namespace boost::mpi