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, /* maximum number of restarts */ Real rsqmin, /* desired residue squared */ int prec, /* internal precision for the inversion */ int parity, /* parity to be worked on */ Real *final_rsq_ptr, /* final residue squared */ imp_ferm_links_t *fn /* Storage for fermion links */ ) { int myiters = 0; myiters += ks_congrad( src1, dest1, mass1, niter, nrestart, rsqmin, prec, parity, final_rsq_ptr, fn ); myiters += ks_congrad( src2, dest2, mass2, niter, nrestart, rsqmin, prec, parity, final_rsq_ptr, fn ); return myiters; }
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) ); }
// ----------------------------------------------------------------- // dest <-- M^(-1) src int mat_invert_uml(field_offset src, field_offset dest, field_offset temp, Real mass) { register int i; register site *s; int cgn; Real norm = 1.0 / (2.0 * mass); if (src == temp) { printf("MAT_INVERT_UML: src = temp\n"); exit(0); } // "Precondition" both even and odd sites // temp <-- M^dag src dslash(src, F_OFFSET(ttt), EVENANDODD); scalar_mult_add_latvec(F_OFFSET(ttt), src, -2.0 * mass, temp, EVENANDODD); scalar_mult_latvec(temp, -1.0, temp, EVENANDODD); // dest_e <-- (M^dag M)^-1 temp_e (even sites only) cgn = ks_congrad(temp, dest, mass, EVEN); // Reconstruct odd site solution // dest_o <-- 1/2m (Dslash_oe * dest_e + src_o) dslash(dest, F_OFFSET(ttt), ODD); FORODDSITES(i, s) { sub_vector((vector *)F_PT(s, src), &(s->ttt), (vector *)F_PT(s, dest)); scalar_mult_vector((vector *)F_PT(s, dest), norm, (vector *)F_PT(s, dest)); }
// ----------------------------------------------------------------- // dest = src - 8M^2 (DD^dag + 4M^2)^(-1) src // Hard-code EVEN parity in inverse void X(field_offset src, field_offset dest) { register int i; register site *s; Real MSq_x2 = -8.0 * M * M / starSq; // psi = (DD^dag + 4M^2)^{-1} src clear_latvec(F_OFFSET(psi), EVENANDODD); // Zero initial guess #ifdef CG_DEBUG int iters = ks_congrad(src, F_OFFSET(psi), M / star, EVEN); node0_printf("%d iters in congrad with M=%.4g\n", iters, M / star); #else ks_congrad(src, F_OFFSET(psi), M / star, EVEN); #endif // dest = src - 8M^2 psi FOREVENSITES(i, s) scalar_mult_add_vector((vector *)F_PT(s, src), &(s->psi), MSq_x2, (vector *)F_PT(s, dest)); }
/* Compute M^-1 * phi, answer in dest Uses phi, ttt, resid, xxx, and cg_p as workspace */ int mat_invert_cg( field_offset src, field_offset dest, field_offset temp, double mass ){ int cgn; double finalrsq; clear_latvec( dest, EVENANDODD ); cgn = ks_congrad( src, dest, mass, niter,rsqprop,EVENANDODD,&finalrsq); /* Multiply by Madjoint */ dslash( dest, F_OFFSET(ttt), EVENANDODD); scalar_mult_add_latvec( F_OFFSET(ttt), dest, -2.0*mass, F_OFFSET(ttt), EVENANDODD); scalar_mult_latvec( F_OFFSET(ttt), -1.0, dest, EVENANDODD ); return(cgn); }
int quark_renorm( void ) { register int i, dir; register site *s; int j, cgn; Real mass_x2, finalrsq; Real pix, piy, piz, pit; Real sin_pmu, q_mu, prop_a, prop_b, z_fac, m_func, ftmp = 0; Real r1, r2, r3; int pmu, px, py, pz, pt; int pxn, pyn, pzn, ptn; int currentnode; int j1, jm2, k, dirs[4]; msg_tag *mtag[2]; int j_mass; su3_vector **psim = NULL; int xi, j2, j3, j4, parity; int multiflag; FILE *fp_mom_ks[MAX_NUM_MASS]; /* for writing mom propagator files */ char filename[50]; int prec = PRECISION; /* Make internal precision for CG the same as the prevailing precision */ pix = 2.*PI / (Real)nx; piy = 2.*PI / (Real)ny; piz = 2.*PI / (Real)nz; pit = 2.*PI / (Real)nt; cgn = 0; if( num_mass == 1){ multiflag = 0; } else{ multiflag = 1; psim = (su3_vector **)malloc(num_mass*sizeof(su3_vector *)); for(j=0; j<num_mass; j++){ psim[j] = (su3_vector *)malloc(sites_on_node*sizeof(su3_vector)); } } /* Open the momentum propagator files */ if(this_node == 0){ for(j=0; j<num_mass; j++){ sprintf(filename,"mom_pt_prop.m_%d",j); fp_mom_ks[j] = fopen(filename, "ab"); if(fp_mom_ks[j] == NULL){ printf("quark_renorm: Node %d can't open file %s, error %d\n", this_node,filename,errno);fflush(stdout); terminate(1); } } } rephase( ON ); /* Turn staggered phases on */ /* Create fat and long links */ load_ferm_links(&fn_links, &ks_act_paths); /* Loop over the 16 source points */ for(xi=0; xi<16; xi++){ /* Initialize color trace of the propagator */ FORALLSITES(i,s){ for(j=0; j<num_mass; j++){ s->trace_prop[j].real = 0.0; s->trace_prop[j].imag = 0.0; } } j1 = xi%2; k = xi/2; j2 = k%2; k /= 2; j3 = k%2; k /= 2; j4 = k%2; parity = (j1+j2+j3+j4)%2; /* dirs[XUP] = j1; dirs[YUP] = j2; dirs[ZUP] = j3; dirs[TUP] = j4; */ /* Loop over colors of source vector */ for(j=0; j<3; j++){ /* initialize the source in phi */ FORALLSITES(i,s){ clearvec( &(s->phi)); } /* Point source at site xi in the hypercube at origin */ if( node_number(j1,j2,j3,j4) == this_node ){ i=node_index(j1,j2,j3,j4); lattice[i].phi.c[j].real = -1.0; } if( multiflag == 0){ for(j_mass=0; j_mass<num_mass; j_mass++){ FORALLSITES(i,s){ clearvec( &(s->xxx1)); } if(parity == 0){ /* do a C.G. (source in phi, result in xxx1) */ cgn += ks_congrad( F_OFFSET(phi), F_OFFSET(xxx1), mass[j_mass], niter, nrestart, rsqprop, PRECISION, EVEN, &finalrsq, &fn_links); /* Multiply by -Madjoint */ dslash_site( F_OFFSET(xxx1), F_OFFSET(ttt), ODD, &fn_links); mass_x2 = 2.*mass[j_mass]; FOREVENSITES(i,s){ scalar_mult_su3_vector( &(s->xxx1), -mass_x2, &(s->ttt)); } } else{
int spectrum_nd( Real mass1, Real mass2, Real tol, ferm_links_t *fn ){ /* arguments are light and heavy quark masses, return C.G. iteration number */ int cgn; register int i,j,x,y,z,t,t_off; register site* s; register complex cc; register int t_source; int color; /* color for source */ int src_count; /* number of source time slices used */ complex **props; /* arrays of propagators */ su3_matrix tmat; Real finalrsq; cgn=0; /* number of CG iterations */ /* allocate arrays to accumulate propagators */ props = (complex **)malloc(nprops*sizeof(complex *)); props[0] = (complex *)malloc(nprops*nt*sizeof(complex)); for(i=1;i<nprops;i++)props[i]=props[i-1]+nt; /* set propagators to zero */ for(cc.real=cc.imag=0.0,i=0;i<nprops;i++)for(j=0;j<nt;j++){ props[i][j]=cc; } /* allocate light and heavy quark propagators for each color */ for( color=0; color<3; color++){ lightprop[color] = (su3_vector *)malloc( sizeof(su3_vector)*sites_on_node ); heavyprop[color] = (su3_vector *)malloc( sizeof(su3_vector)*sites_on_node ); } /* loop over "source" time slice */ for(src_count=0,t_source=source_start; t_source<nt && src_count<n_sources; t_source += source_inc,src_count++){ /* Corner wall source */ /* Use quark_source for quark source */ if(this_node==0)printf("spectrum_nd(): source time = %d\n",t_source); for(color=0;color<3;color++){ clear_latvec( F_OFFSET(quark_source), EVENANDODD ); 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_source) != mynode() )continue; i=node_index(x,y,z,t_source); lattice[i].quark_source.c[color].real = -1.0; } /* do a C.G. (source in quark_source, result in g_rand) */ if(t_source%2 == 0) { cgn += ks_congrad( F_OFFSET(quark_source), F_OFFSET(g_rand), mass1, niter, nrestart, rsqprop, PRECISION, EVEN, &finalrsq, fn); /* Multiply by -Madjoint */ dslash_site( F_OFFSET(g_rand), F_OFFSET(quark_prop), ODD, fn); scalar_mult_latvec( F_OFFSET(g_rand), -2.0*mass1, F_OFFSET(quark_prop),EVEN); } else { cgn += ks_congrad( F_OFFSET(quark_source), F_OFFSET(g_rand), mass1, niter, nrestart, rsqprop, PRECISION, ODD, &finalrsq, fn); /* Multiply by -Madjoint */ dslash_site( F_OFFSET(g_rand), F_OFFSET(quark_prop), EVEN, fn); scalar_mult_latvec( F_OFFSET(g_rand), -2.0*mass1, F_OFFSET(quark_prop),ODD); } FORALLSITES(i,s){ lightprop[color][i] = lattice[i].quark_prop; } scalar_mult_latvec( F_OFFSET(quark_prop), -1.0, F_OFFSET(g_rand), EVENANDODD ); check_invert( F_OFFSET(g_rand), F_OFFSET(quark_source), mass1, tol, fn); /* repeat for heavy quark */ if(t_source%2 == 0) { cgn += ks_congrad( F_OFFSET(quark_source), F_OFFSET(g_rand), mass2, niter, nrestart, rsqprop, PRECISION, EVEN, &finalrsq, fn); /* Multiply by -Madjoint */ dslash_site( F_OFFSET(g_rand), F_OFFSET(quark_prop), ODD, fn); scalar_mult_latvec( F_OFFSET(g_rand), -2.0*mass2, F_OFFSET(quark_prop),EVEN); } else { cgn += ks_congrad( F_OFFSET(quark_source), F_OFFSET(g_rand), mass2, niter, nrestart, rsqprop, PRECISION, ODD, &finalrsq, fn); /* Multiply by -Madjoint */ dslash_site( F_OFFSET(g_rand), F_OFFSET(quark_prop), EVEN, fn); scalar_mult_latvec( F_OFFSET(g_rand), -2.0*mass2, F_OFFSET(quark_prop),ODD); } FORALLSITES(i,s){ heavyprop[color][i] = lattice[i].quark_prop; } /* TEMP: test inversion, */ scalar_mult_latvec( F_OFFSET(quark_prop), -1.0, F_OFFSET(g_rand), EVENANDODD ); check_invert( F_OFFSET(g_rand), F_OFFSET(quark_source), mass2, tol, fn); } /* end color loop*/ /* add contributions into propagators */ /* measure the meson 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++)for(y=0;y<ny;y++)for(z=0;z<nz;z++) for(color=0;color<3;color++) { if( node_number(x,y,z,t_off) != mynode() )continue; i=node_index(x,y,z,t_off); /* light-light mesons */ cc = su3_dot( &lightprop[color][i], &lightprop[color][i] ); CSUM( props[prop_pion5_ll][t], cc ) if( (x+y)%2==0)CSUM( props[prop_rhoi0_ll][t], cc ) else CSUB( props[prop_rhoi0_ll][t], cc, props[prop_rhoi0_ll][t] ) if( (y+z)%2==0)CSUM( props[prop_rhoi0_ll][t], cc ) else CSUB( props[prop_rhoi0_ll][t], cc, props[prop_rhoi0_ll][t] ) if( (z+x)%2==0)CSUM( props[prop_rhoi0_ll][t], cc ) else CSUB( props[prop_rhoi0_ll][t], cc, props[prop_rhoi0_ll][t] ) if( x%2==0)CSUM( props[prop_rhoi_ll][t], cc ) else CSUB( props[prop_rhoi_ll][t], cc, props[prop_rhoi_ll][t] ) if( y%2==0)CSUM( props[prop_rhoi_ll][t], cc ) else CSUB( props[prop_rhoi_ll][t], cc, props[prop_rhoi_ll][t] ) if( z%2==0)CSUM( props[prop_rhoi_ll][t], cc ) else CSUB( props[prop_rhoi_ll][t], cc, props[prop_rhoi_ll][t] ) if( (x+y+z)%2==0)CSUM( props[prop_pion05_ll][t], cc ) else CSUB( props[prop_pion05_ll][t], cc, props[prop_pion05_ll][t] ) /* light-heavy mesons */ cc = su3_dot( &lightprop[color][i], &heavyprop[color][i] ); CSUM( props[prop_pion5_lh][t], cc ) if( (x+y)%2==0)CSUM( props[prop_rhoi0_lh][t], cc ) else CSUB( props[prop_rhoi0_lh][t], cc, props[prop_rhoi0_lh][t] ) if( (y+z)%2==0)CSUM( props[prop_rhoi0_lh][t], cc ) else CSUB( props[prop_rhoi0_lh][t], cc, props[prop_rhoi0_lh][t] ) if( (z+x)%2==0)CSUM( props[prop_rhoi0_lh][t], cc ) else CSUB( props[prop_rhoi0_lh][t], cc, props[prop_rhoi0_lh][t] ) if( x%2==0)CSUM( props[prop_rhoi_lh][t], cc ) else CSUB( props[prop_rhoi_lh][t], cc, props[prop_rhoi_lh][t] ) if( y%2==0)CSUM( props[prop_rhoi_lh][t], cc ) else CSUB( props[prop_rhoi_lh][t], cc, props[prop_rhoi_lh][t] ) if( z%2==0)CSUM( props[prop_rhoi_lh][t], cc ) else CSUB( props[prop_rhoi_lh][t], cc, props[prop_rhoi_lh][t] ) if( (x+y+z)%2==0)CSUM( props[prop_pion05_lh][t], cc ) else CSUB( props[prop_pion05_lh][t], cc, props[prop_pion05_lh][t] ) /* heavy-heavy mesons */ cc = su3_dot( &heavyprop[color][i], &heavyprop[color][i] ); CSUM( props[prop_pion5_hh][t], cc ) if( (x+y)%2==0)CSUM( props[prop_rhoi0_hh][t], cc ) else CSUB( props[prop_rhoi0_hh][t], cc, props[prop_rhoi0_hh][t] ) if( (y+z)%2==0)CSUM( props[prop_rhoi0_hh][t], cc ) else CSUB( props[prop_rhoi0_hh][t], cc, props[prop_rhoi0_hh][t] ) if( (z+x)%2==0)CSUM( props[prop_rhoi0_hh][t], cc ) else CSUB( props[prop_rhoi0_hh][t], cc, props[prop_rhoi0_hh][t] ) if( x%2==0)CSUM( props[prop_rhoi_hh][t], cc ) else CSUB( props[prop_rhoi_hh][t], cc, props[prop_rhoi_hh][t] ) if( y%2==0)CSUM( props[prop_rhoi_hh][t], cc ) else CSUB( props[prop_rhoi_hh][t], cc, props[prop_rhoi_hh][t] ) if( z%2==0)CSUM( props[prop_rhoi_hh][t], cc ) else CSUB( props[prop_rhoi_hh][t], cc, props[prop_rhoi_hh][t] ) if( (x+y+z)%2==0)CSUM( props[prop_pion05_hh][t], cc ) else CSUB( props[prop_pion05_hh][t], cc, props[prop_pion05_hh][t] ) } /* color */ } /* nt-loop */ /* measure the baryon 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); /* three light quarks */ for(color=0;color<3;color++){ (tmat.e[0][color]) = lightprop[0][i].c[color]; (tmat.e[1][color]) = lightprop[1][i].c[color]; (tmat.e[2][color]) = lightprop[2][i].c[color]; } cc = det_su3( &tmat ); /* 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. the "-tsource/nt" is in there so that it will work correctly with tsource=nt. */ if( (((t+t_source)/nt-t_source/nt)%2) == 0 ) CSUM( props[prop_nuc_lll][t], cc ) else /* change sign because antiperiodic b.c. sink point should really be in a copy of the lattice */ CSUB( props[prop_nuc_lll][t], cc, props[prop_nuc_lll][t] ) /* two lights and one heavy */ for(color=0;color<3;color++){ (tmat.e[0][color]) = lightprop[0][i].c[color]; (tmat.e[1][color]) = lightprop[1][i].c[color]; (tmat.e[2][color]) = heavyprop[2][i].c[color]; } cc = det_su3( &tmat ); if( (((t+t_source)/nt-t_source/nt)%2) == 0 ) CSUM( props[prop_nuc_llh][t], cc ) else CSUB( props[prop_nuc_llh][t], cc, props[prop_nuc_llh][t] ) /* now repeat for hhl baryon */ for(color=0;color<3;color++){ (tmat.e[0][color]) = lightprop[0][i].c[color]; (tmat.e[1][color]) = heavyprop[1][i].c[color]; (tmat.e[2][color]) = heavyprop[2][i].c[color]; } cc = det_su3( &tmat ); if( (((t+t_source)/nt-t_source/nt)%2) == 0 ) CSUM( props[prop_nuc_lhh][t], cc ) else CSUB( props[prop_nuc_lhh][t], cc, props[prop_nuc_lhh][t] ) /* and hhh baryon (nonexistent particle!!) */ for(color=0;color<3;color++){ (tmat.e[0][color]) = heavyprop[0][i].c[color]; (tmat.e[1][color]) = heavyprop[1][i].c[color]; (tmat.e[2][color]) = heavyprop[2][i].c[color]; } cc = det_su3( &tmat ); if( (((t+t_source)/nt-t_source/nt)%2) == 0 ) CSUM( props[prop_nuc_hhh][t], cc ) else CSUB( props[prop_nuc_hhh][t], cc, props[prop_nuc_hhh][t] ) } } /* nt-loop */ } /* end loop on t_source */ /* Sum propagator arrays over nodes */ /* print out propagators */ g_veccomplexsum( props[0], nprops*nt ); for(i=0;i<nprops;i++)for(j=0;j<nt;j++){ CDIVREAL(props[i][j],n_sources,props[i][j]); } if(this_node==0){ /*meson propagators*/ printf("STARTPROP\n"); printf("MASSES: %e %e\n",mass1,mass1 ); printf("SOURCE: CORNER\n"); printf("SINKS: PION_5 PION_05 RHO_i RHO_i0 \n"); for(j=0;j<nt;j++){ printf("%d %e %e %e %e %e %e %e %e\n",j, props[prop_pion5_ll][j].real, props[prop_pion5_ll][j].imag, props[prop_pion05_ll][j].real, props[prop_pion05_ll][j].imag, props[prop_rhoi_ll][j].real, props[prop_rhoi_ll][j].imag, props[prop_rhoi0_ll][j].real, props[prop_rhoi0_ll][j].imag); } printf("ENDPROP\n"); printf("STARTPROP\n"); printf("MASSES: %e %e\n",mass1,mass2 ); printf("SOURCE: CORNER\n"); printf("SINKS: PION_5 PION_05 RHO_i RHO_i0 \n"); for(j=0;j<nt;j++){ printf("%d %e %e %e %e %e %e %e %e\n",j, props[prop_pion5_lh][j].real, props[prop_pion5_lh][j].imag, props[prop_pion05_lh][j].real, props[prop_pion05_lh][j].imag, props[prop_rhoi_lh][j].real, props[prop_rhoi_lh][j].imag, props[prop_rhoi0_lh][j].real, props[prop_rhoi0_lh][j].imag); } printf("ENDPROP\n"); printf("STARTPROP\n"); printf("MASSES: %e %e\n",mass2,mass2 ); printf("SOURCE: CORNER\n"); printf("SINKS: PION_5 PION_05 RHO_i RHO_i0 \n"); for(j=0;j<nt;j++){ printf("%d %e %e %e %e %e %e %e %e\n",j, props[prop_pion5_hh][j].real, props[prop_pion5_hh][j].imag, props[prop_pion05_hh][j].real, props[prop_pion05_hh][j].imag, props[prop_rhoi_hh][j].real, props[prop_rhoi_hh][j].imag, props[prop_rhoi0_hh][j].real, props[prop_rhoi0_hh][j].imag); } printf("ENDPROP\n"); /* Baryon propagators */ printf("STARTPROP\n"); printf("MASSES: %e %e %e\n",mass1,mass1,mass1); printf("SOURCE: CORNER\n"); printf("SINKS: NUCLEON \n"); for(j=0;j<nt;j++){ printf("%d %e %e\n",j, props[prop_nuc_lll][j].real, props[prop_nuc_lll][j].imag); } printf("ENDPROP\n"); printf("STARTPROP\n"); printf("MASSES: %e %e %e\n",mass1,mass1,mass2); printf("SOURCE: CORNER\n"); printf("SINKS: NUCLEON \n"); for(j=0;j<nt;j++){ printf("%d %e %e\n",j, props[prop_nuc_llh][j].real, props[prop_nuc_llh][j].imag); } printf("ENDPROP\n"); printf("STARTPROP\n"); printf("MASSES: %e %e %e\n",mass1,mass2,mass2); printf("SOURCE: CORNER\n"); printf("SINKS: NUCLEON \n"); for(j=0;j<nt;j++){ printf("%d %e %e\n",j, props[prop_nuc_lhh][j].real, props[prop_nuc_lhh][j].imag); } printf("ENDPROP\n"); printf("STARTPROP\n"); printf("MASSES: %e %e %e\n",mass2,mass2,mass2); printf("SOURCE: CORNER\n"); printf("SINKS: NUCLEON \n"); for(j=0;j<nt;j++){ printf("%d %e %e\n",j, props[prop_nuc_hhh][j].real, props[prop_nuc_hhh][j].imag); } printf("ENDPROP\n"); fflush(stdout); } /* end if(this_node==0) */ /* free arrays */ free(props[0]); free(props); for(color=0;color<3;color++){ free( lightprop[color] ); free( heavyprop[color] ); } return(cgn); } /* spectrum_nd */
/* Hadron wave functions. */ void wavefunc_t() { register int i,j,n; register site *s; register complex cc; msg_tag *tag; Real finalrsq,scale,x; int tmin,tmax,cgn,color; /* for baryon code */ int ca,ca1,ca2,cb,cb1,cb2; void symmetry_combine(field_offset src,field_offset space,int size,int dir); void block_fourier( field_offset src, /* src is field to be transformed */ field_offset space, /* space is working space, same size as src */ int size, /* Size of field in bytes. The field must consist of size/sizeof(complex) consecutive complex numbers. For example, an su3_vector is 3 complex numbers. */ int isign); /* 1 for x -> k, -1 for k -> x */ void fourier( field_offset src, /* src is field to be transformed */ field_offset space, /* space is working space, same size as src */ int size, /* Size of field in bytes. The field must consist of size/sizeof(complex) consecutive complex numbers. For example, an su3_vector is 3 complex numbers. */ int isign); /* 1 for x -> k, -1 for k -> x */ void write_wf(field_offset src,char *string,int tmin,int tmax); /* Fix TUP Coulomb gauge - gauge links only*/ rephase( OFF ); gaugefix(TUP,(Real)1.8,500,(Real)GAUGE_FIX_TOL); rephase( ON ); for(color=0;color<3;color++){ /* Make wall source */ FORALLSITES(i,s){ for(j=0;j<3;j++)s->phi.c[j]=cmplx(0.0,0.0); if( s->x%2==0 && s->y%2==0 && s->z%2==0 && s->t==0 ){ s->phi.c[color] = cmplx(-1.0,0.0); } } /* do a C.G. (source in phi, result in xxx) */ load_ferm_links(&fn_links); cgn = ks_congrad(F_OFFSET(phi),F_OFFSET(xxx),mass, niter, rsqprop, PRECISION, EVEN, &finalrsq, &fn_links); /* Multiply by -Madjoint, result in propmat[color] */ dslash_site( F_OFFSET(xxx), F_OFFSET(propmat[color]), ODD, &fn_links); scalar_mult_latvec( F_OFFSET(xxx), (Real)(-2.0*mass), F_OFFSET(propmat[color]), EVEN); } /* construct the diquark propagator--uses tempmat1 and do this before you fft the quark propagator */ FORALLSITES(i,s){ for(ca=0;ca<3;ca++)for(cb=0;cb<3;cb++){ ca1= (ca+1)%3; ca2= (ca+2)%3; cb1= (cb+1)%3; cb2= (cb+2)%3; CMUL((s->propmat[ca1].c[cb1]),(s->propmat[ca2].c[cb2]), (s->tempmat1.e[ca][cb])); CMUL((s->propmat[ca1].c[cb2]),(s->propmat[ca2].c[cb1]), cc); CSUB((s->tempmat1.e[ca][cb]),cc,(s->tempmat1.e[ca][cb])); } } /* complex conjugate the diquark prop */ FORALLSITES(i,s){ for(ca=0;ca<3;ca++)for(cb=0;cb<3;cb++){ CONJG((s->tempmat1.e[ca][cb]),(s->tempmat1.e[ca][cb])); } } /* Transform the diquark propagator. */ block_fourier( F_OFFSET(tempmat1), F_OFFSET(tempvec[0]), 3*sizeof(su3_vector), FORWARDS); /* complex conjugate the diquark prop. Now we have D(-k) for convolution */ FORALLSITES(i,s){ for(ca=0;ca<3;ca++)for(cb=0;cb<3;cb++){ CONJG((s->tempmat1.e[ca][cb]),(s->tempmat1.e[ca][cb])); } } /* Transform the propagator. */ block_fourier( F_OFFSET(propmat[0]), F_OFFSET(tempvec[0]), 3*sizeof(su3_vector), FORWARDS); /* CODE SPECIFIC TO PARTICULAR PARTICLES */ /* MESON CODE */ /* Square the result, component by component, sum over source and sink colors, result in ttt.c[0] */ FORALLSITES(i,s){ s->ttt.c[0].real = s->ttt.c[0].imag = 0.0; for(color=0;color<3;color++){ s->ttt.c[0].real += magsq_su3vec( &(s->propmat[color]) ); } }
int update() { int step, iters=0; int n; Real final_rsq; #ifdef HMC_ALGORITHM double startaction,endaction,d_action(); Real xrandom; #endif imp_ferm_links_t** fn; /* refresh the momenta */ ranmom(); /* In this application, the number of naik terms is 1 or 2 only */ n = fermion_links_get_n_naiks(fn_links); /* do "steps" microcanonical steps" */ for(step=1; step <= steps; step++){ #ifdef PHI_ALGORITHM /* generate a pseudofermion configuration only at start*/ /* also clear xxx, since zero is our best guess for the solution with a new random phi field. */ if(step==1){ restore_fermion_links_from_site(fn_links, PRECISION); fn = get_fm_links(fn_links); clear_latvec( F_OFFSET(xxx1), EVENANDODD ); grsource_imp( F_OFFSET(phi1), mass1, EVEN, fn[0]); clear_latvec( F_OFFSET(xxx2), EVENANDODD ); grsource_imp( F_OFFSET(phi2), mass2, EVEN, fn[n-1]); } #ifdef HMC_ALGORITHM /* find action */ /* do conjugate gradient to get (Madj M)inverse * phi */ if(step==1){ /* do conjugate gradient to get (Madj M)inverse * phi */ restore_fermion_links_from_site(fn_links, PRECISION); fn = get_fm_links(fn_links); iters += ks_congrad( F_OFFSET(phi1), F_OFFSET(xxx1), mass1, niter, nrestart, rsqmin, PRECISION, EVEN, &final_rsq, fn[0]); restore_fermion_links_from_site(fn_links, PRECISION); fn = get_fm_links(fn_links); iters += ks_congrad( F_OFFSET(phi2), F_OFFSET(xxx2), mass2, niter, nrestart, rsqmin, PRECISION, EVEN, &final_rsq, fn[n-1]); startaction=d_action(); /* copy link field to old_link */ gauge_field_copy( F_OFFSET(link[0]), F_OFFSET(old_link[0])); } #endif /* update U's to middle of interval */ update_u(0.5*epsilon); #else /* "R" algorithm */ /* first update the U's to special time interval */ /* and generate a pseudofermion configuration */ /* probably makes most sense if nflavors1 >= nflavors2 */ update_u(epsilon*(0.5-nflavors1/8.0)); clear_latvec( F_OFFSET(xxx1), EVENANDODD ); restore_fermion_links_from_site(fn_links, PRECISION); fn = get_fm_links(fn_links); grsource_imp( F_OFFSET(phi1), mass1, EVEN, fn[0]); update_u(epsilon*((nflavors1-nflavors2)/8.0)); clear_latvec( F_OFFSET(xxx2), EVENANDODD ); restore_fermion_links_from_site(fn_links, PRECISION); fn = get_fm_links(fn_links); grsource_imp( F_OFFSET(phi2), mass2, EVEN, fn[n-1]); /* update U's to middle of interval */ update_u(epsilon*nflavors2/8.0); #endif /* do conjugate gradient to get (Madj M)inverse * phi */ restore_fermion_links_from_site(fn_links, PRECISION); fn = get_fm_links(fn_links); if(n == 2){ iters += ks_congrad( F_OFFSET(phi1), F_OFFSET(xxx1), mass1, niter, nrestart, rsqmin, PRECISION, EVEN, &final_rsq, fn[0] ); iters += ks_congrad( F_OFFSET(phi2), F_OFFSET(xxx2), mass2, niter, nrestart, rsqmin, PRECISION, EVEN, &final_rsq, fn[1] ); } else { iters += ks_congrad_two_src( F_OFFSET(phi1), F_OFFSET(phi2), F_OFFSET(xxx1), F_OFFSET(xxx2), mass1, mass2, niter, nrestart, rsqmin, PRECISION, EVEN, &final_rsq, fn[0]); } dslash_site( F_OFFSET(xxx1), F_OFFSET(xxx1), ODD, fn[0]); dslash_site( F_OFFSET(xxx2), F_OFFSET(xxx2), ODD, fn[n-1]); /* now update H by full time interval */ update_h(epsilon); #if 0 #ifdef HAVE_QIO { char *filexml; char recxml[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><title>Test fermion force field</title>"; char ansfile[128]; char rootname[] = "fermion_force_dump"; /* Do this at the specified interval */ if(step%3 == 1){ /* Construct a file name */ sprintf(ansfile,"%s%02d",rootname,step); /* Dump the computed fermion force from the site structure */ filexml = create_QCDML(); save_color_matrix_scidac_from_site(ansfile, filexml, recxml, QIO_PARTFILE, F_OFFSET(mom[0]), 4, PRECISION); free_QCDML(filexml); } } #endif #endif /* update U's by half time step to get to even time */ update_u(epsilon*0.5); /* reunitarize the gauge field */ rephase( OFF ); reunitarize(); rephase( ON ); } /* end loop over microcanonical steps */ #ifdef HMC_ALGORITHM /* find action */ /* do conjugate gradient to get (Madj M)inverse * phi */ restore_fermion_links_from_site(fn_links, PRECISION); fn = get_fm_links(fn_links); iters += ks_congrad( F_OFFSET(phi1), F_OFFSET(xxx1), mass1, niter, nrestart, rsqmin, PRECISION, EVEN, &final_rsq, fn[0]); iters += ks_congrad( F_OFFSET(phi2), F_OFFSET(xxx2), mass2, niter, nrestart, rsqmin, PRECISION, EVEN, &final_rsq, fn[n-1]); endaction=d_action(); /* decide whether to accept, if not, copy old link field back */ /* careful - must generate only one random number for whole lattice */ if(this_node==0)xrandom = myrand(&node_prn); broadcast_float(&xrandom); if( exp( (double)(startaction-endaction) ) < xrandom ){ if(steps > 0) gauge_field_copy( F_OFFSET(old_link[0]), F_OFFSET(link[0]) ); #ifdef FN invalidate_fermion_links(fn_links); #endif node0_printf("REJECT: delta S = %e\n", (double)(endaction-startaction)); } else { node0_printf("ACCEPT: delta S = %e\n", (double)(endaction-startaction)); } #endif if(steps > 0)return (iters/steps); else return(-99); }