double imp_gauge_action() { register int i; int rep; register site *s; complex trace; double g_action; double action,act2,total_action; su3_matrix *tempmat1; int length; /* these are for loop_table */ int ln,iloop; g_action=0.0; tempmat1 = (su3_matrix *)special_alloc(sites_on_node*sizeof(su3_matrix)); if(tempmat1 == NULL){ printf("imp_gauge_action: Can't malloc temporary\n"); terminate(1); } /* gauge action */ for(iloop=0;iloop<NLOOP;iloop++){ length=loop_length[iloop]; /* loop over rotations and reflections */ for(ln=0;ln<loop_num[iloop];ln++){ path_product( loop_table[iloop][ln] , length, tempmat1 ); FORALLSITES(i,s){ trace=trace_su3( &tempmat1[i] ); action = 3.0 - (double)trace.real; /* need the "3 -" for higher characters */ total_action= (double)loop_coeff[iloop][0]*action; act2=action; for(rep=1;rep<NREPS;rep++){ act2 *= action; total_action += (double)loop_coeff[iloop][rep]*act2; } g_action += total_action; } END_LOOP /* sites */ } /* ln */ } /* iloop */
double imp_gauge_action() { register int i; int rep; register site *s; complex trace; double g_action; double action,act2,total_action; int length; /* these are for loop_table */ int ln,iloop; g_action=0.0; /* gauge action */ for(iloop=0;iloop<NLOOP;iloop++){ length=loop_length[iloop]; /* loop over rotations and reflections */ for(ln=0;ln<loop_num[iloop];ln++){ path_product( loop_table[iloop][ln] , length ); FORALLSITES(i,s){ trace=trace_su3( &s->tempmat1 ); action = 3.0 - (double)trace.real; /* need the "3 -" for higher characters */ total_action= (double)loop_coeff[iloop][0]*action; act2=action; for(rep=1;rep<NREPS;rep++){ act2 *= action; total_action += (double)loop_coeff[iloop][rep]*act2; } g_action += total_action; } END_LOOP /* sites */ } /* ln */ } /* iloop */
void hybrid_loop1(int tot_smear) { char myname[] = "hybrid_loop1"; register int i,j,dir,r,t; int dir1=0,dir2=0,trans_path1=0,trans_path2=0; int disp[4]; int nth,nxh; register site *s; su3_matrix tmat1,tmat2; su3_matrix *tmatp; Real *wils_loop1; su3_matrix *flux_links_f; su3_matrix *trans_links, *trans_links_f; su3_matrix *flux_links; su3_matrix *tempmat1; /* Names of messages used to index "mtag" and "gen_pt" */ /* NMSGS must not exceed N_POINTERS */ enum{ M_S_LINK, M_F_LINKS_F, M_T_LINKS_F, M_STAP_POS1, M_STAP_NEG1, M_STAP_POS2, M_STAP_NEG2, NMSGS }; msg_tag *mtag[NMSGS]; /* Names of flux tube shapes built from transverse links and on-axis links used to index "flux_links" */ enum{ S_LINK, STAP_POS1, STAP_NEG1, STAP_POS2, STAP_NEG2, NFLUX }; /* Names of transverse links used to index "trans_path", "trans_links" and "trans_links_f" */ enum{ XX, YY, ZZ, NTRANS }; /* Names of space-shifted transverse links */ /* used to index "trans_links_f" */ enum{ TRANS_PATH1_F, TRANS_PATH2_F, T_LINK_F, NTRANS_F }; /* Paths for transverse links */ const link_path trans_path[NTRANS] = { { "XX", 2, {2,0,0,0}, {XUP, XUP, NODIR, NODIR} }, { "YY", 2, {0,2,0,0}, {YUP, YUP, NODIR, NODIR} }, { "ZZ", 2, {0,0,2,0}, {ZUP, ZUP, NODIR, NODIR} } }; /* Names of flux tube shapes transported forward in time */ /* Used to index "flux_links_f" */ enum{ S_LINK_F, STAP_POS1_F, NFLUX_F }; /* Names of loop observables */ /* Used to index "wils_loop1" */ enum{ W_LOOP1, STAP_SIG_GP1, STAP_PI_U1, STAP_DELTA_G1, NWLOOP1 }; /* Check the rules */ if(NMSGS > N_POINTERS){ if(this_node == 0)fprintf(stderr,"%s: Aborted. gen_pt array too small.",myname); terminate(1); } if( nx != ny || nx != ny){ if(this_node == 0)fprintf(stderr,"%s: Aborted. requires nx=ny=nz",myname); terminate(1); } /* Allocate space for observables */ //AB nth = nt/2; nxh = nx/2; //CD nth = nt; nxh = nx/2; nth = max_t; nxh = nx/2; wils_loop1 = (Real *)malloc(nth*nxh*sizeof(Real)*NWLOOP1); if(wils_loop1 == NULL){ fprintf(stderr,"%s: CAN'T MALLOC wils_loop1\n",myname); fflush(stderr); terminate(1); } for(i=0;i<NWLOOP1;i++) for(t=0;t<nth;t++) for(r=0;r<nxh;r++) WILS_LOOP1(i,t,r) = 0.0; /* Allocate space for timeward shifted flux tube shapes */ flux_links_f = (su3_matrix *)malloc(sites_on_node*sizeof(su3_matrix)*NFLUX_F); if(flux_links_f == NULL){ fprintf(stderr,"%s: CAN'T MALLOC flux_links_f\n",myname); fflush(stderr); terminate(1); } /* Allocate space for transverse link products */ trans_links = (su3_matrix *)malloc(NTRANS*sites_on_node*sizeof(su3_matrix)); if(trans_links == NULL){ fprintf(stderr,"%s: CAN'T MALLOC trans_links\n",myname); fflush(stderr); terminate(1); } /* Allocate space for shifted auxiliary link products */ trans_links_f = (su3_matrix *)malloc(NTRANS_F*sites_on_node*sizeof(su3_matrix)); if(trans_links_f == NULL){ fprintf(stderr,"%s: CAN'T MALLOC trans_links_f\n",myname); fflush(stderr); terminate(1); } tempmat1 = (su3_matrix *)malloc(sites_on_node*sizeof(su3_matrix)); if(tempmat1 == NULL){ printf("%s(%d): Can't malloc temporary\n",myname,this_node); terminate(1); } /* Compute and store products of transverse links */ /* trans_links[i][j] is set to the link product for the jth path type that ends at site i */ for(j = 0; j < NTRANS; j++){ path_product(trans_path[j].dir, trans_path[j].length, tempmat1); FORALLSITES(i,s){ su3mat_copy(tempmat1+i, TRANS_LINKS(i,j)); } }
/* update the momenta with the gauge force */ void QOP_symanzik_1loop_gauge_force(QOP_info_t *info, QOP_GaugeField *gauge, QOP_Force *force, QOP_gauge_coeffs_t *coeffs, Real eps) { register int i,dir; register site *st; su3_matrix tmat1; register Real eb3; /* Note: eps now includes eps*beta */ register su3_matrix* momentum; su3_matrix *staple, *tempmat1; /* lengths of various kinds of loops */ int *loop_length = get_loop_length(); /* number of rotations/reflections for each kind */ int *loop_num = get_loop_num(); /* table of directions, 1 for each kind of loop */ int ***loop_table = get_loop_table(); /* table of coefficients in action, for various "representations" (actually, powers of the trace) */ Real **loop_coeff = get_loop_coeff(); /* We make our own */ int max_length = get_max_length(); /* For Symanzik 1 loop! */ int nloop = get_nloop(); int nreps = get_nreps(); su3_matrix *forwardlink[4]; su3_matrix *tmpmom[4]; int nflop = 153004; /* For Symanzik1 action */ Real final_flop; double dtime; int j,k; int *dirs,length; int *path_dir,path_length; int ln,iloop; Real action,act2,new_term; int ncount; char myname[] = "imp_gauge_force"; dtime=-dclock(); info->status = QOP_FAIL; /* Parity requirements */ if(gauge->evenodd != QOP_EVENODD || force->evenodd != QOP_EVENODD ) { printf("QOP_asqtad_force: Bad parity gauge %d force %d\n", gauge->evenodd, force->evenodd); return; } /* Map field pointers to local static pointers */ FORALLUPDIR(dir){ forwardlink[dir] = gauge->g + dir*sites_on_node; tmpmom[dir] = force->f + dir*sites_on_node; } /* Check loop coefficients */ if(coeffs->plaquette != loop_coeff[0][0] || coeffs->rectangle != loop_coeff[1][0] || coeffs->parallelogram != loop_coeff[2][0]) { printf("%s(%d): Path coeffs don't match\n",myname,this_node); return; } /* Allocate arrays according to action */ dirs = (int *)malloc(max_length*sizeof(int)); if(dirs == NULL){ printf("%s(%d): Can't malloc dirs\n",myname,this_node); return; } path_dir = (int *)malloc(max_length*sizeof(int)); if(path_dir == NULL){ printf("%s(%d): Can't malloc path_dir\n",myname,this_node); return; } staple = (su3_matrix *)special_alloc(sites_on_node*sizeof(su3_matrix)); if(staple == NULL){ printf("%s(%d): Can't malloc temporary\n",myname,this_node); return; } tempmat1 = (su3_matrix *)special_alloc(sites_on_node*sizeof(su3_matrix)); if(tempmat1 == NULL){ printf("%s(%d): Can't malloc temporary\n",myname,this_node); return; } eb3 = eps/3.0; /* Loop over directions, update mom[dir] */ for(dir=XUP; dir<=TUP; dir++){ FORALLSITES(i,st)for(j=0;j<3;j++)for(k=0;k<3;k++){ staple[i].e[j][k]=cmplx(0.0,0.0); } END_LOOP ncount=0; for(iloop=0;iloop<nloop;iloop++){ length=loop_length[iloop]; for(ln=0;ln<loop_num[iloop];ln++){ /**printf("UPD: "); printpath( loop_table[iloop][ln], length );**/ /* set up dirs. we are looking at loop starting in "XUP" direction, rotate so it starts in "dir" direction. */ for(k=0;k<length;k++){ if( GOES_FORWARDS(loop_table[iloop][ln][k]) ){ dirs[k]=(dir+loop_table[iloop][ln][k] )% 4; } else { dirs[k]=OPP_DIR( (dir+OPP_DIR(loop_table[iloop][ln][k]))%4 ); } } path_length= length-1; /* generalized "staple" */ /* check for links in direction of momentum to be updated, each such link gives a contribution. Note the direction of the path - opposite the link. */ for(k=0;k<length;k++)if( dirs[k]==dir||dirs[k]==OPP_DIR(dir)) { if( GOES_FORWARDS(dirs[k]) ) for(j=0;j<path_length;j++) { path_dir[j] = dirs[(k+j+1)%length]; } if( GOES_BACKWARDS(dirs[k]) ) for(j=0;j<path_length;j++) { path_dir[path_length-1-j] = OPP_DIR(dirs[(k+j+1)%length]); } /**if(dir==XUP)printf("X_UPDATE PATH: "); printpath( path_dir, path_length );**/ path_product(path_dir,path_length, tempmat1); /* We took the path in the other direction from our old convention in order to get it to end up "at our site", so now take adjoint */ /* then compute "single_action" contribution to staple */ FORALLSITES(i,st){ su3_adjoint( &(tempmat1[i]), &tmat1 ); /* first we compute the fundamental term */ new_term = loop_coeff[iloop][0]; /* now we add in the higher representations */ if(nreps > 1){ node0_printf("WARNING: THIS CODE IS NOT TESTED\n"); exit(0); act2=1.0; action = 3.0 - realtrace_su3(forwardlink[dir]+i, &tmat1 ); for(j=1;j<nreps;j++){ act2 *= action; new_term += loop_coeff[iloop][j]*act2*(Real)(j+1); } } /* end if nreps > 1 */ scalar_mult_add_su3_matrix( &(staple[i]), &tmat1, new_term, &(staple[i]) ); } END_LOOP ncount++; } /* k (location in path) */ } /* ln */ } /* iloop */ /* Now multiply the staple sum by the link, then update momentum */ FORALLSITES(i,st){ mult_su3_na( forwardlink[dir]+i, &(staple[i]), &tmat1 ); momentum = tmpmom[dir] + i; scalar_mult_sub_su3_matrix( momentum, &tmat1, eb3, momentum ); } END_LOOP
/* update the momenta with the gauge force */ void imp_gauge_force_cpu( Real eps, field_offset mom_off ){ register int i,dir; register site *st; su3_matrix tmat1,tmat2; register Real eb3; register anti_hermitmat* momentum; su3_matrix *staple, *tempmat1; /* lengths of various kinds of loops */ int *loop_length = get_loop_length(); /* number of rotations/reflections for each kind */ int *loop_num = get_loop_num(); /* table of directions, 1 for each kind of loop */ int ***loop_table = get_loop_table(); /* table of coefficients in action, for various "representations" (actually, powers of the trace) */ Real **loop_coeff = get_loop_coeff(); int max_length = get_max_length(); int nloop = get_nloop(); int nreps = get_nreps(); #ifdef GFTIME int nflop = 153004; /* For Symanzik1 action */ double dtime; #endif int j,k; int *dirs,length; int *path_dir,path_length; int ln,iloop; Real action,act2,new_term; int ncount; char myname[] = "imp_gauge_force"; #ifdef GFTIME dtime=-dclock(); #endif dirs = (int *)malloc(max_length*sizeof(int)); if(dirs == NULL){ printf("%s(%d): Can't malloc dirs\n",myname,this_node); terminate(1); } path_dir = (int *)malloc(max_length*sizeof(int)); if(path_dir == NULL){ printf("%s(%d): Can't malloc path_dir\n",myname,this_node); terminate(1); } staple = (su3_matrix *)special_alloc(sites_on_node*sizeof(su3_matrix)); if(staple == NULL){ printf("%s(%d): Can't malloc temporary\n",myname,this_node); terminate(1); } tempmat1 = (su3_matrix *)special_alloc(sites_on_node*sizeof(su3_matrix)); if(tempmat1 == NULL){ printf("%s(%d): Can't malloc temporary\n",myname,this_node); terminate(1); } eb3 = eps*beta/3.0; /* Loop over directions, update mom[dir] */ for(dir=XUP; dir<=TUP; dir++){ FORALLSITES(i,st)for(j=0;j<3;j++)for(k=0;k<3;k++){ staple[i].e[j][k]=cmplx(0.0,0.0); } END_LOOP ncount=0; for(iloop=0;iloop<nloop;iloop++){ length=loop_length[iloop]; for(ln=0;ln<loop_num[iloop];ln++){ /**printf("UPD: "); printpath( loop_table[iloop][ln], length );**/ /* set up dirs. we are looking at loop starting in "XUP" direction, rotate so it starts in "dir" direction. */ for(k=0;k<length;k++){ if( GOES_FORWARDS(loop_table[iloop][ln][k]) ){ dirs[k]=(dir+loop_table[iloop][ln][k] )% 4; } else { dirs[k]=OPP_DIR( (dir+OPP_DIR(loop_table[iloop][ln][k]))%4 ); } } path_length= length-1; /* generalized "staple" */ /* check for links in direction of momentum to be updated, each such link gives a contribution. Note the direction of the path - opposite the link. */ for(k=0;k<length;k++)if( dirs[k]==dir||dirs[k]==OPP_DIR(dir)) { if( GOES_FORWARDS(dirs[k]) ) for(j=0;j<path_length;j++) { path_dir[j] = dirs[(k+j+1)%length]; } if( GOES_BACKWARDS(dirs[k]) ) for(j=0;j<path_length;j++) { path_dir[path_length-1-j] = OPP_DIR(dirs[(k+j+1)%length]); } /**if(dir==XUP)printf("X_UPDATE PATH: "); printpath( path_dir, path_length );**/ path_product(path_dir,path_length, tempmat1); /* We took the path in the other direction from our old convention in order to get it to end up "at our site", so now take adjoint */ /* then compute "single_action" contribution to staple */ FORALLSITES(i,st){ su3_adjoint( &(tempmat1[i]), &tmat1 ); /* first we compute the fundamental term */ new_term = loop_coeff[iloop][0]; /* now we add in the higher representations */ if(nreps > 1){ node0_printf("WARNING: THIS CODE IS NOT TESTED\n"); exit(0); act2=1.0; action = 3.0 - realtrace_su3(&(st->link[dir]), &tmat1 ); for(j=1;j<nreps;j++){ act2 *= action; new_term += loop_coeff[iloop][j]*act2*(Real)(j+1); } } /* end if nreps > 1 */ scalar_mult_add_su3_matrix( &(staple[i]), &tmat1, new_term, &(staple[i]) ); } END_LOOP ncount++; } /* k (location in path) */ } /* ln */ } /* iloop */ /* Now multiply the staple sum by the link, then update momentum */ FORALLSITES(i,st){ mult_su3_na( &(st->link[dir]), &(staple[i]), &tmat1 ); momentum = (anti_hermitmat *)F_PT(st,mom_off); uncompress_anti_hermitian( &momentum[dir], &tmat2 ); scalar_mult_sub_su3_matrix( &tmat2, &tmat1, eb3, &(staple[i]) ); make_anti_hermitian( &(staple[i]), &momentum[dir] ); } END_LOOP