CPS-615 Fall 1996 -- Final Project -- The HPF Source Code

HPF Distribution Methods in a Model CFD Problem

Michael McMahon



!To compile: f90 -fixed -o executable_name -wsf #of_processors vent.f90
!This program solves laplace's equation for Psi over a grid that
!is shaped into an air vent.  The grid is shaped using the logical
!variable Hide.  The equation is solved using a red black SOR method
!with the relaxation parameter set to the best value I could find,
!omega=1.92.  The execution time and number of iterations required
!are output upon completion.  The critical line is the HPF DISTRIBUTE
!line.  This line allows the method of distribution to be altered
!and the run time to be reduced to a minimum.

        Program Invis
        Parameter(n=100)
        Parameter(m=200)
        Parameter(z=4)
        Real,dimension(1:n,1:m)  ::  Psi,Psiold
        Real omega,tol,tstart,tend
        Logical,dimension(1:n,1:m) :: hide,even
        Integer i,j
        Integer iteration

!****************HPF Directives*************************

!HPF$ DISTRIBUTE Psi(*,cyclic(10))
!HPF$ ALIGN (:,:) with psi :: Psiold,hide,even

!*******************************************************

!Start to shape grid and begin timing
!Logical variable even is used for red-black algorithm
        hide = .false.
        even = .false.

        call timer(tstart,0.0)
        Forall(i=1:n,j=1:m,mod((i+j),2) .eq. 0) even(i,j)=.true.
        Forall(i=1:n-1,j=1:m/4,(i-j) > 0) hide(i,j) = .true.
        Forall(i=n/2+1:n-1,j=m/4:3*m/4) hide(i,j) = .true.
        Forall(i=1:n-1,j=3*m/4:m,(i+j-m) > 0) hide(i,j) = .true.

!Set boundary conditions

        Forall(i=1:n/2,j=1:m/4,(i-j).eq.0) Psi(i,j) = 50.0
        Forall(j=m/4:3*m/4) Psi(n/2,j)=50.0
        Forall(i=1:n/2,j=3*m/4:m/4,(i+j-200).eq.0) Psi(i,j)=50.0
        Forall(j=1:m) Psi(n,j) = 0.0

!Entrance and exit to vary linearly between top and bottom edges

        Forall(i=1:n) Psi(i,1)=50.0-50.0*real(i/n)
        Forall(i=1:n) Psi(i,m)=50.0-50.0*real(i/n)

!Preliminaries
        iteration=0
        Psiold=Psi
        omega=1.92
        tol=1.0
!on your marks, get set, go

        Do While(tol .ge. 1.0e-4)

!-------------red (even) sites----------------------
        Where(hide .eq. .true. .and. even .eq. .true.)
                psi=omega/4.0*(cshift(psi,dim=1,shift=1) 
     $       + cshift(psi,dim=1,shift= -1) 
     $       + cshift(psi,dim=2,shift=1)
     $       + cshift(psi,dim=2,shift= -1)) +(1.0-omega)*psi
        end where
!-------------------black (odd) sites------------------
        Where((hide .eq. .true.) .and. even .eq. .false.)
                psi=omega/4.0*(cshift(psi,dim=1,shift=1) 
     $       + cshift(psi,dim=1,shift= -1) 
     $       + cshift(psi,dim=2,shift=1)
     $       + cshift(psi,dim=2,shift= -1)) +(1.0-omega)*psi
        end where
!-------------------black (odd) sites------------------
        Where((hide .eq. .true.) .and. even .eq. .false.)
                psi=omega/4.0*(cshift(psi,dim=1,shift=1) 
     $       + cshift(psi,dim=1,shift= -1) 
     $       + cshift(psi,dim=2,shift=1)
     $       + cshift(psi,dim=2,shift= -1))+(1.0-omega)*psi
        end where

        iteration=iteration+1
        tol=maxval(abs(psiold-psi))

        psiold=psi

        end do
        call timer(tend,tstart)

        write(6,*) 'This many interations:',iteration
        write(6,*) 'And it took this long:',tend,'seconds'
        end program

!++++++++++++++++
         Subroutine timer(return_time,initial_time)
         real, intent(in)  :: initial_time
         real,  intent(out) :: return_time
         integer finish,rate
          CALL system_clock( COUNT=finish,COUNT_RATE=rate)
          return_time = FLOAT(finish) / FLOAT(rate) - initial_time
          end