NPS Shield image Super Hornet NPS Seal Image
Home
Go up 1 level
Resume
Research
Publications
Online Tools
NPS Links
Get an overview of the full site.
Site Search
Kevin's Online Tools: Panel Code Version 1.2 - Source Code

The Online Panel Code is based on a short Fortran code with a main program and 11 subroutines and functions. The source code is included below. Note: I'm frequently asked to send people the GETARG subroutine, which is called from the main program below. This is actually a standard fortran subroutine, recognized by all my unix compilers including the GNU fortran compiler (g77) and the GNU f2c/gcc translation/compilation method (fort77). It's sole purpose is to extract input data from the command line, a requirement of the CGI scripting for the web-interface. If your compiler does not recognize GETARG, no problem, just replace those lines with lines that read the inputs from standard input or a file. Also note, this code was quickly ripped from a much more complicated unsteady code, and consequently, some of the coding is not very optimised for steady calculations. Check out Version 2.0 for a much cleaner steady algorithm.


       program main
c
       parameter( npmx = 101 )
c
c----  All common blocks listed here.
c
       common/bod   / nlower, nupper, nodtot, np1, ss,
     &                x(npmx+1), y(npmx+1), xm(npmx), ym(npmx),
     &                costhe(npmx), sinthe(npmx)
       common/cof   / a(npmx,npmx+10), kutta
       common/cpd   / cp(npmx), xp
       common/inf1  / aan(npmx,npmx), bbn(npmx,npmx)
       common/sing  / q(npmx), gamma
       common/forces/ cl, cm
       character*10 argi
c
       pi = acos(-1.0)
c
c----  Retrieve parameters from the command line.
c
       call getarg(1,argi)
       read(argi,*) naca
       call getarg(2,argi)
       read(argi,*) nodtot
       call getarg(3,argi)
       read(argi,*) alpi
c
c----  Valid parameter check.
c
       if (( naca .gt. 25999 ).or.( naca .lt. 1 )) naca = 12
       if ( nodtot .lt. 20 ) nodtot = 20
       if ( nodtot .gt. 100 ) nodtot = 100
       if ( alpi .gt. 90.0 ) alpi = 90.0
       if ( alpi .lt. -90.0 ) alpi = -90.0
c
       nlower = nodtot / 2
       nupper = nodtot - nlower
       np1 = nodtot + 1
c
       alpi = alpi*pi/180
c
c----  Generate the airfoil coordinates.
c
       call airfoil(naca)
c
c----  Compute a steady solution at AOA = alpi.
c
       call steady(alpi)
c
c----  Write the data.
c
       call print_cp(naca,alpi)
c
       stop
       end

c------------------------------------------------------------------

       subroutine airfoil(naca)
c
       parameter( npmx = 101 )
c
       common/bod   / nlower, nupper, nodtot, np1, ss,
     &                x(npmx+1), y(npmx+1), xm(npmx), ym(npmx),
     &                costhe(npmx), sinthe(npmx)
c
c----  Compute the airfoil coordinates and panal angles.
c
       pi = acos( -1.0 )
c
c----  Decompose the NACA number to determine airfoil coefficients.
c
       ieps = naca / 1000
       iptmax = naca / 100 - 10 * ieps
       itau = naca - 1000 * ieps - 100 * iptmax
c
c----  Compute the coefficients.
c
       epsmax = ieps   * 0.01
       ptmax  = iptmax * 0.1
       tau    = itau   * 0.01
c
c----  Error correction for bogus NACA numbers.
c
       if (( naca .le. 9999 ) .and. ( epsmax .gt. 0 ) .and.
     &     ( ptmax .eq. 0 )) ptmax = .1
c
c----  If NACA 5 digit coding is used, make neccessary changes.
c
       if ( ieps .ge. 10 ) then
         if ( ieps .eq. 21 ) then
           ptmax = 0.0580
           ak1 = 361.4
         elseif ( ieps .eq. 22 ) then
           ptmax = 0.1260
           ak1 = 51.64
         elseif ( ieps .eq. 23 ) then
           ptmax = 0.2025
           ak1 = 15.957
         elseif ( ieps .eq. 24 ) then
           ptmax = 0.2900
           ak1 = 6.643
         elseif ( ieps .eq. 25 ) then
           ptmax = 0.3910
           ak1 = 3.230
         endif
         epsmax = ak1 * ptmax**3 / 6
       endif
c
c----  initialize indexing for lower surface.
c
       npoint = nlower
       nstart = 0
c
c----  Loop over lower surface.
c
       do n = 1, npoint
         z = ( 1 + cos( pi * ( n-1 ) / npoint )) / 2
         i = nstart + n
         call naca45(naca,tau,epsmax,ptmax,z,thick,camber,beta)
         x(i) = body_x(thick,beta,z,-1.0)
         y(i) = body_y(thick,camber,beta,-1.0)
       enddo
c
c----  Reinitialize indexing for upper surface
c
       npoint = nupper
       nstart = nlower
c
c----  Loop over upper surface.
c
       do n = 1, npoint
         z = ( 1 - cos( pi * ( n-1 ) / npoint )) / 2
         i = nstart + n
         call naca45(naca,tau,epsmax,ptmax,z,thick,camber,beta)
         x(i) = body_x(thick,beta,z,1.0)
         y(i) = body_y(thick,camber,beta,1.0)
       enddo
c
c----  Load final point.
c
       x(np1) = x(1)
       y(np1) = y(1)
c
c----  Compute slopes of panals and arc length of airfoil skin.
c
       ss = 0.0
       do i = 1, nodtot
c
c----    Control points.
c
         xm(i) = ( x(i+1) + x(i)) / 2
         ym(i) = ( y(i+1) + y(i)) / 2
c
c----    Arc length.
c
         dx = x(i+1) - x(i)
         dy = y(i+1) - y(i)
         dist = sqrt( dx**2 + dy**2 )
         ss = ss + dist
c
c----    Slope.
c
         sinthe(i) = dy / dist
         costhe(i) = dx / dist
       enddo
c
       return
       end

c------------------------------------------------------------------

       function body_x(thick,beta,z,sign)
c
c----  Compute the x coordinate of an airfoil point.
c
       body_x = z - sign * thick * sin( beta )
c
       return
       end

c------------------------------------------------------------------

       function body_y(thick,camber,beta,sign)
c
c----  Compute the y coordinate of an airfoil point.
c
       body_y = camber + sign * thick * cos( beta )
c
       return
       end

c------------------------------------------------------------------

       subroutine cofish(alpha)
c
       parameter( npmx = 101 )
c
       common/bod   / nlower, nupper, nodtot, np1, ss,
     &                x(npmx+1), y(npmx+1), xm(npmx), ym(npmx),
     &                costhe(npmx), sinthe(npmx)
       common/cof   / a(npmx,npmx+10), kutta
       common/inf1  / aan(npmx,npmx), bbn(npmx,npmx)
c
       pi = acos( -1.0 )
       pi2inv = 0.5 / pi
       kutta = nodtot + 1
       cosalf = cos( alpha )
       sinalf = sin( alpha )
c
c----  Initialize coefs.
c
       do 10 j = 1, kutta
         a(kutta,j) = 0.0
   10  continue
c
c----  Set vn = 0 at midpoint of ith panel.
c
       do 30 i = 1, nodtot
         a(i,kutta) = 0.0
c
c----    Find contribution of jth panel.
c
         do 20 j = 1, nodtot
           if ( j .eq. i ) then
             flog = 0.0
             ftan = pi
           else
             dxj  = xm(i) - x(j)
             dxjp = xm(i) - x(j+1)
             dyj  = ym(i) - y(j)
             dyjp = ym(i) - y(j+1)
             flog = alog( ( dxjp**2 + dyjp**2 )
     &                  / ( dxj**2 + dyj**2 )) / 2
             ftan = atan2( dyjp * dxj - dxjp * dyj,
     &                     dxjp * dxj + dyjp * dyj )
           endif
           ctimtj = costhe(i) * costhe(j) + sinthe(i) * sinthe(j)
           stimtj = sinthe(i) * costhe(j) - costhe(i) * sinthe(j)
           a(i,j) = pi2inv * ( ftan * ctimtj + flog * stimtj )
           bbn(i,j) = pi2inv * ( flog * ctimtj - ftan * stimtj )
           a(i,kutta) = a(i,kutta) + bbn(i,j)
           if (( i .eq. 1 ) .or. ( i .eq. nodtot )) then
             a(kutta,j) = a(kutta,j) - bbn(i,j)
             a(kutta,kutta) = a(kutta,kutta) + a(i,j)
           endif
c
c----      Load aan and bbn values now so that they don't have to be
c----      recomputed in infl.
c
           aan(i,j) = a(i,j)
   20    continue
c
c----    Fill in known sides.
c
         a(i,kutta+1) = sinthe(i) * cosalf - costhe(i) * sinalf
   30  continue
       a(kutta,kutta+1) = -( costhe(1) + costhe( nodtot )) * cosalf
     &                    -( sinthe(1) + sinthe( nodtot )) * sinalf
c
       return
       end

c------------------------------------------------------------------

       subroutine formom(alpha)
c
       parameter( npmx = 101 )
c
       common/bod   / nlower, nupper, nodtot, np1, ss,
     &                x(npmx+1), y(npmx+1), xm(npmx), ym(npmx),
     &                costhe(npmx), sinthe(npmx)
       common/cpd   / cp(npmx), xp
       common/forces/ cl, cm
c
       cosalf = cos( alpha )
       sinalf = sin( alpha )
       cfx = 0.0
       cfy = 0.0
       cm = 0.0
c
       do i = 1, nodtot
c
c----    Moment coefficient is computed about the elastic axis.
c
         xmid = xm(i) - xp
         ymid = ym(i)
         dx = x(i+1) - x(i)
         dy = y(i+1) - y(i)
         cfx = cfx + cp(i) * dy
         cfy = cfy - cp(i) * dx
         cm = cm + cp(i) * ( dx * xmid + dy * ymid )
       enddo
c
c----  Compute lift.
c
       cl = cfy * cosalf - cfx * sinalf
c
       return
       end

c------------------------------------------------------------------

       subroutine gauss(nrhs,m,nitr)
c
       parameter( npmx = 101 )
c
       common/cof   / a(npmx,npmx+10), neqns
c
c----  Performs Gaussian elimination of matrix a.
c
       np = neqns + 1
       ntot = neqns + nrhs
c
       if (( m .le. 1 ) .and. ( nitr .eq. 0 )) then
c
c----    Do full matrix elimination sequence.
c
         do 10 i = 2, neqns
           im = i - 1
c
c----      Eliminate the (i-1)th unknown from i-th through
c----      neqns-th equations.
c
           do 10 j = i, neqns
             r = a(j,im) / a(im,im)
             do 10 k = i, ntot
               a(j,k) = a(j,k) - r * a(im,k)
   10    continue
       else
c
c----    Elimination on RHS only.
c
         do 20 i = 2, neqns
           im = i - 1
           do 20 j = i, neqns
             r = a(j,im) / a(im,im)
             do 20 k = np, ntot
               a(j,k) = a(j,k) - r * a(im,k)
   20    continue
       endif
c
c----  Back subtitution.
c
       do 40 k = np, ntot
         a(neqns,k) = a(neqns,k) / a(neqns,neqns)
         do 40 l = 2, neqns
           i = neqns + 1 - l
           do 30 j = i+1, neqns
             a(i,k) = a(i,k) - a(i,j) * a(j,k)
   30      continue
           a(i,k) = a(i,k) / a(i,i)
   40  continue
c
       return
       end


c------------------------------------------------------------------

       subroutine naca45(naca,tau,epsmax,ptmax,z,thick,camber,beta)
c
c----  Compute the thickness, camber, and angular location of an
c----  airfoil point.
c
c----  Thickness, corrected when z is very small.
c
       if ( z .lt. 1.0e-10 ) then
         thick = 0.0
       else
         thick = tau * 5 * ( 0.2969 * SQRT(Z)
     &               - Z * ( 0.1260
     &               + Z * ( 0.3537
     &               - Z * ( 0.2843
     &               - Z * 0.1015))))
       endif
c
       if ( epsmax .eq. 0.0 ) then
c
c----    For NACA 4-digit symmetrical arfoils.
c
         camber = 0.0
         beta = 0.0
       else
         if ( naca .gt. 9999 ) then
c
c----      For NACA 5 digit numbers.
c
c----      Ptmax = m and epsmax = (k_1*m^3)/6 from Abbott and Doenhoff.
c
           if ( z .gt. ptmax ) then
             camber = epsmax * ( 1.0 - z )
             dcamdx = - epsmax
           else
             w = z / ptmax
             camber = epsmax * ( w**3 - 3*w**2 +(3.-ptmax)*w)
             dcamdx = epsmax/ptmax*(3*w**2 - 6*w + ( 3.0-ptmax))
           endif
         else
c
c----      For NACA 4 digit airfoils.
c
           if ( z .gt. ptmax ) then
             camber = epsmax / ( 1.0 - ptmax )**2
     &              * ( 1. + z - ptmax * 2 ) * ( 1. - z )
             dcamdx = epsmax * 2 / ( 1.0 - ptmax )**2
     &              * ( ptmax - z )
           else
             camber = epsmax / ptmax**2 * ( ptmax*2 - z ) * z
             dcamdx = epsmax * 2 / ptmax**2  * ( ptmax - z )
           endif
         endif
c
         beta = atan( dcamdx )
       endif
c
       return
       end

c------------------------------------------------------------------

       subroutine print_cp(naca,alpi)
c
       parameter( npmx = 101 )
c
       common/bod   / nlower, nupper, nodtot, np1, ss,
     &                x(npmx+1), y(npmx+1), xm(npmx), ym(npmx),
     &                costhe(npmx), sinthe(npmx)
       common/cpd   / cp(npmx), xp
c
c----  Write out data.
c
       open(8,file='cp.fmt',form='formatted',status='unknown')
       do n=1,nodtot
         write(8,*) xm(n), ym(n), cp(n)
       enddo
       close(8)
c
       return
       end

c------------------------------------------------------------------

       subroutine steady(alpha)
c
c----  alpha is angle of attack in radians, positive clockwise.
c
       call cofish(alpha)
       call gauss(1,0,0)
       call veldis(alpha)
       call formom(alpha)
c
       return
       end

c------------------------------------------------------------------

       subroutine veldis(alpha)
c
       parameter( npmx = 101 )
c
       common/bod   / nlower, nupper, nodtot, np1, ss,
     &                x(npmx+1), y(npmx+1), xm(npmx), ym(npmx),
     &                costhe(npmx), sinthe(npmx)
       common/cof   / a(npmx,npmx+10), kutta
       common/cpd   / cp(npmx), xp
       common/inf1  / aan(npmx,npmx), bbn(npmx,npmx)
       common/sing  / q(npmx), gamma
c
       cosalf = cos( alpha )
       sinalf = sin( alpha )
c
c----  Retrieve solution from a matrix.
c
       sum = 0.0
       do i = 1, nodtot
         q(i) = a(i,kutta+1)
         ds = sqrt((x(i+1)-x(i))**2 + (y(i+1)-y(i))**2)
       enddo
       gamma = a(kutta,kutta+1)
c
c----  Find vt and cp at mid-point of i-th panel.
c
       do i = 1, nodtot
         vtfree = cosalf * costhe(i) + sinalf * sinthe(i)
         vtang = vtfree
c
c----    Add contribution of j-th panel.
c
         do j = 1, nodtot
           vtang = vtang - bbn(i,j) * q(j) + gamma * aan(i,j)
         enddo
         cp(i) = 1.0 - vtang**2
       enddo
c
       return
       end 
Pages served since Oct. 17, 2000 footer image
This is an official U.S. Navy Web site.
Page content last revised on March 19, 2010, 5:20 am Send questions and comments concerning the content of this site to the webmaster.
Privacy Policy |  Accessibility Statement  |  Navy Links  |  Disclaimers  |  Intranet  |  Freedom Of Information Act Send me mail Return to my home page Visit the NPS site Visit the NPS site Return to the home page. Go up 1 level View my online resume Find out about my past and present research interests View my publication list, and download papers. Free online tools for you to use. Links to other NPS sites and utilities. View a complete index of the pages on this site. Search the whole site for specific words or word combinations.