1 package com.billkuker.rocketry.motorsim;
\r
3 import java.awt.Shape;
\r
4 import java.awt.geom.AffineTransform;
\r
5 import java.awt.geom.GeneralPath;
\r
6 import java.awt.geom.Line2D;
\r
8 import javax.measure.quantity.Area;
\r
9 import javax.measure.quantity.Dimensionless;
\r
10 import javax.measure.quantity.Force;
\r
11 import javax.measure.quantity.Length;
\r
12 import javax.measure.quantity.Pressure;
\r
13 import javax.measure.unit.SI;
\r
15 import org.jscience.physics.amount.Amount;
\r
17 public class ConvergentDivergentNozzle implements Nozzle, Validating {
\r
19 private Amount<Length> throatDiameter;
\r
21 private Amount<Length> exitDiameter;
\r
23 private double efficiency = 1.0;
\r
26 public Amount<Area> throatArea() {
\r
27 return throatDiameter.divide(2).pow(2).times(Math.PI).to(Area.UNIT);
\r
30 public Amount<Area> exitArea() {
\r
31 return exitDiameter.divide(2).pow(2).times(Math.PI).to(Area.UNIT);
\r
35 public Amount<Length> getThroatDiameter() {
\r
36 return throatDiameter;
\r
40 public void setThroatDiameter(Amount<Length> throatDiameter) {
\r
41 this.throatDiameter = throatDiameter;
\r
45 public Amount<Length> getExitDiameter() {
\r
46 return exitDiameter;
\r
50 public void setExitDiameter(Amount<Length> exitDiameter) {
\r
51 this.exitDiameter = exitDiameter;
\r
54 public Amount<Force> thrust(Amount<Pressure> Po, Amount<Pressure> Pe, Amount<Pressure> Patm, final double k ){
\r
55 double cF = thrustCoefficient(Po, Pe, Patm, k);
\r
56 return Po.times(throatArea()).times(cF).to(Force.UNIT);
\r
59 public double thrustCoefficient(Amount<Pressure> Po, Amount<Pressure> Pe, Amount<Pressure> Patm, final double k ){
\r
60 double pRatio = Pe.divide(Po).to(Dimensionless.UNIT).doubleValue(Dimensionless.UNIT);
\r
62 double a = (2*k*k)/(k-1);
\r
64 double b = Math.pow(2/(k+1), (k+1)/(k-1) );
\r
66 double c = 1.0 - Math.pow(pRatio, (k-1)/k);
\r
68 Amount<Pressure> pDiff = Pe.minus(Patm);
\r
70 double d = pDiff.times(exitArea()).divide(Po.times(throatArea())).to(Dimensionless.UNIT).doubleValue(Dimensionless.UNIT);
\r
72 double Cf = efficiency * Math.sqrt(a*b*c)+d;
\r
77 public double getEfficiency() {
\r
81 public void setEfficiency(double efficiency) {
\r
82 this.efficiency = efficiency;
\r
85 public Shape nozzleShape(Amount<Length> chamberDiameter){
\r
86 GeneralPath s = new GeneralPath();
\r
87 double throatR = throatDiameter.divide(2).doubleValue(SI.MILLIMETER);
\r
88 double exitR = exitDiameter.divide(2).doubleValue(SI.MILLIMETER);
\r
90 if (chamberDiameter == null)
\r
93 cR = chamberDiameter.divide(2).doubleValue(SI.MILLIMETER);
\r
95 double diff = exitR-throatR;
\r
96 double cDiff = cR-throatR;
\r
98 s.append(new Line2D.Double(0,0,diff,diff*3), false);
\r
99 s.append(new Line2D.Double(0,0,cDiff,-cDiff), true);
\r
101 s.transform(AffineTransform.getScaleInstance(-1, 1));
\r
102 s.transform(AffineTransform.getTranslateInstance(-throatR, 0));
\r
104 s.append(new Line2D.Double(0,0,diff,diff*3), false);
\r
105 s.append(new Line2D.Double(0,0,cDiff,-cDiff), true);
\r
107 //a.add(new java.awt.geom.Area( new Ellipse2D.Double(0,0,5,5)));
\r
113 public void validate() throws ValidationException {
\r
114 if ( exitDiameter != null && throatDiameter.isGreaterThan(exitDiameter))
\r
115 throw new IllegalArgumentException("Throat > Exit");
\r