/* Test case for mpi_array_distrib.cpp
 *
 * To compile: 
 *  mpicxx  test_mpi_array_distrib.cpp general.cpp -o ../bin/test_mpi_array_distrib
 *
 */

#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include "general.h"

#define _PARALLEL
#include "mpi_array_distrib.cpp"

#define MASTER		0
#define Realloc(p,t,s) {p=(t *)realloc(p,sizeof(t)*s);}

int main (int argc, char *argv[])
{
    int _NX, _NY, _NZ, Ntot; /* size of array */
    double *_PHI, *buffer;
    MPI_Status status;
    int nDomains, domainID;
    int i, j, k;
    class Distributor3D *d;

    /***** Initializations *****/
    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &nDomains);

    MPI_Comm_rank(MPI_COMM_WORLD,&domainID);
    INFO_Printf("MPI task %d has started...\n", domainID);

    /* allocate array */
    //_NX = 40; _NY = 40; _NZ = 40;
    _NX = 8; _NY = 8; _NZ = 8;
    //_NX = 4; _NY = 4; _NZ = 4;
    Ntot = _NX*_NY*_NZ;

    Realloc(_PHI,double,Ntot);
    memset(_PHI,0,sizeof(double)*Ntot);

    Realloc(buffer,double,Ntot);
    memset(buffer,0,sizeof(double)*Ntot);

    /* construct distributor */
    d = new Distributor3D(_NX,_NY,_NZ,1,1,nDomains,2,nDomains,domainID);
    
    /***** Master task only ******/
    if (domainID == MASTER){
        for(i=0;i<_NX;i++)
            for(j=0;j<_NY;j++)
                for(k=0;k<_NZ;k++)
                    _PHI[i*_NY*_NZ+j*_NZ+k] = 10000*i+100*j+k;
    }  /* end of master section */

    /* print out distributor information */
    INFO_Printf("Domain [%d]: NXYZ(%d,%d,%d) ndom(%d,%d,%d) splitDim(%d)\n",
                d->domainID,d->NX,d->NY,d->NZ,d->ndomX,d->ndomY,d->ndomZ,d->splitDim);
    INFO_Printf("Domain [%d]: irange(%d,%d:%d,%d) jrange(%d,%d:%d,%d) krange(%d,%d:%d,%d)\n",
                d->domainID,d->ig0,d->in0,d->in1,d->ig1, d->jg0,d->jn0,d->jn1,d->jg1, d->kg0,d->kn0,d->kn1,d->kg1);

    d->distribute_array(_PHI, buffer);

    /* multiple -1.0 for all local elements */
    for(i=d->in0;i<d->in1;i++) for(j=d->jn0;j<d->jn1;j++) for(k=d->kn0;k<d->kn1;k++)
                _PHI[i*_NY*_NZ+j*_NZ+k] *= -1.0;

    d->collect_array(_PHI, buffer);

    d->update_neighbor(_PHI, buffer);

    //if (domainID == MASTER) {
    if (domainID == 1) {
        for(i=0;i<_NX;i++) for(j=0;j<_NY;j++) for(k=0;k<_NZ;k++)
               INFO_Printf("buf(%d,%d,%d) = %12f  _PHI(%d,%d,%d) = %12f\n", 
                           i,j,k, buffer[i*_NY*_NZ+j*_NZ+k],
                           i,j,k, _PHI[i*_NY*_NZ+j*_NZ+k]);
    }

    free(_PHI);
    free(buffer);

    MPI_Finalize();
}   /* end of main */


