/*********************** io_lattice_generic.c *************************/
/* This reads and writes a (binary) lattice
 *
 * NOTE: THIS HAS TO BE ENCAPSULATED BY A FILE 
 * io_lattice.c 
 * WHICH DEFINES
 *
 * typedef struct { } allfields;
 *
 * void copy_fields(int site, allfields *s)    copy from all latfields to s.(whatever)
 * void set_fields(allfields *s, int site)     copy s.(stuff) to lattice fields
 *
 * #include "../generic/io_lattice_generic.c"
 */ 

/* read and write a binary lattice */

void restore_binary(FILE * f) 
{
  int currentnode,newnode,ok;
  int i,j,x[NDIM],dir,dims[NDIM],lbuf[4];
  allfields nf;
  float tf;

  if(this_node==0) {
    
    ok = (fread(dims,sizeof(int),NDIM,f) == NDIM);
    foralldir(i) if (dims[i] != lattice.size[i])
      halt("* Lattice size error");
  }
  currentnode=0;
  g_sync();

  forallcoordinates(x) {
    newnode=node_number(x);
    if(newnode != currentnode) {
      /* tell newnode it's OK to send */
      if( this_node==0 && newnode!=0 )send_field(lbuf,4,newnode);
      if( this_node==newnode && newnode!=0 )receive_field(lbuf,4);
      currentnode = newnode;
    }

    /* Node 0 reads, and sends site to correct node */
    if(this_node == 0) {
      if (fread(&nf[ibuf++],sizeof(allfields),1,f) != 1)
	halt("Read error in restore_binary");
      if (currentnode == 0) {	/* just copy links */
	i = node_index(x,&node);
	set_fields( &nf[ibuf++], i );
      } else {  /* send to correct node */
	send_field( &nf, sizeof(allfields), currentnode );
      }
    }

    /* The node which contains this site reads message */
    else {	/* for all nodes other than node 0 */
      if(this_node == currentnode){
	receive_field(&nf,sizeof(allfields));
	i = node_index(x,&node);
	set_fields( &nf, i );
      }
    }
  }

  g_sync();
  
}

void save_binary(FILE *f) 
{
  int currentnode,newnode,ok;
  int i,j,x[NDIM],dir,lbuf[4];
  allfields nf;

  /* node 0 does all the writing */
  if(this_node==0){
    if (fwrite(lattice.size,sizeof(int),NDIM,f) != NDIM)
      halt("Error in writing lattice header");
  }

  g_sync();
  currentnode=0;

  forallcoordinates(x) {
    newnode=node_number(x);
    if(newnode != currentnode){	/* switch to another node */
      /**g_sync();**/
      /* tell newnode it's OK to send */
      if( this_node==0 && newnode!=0 )send_field(lbuf,4,newnode);
      if( this_node==newnode && newnode!=0 )receive_field(lbuf,4);
      currentnode=newnode;
    }

    if (this_node==0){
      if (currentnode==0){
	i=node_index(x,&node);
	copy_fields( i, &nf );
      } else {
	receive_field(&nf,sizeof(allfields));
      }
    } else {	/* for nodes other than 0 */
      if(this_node==currentnode){
	i=node_index(x,&node);
	copy_fields( i, &nf );
	send_field(&nf,sizeof(allfields),0);
      }
    }

    if(this_node==0){
      if(fwrite(&nf,sizeof(allfields),1,f) != 1)
	halt("Write error in save_binary");
    }
  } /*close coordinate loop */

  /* if(this_node==0){printf("Body done\n"); fflush(stdout);} */
  g_sync();
}


