1 package net.sf.openrocket.utils;
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;
21 import net.sf.openrocket.util.MathUtil;
23 public class Analysis {
25 private static final double MACH_MIN = 0.01;
26 private static final double MACH_MAX = 5.00001;
27 private static final double MACH_STEP = 0.02;
29 private static final double AOA_MACH = 0.6;
30 private static final double AOA_MIN = 0;
31 private static final double AOA_MAX = 15.00001*Math.PI/180;
32 private static final double AOA_STEP = 0.5*Math.PI/180;
34 private static final double REYNOLDS = 9.8e6;
35 private static final double STAG_TEMP = 330;
38 private final RocketLoader loader = new GeneralRocketLoader();
39 private final AerodynamicCalculator calculator = new BarrowmanCalculator();
41 private final FlightConditions conditions;
42 private final double length;
44 private final Configuration config;
46 private final AtmosphericConditions atmosphere;
50 private Analysis(String filename) throws RocketLoadException {
52 OpenRocketDocument doc = loader.load(new File(filename));
53 config = doc.getRocket().getDefaultConfiguration();
55 calculator.setConfiguration(config);
57 conditions = new FlightConditions(config);
58 System.out.println("Children: " + Arrays.toString(config.getRocket().getChildren()));
59 System.out.println("Children: " + Arrays.toString(config.getRocket().getChild(0).getChildren()));
60 length = config.getLength();
61 System.out.println("Rocket length: " + (length*1000)+"mm");
63 atmosphere = new ExactAtmosphericConditions();
68 private double computeVelocityAndAtmosphere(double mach, double reynolds, double stagTemp) {
69 final double temperature;
70 final double pressure;
73 temperature = stagTemp / (1 + (GAMMA-1)/2 * MathUtil.pow2(mach));
76 double c = 331.3 * Math.sqrt(1 + (temperature - 273.15)/273.15);
78 // Free-stream velocity
81 // kin.visc. = (3.7291e-06 + 4.9944e-08 * temperature) / density
82 pressure = reynolds * (3.7291e-06 + 4.9944e-08 * temperature) * R * temperature /
85 atmosphere.pressure = pressure;
86 atmosphere.temperature = temperature;
87 conditions.setAtmosphericConditions(atmosphere);
88 conditions.setVelocity(v0);
90 if (Math.abs(conditions.getMach() - mach) > 0.001) {
91 System.err.println("Computed mach: "+conditions.getMach() + " requested "+mach);
100 private void computeVsMach(PrintStream stream) {
102 conditions.setAOA(0);
103 conditions.setTheta(45*Math.PI/180);
104 stream.println("% Mach, Caxial, CP, , CNa, Croll");
106 for (double mach = MACH_MIN; mach <= MACH_MAX; mach += MACH_STEP) {
108 computeVelocityAndAtmosphere(mach, REYNOLDS, STAG_TEMP);
109 // conditions.setMach(mach);
112 AerodynamicForces forces = calculator.getAerodynamicForces(0, conditions, null);
115 double Re = conditions.getVelocity() *
116 calculator.getConfiguration().getLength() /
117 conditions.getAtmosphericConditions().getKinematicViscosity();
118 if (Math.abs(Re - REYNOLDS) > 1) {
119 throw new RuntimeException("Re="+Re);
121 stream.printf("%f, %f, %f, %f, %f\n", mach, forces.Caxial, forces.cp.x, forces.CNa,
129 private void computeVsAOA(PrintStream stream, double thetaDeg) {
131 computeVelocityAndAtmosphere(AOA_MACH, REYNOLDS, STAG_TEMP);
132 conditions.setTheta(thetaDeg * Math.PI/180);
133 stream.println("% AOA, CP, CN, Cm at theta = "+thetaDeg);
135 for (double aoa = AOA_MIN; aoa <= AOA_MAX; aoa += AOA_STEP) {
137 conditions.setAOA(aoa);
138 AerodynamicForces forces = calculator.getAerodynamicForces(0, conditions, null);
141 double Re = conditions.getVelocity() *
142 calculator.getConfiguration().getLength() /
143 conditions.getAtmosphericConditions().getKinematicViscosity();
144 if (Math.abs(Re - REYNOLDS) > 1) {
145 throw new RuntimeException("Re="+Re);
147 stream.printf("%f, %f, %f, %f\n", aoa*180/Math.PI, forces.cp.x, forces.CN, forces.Cm);
155 public static void main(String arg[]) throws Exception {
157 if (arg.length != 2) {
158 System.err.println("Arguments: <rocket file> <output prefix>");
162 Analysis a = new Analysis(arg[0]);
163 final String prefix = arg[1];
167 double v0 = a.computeVelocityAndAtmosphere(0.6, 9.8e6, 322);
168 System.out.printf("Sanity test: mach = %.1f v=%.1f temp=%.1f pres=%.0f c=%.1f " +
169 "ref.length=%.1fmm\n",
170 a.conditions.getMach(), v0, a.atmosphere.temperature, a.atmosphere.pressure,
171 a.atmosphere.getMachSpeed(), a.conditions.getRefLength()*1000);
172 System.out.println();
175 // CA, CP, Croll vs. Mach at AOA=0
176 name = prefix + "-CA-CP-CNa-Croll-vs-Mach.csv";
177 System.out.println("Computing CA, CP, CNa, Croll vs. Mach to file "+name);
178 a.computeVsMach(new PrintStream(name));
181 // CN & Cm vs. AOA at M=0.6
182 name = prefix + "-CP-CN-Cm-vs-AOA-0.csv";
183 System.out.println("Computing CP, CN, Cm vs. AOA at theta=0 to file "+name);
184 a.computeVsAOA(new PrintStream(name), 0);
186 // CN & Cm vs. AOA at M=0.6
187 name = prefix + "-CP-CN-Cm-vs-AOA-22.5.csv";
188 System.out.println("Computing CP, CN, Cm vs. AOA at theta=22.5 to file "+name);
189 a.computeVsAOA(new PrintStream(name), 0);
191 // CN & Cm vs. AOA at M=0.6
192 name = prefix + "-CP-CN-Cm-vs-AOA-45.csv";
193 System.out.println("Computing CP, CN, Cm vs. AOA at theta=45 to file "+name);
194 a.computeVsAOA(new PrintStream(name), 0);
197 System.out.println("Done.");