
           PROGRAM MAIN
           include "mpif.h"
           INTEGER N
           PARAMETER(N=400)
           REAL,ALLOCATABLE:: NEW(:,:),OLD(:,:), TMP(:,:)
           REAL MAXERR, ERR, MAXERRG
           INTEGER NPROCS, NID, REMAINDER, SIZE, I, J,IERR
           CHARACTER*2 STR
           REAL TOL
           INTEGER STATUS
           TOL=0.00001
           CALL MPI_INIT(IERR)
           CALL MPI_COMM_RANK(MPI_COMM_WORLD, NID,IERR)
           CALL MPI_COMM_SIZE(MPI_COMM_WORLD,NPROCS,IERR)
           REMAINDER = MOD((N-1), NPROCS)
           SIZE = (N-1-REMAINDER)/NPROCS
           IF(NID .LT. REMAINDER) THEN
             SIZE=SIZE+2
           ELSE
             SIZE = SIZE+1 
           ENDIF
           ALLOCATE(NEW(0:N+1,0:SIZE+1),
     &     OLD(0:N+1,0:SIZE+1),TMP(0:N+1,0:SIZE+1))
           NEW=0.
           OLD=0.
           TMP=0.
           DO I=0, SIZE
           NEW(0,I) = 1.0
           NEW (N,I) =1.0 
           OLD(0,I) =1.0 
           OLD (N,I) = 1.0
          ENDDO
           IF(NID .EQ. 0) THEN
           DO J=1, N-1
            NEW(J,0) = 1.0
            OLD(J,0)  =1.0
           ENDDO
           ENDIF
           IF(NID .EQ. NPROCS-1)THEN
           DO J=1,N-1
            NEW(J,SIZE) =1.0 
           OLD(J,SIZE) =1.0
           ENDDO
           ENDIF
           CALL ITERATION(OLD,NEW,N+1,SIZE+1,1,SIZE,MAXERR)
           CALL MPI_ALLREDUCE(MAXERR,MAXERRG, 1, MPI_REAL, MPI_MAX, 
     &      MPI_COMM_WORLD,IERR)
  101       DO I=0,SIZE+1
            DO J=0,N+1
            TMP(J,I) = NEW(J,I)
          NEW(J,I) = OLD(J,I)
          OLD(J,I) = TMP(J,I)
          ENDDO
          ENDDO
!
!         Example for four processors 0 <- 1  2 <- 3
!
         if(mod(nid,2).eq.1)then
          IF(NID .GT. 0)THEN
       CALL MPI_SEND(OLD(1,1), N-1,MPI_REAL, NID-1,
     & 10, MPI_COMM_WORLD,IERR)
          ENDIF
          ELSE
          IF (NID .LT. NPROCS-1) THEN
       CALL MPI_RECV(OLD(1,SIZE),N-1,MPI_REAL,NID+1,10,
     & MPI_COMM_WORLD,status,IERR)
          ENDIF
          ENDIF
!
!        Example for four processors  0 -> 1  2 -> 3
!
         if(mod(nid,2).eq.1)then
          IF(NID .GT. 0)THEN
            CALL  MPI_RECV(OLD(1,0), N-1,MPI_REAL, NID-1,20, 
     &         MPI_COMM_WORLD,status,IERR)
          ENDIF
          ELSE
          IF (NID .LT. NPROCS-1) THEN
           CALL MPI_SEND(OLD(1,SIZE-1),N-1,MPI_REAL,NID+1,20,
     & MPI_COMM_WORLD,IERR)
          ENDIF
          ENDIF
!
!        Example for four processors  0  1 ->  2  3
!
          IF(mod(nid,2).eq.1)then
          IF(NID.LT.NPROCS-1)THEN
        CALL MPI_SEND(OLD(1,SIZE-1),N-1,MPI_REAL,NID+1,30,
     & MPI_COMM_WORLD,IERR)
         ENDIF
         ELSE
          IF(NID .GT. 0)THEN
            CALL  MPI_RECV(OLD(1,0), N-1,MPI_REAL, NID-1,30, 
     &         MPI_COMM_WORLD,status,IERR)
         ENDIF
         ENDIF
!
!        Example for four processors  0  1 <-  2  3
!
          IF(mod(nid,2).eq.1)then
          IF(NID.LT.NPROCS-1)THEN
        CALL MPI_RECV(OLD(1,SIZE),N-1,MPI_REAL,NID+1,40,
     & MPI_COMM_WORLD,status,IERR)
         ENDIF
         ELSE
          IF(NID .GT. 0)THEN
            CALL  MPI_SEND(OLD(1,1), N-1,MPI_REAL, NID-1,40, 
     &         MPI_COMM_WORLD,IERR)
         ENDIF
         ENDIF
          
          CALL ITERATION (OLD, NEW,N+1,SIZE+1, 2, SIZE-1, MAXERR)
              CALL ITERATION (OLD,NEW,N+1,SIZE+1,SIZE-1,SIZE,ERR)
              IF(ERR .GT. MAXERR) THEN
                 MAXERR = ERR
               ENDIF
               CALL ITERATION (OLD,NEW,N+1,SIZE+1,1,2,ERR)
           
            IF(ERR .GT. MAXERR) THEN
              MAXERR = ERR
            ENDIF
      CALL MPI_ALLREDUCE(MAXERR,MAXERRG, 1,MPI_REAL,MPI_MAX, 
     &MPI_COMM_WORLD,IERR)
        IF(MAXERRG .GT. TOL) THEN
        GO TO 101
        ENDIF
         WRITE (STR,'(i2)')NID
         IF(NID.LT.9)THEN
         STR(1:1)='0'
         ENDIF 
         OPEN(10,FILE ='Solution'//STR//'.Txt',FORM='FORMATTED')
         IF(NID ==0)THEN
         DO J=0, N
           WRITE(10,10)NEW(J,0)
         ENDDO
         ENDIF
        DO I=1, SIZE-1
        DO J=0, N
            WRITE(10,10)NEW(J,I)
        ENDDO
        ENDDO
        IF(NID .EQ. NPROCS-1) THEN
        DO J=0 , N
            WRITE(10,10)NEW(J,SIZE)
        ENDDO
        ENDIF
        CLOSE(10)
  10    FORMAT(E15.4)
        CALL MPI_FINALIZE(IERR)
        END



        SUBROUTINE ITERATION( OLD, NEW,M1,N1,START, FINISH,ERR)
        INTEGER M1,N1,START,FINISH
        REAL OLD(0:M1,0:N1),NEW(0:M1,0:N1)
        REAL DIFF, ERR 
        INTEGER I,J
        ERR =0.
        DO I= START, FINISH-1
        DO J=1,M1-1 
        NEW(J,I) =.25*(OLD(J,I+1)+OLD(J,I-1)+OLD(J+1,I)+OLD(J-1,I))
        DIFF = NEW(J,I) - OLD(J,I)
        IF(DIFF.LT. 0) THEN 
        DIFF = -DIFF
        ENDIF
        IF(ERR .LT. DIFF) THEN
        ERR= DIFF
        ENDIF
        ENDDO
        ENDDO
        RETURN
        END
