/* Put antihermitian traceless part into momentum */ static void add_forces_to_mom(QDP_ColorVector **back_qdp, QDP_ColorVector **forw_qdp, int dir, REAL coeff[], int nsrc) { REAL tmp_coeff[nsrc]; QDP_ColorMatrix *tm[nsrc]; int i; QOP_trace("test 481\n"); if(GOES_BACKWARDS(dir)) { dir = OPP_DIR(dir); for(i=0; i<nsrc; i++) { tmp_coeff[i] = -coeff[i]; } } else { for(i=0; i<nsrc; i++) { tmp_coeff[i] = coeff[i]; } } QOP_trace("test 482\n"); for(i=0; i<nsrc; i++) { QDP_V_eq_r_times_V(tv[i], &tmp_coeff[i], forw_qdp[i], QDP_all); tm[i] = tempmom_qdp[dir]; } QOP_trace("test 483\n"); QDP_M_vpeq_V_times_Va(tm, back_qdp, tv, QDP_all, nsrc); QOP_trace("test 484\n"); }
/* normalizes the vecror vec. Work only on subset. */ void normalize_qdp(QDP_ColorVector *vec, QDP_Subset subset) { QLA_Real norm; QDP_r_eq_norm2_V(&norm, vec, subset); norm = 1.0/sqrt(norm); QDP_V_eq_r_times_V(vec, &norm, vec, subset); }
int Rayleigh_min_qdp(QDP_ColorVector *vec, QDP_ColorVector **eigVec, Real Tolerance, Real RelTol, int Nvecs, int MaxIter, int Restart, QDP_Subset subset) { QLA_Complex cc; QLA_Real beta, cos_theta, sin_theta; QLA_Real quot, P_norm, theta, real_vecMp, pMp; QLA_Real g_norm, old_g_norm, start_g_norm; QDP_ColorVector *Mvec, *grad, *P, *MP; int iter; #ifdef DEBUG if(QDP_this_node==0) printf("begin Rayleigh_min_qdp\n"); #endif Mvec = QDP_create_V(); grad = QDP_create_V(); //oldgrad = QDP_create_V(); P = QDP_create_V(); MP = QDP_create_V(); project_out_qdp(vec, eigVec, Nvecs, subset); normalize_qdp(vec, subset); Matrix_Vec_mult_qdp(vec, Mvec, subset); project_out_qdp(Mvec, eigVec, Nvecs, subset); /* Compute the quotient quot=vev*M*vec */ QDP_r_eq_re_V_dot_V(", vec, Mvec, subset); /* quot is real since M is hermitian. quot = vec*M*vec */ #ifdef DEBUG if(QDP_this_node==0) printf("Rayleigh_min: Start -- quot=%g\n", quot); #endif /* Compute the grad=M*vec - quot*vec */ QDP_V_eq_V(grad, Mvec, QDP_all); QDP_V_meq_r_times_V(grad, ", vec, subset); /* set P (the search direction) equal to grad */ QDP_V_eq_V(P, grad, QDP_all); /* compute the norms of P and grad */ QDP_r_eq_norm2_V(&P_norm, P, subset); P_norm = sqrt(P_norm); QDP_r_eq_norm2_V(&g_norm, grad, subset); g_norm = sqrt(g_norm); start_g_norm = g_norm; //QDP_V_eq_V(oldgrad, grad, subset); #ifdef DEBUG if(QDP_this_node==0) printf("Rayleigh_min: Start -- g_norm=%g\n", g_norm); #endif iter = 0; while( (g_norm>Tolerance*quot) && ( ((iter<MaxIter)&&(g_norm/start_g_norm>RelTol)) || (iter<MINITER) ) ) { iter++; Matrix_Vec_mult_qdp(P, MP, subset); QDP_r_eq_re_V_dot_V(&real_vecMp, vec, MP, subset); QDP_r_eq_re_V_dot_V(&pMp, P, MP, subset); theta = 0.5*atan(2.0*real_vecMp/(quot*P_norm - pMp/P_norm)); sin_theta = sin(theta); cos_theta = cos(theta); if(sin_theta*cos_theta*real_vecMp>0) { theta = theta - 0.5*M_PI; /* chose the minimum not the maximum */ sin_theta = sin(theta); /* the sin,cos calls can be avoided */ cos_theta = cos(theta); } sin_theta = sin_theta/P_norm; /* vec = cos(theta)*vec +sin(theta)*P/p_norm */ //dax_p_by_qdp(cos_theta, vec, sin_theta, P, subset); QDP_V_eq_r_times_V(vec, &cos_theta, vec, subset); QDP_V_peq_r_times_V(vec, &sin_theta, P, subset); /* Mvec = cos(theta)*Mvec +sin(theta)*MP/p_norm */ //dax_p_by_qdp(cos_theta, Mvec, sin_theta, MP, subset); QDP_V_eq_r_times_V(Mvec, &cos_theta, Mvec, subset); QDP_V_peq_r_times_V(Mvec, &sin_theta, MP, subset); /* renormalize vec ... */ if( iter%Restart == 0 ) { #ifdef DEBUG { QLA_Real vec_norm; if(QDP_this_node==0) printf("Renormalizing..."); QDP_r_eq_norm2_V(&vec_norm, vec, subset); if(QDP_this_node==0) printf(" norm: %g\n", sqrt(vec_norm)); } #endif /* Project vec on the orthogonal complement of eigVec */ project_out_qdp(vec, eigVec, Nvecs, subset); normalize_qdp(vec, subset); Matrix_Vec_mult_qdp(vec, Mvec, subset); /* Recompute the quotient */ QDP_r_eq_re_V_dot_V(", vec, Mvec, subset); /* Recompute the grad */ QDP_V_eq_V(grad, Mvec, QDP_all); QDP_V_meq_r_times_V(grad, ", vec, subset); //QDP_r_eq_norm2_V(&g_norm, grad, subset); //printf("g_norm = %g\n", g_norm); /* Project P on the orthogonal complement of eigVec */ //QDP_r_eq_norm2_V(&P_norm, P, subset); //printf("P_norm = %g\n", P_norm); project_out_qdp(P, eigVec, Nvecs, subset); //QDP_r_eq_norm2_V(&P_norm, P, subset); //printf("P_norm = %g\n", P_norm); /* make P orthogonal to vec */ QDP_c_eq_V_dot_V(&cc, vec, P, subset); //printf("cc = %g\n", QLA_real(cc)); QDP_V_meq_c_times_V(P, &cc, vec, subset); //QDP_r_eq_norm2_V(&P_norm, P, subset); //printf("P_norm = %g\n", P_norm); /* make P orthogonal to grad */ QDP_c_eq_V_dot_V(&cc, grad, P, subset); //printf("cc = %g\n", QLA_real(cc)); QDP_V_meq_c_times_V(P, &cc, grad, subset); QDP_r_eq_norm2_V(&P_norm, P, subset); P_norm = sqrt(P_norm); } QDP_r_eq_re_V_dot_V(", vec, Mvec, subset); #ifdef DEBUG node0_printf("Rayleigh_min: %i, quot=%8g g=%8g b=%6g P:%6g\n", iter, quot, g_norm, beta, P_norm); #endif old_g_norm = g_norm; QDP_V_eq_V(grad, Mvec, QDP_all); QDP_V_meq_r_times_V(grad, ", vec, subset); //QDP_V_meq_V(oldgrad, grad, subset); //QDP_r_eq_re_V_dot_V(&g_norm, oldgrad, grad, subset); //QDP_V_eq_V(oldgrad, grad, subset); QDP_r_eq_norm2_V(&g_norm, grad, subset); g_norm = sqrt(g_norm); beta = cos_theta*g_norm*g_norm/(old_g_norm*old_g_norm); if( beta>2.0 ) beta = 2.0; /* Cut off beta */ QDP_c_eq_V_dot_V(&cc, vec, P, subset); QLA_real(cc) *= beta; QLA_imag(cc) *= beta; QDP_V_eq_r_times_V_plus_V(P, &beta, P, grad, subset); QDP_V_meq_c_times_V(P, &cc, vec, subset); QDP_r_eq_norm2_V(&P_norm, P, subset); P_norm = sqrt(P_norm); } project_out_qdp(vec, eigVec, Nvecs, subset); normalize_qdp(vec, subset); QDP_destroy_V(MP); QDP_destroy_V(P); //QDP_destroy_V(oldgrad); QDP_destroy_V(grad); QDP_destroy_V(Mvec); iter++; #ifdef DEBUG if(QDP_this_node==0) printf("end Rayleigh_min_qdp\n"); #endif return iter; }