SIRIUS 7.5.0
Electronic structure library and applications
mpi_grid.hpp
Go to the documentation of this file.
1// Copyright (c) 2013-2016 Anton Kozhevnikov, Thomas Schulthess
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
5// the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
8// following disclaimer.
9// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
10// and the following disclaimer in the documentation and/or other materials provided with the distribution.
11//
12// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
13// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
14// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
15// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
16// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
17// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
18// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19
20/** \file mpi_grid.hpp
21 *
22 * \brief Contains declaration and implementation of sddk::MPI_grid class.
23 */
24
25#ifndef __MPI_GRID_HPP__
26#define __MPI_GRID_HPP__
27
28#include "communicator.hpp"
29#include "core/rte/rte.hpp"
30
31namespace sirius {
32
33namespace mpi {
34
35/// MPI grid interface
36/** The following terminology is used. Suppose we have a 4x5 grid of MPI ranks. We say it's a two-\em dimensional
37 * grid with the first dimension of the size 4 and the second dimensoion of the size 5. The \em actual number of
38 * grid dimensions is two, however we may also consider the grid as being a D-dimensional (D >= 2) with implicit
39 * dimension sizes equal to one, e.g. 4x5 := 4x5x1x1x1... The communication happens along single or multiple
40 * \em directions along the grid dimensions. We specify directions wth bits, eg. directions=00000101 reads as
41 * "communication along 1-st and 3-rd dimensions".
42 * \image html mpi_grid_comm.png "Communication along dimension d0 (between ranks of d0)."
43 * In the provided example the corresponding communicator is MPI_grid::communicator(1 << d0), where d0 is the integer
44 * index of dimension.
45 */
46class Grid
47{
48 private:
49 /// Dimensions of the grid.
50 std::vector<int> dimensions_;
51
52 /// Parent communicator
54
55 /// Grid communicator of the enrire grid returned by MPI_Cart_create
57
58 /// Grid communicators
59 /** Grid comminicators are built for all possible combinations of directions, i.e. 001, 010, 011, etc.
60 * First communicator is the trivial "self" communicator; the last communicator handles the entire grid. */
61 std::vector<Communicator> communicators_;
62
63 /// Return valid directions for the current grid dimensionality.
64 inline int valid_directions(int directions__) const
65 {
66 return (directions__ & ((1 << dimensions_.size()) - 1));
67 }
68
69 /// Initialize the grid.
71 {
72 if (dimensions_.size() == 0) {
73 RTE_THROW("no dimensions provided for the MPI grid");
74 }
75
76 int sz{1};
77 for (size_t i = 0; i < dimensions_.size(); i++) {
78 sz *= dimensions_[i];
79 }
80
81 if (parent_communicator_.size() != sz) {
82 std::stringstream s;
83 s << "Number of MPI ranks doesn't match the size of the grid." << std::endl << " grid dimensions :";
84 for (auto& e : dimensions_) {
85 s << " " << e;
86 }
87 s << std::endl << " available number of MPI ranks : " << parent_communicator_.size();
88
89 RTE_THROW(s);
90 }
91
92 /* communicator of the entire grid */
93 std::vector<int> periods(dimensions_.size(), 0);
95 periods.data());
96
97 /* total number of communicators inside the grid */
98 int num_comm = 1 << dimensions_.size();
99
100 communicators_ = std::vector<Communicator>(num_comm);
101
102 /* get all possible communicators */
103 for (int i = 1; i < num_comm; i++) {
104 //bool is_root = true;
105 //int comm_size = 1;
106 std::vector<int> flg(dimensions_.size(), 0);
107
108 /* each bit represents a directions */
109 for (int j = 0; j < (int)dimensions_.size(); j++) {
110 if (i & (1 << j)) {
111 flg[j] = 1;
112 }
113 }
114 /* subcommunicators */
115 communicators_[i] = base_grid_communicator_.cart_sub(flg.data());
116 }
117
118 /* expicitly set the "self" communicator */
119 communicators_[0] = Communicator(MPI_COMM_SELF);
120 }
121
122 /* forbid copy constructor */
123 Grid(Grid const& src) = delete;
124 /* forbid assignment operator */
125 Grid& operator=(Grid const& src) = delete;
126
127 public:
128 Grid(std::vector<int> dimensions__, Communicator const& parent_communicator__)
129 : dimensions_(dimensions__)
130 , parent_communicator_(parent_communicator__)
131 {
132 initialize();
133 }
134
135 /// Actual number of grid dimensions
136 inline int num_dimensions() const
137 {
138 return static_cast<int>(dimensions_.size());
139 }
140
141 inline auto const& communicator(int directions__ = 0xFF) const
142 {
143 assert(communicators_.size() != 0);
144 return communicators_[valid_directions(directions__)];
145 }
146};
147
148} // namespace mpi
149
150} // namespace sirius
151
152#endif // __MPI_GRID_HPP__
MPI communicator wrapper.
int size() const
Size of the communicator (number of ranks).
MPI grid interface.
Definition: mpi_grid.hpp:47
Communicator const & parent_communicator_
Parent communicator.
Definition: mpi_grid.hpp:53
std::vector< int > dimensions_
Dimensions of the grid.
Definition: mpi_grid.hpp:50
Communicator base_grid_communicator_
Grid communicator of the enrire grid returned by MPI_Cart_create.
Definition: mpi_grid.hpp:56
std::vector< Communicator > communicators_
Grid communicators.
Definition: mpi_grid.hpp:61
int valid_directions(int directions__) const
Return valid directions for the current grid dimensionality.
Definition: mpi_grid.hpp:64
void initialize()
Initialize the grid.
Definition: mpi_grid.hpp:70
int num_dimensions() const
Actual number of grid dimensions.
Definition: mpi_grid.hpp:136
Contains declaration and implementation of mpi::Communicator class.
Namespace of the SIRIUS library.
Definition: sirius.f90:5
Eror and warning handling during run-time execution.