Skip to content

Commit

Permalink
Flow Separation Warning (#205)
Browse files Browse the repository at this point in the history
If the simulation shows an exit pressure which is below the Summerfield Criteria for flow separation, a warning will be generated.
  • Loading branch information
AstroChuck committed May 30, 2023
1 parent 28d4c5b commit 1286748
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 2 deletions.
8 changes: 8 additions & 0 deletions motorlib/motor.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ def __init__(self):
self.props['maxPressure'] = FloatProperty('Maximum Allowed Pressure', 'Pa', 0, 7e7)
self.props['maxMassFlux'] = FloatProperty('Maximum Allowed Mass Flux', 'kg/(m^2*s)', 0, 1e4)
self.props['minPortThroat'] = FloatProperty('Minimum Allowed Port/Throat Ratio', '', 1, 4)
self.props['flowSeparationWarnPercent'] = FloatProperty('Flow Separation Warning Threshold', '', 0.00, 1)
# Simulation
self.props['burnoutWebThres'] = FloatProperty('Web Burnout Threshold', 'm', 2.54e-5, 3.175e-3)
self.props['burnoutThrustThres'] = FloatProperty('Thrust Burnout Threshold', '%', 0.01, 10)
self.props['timestep'] = FloatProperty('Simulation Timestep', 's', 0.0001, 0.1)
self.props['ambPressure'] = FloatProperty('Ambient Pressure', 'Pa', 0.0001, 102000)
self.props['mapDim'] = IntProperty('Grain Map Dimension', '', 250, 2000)
self.props['sepPressureRatio'] = FloatProperty('Separation Pressure Ratio', '', 0.001, 1)



class Motor():
Expand Down Expand Up @@ -280,6 +283,11 @@ def runSimulation(self, callback=None):
alert = SimAlert(SimAlertLevel.WARNING, SimAlertType.CONSTRAINT, desc, 'Motor')
simRes.addAlert(alert)

if (simRes.getPercentBelowThreshold('exitPressure', self.config.getProperty('ambPressure') * self.config.getProperty('sepPressureRatio')) > self.config.getProperty('flowSeparationWarnPercent')):
desc = 'Low exit pressure, nozzle flow may separate'
alert = SimAlert(SimAlertLevel.WARNING, SimAlertType.VALUE, desc, 'Nozzle')
simRes.addAlert(alert)

# Note that this only adds all errors found on the first datapoint where there were errors to avoid repeating
# errors. It should be revisited if getPressureErrors ever returns multiple types of errors
for pressure in simRes.channels['pressure'].getData():
Expand Down
21 changes: 21 additions & 0 deletions motorlib/simResult.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ def getMax(self):
if self.valueType in (list, tuple):
return max([max(l) for l in self.data])
return max(self.data)

def getMin(self):
"""Returns the minimum value of all datapoints. For list datatypes, this operation finds the smallest single
value in any list."""
if self.valueType in (list, tuple):
return min([min(l) for l in self.data])
return min(self.data)

singleValueChannels = ['time', 'kn', 'pressure', 'force', 'volumeLoading', 'exitPressure', 'dThroat']
multiValueChannels = ['mass', 'massFlow', 'massFlux', 'regression', 'web']
Expand Down Expand Up @@ -143,6 +150,20 @@ def getAveragePressure(self):
def getMaxPressure(self):
"""Returns the highest chamber pressure that was observed during the motor's burn."""
return self.channels['pressure'].getMax()

def getMinExitPressure(self):
"""Returns the lowest exit pressure that was observed during the motor's burn, ignoring startup and shutdown transients"""
exit_pressures = self.channels['exitPressure'].getData()
return min(exit_pressures)

def getPercentBelowThreshold(self, channel, threshold):
"""Returns the total number of seconds spent below a given threshold value"""
count = 0
data = self.channels[channel].getData()
for point in data:
if point < threshold:
count += 1
return count/len(data)

def getImpulse(self, stop=None):
"""Returns the impulse the simulated motor produced. If 'stop' is set to a value other than None, only the
Expand Down
4 changes: 3 additions & 1 deletion uilib/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
'timestep': 0.03,
'ambPressure': 101325,
'igniterPressure': 150 * 6895, # Deprecated, but needed for migration
'mapDim': 750
'mapDim': 750,
'sepPressureRatio' : 0.4, # This is a good default value known as the Summerfield Criteria https://ntrs.nasa.gov/api/citations/19840011402/downloads/19840011402.pdf
'flowSeparationWarnPercent': 0.05
},
'units': {
'm': 'in',
Expand Down
15 changes: 14 additions & 1 deletion uilib/fileIO.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from .defaults import DEFAULT_PREFERENCES, DEFAULT_PROPELLANTS, KNSU_PROPS
from .logger import logger

appVersion = (0, 5, 0)
appVersion = (0, 6, 0)
appVersionStr = '.'.join(map(str, appVersion))

class fileTypes(Enum):
Expand Down Expand Up @@ -66,6 +66,13 @@ def getConfigPath():

def passthrough(data):
return data


#0.5.0 to 0.6.0
def migrateMotor_0_5_0_to_0_6_0(data):
data['config']['sepPressureRatio'] = DEFAULT_PREFERENCES['general']['sepPressureRatio']
data['config']['flowSeparationWarnPercent'] = DEFAULT_PREFERENCES['general']['flowSeparationWarnPercent']
return data

# 0.4.0 to 0.5.0

Expand Down Expand Up @@ -148,6 +155,12 @@ def migrateMotor_0_2_0_to_0_3_0(data):
return data

migrations = {
(0, 5, 0): {
'to': (0, 6, 0),
fileTypes.PREFERENCES: passthrough,
fileTypes.PROPELLANTS: passthrough,
fileTypes.MOTOR: migrateMotor_0_5_0_to_0_6_0
},
(0, 4, 0): {
'to': (0, 5, 0),
fileTypes.PREFERENCES: migratePref_0_4_0_to_0_5_0,
Expand Down

0 comments on commit 1286748

Please sign in to comment.