001/* 002* NACA4Cambered -- An arbitrary cambered NACA 4 digit 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 NACA 4 031* digit airfoil section with 2 digit camber such as a 032* NACA 6409 airfoil. 033* The 1st digit is the maximum camber in percent chord. 034* The 2nd digit is the chordwise location of maximum 035* camber in tenths of chord. The last two digits are 036* the airfoil thickness in percent chord. 037* </p> 038* 039* <p> Ported from FORTRAN "NACA4.FOR" to Java by: 040* Joseph A. Huwaldt, October 8, 2000 </p> 041* 042* <p> Original FORTRAN "NACA4" code had the following note: </p> 043* 044* <pre> 045* AUTHORS - Charles L.Ladson and Cuyler W. Brooks, NASA Langley 046* Liam Hardy, NASA Ames 047* Ralph Carmichael, Public Domain Aeronautical Software 048* Last FORTRAN version: 8Aug95 1.7 RLC 049* 050* NOTES - This program has been known by the names ANALIN, FOURDIGIT and NACA4. 051* REFERENCES- NASA Technical Memorandum TM X-3284 (November, 1975) 052* "Development of a Computer Program to Obtain Ordinates for 053* NACA 4-Digit, 4-Digit Modified, 5-Digit and 16-Digit Airfoils", 054* by Charles L. Ladson and Cuyler W. Brooks, Jr., 055* NASA Langley Research Center. 056* 057* NASA Technical Memorandum TM 4741 (December 1996), 058* "Computer Program to Obtain Ordinates for NACA Airfoils", 059* by Charles L. Ladson, Cuyler W. Brooks, Jr., and Acquilla S. Hill, 060* NASA Langley Research Center and 061* Darrell W. Sproles, Computer Sciences Corporation, Hampton, VA. 062* 063* "Theory of Wing Sections", by Ira Abbott and Albert Von Doenhoff. 064* </pre> 065* 066* <p> Modified by: Joseph A. Huwaldt </p> 067* 068* @author Joseph A. Huwaldt Date: October 8, 2000 069* @version February 22, 2025 070*/ 071public class NACA4Cambered extends NACA4Uncambered { 072 073 /** 074 * The amount of camber in terms of maximum ordinate-to-chord ratio. 075 */ 076 private double CMB; 077 078 /** 079 * The position in x/c of the maximum camber. 080 */ 081 private double xCM; 082 083 084 /** 085 * Create a cambered NACA 4 digit airfoil with the 086 * specified parameters. For example: a NACA 6409 airfoil 087 * translates to: thickness = 0.09, camber = 0.06, xcamber = 0.40. 088 * 089 * @param thickness The thickness to chord ratio (e.g.: 0.09 == 9% t/c). 090 * @param camber The maximum camber ordinate-to-chord ratio 091 * (e.g.: 0.06 == 6% camber/c). 092 * @param xcamber The position of maximum camber in tenths of chord 093 * (e.g.: 0.40 == max camber at 4% chord). 094 * @param length The chord length. 095 */ 096 public NACA4Cambered(double thickness, double camber, double xcamber, double length) { 097 super(thickness, length); 098 099 CMB = camber; 100 xCM = xcamber; 101 } 102 103 104 /** 105 * Returns a string representation of this airfoil 106 * (the NACA designation of this airfoil). 107 */ 108 @Override 109 public String toString() { 110 StringBuilder buffer = new StringBuilder("NACA "); 111 112 buffer.append((int)(CMB*100)); 113 buffer.append((int)(xCM*10)); 114 115 if (TOC < 0.1) 116 buffer.append("0"); 117 buffer.append((int)(TOC*100)); 118 119 if (chord != 1.0) { 120 buffer.append(" c="); 121 buffer.append(chord); 122 } 123 return buffer.toString(); 124 } 125 126 /** 127 * Method to determine the local slope of the airfoil at 128 * the leading edge. This implementation sets the 129 * slope of the leading edge to a very large number and 130 * sets tanth to 2*CMB/xCM. 131 * This method sets the class variables: tanth, yp, ypp. 132 * 133 * @param o The ordinate data structure. The following are set: tanth, yp, ypp. 134 */ 135 @Override 136 protected void calcLESlope(Ordinate o) { 137 if (CMB < EPS) 138 o.tanth = EPS; 139 else 140 o.tanth = 2*CMB/xCM; 141 o.yp = BIG; 142 o.ypp = BIG; 143 } 144 145 /** 146 * Method to calculate the camber distribution for the airfoil. 147 * This implementation computes a camber distribution that is 148 * appropriate for a cambered NACA 4 digit airfoil. 149 * 150 * @param x The x/c location currently being calculated. 151 * @param o The ordinate data structure. The following are set: yCMB, tanth, thp. 152 * @return The following function value is returned: sqrt(1 + tanth^2). 153 */ 154 @Override 155 protected double calcCamber(double x, Ordinate o) { 156 if (x > xCM) { 157 double OneMxCM = 1 - xCM; 158 double OneMxCM2 = OneMxCM*OneMxCM; 159 o.yCMB = CMB*(1 - 2*xCM + 2*xCM*x - x*x)/OneMxCM2; 160 o.tanth = (2*xCM - 2*x)*CMB/OneMxCM2; 161 162 } else { 163 o.yCMB = CMB*(2*xCM*x - x*x)/(xCM*xCM); 164 o.tanth = 2*CMB*(1 - x/xCM)/xCM; 165 } 166 167 double func = Math.sqrt(1 + o.tanth*o.tanth); 168 169 if (x > xCM) { 170 double OneMxCM = 1 - xCM; 171 o.thp = -2*CMB/(OneMxCM*OneMxCM)/(func*func); 172 173 } else 174 o.thp = -2*CMB/(xCM*xCM)/(func*func); 175 176 return func; 177 } 178 179 180 /** 181 * Simple method to test this class. 182 * 183 * @param args the command line arguments. 184 */ 185 public static void main(String[] args) { 186 187 DecimalFormat nf = (DecimalFormat)NumberFormat.getInstance(); 188 nf.setMaximumFractionDigits(5); 189 nf.setMinimumFractionDigits(5); 190 191 System.out.println("Start NACA4Cambered..."); 192 193 System.out.println("Creating a NACA 6409 airfoil..."); 194 Airfoil af = new NACA4Cambered(0.09, 0.06, 0.4, 1); 195 196 System.out.println("Airfoil = " + af.toString()); 197 198 // Output the upper surface of the airfoil. 199 List<Point2D> upper = af.getUpper(); 200 List<Double> ypArr = af.getUpperYp(); 201 202 System.out.println(" X \t Y \t dy/dx"); 203 int length = upper.size(); 204 for (int i=0; i < length; ++i) { 205 Point2D o = upper.get(i); 206 System.out.println(" " + nf.format(o.getX()) + "\t" + nf.format(o.getY()) + 207 "\t" + nf.format(ypArr.get(i))); 208 } 209 210 System.out.println("# ordinates = " + length); 211 System.out.println("Done!"); 212 } 213} 214 215