
      SUBROUTINE globalInit(numChunk)
          USE chunkModule
          IMPLICIT NONE
          INTEGER numChunk
          numChunk = tchunks
      END SUBROUTINE

      function index1d(ix, iy, iz)
        USE chunkModule
        IMPLICIT NONE
        integer ix, iy, iz, index1d
        index1d = ny*nz*ix + nz*iy + iz
      end function

      subroutine index3d(index, ix, iy, iz)
        USE chunkModule
        IMPLICIT NONE
        integer ix, iy, iz, index
        ix = index/(ny*nz)
        iy = mod(index,(ny*nz))/nz
        iz = mod(index,nz)
      end subroutine

      SUBROUTINE processorInit()
      END SUBROUTINE

      SUBROUTINE chunkInit(obj, chunkStruct, thisIndex)
          USE chunkModule
	  IMPLICIT NONE
#include <receiverf.h>

          INTERFACE
            INTEGER FUNCTION index1d(ix,iy,iz)
              INTEGER ix, iy, iz
            END FUNCTION
            SUBROUTINE index3d(index, ix, iy, iz)
              INTEGER index, ix, iy, iz
            END SUBROUTINE
          END INTERFACE

          TYPE(chunk_struct) :: chunkStruct
          TYPE(chunk_type), POINTER :: chunk
          INTEGER thisIndex
          INTEGER (KIND=8) obj
          INTEGER i,j,k

          ALLOCATE (chunk)
          chunkStruct%chunk_ptr => chunk

          chunk%objPtr = obj
          chunk%index = thisIndex
          call index3d(chunk%index, chunk%xidx, chunk%yidx, chunk%zidx)
          chunk%xp = index1d(mod(chunk%xidx+1,nx),chunk%yidx,chunk%zidx)
          chunk%xm = index1d(mod(chunk%xidx+nx-1,nx),chunk%yidx,chunk%zidx)
          chunk%yp = index1d(chunk%xidx,mod(chunk%yidx+1,ny),chunk%zidx)
          chunk%ym = index1d(chunk%xidx,mod(chunk%yidx+ny-1,ny),chunk%zidx)
          chunk%zp = index1d(chunk%xidx,chunk%yidx,mod(chunk%zidx+1,nz))
          chunk%zm = index1d(chunk%xidx,chunk%yidx,mod(chunk%zidx+nz-1,nz))
          chunk%iterations = 0

          DO i = 2, 11
            DO j = 2, 11
              DO k = 2, 11
                chunk%t(k, j, i) = 100*(i-2) + 10*(j-2) + (k-2)
              ENDDO 
            ENDDO 
          ENDDO

        END SUBROUTINE        


        RECURSIVE SUBROUTINE sendToNeighbors(chunkStruct)
          USE chunkModule
	  IMPLICIT NONE
#include <receiverf.h>

          TYPE(chunk_struct) :: chunkStruct
          TYPE(chunk_type), POINTER :: chunk

          EXTERNAL nextStep

          chunk => chunkStruct%chunk_ptr

          chunk%sbxm = reshape(chunk%t(2,2:11,2:11), (/ 100 /))
          chunk%sbxp = reshape(chunk%t(11,2:11,2:11), (/ 100 /))
          chunk%sbym = reshape(chunk%t(2:11,2,2:11), (/ 100 /))
          chunk%sbyp = reshape(chunk%t(2:11,11,2:11), (/ 100 /))
          chunk%sbzm = reshape(chunk%t(2:11,2:11,2), (/ 100 /))
          chunk%sbzp = reshape(chunk%t(2:11,2:11,11), (/ 100 /))
          call f_send(chunk%objPtr, chunk%xm, chunk%sbxm, 100, &
&                     AMPI_DOUBLE_PRECISION, 0, chunk%iterations)

          call f_send(chunk%objPtr, chunk%xp, chunk%sbxp,&
&                    100, AMPI_DOUBLE_PRECISION, 1, chunk%iterations)
 
          call f_send(chunk%objPtr, chunk%ym, chunk%sbym, 100, &
&                     AMPI_DOUBLE_PRECISION, 2, chunk%iterations)

          call f_send(chunk%objPtr, chunk%yp,chunk%sbyp,&
&                    100, AMPI_DOUBLE_PRECISION, 3, chunk%iterations)
 
          call f_send(chunk%objPtr, chunk%zm, chunk%sbzm, 100, &
&                     AMPI_DOUBLE_PRECISION, 4, chunk%iterations)

          call f_send(chunk%objPtr, chunk%zp,chunk%sbzp,&
&                    100, AMPI_DOUBLE_PRECISION, 5, chunk%iterations)
 
          call f_irecv(chunk%objPtr, chunk%rbxm, 100, &
&                     AMPI_DOUBLE_PRECISION, 1, chunk%xm, chunk%iterations)

          call f_irecv(chunk%objPtr, chunk%rbxp, 100, &
&                      AMPI_DOUBLE_PRECISION, 0, chunk%xp, chunk%iterations)

          call f_irecv(chunk%objPtr, chunk%rbym,100, &
&                     AMPI_DOUBLE_PRECISION, 3, chunk%ym, chunk%iterations)

          call f_irecv(chunk%objPtr, chunk%rbyp, 100, &
&                      AMPI_DOUBLE_PRECISION, 2, chunk%yp, chunk%iterations)

          call f_irecv(chunk%objPtr, chunk%rbzm,100, &
&                     AMPI_DOUBLE_PRECISION, 5, chunk%zm, chunk%iterations)

          call f_irecv(chunk%objPtr, chunk%rbzp, 100, &
&                      AMPI_DOUBLE_PRECISION, 4, chunk%zp, chunk%iterations)

          call f_iwaitall(chunk%objPtr, nextStep, chunkStruct, chunk%iterations)

        END SUBROUTINE


        RECURSIVE SUBROUTINE nextStep(chunkStruct)
          USE chunkModule
	  IMPLICIT NONE
#include <receiverf.h>

          TYPE(chunk_struct) :: chunkStruct
          TYPE(chunk_type), POINTER :: chunk
          INTEGER i,j,k
          DOUBLE PRECISION   val

          chunk => chunkStruct%chunk_ptr

          chunk%iterations = chunk%iterations + 1

          if (chunk%index .eq. 0 .and. chunk%iterations .eq. 1) then
            startTime = IMPI_Wtime()
          endif
          IF ( chunk%iterations .lt. 30) THEN
            chunk%t(1,2:11,2:11) = reshape(chunk%rbxm,(/10,10/))
            chunk%t(12,2:11,2:11) = reshape(chunk%rbxp,(/10,10/))
            chunk%t(2:11,1,2:11) = reshape(chunk%rbym,(/10,10/))
            chunk%t(2:11,12,2:11) = reshape(chunk%rbyp,(/10,10/))
            chunk%t(2:11,2:11,1) = reshape(chunk%rbzm,(/10,10/))
            chunk%t(2:11,2:11,12) = reshape(chunk%rbzp,(/10,10/))
            DO i = 2, 11
             DO j = 2, 11
               DO k = 2, 11
                 val = ( chunk%t(k,j,i)+chunk%t(k,j,i+1)+&
&                        chunk%t(k,j,i-1)+chunk%t(k,j+1,i)+&
&                        chunk%t(k,j-1,i)+chunk%t(k+1,j,i)+chunk%t(k-1,j,i))/7.0
                 chunk%t(k,j,i) = val
	       END DO
	     END DO
	    ENDDO
            call sendToNeighbors(chunkStruct)
          ELSE
            if (chunk%index .eq. 0) then
              endTime = IMPI_Wtime()
              write (*,*) "Time per Iteration:", (endTime-startTime)/30.0
            endif
          ENDIF

        END SUBROUTINE
