HΦ  3.2.0
CG_EigenVector.c
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/>. */
19 #include "CG_EigenVector.h"
20 #include "FileIO.h"
21 #include "mltply.h"
22 #include "wrapperMPI.h"
23 #include "CalcTime.h"
31 
32  fprintf(stdoutMPI, "%s", cLogCG_EigenVecStart);
34 
35  time_t start,mid;
36  FILE *fp_0;
37  char sdt_1[D_FileNameMax];
38  dsfmt_t dsfmt;
39  long unsigned int u_long_i;
40  int mythread;
41 
42  long int i,j;
43  double Eig;
44  int i_itr,itr,iv,itr_max;
45  int t_itr;
46  double bnorm,xnorm,rnorm,rnorm2;
47  double complex alpha,beta,xb,rp,yp,gosa1,tmp_r,gosa2;
48  double complex *y,*b;
49  long int L_size;
50  long int i_max;
51 
52  i_max=X->Check.idim_max;
53  Eig=X->Phys.Target_CG_energy;
54 
55  strcpy(sdt_1, cFileNameTimeEV_CG);
56  if(childfopenMPI(sdt_1, "w", &fp_0) !=0){
57  return -1;
58  }
59 
60  L_size=sizeof(double complex)*(i_max+1);
61 
62  b=(double complex *)malloc(L_size);
63  y=(double complex *)malloc(L_size);
64 
65  if(y==NULL){
66  fprintf(fp_0,"BAD in CG_EigenVector \n");
67  }else{
68  fprintf(fp_0,"allocate succeed !!! \n");
69  }
70  fclose(fp_0);
71 
72  start=time(NULL);
73  /*
74  add random components
75  */
76  iv = X->Def.initial_iv;
77  bnorm = 0.0;
78 #pragma omp parallel default(none) private(i, u_long_i, mythread, dsfmt) \
79  shared(v0, v1, iv, X, nthreads, myrank, b, bnorm) firstprivate(i_max)
80  {
81  /*
82  Initialise MT
83  */
84 #ifdef _OPENMP
85  mythread = omp_get_thread_num();
86 #else
87  mythread = 0;
88 #endif
89  u_long_i = 123432 + abs(iv) + mythread + nthreads * myrank;
90  dsfmt_init_gen_rand(&dsfmt, u_long_i);
91 
92 #pragma omp for
93  for (i = 1; i <= i_max; i++) {
94  v0[i] = v1[i];
95  b[i] = v0[i];
96  }
97 
98 #pragma omp for reduction(+:bnorm)
99  for (i = 1; i <= i_max; i++) {
100  b[i] += 2.0*(dsfmt_genrand_close_open(&dsfmt) - 0.5)*0.001;
101  bnorm += conj(b[i])*b[i];
102  }
103  }/*#pragma omp*/
104  /*
105  Normalize b
106  */
107  bnorm = SumMPI_d(bnorm);
108  bnorm=sqrt(bnorm);
109 
110 #pragma omp parallel for default(none) private(i) shared(b) firstprivate(i_max,bnorm)
111  for(i=1;i<=i_max;i++){
112  b[i]=b[i]/bnorm;
113  }
114 
115  t_itr=0;
116  for(i_itr=0;i_itr<=50;i_itr++){
117  //CG start!!
118  bnorm=0.0;
119  //initialization
120 #pragma omp parallel for reduction(+:bnorm) default(none) private(i) shared(b, v1, vg, v0) firstprivate(i_max)
121  for(i=1;i<=i_max;i++){
122  bnorm+=conj(b[i])*b[i];
123  v1[i]=b[i];
124  vg[i]=b[i];
125  v0[i]=0.0;
126  }
127  bnorm = SumMPI_d(bnorm);
128  if(iv >= 0){
129  childfopenMPI(sdt_1,"a",&fp_0);
130  fprintf(fp_0,"b[%d]=%lf bnorm== %lf \n ",iv,creal(b[iv]),bnorm);
131  fclose(fp_0);
132  }
133  //iteration
134  if(i_itr==0){
135  itr_max=500;
136  }else{
137  itr_max=500;
138  }
139 
140  for(itr=1;itr<=itr_max;itr++){
141 #pragma omp parallel for default(none) private(j) shared(y, vg) firstprivate(i_max, Eig,eps_CG)
142  for(j=1;j<=i_max;j++){
143  y[j]=(-Eig+eps_CG)*vg[j]; //y = -E*p
144  }
145  StartTimer(4401);
146  mltply(X,y,vg); // y += H*p
147  StopTimer(4401);
148  // (H-E)p=y finish!
149  rp=0.0;
150  yp=0.0;
151 #pragma omp parallel for reduction(+:rp, yp) default(none) private(i) shared(v1, vg, y) firstprivate(i_max)
152  for(i=1;i<=i_max;i++){
153  rp+=v1[i]*conj(v1[i]);
154  yp+=y[i]*conj(vg[i]);
155  }
156  rp = SumMPI_dc(rp);
157  yp = SumMPI_dc(yp);
158  alpha=rp/yp;
159  rnorm=0.0;
160 #pragma omp parallel for reduction(+:rnorm) default(none) private(i) shared(v0, v1, vg)firstprivate(i_max, alpha)
161  for(i=1;i<=i_max;i++){
162  v0[i]+=alpha*vg[i];
163  rnorm+=conj(v1[i])*v1[i];
164  }
165  rnorm = SumMPI_d(rnorm);
166  rnorm2=0.0;
167  gosa1=0.0;
168 #pragma omp parallel for reduction(+:rnorm2, gosa1) default(none) private(i) shared(v1 , y) firstprivate(i_max, alpha) private(tmp_r)
169  for(i=1;i<=i_max;i++){
170  tmp_r=v1[i]-alpha*y[i];
171  gosa1+=conj(tmp_r)*v1[i];// old r and new r should be orthogonal -> gosa1=0
172  v1[i]=tmp_r;
173  rnorm2+=conj(v1[i])*v1[i];
174  }
175  gosa1 = SumMPI_dc(gosa1);
176  rnorm2 = SumMPI_d(rnorm2);
177 
178  gosa2=0.0;
179 #pragma omp parallel for reduction(+:gosa2) default(none) private(i) shared(v1, vg) firstprivate(i_max)
180  for(i=1;i<=i_max;i++){
181  gosa2+=v1[i]*conj(vg[i]); // new r and old p should be orthogonal
182  }
183  gosa2 = SumMPI_dc(gosa2);
184 
185  beta=rnorm2/rnorm;
186 #pragma omp parallel for default(none) shared(v1, vg) firstprivate(i_max, beta)
187  for(i=1;i<=i_max;i++){
188  vg[i]=v1[i]+beta*vg[i];
189  }
190  // if(itr%5==0){
191  childfopenMPI(sdt_1,"a", &fp_0);
192  fprintf(fp_0,"i_itr=%d itr=%d %.10lf %.10lf \n ",
193  i_itr,itr,sqrt(rnorm2),pow(10,-5)*sqrt(bnorm));
194  fclose(fp_0);
195  if(sqrt(rnorm2)<eps*sqrt(bnorm)){
196  t_itr+=itr;
197  childfopenMPI(sdt_1,"a", &fp_0);
198  fprintf(fp_0,"CG OK: t_itr=%d \n ",t_itr);
199  fclose(fp_0);
200  break;
201  }
202  //}
203  }
204  //CG finish!!
205  xnorm=0.0;
206 #pragma omp parallel for reduction(+:xnorm) default(none) private(i) shared(v0) firstprivate(i_max)
207  for(i=1;i<=i_max;i++){
208  xnorm+=conj(v0[i])*v0[i];
209  }
210  xnorm = SumMPI_d(xnorm);
211  xnorm=sqrt(xnorm);
212 
213 #pragma omp parallel for default(none) shared(v0) firstprivate(i_max, xnorm)
214  for(i=1;i<=i_max;i++){
215  v0[i]=v0[i]/xnorm;
216  }
217  xb=0.0;
218 
219 #pragma omp parallel for default(none) reduction(+:xb) private(i) shared(v0, b) firstprivate(i_max)
220  for(i=1;i<=i_max;i++){
221  xb+=conj(v0[i])*b[i];
222  }
223  xb = SumMPI_dc(xb);
224 
225  mid=time(NULL);
226 
227  childfopenMPI(sdt_1,"a", &fp_0);
228  fprintf(fp_0,"i_itr=%d itr=%d time=%lf fabs(fabs(xb)-1.0)=%.16lf\n"
229  ,i_itr,itr,difftime(mid,start),fabs(cabs(xb)-1.0));
230  fclose(fp_0);
231 
232  if(fabs(cabs(xb)-1.0)<eps){
233  childfopenMPI(sdt_1,"a", &fp_0);
234  fprintf(fp_0,"number of iterations in inv1:i_itr=%d itr=%d t_itr=%d %lf\n ",
235  i_itr,itr,t_itr,fabs(cabs(xb)-1.0));
236  fclose(fp_0);
237 
238  break;
239  }else{
240 #pragma omp parallel for default(none) private(i) shared(b, v0) firstprivate(i_max)
241  for(i=1;i<=i_max;i++){
242  b[i]=v0[i];
243  }
244  }
245  //inv1 routine finish!!
246  }
247 
248  free(b);
249  free(y);
250 
252  fprintf(stdoutMPI, "%s", cLogCG_EigenVecEnd);
253 
254  return 0;
255 }/*int CG_EigenVector*/
struct DefineList Def
Definision of system (Hamiltonian) etc.
Definition: struct.h:410
int mltply(struct BindStruct *X, double complex *tmp_v0, double complex *tmp_v1)
Parent function of multiplying the wavefunction by the Hamiltonian. . First, the calculation of diago...
Definition: mltply.c:56
void StartTimer(int n)
function for initializing elapse time [start]
Definition: time.c:71
double complex SumMPI_dc(double complex norm)
MPI wrapper function to obtain sum of Double complex across processes.
Definition: wrapperMPI.c:205
unsigned long int idim_max
The dimension of the Hilbert space of this process.
Definition: struct.h:303
const char * cLogCG_EigenVecEnd
Definition: LogMessage.c:51
double Target_CG_energy
Taget energy of CG-inversed iteration (NOT LOBCG) method.
Definition: struct.h:389
void StopTimer(int n)
function for calculating elapse time [elapse time=StartTimer-StopTimer]
Definition: time.c:83
double complex * v1
Definition: global.h:35
#define D_FileNameMax
Definition: global.h:23
double SumMPI_d(double norm)
MPI wrapper function to obtain sum of Double across processes.
Definition: wrapperMPI.c:222
int childfopenMPI(const char *_cPathChild, const char *_cmode, FILE **_fp)
Only the root process open file in output/ directory.
Definition: FileIO.c:27
struct PhysList Phys
Physical quantities.
Definition: struct.h:413
const char * cFileNameTimeEV_CG
Definition: global.c:47
int nthreads
Number of Threads, defined in InitializeMPI()
Definition: global.h:164
int CG_EigenVector(struct BindStruct *X)
inversed power method with CG
double eps_CG
Definition: global.h:154
Bind.
Definition: struct.h:409
double eps
Definition: global.h:153
double * alpha
Definition: global.h:44
const char * cFileNameTimeKeep
Definition: global.c:23
double complex * vg
Definition: global.h:41
const char * cCG_EigenVecStart
Definition: LogMessage.c:52
double * beta
Definition: global.h:44
struct EDMainCalStruct X
Definition: struct.h:432
long int initial_iv
Seed of random number for initial guesss of wavefunctions.
Definition: struct.h:76
const char * cCG_EigenVecFinish
Definition: LogMessage.c:53
int myrank
Process ID, defined in InitializeMPI()
Definition: global.h:163
const char * cLogCG_EigenVecStart
Definition: LogMessage.c:50
double complex * v0
Definition: global.h:34
struct CheckList Check
Size of the Hilbert space.
Definition: struct.h:411
int TimeKeeper(struct BindStruct *X, const char *cFileName, const char *cTimeKeeper_Message, const char *cWriteType)
Functions for writing a time log.
Definition: log.c:42
FILE * stdoutMPI
File pointer to the standard output defined in InitializeMPI()
Definition: global.h:165