int mat_invert_uml(field_offset src, field_offset dest, field_offset temp,
		   double mass ){
    int cgn;
    double finalrsq;
    register int i;
    register site *s;

    if( src==temp ){
	printf("BOTCH\n"); exit(0);
    }
    /* multiply by U - even sites only */
    dslash( src, F_OFFSET(ttt), EVEN);
    scalar_mult_add_latvec( F_OFFSET(ttt), src,
       -2.0*mass, temp, EVEN);
    scalar_mult_latvec( temp, -1.0, temp, EVEN);
    /* invert with M_adj M even */
    cgn = ks_congrad( temp, dest, mass, niter, rsqprop,
	EVEN, &finalrsq );
    /* multiply by (1/2m)L, does nothing to even sites */
    /* fix up odd sites , 1/2m (Dslash_oe*dest_e + phi_odd) */
    dslash( dest, F_OFFSET(ttt), ODD );
    FORODDSITES(i,s){
	sub_su3_vector( (su3_vector *)F_PT(s,src), &(s->ttt), 
	    (su3_vector *)F_PT(s,dest) );
	scalar_mult_su3_vector( (su3_vector *)F_PT(s,dest), 1.0/(2.0*mass),
	    (su3_vector *)F_PT(s,dest) );
    }
Esempio n. 2
0
int nl_spectrum( Real vmass, field_offset temp1, field_offset temp2 ) { 
  /* return the C.G. iteration number */
  double *piprop,*pi2prop,*rhoprop,*rho2prop,*barprop;
  double *nlpiprop,*nlpi2prop,*ckpiprop,*ckpi2prop;
  double *delprop,*ckbarprop;
  Real vmass_x2;
  site* s;
  register complex cc;
  Real finalrsq;
  register int i,x,y,z,t,icol,cgn;
  register int t_source,t_off;
  int dir,isrc;

  msg_tag *mtag[16];

  piprop = (double *)malloc( nt*sizeof(double) );
  pi2prop = (double *)malloc( nt*sizeof(double) );
  rhoprop = (double *)malloc( nt*sizeof(double) );
  rho2prop = (double *)malloc( nt*sizeof(double) );
  barprop = (double *)malloc( nt*sizeof(double) );
  nlpiprop = (double *)malloc( nt*sizeof(double) );
  nlpi2prop = (double *)malloc( nt*sizeof(double) );
  ckpiprop = (double *)malloc( nt*sizeof(double) );
  ckpi2prop = (double *)malloc( nt*sizeof(double) );
  delprop = (double *)malloc( nt*sizeof(double) );
  ckbarprop = (double *)malloc( nt*sizeof(double) );

  for( t=0; t<nt; t++ ){
    piprop[t]=0.0; pi2prop[t]=0.0; rhoprop[t]=0.0; rho2prop[t]=0.0;
    nlpiprop[t]=0.0; nlpi2prop[t]=0.0;
    ckpiprop[t]=0.0; ckpi2prop[t]=0.0;
    barprop[t]=0.0; delprop[t]=0.0; ckbarprop[t]=0.0;
  }

  vmass_x2 = 2.*vmass;
  cgn=0;

  /* Fix TUP Coulomb gauge - gauge links only*/
  rephase( OFF );
  gaugefix(TUP,(Real)1.8,500,(Real)GAUGE_FIX_TOL);
  rephase( ON );
#ifdef FN
  invalidate_all_ferm_links(&fn_links);
#endif

  /* Unlike spectrum.c, here we calculate only with wall sources */
  for(t_source=source_start, isrc=0; t_source<2*nt && isrc < n_sources;
        ++isrc, t_source += source_inc ) {
      
      /* Only work for even source slices */
      if( t_source%2 != 0 ){
	printf("DUMMY:  Use even time slices for nl_spectrum()\n");
	terminate(0);
      }

      /* Compute propagator from even wall sites */
      /* Sources are normalized to 1/8 to make them comparable to */
      /* propagators from a wall with ones on the cube origin. */
      /* Put result in propmat */
      
      for(icol=0; icol<3; icol++) {
	  
	  /* initialize temp1 and temp2 */
	  clear_latvec( temp1, EVEN);
	  clear_latvec( temp2, EVEN);
	  
	  for(x=0;x<nx;x++)for(y=0;y<ny;y++)for(z=0;z<nz;z++) {
	      if((x+y+z) % 2 == 0) {
		  if( node_number(x,y,z,t_source) != mynode() )continue;
		  i=node_index(x,y,z,t_source);
		  ((su3_vector *)(F_PT(&lattice[i],temp1)))->c[icol].real = 
		    -0.25;
		}
	    }
	  
	  /* do a C.G. */
	  load_ferm_links(&fn_links);
	  cgn += congrad(niter,rsqprop,EVEN,&finalrsq, &fn_links);
	  /* Multiply by -Madjoint */
	  dslash_site( temp2, temp2, ODD, &fn_links);
	  scalar_mult_latvec( temp2, -vmass_x2, temp2, EVEN);
	  
	  /* fill the hadron matrix */
	  copy_latvec( temp2, F_OFFSET(propmat[icol]), EVENANDODD);
	} /* end loop on icol */
      
      
      /* Compute propagator from odd wall sites */
      /* Put result in propmat2 */
      
      for(icol=0; icol<3; icol++) {
	  
	  /* initialize temp1 and temp2 */
	  clear_latvec( temp1, ODD);
	  clear_latvec( temp2, ODD);
	  for(x=0;x<nx;x++)for(y=0;y<ny;y++)for(z=0;z<nz;z++) {
	      if((x+y+z) % 2 == 1) {
		  if( node_number(x,y,z,t_source) != mynode() )continue;
		  i=node_index(x,y,z,t_source);
		  ((su3_vector *)(F_PT(&lattice[i],temp1)))->c[icol].real = 
		    -0.25;
		}
	    }
	  
	  /* do a C.G. */
	  load_ferm_links(&fn_links);
	  cgn += congrad(niter,rsqprop,ODD,&finalrsq,&fn_links);
	  /* Multiply by -Madjoint */
	  dslash_site( temp2, temp2, EVEN, &fn_links);
	  scalar_mult_latvec( temp2, -vmass_x2, temp2, ODD);
	  
	  /* fill the hadron matrix */
	  copy_latvec( temp2, F_OFFSET(propmat2[icol]), EVENANDODD);
	} /* end loop on icol */
      
      /* cgn now gives the sum for both inversions */
      
      
      /* measure the meson propagator for the E wall source */
      for(t=0; t<nt; t++) {
	  /* define the time value offset t from t_source */
	  t_off = (t+t_source)%nt;
	  
	  for(x=0;x<nx;x++)for(y=0;y<ny;y++)for(z=0;z<nz;z++)
	    for(icol=0;icol<3;icol++) {
		if( node_number(x,y,z,t_off) != mynode() )continue;
		i=node_index(x,y,z,t_off);
		cc = su3_dot( &lattice[i].propmat[icol],
			     &lattice[i].propmat[icol] );
		
		piprop[t] += cc.real;
		/* (rhoprop and rho2prop are not generated by this source) */
		
		if( (x+y+z)%2==0)pi2prop[t] += cc.real;
		else	     pi2prop[t] -= cc.real;
		
	      }
	  
	} /* nt-loop */
      
      /* measure the baryon propagator for the E wall source */
      for(t=0; t<nt; t++) {
	  /* define the time value offset t from t_source */
	  t_off = (t+t_source)%nt;
	  
	  for(x=0;x<nx;x+=2)for(y=0;y<ny;y+=2)for(z=0;z<nz;z+=2) {
	      if( node_number(x,y,z,t_off) != mynode() )continue;
	      i=node_index(x,y,z,t_off);
	      cc = det_su3( (su3_matrix *)(lattice[i].propmat) );
	      barprop[t] += cc.real;
	  }
	  
	  /* must get sign right.  This looks to see if we have
	     wrapped around the lattice.  "t" is the distance
	     from the source to the measurement, so we are
	     trying to find out if t_source+t is greater than
	     or equal to nt. */
	  if( (((t+t_source)/nt-t_source/nt)%2) == 1 )barprop[t] *= -1.0;
	  /* change sign because antiperiodic b.c.  sink point
	     should really be in a copy of the lattice */
	} /* nt-loop */
      
      
      /* Measure nonlocal (and some local for checking) propagators    */
      /* These propagators include the delta and some nonlocal mesons  */
      /* The method for the delta is described in M.F.L. Golterman and */
      /* J. Smit, Nucl. Phys. B 255, 328 (1985)                        */
      /* Equation (6.3) defines the sink operator for the delta        */
      /* The method for the mesons is described in M.F.L. Golterman    */
      /* Nucl. Phys. B 273, 663 (1986)                                 */
      /* The treatment of the source wall is described in Gupta,       */
      /* Guralnik, Kilcup, and Sharpe, (GGKS) NSF-ITP-90-172 (1990)    */
      /* To get the delta propagator, we take the "q" propagator       */
      /* matrices for each of the wall colors and antisymmetrize over  */
      /* wall color as well as s                    */
      
      /* First construct the "q" and "o" propagators                   */
      /* Put q = E + O in propmat and o = E - O in propmat2 */
      
      FORALLSITES(i,s) {
	  for(icol=0; icol<3; icol++) {
	      add_su3_vector (&(s->propmat[icol]), &(s->propmat2[icol]), 
			      (su3_vector *)(s->tempmat1.e[icol]) );
	      sub_su3_vector (&(s->propmat[icol]), &(s->propmat2[icol]), 
			      &(s->propmat2[icol]) );
	      su3vec_copy( (su3_vector *)(s->tempmat1.e[icol]),
		&(s->propmat[icol]) );
	    }
	}
      
      
      
      /* Next gather the propagators in preparation for calculating   */
      /* shifted propagators Dq and Do                                */
      
      FORALLUPDIRBUT(TUP,dir) {
	  /* Start bringing "q" = propmat from forward sites    */
	  
	  mtag[dir] = start_gather_site(F_OFFSET(propmat[0]), 
		   sizeof(su3_matrix), dir, EVENANDODD, gen_pt[dir]);
	  
	  /* Start bringing "q" from backward neighbors       */
	  
	  mtag[dir+4] = start_gather_site(F_OFFSET(propmat[0]), 
		   sizeof(su3_matrix), OPP_DIR(dir), EVENANDODD,
		   gen_pt[dir+4]);
	  wait_gather(mtag[dir]);
	  wait_gather(mtag[dir+4]);
	  
	  /* Start bringing "o" = propmat2 from forward sites   */
	  
	  mtag[8+dir] = start_gather_site(F_OFFSET(propmat2[0]), 
		   sizeof(su3_matrix), dir, EVENANDODD, gen_pt[8+dir]);
	  
	      /* Start bringing "o" from backward neighbors       */
	  
	  mtag[8+dir+4] = start_gather_site(F_OFFSET(propmat2[0]), 
		    sizeof(su3_matrix), OPP_DIR(dir), EVENANDODD,
		    gen_pt[8+dir+4]);
	  wait_gather(mtag[8+dir]);
	  wait_gather(mtag[8+dir+4]);
	  
	}
      
      
      /* Calculate and dump delta propagator */
      for(t=0; t<nt; t++) {
	  /* define the time value offset t from t_source */
	  t_off = (t+t_source)%nt;
	  
	  /* Calculate contribution for each permutation of source color */
	  delta_prop (0,1,2, 1, t_off, &delprop[t]);
	  delta_prop (1,2,0, 1, t_off, &delprop[t]);
	  delta_prop (2,0,1, 1, t_off, &delprop[t]);
	  delta_prop (1,0,2,-1, t_off, &delprop[t]);
	  delta_prop (0,2,1,-1, t_off, &delprop[t]);
	  delta_prop (2,1,0,-1, t_off, &delprop[t]);
	  
	  if( (((t+t_source)/nt-t_source/nt)%2) == 1 ) delprop[t] *= -1;
	} /* nt-loop */
      
      /* Calculate the "q" source nucleon as a check */
      
      /* Calculate and dump nucleon check propagator */
      for(t=0; t<nt; t++) {
	  /* define the time value offset t from t_source */
	  t_off = (t+t_source)%nt;
	  
	  for(x=0;x<nx;x+=2)for(y=0;y<ny;y+=2)for(z=0;z<nz;z+=2) {
	      if( node_number(x,y,z,t_off) != mynode() )continue;
	      i=node_index(x,y,z,t_off);
	      /* The q propagator is in propmat */
	      cc = det_su3( (su3_matrix *)(lattice[i].propmat) );
	      ckbarprop[t] += cc.real;
	    }
	  
	  if( (((t+t_source)/nt-t_source/nt)%2) == 1 )ckbarprop[t]*= -1.0;
	  /* change sign because antiperiodic b.c.  sink point
	     should really be in a copy of the lattice */
	} /* nt-loop */
      
      /* Calculate nonlocal meson propagators and local check */
      for(t=0; t<nt; t++) {
	  /* Calculate two nonlocal pion propagators */
	  /* These are pi_1 and pi_1 tilde of Gupta et al */
	  /* Also calculate two local propagators as a check */
	  
	  /* define the time value offset t from t_source */
	  t_off = (t+t_source)%nt;
	  
	  nl_meson_prop(t_off,&nlpiprop[t],&nlpi2prop[t],&ckpiprop[t],
	     &ckpi2prop[t]);
	  
	} /* nt-loop */
      
      /* Clean up gathers */
      FORALLUPDIRBUT(TUP,dir) {
	  cleanup_gather(mtag[dir]);
	  cleanup_gather(mtag[dir+4]);
	  cleanup_gather(mtag[8+dir]);
	  cleanup_gather(mtag[8+dir+4]);
	}
Esempio n. 3
0
Until we have EO versions of dslash_field, we require FN
#endif

#include "generic_ks_includes.h"	/* definitions files and prototypes */
#include "../include/dslash_ks_redefine.h"   /* Actually not used, yet */
#include "../include/loopend.h"

/*#define CGTIME*/

int ks_congrad_two_src(	/* Return value is number of iterations taken */
    field_offset src1,    /* source vector (type su3_vector) */
    field_offset src2,
    field_offset dest1,	/* solution vectors */
    field_offset dest2,
    Real mass1,
    Real mass2,
    int niter,		/* maximal number of CG interations */
    int nrestart,       /* maximal number of CG restarts */
    Real rsqmin,	/* desired residue squared */
    int prec,           /* internal precision for the inversion (ignored) */
    int parity,		/* parity to be worked on */
    Real  *final_rsq_ptr, /* final residue squared */
    ferm_links_t *fn       /* Storage for fermion links */
    )
{
    /* Site su3_vector's resid, cg_p and ttt are used as temporaries */
    register int i;
    register site *s;
    int iteration;       /* counter for iterations */
    double c1, c2, rsq, oldrsq, pkp;            /* pkp = cg_p.K.cg_p */
    double source_norm,source_norm1;	/* squared magnitude of source vector */
    double rsqstop;	/* stopping residual normalized by source norm */
    int l_parity;	/* parity we are currently doing */
    int l_otherparity;	/* the other parity */
    msg_tag *tags1[16], *tags2[16];	/* tags for gathers to parity and opposite */
    int special_started;	/* 1 if dslash_special has been called */
    int j, jud, jstrange;
    double shift, msq_xm4;
    double zeta_i[2], zeta_im1[2], zeta_ip1[2];
    double beta_i[2], beta_im1[2], alpha[2];
    int first;                                                 
    su3_vector *temp;
    su3_vector *destvec1;
    su3_vector *destvec2;
    su3_vector *pm_strange;
    su3_vector *init_guess;
    su3_vector *common_source;
    su3_vector *ttt;
    su3_vector *cg_p;
    su3_vector *resid;

/* Timing */
#ifdef CGTIME
    double dtimed,dtimec;
#endif
    double nflop;

/* debug */
#ifdef CGTIME
    dtimec = -dclock();   
#endif
    first = 0;
    nflop = 1187;	/* THIS LOOKS WRONG - DT */
    if(parity==EVENANDODD)nflop *=2;
	
    special_started = 0;
    /* if we want both parities, we will do even first. */
    switch(parity){
	case(EVEN): l_parity=EVEN; l_otherparity=ODD; break;
	case(ODD):  l_parity=ODD; l_otherparity=EVEN; break;
	case(EVENANDODD):  l_parity=EVEN; l_otherparity=ODD; break;
     }
    jud = 0;
    jstrange = 1;
    temp=(su3_vector *)malloc(sites_on_node*sizeof(su3_vector));
    destvec1=(su3_vector *)malloc(sites_on_node*sizeof(su3_vector));
    destvec2=(su3_vector *)malloc(sites_on_node*sizeof(su3_vector));
    ttt=(su3_vector *)malloc(sites_on_node*sizeof(su3_vector));
    cg_p=(su3_vector *)malloc(sites_on_node*sizeof(su3_vector));
    resid=(su3_vector *)malloc(sites_on_node*sizeof(su3_vector));
    pm_strange = (su3_vector *)malloc(sites_on_node*sizeof(su3_vector));
    init_guess = (su3_vector *)malloc(sites_on_node*sizeof(su3_vector) );
    common_source = (su3_vector *)malloc(sites_on_node*sizeof(su3_vector) );
    shift = 4.0*( mass2*mass2 - mass1*mass1);
    
    msq_xm4 = -4.0*mass1*mass1;                              
    iteration = 0;

#ifdef CGTIME
    dtimec = -dclock();                   
#endif
    /* initialization process */
    start:
#ifdef FN
	if(special_started==1) {        /* clean up gathers */
	    cleanup_gathers(tags1, tags2);
	    special_started = 0;
	}
#endif
	/*This loop calculates init_guess = (phi2 - phi1)/shift = X0 , which
	 * is used to equalize the two sources*/
	
	FORSOMEPARITY(i,s,l_parity){
	    sub_su3_vector( (su3_vector *)F_PT(s,src2),(su3_vector *)F_PT(s,src1),&temp[i] );      
	    scalar_mult_su3_vector(&temp[i],1.0/shift,&init_guess[i] );
       }END_LOOP