/******************  com_vanilla.c ***************************************
 * 
 *  Communications routines, for single node interface
 *
 *

   g_sync() provides a synchronization point for all nodes.
   g_floatsum() sums a floating point number over all nodes.
   g_doublesum() sums a double over all nodes.
   g_vecdoublesum() sums a vector of doubles over all nodes.
   g_floatmax() finds maximum of a floating point number over all nodes.
   g_doublemax() finds maximum of a double over all nodes.
   broadcast_float()  broadcasts a single precision number from
	node 0 to all nodes.
   broadcast_double()  broadcasts a double precision number
   send_integer() sends an integer to one other node
   receive_integer() receives an integer
   terminate() kills the job on all processors

   start_gather() starts asynchronous sends and receives required
   to gather neighbors.
   wait_gather()  waits for receives to finish, insuring that the
   data has actually arrived.

   send_field() sends a field to one other node.
   receive_field() receives a field from some other node.
*/

/* load in definitions, variables etc. */

#include "comdefs.h"
#include "generic.h"

#define MIN_GATHER_INDEX 100
#define MAX_GATHER_INDEX 7100    /* allows 7000 concurrent gathers */
#define FIELD_TYPE 11            /* used in send/receive field */
#define SEND_INTEGER_TYPE 12     /* used in send/receive int */

#define SEND_FLAG 1              /* flags for marking msg_tags */
#define RECEIVE_FLAG 2
#define END_FLAG 3


extern comlist_struct *comlist;   /* the comlist variables in layout */


/************************************************************************/

/* Machine initialization */
#include <sys/types.h>
void initialize_machine(argc,argv) int argc; char **argv; {
  /* MPI_Init(&argc,&argv); */
}


/* GATHER ROUTINES */
/* start_gather() returns a pointer to a list of msg_tag's, which
   be used as input to subsequent wait_gather().

   This list contains msg_tags for all receive buffers, followed by
   end flag.

   If no messages at all are required, the routine will return NULL.
   msg_buf=NULL should be a reliable indicator of no message.

   usage:  tag = start_gather( source, size, direction, parity )
*/

msg_tag * start_gather( field, size, dir, parity )
     /* arguments */
     char * field;      /* pointer to some latfield */
     int size;		/* size in bytes of the field (eg sizeof(su3_vector))*/
     int dir;		/* direction to gather from. eg XUP - index into
			   neighbor tables */
     int parity;	/* parity of sites whose neighbors we gather.
			   one of EVEN, ODD or EVENODD (EVEN+ODD). */
{
  return((msg_tag *)NULL);
}


msg_tag * wait_gather( msg_tag *mbuf ) 
{
  if (mbuf == NULL) return((msg_tag *)NULL);
  halt ("Wait in com_vanilla!  Never happens! ");
  return((msg_tag *)NULL);
}


/***************************************************/

msg_tag * start_scatter( field, size, dir, parity )
     char * field;      /* pointer to some latfield */
     int size;		/* size in bytes of the field (eg sizeof(su3_vector))*/
     int dir;		
     int parity;	/* parity of sites whose neighbors we scatter
			   one of EVEN or ODD  */
{
  return((msg_tag *)NULL);
}

msg_tag * wait_scatter( msg_tag *mbuf ) 
{
  if (mbuf == NULL) return((msg_tag *)NULL);
  halt ("Wait in com_vanilla!  Never happens! ");
  return((msg_tag *)NULL);
}

/***************************************************/


/* SEND AND RECEIVE FIELD */
/* send_field is to be called only by the node doing the sending */
/* get_field is to be called only by the node to which the field was sent */
void send_field(buf,size,tonode) 
     void *buf; int size,tonode; 
{
  /* MPI_Send(buf,size,MPI_BYTE,tonode,FIELD_TYPE,MPI_COMM_WORLD); */
}
void receive_field(buf,size) 
     void *buf; int size; 
{
  /* MPI_Status status;
     MPI_Recv(buf,size,MPI_BYTE,MPI_ANY_SOURCE,FIELD_TYPE,
     MPI_COMM_WORLD,&status);
  */
}

/* BASIC COMMUNICATIONS FUNCTIONS */

/* Tell what kind of machine we are on */
static char name[]="Single node (vanilla)";
char * machine_type(){
  return(name);
}

/* Return my node number */
int mynode()
{
  return( 0 );
}

/* Return number of nodes */
int numnodes()
{
  return( 1 );
}

/* Synchronize all nodes */
void g_sync() {}

/* Sum float over all nodes to node 0 */
void g_floatsum( float * fpt, int dist ) {}

/* Sum double over all nodes */
void g_doublesum( double * dpt, int dist ) {}

/* Sum a vector of doubles over all nodes */
void g_vecintsum( int *dpt, int nfloats, int dist ) {} 

/* Sum a vector of doubles over all nodes */
void g_vecfloatsum( float *dpt, int nfloats, int dist ) {} 

/* Sum a vector of doubles over all nodes */
void g_vecdoublesum( double *dpt, int ndoubles, int dist ) {}

/* Find maximum of float over all nodes */
void g_floatmax( float * fpt ) {}

/* Find maximum of double over all nodes */
void g_doublemax( double *dpt ) {}

/* Broadcast a whole field */
void broadcast_field(void *pt, int size) {}

/* Broadcast floating point number from node zero */
void broadcast_float(float *fpt) {}

/* Broadcast double precision floating point number from node zero */
void broadcast_double( double *dpt ) {}

/* Broadcast double precision floating point number from node zero */
void broadcast_int( int *dpt ) {}

/* Send an integer to one other node */
/* This is to be called only by the node doing the sending */
void send_integer(tonode,address) 
     int tonode; int *address; 
{ }

/* Receive an integer from another node */
/* Note we do not check if this was really meant for us */
void receive_integer(address) 
     int *address; 
{ }

/* version of exit for multinode processes -- kill all nodes */
void terminate(int status)
{
  printf("Termination: node %d, status = %d\n",this_node,status);
  exit(status);
}

/* clean exit from all nodes */
void finishrun() 
{
  exit(1);
}
