1 package net.sf.openrocket.util;
3 import static net.sf.openrocket.aerodynamics.AtmosphericConditions.GAMMA;
4 import static net.sf.openrocket.aerodynamics.AtmosphericConditions.R;
7 import java.io.PrintStream;
8 import java.util.Arrays;
10 import net.sf.openrocket.aerodynamics.AerodynamicCalculator;
11 import net.sf.openrocket.aerodynamics.AerodynamicForces;
12 import net.sf.openrocket.aerodynamics.AtmosphericConditions;
13 import net.sf.openrocket.aerodynamics.BarrowmanCalculator;
14 import net.sf.openrocket.aerodynamics.ExactAtmosphericConditions;
15 import net.sf.openrocket.aerodynamics.FlightConditions;
16 import net.sf.openrocket.document.OpenRocketDocument;
17 import net.sf.openrocket.file.GeneralRocketLoader;
18 import net.sf.openrocket.file.RocketLoadException;
19 import net.sf.openrocket.file.RocketLoader;
20 import net.sf.openrocket.rocketcomponent.Configuration;
22 public class Analysis {
24 private static final double MACH_MIN = 0.01;
25 private static final double MACH_MAX = 5.00001;
26 private static final double MACH_STEP = 0.02;
28 private static final double AOA_MACH = 0.6;
29 private static final double AOA_MIN = 0;
30 private static final double AOA_MAX = 15.00001*Math.PI/180;
31 private static final double AOA_STEP = 0.5*Math.PI/180;
33 private static final double REYNOLDS = 9.8e6;
34 private static final double STAG_TEMP = 330;
37 private final RocketLoader loader = new GeneralRocketLoader();
38 private final AerodynamicCalculator calculator = new BarrowmanCalculator();
40 private final FlightConditions conditions;
41 private final double length;
43 private final Configuration config;
45 private final AtmosphericConditions atmosphere;
49 private Analysis(String filename) throws RocketLoadException {
51 OpenRocketDocument doc = loader.load(new File(filename));
52 config = doc.getRocket().getDefaultConfiguration();
54 calculator.setConfiguration(config);
56 conditions = new FlightConditions(config);
57 System.out.println("Children: " + Arrays.toString(config.getRocket().getChildren()));
58 System.out.println("Children: " + Arrays.toString(config.getRocket().getChild(0).getChildren()));
59 length = config.getLength();
60 System.out.println("Rocket length: " + (length*1000)+"mm");
62 atmosphere = new ExactAtmosphericConditions();
67 private double computeVelocityAndAtmosphere(double mach, double reynolds, double stagTemp) {
68 final double temperature;
69 final double pressure;
72 temperature = stagTemp / (1 + (GAMMA-1)/2 * MathUtil.pow2(mach));
75 double c = 331.3 * Math.sqrt(1 + (temperature - 273.15)/273.15);
77 // Free-stream velocity
80 // kin.visc. = (3.7291e-06 + 4.9944e-08 * temperature) / density
81 pressure = reynolds * (3.7291e-06 + 4.9944e-08 * temperature) * R * temperature /
84 atmosphere.pressure = pressure;
85 atmosphere.temperature = temperature;
86 conditions.setAtmosphericConditions(atmosphere);
87 conditions.setVelocity(v0);
89 if (Math.abs(conditions.getMach() - mach) > 0.001) {
90 System.err.println("Computed mach: "+conditions.getMach() + " requested "+mach);
99 private void computeVsMach(PrintStream stream) {
101 conditions.setAOA(0);
102 conditions.setTheta(45*Math.PI/180);
103 stream.println("% Mach, Caxial, CP, , CNa, Croll");
105 for (double mach = MACH_MIN; mach <= MACH_MAX; mach += MACH_STEP) {
107 computeVelocityAndAtmosphere(mach, REYNOLDS, STAG_TEMP);
108 // conditions.setMach(mach);
111 AerodynamicForces forces = calculator.getAerodynamicForces(0, conditions, null);
114 double Re = conditions.getVelocity() *
115 calculator.getConfiguration().getLength() /
116 conditions.getAtmosphericConditions().getKinematicViscosity();
117 if (Math.abs(Re - REYNOLDS) > 1) {
118 throw new RuntimeException("Re="+Re);
120 stream.printf("%f, %f, %f, %f, %f\n", mach, forces.Caxial, forces.cp.x, forces.CNa,
128 private void computeVsAOA(PrintStream stream, double thetaDeg) {
130 computeVelocityAndAtmosphere(AOA_MACH, REYNOLDS, STAG_TEMP);
131 conditions.setTheta(thetaDeg * Math.PI/180);
132 stream.println("% AOA, CP, CN, Cm at theta = "+thetaDeg);
134 for (double aoa = AOA_MIN; aoa <= AOA_MAX; aoa += AOA_STEP) {
136 conditions.setAOA(aoa);
137 AerodynamicForces forces = calculator.getAerodynamicForces(0, conditions, null);
140 double Re = conditions.getVelocity() *
141 calculator.getConfiguration().getLength() /
142 conditions.getAtmosphericConditions().getKinematicViscosity();
143 if (Math.abs(Re - REYNOLDS) > 1) {
144 throw new RuntimeException("Re="+Re);
146 stream.printf("%f, %f, %f, %f\n", aoa*180/Math.PI, forces.cp.x, forces.CN, forces.Cm);
154 public static void main(String arg[]) throws Exception {
156 if (arg.length != 2) {
157 System.err.println("Arguments: <rocket file> <output prefix>");
161 Analysis a = new Analysis(arg[0]);
162 final String prefix = arg[1];
166 double v0 = a.computeVelocityAndAtmosphere(0.6, 9.8e6, 322);
167 System.out.printf("Sanity test: mach = %.1f v=%.1f temp=%.1f pres=%.0f c=%.1f " +
168 "ref.length=%.1fmm\n",
169 a.conditions.getMach(), v0, a.atmosphere.temperature, a.atmosphere.pressure,
170 a.atmosphere.getMachSpeed(), a.conditions.getRefLength()*1000);
171 System.out.println();
174 // CA, CP, Croll vs. Mach at AOA=0
175 name = prefix + "-CA-CP-CNa-Croll-vs-Mach.csv";
176 System.out.println("Computing CA, CP, CNa, Croll vs. Mach to file "+name);
177 a.computeVsMach(new PrintStream(name));
180 // CN & Cm vs. AOA at M=0.6
181 name = prefix + "-CP-CN-Cm-vs-AOA-0.csv";
182 System.out.println("Computing CP, CN, Cm vs. AOA at theta=0 to file "+name);
183 a.computeVsAOA(new PrintStream(name), 0);
185 // CN & Cm vs. AOA at M=0.6
186 name = prefix + "-CP-CN-Cm-vs-AOA-22.5.csv";
187 System.out.println("Computing CP, CN, Cm vs. AOA at theta=22.5 to file "+name);
188 a.computeVsAOA(new PrintStream(name), 0);
190 // CN & Cm vs. AOA at M=0.6
191 name = prefix + "-CP-CN-Cm-vs-AOA-45.csv";
192 System.out.println("Computing CP, CN, Cm vs. AOA at theta=45 to file "+name);
193 a.computeVsAOA(new PrintStream(name), 0);
196 System.out.println("Done.");