001/*
002*   NACA5Cambered -- An arbitrary cambered NACA 5 digit unreflexed 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 unreflexed
032*       NACA 5 digit airfoil section with 3 digit camber such
033*       as a NACA 23012 airfoil.
034*       The 1st digit is defined as 2/3 of the design lift
035*       coefficient (in tenths, i.e.: 2 denotes cl = 0.3).
036*       The 2nd digit is twice the chordwise location of maximum
037*       camber in tenths of chord.  The 3rd digit of zero
038*       indicates a non-reflexed trailing edge and the
039*       last two digits indicate the thickness ratio in
040*       percent chord.
041*  </p>
042*
043*  <p> Ported from FORTRAN "NACA4.FOR" to Java by:
044*                Joseph A. Huwaldt, October 9, 2000     </p>
045*
046*  <p> Original FORTRAN "NACA4" code had the following note:  </p>
047*
048*  <pre>
049*         AUTHORS - Charles L.Ladson and Cuyler W. Brooks, NASA Langley
050*                   Liam Hardy, NASA Ames
051*                   Ralph Carmichael, Public Domain Aeronautical Software
052*         Last FORTRAN version:  8Aug95  1.7   RLC
053*
054*         NOTES - This program has been known by the names ANALIN, FOURDIGIT and NACA4.
055*         REFERENCES-  NASA Technical Memorandum TM X-3284 (November, 1975),
056*                      "Development of a Computer Program to Obtain Ordinates for
057*                      NACA 4-Digit, 4-Digit Modified, 5-Digit and 16-Digit Airfoils",
058*                      by Charles L. Ladson and Cuyler W. Brooks, Jr.,
059*                      NASA Langley Research Center.
060*
061*                      NASA Technical Memorandum TM 4741 (December 1996),
062*                      "Computer Program to Obtain Ordinates for NACA Airfoils",
063*                      by Charles L. Ladson, Cuyler W. Brooks, Jr., and Acquilla S. Hill,
064*                      NASA Langley Research Center and
065*                      Darrell W. Sproles, Computer Sciences Corporation, Hampton, VA.
066*
067*                      "Theory of Wing Sections", by Ira Abbott and Albert Von Doenhoff.
068*  </pre>
069*
070*  <p>  Modified by:  Joseph A. Huwaldt  </p>
071*
072*  @author  Joseph A. Huwaldt   Date:  October 9, 2000
073*  @version March 7, 2013
074**/
075public class NACA5Cambered extends NACA4Uncambered {
076
077        /**
078        *  The camber function K factor.
079        **/
080        private double k1;
081        
082        /**
083        *  The camber function "r" factor.
084        **/
085        private double rFactor;
086        
087        /**
088        *  The position in x/c of the maximum camber.
089        **/
090        private double xCM;
091        
092        
093        /**
094        *  Create a cambered unreflexed NACA 5 digit airfoil with the
095        *  specified parameters.  For example:  a NACA 23012 airfoil
096        *  translates to:  thickness = 0.12, cl*2/3 = 2, xcamber*2 = 0.30.
097        *  The 3rd digit must be 0 for an unreflexed airfoil.
098        *  This constructor requires the user to specify the 5 digit airfoil
099        *  k and r factors and position of max camber explicitly.
100        *  See NASA TM X-3284.
101        *
102        *  @param  thickness  The thickness to chord ratio (e.g.: 0.09 ==> 9% t/c).
103        *  @param  k1         The airfoil camber k factor as described in
104        *                     NASA TM X-3284.
105        *  @param  r          The airfoil camber r factor as described in
106        *                     NASA TM X-3284.
107        *  @param  xcamber    The position of maximum camber in tenths of chord
108        *                     (e.g.:  0.40 ==> max camber at 4% chord).
109        *  @param  length     The chord length.
110        **/
111        public NACA5Cambered(double thickness, double k1, double r, double xcamber, double length) {
112                super(thickness, length);
113                
114                this.k1 = k1;
115                rFactor = r;
116                xCM = xcamber;
117        }
118        
119        /**
120        *  Create a cambered unreflexed NACA 5 digit airfoil with the
121        *  specified parameters.  For example:  a NACA 23012 airfoil
122        *  translates to:  thickness = 0.12, cl*2/3 = 2, xcamber*2 = 0.30.
123        *  The 3rd digit must be 0 for an unreflexed airfoil.
124        *  This constructor requires the thickness and camber code (the
125        *  1st 2 digits of the airfoil designation).
126        *
127        *  @param  thickness  The thickness to chord ratio (e.g.: 0.09 ==> 9% t/c).
128        *  @param  code       The 1st 2 digits of the airfoil designation.
129        *                     Acceptable values are:  21, 22, 23, 24, and 25.
130        *  @param  length     The chord length.
131        **/
132        public NACA5Cambered(double thickness, int code, double length) {
133                super(thickness, length);
134                
135                switch (code) {
136                        case 21:
137                                xCM = 0.05;
138                                rFactor = 0.0580;
139                                k1 = 361.400;
140                                break;
141                        
142                        case 22:
143                                xCM = 0.10;
144                                rFactor = 0.1260;
145                                k1 = 51.640;
146                                break;
147                        
148                        case 23:
149                                xCM = 0.15;
150                                rFactor = 0.2025;
151                                k1 = 15.957;
152                                break;
153                        
154                        case 24:
155                                xCM = 0.20;
156                                rFactor = 0.2900;
157                                k1 = 6.643;
158                                break;
159                        
160                        case 25:
161                                xCM = 0.25;
162                                rFactor = 0.3910;
163                                k1 = 3.230;
164                                break;
165                        
166                        default:
167                                throw new IllegalArgumentException("Unknown camber code.");
168                }
169                
170                
171        }
172        
173
174        /**
175        *  Returns a string representation of this airfoil
176        *  (the NACA designation of this airfoil).
177        **/
178    @Override
179        public String toString() {
180                StringBuilder buffer = new StringBuilder("NACA 2");
181                
182                buffer.append((int)(xCM*20));
183                buffer.append("0");
184                
185                if (TOC < 0.1)
186                        buffer.append("0");
187                buffer.append((int)(TOC*100));
188                
189                if (chord != 1.0) {
190                        buffer.append(" c=");
191                        buffer.append(chord);
192                }
193                return buffer.toString();
194        }
195        
196        /**
197        *  Method to determine the local slope of the airfoil at
198        *  the leading edge.  This implementation sets the LE
199        *  slope to a very large number and sets the value for
200        *  tanth to k1*rFactor*rFactor*(3 - rFactor)/6.
201        *  This method sets the class variables:  tanth, yp, ypp.
202        *
203        *  @param  o  The ordinate data structure.  The following are set:  tanth, yp, ypp.
204        **/
205    @Override
206        protected void calcLESlope(Ordinate o) {
207                if (k1 < EPS)
208                        o.tanth = EPS;
209                else
210                        o.tanth = k1*rFactor*rFactor*(3 - rFactor)/6;
211                o.yp = BIG;
212                o.ypp = BIG;
213        }
214        
215        /**
216        *  Method to calculate the camber distribution for the airfoil.
217        *  This implementation computes a camber distribution that is
218        *  appropriate for an unreflexed NACA 5 digit cambered airfoil.
219        *  This method sets the class variables:  yCMB, tanth, thp.
220        *
221        *  @param  x  The x/c location currently being calculated.
222        *  @param  o  The ordinate data structure. The following are set: yCMB, tanth, thp.
223        *  @return The following function value is returned: sqrt(1 + tanth^2).
224        **/
225    @Override
226        protected double calcCamber(double x, Ordinate o) {
227        
228                double r2 = rFactor*rFactor;
229                
230                if (x > rFactor) {
231                        double r3 = r2*rFactor;
232                        o.yCMB = k1*r3*(1 - x)/6;
233                        o.tanth = -k1*r3/6;
234                        
235                } else {
236                        double x2 = x*x;
237                        double x3 = x2*x;
238                        o.yCMB = k1*(x3 - 3*rFactor*x2 + r2*(3 - rFactor)*x)/6;
239                        o.tanth = k1*(3*x2 - 6*rFactor*x + r2*(3 - rFactor))/6;
240                }
241                
242                double func = Math.sqrt(1 + o.tanth*o.tanth);
243                
244                if (x > rFactor) {
245                        o.thp = 0;
246                        
247                } else 
248                        o.thp = k1*(x - rFactor)/(func*func);
249                
250                return func;
251        }
252        
253        /**
254        *  Simple method to test this class.
255        **/
256        public static void main(String[] args) {
257        
258                DecimalFormat nf = (DecimalFormat)NumberFormat.getInstance();
259                nf.setMaximumFractionDigits(5);
260                nf.setMinimumFractionDigits(5);
261                
262                System.out.println("Start NACA5Cambered...");
263                
264                System.out.println("Creating a NACA 23012 airfoil...");
265                Airfoil af = new NACA5Cambered(0.12, 23, 1);
266                
267                System.out.println("Airfoil = " + af.toString());
268                
269                //      Output the upper surface of the airfoil.
270                List<Point2D> upper = af.getUpper();
271                List<Double> ypArr = af.getUpperYp();
272                
273                System.out.println("        X    \t    Y    \t    dy/dx");
274                int length = upper.size();
275                for (int i=0; i < length; ++i) {
276                        Point2D o = upper.get(i);
277                        System.out.println("    " + nf.format(o.getX()) + "\t" + nf.format(o.getY()) +
278                                                                        "\t" + nf.format(ypArr.get(i)));
279                }
280                
281                System.out.println("# ordinates = " + length);
282                System.out.println("Done!");
283        }
284}
285
286