Пример #1
0
MUST COMPILE WITH QIO FOR THE SCRATCH FILE
#endif

/* Comment these out if you want to suppress detailed timing */
/*#define IOTIME*/
/*#define PRTIME*/

int main(int argc, char *argv[])
{
  int meascount;
  int prompt;
  Real avm_iters,avs_iters;
  
  double starttime,endtime;
#ifdef IOTIME
  double dtime;
  int iotime = 1;
#else
  int iotime = 0;
#endif
  
  int MinCG,MaxCG;
  Real RsdCG, RRsdCG;
  
  int spin,color,j,k;
  int flag;
  int status;
  
  w_prop_file *fp_in_w[MAX_KAP];        /* For reading binary propagator files */
  w_prop_file *fp_out_w[MAX_KAP];       /* For writing binary propagator files */
  w_prop_file *fp_scr[MAX_KAP];
  quark_source wqs_scr;  /* scratch file */
  char scratch_file[MAX_KAP][MAXFILENAME];
  
  wilson_vector *psi = NULL;
  wilson_prop_field *quark_propagator = NULL;
  wilson_prop_field *quark_prop2 = NULL;
  int cg_cl = CL_CG;
  int source_type;
  
  initialize_machine(&argc,&argv);

  /* Remap standard I/O */
  if(remap_stdio_from_args(argc, argv) == 1)terminate(1);
  
  g_sync();
  /* set up */
  prompt = setup_cl();
  /* loop over input sets */
  
  psi = create_wv_field();
  quark_propagator = create_wp_field(3);
  quark_prop2 = create_wp_field(3);

  while( readin(prompt) == 0)
    {
      
      starttime=dclock();
      MaxCG=niter;
      
      avm_iters=0.0;
      meascount=0;
      
      spectrum_cl_hl_init();
  
      if( fixflag == COULOMB_GAUGE_FIX)
	{
	  if(this_node == 0) 
	    printf("Fixing to Coulomb gauge\n");
#ifdef IOTIME
	  dtime = -dclock();
#endif
	  gaugefix(TUP,(Real)1.5,500,GAUGE_FIX_TOL);
#ifdef IOTIME
	  dtime += dclock();
	  if(this_node==0)printf("Time to gauge fix = %e\n",dtime);
#endif
	  invalidate_this_clov(gen_clov);
	}
      else
	if(this_node == 0)printf("COULOMB GAUGE FIXING SKIPPED.\n");
      
      /* save lattice if requested */
      if( saveflag != FORGET ){
	savelat_p = save_lattice( saveflag, savefile, stringLFN );
      }
      
      if(this_node==0)printf("END OF HEADER\n");
      
      /*	if(this_node==0) printf("num_kap = %d\n", num_kap); */
      /* Loop over kappas to compute and store quark propagator */
      for(k=0;k<num_kap;k++){
	
	kappa=kap[k];
	RsdCG=resid[k];
	RRsdCG=relresid[k];
	if(this_node==0)printf("Kappa= %g r0= %g residue= %g rel= %g\n",
			       (double)kappa,(double)wqs.r0,(double)RsdCG,
			       (double)RRsdCG);
	
	/* open files for wilson propagators */
	
#ifdef IOTIME
	dtime = -dclock();
#endif
	wqstmp = wqs;  /* For clover_info.c */
	fp_in_w[k]  = r_open_wprop(startflag_w[k], startfile_w[k]);
	fp_out_w[k] = w_open_wprop(saveflag_w[k],  savefile_w[k],
				   wqs.type);
#ifdef IOTIME
	dtime += dclock();
	if(startflag_w[k] != FRESH)
	  node0_printf("Time to open prop = %e\n",dtime);
#endif
	
	/* Open scratch file and write header */
	sprintf(scratch_file[k],"%s_%02d",scratchstem_w,k);
	source_type = UNKNOWN;
	fp_scr[k] = w_open_wprop(scratchflag, scratch_file[k], source_type);
	init_qs(&wqs_scr);

	  
	/* Loop over source spins */
	for(spin=0;spin<4;spin++){
	  /* Loop over source colors */
	  for(color=0;color<3;color++){
	    meascount ++;
	    /*if(this_node==0)printf("color=%d spin=%d\n",color,spin);*/
	    
	    if(startflag_w[k] == CONTINUE)
	      {
		if(k == 0)
		  {
		    node0_printf("Can not continue propagator here! Zeroing it instead\n");
		    startflag_w[k] = FRESH;
		  }
		else
		  {
		    copy_wv_from_wp(psi, quark_propagator, color, spin);
		  }
	      }
	    
	    /* Saves one multiplication by zero in cgilu */
	    if(startflag_w[k] == FRESH)flag = 0;
	    else 
	      flag = 1;      
	    
	    /* load psi if requested */
	    status = reload_wprop_sc_to_field( startflag_w[k], fp_in_w[k], 
					       &wqs, spin, color, psi, iotime);
	    if(status != 0)
	      {
		node0_printf("control_cl_hl: Recovering from error by resetting initial guess to zero\n");
		reload_wprop_sc_to_field( FRESH, fp_in_w[k], &wqs,
					  spin, color, psi,0);
		flag = 0;
	      }
	    
	    /* Complete the source structure */
	    wqs.color = color;
	    wqs.spin = spin;
	    
	    /* If we are starting afresh, we set a minimum number
	       of iterations */
	    if(startflag_w[k] == FRESH || status != 0)MinCG = nt/2; 
	    else MinCG = 0;
	    
	    /* Load inversion control structure */
	    qic.prec = PRECISION;
	    qic.min = 0;
	    qic.max = MaxCG;
	    qic.nrestart = nrestart;
	    qic.parity = EVENANDODD;
	    qic.start_flag = flag;
	    qic.nsrc = 1;
	    qic.resid = RsdCG;
	    qic.relresid = RRsdCG;
	    
	    /* Load Dirac matrix parameters */
	    dcp.Kappa = kappa;
	    dcp.Clov_c = clov_c;
	    dcp.U0 = u0;
	    
	    switch (cg_cl) {
	    case BICG:
	      avs_iters =
		(Real)wilson_invert_field_wqs(&wqs, w_source_field, psi,
					      bicgilu_cl_field,
					      &qic,(void *)&dcp);
	      break;
	    case HOP:
	      avs_iters = 
		(Real)wilson_invert_field_wqs(&wqs, w_source_field, psi,
					      hopilu_cl_field,
					      &qic,(void *)&dcp);
	      break;
	    case MR:
	      avs_iters = 
		(Real)wilson_invert_field_wqs(&wqs, w_source_field, psi,
					      mrilu_cl_field,
					      &qic,(void *)&dcp);
		break;
	    case CG:
	      avs_iters = 
		(Real)wilson_invert_field_wqs(&wqs, w_source_field, psi,
					      cgilu_cl_field,
					      &qic,(void *)&dcp);
	      break;
	    default:
	      node0_printf("main(%d): Inverter choice %d not supported\n",
			   cg_cl, this_node);
	    }
	    
	    avm_iters += avs_iters;
	    
	    copy_wp_from_wv(quark_propagator, psi, color, spin);
	    
	    /* Write psi to scratch disk */
#ifdef IOTIME
	    dtime = -dclock();
#endif
	    save_wprop_sc_from_field(scratchflag, fp_scr[k], &wqs_scr,
				     spin, color, psi, "Scratch record", iotime);
#ifdef IOTIME
	    dtime += dclock();
	    if(this_node==0) 
	      printf("Time to dump prop spin %d color %d %e\n",
		     spin,color,dtime);
#endif
	    
	    /* save psi if requested */
	    save_wprop_sc_from_field( saveflag_w[k],fp_out_w[k], &wqs,
				      spin,color,psi,"", iotime);
	    
	  } /* source colors */
	} /* source spins */
	
	/* Close and release scratch file */
	w_close_wprop(scratchflag, fp_scr[k]);
	
	/*if(this_node==0)printf("Dumped prop to file  %s\n",
	  scratch_file[k]); */
	
	/* close files for wilson propagators */
#ifdef IOTIME
	dtime = -dclock();
#endif
	r_close_wprop(startflag_w[k],fp_in_w[k]);
	w_close_wprop(saveflag_w[k],fp_out_w[k]);
#ifdef IOTIME
	dtime += dclock();
	if(saveflag_w[k] != FORGET)
	  node0_printf("Time to close prop = %e\n",dtime);
#endif
	
      } /* kappas */
      
      
      /* Loop over heavy kappas for the point sink spectrum */
      for(k=0;k<num_kap;k++){
	
	/* Read the propagator from the scratch file */

#ifdef IOTIME
	dtime = -dclock();
#endif
	kappa=kap[k];
	init_qs(&wqs_scr);
	reload_wprop_to_wp_field(scratchflag, scratch_file[k], &wqs_scr,
				 quark_propagator, iotime);
#ifdef IOTIME
	dtime += dclock();
	if(this_node==0) 
	  {
	    printf("Time to read 12 spin,color combinations %e\n",dtime);
	    fflush(stdout);
	  }
#endif
	
	/*if(this_node==0)
	  printf("Closed scratch file %s\n",scratch_file[k]);
	  fflush(stdout); */
	
	/* Diagonal spectroscopy */
	spectrum_cl_hl_diag_baryon(quark_propagator, k);
	spectrum_cl_hl_diag_meson(quark_propagator, k);
	spectrum_cl_hl_diag_rot_meson(quark_propagator, k);
	if(strstr(spectrum_request,",sink_smear,") != NULL){
	  spectrum_cl_hl_diag_smeared_meson(quark_propagator, k);
	}
	
	/* Heavy-light spectroscopy */
	/* Loop over light kappas for the point sink spectrum */
	for(j=k+1;j<num_kap;j++){

#ifdef IOTIME
	  dtime = -dclock();
#endif
	  /* Read the propagator from the scratch file */
	  kappa=kap[j];
	  init_qs(&wqs_scr);
	  reload_wprop_to_wp_field(scratchflag,  scratch_file[j], &wqs_scr,
				   quark_prop2, iotime);
#ifdef IOTIME
	  dtime += dclock();
	  if(this_node==0) 
	    {
	      printf("Time to read 12 spin,color combinations %e\n",dtime);
	      fflush(stdout);
	    }
#endif
#ifdef PRTIME
	  dtime = -dclock();
#endif
	  spectrum_cl_hl_offdiag_baryon( quark_propagator, quark_prop2, 
					 j, k);
	  spectrum_cl_hl_offdiag_meson( quark_propagator, quark_prop2, 
					j, k);
	  spectrum_cl_hl_offdiag_rot_meson( quark_propagator, quark_prop2, 
					    j, k);
	  
#ifdef PRTIME
	  dtime = -dclock();
#endif
	} /* light kappas */
	
	/* Smear the heavy propagator in place */
	sink_smear_prop( quark_propagator );
	
	/* Write the smeared propagator to the scratch file (overwriting)*/
	
	kappa=kap[k];

#ifdef IOTIME
	dtime = -dclock();
#endif
	save_wprop_from_wp_field(scratchflag, scratch_file[k], &wqs_scr,
				 quark_propagator, "Scratch propagator", 
				 iotime);
	
#ifdef IOTIME
	dtime += dclock();
	if(this_node==0) 
	  {
	    printf("Time to dump convolution %d %e\n",k,dtime);
	    fflush(stdout);
	  }
#endif
      } /* heavy kappas */
      
      /* Loop over heavy kappas for the shell sink spectrum */
      if(strstr(spectrum_request,",sink_smear,") != NULL)
	for(k=0;k<num_kap;k++){
	  
#ifdef IOTIME
	  dtime = -dclock();
#endif
	  /* Read the propagator from the scratch file */
	  kappa=kap[k];
	  init_qs(&wqs_scr);
	  reload_wprop_to_wp_field(scratchflag,  scratch_file[k], &wqs_scr,
				   quark_propagator, iotime);
#ifdef IOTIME
	  dtime += dclock();
	  if(this_node==0) 
	    {
	      printf("Time to read convolution %d %e\n",k,dtime);
	      fflush(stdout);
	    }
#endif
	  
	  /* Diagonal spectroscopy */
	  spectrum_cl_hl_diag_smeared_meson(quark_propagator, k);
	  
	  /* Heavy-light spectroscopy */
	  /* Loop over light kappas for the shell sink spectrum */
	  for(j=k+1;j<num_kap;j++){
#ifdef PRTIME
	    dtime = -dclock();
#endif
	    /* Read the propagator from the scratch file */
	    kappa=kap[j];
	    init_qs(&wqs_scr);
	    reload_wprop_to_wp_field(scratchflag,  scratch_file[j], &wqs_scr,
				     quark_prop2, iotime);
	      
	    /* Compute the spectrum */
	    spectrum_cl_hl_offdiag_smeared_meson( quark_propagator,
						  quark_prop2, j, k);
	    
#ifdef PRTIME
	    dtime += dclock();
	    if(this_node==0) 
	      {
		printf("Time to read and do off diagonal mesons %d %d %e\n",
		       j,k,dtime);
		fflush(stdout);
	      }
#endif
	} /* light kappas */
	
      } /* heavy kappas */
      
      spectrum_cl_hl_print(wqs.t0);
      spectrum_cl_hl_cleanup();

      if(this_node==0)printf("RUNNING COMPLETED\n");
      if(meascount>0){
	if(this_node==0)printf("total cg iters for measurement= %e\n",
			       (double)avm_iters);
	if(this_node==0)printf("cg iters for measurement= %e\n",
			       (double)avm_iters/(double)meascount);
      }
      
      endtime=dclock();
      if(this_node==0){
	printf("Time = %e seconds\n",(double)(endtime-starttime));
	printf("total_iters = %d\n",total_iters);
      }
      fflush(stdout);
    }
      
  destroy_wv_field(psi);
  destroy_wp_field(quark_propagator);
  
  return 0;
}
Пример #2
0
int solve_ksprop(int num_prop, int startflag[], char startfile[][MAXFILENAME],
		 int saveflag[], char savefile[][MAXFILENAME],
		 ks_prop_field *ksprop[],
		 quark_source *my_ksqs,
		 quark_invert_control my_qic[],
		 ks_param my_ksp[],
		 Real charge,
		 Real bdry_phase[],
		 int r0[4],
		 int check)
{

  int color;
  int i,j;
  int status = 0;
  char *fileinfo;
  int tot_iters = 0;
  ks_prop_file *fp_in[MAX_PROP], *fp_out[MAX_PROP]; 
  su3_vector **dst, *src;
  imp_ferm_links_t **fn = NULL;
  Real mybdry_phase[4];
  imp_ferm_links_t **fn_multi = NULL;
  int n_naiks = fermion_links_get_n_naiks(fn_links);
  char myname[] = "solve_ksprop";

  /* Local copy of bdry_phase */
  for(i = 0; i < 4; i++)
    mybdry_phase[i] = bdry_phase[i];

  /* Offset for setting the staggered phases in FN links.
     They can be different for each propagator
     NO, they must be the same! */

//  r0[0] = my_ksqs->x0;
//  r0[1] = my_ksqs->y0;
//  r0[2] = my_ksqs->z0;
//  r0[3] = my_ksqs->t0;
  
  ksqstmp = *my_ksqs;     /* For ksprop_info. Source is common to the set */
  ksptmp  = my_ksp[0];      /* For action parameters */

  /* Open files for KS propagators, if requested */

  for(j = 0; j < num_prop; j++){
    fp_in[j]  = r_open_ksprop(startflag[j], startfile[j]);
    fp_out[j] = w_open_ksprop(saveflag[j],  savefile[j], VECTOR_FIELD_FILE);
  }

  /* Provision for writing the source to a file */
  
  if(my_ksqs->saveflag != FORGET){
    fileinfo = create_ks_XML();
    w_source_open_ks(my_ksqs, fileinfo);
    free(fileinfo);
  }
  
  /* Construct fermion links if we will need them */

  if(check != CHECK_NO || startflag[0] == FRESH ){

#ifdef U1_FIELD
    /* Apply U(1) phases if we are using it */
    u1phase_on(charge, u1_A);
    invalidate_fermion_links(fn_links);
#endif

    restore_fermion_links_from_site(fn_links, my_qic[0].prec);
    fn = get_fm_links(fn_links);

    /* Apply twisted boundary conditions and move KS phases and
       time boundary to new origin r0, if requested */
    /* This operation applies the phase to the boundary FN links */
    for(j = 0; j < n_naiks; j++){
      set_boundary_twist_fn(fn[j], mybdry_phase, r0);
      boundary_twist_fn(fn[j], ON);
    }

    /* Apply twist to the APE links */
    /* They do not carry the KS phases, but they do carry an antiperiodic bc */
    /* This operation applies the phase to the volume */
    //    mybdry_phase[3] = 0; 
    //    momentum_twist_links(mybdry_phase, 1, ape_links);
    //    mybdry_phase[3] = bdry_phase[3]; 
    boundary_twist_field( mybdry_phase, r0, 1, ape_links);

    /* Copy pointers for fermion links, based on Naik epsilon indices */
    fn_multi = (imp_ferm_links_t **)
      malloc(sizeof(imp_ferm_links_t *)*num_prop);
    for(j = 0; j < num_prop; j++)
      fn_multi[j] = fn[my_ksp[j].naik_term_epsilon_index];
    
  }

  /* Check (or produce) the solution if requested */
  for(color = 0; color < my_ksqs->ncolor; color++){
    
    node0_printf("%s: color = %d\n",myname, color);

    /* Load the propagators */

    for(j = 0; j < num_prop; j++){
      status = reload_ksprop_c_to_field(startflag[j], fp_in[j], my_ksqs, 
					color, ksprop[j]->v[color], 1);
      if(status != 0){
	node0_printf("Failed to reload propagator\n");
	terminate(1);
      }
    }
      
    /* Solve for the propagator if the starting guess is zero
       or we didn't say not to solve. */
    if(check != CHECK_NO || startflag[0] == FRESH){
      /* Create the source common to this inversion */
      src = create_v_field();

      if(v_source_field(src, my_ksqs)){
	printf("%s(%d): error getting source\n",myname,this_node);
	terminate(1);
      };
    
      /* Cache the source for writing to the propagator file */
      if(my_ksqs->saveflag != FORGET){
	alloc_cached_v_source(my_ksqs);
	copy_v_field(my_ksqs->v_src, src);
      }
      
      /* Write the source, if requested */
      if(my_ksqs->saveflag != FORGET){
	if(w_source_ks( src, my_ksqs ) != 0){
	  node0_printf("Error writing source\n");
	}
      }
      
      /* Make a list of num_prop solution pointers for the current color */
      dst = (su3_vector **)malloc(num_prop*sizeof(su3_vector *));
      for(j = 0; j < num_prop; j++){
	dst[j] = ksprop[j]->v[color];
      }
	
      if(check != CHECK_SOURCE_ONLY){

	/* Apply the momentum twist to the source.  This U(1) gauge
	   transformation converts the boundary twist on the gauge field
	   above into the desired volume twist. We do it this way to
	   make our coding compatible with QOP, which does only a
	   surface twist. */
	
	/* The time phase is special.  It is applied only on the
	   boundary, so we don't gauge-transform it to the volume here.
	   It is used only for switching between periodic and
	   antiperiodic bc's */
	
	mybdry_phase[3] = 0; 
	rephase_v_field(src, mybdry_phase, r0, 1);
	mybdry_phase[3] = bdry_phase[3]; 
	
	if(startflag[0] != FRESH){

	  /* Apply the momentum twist to the initial guess */
	  mybdry_phase[3] = 0; 
	  for(j = 0; j < num_prop; j++){
	    rephase_v_field(dst[j], mybdry_phase, r0, 1);
	  }
	  mybdry_phase[3] = bdry_phase[3]; 
	}

	if(num_prop == 1){
	  
	  /* Single mass inversion */
	  
	  if(startflag[0] == FRESH) my_qic[0].start_flag = START_ZERO_GUESS;
	  else                      my_qic[0].start_flag = START_NONZERO_GUESS;
	  
	  /* When we start from a preloaded solution we use the less
	     optimized mat_invert_cg_field algorithm, instead of
	     mat_invert_uml_field here to avoid "reconstructing", and so
	     overwriting the odd-site solution.  This would be a
	     degradation if the propagator was precomputed in double
	     precision, and we were doing single precision here. When we
	     are computing the propagator from a fresh start, we use
	     the optimized mat_invert_uml_field algorithm. */
	  
	  if(startflag[0] == FRESH){
	    tot_iters += mat_invert_uml_field(src, dst[0], 
	      my_qic+0, my_ksp[0].mass, fn_multi[0]);
	  } else {
	    tot_iters += mat_invert_cg_field(src, dst[0],
	     my_qic+0, my_ksp[0].mass, fn_multi[0]);
	  }
	} else {
	  
	  /* Multimass inversion */
	  tot_iters = 
	    mat_invert_multi(src, dst, my_ksp, num_prop, my_qic, fn_multi);
	}
	
	
	/* Transform solution, completing the U(1) gauge transformation */
	mybdry_phase[3] = 0; 
	for(j = 0; j < num_prop; j++){
	  rephase_v_field(dst[j], mybdry_phase, r0, -1);
	}
	mybdry_phase[3] = bdry_phase[3]; 
	
      } else { /* if(check != CHECK_SOURCE_ONLY) */

	/* Copy source to solution(s) so we can use it there */
	for(j = 0; j < num_prop; j++)
	  copy_v_field(dst[j], src);
	
      }

      /* save solutions if requested */
      for(i = 0; i < num_prop; i++){
	status = save_ksprop_c_from_field( saveflag[i], fp_out[i], my_ksqs, 
					   color, dst[i], "", 1);
	if(status != 0){
	  node0_printf("Failed to write propagator\n");
	  terminate(1);
	}
      }
      
#ifdef DEBUG_NAIVE
      rephase( OFF );
      for(i = 0; i < num_prop; i++)
	{
	  spin_wilson_vector *swv = create_swv_field();
	  wilson_vector *wv  = create_wv_field();
	  wilson_vector *wvsrc = create_wv_field();
	  su3_vector *v = create_v_field();
	  int ks_source_r[4] = {0,0,0,0};   /* Hypercube corners */
	  int spin;
	  
	  convert_ksprop_to_wprop_swv(swv, dst[i], ks_source_r, r0);
	  for(spin = 0; spin < 4; spin++){
	    copy_wv_from_swv(wv, swv, spin);
	    clear_wv_field(wvsrc);
	    copy_wv_from_v(wvsrc, src, spin);
	    check_naive(wv, wvsrc, my_ksp[i].mass, 1e-5);
	  }
	  
	  destroy_v_field(v);
	  destroy_wv_field(wv);
	  destroy_wv_field(wvsrc);
	  destroy_swv_field(swv);
	}
      rephase( ON );
#endif
      
      /* Clean up */
      free(dst);
      
      destroy_v_field(src);
      
    } /* if(check != CHECK_NO || startflag[0] == FRESH)} */

  } /* color */

  
  if(check != CHECK_NO || startflag[0] == FRESH ){

    /* Unapply twist to the APE links */
    //    mybdry_phase[3] = 0; 
    //    momentum_twist_links(mybdry_phase, -1, ape_links);
    //    mybdry_phase[3] = bdry_phase[3]; 
    boundary_twist_field( mybdry_phase, r0, -1, ape_links);

  /* Unapply twisted boundary conditions on the fermion links and
     restore conventional KS phases and antiperiodic BC, if
     changed. */
    for(j = 0; j < n_naiks; j++)
      boundary_twist_fn(fn[j], OFF);
  }
    
  for(i = 0; i < num_prop; i++){
    r_close_ksprop(startflag[i], fp_in[i]); 
    w_close_ksprop(saveflag[i],  fp_out[i]);
    if(saveflag[i] != FORGET)
      node0_printf("Saved propagator to %s\n",savefile[i]);
  }

  if(my_ksqs->saveflag != FORGET){
    w_source_close(my_ksqs);
  }
  
#ifdef U1_FIELD
  /* Unapply the U(1) field phases */
  u1phase_off();
  invalidate_fermion_links(fn_links);
#endif

  if(fn_multi != NULL)free(fn_multi);

  return tot_iters;

}
Пример #3
0
int main(int argc, char *argv[])
{
  int meascount;
  int prompt;
  Real avm_iters,avs_iters;
  
  double starttime,endtime;
#ifdef IOTIME
  double dtime;
  int iotime = 1;
#else
  int iotime = 0;
#endif
  
  int MaxCG;
  Real RsdCG, RRsdCG;
  
  int spin,color,k;
  int flag;

  int status;

  int cl_cg = CL_CG;

  w_prop_file *fp_in_w[MAX_KAP];        /* For propagator files */
  w_prop_file *fp_out_w[MAX_KAP];       /* For propagator files */

  wilson_vector *psi = NULL;
  wilson_prop_field quark_propagator = NULL;
  
  initialize_machine(&argc,&argv);
#ifdef HAVE_QDP
  QDP_initialize(&argc, &argv);
#endif
  /* Remap standard I/O */
  if(remap_stdio_from_args(argc, argv) == 1)terminate(1);
  
  g_sync();
  /* set up */
  prompt = setup_cl();
  /* loop over input sets */

  psi = create_wv_field();
  quark_propagator = create_wp_field();
  
  while( readin(prompt) == 0)
    {
      
      starttime=dclock();
      MaxCG=niter;
      wqstmp = wqs;  /* For clover_info.c */
      
      avm_iters=0.0;
      meascount=0;
      
      if( fixflag == COULOMB_GAUGE_FIX)
	{
	  if(this_node == 0) 
	    printf("Fixing to Coulomb gauge\n");
#ifdef IOTIME
	  dtime = -dclock();
#endif
	  gaugefix(TUP,(Real)1.5,500,GAUGE_FIX_TOL);
#ifdef IOTIME
	  dtime += dclock();
	  if(this_node==0)printf("Time to gauge fix = %e\n",dtime);
#endif
	  invalidate_this_clov(gen_clov);
	}
      else
	if(this_node == 0)printf("COULOMB GAUGE FIXING SKIPPED.\n");
      
      /* save lattice if requested */
      if( saveflag != FORGET ){
	savelat_p = save_lattice( saveflag, savefile, stringLFN );
      }
      
      if(this_node==0)printf("END OF HEADER\n");
      
      /*	if(this_node==0) printf("num_kap = %d\n", num_kap); */
      /* Loop over kappas */
      for(k=0;k<num_kap;k++){
	
	kappa=kap[k];
	RsdCG=resid[k];
	RRsdCG=relresid[k];
	if(this_node==0)printf("Kappa= %g r0= %g residue= %g rel= %g\n",
			       (double)kappa,(double)wqs.r0,(double)RsdCG,
			       (double)RRsdCG);
	
	/* open files for wilson propagators */
	
#ifdef IOTIME
	dtime = -dclock();
#endif
	fp_in_w[k]  = r_open_wprop(startflag_w[k], startfile_w[k]);
#ifdef IOTIME
	dtime += dclock();
	if(startflag_w[k] != FRESH)
	node0_printf("Time to open prop = %e\n",dtime);
#endif
	fp_out_w[k] = w_open_wprop(saveflag_w[k],  savefile_w[k],
				   wqs.type);
	
	
	/* Loop over source spins */
	for(spin=0;spin<4;spin++){
	  /* Loop over source colors */
	  for(color=0;color<3;color++){
	  
	    meascount ++;
	    /*if(this_node==0)printf("color=%d spin=%d\n",color,spin); */
	    if(startflag_w[k] == CONTINUE)
	      {
		node0_printf("Can not continue propagator here! Zeroing it instead\n");
		startflag_w[k] = FRESH;
	      }
	    
	    /* Saves one multiplication by zero in cgilu */
	    if(startflag_w[k] == FRESH)flag = 0;
	    else 
	      flag = 1;      
	    
	    /* load psi if requested */
	    status = reload_wprop_sc_to_field( startflag_w[k], fp_in_w[k], 
				       &wqs, spin, color, psi, iotime);

	    if(status != 0)
	      {
		node0_printf("control_cl: Recovering from error by resetting initial guess to zero\n");
		reload_wprop_sc_to_field( FRESH, fp_in_w[k], &wqs,
			       spin, color, psi, 0);
		flag = 0;
	      }

	    /* Complete the source structure */
	    wqs.color = color;
	    wqs.spin = spin;

	    /* Load inversion control structure */
	    qic.prec = PRECISION;
	    qic.max = MaxCG;
	    qic.nrestart = nrestart;
	    qic.resid = RsdCG;
	    qic.relresid = RRsdCG;
	    qic.start_flag = flag;
	    
	    /* Load Dirac matrix parameters */
	    dcp.Kappa = kappa;
	    dcp.Clov_c = clov_c;
	    dcp.U0 = u0;


	    /* compute the propagator.  Result in psi. */
	    
	    switch (cl_cg) {
	      case BICG:
		avs_iters =
		  (Real)wilson_invert_field_wqs(&wqs, w_source_field, psi,
						bicgilu_cl_field,
						&qic,(void *)&dcp);
		break;
	      case HOP:
		avs_iters = 
		  (Real)wilson_invert_field_wqs(&wqs, w_source_field, psi,
						hopilu_cl_field,
						&qic,(void *)&dcp);
		break;
	      case MR:
		avs_iters = 
		  (Real)wilson_invert_field_wqs(&wqs, w_source_field, psi,
						mrilu_cl_field,
						&qic,(void *)&dcp);
		break;
	      case CG:
		avs_iters = 
		  (Real)wilson_invert_field_wqs(&wqs, w_source_field, psi,
						cgilu_cl_field,
						&qic,(void *)&dcp);
		break;
	      default:
		node0_printf("main(%d): Inverter choice %d not supported\n",
			     this_node,cl_cg);
	      }

	    avm_iters += avs_iters;

	    copy_wp_from_wv(quark_propagator, psi, color, spin);
	    
	    /* save psi if requested */
	    save_wprop_sc_from_field( saveflag_w[k],fp_out_w[k], &wqs,
			     spin,color,psi,"Fill in record info here",iotime);
	  } /* source spins */
	} /* source colors */
	
	/* close files for wilson propagators */
	r_close_wprop(startflag_w[k],fp_in_w[k]);
#ifdef IOTIME
	dtime = -dclock();
#endif
	w_close_wprop(saveflag_w[k],fp_out_w[k]);
#ifdef IOTIME
      dtime += dclock();
      if(saveflag_w[k] != FORGET)
	node0_printf("Time to close prop = %e\n",dtime);
#endif
	
	/* spectrum, if requested */

	if(strstr(spectrum_request,",spectrum,") != NULL)
	  spectrum_cl(quark_propagator, wqs.t0, k);

      } /* kappas */


      if(this_node==0)printf("RUNNING COMPLETED\n");
      if(meascount>0){
	if(this_node==0)printf("total cg iters for measurement= %e\n",
			       (double)avm_iters);
	if(this_node==0)printf("cg iters for measurement= %e\n",
			       (double)avm_iters/(double)meascount);
      }
      
      endtime=dclock();
      if(this_node==0){
	printf("Time = %e seconds\n",(double)(endtime-starttime));
	printf("total_iters = %d\n",total_iters);
      }
      fflush(stdout);
      
    }

  destroy_wv_field(psi);
  destroy_wp_field(quark_propagator);
  return 0;
}