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