1 package com.billkuker.rocketry.motorsim.fuel;
\r
4 import java.util.NoSuchElementException;
\r
5 import java.util.SortedMap;
\r
6 import java.util.TreeMap;
\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
15 import org.apache.log4j.Logger;
\r
16 import org.jscience.physics.amount.Amount;
\r
18 import com.billkuker.rocketry.motorsim.Fuel;
\r
19 import com.billkuker.rocketry.motorsim.visual.Chart;
\r
21 public class PiecewiseLinearFuel implements Fuel{
\r
22 private static final Logger log = Logger.getLogger(PiecewiseLinearFuel.class);
\r
24 private String name;
\r
26 private Amount<VolumetricDensity> density;
\r
27 private float densityRatio;
\r
28 private float combustionEfficiency;
\r
30 private class Entry implements Comparable<Entry>{
\r
31 Amount<Pressure> pressure;
\r
32 Amount<Velocity> burnRate;
\r
34 public int compareTo(Entry o) {
\r
35 if ( o.pressure.approximates(pressure) )
\r
37 return o.pressure.isGreaterThan(pressure)?-1:1;
\r
41 private SortedMap<Amount<Pressure>, Entry> entries = new TreeMap<Amount<Pressure>, Entry>();
\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
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
53 public String getName() {
\r
58 public URI getURI() {
\r
63 public Amount<VolumetricDensity> getIdealDensity() {
\r
68 public Amount<Velocity> burnRate(Amount<Pressure> pressure) {
\r
70 low = entries.get(entries.headMap(pressure).lastKey());
\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
77 low = entries.get(entries.headMap(low.pressure).lastKey());
\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
84 Amount<Velocity> vdiff = high.burnRate.minus(low.burnRate);
\r
85 Amount<Velocity> ret = low.burnRate.plus(vdiff.times(frac));
\r
92 public CombustionProduct getCombustionProduct(){
\r
97 public double getDensityRatio() {
\r
98 return densityRatio;
\r
102 public double getCombustionEfficiency() {
\r
103 return combustionEfficiency;
\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
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