ABACUS develop
Atomic-orbital Based Ab-initio Computation at UStc
Loading...
Searching...
No Matches
diago_elpa_utils.h
Go to the documentation of this file.
3#include "mpi.h"
4
5#include <complex>
6#include <fstream>
7#include <iomanip>
8#include <iostream>
9#include <math.h>
10#include <random>
11#include <type_traits>
12#include <vector>
13
14#ifdef __ELPA
16#endif
17
19{
20void process_2d(int &nprows, int &npcols, int &myprow, int &mypcol, int &icontxt) // map the processes to 2D matrix
21{
22 int nprocs, mypnum;
23 MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
24 MPI_Comm_rank(MPI_COMM_WORLD, &mypnum);
25
26 for (npcols = int(sqrt(double(nprocs))); npcols >= 1; --npcols)
27 {
28 if (nprocs % npcols == 0)
29 break;
30 }
31 nprows = nprocs / npcols;
32
33 int *usermap = new int[nprocs];
34 for (int i = 0; i < nprows; i++)
35 {
36 for (int j = 0; j < npcols; j++)
37 usermap[j * nprows + i] = i * npcols + j;
38 }
39
40 int what = 0, ic = 0;
41 Cblacs_get(ic, what, &icontxt);
42 Cblacs_pinfo(&mypnum, &nprocs);
43 Cblacs_gridmap(&icontxt, usermap, nprows, nprows, npcols);
44 Cblacs_gridinfo(icontxt, &nprows, &npcols, &myprow, &mypcol);
45 delete[] usermap;
46}
47
48inline int na_rc(int n, int nblk, int nprows, int myprow) // calculate the row/column number in each process
49{
50 int i, na = 0;
51 for (i = 0; i < n; i++)
52 if ((i % (nblk * nprows)) / nblk == myprow)
53 na++;
54 return na;
55}
56
57// distribute hmatrix to each process
58// hmatrix is row-first, and new_matrix is column-first
59template <class T>
60void distribute_data(T *hmatrix, T *new_matrix, int &nFull, int &nblk, int &na_rows, int &na_cols, int &icontxt)
61{
62 int mypnum;
63 MPI_Comm_rank(MPI_COMM_WORLD, &mypnum);
64 int nprows, npcols, myprow, mypcol;
65 Cblacs_gridinfo(icontxt, &nprows, &npcols, &myprow, &mypcol);
66
67 int SENDPROW = 0, SENDPCOL = 0, tag = 0;
68 T *tmp = new T[nblk];
69
70 // do iteration for matrix, distribute old_matrix to each process, pass a block each time
71 for (int row = 0; row < nFull; row++)
72 {
73 int recv_prow = (row / nblk) % nprows; // the row number of recive process
74 int nm_row = ((row / nblk) / nprows) * nblk + row % nblk; // row number of block in new_matrix
75 for (int col = 0; col < nFull; col += nblk)
76 {
77 int recv_pcol = (col / nblk) % npcols; // the column number of recive process
78 int nm_col = ((col / nblk) / npcols) * nblk + col % nblk;
79 int pass_length = std::min(nFull - col, nblk); // nFull may not be devided by nblk;
80
81 if (myprow == SENDPROW && mypcol == SENDPCOL)
82 {
83 if (myprow == recv_prow && mypcol == recv_pcol)
84 {
85 for (int i = 0; i < pass_length; i++)
86 {
87 new_matrix[(nm_col + i) * na_rows + nm_row] = hmatrix[nFull * row + col + i];
88 }
89 }
90 else
91 {
92 if (std::is_same<T, double>::value)
93 MPI_Send(&(hmatrix[nFull * row + col]),
94 pass_length,
95 MPI_DOUBLE,
96 recv_prow * npcols + recv_pcol,
97 tag,
98 MPI_COMM_WORLD);
99 else
100 MPI_Send(&(hmatrix[nFull * row + col]),
101 pass_length,
102 MPI_DOUBLE_COMPLEX,
103 recv_prow * npcols + recv_pcol,
104 tag,
105 MPI_COMM_WORLD);
106 }
107 }
108 else if (myprow == recv_prow && mypcol == recv_pcol)
109 {
110 if (std::is_same<T, double>::value)
111 MPI_Recv(tmp, pass_length, MPI_DOUBLE, 0, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
112 else
113 MPI_Recv(tmp, pass_length, MPI_DOUBLE_COMPLEX, 0, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
114 for (int i = 0; i < pass_length; i++)
115 {
116 new_matrix[(nm_col + i) * na_rows + nm_row] = tmp[i];
117 }
118 }
119 }
120 }
121 delete[] tmp;
122}
123
124template <class T> inline void print_matrix(std::ofstream &fp, T *matrix, int &nrow, int &ncol, bool row_first)
125{
126 int coef_row = row_first ? ncol : 1;
127 int coef_col = row_first ? 1 : nrow;
128 for (int i = 0; i < nrow; i++)
129 {
130 for (int j = 0; j < ncol; j++)
131 {
132 fp << std::setw(15) << matrix[i * coef_row + j * coef_col] << " ";
133 }
134 fp << std::endl;
135 }
136}
137
138template <class T> bool read_hs(std::string fname, T &matrix)
139{
140 int ndim;
141 std::ifstream inf(fname);
142 if(! inf.is_open())
143 {
144 std::cout << "Error: open file " << fname << " failed, skip!" << std::endl;
145 return false;
146 }
147 inf >> ndim;
148 matrix.resize(ndim*ndim);
149 for (int i = 0; i < ndim; i++)
150 {
151 for (int j = i; j < ndim; j++)
152 {
153 inf >> matrix[i * ndim + j];
154 if (i != j)
155 {
156 matrix[j * ndim + i] = matrix[i * ndim + j];
157 }
158 }
159 }
160 inf.close();
161 return true;
162}
163
164void lapack_diago(double *hmatrix, double *smatrix, double *e, int &nFull)
165{
166 const int itype = 1; // solve A*X=(lambda)*B*X
167 const char jobz = 'V'; // 'N':only calc eigenvalue, 'V': eigenvalues and eigenvectors
168 const char uplo = 'U'; // Upper triangles
169 int lwork = (nFull + 2) * nFull, info = 0;
170 double *ev = new double[nFull * nFull];
171
172 double *a = new double[nFull * nFull];
173 double *b = new double[nFull * nFull];
174 for (int i = 0; i < nFull * nFull; i++)
175 {
176 a[i] = hmatrix[i];
177 b[i] = smatrix[i];
178 }
179
180 dsygv_(&itype, &jobz, &uplo, &nFull, a, &nFull, b, &nFull, e, ev, &lwork, &info);
181 if (info != 0)
182 {
183 std::cout << "ERROR: solvered by LAPACK error, info=" << info << std::endl;
184 exit(1);
185 }
186
187 delete[] a;
188 delete[] b;
189 delete[] ev;
190}
191
192void lapack_diago(std::complex<double> *hmatrix, std::complex<double> *smatrix, double *e, int &nFull)
193{
194 const int itype = 1; // solve A*X=(lambda)*B*X
195 const char jobz = 'V'; // 'N':only calc eigenvalue, 'V': eigenvalues and eigenvectors
196 const char uplo = 'U'; // Upper triangles
197 int lwork = (nFull + 1) * nFull, info = 0;
198 double *rwork = new double[3 * nFull - 2];
199 std::complex<double> *ev = new std::complex<double>[nFull * nFull];
200
201 std::complex<double> *a = new std::complex<double>[nFull * nFull];
202 std::complex<double> *b = new std::complex<double>[nFull * nFull];
203 for (int i = 0; i < nFull * nFull; i++)
204 {
205 a[i] = hmatrix[i];
206 b[i] = smatrix[i];
207 }
208
209 zhegv_(&itype, &jobz, &uplo, &nFull, a, &nFull, b, &nFull, e, ev, &lwork, rwork, &info);
210 if (info != 0)
211 {
212 std::cout << "ERROR: solvered by LAPACK error, info=" << info << std::endl;
213 exit(1);
214 }
215
216 delete[] a;
217 delete[] b;
218 delete[] ev;
219 delete[] rwork;
220}
221
222} // namespace LCAO_DIAGO_TEST
void Cblacs_get(int icontxt, int what, int *val)
void Cblacs_pinfo(int *myid, int *nprocs)
void Cblacs_gridmap(int *icontxt, int *usermap, int ldumap, int nprow, int npcol)
void Cblacs_gridinfo(int icontxt, int *nprow, int *npcol, int *myprow, int *mypcol)
#define T
Definition exp.cpp:237
void zhegv_(const int *itype, const char *jobz, const char *uplo, const int *n, std::complex< double > *a, const int *lda, std::complex< double > *b, const int *ldb, double *w, std::complex< double > *work, int *lwork, double *rwork, int *info)
void dsygv_(const int *itype, const char *jobz, const char *uplo, const int *n, double *a, const int *lda, double *b, const int *ldb, double *w, double *work, int *lwork, int *info)
Definition diago_elpa_utils.h:19
int na_rc(int n, int nblk, int nprows, int myprow)
Definition diago_elpa_utils.h:48
void process_2d(int &nprows, int &npcols, int &myprow, int &mypcol, int &icontxt)
Definition diago_elpa_utils.h:20
void print_matrix(std::ofstream &fp, T *matrix, int &nrow, int &ncol, bool row_first)
Definition diago_elpa_utils.h:124
void distribute_data(T *hmatrix, T *new_matrix, int &nFull, int &nblk, int &na_rows, int &na_cols, int &icontxt)
Definition diago_elpa_utils.h:60
void lapack_diago(double *hmatrix, double *smatrix, double *e, int &nFull)
Definition diago_elpa_utils.h:164
bool read_hs(std::string fname, T &matrix)
Definition diago_elpa_utils.h:138
int mypcol
Definition tddft_test.cpp:14
int myprow
Definition tddft_test.cpp:14