HPhi++  3.1.0
wrapperMPI.cpp
Go to the documentation of this file.
1 /*
2 HPhi - Quantum Lattice Model Simulator
3 Copyright (C) 2015 The University of Tokyo
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
21 #ifdef __MPI
22 #include <mpi.h>
23 #endif
24 #include <cstdio>
25 #include <cstdlib>
26 #include <cstring>
27 #include "wrapperMPI.hpp"
28 #ifdef _OPENMP
29 #include <omp.h>
30 #endif
31 #include <cmath>
32 #include <complex>
33 #include "splash.hpp"
34 #include "global.hpp"
35 #include "common/setmemory.hpp"
36 
44 void InitializeMPI(int argc, char *argv[]){
45 #ifdef __MPI
46  int ierr;
47  ierr = MPI_Init(&argc, &argv);
48  ierr = MPI_Comm_size(MPI_COMM_WORLD, &nproc);
49  ierr = MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
50  if(ierr != 0) exitMPI(ierr);
51 #else
52  nproc = 1;
53  myrank = 0;
54 #endif
55  if (myrank == 0) stdoutMPI = stdout;
56  else stdoutMPI = fopen("/dev/null", "w");
57  splash();
58 
59 #pragma omp parallel default(none) shared(nthreads)
60 #pragma omp master
61 #ifdef _OPENMP
62  nthreads = omp_get_num_threads();
63 #else
64  nthreads=1;
65 #endif
66  fprintf(stdoutMPI, "\n\n##### Parallelization Info. #####\n\n");
67  fprintf(stdoutMPI, " OpenMP threads : %d\n", nthreads);
68  fprintf(stdoutMPI, " MPI PEs : %d \n\n", nproc);
69 }/*void InitializeMPI(int argc, char *argv[])*/
74 void FinalizeMPI(){
75 #ifdef __MPI
76  int ierr;
77  ierr = MPI_Finalize();
78  if (ierr != 0) fprintf(stderr, "\n MPI_Finalize() = %d\n\n", ierr);
79 #endif
80  if (myrank != 0) fclose(stdoutMPI);
81 }
86 void exitMPI(
87  int errorcode
88 )
89 {
90  fflush(stdout);
91 #ifdef __MPI
92  fprintf(stdout,"\n\n ####### [HPhi] You DO NOT have to WORRY about the following MPI-ERROR MESSAGE. #######\n\n");
93  int ierr;
94  ierr = MPI_Abort(MPI_COMM_WORLD, errorcode);
95  ierr = MPI_Finalize();
96  if (ierr != 0) fprintf(stderr, "\n MPI_Finalize() = %d\n\n", ierr);
97 #endif
98  exit(errorcode);
99 }/*void exitMPI*/
105 FILE* fopenMPI(
106  const char* FileName,
107  const char* mode
108 ){
109  FILE* fp;
110 
111  if (myrank == 0) fp = fopen(FileName, mode);
112  else fp = fopen("/dev/null", "w");
113 
114  return fp;
115 }/*FILE* fopenMPI*/
122 char* fgetsMPI(
123  char* InputString,
124  int maxcount,
125  FILE* fp
126 ){
127  int inull;
128  char *ctmp;
129 
130  ctmp = InputString;
131  inull = 0;
132  if (myrank == 0) {
133  ctmp = fgets(InputString, maxcount, fp);
134  if (ctmp == NULL){
135  inull = 1;
136  }
137 
138  while(*InputString == '\n' || strncmp(InputString, "#", 1)==0){
139  ctmp = fgets(InputString, maxcount, fp);
140  if (ctmp == NULL){
141  inull=1;
142  break;
143  }
144  }
145  }
146 #ifdef __MPI
147  MPI_Bcast(InputString, maxcount, MPI_CHAR, 0, MPI_COMM_WORLD);
148  MPI_Bcast(&inull, 1, MPI_INT, 0, MPI_COMM_WORLD);
149 #endif
150  if (myrank != 0 && inull == 1) {
151  ctmp = NULL;
152  }
153 
154  return ctmp;
155 }/*char* fgetsMPI*/
160 void BarrierMPI(){
161 #ifdef __MPI
162  MPI_Barrier(MPI_COMM_WORLD);
163 #endif
164 }/*void BarrierMPI()*/
171 long int MaxMPI_li(
172  long int idim
173 ){
174 #ifdef __MPI
175  int ierr;
176  ierr = MPI_Allreduce(MPI_IN_PLACE, &idim, 1,
177  MPI_LONG, MPI_MAX, MPI_COMM_WORLD);
178  if(ierr != 0) exitMPI(-1);
179 #endif
180  return(idim);
181 }/*long int MaxMPI_li*/
188 double MaxMPI_d(
189  double dvalue
190 ){
191 #ifdef __MPI
192  int ierr;
193  ierr = MPI_Allreduce(MPI_IN_PLACE, &dvalue, 1,
194  MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
195  if(ierr != 0) exitMPI(-1);
196 #endif
197  return(dvalue);
198 }/*double MaxMPI_d*/
205 std::complex<double> SumMPI_dc(
206  std::complex<double> norm
207 ){
208 #ifdef __MPI
209  int ierr;
210  ierr = MPI_Allreduce(MPI_IN_PLACE, &norm, 1,
211  MPI_DOUBLE_COMPLEX, MPI_SUM, MPI_COMM_WORLD);
212  if(ierr != 0) exitMPI(-1);
213 #endif
214  return(norm);
215 }/*std::complex<double> SumMPI_dc*/
222 double SumMPI_d(
223  double norm
224 ){
225 #ifdef __MPI
226  int ierr;
227  ierr = MPI_Allreduce(MPI_IN_PLACE, &norm, 1,
228  MPI_DOUBLE_PRECISION, MPI_SUM, MPI_COMM_WORLD);
229  if(ierr != 0) exitMPI(-1);
230 #endif
231  return(norm);
232 }/*double SumMPI_d*/
239  int nnorm,
240  double *norm
241 ) {
242 #ifdef __MPI
243  int ierr;
244  ierr = MPI_Allreduce(MPI_IN_PLACE, norm, nnorm,
245  MPI_DOUBLE_PRECISION, MPI_SUM, MPI_COMM_WORLD);
246  if (ierr != 0) exitMPI(-1);
247 #endif
248 }/*void SumMPI_dv*/
255  int nnorm,
256  std::complex<double> *norm
257 ) {
258 #ifdef __MPI
259  int ierr;
260  ierr = MPI_Allreduce(MPI_IN_PLACE, norm, nnorm,
261  MPI_DOUBLE_COMPLEX, MPI_SUM, MPI_COMM_WORLD);
262  if (ierr != 0) exitMPI(-1);
263 #endif
264 }/*void SumMPI_cv*/
271 long int SumMPI_li(
272  long int idim
273 ){
274 #ifdef __MPI
275  int ierr;
276  ierr = MPI_Allreduce(MPI_IN_PLACE, &idim, 1,
277  MPI_LONG, MPI_SUM, MPI_COMM_WORLD);
278  if(ierr != 0) exitMPI(-1);
279 #endif
280  return(idim);
281 }/*long int SumMPI_li*/
289  int idim
290 ) {
291 #ifdef __MPI
292  int ierr;
293  ierr = MPI_Allreduce(MPI_IN_PLACE, &idim, 1,
294  MPI_INT, MPI_SUM, MPI_COMM_WORLD);
295  if(ierr != 0) exitMPI(-1);
296 #endif
297  return(idim);
298 }/*int SumMPI_i*/
305 long int BcastMPI_li(
306  int root,
307  long int idim
308 ) {
309  long int idim0;
310  idim0 = idim;
311 #ifdef __MPI
312  MPI_Bcast(&idim0, 1, MPI_LONG, root, MPI_COMM_WORLD);
313 #endif
314  return(idim0);
315 }/*long int BcastMPI_li*/
321 double NormMPI_dc(
322  long int idim,
323  std::complex<double> *_v1
324 ){
325  double dnorm =0;
326  long int i;
327 
328  dnorm = 0.0;
329 #pragma omp parallel for default(none) private(i) \
330 shared(_v1, idim) reduction(+:dnorm)
331  for (i = 1; i <= idim; i++)
332  dnorm += real(conj(_v1[i])*_v1[i]);
333 
334 #ifdef __MPI
335  dnorm = SumMPI_d(dnorm);
336 #endif
337  return dnorm;
338 }/*double NormMPI_dc*/
345  long int ndim,
346  int nstate,
347  std::complex<double> **_v1,
348  double *dnorm
349 ) {
350  long int idim;
351  int istate;
352 
353  for (istate = 0; istate < nstate; istate++) dnorm[istate] = 0.0;
354  for (idim = 1; idim <= ndim; idim++) {
355  for (istate = 0; istate < nstate; istate++) {
356  dnorm[istate] += real(conj(_v1[idim][istate])*_v1[idim][istate]);
357  }
358  }
359  SumMPI_dv(nstate, dnorm);
360  for (istate = 0; istate < nstate; istate++) dnorm[istate] = sqrt(dnorm[istate]);
361 }/*double NormMPI_cv*/
367 std::complex<double> VecProdMPI(
368  long int ndim,
369  std::complex<double> *v1,
370  std::complex<double> *v2
371 ){
372  long int idim;
373  std::complex<double> prod, *prod_thr;
374  int mythread;
375 
376  prod_thr = cd_1d_allocate(nthreads);
377 #pragma omp parallel default(none) shared(v1,v2,ndim,prod,prod_thr) private(idim,mythread)
378  {
379 #ifdef _OPENMP
380  mythread = omp_get_thread_num();
381 #else
382  mythread = 0;
383 #endif
384 #pragma omp for
385  for (idim = 1; idim <= ndim; idim++)
386  prod_thr[mythread] += conj(v1[idim]) * v2[idim];
387  }
388  prod = 0.0;
389  for (mythread = 0; mythread < nthreads; mythread++)
390  prod += prod_thr[mythread];
391  free_cd_1d_allocate(prod_thr);
392 
393  prod = SumMPI_dc(prod);
394 
395  return(prod);
396 }/*std::complex<double> VecProdMPI*/
402  long int ndim,
403  int nstate,
404  std::complex<double> **v1,
405  std::complex<double> **v2,
406  std::complex<double> *prod
407 ) {
408  long int idim;
409  int istate;
410 
411  for (istate = 0; istate < nstate; istate++) prod[istate] = 0.0;
412  for (idim = 1; idim <= ndim; idim++) {
413  for (istate = 0; istate < nstate; istate++) {
414  prod[istate] += conj(v1[idim][istate])*v2[idim][istate];
415  }
416  }
417  SumMPI_cv(nstate, prod);
418 }/*void MultiVecProdMPI*/
425  int origin,
426  long int nMsgS,
427  long int nMsgR,
428  std::complex<double> *vecs,
429  std::complex<double> *vecr
430 ) {
431 #ifdef __MPI
432  int ierr, two31m1 = 2147483647, modMsg, nMsgS2, nMsgR2;
433  long int nMsg, nnMsg, iMsg, sMsgR, sMsgS;
434  MPI_Status statusMPI;
435 
436  if (nMsgS > nMsgR) nMsg = nMsgS;
437  else nMsg = nMsgR;
438  nnMsg = nMsg / two31m1;
439  modMsg = nMsg % two31m1;
440  if (modMsg != 0) nnMsg += 1;
441 
442  sMsgS = 0;
443  sMsgR = 0;
444  for (iMsg = 0; iMsg < nnMsg; iMsg++) {
445  nMsgS2 = nMsgS / nnMsg;
446  nMsgR2 = nMsgR / nnMsg;
447  if (iMsg < nMsgS % nnMsg) nMsgS2 += 1;
448  if (iMsg < nMsgR % nnMsg) nMsgR2 += 1;
449 
450  ierr = MPI_Sendrecv(&vecs[sMsgS], nMsgS2, MPI_DOUBLE_COMPLEX, origin, 0,
451  &vecr[sMsgR], nMsgR2, MPI_DOUBLE_COMPLEX, origin, 0,
452  MPI_COMM_WORLD, &statusMPI);
453  if (ierr != 0) exitMPI(-1);
454 
455  sMsgS += nMsgS2;
456  sMsgR += nMsgR2;
457  }
458 #endif
459 }/*void SendRecv_cv*/
466  int origin,
467  long int nMsgS,
468  long int nMsgR,
469  long int *vecs,
470  long int *vecr
471 ) {
472 #ifdef __MPI
473  int ierr, two31m1 = 2147483647, modMsg, nMsgS2, nMsgR2;
474  long int nMsg, nnMsg, iMsg, sMsgR, sMsgS;
475  MPI_Status statusMPI;
476 
477  if (nMsgS > nMsgR) nMsg = nMsgS;
478  else nMsg = nMsgR;
479  nnMsg = nMsg / two31m1;
480  modMsg = nMsg % two31m1;
481  if (modMsg != 0) nnMsg += 1;
482 
483  sMsgS = 0;
484  sMsgR = 0;
485  for (iMsg = 0; iMsg < nnMsg; iMsg++) {
486  nMsgS2 = nMsgS / nnMsg;
487  nMsgR2 = nMsgR / nnMsg;
488  if (iMsg < nMsgS % nnMsg) nMsgS2 += 1;
489  if (iMsg < nMsgR % nnMsg) nMsgR2 += 1;
490 
491  ierr = MPI_Sendrecv(&vecs[sMsgS], nMsgS2, MPI_LONG, origin, 0,
492  &vecr[sMsgR], nMsgR2, MPI_LONG, origin, 0,
493  MPI_COMM_WORLD, &statusMPI);
494  if (ierr != 0) exitMPI(-1);
495 
496  sMsgS += nMsgS2;
497  sMsgR += nMsgR2;
498  }
499 #endif
500 }/*void SendRecv_iv*/
504 long int SendRecv_i(
505  int origin,
506  long int isend
507 ) {
508 #ifdef __MPI
509  int ierr;
510  MPI_Status statusMPI;
511  long int ircv;
512  ierr = MPI_Sendrecv(&isend, 1, MPI_LONG, origin, 0,
513  &ircv, 1, MPI_LONG, origin, 0,
514  MPI_COMM_WORLD, &statusMPI);
515  if (ierr != 0) exitMPI(ierr);
516  return ircv;
517 #else
518  return isend;
519 #endif
520 }/*void SendRecv_i*/
void exitMPI(int errorcode)
MPI Abortation wrapper.
Definition: wrapperMPI.cpp:86
int nproc
Number of processors, defined in InitializeMPI()
Definition: global.cpp:72
FILE * stdoutMPI
File pointer to the standard output defined in InitializeMPI()
Definition: global.cpp:75
double NormMPI_dc(long int idim, std::complex< double > *_v1)
Compute norm of process-distributed vector .
Definition: wrapperMPI.cpp:321
void FinalizeMPI()
MPI Finitialization wrapper.
Definition: wrapperMPI.cpp:74
void splash()
Print logo mark and version number.
Definition: splash.cpp:25
long int SumMPI_li(long int idim)
MPI wrapper function to obtain sum of unsigned long integer across processes.
Definition: wrapperMPI.cpp:271
FILE * fopenMPI(const char *FileName, const char *mode)
MPI file I/O (open) wrapper. Only the root node (myrank = 0) should be open/read/write (small) parame...
Definition: wrapperMPI.cpp:105
double MaxMPI_d(double dvalue)
MPI wrapper function to obtain maximum Double across processes.
Definition: wrapperMPI.cpp:188
long int MaxMPI_li(long int idim)
MPI wrapper function to obtain maximum unsigned long integer across processes.
Definition: wrapperMPI.cpp:171
void NormMPI_dv(long int ndim, int nstate, std::complex< double > **_v1, double *dnorm)
Compute norm of process-distributed vector .
Definition: wrapperMPI.cpp:344
std::complex< double > ** v1
Definition: global.cpp:21
void SumMPI_cv(int nnorm, std::complex< double > *norm)
MPI wrapper function to obtain sum of Double array across processes.
Definition: wrapperMPI.cpp:254
long int SendRecv_i(int origin, long int isend)
Wrapper of MPI_Sendrecv for long integer number.
Definition: wrapperMPI.cpp:504
void BarrierMPI()
MPI barrier wrapper.
Definition: wrapperMPI.cpp:160
std::complex< double > VecProdMPI(long int ndim, std::complex< double > *v1, std::complex< double > *v2)
Compute conjugate scaler product of process-distributed vector .
Definition: wrapperMPI.cpp:367
int nthreads
Number of Threads, defined in InitializeMPI()
Definition: global.cpp:74
void InitializeMPI(int argc, char *argv[])
MPI initialization wrapper Process ID (myrank), Number of processes (nproc), Number of threads (nthre...
Definition: wrapperMPI.cpp:44
int SumMPI_i(int idim)
MPI wrapper function to obtain sum of integer across processes.
Definition: wrapperMPI.cpp:288
char * fgetsMPI(char *InputString, int maxcount, FILE *fp)
MPI file I/O (get a line, fgets) wrapper. Only the root node (myrank = 0) reads and broadcast string...
Definition: wrapperMPI.cpp:122
int myrank
Process ID, defined in InitializeMPI()
Definition: global.cpp:73
void SendRecv_cv(int origin, long int nMsgS, long int nMsgR, std::complex< double > *vecs, std::complex< double > *vecr)
Wrapper of MPI_Sendrecv for std::complex<double> number. When we pass a message longer than 2^31-1 (m...
Definition: wrapperMPI.cpp:424
void SumMPI_dv(int nnorm, double *norm)
MPI wrapper function to obtain sum of Double array across processes.
Definition: wrapperMPI.cpp:238
void MultiVecProdMPI(long int ndim, int nstate, std::complex< double > **v1, std::complex< double > **v2, std::complex< double > *prod)
Compute conjugate scaler product of process-distributed vector .
Definition: wrapperMPI.cpp:401
double SumMPI_d(double norm)
MPI wrapper function to obtain sum of Double across processes.
Definition: wrapperMPI.cpp:222
long int BcastMPI_li(int root, long int idim)
MPI wrapper function to broadcast long integer across processes.
Definition: wrapperMPI.cpp:305
void SendRecv_iv(int origin, long int nMsgS, long int nMsgR, long int *vecs, long int *vecr)
Wrapper of MPI_Sendrecv for long integer number. When we pass a message longer than 2^31-1 (max of in...
Definition: wrapperMPI.cpp:465
std::complex< double > SumMPI_dc(std::complex< double > norm)
MPI wrapper function to obtain sum of Double complex across processes.
Definition: wrapperMPI.cpp:205