001/*
002*   NACA5Reflexed -- An arbitrary cambered NACA 5 digit reflexed airfoil.
003*
004*   Copyright (C) 2000-2025, by Joseph A. Huwaldt. All rights reserved.
005*   
006*   This library is free software; you can redistribute it and/or
007*   modify it under the terms of the GNU Lesser General Public
008*   License as published by the Free Software Foundation; either
009*   version 2.1 of the License, or (at your option) any later version.
010*   
011*   This library is distributed in the hope that it will be useful,
012*   but WITHOUT ANY WARRANTY; without even the implied warranty of
013*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014*   Lesser General Public License for more details.
015*
016*   You should have received a copy of the GNU Lesser General Public License
017*   along with this program; if not, write to the Free Software
018*   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
019*   Or visit:  http://www.gnu.org/licenses/lgpl.html
020*/
021package jahuwaldt.aero.airfoils;
022
023import java.util.List;
024import java.awt.geom.Point2D;
025import java.text.DecimalFormat;
026import java.text.NumberFormat;
027
028
029/**
030*  <p> This class represents an arbitrary cambered, reflexed,
031*      NACA 5 digit airfoil section with 3 digit camber such
032*      as a NACA 23112 airfoil.
033*      The 1st digit is defined as 2/3 of the design lift
034*      coefficient (in tenths, i.e.: 2 denotes cl = 0.3).
035*      The 2nd digit is twice the chordwise location of maximum
036*      camber in tenths of chord.  The 3rd digit of one
037*      indicates a reflexed trailing edge and the
038*      last two digits indicate the thickness ratio in
039*      percent chord.
040*  </p>
041*
042*  <p> Ported from FORTRAN "NACA4.FOR" to Java by:
043*                Joseph A. Huwaldt, October 11, 2000     </p>
044*
045*  <p> Original FORTRAN "NACA4" code had the following note:  </p>
046*
047*  <pre>
048*         AUTHORS - Charles L.Ladson and Cuyler W. Brooks, NASA Langley
049*                   Liam Hardy, NASA Ames
050*                   Ralph Carmichael, Public Domain Aeronautical Software
051*         Last FORTRAN version:  8Aug95  1.7   RLC
052*
053*         NOTES - This program has been known by the names ANALIN, FOURDIGIT and NACA4.
054*         REFERENCES-  NASA Technical Memorandum TM X-3284 (November, 1975),
055*                      "Development of a Computer Program to Obtain Ordinates for
056*                      NACA 4-Digit, 4-Digit Modified, 5-Digit and 16-Digit Airfoils",
057*                      by Charles L. Ladson and Cuyler W. Brooks, Jr.,
058*                      NASA Langley Research Center.
059*
060*                      NASA Technical Memorandum TM 4741 (December 1996),
061*                      "Computer Program to Obtain Ordinates for NACA Airfoils",
062*                      by Charles L. Ladson, Cuyler W. Brooks, Jr., and Acquilla S. Hill,
063*                      NASA Langley Research Center and
064*                      Darrell W. Sproles, Computer Sciences Corporation, Hampton, VA.
065*
066*                      "Theory of Wing Sections", by Ira Abbott and Albert Von Doenhoff.
067*  </pre>
068*
069*  <p>  Modified by:  Joseph A. Huwaldt  </p>
070*
071*  @author  Joseph A. Huwaldt   Date:  October 11, 2000
072*  @version February 22, 2025
073*/
074public class NACA5Reflexed extends NACA4Uncambered {
075
076        /**
077        *  The camber function K factor.
078        */
079        private double k1;
080        
081        /**
082        *  The camber function k2/k1.
083        */
084        private double k2ok1;
085        
086        /**
087        *  The camber function "r" factor.
088        */
089        private double rFactor;
090        
091        /**
092        *  The postion in x/c of the maximum camber.
093        */
094        private double xCM;
095        
096        
097        /**
098        *  Create a cambered reflexed NACA 5 digit airfoil with the
099        *  specified parameters.  For example:  a NACA 23112 airfoil
100        *  translates to:  thickness = 0.12, cl*2/3 = 2, xcamber*2 = 0.30.
101        *  The 3rd digit must be 1 for a reflexed airfoil.
102        *  This constructor requires the user to specify the 5 digit airfoil
103        *  k and r factors and position of max camber explicitly.
104        *  See NASA TM X-3284.
105        *
106        *  @param  thickness  The thickness to chord ratio (e.g.: 0.09 == 9% t/c).
107        *  @param  k1         The airfoil camber k1 factor as described in
108        *                     NASA TM X-3284.
109        *  @param  k2ok1      The ratio of the k2 to k1 camber factors as
110        *                     described in NASA TM X-3284.
111        *  @param  r          The airfoil camber r factor as described in
112        *                     NASA TM X-3284.
113        *  @param  xcamber    The position of maximum camber in tenths of chord
114        *                     (e.g.:  0.40 == max camber at 4% chord).
115        *  @param  length     The chord length.
116        */
117        public NACA5Reflexed(double thickness, double k1, double k2ok1, double r,
118                                                        double xcamber, double length) {
119                super(thickness, length);
120                
121                this.k1 = k1;
122                this.k2ok1 = k2ok1;
123                rFactor = r;
124                xCM = xcamber;
125        }
126        
127        /**
128        *  Create a cambered reflexed NACA 5 digit airfoil with the
129        *  specified parameters.  For example:  a NACA 23112 airfoil
130        *  translates to:  thickness = 0.12, cl*2/3 = 2, xcamber*2 = 0.30.
131        *  The 3rd digit must be 1 for a reflexed airfoil.
132        *  This constructor requires the thickness and camber code (the
133        *  1st 2 digits of the airfoil designation).
134        *
135        *  @param  thickness  The thickness to chord ratio (e.g.: 0.09 == 9% t/c).
136        *  @param  code       The 1st 2 digits of the airfoil designation.
137        *                     Acceptable values are:  22, 23, 24, and 25.
138        *  @param  length     The chord length.
139        */
140        public NACA5Reflexed(double thickness, int code, double length) {
141                super(thickness, length);
142                
143                switch (code) {
144                        case 22:
145                                xCM = 0.10;
146                                rFactor = 0.1300;
147                                k1 = 51.990;
148                                k2ok1 = 0.000764;
149                                break;
150                        
151                        case 23:
152                                xCM = 0.15;
153                                rFactor = 0.2170;
154                                k1 = 15.793;
155                                k2ok1 = 0.00677;
156                                break;
157                        
158                        case 24:
159                                xCM = 0.20;
160                                rFactor = 0.3180;
161                                k1 = 6.520;
162                                k2ok1 = 0.0303;
163                                break;
164                        
165                        case 25:
166                                xCM = 0.25;
167                                rFactor = 0.4410;
168                                k1 = 3.191;
169                                k2ok1 = 0.1355;
170                                break;
171                        
172                        default:
173                                throw new IllegalArgumentException("Unknown camber code.");
174                }
175                
176                
177        }
178        
179
180        /**
181        *  Returns a string representation of this airfoil
182        *  (the NACA designation of this airfoil).
183        */
184    @Override
185        public String toString() {
186                StringBuilder buffer = new StringBuilder("NACA 2");
187                
188                buffer.append((int)(xCM*20));
189                buffer.append("1");
190                
191                if (TOC < 0.1)
192                        buffer.append("0");
193                buffer.append((int)(TOC*100));
194                
195                if (chord != 1.0) {
196                        buffer.append(" c=");
197                        buffer.append(chord);
198                }
199                return buffer.toString();
200        }
201        
202        //-----------------------------------------------------------------------------------
203
204        /**
205        *  Method to determine the local slope of the airfoil at
206        *  the leading edge.  This implementation sets the LE
207        *  slope to a very large number and computes a value for
208        *  tanth that is appropriate for a NACA 5 digit reflexed
209        *  airfoil.
210        *  This method sets the class variables:  tanth, yp, ypp.
211        *
212        *  @param  o  The ordinate data structure.  The following are set:  tanth, yp, ypp.
213        */
214    @Override
215        protected void calcLESlope(Ordinate o) {
216                if (k1 < EPS)
217                        o.tanth = EPS;
218                else {
219                        double r2 = rFactor*rFactor;
220                        double oneMr = 1 - rFactor;
221                        double oneMr3 = oneMr*oneMr*oneMr;
222                        o.tanth = k1*(3*r2 - k2ok1*oneMr3 - r2*rFactor)/6;
223                }
224                o.yp = BIG;
225                o.ypp = BIG;
226        }
227        
228        /**
229        *  Method to calculate the camber distribution for the airfoil.
230        *  This method computes a camber distribution that is appropriate
231        *  for a NACA 5 digit reflexed airfoil.
232        *  This method sets the class variables:  yCMB, tanth, thp.
233        *
234        *  @param  x  The x/c location currently being calculated.
235        *  @param  o  The ordinate data structure. The following are set: yCMB, tanth, thp.
236        *  @return The following function value is returned: sqrt(1 + tanth^2).
237        */
238    @Override
239        protected double calcCamber(double x, Ordinate o) {
240        
241                double r3 = rFactor*rFactor*rFactor;
242                double oneMr = 1 - rFactor;
243                double oneMr3 = oneMr*oneMr*oneMr;
244                double xMr = x - rFactor;
245                double xMr2 = xMr*xMr;
246                
247                if (x > rFactor) {
248                        o.yCMB = k1*(k2ok1*xMr2*xMr - k2ok1*oneMr3*x - r3*x + r3)/6;
249                        o.tanth = k1*(3*k2ok1*xMr2 - k2ok1*oneMr3 - r3)/6;
250                        
251                } else {
252                        o.yCMB = k1*(xMr2*xMr - k2ok1*oneMr3*x - r3*x + r3)/6;
253                        o.tanth = k1*(3*xMr2 - k2ok1*oneMr3 - r3)/6;
254                }
255                
256                double func = Math.sqrt(1 + o.tanth*o.tanth);
257                
258                if (x > rFactor) {
259                        o.thp = k2ok1*k1*xMr/(func*func);
260                        
261                } else 
262                        o.thp = k1*xMr/(func*func);
263                
264                return func;
265        }
266        
267        //-----------------------------------------------------------------------------------
268
269        /**
270        *  Simple method to test this class.
271        *
272        * @param args the command-line arguments
273        */
274        public static void main(String[] args) {
275        
276                DecimalFormat nf = (DecimalFormat)NumberFormat.getInstance();
277                nf.setMaximumFractionDigits(5);
278                nf.setMinimumFractionDigits(5);
279                
280                System.out.println("Start NACA5Reflexed...");
281                
282                System.out.println("Creating a NACA 23112 airfoil...");
283                Airfoil af = new NACA5Reflexed(0.12, 23, 1);
284                
285                System.out.println("Airfoil = " + af.toString());
286                
287                //      Output the upper surface of the airfoil.
288                List<Point2D> upper = af.getUpper();
289                List<Double> ypArr = af.getUpperYp();
290                
291                System.out.println("        X    \t    Y    \t    dy/dx");
292                int length = upper.size();
293                for (int i=0; i < length; ++i) {
294                        Point2D o = upper.get(i);
295                        System.out.println("    " + nf.format(o.getX()) + "\t" + nf.format(o.getY()) +
296                                                                        "\t" + nf.format(ypArr.get(i)));
297                }
298                
299                System.out.println("# ordinates = " + length);
300                System.out.println("Done!");
301        }
302}
303
304