//
// 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;
}