From d31d7d6d478655b22461a08847627af8878bd7f7 Mon Sep 17 00:00:00 2001 From: Bill Kuker Date: Fri, 12 Nov 2010 14:01:35 +0000 Subject: [PATCH] Two editable, saveable fuels --- .../editable/EditablePiecewiseLinearFuel.java | 195 ++++++++++++++++++ .../EditablePiecewiseSaintRobertFuel.java | 116 +++++++++++ 2 files changed, 311 insertions(+) create mode 100644 src/com/billkuker/rocketry/motorsim/fuel/editable/EditablePiecewiseLinearFuel.java create mode 100644 src/com/billkuker/rocketry/motorsim/fuel/editable/EditablePiecewiseSaintRobertFuel.java diff --git a/src/com/billkuker/rocketry/motorsim/fuel/editable/EditablePiecewiseLinearFuel.java b/src/com/billkuker/rocketry/motorsim/fuel/editable/EditablePiecewiseLinearFuel.java new file mode 100644 index 0000000..f3d2579 --- /dev/null +++ b/src/com/billkuker/rocketry/motorsim/fuel/editable/EditablePiecewiseLinearFuel.java @@ -0,0 +1,195 @@ +package com.billkuker.rocketry.motorsim.fuel.editable; + +import java.net.URI; +import java.util.HashMap; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.SortedMap; +import java.util.TreeMap; + +import javax.measure.quantity.Dimensionless; +import javax.measure.quantity.Pressure; +import javax.measure.quantity.Velocity; +import javax.measure.quantity.VolumetricDensity; +import javax.measure.unit.SI; + +import org.apache.log4j.Logger; +import org.jscience.physics.amount.Amount; + +import com.billkuker.rocketry.motorsim.Fuel; +import com.billkuker.rocketry.motorsim.RocketScience; +import com.billkuker.rocketry.motorsim.fuel.EditableCombustionProduct; +import com.billkuker.rocketry.motorsim.visual.Chart; + +public class EditablePiecewiseLinearFuel implements Fuel{ + private static final Logger log = Logger + .getLogger(EditablePiecewiseLinearFuel.class); + private static final Amount ZERO_PRESSURE = Amount.valueOf(0, + SI.PASCAL); + private static final Amount ZERO_VELOCITY = Amount.valueOf(0, + RocketScience.UnitPreference + .getUnitPreference().getPreferredUnit(SI.METERS_PER_SECOND)); + + private static class Entry implements Comparable{ + Amount pressure; + Amount burnRate; + @Override + public int compareTo(Entry o) { + if ( o.pressure.approximates(pressure) ) + return 0; + return o.pressure.isGreaterThan(pressure)?-1:1; + } + } + + + private String name = "New Linear Fuel"; + private URI uri; + private double combustionEfficiency = .97; + private double densityRatio = .96; + private Amount density = Amount.valueOf(1889, 0, SI.KILOGRAM.divide(SI.METER.pow(3))).to(VolumetricDensity.UNIT); + + + private EditableCombustionProduct product = new EditableCombustionProduct(); + private SortedMap, Entry> entries ; + + public EditablePiecewiseLinearFuel(){ + clear(); + } + public void add(final Amount p, final Amount r){ + entries.put(p, new Entry(){{pressure = p; burnRate = r;}}); + } + + @Override + public Amount burnRate(final Amount pressure) { + if ( pressure.isLessThan(ZERO_PRESSURE) ) + return ZERO_VELOCITY; + + if ( entries.size() == 1 ){ + return entries.get(entries.firstKey()).burnRate; + } + + if ( entries.containsKey(pressure) ){ + return entries.get(pressure).burnRate; + } + + Entry low = null; + low = entries.get(entries.headMap(pressure).lastKey()); + Entry high = null; + try { + high = entries.get(entries.tailMap(pressure).firstKey()); + } catch ( NoSuchElementException e ){ + log.warn("Pressure " + pressure + " is outside of expiermental range for " + this.getName()); + high = low; + low = entries.get(entries.headMap(low.pressure).lastKey()); + } + + Amount lowToHigh = high.pressure.minus(low.pressure); + Amount lowToTarget = pressure.minus(low.pressure); + Amount frac = lowToTarget.divide(lowToHigh).to(Dimensionless.UNIT); + + Amount vdiff = high.burnRate.minus(low.burnRate); + Amount ret = low.burnRate.plus(vdiff.times(frac)); + + if ( ret.isLessThan(ZERO_VELOCITY) ) + return ZERO_VELOCITY; + + return ret; + + } + + public void clear(){ + entries = new TreeMap, Entry>(); + add(Amount.valueOf(0,SI.MEGA(SI.PASCAL)), ZERO_VELOCITY); + } + + @Override + public double getCombustionEfficiency() { + return combustionEfficiency; + } + + + public void setCombustionEfficiency(double combustionEfficiency) { + this.combustionEfficiency = combustionEfficiency; + } + + @Override + public CombustionProduct getCombustionProduct(){ + return product; + } + + public void setCombustionProduct(final CombustionProduct product){ + this.product = (EditableCombustionProduct)product; + } + + @Override + public double getDensityRatio() { + return densityRatio; + } + + public void setDensityRatio(double densityRatio) { + this.densityRatio = densityRatio; + } + + @Override + public Amount getIdealDensity() { + return density; + } + + public void setIdealDensity(Amount density) { + this.density = density; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public URI getURI() { + return uri; + } + + + + public Map, Amount> getEntries() { + HashMap, Amount> ret = new HashMap, Amount>(); + for ( Entry e : entries.values() ) + ret.put(e.pressure, e.burnRate); + return ret; + } + + public void setEntries(Map, Amount> in) { + clear(); + for ( Map.Entry, Amount> e : in.entrySet()){ + add( e.getKey(), e.getValue()); + } + } + + + + public static void main( String args[]) throws Exception{ + EditablePiecewiseLinearFuel f = new EditablePiecewiseLinearFuel(); + f.add(Amount.valueOf(0,SI.MEGA(SI.PASCAL)), Amount.valueOf(2, SI.METERS_PER_SECOND)); + //f.add(Amount.valueOf(2,SI.MEGA(SI.PASCAL)), Amount.valueOf(2, SI.METERS_PER_SECOND)); + //f.add(Amount.valueOf(4,SI.MEGA(SI.PASCAL)), Amount.valueOf(1, SI.METERS_PER_SECOND)); + //f.add(Amount.valueOf(10,SI.MEGA(SI.PASCAL)), Amount.valueOf(3, SI.METERS_PER_SECOND)); + //f.add(Amount.valueOf(20,SI.MEGA(SI.PASCAL)), Amount.valueOf(4, SI.METERS_PER_SECOND)); + Chart burnRate = new Chart( + SI.MEGA(SI.PASCAL), + SI.METERS_PER_SECOND, + f, + "burnRate"); + burnRate.setDomain( + burnRate.new IntervalDomain( + Amount.valueOf(0, SI.MEGA(SI.PASCAL)), + Amount.valueOf(11, SI.MEGA(SI.PASCAL)), + 200 + )); + + burnRate.show(); + } +} diff --git a/src/com/billkuker/rocketry/motorsim/fuel/editable/EditablePiecewiseSaintRobertFuel.java b/src/com/billkuker/rocketry/motorsim/fuel/editable/EditablePiecewiseSaintRobertFuel.java new file mode 100644 index 0000000..1c80761 --- /dev/null +++ b/src/com/billkuker/rocketry/motorsim/fuel/editable/EditablePiecewiseSaintRobertFuel.java @@ -0,0 +1,116 @@ +package com.billkuker.rocketry.motorsim.fuel.editable; + +import java.util.HashMap; +import java.util.Map; + +import javax.measure.quantity.Pressure; +import javax.measure.quantity.VolumetricDensity; + +import org.jscience.physics.amount.Amount; + +import com.billkuker.rocketry.motorsim.fuel.EditableCombustionProduct; +import com.billkuker.rocketry.motorsim.fuel.PiecewiseSaintRobertFuel; + +public class EditablePiecewiseSaintRobertFuel extends PiecewiseSaintRobertFuel { + + @SuppressWarnings("unchecked") + private Amount idealDensity = (Amount) Amount + .valueOf("1 g/mm^3"); + + private double combustionEfficiency = 1; + private double densityRatio = 1; + private EditableCombustionProduct cp; + private String name = "New Fuel"; + + public EditablePiecewiseSaintRobertFuel() { + super(Type.SI); + clear(); + cp = new EditableCombustionProduct(); + } + + private Map, Double> aMap; + private Map, Double> nMap; + + public void clear(){ + super.clear(); + aMap = new HashMap, Double>(); + nMap = new HashMap, Double>(); + } + + public void setType(Type t){ + super.setType(t); + } + + public void add(Amount p, final double _a, final double _n) { + super.add(p, _a, _n); + aMap.put(p, _a); + nMap.put(p, _n); + } + + public Amount getIdealDensity() { + return idealDensity; + } + + public void setIdealDensity(Amount idealDensity) { + this.idealDensity = idealDensity; + } + + public double getCombustionEfficiency() { + return combustionEfficiency; + } + + public void setCombustionEfficiency(double combustionEfficiency) { + this.combustionEfficiency = combustionEfficiency; + } + + public double getDensityRatio() { + return densityRatio; + } + + public void setDensityRatio(double densityRatio) { + this.densityRatio = densityRatio; + } + + @Override + public CombustionProduct getCombustionProduct() { + return cp; + } + + public void setCombustionProduct(final CombustionProduct product){ + this.cp = (EditableCombustionProduct)product; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Map, Double> getAMap() { + return aMap; + } + + public void setAMap(Map, Double> aMap) { + this.aMap = aMap; + reset(); + } + + public Map, Double> getNMap() { + return nMap; + } + + public void setNMap(Map, Double> nMap) { + this.nMap = nMap; + reset(); + } + + private void reset(){ + if (nMap != null && aMap != null && nMap.size() == aMap.size()){ + for ( Amount p : aMap.keySet() ){ + add(p, aMap.get(p), nMap.get(p)); + } + } + } +} \ No newline at end of file -- 2.47.2