• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 //          Copyright Alain Miniussi 2014.
3 // Distributed under the Boost Software License, Version 1.0.
4 //    (See accompanying file LICENSE_1_0.txt or copy at
5 //          http://www.boost.org/LICENSE_1_0.txt)
6 
7 // Authors: Alain Miniussi
8 
9 #include <algorithm>
10 #include <cassert>
11 
12 #include <boost/mpi/cartesian_communicator.hpp>
13 #include <boost/mpi/detail/antiques.hpp>
14 
15 namespace boost { namespace mpi {
16 
17 std::ostream&
operator <<(std::ostream & out,cartesian_dimension const & d)18 operator<<(std::ostream& out, cartesian_dimension const& d) {
19   out << '(' << d.size << ',';
20   if (d.periodic) {
21     out << "periodic";
22   } else {
23     out << "bounded";
24   }
25   out << ')';
26   return out;
27 }
28 
29 std::ostream&
operator <<(std::ostream & out,cartesian_topology const & topo)30 operator<<(std::ostream& out, cartesian_topology const& topo) {
31   out << '{';
32   int const sz = topo.size();
33   for (int i = 0; i < sz; ++i) {
34     out << topo[i];
35     if ( i < (sz-1) ) {
36       out << ',';
37     }
38   }
39   out << '}';
40   return out;
41 }
42 
cartesian_communicator(const communicator & comm,const cartesian_topology & topology,bool reorder)43 cartesian_communicator::cartesian_communicator(const communicator&         comm,
44                                                const cartesian_topology&   topology,
45                                                bool                        reorder )
46   : communicator(MPI_COMM_NULL, comm_attach)
47 {
48   std::vector<int> dims(topology.size());
49   std::vector<int> periodic(topology.size());
50   int tsz = topology.size();
51   for(int i = 0; i < tsz; ++i) {
52     dims[i]     = topology[i].size;
53     periodic[i] = topology[i].periodic;
54   }
55   // Fill the gaps, if any
56   if (std::count(dims.begin(), dims.end(), 0) > 0) {
57     cartesian_dimensions(comm, dims);
58   }
59   MPI_Comm newcomm;
60   BOOST_MPI_CHECK_RESULT(MPI_Cart_create,
61                          ((MPI_Comm)comm, dims.size(),
62                           detail::c_data(dims), detail::c_data(periodic),
63                           int(reorder), &newcomm));
64   if(newcomm != MPI_COMM_NULL) {
65     comm_ptr.reset(new MPI_Comm(newcomm), comm_free());
66   }
67 }
68 
cartesian_communicator(const cartesian_communicator & comm,const std::vector<int> & keep)69 cartesian_communicator::cartesian_communicator(const cartesian_communicator& comm,
70                                                const std::vector<int>&       keep )
71   : communicator(MPI_COMM_NULL, comm_attach)
72 {
73   int const max_dims = comm.ndims();
74   int const nbkept = keep.size();
75   assert(nbkept <= max_dims);
76   std::vector<int> bitset(max_dims, int(false));
77   for(int i = 0; i < nbkept; ++i) {
78     assert(keep[i] < max_dims);
79     bitset[keep[i]] = true;
80   }
81 
82   MPI_Comm newcomm;
83   BOOST_MPI_CHECK_RESULT(MPI_Cart_sub,
84                          ((MPI_Comm)comm, detail::c_data(bitset), &newcomm));
85   if(newcomm != MPI_COMM_NULL) {
86     comm_ptr.reset(new MPI_Comm(newcomm), comm_free());
87   }
88 }
89 
90 int
ndims() const91 cartesian_communicator::ndims() const {
92   int n = -1;
93   BOOST_MPI_CHECK_RESULT(MPI_Cartdim_get,
94                          (MPI_Comm(*this), &n));
95   return n;
96 }
97 
98 int
rank(const std::vector<int> & coords) const99 cartesian_communicator::rank(const std::vector<int>& coords ) const {
100   int r = -1;
101   assert(int(coords.size()) == ndims());
102   BOOST_MPI_CHECK_RESULT(MPI_Cart_rank,
103                          (MPI_Comm(*this), detail::c_data(const_cast<std::vector<int>&>(coords)),
104                           &r));
105   return r;
106 }
107 
108 std::pair<int, int>
shifted_ranks(int dim,int disp) const109 cartesian_communicator::shifted_ranks(int dim, int disp) const {
110   std::pair<int, int> r(-1,-1);
111   assert(0 <= dim && dim < ndims());
112   BOOST_MPI_CHECK_RESULT(MPI_Cart_shift,
113                          (MPI_Comm(*this), dim, disp, &(r.first), &(r.second)));
114   return r;
115 }
116 
117 std::vector<int>
coordinates(int rk) const118 cartesian_communicator::coordinates(int rk) const {
119   std::vector<int> cbuf(ndims());
120   BOOST_MPI_CHECK_RESULT(MPI_Cart_coords,
121                          (MPI_Comm(*this), rk, cbuf.size(), detail::c_data(cbuf) ));
122   return cbuf;
123 }
124 
125 void
topology(cartesian_topology & topo,std::vector<int> & coords) const126 cartesian_communicator::topology(  cartesian_topology&  topo,
127                                    std::vector<int>&  coords ) const {
128   int ndims = this->ndims();
129   topo.resize(ndims);
130   coords.resize(ndims);
131   std::vector<int> cdims(ndims);
132   std::vector<int> cperiods(ndims);
133   BOOST_MPI_CHECK_RESULT(MPI_Cart_get,
134                          (MPI_Comm(*this), ndims, detail::c_data(cdims), detail::c_data(cperiods), detail::c_data(coords)));
135   cartesian_topology res(cdims.begin(), cperiods.begin(), ndims);
136   topo.swap(res);
137 }
138 
139 cartesian_topology
topology() const140 cartesian_communicator::topology() const {
141   cartesian_topology topo(ndims());
142   std::vector<int> coords;
143   topology(topo, coords);
144   return topo;
145 }
146 
147 void
split(std::vector<int> & dims,std::vector<bool> & periodics) const148 cartesian_topology::split(std::vector<int>& dims, std::vector<bool>& periodics) const {
149   int ndims = size();
150   dims.resize(ndims);
151   periodics.resize(ndims);
152   for(int i = 0; i < ndims; ++i) {
153     cartesian_dimension const& d = (*this)[i];
154     dims[i]      = d.size;
155     periodics[i] = d.periodic;
156   }
157 }
158 
159 std::vector<int>&
cartesian_dimensions(int sz,std::vector<int> & dims)160 cartesian_dimensions(int sz, std::vector<int>&  dims) {
161   int min = 1;
162   int const dimsz = dims.size();
163   for(int i = 0; i < dimsz; ++i) {
164     if (dims[i] > 0) {
165       min *= dims[i];
166     }
167   }
168   int leftover = sz % min;
169 
170   BOOST_MPI_CHECK_RESULT(MPI_Dims_create,
171                          (sz-leftover, dims.size(), detail::c_data(dims)));
172   return dims;
173 }
174 
175 } } // end namespace boost::mpi
176