001/*
002*   NACA4ModCambered -- An arbitrary cambered NACA 4 digit modified airfoil.
003*
004*   Copyright (C) 2000-2012, 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
032*      modified 4 digit airfoil section with 2 digit camber
033*      such as a NACA 2512-34 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 next two digits are
037*      the airfoil thickness in percent chord.  The 1st digit
038*      after the hyphen is the leading edge radius index and
039*      the last digit after the hyphen is the position of
040*      maximum thickness in tenths of chord.
041*  </p>
042*
043*  <p> Ported from FORTRAN "NACA4.FOR" to Java by:
044*                Joseph A. Huwaldt, October 20, 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 20, 2000
073*  @version September 15, 2012
074**/
075public class NACA4ModCambered extends NACA4ModUncambered {
076
077        /**
078        *  The amount of camber in terms of maximum ordinate-to-chord ratio.
079        **/
080        private double CMB;
081        
082        /**
083        *  The position in x/c of the maximum camber.
084        **/
085        private double xCM = 0.50;
086        
087        
088        /**
089        *  Create a cambered NACA modified 4 digit airfoil with the
090        *  specified parameters.  For example:  a NACA 2512-34 airfoil
091        *  translates to:  thickness = 0.12, camber = 0.02, xcamber = 0.50,
092        *                  Rle = 0.003967, and xThickness = 0.40.
093        *
094        *  @param  thickness  The thickness to chord ratio (e.g.: 0.09 ==> 9% t/c).
095        *  @param  camber     The maximum camber ordinate-to-chord ratio
096        *                     (e.g.:  0.06 ==> 6% camber/c).
097        *  @param  xcamber    The position of maximum camber in tenths of chord
098        *                     (e.g.:  0.40 ==> max camber at 4% chord).
099        *  @param  Rle        The radius of the leading edge of the airfoil in
100        *                     percent chord.
101        *  @param  xThickness The position of maximum thickness in percent chord
102        *                     (e.g.:  0.40 => 40% t/c).
103        *  @param  length     The chord length.
104        **/
105        public NACA4ModCambered(double thickness, double camber, double xcamber,
106                                                                double Rle, double xThickness, double length) {
107                super(thickness, Rle, xThickness, length);
108                
109                CMB = camber;
110                xCM = xcamber;
111        }
112        
113
114        /**
115        *  Create a cambered NACA modified 4 digit airfoil with the
116        *  specified parameters.  For example:  a NACA 2512-34 airfoil
117        *  translates to:  thickness = 0.12, camber = 0.02, xcamber = 0.50,
118        *                  LEindex = 3, xThickness = 0.40..
119        *
120        *  @param  thickness  The thickness to chord ratio (e.g.: 0.09 ==> 9% t/c).
121        *  @param  camber     The maximum camber ordinate-to-chord ratio
122        *                     (e.g.:  0.06 ==> 6% camber/c).
123        *  @param  xcamber    The position of maximum camber in tenths of chord
124        *                     (e.g.:  0.40 ==> max camber at 4% chord).
125        *  @param  LEindex    The leading edge radius index for this airfoil.  Should
126        *                     be a number from 1 to 8.
127        *  @param  xThickness The position of maximum thickness in percent chord
128        *                     (e.g.:  0.40 => 40% t/c).
129        *  @param  length     The chord length.
130        **/
131        public NACA4ModCambered(double thickness, double camber, double xcamber,
132                                                                int LEindex, double xThickness, double length) {
133                super(thickness, LEindex, xThickness, length);
134                
135                CMB = camber;
136                xCM = xcamber;
137        }
138        
139        /**
140        *  Returns a string representation of this airfoil
141        *  (the NACA designation of this airfoil).
142        **/
143    @Override
144        public String toString() {
145                StringBuilder buffer = new StringBuilder("NACA ");
146                
147                buffer.append((int)(CMB*100));
148                buffer.append((int)(xCM*10));
149                
150                if (TOC < 0.1)
151                        buffer.append("0");
152                buffer.append((int)(TOC*100));
153                
154                buffer.append("-");
155                
156                if (leIndex == 0)
157                        buffer.append("?");
158                else
159                        buffer.append(leIndex);
160                
161                buffer.append((int)(xMaxT*10));
162                
163                if (chord != 1.0) {
164                        buffer.append(" c=");
165                        buffer.append(chord);
166                }
167                return buffer.toString();
168        }
169        
170        //-----------------------------------------------------------------------------------
171
172        /**
173        *  Method to determine the local slope of the airfoil at
174        *  the leading edge.  This implementation sets the LE
175        *  slope to a very large number and sets the tanth
176        *  parameter to 2*CMB/xCM just as the NACA 4 digit
177        *  uncambered implementation does.
178        *  This method sets the class variables:  tanth, yp, ypp.
179        *
180        *  @param  o  The ordinate data structure.  The following are set:  tanth, yp, ypp.
181        **/
182    @Override
183        protected void calcLESlope(Ordinate o) {
184                if (CMB < EPS)
185                        o.tanth = EPS;
186                else
187                        o.tanth = 2*CMB/xCM;
188                o.yp = BIG;
189                o.ypp = BIG;
190        }
191        
192        /**
193        *  Method to calculate the camber distribution for the airfoil.
194        *  This implementation computes a camber distribution that is
195        *  appropriate for a modified, NACA 4 digit, cambered airfoil.
196        *  This method sets the class variables:  yCMB, tanth, thp.
197        *
198        *  @param  x  The x/c location currently being calculated.
199        *  @param  o  The ordinate data structure. The following are set: yCMB, tanth, thp.
200        *  @return The following function value is returned: sqrt(1 + tanth^2).
201        **/
202    @Override
203        protected double calcCamber(double x, Ordinate o) {
204                if (x > xCM) {
205                        double OneMxCM = 1 - xCM;
206                        double OneMxCM2 = OneMxCM*OneMxCM;
207                        o.yCMB = CMB*(1 - 2*xCM + 2*xCM*x - x*x)/OneMxCM2;
208                        o.tanth = (2*xCM - 2*x)*CMB/OneMxCM2;
209                        
210                } else {
211                        o.yCMB = CMB*(2*xCM*x - x*x)/(xCM*xCM);
212                        o.tanth = 2*CMB*(1 - x/xCM)/xCM;
213                }
214                
215                double func = Math.sqrt(1 + o.tanth*o.tanth);
216                
217                if (x > xCM) {
218                        double OneMxCM = 1 - xCM;
219                        o.thp = -2*CMB/(OneMxCM*OneMxCM)/(func*func);
220                        
221                } else 
222                        o.thp = -2*CMB/(xCM*xCM)/(func*func);
223                
224                return func;
225        }
226        
227        //-----------------------------------------------------------------------------------
228
229        /**
230        *  Simple method to test this class.
231        **/
232        public static void main(String[] args) {
233        
234                DecimalFormat nf = (DecimalFormat)NumberFormat.getInstance();
235                nf.setMaximumFractionDigits(5);
236                nf.setMinimumFractionDigits(5);
237                
238                System.out.println("Start NACA4ModCambered...");
239                
240                System.out.println("Creating a NACA 6409-34 airfoil...");
241                Airfoil af = new NACA4ModCambered(0.09, 0.06, 0.4, 3, 0.4, 1);
242                
243                System.out.println("Airfoil = " + af.toString());
244                
245                //      Output the upper surface of the airfoil.
246                List<Point2D> upper = af.getUpper();
247                List<Double> ypArr = af.getUpperYp();
248                
249                System.out.println("        X    \t    Y    \t    dy/dx");
250                int length = upper.size();
251                for (int i=0; i < length; ++i) {
252                        Point2D o = upper.get(i);
253                        System.out.println("    " + nf.format(o.getX()) + "\t" + nf.format(o.getY()) +
254                                                                        "\t" + nf.format(ypArr.get(i)));
255                }
256                
257                System.out.println("# ordinates = " + length);
258                System.out.println("Done!");
259        }
260}
261
262