      program transpose_matrix
      include 'mpif.h'
      integer ndims,xmax,ymax,nnodes,myid
      parameter(ndims=2)
      parameter(xmax=1000,ymax=1000)
       parameter(niters=100)
      integer comm,ierr
      integer status(MPI_STATUS_SIZE)

      real,allocatable,dimension(:,:) :: A,B

      integer xb,yb,i,j,nitems

      comm=MPI_COMM_WORLD
 
      call MPI_init(ierr)
      call MPI_COMM_RANK(comm,myid,ierr)
      call MPI_COMM_SIZE(comm,nnodes,ierr)
  
!initialize the input matrixes A and allocate necessary spaces for A,B
!partition the matrix a in (block ,*) way

      xb = xmax/nnodes

      allocate(A(xb,ymax))
      allocate(B(xb,ymax))
   
      nitems = xb*ymax
      if (myid == nnodes-1) then
        do np=0,nnodes-1
           call random_number(A)
           A = 1000000.0*A
           if (np < nnodes-1) then
             call MPI_SEND(A,nitems,MPI_REAL,np,0,comm,ierr)
           endif
        enddo
      else
         call MPI_RECV(A,nitems,MPI_REAL,nnodes-1,0,comm,status,ierr)
      endif

      nitems = xb*(ymax/nnodes)

!start timer .....
      time_begin =  MPI_Wtime()
    
      do iter = 1,niters
! Do all-to-all personilized communication of matrix blocks

          call MPI_ALLTOALL(A,nitems,MPI_REAL,B,nitems,MPI_REAL,&
             comm,ierr)
! Do local transposition
          
          do np = 0,nnodes-1
            B(:,np*nnodes+1:(np+1)*nnodes) =  &
            transpose(B(:,np*nnodes+1:(np+1)*nnodes))
          enddo
      enddo
! Stop timer

      time_end =  MPI_Wtime()

      if (myid == 0) then
        print *,'Elapsed time ',niters,'iterations for Transpose'
        print *,'For matrix with dimensions',xmax,ymax ,'is'
        print *,time_end-time_begin ,'seconds'   
       endif

      deallocate(a)
      deallocate(b)
     
      call MPI_FINALIZE(ierr)

      end


      


