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