HΦ  3.2.0
PowerLanczos.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/>. */
16 #include "PowerLanczos.h"
17 #include "mltply.h"
18 #include "wrapperMPI.h"
19 
20 int PowerLanczos(struct BindStruct *X){
21 
22  long int i,j;
23 
24  double dnorm, dnorm_inv;
25  double complex dam_pr1,dam_pr2a,dam_pr2b,dam_pr3,dam_pr4;
26  double E1,E2a,E2b,E3,E4;
27  double alpha_p,alpha_m;
28  double Lz_Var;
29  double Lz_Ene_p,Lz_Ene_m;
30  double Lz_Var_p,Lz_Var_m;
31  long int i_max,i_Lz;
32 
33  i_max=X->Check.idim_max;
34 
35 // v1 is eigenvector
36 // v0 = H*v1
37 // this subroutine
38  for(i_Lz=0;i_Lz<50;i_Lz++){
39  //v1 -> eigen_vec
40  //v0 -> v0=H*v1
41 // if(i_Lz>1){
42  #pragma omp parallel for default(none) private(i) shared(v0) firstprivate(i_max)
43  for(i = 1; i <= i_max; i++){
44  v0[i]=0.0+0.0*I;
45  }
46  mltply(X, v0, v1); // v0+=H*v1
47 
48  dam_pr1=0.0;
49  dam_pr2a=0.0;
50  #pragma omp parallel for default(none) reduction(+:dam_pr1,dam_pr2a) private(j) shared(v0, v1)firstprivate(i_max)
51  for(j=1;j<=i_max;j++){
52  dam_pr1 += conj(v1[j])*v0[j]; // E = <v1|H|v1>=<v1|v0>
53  dam_pr2a += conj(v0[j])*v0[j]; // E^2 = <v1|H*H|v1>=<v0|v0>
54  //v0[j]=v1[j]; v1-> orginal v0=H*v1
55  }
56  dam_pr1 = SumMPI_dc(dam_pr1);
57  dam_pr2a = SumMPI_dc(dam_pr2a);
58  E1 = creal(dam_pr1); // E
59  E2a = creal(dam_pr2a);// E^2
60 
61  #pragma omp parallel for default(none) private(i) shared(vg) firstprivate(i_max)
62  for(i = 1; i <= i_max; i++){
63  vg[i]=0.0;
64  }
65 
66  mltply(X, vg, v0); // vg=H*v0=H*H*v1
67  dam_pr2b = 0.0;
68  dam_pr3 = 0.0;
69  dam_pr4 = 0.0;
70  #pragma omp parallel for default(none) reduction(+:dam_pr2b,dam_pr3, dam_pr4) private(j) shared(v0,v1, vg)firstprivate(i_max)
71  for(j=1;j<=i_max;j++){
72  dam_pr2b += conj(vg[j])*v1[j]; // E^2 = <v1|H^2|v1>=<vg|v1>
73  dam_pr3 += conj(vg[j])*v0[j]; // E^3 = <v1|H^3|v1>=<vg|v0>
74  dam_pr4 += conj(vg[j])*vg[j]; // E^4 = <v1|H^4|v1>=<vg|vg>
75  }
76  dam_pr2b = SumMPI_dc(dam_pr2b);
77  dam_pr3 = SumMPI_dc(dam_pr3);
78  dam_pr4 = SumMPI_dc(dam_pr4);
79  //E1 = X->Phys.energy;// E^1
80  //E2a = X->Phys.var ;// E^2 = <v1|H*H|v1>
81  E2b = creal(dam_pr2b) ;// E^2 = (<v1|H^2)|v1>
82  E3 = creal(dam_pr3) ;// E^3
83  E4 = creal(dam_pr4) ;// E^4
84 
85  if(solve_2ndPolinomial(X,&alpha_p,&alpha_m,E1,E2a,E2b,E3,E4)!=TRUE){
86  fprintf(stdoutMPI,"Power Lanczos break \n");
87  return 0;
88  }
89  //printf("E1=%.16lf E2a=%.16lf E2b=%.16lf E3=%.16lf E4=%.16lf \n",E1,E2a,E2b,E3,E4);
90 
91  Lz(X,alpha_p,&Lz_Ene_p,&Lz_Var_p,E1,E2a,E3,E4);
92  Lz(X,alpha_m,&Lz_Ene_m,&Lz_Var_m,E1,E2a,E3,E4);
93 
94  if(Lz_Ene_p < Lz_Ene_m){
95  Lz_Var=Lz_Var_p;
96  fprintf(stdoutMPI,"Power Lanczos (P): %.16lf %.16lf \n",Lz_Ene_p,Lz_Var_p);
97  #pragma omp parallel for default(none) private(j) shared(v0, v1) firstprivate(i_max,alpha_p)
98  for(j=1;j<=i_max;j++){
99  v1[j] = v1[j]+alpha_p*v0[j]; // (1+alpha*H)v1=v1+alpha*v0
100  }
101  }else{
102  Lz_Var=Lz_Var_m;
103  fprintf(stdoutMPI,"Power Lanczos (M): %.16lf %.16lf \n",Lz_Ene_m,Lz_Var_m);
104  #pragma omp parallel for default(none) private(j) shared(v0, v1)firstprivate(i_max,alpha_m)
105  for(j=1;j<=i_max;j++){
106  v1[j] = v1[j]+alpha_m*v0[j]; // (1+alpha*H)v1=v1+alpha*v0
107  }
108  }
109  //normalization
110  dnorm=0.0;
111  #pragma omp parallel for default(none) reduction(+:dnorm) private(j) shared(v1) firstprivate(i_max)
112  for(j=1;j<=i_max;j++){
113  dnorm += conj(v1[j])*v1[j];
114  }
115  dnorm = SumMPI_d(dnorm);
116  dnorm=sqrt(dnorm);
117  dnorm_inv=1.0/dnorm;
118 #pragma omp parallel for default(none) private(j) shared(v1) firstprivate(i_max, dnorm_inv)
119  for(j=1;j<=i_max;j++){
120  v1[j] = v1[j]*dnorm_inv;
121  }
122  if(Lz_Var < eps_Energy){
123  fprintf(stdoutMPI,"Power Lanczos break \n");
124  return 1;
125  //break;
126  }
127  }
128  return 0;
129 }
130 
131 int solve_2ndPolinomial(struct BindStruct *X,double *alpha_p,double *alpha_m,double E1,double E2a,double E2b,double E3,double E4){
132  double a,b,c,d;
133  double tmp_AA,tmp_BB,tmp_CC;
134 
135  //not solving 2nd Polinomial
136  //approximate linear equation is solved
137 
138 
139  a = E1;
140  b = E2a;
141  c = E2a;
142  d = E3;
143 
144  tmp_AA = b*(b+c)-2*a*d;
145  tmp_BB = -a*b+d;
146  tmp_CC = b*((b+c)*(b+c))-(a*a)*b*(b+2*c)+4*(a*a*a)*d-2*a*(2*b+c)*d+d*d;
147  if(tmp_AA< pow(b, 2)*pow(10.0, -15)){
148  return FALSE;
149  }
150  //printf("XXX: %.16lf %.16lf %.16lf %.16lf \n",a, b, c, d);
151  //printf("XXX: %.16lf %.16lf %.16lf \n",tmp_AA,tmp_BB,tmp_CC);
152  if(tmp_CC>=0){
153  *alpha_p = (tmp_BB+sqrt((tmp_CC)))/tmp_AA;
154  *alpha_m = (tmp_BB-sqrt((tmp_CC)))/tmp_AA;
155  //printf("YYY: %.16lf %.16lf \n",*alpha_p,*alpha_m);
156  }
157  else{
158  //*alpha_m = -E2a/E3*(1-E1*E1/E2a)/(1-E1*E2a/E3);
159  //*alpha_p = 0.0;
160  //*alpha_m = -E3/E4*(1+2*E1*E1*E1/E3-3*E1*E2a/E3)/(1-5*E2a*E2a/E4+4*E1*E1*E2a/E4);
161  *alpha_p = cabs((tmp_BB+csqrt((tmp_CC))))/tmp_AA;
162  *alpha_m = cabs((tmp_BB-csqrt((tmp_CC))))/tmp_AA;
163  }
164  return TRUE;
165 }
166 
167 void Lz(struct BindStruct *X,double alpha,double *Lz_Ene,double *Lz_Var,double E1,double E2,double E3,double E4){
168 
169  double tmp_ene,tmp_var;
170 
171  tmp_ene = (E1+2*alpha*E2+alpha*alpha*E3)/(1+2*alpha*E1+alpha*alpha*E2);
172  *Lz_Ene = tmp_ene;
173  X->Phys.energy = tmp_ene;
174  tmp_var = (E2+2*alpha*E3+alpha*alpha*E4)/(1+2*alpha*E1+alpha*alpha*E2);
175  X->Phys.var = tmp_var;
176  *Lz_Var = fabs(tmp_var-tmp_ene*tmp_ene)/tmp_var;
177 
178 }
179 
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
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
double complex * v1
Definition: global.h:35
double SumMPI_d(double norm)
MPI wrapper function to obtain sum of Double across processes.
Definition: wrapperMPI.c:222
struct PhysList Phys
Physical quantities.
Definition: struct.h:413
void Lz(struct BindStruct *X, double alpha, double *Lz_Ene, double *Lz_Var, double E1, double E2, double E3, double E4)
Definition: PowerLanczos.c:167
#define TRUE
Definition: global.h:26
Bind.
Definition: struct.h:409
double eps_Energy
Definition: global.h:156
int PowerLanczos(struct BindStruct *X)
Definition: PowerLanczos.c:20
double * alpha
Definition: global.h:44
double var
Expectation value of the Energy variance.
Definition: struct.h:363
#define FALSE
Definition: global.h:25
double complex * vg
Definition: global.h:41
struct EDMainCalStruct X
Definition: struct.h:432
int solve_2ndPolinomial(struct BindStruct *X, double *alpha_p, double *alpha_m, double E1, double E2a, double E2b, double E3, double E4)
Definition: PowerLanczos.c:131
double energy
Expectation value of the total energy.
Definition: struct.h:355
double complex * v0
Definition: global.h:34
struct CheckList Check
Size of the Hilbert space.
Definition: struct.h:411
FILE * stdoutMPI
File pointer to the standard output defined in InitializeMPI()
Definition: global.h:165