2次元角柱周りの流れ解析(FORTRAN)プログラム

    2003/09/17 日立製作所 & 早稲田大学 後 保範 ( Ushiro Yasunori )
--------------------------------------------------------------

1. 概要

 2次元角柱周りの流れを速度-圧力法により差分法で計算する。

2. プログラム

C=================================================================C
C  2-Dimensional Flow around Square a Pillar by velocity          C
C       and pressure with FDM and SOR                             C
C-----------------------------------------------------------------C
C    Written by Yasunori Ushiro,   2003/09/14                     C
C        ( Hitachi Ltd. and Waseda University )                   C
C=================================================================C
      PARAMETER(NDX=301, NDY=301)
      IMPLICIT REAL*8(A-H,O-Z)
      DIMENSION U(-1:NDX,-1:NDY), V(-1:NDX,-1:NDY)
      DIMENSION A(-1:NDX,-1:NDY,5), B(-1:NDX,-1:NDY)
      DIMENSION P(-1:NDX,-1:NDY), PHI(-1:NDX,-1:NDY)
      CHARACTER*12 FLOW3
      DATA FLOW3/'FLOW3-??.txt'/
      COMMON /MESH/NX,NX1,NX2,NY,NY1,NY2
C  Initial Data
      ID = 0
      CALL XCLOCK(T1,3)
      XM = 2.0
      YM = 1.0
      WRITE(6,*) 'Type In  NX,NY'
      READ(5,*) NX,NY
      WRITE(6,*) 'Type in  Re,DT,NT(Total NO.),MT(Output Interval)'
      READ(5,*) Re,dt,NT,MT
      if(NX.ge.NDX) NX = NDX - 1
      if(NY.ge.NDY) NY = NDY - 1
      NX1 = NX*2/10
      NX2 = NX*3/10
      NY1 = NY*2/5
      NY2 = NY*3/5
      WRITE(6,100) XM,NX1,NX2,NX
      WRITE(6,110) YM,NY1,NY2,NY
      WRITE(6,120) Re,dt,NT,MT
C  Initial Constant
      T   = 0.0
      hx  = XM/NX
      hy  = YM/NY
      dx  = 1.0/(2.0*hx)
      dy  = 1.0/(2.0*hy)
      ddx = 1.0/hx**2
      ddy = 1.0/hy**2
      EPS = 1.0e-4
      OMG = 1.0 + DLOG((NX+NY)*1.0D0)/DLOG((NDX+NDY)*1.2D0)
C   Set Initial U,V
      ITER = NX*NY
      CALL PHISOL(PHI,A,B,U,V,hx,hy,OMG,NDX,NDY,EPS,ITER)
C   Set Initial P
      do j=-1,NY+1
        do i=-1,NX+1
          P(i,j) = 0.0
        end do
      end do
C  Main Loop
      CALL XCLOCK(T1,5)
      NITER = ITER
      do k=1,NT
        T = T + DT
C   Compute P
        ITER = NX*NY
        CALL PSOL(P,A,B,U,V,hx,hy,dt,Re,OMG,NDX,NDY,EPS,ITER)
        NITER = NITER + ITER
C   Compute U,V
        OVER = 0.0
C    Lower-Y Area
        do j=1,NY1-1
          do i=1,NX
            include 'UV.h'
          end do
        end do
C    Middle-Y Area
        do j=NY1,NY2
          do i=1,NX1-1
            include 'UV.h'
          end do
          do i=NX2+1,NX
            include 'UV.h'
          end do
        end do
C    Upper-Y Area
        do j=NY2+1,NY-1
          do i=1,NX
            include 'UV.h'
          end do
        end do
C   Check Divergent
        if(OVER.gt.1.0D10) then
          WRITE(6,*) '** Stop for over flow computation **'
          WRITE(6,*) '  You have to give smaller DT'
          STOP
        end if
C   Output U,V,Phi
        if(MOD(k,MT).eq.0) then
          NI1 = ID/10
          NI2 = ID - NI1*10 
          FLOW3(7:7) = CHAR(NI1+ICHAR('0'))
          FLOW3(8:8) = CHAR(NI2+ICHAR('0'))
          OPEN(UNIT=1,FILE=FLOW3)
          WRITE(1,100) XM,NX1,NX2,NX
          WRITE(1,110) YM,NY1,NY2,NY
          WRITE(1,120) Re,dt,NT,MT
          WRITE(1,150) T,k,NITER
          WRITE(6,150) T,k,NITER
          NITER = 0
          CALL OUTUVP(P,U,V,PHI,hx,hy,NDX,NDY)
          CLOSE(UNIT=1)
          if(ID.lt.99) ID = ID + 1
        end if
      end do
      CALL XCLOCK(T2,5)
      WRITE(6,200) NX,NT,T2-T1 
C
      STOP
  100 FORMAT('# Flow around Square a Pillar Numerical Analysis',/,
     1 '# XM=',F8.1,'  NX1,NX2,NX=',3I4)
  110 FORMAT('# YM=',F8.1,'  NY1,NY2,NY=',3I4)
  120 FORMAT('# Re=',F8.1,'  DT=',F7.3,'  NT,MT=',2I5)
  150 FORMAT('#Time=',F7.3,'  Step=',I5,'  SOR Loops=',I6) 
  200 FORMAT(1H ,' NX,NT,Time(s)=',2I5,F9.2) 
      END
C=================================================================C
      SUBROUTINE PSOL(P,A,B,U,V,hx,hy,dt,Re,OMG,NDX,NDY,EPS,ITER)
C=================================================================C
C  Solve Ax=b by SOR with 2 dimensional FDM                       C
C    Solve P by U,V with -div(P)=f(U,V)                           C
C-----------------------------------------------------------------C
C    P(-1:NDX,-1:NDY)   R*8, I/O, P vector                        C
C    A(-1:NDX,-1:NDY,5) R*8, Wk,  Matrix A for -div(PHI)=0        C
C    B(-1:NDX,-1:NDY)   R*8, Wk,  Right Vector for -div(PHI)=0    C
C    U(-1:NDX,-1:NDY)   R*8, In,  U vector                        C
C    V(-1:NDX,-1:NDY)   R*8, In,  V vector                        C
C    hx              R*8, In.  Delta x                            C
C    hy              R*8, In,  Delta y                            C
C    dt              R*8, In,  Delta t                            C
C    Re              R*8, In,  Re Number                          C
C    OMG             R*8, In,  Acceleration parameter for SOR     C
C    NDX             I*4, In,  First Array Size                   C
C    NDY             I*4, In,  Second Array Sixe                  C
C    EPS             R*8, In,  if ||r||/||b|| <= EPS --> return   C
C    ITER            I*4, Out, Number of Iteration                C
C-----------------------------------------------------------------C
C    Written by Yasunori Ushiro,   2003/09/14                     C
C        ( Hitachi Ltd. and Waseda University )                   C
C=================================================================C
      IMPLICIT REAL*8(A-H,O-Z)
      DIMENSION U(-1:NDX,-1:NDY), V(-1:NDX,-1:NDY)
      DIMENSION A(-1:NDX,-1:NDY,3), B(-1:NDX,-1:NDY)
      DIMENSION P(-1:NDX,-1:NDY), W(-1:NDX,-1:NDY,3)
      COMMON /MESH/NX,NX1,NX2,NY,NY1,NY2
C  Set Value
      DYX = hy/hx
      DXY = hx/hy
      DHX = 1.0/(2.0*hx)
      DHY = 1.0/(2.0*hy)
C  Set Outer Boundary U,V,P
      do i=-1,NX+1
        P(i,-1)   = P(i,1)
        P(i,NY+1) = P(i,NY-1)
        U(i,-1)   = U(i,0)
        V(i,-1)   = V(i,0)
        U(i,NY+1) = U(i,NY)
        V(i,NY+1) = V(i,NY)
      end do 
      do j=-1,NY+1
C   P=0 on L3
        P(NX,j)   = 0.0
        P(-1,j)   = P(1,j)
        P(NX+1,j) = P(NX-1,j)
        U(-1,j)   = U(0,j)
        V(-1,j)   = V(0,j)
        U(NX+1,j) = U(NX,j)
        V(NX+1,j) = V(NX,j)
      end do
C  Set A and B
      BN = 0.0
      do j=0,NY
        do i=0,NX-1
C    Inner
          A1 = -DXY
          A2 = -DYX
          A3 = 2.0*(DXY + DYX)
          A4 = -DYX
          A5 = -DXY 
C    on B1
          if(i.eq.NX1 .and. j.ge.NY1 .and. j.le.NY2) then
            A3  = A3 - DYX
            A4  = 0.0
            UP0 = 0.0
            VP0 = 0.0
          else
            UP0 = U(i+1,j)
            VP0 = V(i+1,j)
          end if
C    on B2
          if(j.eq.NY1 .and. i.ge.NX1 .and. i.le.NX2) then
            A3  = A3 - DXY
            A5  = 0.0
            U0P = 0.0
            V0P = 0.0
          else
            U0P = U(i,j+1)
            V0P = V(i,j+1)
          end if
C    on B3
          if(i.eq.NX2 .and. j.ge.NY1 .and. j.le.NY2) then
            A2  = 0.0
            A3  = A3 - DYX
            UM0 = 0.0
            VM0 = 0.0
          else
            UM0 = U(i-1,j)
            VM0 =	V(i-1,j)
          end if
C    on B4
          if(j.eq.NY2 .and. i.ge.NX1 .and. i.le.NX2) then
            A1  = 0.0
            A3  = A3 - DXY
            U0M = 0.0
            V0M = 0.0
          else
            U0M = U(i,j-1)
            V0M = V(i,j-1)
          end if
C   Set A,B
          A(i,j,1) = A1
          A(i,j,2) = A2
          A(i,j,3) = A3
          A(i,j,4) = A4
          A(i,j,5) = A5
          B(i,j) = ((UP0-UM0)**2*DYX + (V0P-V0M)**2*DXY )/4.0
     1           + (VP0-VM0)*(U0P-U0M)/2.0 
     2           - ((UP0-UM0)*hy + (V0P-V0M)*hx)/(2.0*dt)		 
C    in Square a Pillar
          if( (i.gt.NX1.and.i.lt.NX2) .and. 
     1        (j.gt.NY1.and.j.lt.NY2) ) then
            A(i,j,1) = 0.0
            A(i,j,2) = 0.0
            A(i,j,3) = 1.0
            A(i,j,4) = 0.0
            A(i,j,5) = 0.0
            B(i,j)   = P(NX1,NY1)
          end if
          BN = BN + (B(i,j)/A(i,j,3))**2
        end do
      end do
C  Solve Ax=b
      do k=1,ITER
        RN = 0.0
        do j=0,NY
         do i=0,NX-1
            R = ( B(i,j) - A(i,j,1)*P(i,j-1) - A(i,j,2)*P(i-1,j)
     1        - A(i,j,4)*P(i+1,j) - A(i,j,5)*P(i,j+1) )/A(i,j,3)
     2        - P(i,j)
            P(i,j) = P(i,j) + OMG*R
            RN = RN + (R/A(i,j,3))**2
          end do
        end do
C   Check Conversion
        ERR = sqrt(RN/BN)
        if(ERR.le.EPS) go to 100
      end do
  100 CONTINUE
      ITER = k
C
      RETURN
      END
C=================================================================C
      SUBROUTINE PHISOL(PHI,A,B,U,V,hx,hy,OMG,NDX,NDY,EPS,ITER)
C=================================================================C
C  Solve Ax=b by SOR with 2 dimensional FDM                       C
C    Solve PHI and Compute U,V                                    C
C    -div(PHI)=0 and d(PHI)/dx=U, d(PHI)/dy=V                     C
C-----------------------------------------------------------------C
C    PHI(-1:NDX,-1:NDY) R*8, I/O, PHI vector                      C
C    A(-1:NDX,-1:NDY,5) R*8, Wk,  Matrix A for -div(PHI)=0        C
C    B(-1:NDX,-1:NDY)   R*8, Wk,  Right Vector for -div(PHI)=0    C
C    U(-1:NDX,-1:NDY)   R*8, In,  U vector                        C
C    V(-1:NDX,-1:NDY)   R*8, In,  V vector                        C
C    hx              R*8, In.  Delta x                            C
C    hy              R*8, In,  Delta y                            C
C    OMG             R*8, In,  Acceleration parameter for SOR     C
C    NDX             I*4, In,  First Array Size                   C
C    NDY             I*4, In,  Second Array Sixe                  C
C    EPS             R*8, In,  if ||r||/||b|| <= EPS --> return   C
C    ITER            I*4, Out, Number of Iteration                C
C-----------------------------------------------------------------C
C    Written by Yasunori Ushiro,   2003/09/14                     C
C        ( Hitachi Ltd. and Waseda University )                   C
C=================================================================C
      IMPLICIT REAL*8(A-H,O-Z)
      DIMENSION U(-1:NDX,-1:NDY), V(-1:NDX,-1:NDY)
      DIMENSION A(-1:NDX,-1:NDY,5), B(-1:NDX,-1:NDY)
      DIMENSION PHI(-1:NDX,-1:NDY)
      COMMON /MESH/NX,NX1,NX2,NY,NY1,NY2
C  Set Value
      DYX = hy/hx
      DXY = hx/hy
      DHX = 1.0/(2.0*hx)
      DHY = 1.0/(2.0*hy)
C  Set Initial PHI=X
      do j=0,NY
        do i=0,NX+1
          PHI(i,j) = i*hx
        end do
      end do
C  Set A and B
      BN = 0.0
      do j=1,NY-1
        do i=1,NX
C    Inner
          A1 = -DXY
          A2 = -DYX
          A3 = 2.0*(DXY + DYX)
          A4 = -DYX
          A5 = -DXY 
          BV = 0.0
C    on L3
          if(i.eq.NX) then
            A3 = A3 - DYX
            A4 = 0.0   
            BV = BV + hy
          end if
C    on B1
          if(i.eq.NX1 .and. j.ge.NY1 .and. j.le.NY2) then
            A3 = A3 - DYX
            A4 = 0.0
          end if
C    on B2
          if(j.eq.NY1 .and. i.ge.NX1 .and. i.le.NX2) then
            A3 = A3 - DXY
            A5 = 0.0
          end if
C    on B3
          if(i.eq.NX2 .and. j.ge.NY1 .and. j.le.NY2) then
            A2 = 0.0
            A3 = A3 - DYX
          end if
C    on B4
          if(j.eq.NY2 .and. i.ge.NX1 .and. i.le.NX2) then
            A1 = 0.0
            A3 = A3 - DXY
          end if 	 
C    in Square a Pillar
          if( (i.gt.NX1.and.i.lt.NX2) .and. 
     1        (j.gt.NY1.and.j.lt.NY2) ) then
            A1 = 0.0
            A2 = 0.0
            A3 = 1.0
            A4 = 0.0
            A5 = 0.0
            BV = 0.0
          end if
C    Set A,B
          A(i,j,1) = A1
          A(i,j,2) = A2
          A(i,j,3) = A3
          A(i,j,4) = A4
          A(i,j,5) = A5
          B(i,j)   = BV
          BN       = BN + (BV/A3)**2
        end do
      end do
C  Solve Ax=b
      do k=1,ITER
        RN = 0.0
        do j=1,NY-1
         do i=1,NX
            R = ( B(i,j) - A(i,j,1)*PHI(i,j-1) - A(i,j,2)*PHI(i-1,j)
     1        - A(i,j,4)*PHI(i+1,j) - A(i,j,5)*PHI(i,j+1) )/A(i,j,3)
     2        - PHI(i,j)
            PHI(i,j) = PHI(i,j) + OMG*R
            RN = RN + R**2
          end do
        end do
C   Check Conversion
        ERR = sqrt(RN/BN)
        if(ERR.le.EPS) go to 100
      end do
  100 CONTINUE
      ITER = k
C  Compute U,V
      do j=1,NY-1
        do i=1,NX
          U(i,j) = (PHI(i+1,j) - PHI(i-1,j))*DHX
          V(i,j) = (PHI(i,j+1) - PHI(i,j-1))*DHY
        end do
      end do
C   in B
      do j=NY1,NY2
        do i=NX1,NX2
          U(i,j) = 0.0
          V(i,j) = 0.0
        end do
      end do
C   on L1 Boundary
      do j=1,NY-1
        U(0,j)  = 1.0
        V(0,j)  = 0.0
      end do
C   on L2,L4 Boundary
      do i=0,NX
        U(i,0)  = 1.0
        V(i,0)  = 0.0
        U(i,NY) = 1.0
        V(i,NY) = 0.0
      end do
C
      RETURN
      END
C=================================================================C
      SUBROUTINE OUTUVP(P,U,V,OMG,hx,hy,NDX,NDY)
C=================================================================C
C  Compute PHI and Output PHI,U,V                                 C
C    OMG(i,j) = dV/dx - dU/dy                                     C
C-----------------------------------------------------------------C
C    P(0:NDX,0:NY)    R*8, In,  P vector                          C
C    U(0:NDX,0:NY)    R*8, In,  U vector                          C
C    V(0:NDX,0:NY)    R*8, In,  V vector                          C
C    OMG(0:NDX,0:NDY) R*8, Wk,  Vorticity Vector                  C
C    hx               R*8, In,  Delta x                           C
C    hy               R*8, In,  Delta y                           C
C    NDX              I*4, In,  First Array Size of P,U,V         C
C    NDY              I*4, In,  Second Array Size of P,U,V        C
C-----------------------------------------------------------------C
C    Written by Yasunori Ushiro,   2003/09/14                     C
C        ( Hitachi Ltd. and Waseda University )                   C
C=================================================================C
      IMPLICIT REAL*8(A-H,O-Z)
      DIMENSION P(-1:NDX,-1:NDY), OMG(-1:NDX,-1:NDY)
      DIMENSION U(-1:NDX,-1:NDY), V(-1:NDX,-1:NDY)
      COMMON /MESH/NX,NX1,NX2,NY,NY1,NY2
C   Set Omega
      do j=0,NY
        do i=0,NX
          OMG(i,j) = (V(i+1,j)-V(i-1,j))/hx - (U(i,j+1)-U(i,j-1))/hy
        end do
      end do
C   Output
      do j=0,NY
        Y = j*hy
        do i=0,NX
          X = i*hx
          WRITE(1,100) X,Y,OMG(i,j),U(i,j),V(i,j)
        end do
      end do
C
      RETURN
  100 FORMAT(1H ,5F10.4)
      END
C=================================================================C
      SUBROUTINE XCLOCK(CPU,ID)
C=================================================================C
C   CPU time Subroutine                                           C
C     CPU     R*8  Out, CPU Time                                  C
C     ID      I*4  In,  Dummy ( Same Hitachi FORTRAN XCLOCK )     C
C-----------------------------------------------------------------C
C  Written by Y. Ushiro ( Waseda and Hitachi )  2002.10.29        C
C=================================================================C
      REAL*8 CPU
      INTEGER*2 I1, I2, I3, I4
C
      IF(ID.GE.1) THEN
        CALL GETTIM(I1,I2,I3,I4)
        CPU = ( I1*60.0 + I2 )*60.0 + I3 + I4*0.01
      END IF
C
      RETURN
      END

3. include file(ファイル名:UV.h)

            U(i,j) = U(i,j) - dt*( (U(i+1,j)**2 - U(i-1,j)**2)*dx
     1             + (U(i,j+1)*V(i,j+1) - U(i,j-1)*V(i,j-1))*dy
     2             + (P(i+1,j) - P(i-1,j))*dx 
     3             + ( (2.0*U(i,j) - U(i-1,j) - U(i+1,j))*ddx
     4             + (2.0*U(i,j) - U(i,j-1) - U(i,j+1))*ddy )/Re )
            V(i,j) = V(i,j) - dt*( (V(i,j+1)**2 - V(i,j-1)**2)*dy
     1             + (U(i+1,j)*V(i+1,j) - U(i-1,j)*V(i-1,j))*dx
     2             + (P(i,j+1) - P(i,j-1))*dy 
     3             + ( (2.0*V(i,j) - V(i-1,j) - V(i+1,j))*ddx
     4             + (2.0*V(i,j) - V(i,j-1) - V(i,j+1))*ddy )/Re )
            OVER   = OVER + abs(U(i,j)) + abs(V(i,j))