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
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
14 import org.apache.log4j.Logger;
\r
15 import org.jscience.physics.amount.Amount;
\r
17 import com.billkuker.rocketry.motorsim.Fuel;
\r
18 import com.billkuker.rocketry.motorsim.visual.Chart;
\r
20 public class PiecewiseLinearFuel implements Fuel{
\r
21 private static final Logger log = Logger.getLogger(PiecewiseLinearFuel.class);
\r
23 private String name;
\r
25 private Amount<VolumetricDensity> density;
\r
26 private float densityRatio;
\r
27 private float combustionEfficiency;
\r
29 private class Entry implements Comparable<Entry>{
\r
30 Amount<Pressure> pressure;
\r
31 Amount<Velocity> burnRate;
\r
33 public int compareTo(Entry o) {
\r
34 if ( o.pressure.approximates(pressure) )
\r
36 return o.pressure.isGreaterThan(pressure)?-1:1;
\r
40 private SortedMap<Amount<Pressure>, Entry> entries = new TreeMap<Amount<Pressure>, Entry>();
\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
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
52 public String getName() {
\r
57 public URI getURI() {
\r
62 public Amount<VolumetricDensity> getIdealDensity() {
\r
67 public Amount<Velocity> burnRate(Amount<Pressure> pressure) {
\r
69 low = entries.get(entries.headMap(pressure).lastKey());
\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
76 low = entries.get(entries.headMap(low.pressure).lastKey());
\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
83 Amount<Velocity> vdiff = high.burnRate.minus(low.burnRate);
\r
84 Amount<Velocity> ret = low.burnRate.plus(vdiff.times(frac));
\r
91 public CombustionProduct getCombustionProduct(){
\r
96 public double getDensityRatio() {
\r
97 return densityRatio;
\r
101 public double getCombustionEfficiency() {
\r
102 return combustionEfficiency;
\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
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