HPhi++  3.1.0
matrixscalapack.cpp
Go to the documentation of this file.
1 /* HPhi - Quantum Lattice Model Simulator */
2 /* Copyright (C) 2015 The University of Tokyo */
3 
4 /* This program is free software: you can redistribute it and/or modify */
5 /* it under the terms of the GNU General Public License as published by */
6 /* the Free Software Foundation, either version 3 of the License, or */
7 /* (at your option) any later version. */
8 
9 /* This program is distributed in the hope that it will be useful, */
10 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
11 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
12 /* GNU General Public License for more details. */
13 
14 /* You should have received a copy of the GNU General Public License */
15 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
16 #include "matrixscalapack.hpp"
29 #ifdef _SCALAPACK
30 int use_scalapack = 0;
31 
41 long int GetBlockSize(long int Msize, long int nproc) {
42  long int block_size = 16;
43  if(Msize*Msize/nproc > block_size*block_size)
44  return block_size;
45  return 1;
46 }
47 
58 long int GetPArrayIndex(long int i, long int np, long int nb) {
59  return (i/nb)%np;
60 }
61 
72 long int GetLocalIndex(long int i, long int np, long int nb) {
73  return (i/(np*nb))*nb + i%nb;
74 }
75 
87 long int GetGlobalIndex(long int il, long int p, long int np, long int nb){
88  return ((il/nb)*np+p)*nb + il%nb;
89 }
90 
103 long int MatToRank(long int i, long int j, long int nprow, long int npcol, long int nb){
104  long int iproc, jproc;
105  iproc = GetPArrayIndex(i, nprow, nb);
106  jproc = GetPArrayIndex(j, npcol, nb);
107  return iproc+jproc*nprow;
108 }
109 
121 long int GetMatRawInRank(long int lj, long int rank, long int npcol, long int nb){
122  long int pcol = rank/npcol;
123  return GetGlobalIndex(lj, pcol, npcol, nb);
124 }
125 
138 long int *GetMatElementInRank(long int i, long int j, long int nprow, long int npcol, long int nb){
139  long int *ij;
140  ij = malloc(2*sizeof(int));
141  ij[0] = GetLocalIndex(i, nprow, nb);
142  ij[1] = GetLocalIndex(j, npcol, nb);
143  return ij;
144 }
145 
157 void DivMat(long int m, long int n, std::complex<double> Aorgmn, std::complex<double> *A, int *desca){
158  long int mp = m+1, np = n+1;
159  pzelset_(A, &mp, &np, desca, &Aorgmn);
160 }
161 
173 void GetEigenVector(long int i, long int m, std::complex<double> *Z, int *descZ, std::complex<double> *vec) {
174  std::complex<double> alpha;
175  long int j, ip, jp;
176  int rank;
177  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
178  ip = i+1;
179  for(j=0; j<m; j++){
180  jp = j+1;
181  pzelget_("A", " ", &alpha, Z, &jp, &ip, descZ);
182  if(rank==0) {
183  vec[j] = alpha;
184  }
185  }
186 }
187 
200 int diag_scalapack_cmp(long int xNsize, std::complex<double> **A,
201  std::complex<double> *r, std::complex<double> *Z, int *descZ) {
202  const int i_one=1, i_zero=0;
203  const long int i_negone=-1;
204  const double zero=0.0, one=1.0;
205  long int m, n, mb, nb;
206  int nprow, npcol;
207  int myrow, mycol, info, lld;
208  long int mp, nq;
209  int ictxt;
210  std::complex<double> *A_distr, *work, *rwork;
211  double *W;
212  int descA_distr[9];
213  int rank, size, iam, nprocs;
214  long int lwork, lrwork;
215  int dims[2]={0,0};
216  long int i, j, ip, jp;
217  m=n=xNsize;
218 
219  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
220  MPI_Comm_size(MPI_COMM_WORLD, &size);
221  MPI_Dims_create(size,2,dims);
222  nprow=dims[0]; npcol=dims[1];
223 
224  blacs_pinfo_(&iam, &nprocs);
225  blacs_get_((int *)&i_negone, &i_zero, &ictxt);
226  blacs_gridinit_(&ictxt, "R", &nprow, &npcol);
227  blacs_gridinfo_(&ictxt, &nprow, &npcol, &myrow, &mycol);
228 
229  mb = GetBlockSize(m, size);
230  nb = GetBlockSize(n, size);
231 
232  mp = numroc_(&m, &mb, &myrow, &i_zero, &nprow);
233  nq = numroc_(&n, &nb, &mycol, &i_zero, &npcol);
234  W = malloc(n*sizeof(double));
235  A_distr = malloc(mp*nq*sizeof(std::complex<double>));
236 
237  lld = (mp>0) ? mp : 1;
238  descinit_(descA_distr, &m, &n, &mb, &nb, &i_zero, &i_zero, &ictxt, &lld, &info);
239  descinit_(descZ, &m, &n, &mb, &nb, &i_zero, &i_zero, &ictxt, &lld, &info);
240 
241  for(i=0; i<m; i++){
242  for(j=0; j<n; j++){
243  DivMat(i, j, A[i][j], A_distr, descA_distr);
244  }
245  }
246 
247  std::complex<double> wkopt, rwkopt;
248  pzheev_("V", "U", &n, A_distr, &i_one, &i_one, descA_distr, W, Z, &i_one, &i_one, descZ, &wkopt, &i_negone, &rwkopt, &i_negone, &info);
249 
250  lwork = (long int)wkopt;
251  lrwork = (long int)rwkopt;
252  work = malloc(lwork*sizeof(std::complex<double>));
253  rwork = malloc(lrwork*sizeof(std::complex<double>));
254 
255 
256  pzheev_("V", "U", &n, A_distr, &i_one, &i_one, descA_distr, W, Z, &i_one, &i_one, descZ, work, &lwork, rwork, &lrwork, &info);
257 
258  if(rank == 0){
259  for(i=0; i<n; i++){
260  r[i] = W[i];
261  }
262  }
263 
264  free(A_distr);
265  free(work);
266  free(rwork);
267  free(W);
268 
269  use_scalapack = 1;
270 
271  return 0;
272 }
273 
274 #endif
int nproc
Number of processors, defined in InitializeMPI()
Definition: global.cpp:72