void Q_over_sqrt_Q_sqr(spinor * const R, double * const c, const int n, spinor * const S, const double rnorm, const double minev) { int j; double fact1, fact2, temp1, temp2, temp3, temp4, maxev, tnorm; spinor *sv, *d, *dd, *aux, *aux3; double ap_eps_sq = 0.; sv=lock_Dov_WS_spinor(2); d=lock_Dov_WS_spinor(3); dd=lock_Dov_WS_spinor(4); aux=lock_Dov_WS_spinor(5); aux3=lock_Dov_WS_spinor(6); eigenvalues_for_cg_computed = no_eigenvalues - 1; if(eigenvalues_for_cg_computed < 0) eigenvalues_for_cg_computed = 0; maxev=1.0; fact1=4/(maxev-minev); fact2=-2*(maxev+minev)/(maxev-minev); zero_spinor_field(d, VOLUME); zero_spinor_field(dd, VOLUME); if(1) assign_sub_lowest_eigenvalues(aux3, S, no_eigenvalues-1, VOLUME); else assign(aux3, S, VOLUME); /* Check whether switch for adaptive precision is on */ /* this might be implemented again in the future */ /* Use the 'old' version using Clenshaw's recursion for the Chebysheff polynomial */ if(1) { for (j = n-1; j >= 1; j--) { assign(sv, d, VOLUME); if ( (j%10) == 0 ) { assign_sub_lowest_eigenvalues(aux, d, no_eigenvalues-1, VOLUME); } else { assign(aux, d, VOLUME); } norm_Q_sqr_psi(R, aux, rnorm); /* printf("%d %e %e\n", j, R[0].s0.c0.re, R[0].s0.c0.im); */ /* printf("%e %e\n", R[0].s1.c0.re, R[0].s1.c0.im); */ temp1=-1.0; temp2=c[j]; assign_mul_add_mul_add_mul_add_mul_r(d, R, dd, aux3, fact2, fact1, temp1, temp2, VOLUME); assign(dd, sv, VOLUME); } if(1) assign_sub_lowest_eigenvalues(R, d, no_eigenvalues-1, VOLUME); else assign(R, d, VOLUME); norm_Q_sqr_psi(aux, R, rnorm); temp1=-1.0; temp2=c[0]/2.; temp3=fact1/2.; temp4=fact2/2.; assign_mul_add_mul_add_mul_add_mul_r(aux, d, dd, aux3, temp3, temp4, temp1, temp2, VOLUME); norm_Q_n_psi(R, aux, 1, rnorm); } else { /* Use the adaptive precision version using the forward recursion for the Chebysheff polynomial */ /* d = T_0(Q^2) */ assign(d, aux3, VOLUME); /* dd = T_1(Q^2) */ norm_Q_sqr_psi(dd, d, rnorm); temp3 = fact1/2.; temp4 = fact2/2.; assign_mul_add_mul_r(dd, d, temp3, temp4, VOLUME); /* r = c_1 T_1(Q^2) + 1./2 c_0 */ temp1 = c[1]; temp2 = c[0]/2.; mul_add_mul_r(R, dd, d, temp1, temp2, VOLUME); temp1=-1.0; for (j = 2; j <= n-1; j++) { /* aux = T_j(Q^2) = 2 Q^2 T_{j-1}(Q^2) - T_{j-2}(Q^2) */ norm_Q_sqr_psi(aux, dd, rnorm); assign_mul_add_mul_add_mul_r(aux, dd, d, fact1, fact2, temp1, VOLUME); /* r = r + c_j T_j(Q^2) */ temp2 = c[j]; assign_add_mul_r(R, aux, temp2, VOLUME); /* The stoppping criterio tnorm = |T_j(Q^2)| */ tnorm=square_norm(aux, VOLUME, 1); tnorm*=(temp2*temp2); /* auxnorm=square_norm(R); if(g_proc_id == g_stdio_proc){printf("j= %d\t|c T|^2= %g\t c_j= %g\t|r|^2= %g\n",j,tnorm,temp2,auxnorm); fflush( stdout);}; */ if(tnorm < ap_eps_sq) break; /* d = T_{j-1}(Q^2) */ assign(d, dd, VOLUME); /* dd = T_{j}(Q^2) */ assign(dd, aux, VOLUME); } if(g_proc_id == g_stdio_proc && g_debug_level > 0) { printf("Order of Chebysheff approximation = %d\n",j); fflush( stdout); } /* r = Q r */ assign(aux, R, VOLUME); norm_Q_n_psi(R, aux, 1, rnorm); } /* add in piece from projected subspace */ addproj_q_invsqrt(R, S, no_eigenvalues-1, VOLUME); unlock_Dov_WS_spinor(2); unlock_Dov_WS_spinor(3); unlock_Dov_WS_spinor(4); unlock_Dov_WS_spinor(5); unlock_Dov_WS_spinor(6); return; }
void Ptilde_ndpsi(spinor *R_s, spinor *R_c, double *dd, int n, spinor *S_s, spinor *S_c, matrix_mult_nd Qsq) { int j; double fact1, fact2, temp1, temp2, temp3, temp4; spinor *svs_=NULL, *svs=NULL, *ds_=NULL, *ds=NULL, *dds_=NULL, *dds=NULL, *auxs_=NULL, *auxs=NULL, *aux2s_=NULL, *aux2s=NULL, *aux3s_=NULL, *aux3s=NULL; spinor *svc_=NULL, *svc=NULL, *dc_=NULL, *dc=NULL, *ddc_=NULL, *ddc=NULL, *auxc_=NULL, *auxc=NULL, *aux2c_=NULL, *aux2c=NULL, *aux3c_=NULL, *aux3c=NULL; svs_ = calloc(VOLUMEPLUSRAND+1, sizeof(spinor)); svs = (spinor *)(((unsigned long int)(svs_)+ALIGN_BASE)&~ALIGN_BASE); ds_ = calloc(VOLUMEPLUSRAND+1, sizeof(spinor)); ds = (spinor *)(((unsigned long int)(ds_)+ALIGN_BASE)&~ALIGN_BASE); dds_ = calloc(VOLUMEPLUSRAND+1, sizeof(spinor)); dds = (spinor *)(((unsigned long int)(dds_)+ALIGN_BASE)&~ALIGN_BASE); auxs_ = calloc(VOLUMEPLUSRAND+1, sizeof(spinor)); auxs = (spinor *)(((unsigned long int)(auxs_)+ALIGN_BASE)&~ALIGN_BASE); aux2s_= calloc(VOLUMEPLUSRAND+1, sizeof(spinor)); aux2s = (spinor *)(((unsigned long int)(aux2s_)+ALIGN_BASE)&~ALIGN_BASE); aux3s_= calloc(VOLUMEPLUSRAND+1, sizeof(spinor)); aux3s = (spinor *)(((unsigned long int)(aux3s_)+ALIGN_BASE)&~ALIGN_BASE); svc_ = calloc(VOLUMEPLUSRAND+1, sizeof(spinor)); svc = (spinor *)(((unsigned long int)(svc_)+ALIGN_BASE)&~ALIGN_BASE); dc_ = calloc(VOLUMEPLUSRAND+1, sizeof(spinor)); dc = (spinor *)(((unsigned long int)(dc_)+ALIGN_BASE)&~ALIGN_BASE); ddc_ = calloc(VOLUMEPLUSRAND+1, sizeof(spinor)); ddc = (spinor *)(((unsigned long int)(ddc_)+ALIGN_BASE)&~ALIGN_BASE); auxc_ = calloc(VOLUMEPLUSRAND+1, sizeof(spinor)); auxc = (spinor *)(((unsigned long int)(auxc_)+ALIGN_BASE)&~ALIGN_BASE); aux2c_= calloc(VOLUMEPLUSRAND+1, sizeof(spinor)); aux2c = (spinor *)(((unsigned long int)(aux2c_)+ALIGN_BASE)&~ALIGN_BASE); aux3c_= calloc(VOLUMEPLUSRAND+1, sizeof(spinor)); aux3c = (spinor *)(((unsigned long int)(aux3c_)+ALIGN_BASE)&~ALIGN_BASE); fact1=4/(phmc_cheb_evmax-phmc_cheb_evmin); fact2=-2*(phmc_cheb_evmax+phmc_cheb_evmin)/(phmc_cheb_evmax-phmc_cheb_evmin); zero_spinor_field(&ds[0],VOLUME/2); zero_spinor_field(&dds[0],VOLUME/2); zero_spinor_field(&dc[0],VOLUME/2); zero_spinor_field(&ddc[0],VOLUME/2); /* sub_low_ev(&aux3[0], &S[0]); */ assign(&aux3s[0], &S_s[0],VOLUME/2); assign(&aux3c[0], &S_c[0],VOLUME/2); /* Use the Clenshaw's recursion for the Chebysheff polynomial */ for (j=n-1; j>=1; j--) { assign(&svs[0],&ds[0],VOLUME/2); assign(&svc[0],&dc[0],VOLUME/2); /* * if ( (j%10) == 0 ) { * sub_low_ev(&aux[0], &d[0]); * } else { */ assign(&auxs[0], &ds[0], VOLUME/2); assign(&auxc[0], &dc[0], VOLUME/2); /* } */ Qsq(&R_s[0], &R_c[0], &auxs[0], &auxc[0]); temp1=-1.0; temp2=dd[j]; assign_mul_add_mul_add_mul_add_mul_r(&ds[0] , &R_s[0], &dds[0], &aux3s[0], fact2, fact1, temp1, temp2,VOLUME/2); assign_mul_add_mul_add_mul_add_mul_r(&dc[0] , &R_c[0], &ddc[0], &aux3c[0], fact2, fact1, temp1, temp2,VOLUME/2); assign(&dds[0], &svs[0],VOLUME/2); assign(&ddc[0], &svc[0],VOLUME/2); } assign(&R_s[0], &ds[0],VOLUME/2); assign(&R_c[0], &dc[0],VOLUME/2); Qsq(&auxs[0], &auxc[0], &R_s[0], &R_c[0]); temp1=-1.0; temp2=dd[0]/2; temp3=fact1/2; temp4=fact2/2; assign_mul_add_mul_add_mul_add_mul_r(&auxs[0], &ds[0], &dds[0], &aux3s[0], temp3, temp4, temp1, temp2,VOLUME/2); assign_mul_add_mul_add_mul_add_mul_r(&auxc[0], &dc[0], &ddc[0], &aux3c[0], temp3, temp4, temp1, temp2,VOLUME/2); assign(&R_s[0], &auxs[0],VOLUME/2); assign(&R_c[0], &auxc[0],VOLUME/2); free(svs_); free(ds_); free(dds_); free(auxs_); free(aux2s_); free(aux3s_); free(svc_); free(dc_); free(ddc_); free(auxc_); free(aux2c_); free(aux3c_); }