SIRIUS 7.5.0
Electronic structure library and applications
blacs_grid.hpp
Go to the documentation of this file.
1// Copyright (c) 2013-2018 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 blacs_grid.hpp
21 *
22 * \brief Contains declaration and implementation of sddk::BLACS_grid class.
23 */
24
25#ifndef __BLACS_GRID_HPP__
26#define __BLACS_GRID_HPP__
27
28#include <memory>
29#include "core/mpi/mpi_grid.hpp"
30#include "core/rte/rte.hpp"
31#include "linalg_base.hpp"
32
33#ifdef SIRIUS_DLAF
34#include "dlaf_c/grid.h"
35#endif
36
37namespace sirius {
38
39namespace la {
40
41/// BLACS grid wrapper.
43{
44 private:
45 mpi::Communicator const& comm_;
46
47 std::unique_ptr<mpi::Grid> mpi_grid_;
48
49
50#ifdef SIRIUS_SCALAPACK
51 int blacs_handler_{-1};
52#endif
53
54 int blacs_context_{-1};
55
56 std::vector<int> rank_map_;
57
58 /* forbid copy constructor */
59 BLACS_grid(BLACS_grid const& src) = delete;
60 /* forbid assignment operator */
61 BLACS_grid& operator=(BLACS_grid const& src) = delete;
62
63 public:
64 BLACS_grid(mpi::Communicator const& comm__, int num_ranks_row__, int num_ranks_col__)
65 : comm_(comm__)
66 {
67 mpi_grid_ = std::make_unique<mpi::Grid>(std::vector<int>({num_ranks_row__, num_ranks_col__}), comm_);
68 rank_map_.resize(num_ranks_row__ * num_ranks_col__);
69
70#ifdef SIRIUS_SCALAPACK
71 /* create handler first */
72 blacs_handler_ = linalg_base::create_blacs_handler(mpi_grid_->communicator().native());
73
74 for (int j = 0; j < num_ranks_col__; j++) {
75 for (int i = 0; i < num_ranks_row__; i++) {
76 rank_map_[i + j * num_ranks_row__] = mpi_grid_->communicator().cart_rank({i, j});
77 }
78 }
79
80 /* create context */
81 blacs_context_ = blacs_handler_;
82 linalg_base::gridmap(&blacs_context_, &rank_map_[0], num_ranks_row__, num_ranks_row__, num_ranks_col__);
83
84 /* check the grid */
85 int nrow1, ncol1, irow1, icol1;
86 linalg_base::gridinfo(blacs_context_, &nrow1, &ncol1, &irow1, &icol1);
87
88 if (rank_row() != irow1 || rank_col() != icol1 || num_ranks_row() != nrow1 || num_ranks_col() != ncol1) {
89 std::stringstream s;
90 s << "wrong grid" << std::endl
91 << " row | col | nrow | ncol " << std::endl
92 << " mpi_grid " << rank_row() << " " << rank_col() << " " << num_ranks_row() << " " << num_ranks_col()
93 << std::endl
94 << " blacs " << irow1 << " " << icol1 << " " << nrow1 << " " << ncol1;
95 RTE_THROW(s);
96 }
97
98#ifdef SIRIUS_DLAF
99 dlaf_create_grid_from_blacs(blacs_context_);
100#endif
101
102#else
103 for (int i = 0; i < static_cast<int>(rank_map_.size()); i++) {
104 rank_map_[i] = i;
105 }
106#ifdef SIRIUS_DLAF
107 blacs_context_ = dlaf_create_grid(comm_.native(), num_ranks_row__, num_ranks_col__, 'R');
108#endif
109#endif
110
111 }
112
114 {
115 int mpi_finalized;
116 MPI_Finalized(&mpi_finalized);
117 if (mpi_finalized == 0) {
118#ifdef SIRIUS_SCALAPACK
119 linalg_base::gridexit(blacs_context_);
120 linalg_base::free_blacs_handler(blacs_handler_);
121#endif
122 }
123#ifdef SIRIUS_DLAF
124 dlaf_free_grid(blacs_context_);
125#endif
126 }
127
128 inline int context() const
129 {
130 return blacs_context_;
131 }
132
133 inline auto const& comm() const
134 {
135 return comm_;
136 }
137
138 inline auto const& comm_row() const
139 {
140 return mpi_grid_->communicator(1 << 0);
141 }
142
143 inline auto const& comm_col() const
144 {
145 return mpi_grid_->communicator(1 << 1);
146 }
147
148 inline int num_ranks_row() const
149 {
150 return comm_row().size();
151 }
152
153 inline int rank_row() const
154 {
155 return comm_row().rank();
156 }
157
158 inline int num_ranks_col() const
159 {
160 return comm_col().size();
161 }
162
163 inline int rank_col() const
164 {
165 return comm_col().rank();
166 }
167
168 inline int cart_rank(int irow__, int icol__) const
169 {
170 return mpi_grid_->communicator().cart_rank({irow__, icol__});
171 }
172
173 auto const& mpi_grid() const
174 {
175 return *mpi_grid_;
176 }
177
178 auto const& rank_map() const
179 {
180 return rank_map_;
181 }
182};
183
184} // namespace
185
186} // namespace sirius
187
188#endif // __BLACS_GRID_HPP__
BLACS grid wrapper.
Definition: blacs_grid.hpp:43
static void gridmap(int *blacs_context, int *map, int ld, int nrow, int ncol)
Create BLACS context for the grid of MPI ranks.
static void free_blacs_handler(int blacs_handler)
Free BLACS handler.
static int create_blacs_handler(MPI_Comm comm)
Create BLACS handler.
static void gridexit(int blacs_context)
Destroy BLACS context.
MPI communicator wrapper.
MPI_Comm native() const
Return the native raw MPI communicator handler.
Basic interface to linear algebra functions.
Contains declaration and implementation of sddk::MPI_grid class.
Namespace of the SIRIUS library.
Definition: sirius.f90:5
Eror and warning handling during run-time execution.