#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "fem.h"

#define CkPrintf CmiPrintf

void init(void)
{
  FEM_Print("init called\n");
  FEM_Set_Mesh(0,0,4,NULL);
}

typedef struct {
  int chunkNo;/*number of assocated chunk*/
  int n1;/*Length of first array below*/
  int n2;/*Length of second array below*/
  double *arr1; /*Some doubles, allocated on the heap*/
  int *arr2; /*Some ints, allocated on the heap*/
} my_block;

my_block *pup_my_block(pup_er p,my_block *m)
{
  const char *pt="unknown";

  if (pup_isUnpacking(p)) m=malloc(sizeof(my_block));

  pup_int(p,&m->chunkNo);
  if (pup_isUnpacking(p)) pt="unpacking";
  if (pup_isPacking(p)) pt="packing";
  if (pup_isSizing(p)) pt="sizing";
  CkPrintf("Chunk %d on %d> pup_my_block(%08x) called-- %s [%s]\n",
    m->chunkNo,CmiMyPe(),(int)m,pt,
    pup_isDeleting(p)?"deleting":"non-deleting");

  pup_int(p,&m->n1);
  pup_int(p,&m->n2);
  if (pup_isUnpacking(p)) {
         m->arr1=malloc(m->n1*sizeof(double));
         m->arr2=malloc(m->n2*sizeof(int));
  }
  pup_doubles(p,m->arr1,m->n1);
  pup_ints(p,m->arr2,m->n2);
  if (pup_isDeleting(p)) {
         free(m->arr1);
         free(m->arr2);
         free(m);
  }
  return m;
}

void driver(void)
{
  int i,t,udId;
  int myId = 1+FEM_My_Partition();
  my_block *m;
  FEM_Print("driver called\n");

  /*Build and initialize my heap data*/
  m=malloc(sizeof(my_block));
  m->chunkNo=myId;
  m->n1=93+(int)(40*sin(myId));
  m->n2=135+(int)(72*cos(myId));
  m->arr1=malloc(sizeof(double)*m->n1);
  for (i=0;i<m->n1;i++) m->arr1[i]=myId+i*i;
  m->arr2=malloc(sizeof(int)*m->n2);
  for (i=0;i<m->n2;i++) m->arr2[i]=myId+i*i;

  /*Register my heap data*/
  udId=FEM_Register(m,(FEM_PupFn)pup_my_block);
  
  for (t=0;t<20;t++) {
    /*Migrate*/
    CkPrintf("About to migrate; myId=%d\n",myId);
    FEM_Migrate();
    CkPrintf("Returned from migrate; myId=%d\n",myId);
    m=FEM_Get_Userdata(udId);

    /*Check if heap data made it*/
    for (i=0;i<m->n1;i++) 
      if (m->arr1[i]!=myId+i*i)
	CkPrintf("m->arr1 corrupted during %d migration!\n",myId);
    for (i=0;i<m->n2;i++) 
      if (m->arr2[i]!=myId+i*i)
	CkPrintf("m->arr2 corrupted during %d migration!\n",myId);
  }
}

void mesh_updated(int ts)
{
  FEM_Print("Mesh_updated called.  Why?\n");
}

void finalize(void)
{
  FEM_Print("finalize called\n");
}
