imports
[sw/motorsim] / src / com / billkuker / rocketry / motorsim / fuel / PiecewiseLinearFuel.java
1 package com.billkuker.rocketry.motorsim.fuel;\r
2 \r
3 import java.net.URI;\r
4 import java.util.NoSuchElementException;\r
5 import java.util.SortedMap;\r
6 import java.util.TreeMap;\r
7 \r
8 import javax.measure.quantity.Dimensionless;\r
9 import javax.measure.quantity.Pressure;\r
10 import javax.measure.quantity.Velocity;\r
11 import javax.measure.quantity.VolumetricDensity;\r
12 import javax.measure.unit.SI;\r
13 \r
14 import org.apache.log4j.Logger;\r
15 import org.jscience.physics.amount.Amount;\r
16 \r
17 import com.billkuker.rocketry.motorsim.Fuel;\r
18 import com.billkuker.rocketry.motorsim.visual.Chart;\r
19 \r
20 public class PiecewiseLinearFuel implements Fuel{\r
21         private static final Logger log = Logger.getLogger(PiecewiseLinearFuel.class);\r
22         \r
23         private String name;\r
24         private URI uri;\r
25         private Amount<VolumetricDensity> density;\r
26         private float densityRatio;\r
27         private float combustionEfficiency;\r
28         \r
29         private class Entry implements Comparable<Entry>{\r
30                 Amount<Pressure> pressure;\r
31                 Amount<Velocity> burnRate;\r
32                 @Override\r
33                 public int compareTo(Entry o) {\r
34                         if ( o.pressure.approximates(pressure) )\r
35                                 return 0;\r
36                         return o.pressure.isGreaterThan(pressure)?-1:1;\r
37                 }\r
38         }\r
39         \r
40         private SortedMap<Amount<Pressure>, Entry> entries = new TreeMap<Amount<Pressure>, Entry>();\r
41         \r
42         protected void add(final Amount<Pressure> p, final Amount<Velocity> r){\r
43                 entries.put(p, new Entry(){{pressure = p; burnRate = r;}});\r
44         }\r
45         \r
46         public PiecewiseLinearFuel(){\r
47                 add(Amount.valueOf(-1,SI.MEGA(SI.PASCAL)), Amount.valueOf(0, SI.METERS_PER_SECOND));\r
48                 add(Amount.valueOf(0,SI.MEGA(SI.PASCAL)), Amount.valueOf(0, SI.METERS_PER_SECOND));\r
49         }\r
50 \r
51         @Override\r
52         public String getName() {\r
53                 return name;\r
54         }\r
55 \r
56         @Override\r
57         public URI getURI() {\r
58                 return uri;\r
59         }\r
60 \r
61         @Override\r
62         public Amount<VolumetricDensity> getIdealDensity() {\r
63                 return density;\r
64         }\r
65 \r
66         @Override\r
67         public Amount<Velocity> burnRate(Amount<Pressure> pressure) {\r
68                 Entry low = null;\r
69                 low = entries.get(entries.headMap(pressure).lastKey());\r
70                 Entry high = null;\r
71                 try {\r
72                         high = entries.get(entries.tailMap(pressure).firstKey());\r
73                 } catch ( NoSuchElementException e ){\r
74                         log.warn("Pressure " + pressure + " is outside of expiermental range for " + this.getName());\r
75                         high = low;\r
76                         low = entries.get(entries.headMap(low.pressure).lastKey());\r
77                 }\r
78                 \r
79                 Amount<Pressure> lowToHigh = high.pressure.minus(low.pressure);\r
80                 Amount<Pressure> lowToTarget = pressure.minus(low.pressure);\r
81                 Amount<Dimensionless> frac = lowToTarget.divide(lowToHigh).to(Dimensionless.UNIT);\r
82                 \r
83                 Amount<Velocity> vdiff = high.burnRate.minus(low.burnRate);\r
84                 Amount<Velocity> ret = low.burnRate.plus(vdiff.times(frac));\r
85                 \r
86                 return ret;\r
87                 \r
88         }\r
89 \r
90         @Override\r
91         public CombustionProduct getCombustionProduct(){\r
92                 return null;\r
93         }\r
94 \r
95         @Override\r
96         public double getDensityRatio() {\r
97                 return densityRatio;\r
98         }\r
99 \r
100         @Override\r
101         public double getCombustionEfficiency() {\r
102                 return combustionEfficiency;\r
103         }\r
104 \r
105         public static void main( String args[]) throws Exception{\r
106                 PiecewiseLinearFuel f = new PiecewiseLinearFuel();\r
107                 f.add(Amount.valueOf(0,SI.MEGA(SI.PASCAL)), Amount.valueOf(0, SI.METERS_PER_SECOND));\r
108                 f.add(Amount.valueOf(2,SI.MEGA(SI.PASCAL)), Amount.valueOf(2, SI.METERS_PER_SECOND));\r
109                 f.add(Amount.valueOf(4,SI.MEGA(SI.PASCAL)), Amount.valueOf(1, SI.METERS_PER_SECOND));\r
110                 f.add(Amount.valueOf(10,SI.MEGA(SI.PASCAL)), Amount.valueOf(3, SI.METERS_PER_SECOND));\r
111                 f.add(Amount.valueOf(20,SI.MEGA(SI.PASCAL)), Amount.valueOf(4, SI.METERS_PER_SECOND));\r
112                 Chart<Pressure, Velocity> burnRate = new Chart<Pressure, Velocity>(\r
113                                 SI.MEGA(SI.PASCAL),\r
114                                 SI.METERS_PER_SECOND,\r
115                                 f,\r
116                                 "burnRate");\r
117                 burnRate.setDomain(\r
118                                 burnRate.new IntervalDomain(\r
119                                                 Amount.valueOf(0, SI.MEGA(SI.PASCAL)),\r
120                                                 Amount.valueOf(11, SI.MEGA(SI.PASCAL)),\r
121                                                 200\r
122                                                 ));\r
123                 \r
124                 burnRate.show();\r
125         }\r
126 }\r