2次元角柱周りの流れNO.3(C)プログラム

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

1. 概要

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

2. プログラム

//=================================================================C
//  2-Dimensional Flow around Square a Pillar by velocity          C
//       and pressure with FDM and SOR                             C
//-----------------------------------------------------------------C
//    Written by Yasunori Ushiro,   2003/09/14                     C
//        ( Hitachi Ltd. and Waseda University )                   C
//=================================================================C
#include <stdio.h>
#include <math.h>
#include <time.h>
// Global Define
#define NDX  302
#define NDY  302
#define P(i,j)   P[j+1][i+1]
#define B(i,j)   B[j+1][i+1]
#define U(i,j)   U[j+1][i+1]
#define V(i,j)   V[j+1][i+1]
#define PHI(i,j) PHI[j+1][i+1]
#define A(i,j,k) A[k-1][j+1][i+1]
#define OMG(i,j) PHI[j+1][i+1] 
double P[NDY][NDX], A[5][NDY][NDX], B[NDY][NDX] ;
double U[NDY][NDX], V[NDY][NDX], PHI[NDY][NDX] ;
int    NX, NY, NX1, NX2, NY1, NY2 ;
FILE   *FT1 ;
// Function Definition
int PSOL(double hx, double hy, double dt, double Re, double OMG,
         double EPS, int ITER) ;
int PHISOL(double hx, double hy, double OMG, double EPS, int ITER) ;
void OUTPUT(double hx, double hy) ;
// Main Program
int main()
{ int     i, j, k, NT, MT, ID, T1, T2 ;
  int     ITER, NTER, ILP, NI1, NI2, IER ;
  double  Re, dt, T, hx, hy, dx, dy, ddx, ddy, EPS, OMG ;
  double  XM ,YM, OVER, CPU ;
  char    FLOW3[13]={'F','L','O','W','2','-','?','?','.','t','x','t',} ;
  char    NTABL[10]={'0','1','2','3','4','5','6','7','8','9'} ; 
//  Initial Data
  ID = 0 ;
  XM = 2.0 ;
  YM = 1.0 ;
  printf("Type In  NX,NY \n") ;
  scanf("%d %d",&NX,&NY) ; 
  printf("Type in  Re,DT,NT(Total NO.),MT(Output Interval) \n") ; 
  scanf("%lf %lf %d %d",&Re,&dt,&NT,&MT) ;
//  Initial Data
  if(NX >= NDX-1) { NX = NDX - 2 ; }
  if(NY >= NDY-1) { NY = NDY - 2 ; }
  NX1 = NX*2/10 ;
  NX2 = NX*3/10 ;
  NY1 = NY*2/5 ; 
  NY2 = NY*3/5 ;
  printf("Flow around Square a Pillar Numerical Analysis \n") ;
  printf("XM=%f  NX1,NX2,NX=%d %d %d \n",XM,NX1,NX2,NX) ;
  printf("YM=%f  NY1,NY2,NY=%d %d %d \n",YM,NY1,NY2,NY) ;
  printf("Re=%f  dt=%f  NT,MT=%d %d \n",Re,dt,NT,MT) ;	 
//  Initial Constant
  IER = 0 ;
  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*hx) ;
  ddy = 1.0/(hy*hy) ;
  EPS = 1.0e-4 ;
  OMG = 1.0 + log((NX+NY)*1.0)/log((NDX+NDY)*1.0) ;
//   Set Initial U,V
  ILP = NX*NY ;
  ITER = PHISOL(hx, hy, OMG, EPS, ILP) ;
//   Set Initial P
  for (j=-1; j<=NY+1; j++) {
    for (i=-1; i<=NX+1; i++) {
      P(i,j) = 0.0 ;  }
    }
//  Main Loop
  T1 = clock() ;
  NTER = ITER ;
  for (k=1; k<=NT; k++) {
    T = T + dt ;
//   Compute P
    ILP  = NX*NY ;
    ITER = PSOL(hx, hy, dt, Re, OMG, EPS, ILP) ;
    NTER = NTER + ITER ;
//   Compute U,V
    OVER = 0.0 ;
//    Lower-Y Area
    for (j=1; j<NY1; j++) {
      for (i=1; i<=NX; i++) {
        #include "UV.h" 
	}  }
//    Middle-Y Area
    for (j=NY1; j<=NY2; j++) { 
      for (i=1; i<NX1; i++) {
        #include "UV.h"
	  }
      for (i=NX2+1; i<=NX; i++) {
        #include "UV.h" 
    }  }
//    Upper-Y Area
    for (j=NY2+1; j<NY; j++) {
      for (i=1; i<=NX; i++) {
        #include "UV.h"  
    }  }
//   Check Divergent
    if(OVER > 1.0e10) {
      printf("** Stop for over flow computation ** \n") ;
      printf("  You have to give smaller dt \n") ;
      IER = 1 ;
      goto M100 ;  }
//   Output U,V,Phi     
    if( k%MT == 0) {
      NI1 = ID/10 ;
      NI2 = ID - NI1*10 ;
      FLOW3[6] = NTABL[NI1] ;
      FLOW3[7] = NTABL[NI2] ;
      FT1 = fopen(FLOW3,"w") ;
      fprintf(FT1,"# Flow around Square a Pillar Numerical Analysis \n") ;
      fprintf(FT1,"XM=%f  NX1,NX2,NX=%d %d %d \n",NX1,NX2,NX) ;
      fprintf(FT1,"YM=%f  NY1,NY2,NY=%d %d %d \n",NY1,NY2,NY) ;
      fprintf(FT1,"Re=%f  dt=%f  NT,MT=%d %d \n",Re,dt,NT,MT) ;
      fprintf(FT1,"#Time=%7.2f,  Step=%5d  SOR-loop=%6d \n",T,k,NTER) ; 
      printf("#Time=%7.2f,  Step=%5d SOR-loop=%6d \n",T,k,NTER) ; 
      NTER = 0 ;
      OUTPUT(hx, hy) ;
      fclose(FT1) ;
      if(ID < 99) { ID = ID + 1 ; }
     }
   }
  T2 = clock() ;
  CPU  = (double)(T2 - T1)/CLOCKS_PER_SEC ;
  printf(" NX=%4d,  NT=%5d,  Time(s)=%9.2f \n",NX,NT,CPU) ; 
  M100:  return (IER) ;
  } 
//=================================================================C
int PSOL(double hx, double hy, double dt, double Re, double OMG,
         double EPS, int ITER)
//=================================================================C
//  Solve Ax=b by SOR with 2 dimensional FDM                       C
//    Solve P by U,V with -div(P)=f(U,V)                           C
//-----------------------------------------------------------------C
//    P,A,B,U,V ;  Global array                                    C
//    hx           R*8, In.  Delta x                               C
//    hy           R*8, In,  Delta y                               C
//    dt           R*8, In,  Delta t                               C
//    Re           R*8, In,  Re Number                             C
//    OMG          R*8, In,  Acceleration parameter for SOR        C 
//    EPS          R*8, In,  if ||r||/||b|| <= EPS --> return      C
//    ITER         I*4, In, Maximum Number of Iteration            C
//-----------------------------------------------------------------C
//    Written by Yasunori Ushiro,   2003/09/14                     C
//        ( Hitachi Ltd. and Waseda University )                   C
//=================================================================C
{ int     i, j, k, ILP ;
  double  DYX, DXY, DHX, DHY, BN, RN, ERR, A1, A2, A3, A4, A5 ;
  double  R, UP0, UM0, U0P, U0M, VP0, VM0, V0P, V0M ; 
//  Set Value
  DYX = hy/hx ;
  DXY = hx/hy ;
  DHX = 1.0/(2.0*hx) ;
  DHY = 1.0/(2.0*hy) ;
//  Set Outer Boundary U,V,P
  for (i=-1; i<=NX+1; i++) {
    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) ;  }
  for (j=-1; j<=NY+1; j++) {
//   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) ;  }
//  Set A and B
  BN = 0.0 ;
  for (j=0; j<=NY; j++) {
    for (i=0; i<NX; i++) { 
//   Inner
      A1 = -DXY ;
      A2 = -DYX ;
      A3 = 2.0*(DXY + DYX) ;
      A4 = -DYX ;
      A5 = -DXY ; 
//   on B1
      if(i == NX1 & j >= NY1 & j <= NY2) {
        A3  = A3 - DYX ;
        A4  = 0.0 ;
        UP0 = 0.0 ;
        VP0 = 0.0 ;  }
       else {
        UP0 = U(i+1,j) ;
        VP0 = V(i+1,j) ;  }
//   on B2
      if(j == NY1 & i >= NX1 & i <= NX2) {
        A3  = A3 - DXY ;
        A5  = 0.0 ;
        U0P = 0.0 ;
        V0P = 0.0 ;  }
      else {
        U0P = U(i,j+1) ;
        V0P = V(i,j+1) ;  }     	                                  
//   on B3
      if(i == NX2 & j >= NY1 & j <= NY2) {
        A2  = 0.0 ;
        A3  = A3 - DYX ;
        UM0 = 0.0 ;
        VM0 = 0.0 ;  }
      else {
        UM0 = U(i-1,j) ;
        VM0 = V(i-1,j) ;  } 	  	 
//    on B4
      if(j == NY2 & i >= NX1 & i <= NX2) {
        A1  = 0.0 ;
        A3  = A3 - DXY ;
        U0M = 0.0 ;
        V0M = 0.0 ;  }
      else {
        U0M = U(i,j-1) ;
        V0M = V(i,j-1) ;  }
//  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)*(UP0-UM0)*DYX + (V0P-V0M)*(V0P-V0M)*DXY )/4.0
             + (VP0-VM0)*(U0P-U0M)/2.0 
             - ((UP0-UM0)*hy + (V0P-V0M)*hx)/(2.0*dt) ;		 
//   in Square a Pillar
      if( (i > NX1 & i < NX2) & (j > NY1 & j < NY2) ) {
        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) ;  }
      BN = BN + B(i,j)*B(i,j)/(A(i,j,3)*A(i,j,3)) ;
    }  }
//  Solve Ax=b
  for (k=1; k<=ITER; k++) {
    RN = 0.0 ;
    for (j=0; j<=NY; j++) {
      for (i=0; i<NX; i++) {
        R = ( B(i,j) - A(i,j,1)*P(i,j-1) - A(i,j,2)*P(i-1,j)
          - A(i,j,4)*P(i+1,j) - A(i,j,5)*P(i,j+1) )/A(i,j,3) - P(i,j) ;
        P(i,j) = P(i,j) + OMG*R ;
        RN = RN + R*R ;
     }  }
//   Check Conversion
    ERR = sqrt(RN/BN) ;
//    printf("k=%d  ERR=%e  RN=%e  BN=%e \n",k,ERR,RN,BN) ;
    if(ERR <= EPS) goto M100 ;
    }
 M100: ILP = k ;
  return (ILP) ;
  }
//=================================================================C
int PHISOL(double hx, double hy, double OMG, double EPS, int ITER)
//=================================================================C
//  Solve Ax=b by SOR with 2 dimensional FDM                       C
//    Solve PHI and Compute U,V                                    C
//    -div(PHI)=0 and d(PHI)/dx=U, d(PHI)/dy=V                     C
//-----------------------------------------------------------------C
//    PHI,A,B,U,V ;  Global array                                  C
//    hx           R*8, In.  Delta x                               C
//    hy           R*8, In,  Delta y                               C
//    OMG          R*8, In,  Acceleration parameter for SOR        C 
//    EPS          R*8, In,  if ||r||/||b|| <= EPS --> return      C
//    ITER         I*4, In,  Number of Iteration                   C
//-----------------------------------------------------------------C
//    Written by Yasunori Ushiro,   2003/09/14                     C
//        ( Hitachi Ltd. and Waseda University )                   C
//=================================================================C
{ int     i, j, k, ILP ;
  double  DYX, DXY, DHX, DHY, A1, A2, A3, A4, A5, BV ;
  double  BN, RN, R, ERR ; 
//  Set Value
  DYX = hy/hx ;
  DXY = hx/hy ;
  DHX = 1.0/(2.0*hx) ;
  DHY = 1.0/(2.0*hy) ;
//  Set Initial PHI=X
  for (j=0; j<=NY; j++) {
    for (i=0; i<=NX+1; i++) {
      PHI(i,j) = i*hx ; 
   }  }
//  Set A and B
  BN = 0.0 ;
  for (j=1; j<NY; j++) {
    for (i=1; i<=NX; i++) {
//   Inner
      A1 = -DXY ;
      A2 = -DYX ;
      A3 = 2.0*(DXY + DYX) ;
      A4 = -DYX ;
      A5 = -DXY ; 
      BV = 0.0 ;
//   on L3
      if(i == NX) {
        A3 = A3 - DYX ;
        A4 = 0.0 ; 
        BV = BV + hy ;  }
//   on B1
      if(i == NX1 & j >= NY1 & j <= NY2) {
        A3 = A3 - DYX ;
        A4 = 0.0 ;  }
//   on B2
      if(j == NY1 & i >= NX1 & i <= NX2) {
        A3 = A3 - DXY ;
        A5 = 0.0 ;  }
//   on B3
      if(i == NX2 & j >= NY1 & j <= NY2) {
        A2 = 0.0 ;
        A3 = A3 - DYX ;  }
//   on B4
      if(j == NY2 & i >= NX1 & i <= NX2) {
        A1 = 0.0 ;
        A3 = A3 - DXY ;  }
//   in Square a Pillar
      if( (i > NX1 & i < NX2) & (j > NY1 & j < NY2) ) {
        A1 = 0.0 ;
        A2 = 0.0 ;
        A3 = 1.0 ;
        A4 = 0.0 ;
        A5 = 0.0 ;
        BV = 0.0 ;  }
//   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*BV/(A3*A3)  ;
   }  }
//  Solve Ax=b
  for (k=1; k<=ITER; k++) {
    RN = 0.0 ;
    for (j=1; j<NY; j++) {
      for (i=1; i<=NX; i++) {
        R = ( B(i,j) - A(i,j,1)*PHI(i,j-1) - A(i,j,2)*PHI(i-1,j)
          - A(i,j,4)*PHI(i+1,j)-A(i,j,5)*PHI(i,j+1) )/A(i,j,3) - PHI(i,j) ;
        PHI(i,j) = PHI(i,j) + OMG*R ;
        RN = RN + R*R ;
     }  } 
//   Check Conversion
    ERR = sqrt(RN/BN) ;
    if(ERR <= EPS) goto M100 ;
//    printf("kk=%d  ERR=%e  RN=%e  BN=%e \n",k,ERR,RN,BN) ;
   }   
  M100: ILP = k ;
//  Compute U,V
  for (j=1; jNY; j++) {
    for(i=1; i<=NX; i++) {
      U(i,j) = (PHI(i+1,j) - PHI(i-1,j))*DHX ;
      V(i,j) = (PHI(i,j+1) - PHI(i,j-1))*DHY ;
   }  }
//  in Square a Pillar
  for (j=NY1; j<=NY2; j++) {
    for (i=NX1; i<=NX2; i++) {
      U(i,j) = 0.0 ;
      V(i,j) = 0.0 ;           
   }  }
//   on L1 Boundary
  for (j=1; j<NY; j++) {
    U(0,j)  = 1.0 ;
    V(0,j)  = 0.0 ;  }
//   on L2,L4 Boundary
  for (i=0; i<=NX; i++) {
    U(i,0)  = 1.0 ;
    V(i,0)  = 0.0 ;
    U(i,NY) = 1.0 ;
    V(i,NY) = 0.0 ;  }
  return (ILP) ;
  }
//=================================================================C
void OUTPUT(double hx, double hy)
//=================================================================C
//  Compute PHI and Output PHI,U,V                                 C
//    OMG(i,j) = dV/dx - dU/dy                                     C
//-----------------------------------------------------------------C
//    hx               R*8, In,  Delta x                           C
//    hy               R*8, In,  Delta y                           C                      
//-----------------------------------------------------------------C
//    Written by Yasunori Ushiro,   2003/09/14                     C
//        ( Hitachi Ltd. and Waseda University )                   C
//=================================================================C
{ int     i, j ;
  double  X, Y ;
//   Set Omega
  for (j=0; j<=NY; j++) {
    for (i=0; i<=NX; i++) {
       OMG(i,j) = (V(i+1,j)-V(i-1,j))/hx - (U(i,j+1)-U(i,j-1))/hy ;
   }  }
//   Output
  for (j=0; j<=NY; j++) {
    Y = j*hy ;
    for (i=0; i<=NX; i++) {
      X = i*hx ;
      fprintf(FT1,"%10.4f %10.4f %10.4f %10.4f %10.4f \n",
                  X,Y,OMG(i,j),U(i,j),V(i,j)) ;  }
    }
  }

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

      U(i,j) = U(i,j) - dt*((U(i+1,j)*U(i+1,j) - U(i-1,j)*U(i-1,j))*dx
             + (U(i,j+1)*V(i,j+1) - U(i,j-1)*V(i,j-1))*dy
             + (P(i+1,j) - P(i-1,j))*dx 
             + ( (2.0*U(i,j) - U(i-1,j) - U(i+1,j))*ddx
             + (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)*V(i,j+1) - V(i,j-1)*V(i,j-1))*dy
             + (U(i+1,j)*V(i+1,j) - U(i-1,j)*V(i-1,j))*dx
             + (P(i,j+1) - P(i,j-1))*dy
             + ( (2.0*V(i,j) - V(i-1,j) - V(i+1,j))*ddx
             + (2.0*V(i,j) - V(i,j-1) - V(i,j+1))*ddy )/Re ) ;
      OVER   = OVER + fabs(U(i,j)) + fabs(V(i,j)) ;