GEVfoil

GEVfoil: NACA 4 Series Update

TIt’s been nearly a decade since I wrote the original NACA 4 series aerofoil script, with a ‘to-do’ that I had assumed I would address in days, not years…

That post is available here: GEVfoil: NACA 4 Series

I have, finally, made the small adjustments to the code to address to the ‘to-do’. Hooray, it is done! Hopefully, the motivation is clear when comparing the original and updated script. Previously, I had used linear spacing and despite my confidence in the RDP algorithm (Ramer–Douglas–Peucker algorithm) implementation, there have been deficiencies at the leading edge.

GEVfoil: DHMTU aerofoil implementation in GEVfoil

Introduction

Following on from the previous post, on the definition of the DHMTU aerofoil, an initial implementation of this ground-effect specific aerofoil type has been created for GEVfoil. Through the Wing In Ground Effect group on groups.io, a Matlab script was discovered. This Matlab code was created by Martin Hepperl (of JavaFoil [1] fame), in 2012. Thankfully, the Matlab script is open-source, and thus could be translated directly into Python without fear of breaching copyright.

GEVfoil: Introducing GEVfoil

I have decided to rename my little aerofoil project. I found no fewer than four other projects using the previous name, which I’ll avoid stating to reduce confusing search engines any further.

GEVfoil Logo

I’ve settled on GEVfoil (Ground Effect Vehicle Aerofoil) which may seem a little obvious, but clarity should at least be in my favour. The objectives remain the same:

  • To create a set of tools to aid in the analysis of aerofoils in ground effect.
  • To primarily focus on 2D effects, but not exclude 3D effects where appropriate and relevant.
  • To utilise open-source tools as much as possible, for example links into the OpenFOAM CFD (Computational Fluid Dynamics) project.
  • To maintain a blog of the development, and open-source the whole project when it has content enough to be worthy.

I have renamed previous blog posts with this in mind:

GEVfoil: Ramer–Douglas–Peucker algorithm

Generally speaking, for low-speed flow around an aerofoil, the largest gradients in the flow-properties coincide with the greatest curvature of the aerofoil, and thus are the region that requires the greatest concentration of cells (or nodes) in the computational domain.

Many of the simplified treatments for spacing points along an aerofoil use a logarithmic spacing biased towards the leading edge. This of course can create issues if spaced in the chord-wise direction (x/c). The surface-normal at the leading edge of a symmetric aerofoil is perpendicular to the stream-wise direction, and thus can become under-resolved, and even faceted, with a simple linear or logarithmic chord-wise spacing.

GEVfoil: NACA 4 Series Part 2 and CSV Reading

Previously I had made a simple function that will generate a number of points/coordinates for any specified NACA 4 series aerofoil. The limitation with this approach was that it did a fairly poor job at capturing the leading-edge. The leading edge is of critical importance to the aerodynamic performance and characteristics of the aerofoil. After some consideration, I have decided not to modify this technique. I am designing the GEVfoil tools to be as modular, generic and extendable as possible. This isn’t to say I am neglecting the importance of the leading edge, or that the method is flawed.

GEVfoil: NACA 4 Series

The intention behind GEVfoil is to establish an open-source set of Python classes to handle aerofoils (American English: airfoils). The intention is that these can be used for anything from generating simple point clouds, analytical representations all the way to STL files for CFD meshing and OpenFOAM BlockMesh output.

The first step is starting with something basic, in this case a simple class to generate NACA 4 series aerofoils:

import numpy as np
import matplotlib.pyplot as plt
 
class NACA4(object):
    """A class for generating  NACA 4 series aerofoils
        TO-DO - linspace not good at LE capture """
    def __init__(self, foil, points=200, chord=1):
        super(NACA4, self).__init__()
        m = float(foil[0])/100      # max camber
        p = float(foil[1])/10       # chordwise position of max camber
        t = float(foil[2:])/100     # thickness
        x = np.linspace(0, chord, points)
        self.x = x
        yt = self.thickness(x, t)
        yc = []
        for coord in x:
            if m:
                yc.append(self.camber(m, p, coord))
            else:
                # No camber
                yc.append(0)
        y1 = yc + yt
        y2 = yc - yt
 
        self.y = y1
 
        plt.plot(self.x, yc)
        plt.plot(self.x, y1, '.')
        plt.plot(self.x, y2, '.')
        plt.axis('equal')
        plt.show()
 
    def thickness(self, x, t):
        # Y thickness at given x point
        return t / 0.2 * \
            (0.2969*np.sqrt(x)-0.126*x-0.3516*x**2+0.2843*x**3-0.1015*x**4)
 
    def camber(self, m, p, x):
        # Return the camber of the aerofoil
        if x <= p:
            return m/p**2 * (2*p*x-x**2)
        return m/(1-p)**2*((1-2*p)+2*p*x-x**2)
 
if __name__ == "__main__":
    test = NACA4('2412')

For now, Matplotlib has been built into the class for visual reference. For example, 2412 generates: NACA 2412