001/*
002*   NACA4Cambered -- An arbitrary cambered NACA 4 digit airfoil.
003*
004*   Copyright (C) 2000-2013 by Joseph A. Huwaldt
005*   All rights reserved.
006*   
007*   This library is free software; you can redistribute it and/or
008*   modify it under the terms of the GNU Lesser General Public
009*   License as published by the Free Software Foundation; either
010*   version 2.1 of the License, or (at your option) any later version.
011*   
012*   This library is distributed in the hope that it will be useful,
013*   but WITHOUT ANY WARRANTY; without even the implied warranty of
014*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015*   Lesser General Public License for more details.
016*
017*   You should have received a copy of the GNU Lesser General Public License
018*   along with this program; if not, write to the Free Software
019*   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
020*   Or visit:  http://www.gnu.org/licenses/lgpl.html
021**/
022package jahuwaldt.aero.airfoils;
023
024import java.util.List;
025import java.awt.geom.Point2D;
026import java.text.DecimalFormat;
027import java.text.NumberFormat;
028
029
030/**
031*  <p> This class represents an arbitrary cambered NACA 4
032*      digit airfoil section with 2 digit camber such as a
033*      NACA 6409 airfoil.
034*      The 1st digit is the maximum camber in percent chord.
035*      The 2nd digit is the chordwise location of maximum
036*      camber in tenths of chord.  The last two digits are
037*      the airfoil thickness in percent chord.
038*  </p>
039*
040*  <p> Ported from FORTRAN "NACA4.FOR" to Java by:
041*                Joseph A. Huwaldt, October 8, 2000     </p>
042*
043*  <p> Original FORTRAN "NACA4" code had the following note:  </p>
044*
045*  <pre>
046*         AUTHORS - Charles L.Ladson and Cuyler W. Brooks, NASA Langley
047*                   Liam Hardy, NASA Ames
048*                   Ralph Carmichael, Public Domain Aeronautical Software
049*         Last FORTRAN version:  8Aug95  1.7   RLC
050*
051*         NOTES - This program has been known by the names ANALIN, FOURDIGIT and NACA4.
052*         REFERENCES-  NASA Technical Memorandum TM X-3284 (November, 1975)
053*                      "Development of a Computer Program to Obtain Ordinates for
054*                      NACA 4-Digit, 4-Digit Modified, 5-Digit and 16-Digit Airfoils",
055*                      by Charles L. Ladson and Cuyler W. Brooks, Jr.,
056*                      NASA Langley Research Center.
057*
058*                      NASA Technical Memorandum TM 4741 (December 1996),
059*                      "Computer Program to Obtain Ordinates for NACA Airfoils",
060*                      by Charles L. Ladson, Cuyler W. Brooks, Jr., and Acquilla S. Hill,
061*                      NASA Langley Research Center and
062*                      Darrell W. Sproles, Computer Sciences Corporation, Hampton, VA.
063*
064*                      "Theory of Wing Sections", by Ira Abbott and Albert Von Doenhoff.
065*  </pre>
066*
067*  <p>  Modified by:  Joseph A. Huwaldt  </p>
068*
069*  @author  Joseph A. Huwaldt   Date:  October 8, 2000
070*  @version March 7, 2013
071**/
072public class NACA4Cambered extends NACA4Uncambered {
073
074        /**
075        *  The amount of camber in terms of maximum ordinate-to-chord ratio.
076        **/
077        private double CMB;
078        
079        /**
080        *  The position in x/c of the maximum camber.
081        **/
082        private double xCM;
083        
084        
085        /**
086        *  Create a cambered NACA 4 digit airfoil with the
087        *  specified parameters.  For example:  a NACA 6409 airfoil
088        *  translates to:  thickness = 0.09, camber = 0.06, xcamber = 0.40.
089        *
090        *  @param  thickness  The thickness to chord ratio (e.g.: 0.09 ==> 9% t/c).
091        *  @param  camber     The maximum camber ordinate-to-chord ratio
092        *                     (e.g.:  0.06 ==> 6% camber/c).
093        *  @param  xcamber    The position of maximum camber in tenths of chord
094        *                     (e.g.:  0.40 ==> max camber at 4% chord).
095        *  @param  length     The chord length.
096        **/
097        public NACA4Cambered(double thickness, double camber, double xcamber, double length) {
098                super(thickness, length);
099                
100                CMB = camber;
101                xCM = xcamber;
102        }
103        
104
105        /**
106        *  Returns a string representation of this airfoil
107        *  (the NACA designation of this airfoil).
108        **/
109    @Override
110        public String toString() {
111                StringBuilder buffer = new StringBuilder("NACA ");
112                
113                buffer.append((int)(CMB*100));
114                buffer.append((int)(xCM*10));
115                
116                if (TOC < 0.1)
117                        buffer.append("0");
118                buffer.append((int)(TOC*100));
119                
120                if (chord != 1.0) {
121                        buffer.append(" c=");
122                        buffer.append(chord);
123                }
124                return buffer.toString();
125        }
126        
127        /**
128        *  Method to determine the local slope of the airfoil at
129        *  the leading edge.  This implementation sets the
130        *  slope of the leading edge to a very large number and
131        *  sets tanth to 2*CMB/xCM.
132        *  This method sets the class variables:  tanth, yp, ypp.
133        *
134        *  @param  o  The ordinate data structure.  The following are set:  tanth, yp, ypp.
135        **/
136    @Override
137        protected void calcLESlope(Ordinate o) {
138                if (CMB < EPS)
139                        o.tanth = EPS;
140                else
141                        o.tanth = 2*CMB/xCM;
142                o.yp = BIG;
143                o.ypp = BIG;
144        }
145        
146        /**
147        *  Method to calculate the camber distribution for the airfoil.
148        *  This implementation computes a camber distribution that is
149        *  appropriate for a cambered NACA 4 digit airfoil.
150        *
151        *  @param  x  The x/c location currently being calculated.
152        *  @param  o  The ordinate data structure. The following are set: yCMB, tanth, thp.
153        *  @return The following function value is returned: sqrt(1 + tanth^2).
154        **/
155    @Override
156        protected double calcCamber(double x, Ordinate o) {
157                if (x > xCM) {
158                        double OneMxCM = 1 - xCM;
159                        double OneMxCM2 = OneMxCM*OneMxCM;
160                        o.yCMB = CMB*(1 - 2*xCM + 2*xCM*x - x*x)/OneMxCM2;
161                        o.tanth = (2*xCM - 2*x)*CMB/OneMxCM2;
162                        
163                } else {
164                        o.yCMB = CMB*(2*xCM*x - x*x)/(xCM*xCM);
165                        o.tanth = 2*CMB*(1 - x/xCM)/xCM;
166                }
167                
168                double func = Math.sqrt(1 + o.tanth*o.tanth);
169                
170                if (x > xCM) {
171                        double OneMxCM = 1 - xCM;
172                        o.thp = -2*CMB/(OneMxCM*OneMxCM)/(func*func);
173                        
174                } else 
175                        o.thp = -2*CMB/(xCM*xCM)/(func*func);
176                
177                return func;
178        }
179
180        
181        /**
182        *  Simple method to test this class.
183        **/
184        public static void main(String[] args) {
185        
186                DecimalFormat nf = (DecimalFormat)NumberFormat.getInstance();
187                nf.setMaximumFractionDigits(5);
188                nf.setMinimumFractionDigits(5);
189                
190                System.out.println("Start NACA4Cambered...");
191                
192                System.out.println("Creating a NACA 6409 airfoil...");
193                Airfoil af = new NACA4Cambered(0.09, 0.06, 0.4, 1);
194                
195                System.out.println("Airfoil = " + af.toString());
196                
197                //      Output the upper surface of the airfoil.
198                List<Point2D> upper = af.getUpper();
199                List<Double> ypArr = af.getUpperYp();
200                
201                System.out.println("        X    \t    Y    \t    dy/dx");
202                int length = upper.size();
203                for (int i=0; i < length; ++i) {
204                        Point2D o = upper.get(i);
205                        System.out.println("    " + nf.format(o.getX()) + "\t" + nf.format(o.getY()) +
206                                                                        "\t" + nf.format(ypArr.get(i)));
207                }
208                
209                System.out.println("# ordinates = " + length);
210                System.out.println("Done!");
211        }
212}
213
214