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