//

// a program to distribute an array to one or more processes and multiply by 2o

// and return to the root (rank=0) process.

// illustrates the use of MPI_Send and MPI_Recv

//

// a part is included to display unique file creation in the execution host

// temporary data space /data/$USER

//

#include <string.h>

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#include <mpi.h>

int main(int argc,char *argv[]){

int nstep=1000;

double r1[nstep],r2[nstep],r3[nstep];

int myid,numprocs,itag;

MPI_Status *status;

int nsendcnt,nsend,nrcv,nrcv2,i,j;

char *user,*filename;

FILE *unit8;

//

MPI_Init(&argc,&argv);

MPI_Comm_rank( MPI_COMM_WORLD, &myid);

MPI_Comm_size( MPI_COMM_WORLD, &numprocs);

printf(" process %d of %d exists \n",myid,numprocs);

//

if(myid == 0){

for(i=0;i<nstep;i++){

r1[i]=drand48();

r2[i]=0.0;

r3[i]=0.0;

}

for(i=0;i<nstep;i=i+100){

printf(" start %d: %d %e\n",myid,i,r1[i]);

}

}else{

printf (" %d waiting \n",myid);

}

printf (" %d before barrier \n",myid);

int impi = MPI_Barrier(MPI_COMM_WORLD);

printf (" %d after barrier %d\n",myid,impi);

nsendcnt=(nstep+numprocs-1)/numprocs;

nrcv=myid*nsendcnt+1;

nrcv2=nrcv+nsendcnt-1;

if( nstep < nrcv2 ){nrcv2=nstep;}

nsend=nrcv2-nrcv+1;

itag=1;

printf(" myid data %d: %d,%d,%d\n",myid,nrcv,nrcv2,nsend);

if(myid == 0){

for(i=2;i<=numprocs;i++){

nsendcnt=(nstep+numprocs-1)/numprocs;

nrcv=(i-1)*nsendcnt+1;

nrcv2=nrcv+nsendcnt-1;

if( nstep < nrcv2 ){nrcv2=nstep;}

nsend=nrcv2-nrcv+1;

for(j=nrcv-1;j<nrcv2;j++){

r3[j-nrcv+1]=r1[j];

}

MPI_Send(r3,nsend,MPI_DOUBLE,i-1,itag,MPI_COMM_WORLD);

printf(" 0 sent %d to %d \n",nsend,i-1);

}

}else{

printf(" %d about to recv %d,%d\n",myid,nrcv,nsend);

MPI_Recv(r3,nsend,MPI_DOUBLE,0,itag,MPI_COMM_WORLD,MPI_STATUS_IGNORE);

// MPI_Recv(r3,nsend,MPI_DOUBLE,0,itag,MPI_COMM_WORLD,status);

printf(" %d recved %d from 0\n",myid,nsend);

//

//begin part which shows local (unique) file creation based on rank

//

//presumably you know who you are and can start with filename='/data/aznn/file'

//where aznn=$USER (echo $USER in a command shell)

// filename=malloc(1024);

// user=getenv( "USER" );

// if( user != NULL & filename != NULL){

// if(strlen(user) > 100){user[100]='\0';}

// printf(" %d: user:%s\n",myid,user);

//create /data/$USER or start with '/data/$USER/file"

// snprintf(filename,200,"%s%s%s%d","/data/",user,"/file",myid+1);

//now have made file=/data/$USER/filenn

//open the file and write data and close file

// printf (" %d:filename is %s\n",myid,filename);

// unit8= fopen(filename,"w");

// for(i=0;i<nsend;i++){

// fprintf(unit8," %d %f\n",i,r3[i]);

// }

// fclose(unit8);

// }

// if(filename != NULL){free(filename);}

//

//end file part

//

}

nrcv=myid*nsendcnt+1;

nrcv2=nrcv+nsendcnt-1;

if( nstep < nrcv2 ){nrcv2=nstep;}

nsend=nrcv2-nrcv+1;

// multiply by 2

if(myid == 0){

for(i=nrcv-1;i<nrcv2;i++){

r2[i]=2.0*r1[i];

}

}else{

for( i=0;i<nsend;i++){

r3[i]=2.0*r3[i];

}

}

itag=1;

if(myid == 0){

for(i=2;i<=numprocs;i++){

nsendcnt=(nstep+numprocs-1)/numprocs;

nrcv=(i-1)*nsendcnt+1;

nrcv2=nrcv+nsendcnt-1;

if( nstep < nrcv2 ){nrcv2=nstep;}

nsend=nrcv2-nrcv+1;

// MPI_Recv (r2,nsend,MPI_DOUBLE,i-1,itag,MPI_COMM_WORLD,status);

MPI_Recv (r3,nsend,MPI_DOUBLE,i-1,itag,MPI_COMM_WORLD,MPI_STATUS_IGNORE);

for(j=nrcv-1;j<nrcv2;j++){

r2[j]=r3[j-nrcv+1];

}

printf(" final r from %d,%d\n",i-1,nsend);

}

}else{

MPI_Send(r3,nsend,MPI_DOUBLE,0,itag,MPI_COMM_WORLD);

printf(" final s %d,%d\n",myid,nsend);

}

MPI_Barrier(MPI_COMM_WORLD);

if(myid == 0){

j=0;

for(i=0;i<nstep;i++){

if(fabs(r2[i] - 2.0*r1[i]) > 1.e-8){

j++;

printf(" failed %d:%d %e %e\n",myid,i,2.0*r1[i],r2[i]);

}

}

if(j == 0){printf(" doubling OK \n");}

}

MPI_Finalize();

return 0;

}