diff --git a/motorlib/motor.py b/motorlib/motor.py index abec0d6..2791485 100644 --- a/motorlib/motor.py +++ b/motorlib/motor.py @@ -175,7 +175,7 @@ def runSimulation(self, callback=None): simRes.channels['exitPressure'].addData(0) simRes.channels['dThroat'].addData(0) - # Check port/throat ratio and add a warning if it is large enough + # Check port/throat ratio and add a warning if it is not large enough aftPort = self.grains[-1].getPortArea(0) if aftPort is not None: minAllowed = self.config.getProperty('minPortThroat') @@ -281,3 +281,41 @@ def runSimulation(self, callback=None): break return simRes + + def getQuickResults(self): + results = { + 'volumeLoading': 0, + 'initialKn': 0, + 'propellantMass': 0, + 'portRatio': 0, + 'length': 0 + } + + simRes = SimulationResult(self) + + density = self.propellant.getProperty('density') if self.propellant is not None else None + throatArea = self.nozzle.getThroatArea() + motorVolume = self.calcTotalVolume() + + if motorVolume == 0: + return results + + # Generate coremaps for perforated grains + for grain in self.grains: + for alert in grain.getGeometryErrors(): + if alert.level == SimAlertLevel.ERROR: + return results + + grain.simulationSetup(self.config) + + perGrainReg = [0 for grain in self.grains] + + results['volumeLoading'] = 100 * (1 - (self.calcFreeVolume(perGrainReg) / motorVolume)) + if throatArea != 0: + results['initialKn'] = self.calcKN(perGrainReg, 0) + results['portRatio'] = simRes.getPortRatio() + if density is not None: + results['propellantMass'] = sum([grain.getVolumeAtRegression(0) * density for grain in self.grains]) + results['length'] = simRes.getPropellantLength() + + return results diff --git a/uilib/widgets/mainWindow.py b/uilib/widgets/mainWindow.py index d1962b3..3691a4f 100644 --- a/uilib/widgets/mainWindow.py +++ b/uilib/widgets/mainWindow.py @@ -1,4 +1,5 @@ import sys +from threading import Thread from PyQt6.QtWidgets import QWidget, QMainWindow, QTableWidgetItem, QHeaderView, QTableWidget from PyQt6.QtCore import Qt @@ -32,6 +33,7 @@ def __init__(self, app): self.app.fileManager.fileNameChanged.connect(self.updateWindowTitle) self.app.fileManager.newMotor.connect(self.resetOutput) + self.app.fileManager.newMotor.connect(self.getQuickResults) self.app.importExportManager.motorImported.connect(self.motorImported) @@ -318,6 +320,19 @@ def updateMotorStats(self, simResult): self.ui.labelPeakMassFlux.setText('-') self.ui.labelDeliveredThrustCoefficient.setText(self.formatMotorStat(simResult.getAdjustedThrustCoefficient(), '')) + def getQuickResults(self, motor): + thread = lambda: self.showQuickResults(motor.getQuickResults()) + + dataThread = Thread(target=thread) + dataThread.start() + + def showQuickResults(self, results): + self.ui.labelVolumeLoading.setText('{:.2f}%'.format(results['volumeLoading'])) + self.ui.labelInitialKN.setText(self.formatMotorStat(results['initialKn'], '')) + self.ui.labelPropellantLength.setText(self.formatMotorStat(results['length'], 'm')) + self.ui.labelPropellantMass.setText(self.formatMotorStat(results['propellantMass'], 'kg')) + self.ui.labelPortThroatRatio.setText(self.formatMotorStat(results['portRatio'], '')) + def runSimulation(self): self.resetOutput() cm = self.app.fileManager.getCurrentMotor() @@ -356,6 +371,8 @@ def loadMotor(self, path=None): self.disablePropSelector() if self.app.fileManager.load(path): self.postLoadUpdate() + # Needed because postLoadUpdate clears results + self.getQuickResults(self.app.fileManager.getCurrentMotor()) self.enablePropSelector() self.ui.motorEditor.close()