#include <mpi.h>
#include <stdio.h>
#include <omp.h>

#define n 4
MPI_Comm split_comm[n];

int main(int argc, char ** argv)
{
    int myrank, size;
    int i, provided;
    int thread_id;
    int numsend[n], numrecv[n];
    MPI_Status  status;
    MPI_Info info;
    char s[16];

    //MPI_Init(&argc, &argv);
    MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);
    MPI_Info_create(&info);
    MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

        if(0 == myrank) {
                printf("MPI_INIT_THREAD Support requested= %d provided = %d\n",MPI_THREAD_MULTIPLE, provided);
        }

    for (i = 0; i < n; i++) {
        MPI_Comm_dup(MPI_COMM_WORLD, &split_comm[i]);
        sprintf(s, "%d", i);
        MPI_Info_set(info, "thread_id", s);
        MPI_Comm_set_info(split_comm[i], info);
    }
    
    for (i=0; i < n; i++){
      numsend[i]=33+i;
      numrecv[i]=50+i;
    }

    if (myrank==0)
      #pragma omp parallel for   
      for (i=0; i < n; i++){
         //MPI_Send(&numsend[i],1,MPI_INT,1,i,MPI_COMM_WORLD);
         MPI_Send(&numsend[i],1,MPI_INT,1,i,split_comm[i]);
          printf("Sending value numsend[%d]= %d from thread_id=%d of %d\n",i, numsend[i], omp_get_thread_num(), omp_get_num_threads());
         }
    else if (myrank==1)
      #pragma omp parallel for   
      for (i=0; i < n; i++){
         MPI_Recv(&numrecv[i],1,MPI_INT,0,i,split_comm[i],&status);
         }
    else
      printf("No MPI call assigned to me");

    if(myrank==1){
    printf(" I am rank %d of %d\n", myrank, size);
      for (i=0; i < n; i++){
          printf("Received value numrecv= %d\n", numrecv[i]);}
    }

    MPI_Finalize();
    return 0;
}
