def setupChecks(self, multiselect, disabled=[]): sr = simulationResult(motor( )) # This simres is only used to get the list of channels available for c in sr.channels: if multiselect: check = QCheckBox(sr.channels[c].name) check.setCheckState(2) # Every field is checked by default else: check = QRadioButton(sr.channels[c].name) if c in disabled: check.setEnabled(False) self.layout().addWidget(check) self.checks[c] = check
def defaultMotor(): dm = motorlib.motor() bg = motorlib.batesGrain() bg.setProperties({'diameter': 3.27/39.37, 'length': 5.5/39.37, 'coreDiameter': 1.25/39.37, 'inhibitedEnds': 'Neither' }) dm.grains.append(bg) dm.grains.append(bg) dm.nozzle.setProperties({'throat': 0.55/39.37, 'exit': 1.5/39.37, 'efficiency': 0.85}) dm.propellant.setProperties(clProps) return dm
def load(self, path=None): if self.unsavedCheck(): if path is None: path = QFileDialog.getOpenFileName(None, 'Load motor', '', 'Motor Files (*.ric)')[0] if path != '': # If they cancel the dialog, path will be an empty string try: res = loadFile(path, fileTypes.MOTOR) if res is not None: motor = motorlib.motor() motor.applyDict(res) self.startFromMotor(motor, path) return True except Exception as e: self.showException(e) return False # If no file is loaded, return false
def test_calcKN(self): tm = motorlib.motor() bg = motorlib.batesGrain() bg.setProperties({ 'diameter': 0.083058, 'length': 0.1397, 'coreDiameter': 0.05, 'inhibitedEnds': 'Neither' }) tm.grains.append(bg) tm.nozzle.setProperties({'throat': 0.01428}) self.assertAlmostEqual(tm.calcKN([0]), 180, 0) self.assertAlmostEqual(tm.calcKN([0.0025]), 183, 0) self.assertAlmostEqual(tm.calcKN([0.005]), 185, 0)
def __init__(self): from .views.CSVExporter_ui import Ui_CSVExporter QDialog.__init__(self) self.ui = Ui_CSVExporter() self.ui.setupUi(self) self.simRes = None self.preferences = None self.ui.buttonBox.accepted.connect(self.exportCSV) self.checks = {} # Populate list of checks to toggle channels checkLayout = QVBoxLayout() self.ui.groupBoxChecks.setLayout(checkLayout) sr = simulationResult(motor( )) # This simres is only used to get the list of channels available for c in sr.channels: check = QCheckBox(sr.channels[c].name) check.setCheckState(2) # Every field is checked by default if c == "time": # Time must be set check.setEnabled(False) checkLayout.addWidget(check) self.checks[c] = check
def test_calcPressure(self): tm = motorlib.motor() bg = motorlib.batesGrain() bg.setProperties({ 'diameter': 0.083058, 'length': 0.1397, 'coreDiameter': 0.05, 'inhibitedEnds': 'Neither' }) tm.grains.append(bg) tm.nozzle.setProperties({'throat': 0.01428}) tm.propellant.setProperties({ 'name': 'KNSU', 'density': 1890, 'a': 0.000101, 'n': 0.319, 't': 1720, 'm': 41.98, 'k': 1.133 }) self.assertAlmostEqual(tm.calcIdealPressure([0]), 4050030, 0)
def getCurrentMotor(self): nm = motorlib.motor() nm.loadDict(self.fileHistory[self.currentVersion]) return nm
def newFile(self): if self.unsavedCheck(): self.startFromMotor(motorlib.motor())
def importFile(self, path): motor = motorlib.motor() tree = ET.parse(path) root = tree.getroot() errors = '' propSet = False for child in root: if child.tag == 'Nozzle': motor.nozzle.setProperty('throat', inToM(child.attrib['ThroatDia'])) motor.nozzle.setProperty('exit', inToM(child.attrib['ExitDia'])) motor.nozzle.setProperty( 'efficiency', float(child.attrib['NozzleEfficiency']) / 100) if child.tag == 'Grain': if child.attrib['Type'] in supportedGrainTable: motor.grains.append( supportedGrainTable[child.attrib['Type']]()) motor.grains[-1].setProperty( 'diameter', inToM(child.attrib['Diameter'])) motor.grains[-1].setProperty('length', inToM(child.attrib['Length'])) grainType = child.attrib['Type'] if child.attrib['EndsInhibited'] == '1': motor.grains[-1].setProperty('inhibitedEnds', 'Top') elif child.attrib['EndsInhibited'] == '2': motor.grains[-1].setProperty('inhibitedEnds', 'Both') if grainType in ('1', '3', '7'): # Grains with core diameter motor.grains[-1].setProperty( 'coreDiameter', inToM(child.attrib['CoreDiameter'])) if grainType == '2': # D grain specific properties motor.grains[-1].setProperty( 'slotOffset', inToM(child.attrib['EdgeOffset'])) elif grainType == '3': # Moonburner specific properties motor.grains[-1].setProperty( 'coreOffset', inToM(child.attrib['CoreOffset'])) elif grainType == '5': # C grain specific properties motor.grains[-1].setProperty( 'slotWidth', inToM(child.attrib['SlotWidth'])) radius = motor.grains[-1].getProperty('diameter') / 2 motor.grains[-1].setProperty( 'slotOffset', radius - inToM(child.attrib['SlotDepth'])) elif grainType == '6': # X core specific properties motor.grains[-1].setProperty( 'slotWidth', inToM(child.attrib['SlotWidth'])) motor.grains[-1].setProperty( 'slotLength', inToM(child.attrib['CoreDiameter']) / 2) elif grainType == '7': # Finocyl specific properties motor.grains[-1].setProperty( 'finWidth', inToM(child.attrib['FinWidth'])) motor.grains[-1].setProperty( 'finLength', inToM(child.attrib['FinLength'])) motor.grains[-1].setProperty( 'numFins', int(child.attrib['FinCount'])) if not propSet: # Use propellant numbers from the forward grain impProp = child.find('Propellant') propellant = motorlib.propellant() propellant.setProperty('name', impProp.attrib['Name']) n = float(impProp.attrib['BallisticN']) a = float(impProp.attrib['BallisticA']) * 1 / (6895**n) propellant.setProperty('n', n) propellant.setProperty( 'a', motorlib.convert(a, 'in/(s*psi^n)', 'm/(s*Pa^n)') ) # Conversion only does in/s to m/s, the rest is handled above propellant.setProperty( 'density', motorlib.convert(float(impProp.attrib['Density']), 'lb/in^3', 'kg/m^3')) propellant.setProperty( 'k', float(impProp.attrib['SpecificHeatRatio'])) impMolarMass = impProp.attrib['MolarMass'] if impMolarMass == '0': propellant.setProperty( 'm', 23.67 ) # If the user has entered 0, override it to match the default propellant. else: propellant.setProperty('m', float(impMolarMass)) propellant.setProperty( 't', 3500 ) # Burnsim doesn't provide this property. Set it to match the default propellant. motor.propellant = propellant propSet = True else: if child.attrib['Type'] in unsupportedGrainTable: errors += "File contains a " + unsupportedGrainTable[ child.attrib[ 'Type']] + " grain, which can't be imported.\n" else: errors += "File contains an unknown grain of type " + child.attrib[ 'Type'] + '.\n' if child.tag == 'TestData': errors += "\nFile contains test data, which is not imported." if errors != '': self.showWarning(errors + '\nThe rest of the motor will be imported.') self.fileManager.startFromMotor(motor) return True
if '-h' in sys.argv: if len(sys.argv) < 3: print( 'Not enough arguments. Headless mode requires an input file.') else: preferences = uilib.defaultPreferences() try: prefDict = uilib.loadFile('preferences.yaml', uilib.fileTypes.PREFERENCES) preferences.applyDict(prefDict) except: print('Preferences could not be loaded, using default') try: motorData = uilib.loadFile(sys.argv[-1], uilib.fileTypes.MOTOR) motor = motorlib.motor() motor.loadDict(motorData) simres = motor.runSimulation(preferences) for alert in simres.alerts: print(motorlib.alertLevelNames[alert.level] + '(' + motorlib.alertTypeNames[alert.type] + ', ' + alert.location + '): ' + alert.description) print() if '-o' in sys.argv: with open(sys.argv[sys.argv.index('-o') + 1], 'w') as outputFile: outputFile.write(simres.getCSV(preferences)) else: print(simres.getCSV(preferences)) except: print('Motor could not be loaded')