Exemple #1
0
static void
get_resid(QDP_ColorVector *r, QDP_ColorVector *x, QDP_ColorVector *b,
	  QOP_FermionLinksAsqtad *fla, QLA_Real m, QOP_evenodd_t eo, QDP_ColorVector *t)
{
  if(eo==QOP_EVEN) {
    QOP_asqtad_dslash_qdp(NULL, fla, m, r, x, QOP_ODD, QOP_EVEN);
    QOP_asqtad_dslash_qdp(NULL, fla, m, r, r, QOP_EVEN, QOP_ODD);
    QLA_Real mi = 1/m;
    QDP_V_eq_r_times_V_plus_V(r, &mi, r, b, QDP_even);
    QDP_V_meq_r_times_V(r, &m, x, QDP_even);
  } else if(eo==QOP_EVENODD) {
    QOP_asqtad_dslash_qdp(NULL, fla, m, r, x, QOP_EVENODD, QOP_EVENODD);
    QDP_V_eq_V_minus_V(r, b, r, QDP_all);
  } else {
    QOP_asqtad_dslash_qdp(NULL, fla, m, r, x, QOP_EVEN, QOP_ODD);
    QOP_asqtad_dslash_qdp(NULL, fla, m, r, r, QOP_ODD, QOP_EVEN);
    QLA_Real mi = 1/m;
    QDP_V_eq_r_times_V_plus_V(r, &mi, r, b, QDP_odd);
    QDP_V_meq_r_times_V(r, &m, x, QDP_odd);
  }
}
Exemple #2
0
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(&quot, 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, &quot, 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(&quot, vec, Mvec, subset);
      /* Recompute the grad */
      QDP_V_eq_V(grad, Mvec, QDP_all);
      QDP_V_meq_r_times_V(grad, &quot, 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(&quot, 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, &quot, 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;
}