Free Web Hosting Provider - Web Hosting - E-commerce - High Speed Internet - Free Web Page
Search the Web





Download the code
The model equation to be solved is of the form:
d2T/dx2 = - S(x)
*        A. Salih, Dept. of Mechanical Engg., NIT - Trichy, India.      *
*************************************************************************
*    THIS PROGRAM SOLVES POISSON EQUATION IN A ONE-DIMENSIONAL DOMAIN   *
*    USING FINITE DIFFERENCE METHOD (UNIFORM GRID) AND THEN DETERMINE   *
*    GLOBAL ERROR BY COMPARING THE NUMERICAL AND ANALYTICAL SOLUTION    *
*************************************************************************
*
      program FD1
      implicit doubleprecision (a-h,o-z)
      include 'scalars/integers.inc'
      include 'scalars/parameters.inc'
      open(unit=11,file='input.dat',status='unknown')
      open(unit=21,file='output.dat',status='unknown')
      open(unit=31,file='outputs/x.dat',status='unknown')
      open(unit=32,file='outputs/t.dat',status='unknown')
c
      pi = 4*datan(1d0)
c
      CALL READ_WRITE         ! read-in and write-out data
      close (unit=11)

      CALL GRID               ! setting up the grid points in the domain

      CALL BOUNDARY_COND      ! setting up boundary values

      CALL SOLVE              ! setting up system of equations
      
      CALL ANALYT             ! analytical solution

      CALL PRINTOUT           ! printing out the results
c
      stop
      end
*
***SUBROUTINE: READING IN AND WRITING OUT THE BASIC DATA****************
*
      subroutine READ_WRITE
      implicit doubleprecision (a-h,o-z)
      include 'array_dimension.inc'
      include 'scalars/integers.inc'
      include 'scalars/reals.inc'
      include 'scalars/solveparams.inc'
c
      read(11,*) alx            ! actual length of domain
      read(11,*) boundary_type  ! flag for type of boundary conditions
      read(11,*) solver         ! flag for type of solver to be used
      read(11,*) tolsor         ! tolerance value for terminating the
                                ! iteration (for SOR method)
      read(11,*) wtsor          ! relaxation factor for SOR
      read(11,*) itermax        ! maximum number of iterations (for SOR)
c
      write(21,*) 'Length of the domain', alx

      if (boundary_type == 1) then
         write(21,*) 'Dirichlet bc is specified on all boundaries'
      elseif (boundary_type == 2) then
         write(21,*) 'West-side Dirichlet, east-side Neumann conditions'
      elseif (boundary_type == 3) then
         write(21,*) 'Neumann bc is specified on all boundaries'
      endif

      if (solver == 1) then
         write(21,*) 'The solver used is TDMA'
      elseif (solver == 2) then
         write(21,*) 'The solver used is SOR' 
      endif

      if ((boundary_type == 3).and.(solver == 1)) then
         write(21,*)
         write(21,*) 'WARNING: TDMA solver will not work with a "pure Ne
     $umann problem".'
         write(21,*) 'Try SOR solver.'
      elseif (boundary_type == 3) then
         write(21,*)
         write(21,*) '1) No unique solution exists for a pure Neumann pr
     $oblem.'
         write(21,*) '2) Solutions can only be determined within an arbi
     $trary constant.'
         write(21,*) '3) For a pure Neumann problem, the source and the 
     $net boundary'
         write(21,*) '   flux must be compatible.'
         write(21,*)
      endif
*
      return
      end
*
****SUBROUTINE: GRID****************************************************
*
      SUBROUTINE GRID
      implicit doubleprecision (a-h,o-z)
      include 'array_dimension.inc'
      include 'scalars/integers.inc'
      include 'scalars/reals.inc'
      include 'arrays/grid.inc'
c
c     n = no. of grid points (including boundary nodes) in x-direction
      dx   = alx /(n-1)
      x(1) = 0
      do i = 2, n
         x(i) = x(i-1) + dx
      enddo
c
      return
      end
*
***SUBROUTINE: BOUNDARY CONDITIONS FOR TEMPERATURE**********************
*
      SUBROUTINE BOUNDARY_COND
      implicit doubleprecision (a-h,o-z)
      include 'array_dimension.inc'
      include 'scalars/integers.inc'
      include 'scalars/reals.inc'
      include 'scalars/boundaryvalues.inc'
      include 'scalars/parameters.inc'
      include 'arrays/temperature.inc'
      include 'arrays/grid.inc'
c
c     defining the boundary conditions
      include 'bc/bc.inc'
c
c      boundary_type: 1  - Dirichlet - all
c      boundary_type: 2  - Dirichlet - left;   Neumann - right
c      boundary_type: 3  - Neumann - all
c
      if (boundary_type == 1) then
         TMP(1) = tw
         TMP(n) = te
      elseif (boundary_type == 2) then
         TMP(1) = tw
      elseif (boundary_type == 3) then
         ! nothing
      endif
c
      return
      end
*
***SUBROUTINE: CONSTRUCTION OF SYSTEM OF EQUATION AND ITS SOLUTION******
*
      subroutine SOLVE
      implicit doubleprecision (a-h,o-z)
      include 'array_dimension.inc'
      include 'scalars/integers.inc'
      include 'scalars/reals.inc'
      include 'scalars/boundaryvalues.inc'
      include 'scalars/parameters.inc'
      include 'arrays/grid.inc'
      include 'arrays/temperature.inc'
      include 'arrays/coeff.inc'
c
      include 'arithmeticfunctions/source.inc'    ! source.inc file
                           ! contains the definition of source term 
c
c     construction of coefficient matrix
      do i = 2, n-1
         AW(i) = 1
         AE(i) = 1
         AP(i) = -(AW(i) + AE(i))
      enddo
c
c     construction of RHS vector
      do i = 2, n-1
         C(i) = -S(x(i))*dx**2
      enddo
c
c     incorporation of boundary conditions
      if (boundary_type == 1) then
c        west
         C(2)  = C(2) - AW(2)*TMP(1)
         AW(2) = 0
c        east
         C(n-1)  = C(n-1) - AE(n-1)*TMP(n)
         AE(n-1) = 0
      elseif (boundary_type == 2) then
c        west
         C(2)  = C(2) - AW(2)*TMP(1)
         AW(2) = 0
c        east
         AW(n-1) = AW(n-1) - (1d0/3d0)*AE(n-1)
         AP(n-1) = AP(n-1) + (4d0/3d0)*AE(n-1)
         C(n-1)  = C(n-1)  - (2d0/3d0)*AE(n-1) *qe *dx
         AE(n-1) = 0
      elseif (boundary_type == 3) then
c        west
         AE(2) = AE(2) - (1d0/3d0)*AW(2)
         AP(2) = AP(2) + (4d0/3d0)*AW(2)
         C(2)  = C(2)  + (2d0/3d0)*AW(2) *qw *dx
         AW(2) = 0
c        east
         AW(n-1) = AW(n-1) - (1d0/3d0)*AE(n-1)
         AP(n-1) = AP(n-1) + (4d0/3d0)*AE(n-1)
         C(n-1)  = C(n-1)  - (2d0/3d0)*AE(n-1) *qe *dx
         AE(n-1) = 0
      endif

      if (solver == 1) then
         CALL TDMA(AW,AP,AE,C,TMP)    ! TDMA
      elseif (solver == 2) then
         CALL SOR(TMP)                ! SOR
      endif
c
c     calculation of heat fluxes at boundaries (flux is proportional to 
c                        the negative of slope of the temperature curve)
      if (boundary_type == 1) then
         qw = -(-TMP(3) + 4*TMP(2) - 3*TMP(1)) /(2*dx)
         qe = -(3*TMP(n) - 4*TMP(n-1) + TMP(n-2)) /(2*dx)
      elseif (boundary_type == 2) then
         qw = -(-TMP(3) + 4*TMP(2) - 3*TMP(1)) /(2*dx)
         TMP(n) = (4*TMP(n-1) - TMP(n-2) + 2*qe*dx) /3d0
      elseif (boundary_type == 3) then
         TMP(1) = (4*TMP(2) - TMP(3) - 2*qw*dx) /3d0
         TMP(n) = (4*TMP(n-1) - TMP(n-2) + 2*qe*dx) /3d0
      endif
      write(21,*) ''
      write(21,*) 'The temperature at West boundary is:', TMP(1)
      write(21,*) 'The temperature at East boundary is:', TMP(n)
      write(21,*) 'The heat flux at West boundary is:', qw
      write(21,*) 'The heat flux at East boundary is:', qe
*
      return
      end
*
***SUBROUTINE: TDMA*****************************************************
*
      subroutine TDMA(L,D,U,C,X)
      implicit doubleprecision (a-h,o-z)
      include 'array_dimension.inc'
      doubleprecision L(0:n1),U(0:n1),D(0:n1),C(0:n1),X(0:n1)
      doubleprecision P(-1:n1),Q(-1:n1)
c
      P(1) = 0d0
      Q(1) = 0d0
c
c     forward elimination
      do i = 2, n-1
         denom =  D(i) + L(i)*P(i-1)
         P(i)  = -U(i) /denom
         Q(i)  =  (C(i) - L(i)*Q(i-1)) /denom
      enddo
c
c     back substitution
      do i = n-1, 2, -1
         X(i) = P(i)*X(i+1) + Q(i)
      enddo
*
      return
      end
*
**SUBROUTINE: POINT SOR FOR TRIDIAGONAL MATRIX**************************
*
      SUBROUTINE SOR(X)
      implicit doubleprecision (a-h,o-z)
      include 'array_dimension.inc'
      include 'scalars/integers.inc'
      include 'scalars/solveparams.inc'
      include 'arrays/coeff.inc'
      doubleprecision X(0:n1)
c
      nn   = n-1 
      iter = 1
      wt   = wtsor
      relresidual = 1d9            ! maximum norm of relative residual
c
c     calculation of maximum norm of rhs vector
      rhsnorm = 0
      do i = 2, nn
         rhsnorm = max(rhsnorm, dabs(C(i)))
      enddo
      rhsnorm = rhsnorm + 1d-30     ! avoid overflow if rhsnorm is zero
c
c     initial guess of the solution
      do i = 2, nn
         X(i) = 0
      enddo
c
10    if ((relresidual > tolsor).and.(iter < itermax)) then
         do i = 2, nn
             xold = X(i)
             xnew = ( C(i)- AW(i)*X(i-1) - AE(i)*X(i+1) ) /AP(i)
             X(i) = wt*xnew + (1d0 - wt)*xold
         enddo
c
c        compute new max-norm of residual vector
         residnorm = 0
         do i = 2, nn
              res = C(i) -( AW(i)*X(i-1) + AP(i)*X(i) + AE(i)*X(i+1) )
              residnorm = max(residnorm, dabs(res))
         enddo
         relresidual = residnorm /rhsnorm
*        write(333,101) iter, relresidual
         iter = iter + 1
         go to 10
      endif
c
      if (relresidual > tolsor) then
         write(21,*) 'Tolerance condition for SOR is not met'
      endif
      write(21,*) 'Number of iterations performed by solver', iter
*101  format('',3x,i4,4x,e10.3)
*
      return
      end
*
***SUBROUTINE: ANALYTICAL SOLUTION**************************************
*
      subroutine ANALYT
      implicit doubleprecision (a-h,o-z)
      include 'array_dimension.inc'
      include 'scalars/integers.inc'
      include 'scalars/reals.inc'
      include 'scalars/boundaryvalues.inc'
      include 'scalars/parameters.inc'
      include 'arrays/grid.inc'
      include 'arrays/temperature.inc'
c
      include 'arithmeticfunctions/analyt_sol.inc' ! analyt_sol.inc file
                    ! contains the arithmetic fn for analytical solution
c
      open(unit=33,file='outputs/tanal.dat',status='unknown')
      open(unit=34,file='outputs/errors.dat',status='unknown')
c
      do i = 1, n
         if (boundary_type == 1) then
            tana  = TA(x(i),tw,te)
         elseif (boundary_type == 2) then
            tana  = TA(x(i),tw,qe)
         elseif (boundary_type == 3) then
            tana  = TA(x(i),qw,qe)
         endif
         error = 0d0
         if (dabs(tana) > 1d-12) then
            error = (tana - TMP(i))/tana *100
         endif
         write(33,101) tana
         write(34,101) error
      enddo
101   format(e13.6)
*
      return
      end
*
***SUBROUTINE: Printing-out the output data*****************************
*
      SUBROUTINE PRINTOUT
      implicit doubleprecision (a-h,o-z)
      include 'array_dimension.inc'
      include 'scalars/integers.inc'
      include 'scalars/reals.inc'
      include 'arrays/temperature.inc'
      include 'arrays/grid.inc'
c
      write(31,101) (x(i), i=1,n)   
      write(32,102) (TMP(i), i=1,n)
101   format(e13.6)
102   format(e13.6)
*
      return
      end