/** * @brief A main function to calculate spectrum by Lanczos * * @param[in,out] X CalcStruct list for getting and pushing calculation information * @retval 0 normally finished * @retval -1 unnormally finished * * @version 1.1 * @author Kazuyoshi Yoshimi (The University of Tokyo) * */ int CalcSpectrumByLanczos( struct EDMainCalStruct *X, double complex *tmp_v1, double dnorm, int Nomega, double complex *dcSpectrum, double complex *dcomega ) { char sdt[D_FileNameMax]; unsigned long int i, i_max; FILE *fp; int iret; unsigned long int liLanczosStp = X->Bind.Def.Lanczos_max; unsigned long int liLanczosStp_vec=0; if(X->Bind.Def.iFlgCalcSpec == RECALC_FROM_TMComponents_VEC || X->Bind.Def.iFlgCalcSpec == RECALC_INOUT_TMComponents_VEC) { fprintf(stdoutMPI, " Start: Input vectors for recalculation.\n"); TimeKeeper(&(X->Bind), cFileNameTimeKeep, c_InputSpectrumRecalcvecStart, "a"); StartTimer(6201); sprintf(sdt, cFileNameOutputRestartVec, X->Bind.Def.CDataFileHead, myrank); if (childfopenALL(sdt, "rb", &fp) != 0) { exitMPI(-1); } fread(&liLanczosStp_vec, sizeof(liLanczosStp_vec),1,fp); fread(&i_max, sizeof(long int), 1, fp); if(i_max != X->Bind.Check.idim_max){ fprintf(stderr, "Error: A size of Inputvector is incorrect.\n"); exitMPI(-1); } fread(v0, sizeof(complex double), X->Bind.Check.idim_max + 1, fp); fread(v1, sizeof(complex double), X->Bind.Check.idim_max + 1, fp); fclose(fp); StopTimer(6201); fprintf(stdoutMPI, " End: Input vectors for recalculation.\n"); TimeKeeper(&(X->Bind), cFileNameTimeKeep, c_InputSpectrumRecalcvecEnd, "a"); } //Read diagonal components if(X->Bind.Def.iFlgCalcSpec == RECALC_FROM_TMComponents || X->Bind.Def.iFlgCalcSpec ==RECALC_FROM_TMComponents_VEC|| X->Bind.Def.iFlgCalcSpec == RECALC_INOUT_TMComponents_VEC) { StartTimer(6202); iret=ReadTMComponents(X, &dnorm, &liLanczosStp); if(!iret ==TRUE){ fprintf(stdoutMPI, " Error: Fail to read TMcomponents\n"); return FALSE; } if(X->Bind.Def.iFlgCalcSpec == RECALC_FROM_TMComponents){ X->Bind.Def.Lanczos_restart=0; } else if(X->Bind.Def.iFlgCalcSpec == RECALC_INOUT_TMComponents_VEC|| X->Bind.Def.iFlgCalcSpec == RECALC_FROM_TMComponents_VEC){ if(liLanczosStp_vec !=liLanczosStp){ fprintf(stdoutMPI, " Error: Input files for vector and TMcomponents are incoorect.\n"); fprintf(stdoutMPI, " Error: Input vector %ld th stps, TMcomponents %ld th stps.\n", liLanczosStp_vec, liLanczosStp); return FALSE; } X->Bind.Def.Lanczos_restart=liLanczosStp; liLanczosStp = liLanczosStp+X->Bind.Def.Lanczos_max; } StopTimer(6202); } // calculate ai, bi if (X->Bind.Def.iFlgCalcSpec == RECALC_NOT || X->Bind.Def.iFlgCalcSpec == RECALC_OUTPUT_TMComponents_VEC || X->Bind.Def.iFlgCalcSpec == RECALC_FROM_TMComponents_VEC || X->Bind.Def.iFlgCalcSpec == RECALC_INOUT_TMComponents_VEC ) { fprintf(stdoutMPI, " Start: Calculate tridiagonal matrix components.\n"); TimeKeeper(&(X->Bind), cFileNameTimeKeep, c_GetTridiagonalStart, "a"); // Functions in Lanczos_EigenValue StartTimer(6203); iret = Lanczos_GetTridiagonalMatrixComponents(&(X->Bind), alpha, beta, tmp_v1, &(liLanczosStp)); StopTimer(6203); if (iret != TRUE) { //Error Message will be added. return FALSE; } fprintf(stdoutMPI, " End: Calculate tridiagonal matrix components.\n\n"); TimeKeeper(&(X->Bind), cFileNameTimeKeep, c_GetTridiagonalEnd, "a"); StartTimer(6204); OutputTMComponents(X, alpha,beta, dnorm, liLanczosStp); StopTimer(6204); }//X->Bind.Def.iFlgCalcSpec == RECALC_NOT || RECALC_FROM_TMComponents_VEC fprintf(stdoutMPI, " Start: Caclulate spectrum from tridiagonal matrix components.\n"); TimeKeeper(&(X->Bind), cFileNameTimeKeep, c_CalcSpectrumFromTridiagonalStart, "a"); StartTimer(6205); for( i = 0 ; i < Nomega; i++) { iret = GetSpectrumByTridiagonalMatrixComponents(alpha, beta, dnorm, dcomega[i], &dcSpectrum[i], liLanczosStp); if (iret != TRUE) { //ToDo: Error Message will be added. //ReAlloc alpha, beta and Set alpha_start and beta_start in Lanczos_EigenValue return FALSE; } dcSpectrum[i] = dnorm * dcSpectrum[i]; } StopTimer(6205); fprintf(stdoutMPI, " End: Caclulate spectrum from tridiagonal matrix components.\n\n"); TimeKeeper(&(X->Bind), cFileNameTimeKeep, c_CalcSpectrumFromTridiagonalEnd, "a"); //output vectors for recalculation if(X->Bind.Def.iFlgCalcSpec==RECALC_OUTPUT_TMComponents_VEC || X->Bind.Def.iFlgCalcSpec==RECALC_INOUT_TMComponents_VEC){ StartTimer(6206); fprintf(stdoutMPI, " Start: Output vectors for recalculation.\n"); TimeKeeper(&(X->Bind), cFileNameTimeKeep, c_OutputSpectrumRecalcvecStart, "a"); sprintf(sdt, cFileNameOutputRestartVec, X->Bind.Def.CDataFileHead, myrank); if(childfopenALL(sdt, "wb", &fp)!=0){ exitMPI(-1); } fwrite(&liLanczosStp, sizeof(liLanczosStp),1,fp); fwrite(&X->Bind.Check.idim_max, sizeof(X->Bind.Check.idim_max),1,fp); fwrite(v0, sizeof(complex double),X->Bind.Check.idim_max+1, fp); fwrite(v1, sizeof(complex double),X->Bind.Check.idim_max+1, fp); fclose(fp); fprintf(stdoutMPI, " End: Output vectors for recalculation.\n"); TimeKeeper(&(X->Bind), cFileNameTimeKeep, c_OutputSpectrumRecalcvecEnd, "a"); StopTimer(6206); } return TRUE; }
/** * @brief A main function to calculate eigenvalues and eigenvectors by Lanczos method * * @param[in,out] X CalcStruct list for getting and pushing calculation information * @retval 0 normally finished * @retval -1 unnormally finished * * @version 0.2 * @date 2015/10/20 add function of using a flag of iCalcEigenVec * @version 0.1 * @author Takahiro Misawa (The University of Tokyo) * @author Kazuyoshi Yoshimi (The University of Tokyo) * */ int CalcByLanczos( struct EDMainCalStruct *X ) { char sdt[D_FileNameMax]; double diff_ene,var; long int i; long int i_max=0; FILE *fp; if(X->Bind.Def.iInputEigenVec==FALSE){ // this part will be modified switch(X->Bind.Def.iCalcModel){ case HubbardGC: case SpinGC: case KondoGC: case SpinlessFermionGC: initial_mode = 1; // 1 -> random initial vector break; case Hubbard: case Kondo: case Spin: case SpinlessFermion: if(X->Bind.Def.iFlgGeneralSpin ==TRUE){ initial_mode=1; } else{ if(X->Bind.Def.initial_iv>0){ initial_mode = 0; // 0 -> only v[iv] = 1 }else{ initial_mode = 1; // 1 -> random initial vector } } break; default: //fclose(fp); exitMPI(-1); } if(Lanczos_EigenValue(&(X->Bind))!=0){ fprintf(stderr, " Lanczos Eigenvalue is not converged in this process.\n"); return(FALSE); } if(X->Bind.Def.iCalcEigenVec==CALCVEC_NOT){ fprintf(stdoutMPI, " Lanczos EigenValue = %.10lf \n ",X->Bind.Phys.Target_energy); return(TRUE); } fprintf(stdoutMPI, cLogLanczos_EigenVecStart); // printf("debug: X->Bind.Check.idim_maxMPI=%d\n", X->Bind.Check.idim_maxMPI); if(X->Bind.Check.idim_maxMPI != 1){ Lanczos_EigenVector(&(X->Bind)); expec_energy(&(X->Bind)); //check for the accuracy of the eigenvector var = fabs(X->Bind.Phys.var-X->Bind.Phys.energy*X->Bind.Phys.energy)/fabs(X->Bind.Phys.var); diff_ene = fabs(X->Bind.Phys.Target_energy-X->Bind.Phys.energy)/fabs(X->Bind.Phys.Target_energy); fprintf(stdoutMPI, "\n"); fprintf(stdoutMPI, " Accuracy check !!!\n"); fprintf(stdoutMPI, " LanczosEnergy = %.14e \n EnergyByVec = %.14e \n diff_ene = %.14e \n var = %.14e \n",X->Bind.Phys.Target_energy,X->Bind.Phys.energy,diff_ene,var); if(diff_ene < eps_Energy && var< eps_Energy){ fprintf(stdoutMPI, " Accuracy of Lanczos vectors is enough.\n"); fprintf(stdoutMPI, "\n"); } /* else{ Comment out: Power Lanczos method fprintf(stdoutMPI, " Accuracy of Lanczos vectors is NOT enough\n"); iconv=1; fprintf(stdoutMPI, "Eigenvector is improved by power Lanczos method \n"); fprintf(stdoutMPI, "Power Lanczos starts\n"); flag=PowerLanczos(&(X->Bind)); fprintf(stdoutMPI, "Power Lanczos ends\n"); if(flag==1){ var = fabs(X->Bind.Phys.var-X->Bind.Phys.energy*X->Bind.Phys.energy)/fabs(X->Bind.Phys.var); diff_ene = fabs(X->Bind.Phys.Target_energy-X->Bind.Phys.energy)/fabs(X->Bind.Phys.Target_energy); fprintf(stdoutMPI,"\n"); fprintf(stdoutMPI,"Power Lanczos Accuracy check !!!\n"); fprintf(stdoutMPI,"%.14e %.14e: diff_ene=%.14e var=%.14e \n ",X->Bind.Phys.Target_energy,X->Bind.Phys.energy,diff_ene,var); fprintf(stdoutMPI,"\n"); } else if(X->Bind.Def.iCalcEigenVec==CALCVEC_LANCZOSCG && iconv==1){ */ else if(X->Bind.Def.iCalcEigenVec==CALCVEC_LANCZOSCG){ fprintf(stdoutMPI, " Accuracy of Lanczos vectors is NOT enough\n\n"); X->Bind.Def.St=1; CG_EigenVector(&(X->Bind)); expec_energy(&(X->Bind)); var = fabs(X->Bind.Phys.var-X->Bind.Phys.energy*X->Bind.Phys.energy)/fabs(X->Bind.Phys.var); diff_ene = fabs(X->Bind.Phys.Target_energy-X->Bind.Phys.energy)/fabs(X->Bind.Phys.Target_energy); fprintf(stdoutMPI, "\n"); fprintf(stdoutMPI, " CG Accuracy check !!!\n"); fprintf(stdoutMPI, " LanczosEnergy = %.14e\n EnergyByVec = %.14e\n diff_ene = %.14e\n var = %.14e \n ",X->Bind.Phys.Target_energy,X->Bind.Phys.energy,diff_ene,var); fprintf(stdoutMPI, "\n"); //} } } else{//idim_max=1 v0[1]=1; expec_energy(&(X->Bind)); } } else{// X->Bind.Def.iInputEigenVec=false :input v1: fprintf(stdoutMPI, "An Eigenvector is inputted.\n"); sprintf(sdt, cFileNameInputEigen, X->Bind.Def.CDataFileHead, X->Bind.Def.k_exct-1, myrank); childfopenALL(sdt, "rb", &fp); if(fp==NULL){ fprintf(stderr, "Error: A file of Inputvector does not exist.\n"); exitMPI(-1); } fread(&i_max, sizeof(long int), 1, fp); if(i_max != X->Bind.Check.idim_max){ fprintf(stderr, "Error: A file of Inputvector is incorrect.\n"); exitMPI(-1); } fread(v1, sizeof(complex double),X->Bind.Check.idim_max+1, fp); fclose(fp); } fprintf(stdoutMPI, cLogLanczos_EigenVecEnd); // v1 is eigen vector if(!expec_cisajs(&(X->Bind), v1)==0){ fprintf(stderr, "Error: calc OneBodyG.\n"); exitMPI(-1); } if(!expec_cisajscktaltdc(&(X->Bind), v1)==0){ fprintf(stderr, "Error: calc TwoBodyG.\n"); exitMPI(-1); } /* For ver.1.0 if(!expec_totalspin(&(X->Bind), v1)==0){ fprintf(stderr, "Error: calc TotalSpin.\n"); exitMPI(-1); } */ if(!expec_totalSz(&(X->Bind), v1)==0){ fprintf(stderr, "Error: calc TotalSz.\n"); exitMPI(-1); } if(X->Bind.Def.St==0){ sprintf(sdt, cFileNameEnergy_Lanczos, X->Bind.Def.CDataFileHead); }else if(X->Bind.Def.St==1){ sprintf(sdt, cFileNameEnergy_CG, X->Bind.Def.CDataFileHead); } if(childfopenMPI(sdt, "w", &fp)!=0){ exitMPI(-1); } fprintf(fp,"Energy %.16lf \n",X->Bind.Phys.energy); fprintf(fp,"Doublon %.16lf \n",X->Bind.Phys.doublon); fprintf(fp,"Sz %.16lf \n",X->Bind.Phys.sz); // fprintf(fp,"total S^2 %.10lf \n",X->Bind.Phys.s2); fclose(fp); if(X->Bind.Def.iOutputEigenVec==TRUE){ sprintf(sdt, cFileNameOutputEigen, X->Bind.Def.CDataFileHead, X->Bind.Def.k_exct-1, myrank); if(childfopenALL(sdt, "wb", &fp)!=0){ exitMPI(-1); } fwrite(&X->Bind.Check.idim_max, sizeof(X->Bind.Check.idim_max),1,fp); fwrite(v1, sizeof(complex double),X->Bind.Check.idim_max+1, fp); fclose(fp); } return TRUE; }