#include "mpi.h"
#include <stdio.h>
#define NELEM 20

int main(argc,argv)
  int argc;
  char *argv[];
{
  int numtasks, rank, source=0, dest, tag=1, i;

  typedef struct {
    float x, y, z;
    float velocity;
    int  n, type;
  }          Particle;
  Particle     p[NELEM], particles[NELEM];
  MPI_Datatype particletype, oldtypes[2]; 
  int          blockcounts[2];

/* MPI_Aint type used to be consistent with syntax of */
/* MPI_Type_extent routine */
  MPI_Aint    offsets[2], extent;
  MPI_Status stat;

  MPI_Init(&argc,&argv);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
 
/* Setup description of the 4 MPI_FLOAT fields x, y, z, velocity */
  offsets[0] = 0;
  oldtypes[0] = MPI_FLOAT;
  blockcounts[0] = 4;

/* Setup description of the 2 MPI_INT fields n, type */
/* Need to first figure offset by getting size of MPI_FLOAT */
  MPI_Type_extent(MPI_FLOAT, &extent);
  offsets[1] = 4 * extent;
  oldtypes[1] = MPI_INT;
  blockcounts[1] = 2;

/* Now define structured type and commit it */
  MPI_Type_struct(2, blockcounts, offsets, oldtypes, &particletype);
  MPI_Type_commit(&particletype);

/* Initialize the particle array and then send it to each task */
  if (rank == 0) {
    for (i=0; i<NELEM; i++) {
     particles[i].x = i * 1.0;
     particles[i].y = i * -1.0;
     particles[i].z = i * 1.0; 
     particles[i].velocity = 0.25;
     particles[i].n = i;
     particles[i].type = i % 2; 
    }
    for (i=0; i<numtasks; i++) 
     MPI_Send(particles, NELEM, particletype, i, tag, MPI_COMM_WORLD);
  }
 
  if (rank != 0) {
    MPI_Recv(p, NELEM, particletype, source, tag, MPI_COMM_WORLD, &stat);

/* Print a sample of what was received */
    printf("rank= %d   %3.2f %3.2f %3.2f %3.2f %d %d\n", rank,p[2].x,
         p[6].y,p[10].z,p[1].velocity,p[7].n,p[7].type);
  }

  MPI_Type_free(&particletype);
  MPI_Finalize();
}
