(no commit message)
[sw/motorsim] / src / com / billkuker / rocketry / motorsim / ConvergentDivergentNozzle.java
1 package com.billkuker.rocketry.motorsim;\r
2 \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
7 \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
14 \r
15 import org.jscience.physics.amount.Amount;\r
16 \r
17 public class ConvergentDivergentNozzle implements Nozzle, Validating {\r
18 \r
19         private Amount<Length> throatDiameter;\r
20         \r
21         private Amount<Length> exitDiameter;\r
22         \r
23         private double efficiency = 1.0;\r
24         \r
25         \r
26         public Amount<Area> throatArea() {\r
27                 return throatDiameter.divide(2).pow(2).times(Math.PI).to(Area.UNIT);\r
28         }\r
29         \r
30         public Amount<Area> exitArea() {\r
31                 return exitDiameter.divide(2).pow(2).times(Math.PI).to(Area.UNIT);\r
32         }\r
33 \r
34 \r
35         public Amount<Length> getThroatDiameter() {\r
36                 return throatDiameter;\r
37         }\r
38 \r
39 \r
40         public void setThroatDiameter(Amount<Length> throatDiameter) {\r
41                 this.throatDiameter = throatDiameter;\r
42         }\r
43         \r
44 \r
45         public Amount<Length> getExitDiameter() {\r
46                 return exitDiameter;\r
47         }\r
48 \r
49 \r
50         public void setExitDiameter(Amount<Length> exitDiameter) {\r
51                 this.exitDiameter = exitDiameter;\r
52         }\r
53         \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
57         }\r
58 \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
61 \r
62                 double a = (2*k*k)/(k-1);\r
63                 \r
64                 double b = Math.pow(2/(k+1), (k+1)/(k-1) );\r
65                 \r
66                 double c = 1.0 - Math.pow(pRatio, (k-1)/k);\r
67                 \r
68                 Amount<Pressure> pDiff = Pe.minus(Patm);\r
69                 \r
70                 double d = pDiff.times(exitArea()).divide(Po.times(throatArea())).to(Dimensionless.UNIT).doubleValue(Dimensionless.UNIT);\r
71                 \r
72                 double Cf = efficiency * Math.sqrt(a*b*c)+d;\r
73                 \r
74                 return Cf;\r
75         }\r
76 \r
77         public double getEfficiency() {\r
78                 return efficiency;\r
79         }\r
80 \r
81         public void setEfficiency(double efficiency) {\r
82                 this.efficiency = efficiency;\r
83         }\r
84 \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
89                 double cR;\r
90                 if (chamberDiameter == null)\r
91                         cR = exitR;\r
92                 else\r
93                         cR = chamberDiameter.divide(2).doubleValue(SI.MILLIMETER);\r
94                 \r
95                 double diff = exitR-throatR;\r
96                 double cDiff = cR-throatR;\r
97                 \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
100                 \r
101                 s.transform(AffineTransform.getScaleInstance(-1, 1));\r
102                 s.transform(AffineTransform.getTranslateInstance(-throatR * 2, 0));\r
103                 \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
106                 \r
107                 s.transform(AffineTransform.getTranslateInstance(throatR, cDiff));\r
108                 //a.add(new java.awt.geom.Area( new Ellipse2D.Double(0,0,5,5)));\r
109                 \r
110                 return s;\r
111         }\r
112 \r
113         @Override\r
114         public void validate() throws ValidationException {\r
115                 if ( exitDiameter != null && throatDiameter.isGreaterThan(exitDiameter))\r
116                         throw new IllegalArgumentException("Throat > Exit");\r
117         }\r
118 }\r