def test_get_IvacCstrTc_ChmMwGam(self): """ test call to get_IvacCstrTc_ChmMwGam( Pc=100.0, MR=1.0, eps=40.0) """ C = CEA_Obj(oxName="LOX", fuelName="MMH") IspODE, Cstar, Tcomb, mw, gam = C.get_IvacCstrTc_ChmMwGam( Pc=100.0, MR=1.0, eps=40.0) #print( IspODE, Cstar, Tcomb, mw, gam ) self.assertAlmostEqual(IspODE, 351.7388076713265, places=3) self.assertAlmostEqual(gam, 1.157284929843286, places=3) del C
def main(): print('Python Version:', sys.version, ' RocketCEA Version:', __version__) C = CEA_Obj(oxName='N2O4', fuelName='MMH') Pc = 100.0 eps = 10.0 MR = 1.0 print( ' Pc(psia) AreaRatio MR IspVac(sec) Cstar(fps) Tc(degR) MolWt gamma' ) IspVac, Cstar, Tc, MW, gamma = C.get_IvacCstrTc_ChmMwGam(Pc=Pc, MR=MR, eps=eps) print( '%8.1f %8.1f %3.1f %8.1f %8.1f %5.1f %8.2f %8.4f '%\ (Pc, eps, MR, IspVac, Cstar, Tc, MW, gamma))
def compute(self, inputs, outputs): # inputs of the module pc = inputs['pc1'] pe = inputs['pe1'] OF = inputs['OF1'] # Rocket_CEA (only need pc(psi) and OF, eps no influence for CEA_output) CEA_output = CEA_Obj(fuelName='LH2', oxName='LOX') value = CEA_output.get_IvacCstrTc_ChmMwGam(Pc=pc * 0.000145038, MR=OF, eps=21.5) Tc = value[ 2] * 5 / 9 # chamber temperature (K rocket CEA gives it in deg Rankine) M = value[3] # molecular mass at combustion (kg/kmol) gam = value[4] # isentropic coefficient at throat (SI) #ispvac = value[0] # vacuum Isp (s) # Module parameters R = 8314 / M g0 = 9.81 # gravitational acceleration (m/s²) pa = 101325 # atmospheric pressure at z = 0m (Pa) etac = 0.99 # combustion efficiency etan = 0.938 # nozzle efficiency # Module calculations gamma = np.abs(np.sqrt(gam * (2 / (gam + 1))**((gam + 1) / (gam - 1)))) epsilon = gamma / np.sqrt(2 * gam / (gam - 1) * (pe / pc)**(2 / gam) * (1 - (pe / pc)**((gam - 1) / gam))) c_star = etac * np.sqrt(R * Tc) / gamma cf = gamma * np.sqrt(2 * gam / (gam - 1) * (1 - (pe / pc)**( (gam - 1) / gam))) + epsilon / pc * (pe - pa) Isp = etan * cf * c_star / g0 # outputs of the module outputs['c_star1'] = c_star outputs['epsilon1'] = epsilon outputs['Isp1'] = Isp self.execution_count += 1
class CEA_Obj(object): """ RocketCEA wraps the NASA FORTRAN CEA code to calculate Isp, cstar, and Tcomb This object wraps the English unit version of CEA_Obj to enable desired user units. """ def __init__(self, propName='', oxName='', fuelName='', useFastLookup=0, makeOutput=0, isp_units='sec', cstar_units='ft/sec', pressure_units='psia', temperature_units='degR', sonic_velocity_units='ft/sec', enthalpy_units='BTU/lbm', density_units='lbm/cuft', specific_heat_units='BTU/lbm degR', viscosity_units='millipoise', thermal_cond_units='mcal/cm-K-s', fac_CR=None, make_debug_prints=False): """:: #: RocketCEA wraps the NASA FORTRAN CEA code to calculate Isp, cstar, and Tcomb #: This object wraps the English unit version of CEA_Obj to enable desired user units. #: Same as CEA_Obj with standard units except, input and output units can be specified. #: parameter default options #: isp_units = 'sec', # N-s/kg, m/s, km/s #: cstar_units = 'ft/sec', # m/s #: pressure_units = 'psia', # MPa, KPa, Pa, Bar, Atm, Torr #: temperature_units = 'degR', # K, C, F #: sonic_velocity_units = 'ft/sec', # m/s #: enthalpy_units = 'BTU/lbm', # J/g, kJ/kg, J/kg, kcal/kg, cal/g #: density_units = 'lbm/cuft', # g/cc, sg, kg/m^3 #: specific_heat_units = 'BTU/lbm degR' # kJ/kg-K, cal/g-C, J/kg-K (# note: cal/g K == BTU/lbm degR) #: viscosity_units = 'millipoise' # lbf-sec/sqin, lbf-sec/sqft, lbm/ft-sec, poise, centipoise #: thermal_cond_units = 'mcal/cm-K-s' # millical/cm-degK-sec, BTU/hr-ft-degF, BTU/s-in-degF, cal/s-cm-degC, W/cm-degC #: fac_CR, Contraction Ratio of finite area combustor (None=infinite) #: if make_debug_prints is True, print debugging info to terminal. """ self.isp_units = isp_units self.cstar_units = cstar_units self.pressure_units = pressure_units self.temperature_units = temperature_units self.sonic_velocity_units = sonic_velocity_units self.enthalpy_units = enthalpy_units self.density_units = density_units self.specific_heat_units = specific_heat_units self.viscosity_units = viscosity_units self.thermal_cond_units = thermal_cond_units self.fac_CR = fac_CR # Units objects for input/output (e.g. Pc and Pamb) self.Pc_U = get_units_obj('psia', pressure_units) # units of output quantities self.isp_U = get_units_obj('sec', isp_units) self.cstar_U = get_units_obj('ft/sec', cstar_units) self.temperature_U = get_units_obj('degR', temperature_units) self.sonic_velocity_U = get_units_obj('ft/sec', sonic_velocity_units) self.enthalpy_U = get_units_obj('BTU/lbm', enthalpy_units) self.density_U = get_units_obj('lbm/cuft', density_units) self.specific_heat_U = get_units_obj('BTU/lbm degR', specific_heat_units) self.viscosity_U = get_units_obj('millipoise', viscosity_units) self.thermal_cond_U = get_units_obj('mcal/cm-K-s', thermal_cond_units) self.cea_obj = CEA_Obj_default(propName=propName, oxName=oxName, fuelName=fuelName, useFastLookup=useFastLookup, makeOutput=makeOutput, fac_CR=fac_CR, make_debug_prints=make_debug_prints) self.desc = self.cea_obj.desc def get_IvacCstrTc(self, Pc=100.0, MR=1.0, eps=40.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia IspVac, Cstar, Tcomb = self.cea_obj.get_IvacCstrTc(Pc=Pc, MR=MR, eps=eps) IspVac = self.isp_U.dval_to_uval(IspVac) Cstar = self.cstar_U.dval_to_uval(Cstar) Tcomb = self.temperature_U.dval_to_uval(Tcomb) return IspVac, Cstar, Tcomb def getFrozen_IvacCstrTc(self, Pc=100.0, MR=1.0, eps=40.0, frozenAtThroat=0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia IspFrozen, Cstar, Tcomb = self.cea_obj.getFrozen_IvacCstrTc( Pc=Pc, MR=MR, eps=eps, frozenAtThroat=frozenAtThroat) IspFrozen = self.isp_U.dval_to_uval(IspFrozen) Cstar = self.cstar_U.dval_to_uval(Cstar) Tcomb = self.temperature_U.dval_to_uval(Tcomb) return IspFrozen, Cstar, Tcomb def get_IvacCstrTc_exitMwGam(self, Pc=100.0, MR=1.0, eps=40.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia IspVac, Cstar, Tcomb, mw, gam = self.cea_obj.get_IvacCstrTc_exitMwGam( Pc=Pc, MR=MR, eps=eps) IspVac = self.isp_U.dval_to_uval(IspVac) Cstar = self.cstar_U.dval_to_uval(Cstar) Tcomb = self.temperature_U.dval_to_uval(Tcomb) return IspVac, Cstar, Tcomb, mw, gam def get_IvacCstrTc_ChmMwGam(self, Pc=100.0, MR=1.0, eps=40.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia IspVac, Cstar, Tcomb, mw, gam = self.cea_obj.get_IvacCstrTc_ChmMwGam( Pc=Pc, MR=MR, eps=eps) IspVac = self.isp_U.dval_to_uval(IspVac) Cstar = self.cstar_U.dval_to_uval(Cstar) Tcomb = self.temperature_U.dval_to_uval(Tcomb) return IspVac, Cstar, Tcomb, mw, gam def get_IvacCstrTc_ThtMwGam(self, Pc=100.0, MR=1.0, eps=40.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia IspVac, Cstar, Tcomb, mw, gam = self.cea_obj.get_IvacCstrTc_ThtMwGam( Pc=Pc, MR=MR, eps=eps) IspVac = self.isp_U.dval_to_uval(IspVac) Cstar = self.cstar_U.dval_to_uval(Cstar) Tcomb = self.temperature_U.dval_to_uval(Tcomb) return IspVac, Cstar, Tcomb, mw, gam def __call__(self, Pc=100.0, MR=1.0, eps=40.0): return self.get_Isp(Pc=Pc, MR=MR, eps=eps) def get_Isp(self, Pc=100.0, MR=1.0, eps=40.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia IspVac = self.cea_obj.get_Isp(Pc=Pc, MR=MR, eps=eps) IspVac = self.isp_U.dval_to_uval(IspVac) return IspVac def get_Cstar(self, Pc=100.0, MR=1.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia Cstar = self.cea_obj.get_Cstar(Pc=Pc, MR=MR) Cstar = self.cstar_U.dval_to_uval(Cstar) return Cstar def get_Tcomb(self, Pc=100.0, MR=1.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia Tcomb = self.cea_obj.get_Tcomb(Pc=Pc, MR=MR) Tcomb = self.temperature_U.dval_to_uval(Tcomb) return Tcomb def get_PcOvPe(self, Pc=100.0, MR=1.0, eps=40.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia return self.cea_obj.get_PcOvPe(Pc=Pc, MR=MR, eps=eps) def get_eps_at_PcOvPe(self, Pc=100.0, MR=1.0, PcOvPe=1000.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia return self.cea_obj.get_eps_at_PcOvPe(Pc=Pc, MR=MR, PcOvPe=PcOvPe) def get_Throat_PcOvPe(self, Pc=100.0, MR=1.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia return self.cea_obj.get_Throat_PcOvPe(Pc=Pc, MR=MR) def get_MachNumber(self, Pc=100.0, MR=1.0, eps=40.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia return self.cea_obj.get_MachNumber(Pc=Pc, MR=MR, eps=eps) def get_Temperatures(self, Pc=100.0, MR=1.0, eps=40.0, frozen=0, frozenAtThroat=0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia tempList = self.cea_obj.get_Temperatures(Pc=Pc, MR=MR, eps=eps, frozen=frozen, frozenAtThroat=frozenAtThroat) for i, T in enumerate(tempList): tempList[i] = self.temperature_U.dval_to_uval(T) return tempList # Tc, Tthroat, Texit def get_SonicVelocities(self, Pc=100.0, MR=1.0, eps=40.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia sonicList = self.cea_obj.get_SonicVelocities(Pc=Pc, MR=MR, eps=eps) for i, S in enumerate(sonicList): sonicList[i] = self.sonic_velocity_U.dval_to_uval(S) return sonicList # Chamber, Throat, Exit def get_Chamber_SonicVel(self, Pc=100.0, MR=1.0, eps=40.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia sonicVel = self.cea_obj.get_Chamber_SonicVel(Pc=Pc, MR=MR, eps=eps) sonicVel = self.sonic_velocity_U.dval_to_uval(sonicVel) return sonicVel def get_Enthalpies(self, Pc=100.0, MR=1.0, eps=40.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia hList = self.cea_obj.get_Enthalpies(Pc=Pc, MR=MR, eps=eps) for i, H in enumerate(hList): hList[i] = self.enthalpy_U.dval_to_uval(H) return hList def get_SpeciesMassFractions(self, Pc=100.0, MR=1.0, eps=40.0, frozen=0, frozenAtThroat=0, min_fraction=0.000005): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia molWtD, massFracD = self.cea_obj.get_SpeciesMassFractions( Pc=Pc, MR=MR, eps=eps, frozenAtThroat=frozenAtThroat, min_fraction=min_fraction) return molWtD, massFracD def get_SpeciesMoleFractions(self, Pc=100.0, MR=1.0, eps=40.0, frozen=0, frozenAtThroat=0, min_fraction=0.000005): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia molWtD, moleFracD = self.cea_obj.get_SpeciesMoleFractions( Pc=Pc, MR=MR, eps=eps, frozenAtThroat=frozenAtThroat, min_fraction=min_fraction) return molWtD, moleFracD def get_Chamber_H(self, Pc=100.0, MR=1.0, eps=40.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia H = self.cea_obj.get_Chamber_H(Pc=Pc, MR=MR, eps=eps) return self.enthalpy_U.dval_to_uval(H) def get_Densities(self, Pc=100.0, MR=1.0, eps=40.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia dList = self.cea_obj.get_Densities(Pc=Pc, MR=MR, eps=eps) for i, d in enumerate(dList): dList[i] = self.density_U.dval_to_uval(d) return dList def get_Chamber_Density(self, Pc=100.0, MR=1.0, eps=40.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia H = self.cea_obj.get_Chamber_Density(Pc=Pc, MR=MR, eps=eps) return self.density_U.dval_to_uval(H) def get_HeatCapacities(self, Pc=100.0, MR=1.0, eps=40.0, frozen=0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia cpList = self.cea_obj.get_HeatCapacities(Pc=Pc, MR=MR, eps=eps, frozen=frozen) for i, cp in enumerate(cpList): cpList[i] = self.specific_heat_U.dval_to_uval(cp) return cpList def get_Chamber_Cp(self, Pc=100.0, MR=1.0, eps=40.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia Cp = self.cea_obj.get_Chamber_Cp(Pc=Pc, MR=MR, eps=eps) return self.specific_heat_U.dval_to_uval(Cp) def get_Throat_Isp(self, Pc=100.0, MR=1.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia Isp = self.cea_obj.get_Throat_Isp(Pc=Pc, MR=MR) Isp = self.isp_U.dval_to_uval(Isp) return Isp def get_Chamber_MolWt_gamma(self, Pc=100.0, MR=1.0, eps=40.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia return self.cea_obj.get_Chamber_MolWt_gamma(Pc=Pc, MR=MR, eps=eps) def get_Throat_MolWt_gamma(self, Pc=100.0, MR=1.0, eps=40.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia return self.cea_obj.get_Throat_MolWt_gamma(Pc=Pc, MR=MR, eps=eps) def get_exit_MolWt_gamma(self, Pc=100.0, MR=1.0, eps=40.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia return self.cea_obj.get_exit_MolWt_gamma(Pc=Pc, MR=MR, eps=eps) def get_eqratio(self, Pc=100.0, MR=1.0, eps=40.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia return self.cea_obj.get_eqratio(Pc=Pc, MR=MR, eps=eps) def getMRforER(self, ERphi=None, ERr=None): return self.cea_obj.getMRforER(ERphi=ERphi, ERr=ERr) def get_description(self): return self.cea_obj.get_description() def estimate_Ambient_Isp(self, Pc=100.0, MR=1.0, eps=40.0, Pamb=14.7, frozen=0, frozenAtThroat=0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia Pamb = self.Pc_U.uval_to_dval(Pamb) # convert user units to psia IspAmb, mode = self.cea_obj.estimate_Ambient_Isp( Pc=Pc, MR=MR, eps=eps, Pamb=Pamb, frozen=frozen, frozenAtThroat=frozenAtThroat) IspAmb = self.isp_U.dval_to_uval(IspAmb) return IspAmb, mode def get_PambCf(self, Pamb=14.7, Pc=100.0, MR=1.0, eps=40.0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia Pamb = self.Pc_U.uval_to_dval(Pamb) # convert user units to psia CFcea, CF, mode = self.cea_obj.get_PambCf(Pamb=Pamb, Pc=Pc, MR=MR, eps=eps) return CFcea, CF, mode def getFrozen_PambCf(self, Pamb=0.0, Pc=100.0, MR=1.0, eps=40.0, frozenAtThroat=0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia Pamb = self.Pc_U.uval_to_dval(Pamb) # convert user units to psia CFcea, CFfrozen, mode = self.cea_obj.getFrozen_PambCf( Pamb=Pamb, Pc=Pc, MR=MR, eps=eps, frozenAtThroat=frozenAtThroat) return CFcea, CFfrozen, mode def get_Chamber_Transport(self, Pc=100.0, MR=1.0, eps=40.0, frozen=0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia Cp, visc, cond, Prandtl = self.cea_obj.get_Chamber_Transport( Pc=Pc, MR=MR, eps=eps, frozen=frozen) #Cp = Cp * 8314.51 / 4184.0 # convert into BTU/lbm degR Cp = self.specific_heat_U.dval_to_uval(Cp) visc = self.viscosity_U.dval_to_uval(visc) cond = self.thermal_cond_U.dval_to_uval(cond) return Cp, visc, cond, Prandtl def get_Throat_Transport(self, Pc=100.0, MR=1.0, eps=40.0, frozen=0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia Cp, visc, cond, Prandtl = self.cea_obj.get_Throat_Transport( Pc=Pc, MR=MR, eps=eps, frozen=frozen) #Cp = Cp * 8314.51 / 4184.0 # convert into BTU/lbm degR Cp = self.specific_heat_U.dval_to_uval(Cp) visc = self.viscosity_U.dval_to_uval(visc) cond = self.thermal_cond_U.dval_to_uval(cond) return Cp, visc, cond, Prandtl def get_Exit_Transport(self, Pc=100.0, MR=1.0, eps=40.0, frozen=0): Pc = self.Pc_U.uval_to_dval(Pc) # convert user units to psia Cp, visc, cond, Prandtl = self.cea_obj.get_Exit_Transport( Pc=Pc, MR=MR, eps=eps, frozen=frozen) Cp = Cp * 8314.51 / 4184.0 # convert into BTU/lbm degR Cp = self.specific_heat_U.dval_to_uval(Cp) visc = self.viscosity_U.dval_to_uval(visc) cond = self.thermal_cond_U.dval_to_uval(cond) return Cp, visc, cond, Prandtl
RupArr = np.linspace(0.75, 3, 50) cd_simpL = [ get_Cd( Rup=Rup, gamma=1.2 ) for Rup in RupArr ] prop_cycle = plt.rcParams['axes.prop_cycle'] colors = prop_cycle.by_key()['color'] colorL = [c for c in colors] # ----------- Pc ----------------------- fig, ax = plt.subplots() ax.plot(RupArr, cd_simpL,'-k', label='Simple, gam=%g'%1.2 ) for oxName, fuelName, MR, line_style in [('N2O4','A50', 1.6, '-'), ('LOX','LH2', 6, '--')]: ceaObj = CEA_Obj(oxName=oxName, fuelName=fuelName) for i,Pc in enumerate([3000, 500, 100]): _, _, TcCham, MolWt, gammaInit = ceaObj.get_IvacCstrTc_ChmMwGam( Pc=Pc, MR=MR, eps=20) cd_mlpL = [calc_Cd( Pc=Pc, eps=20, Rthrt=1, pcentBell=80, THETAI=30.0, RWTU=Rup, RWTD=1.0, CR=2.5, RI=1.0, TcCham=TcCham, MolWt=MolWt, gammaInit=gammaInit) for Rup in RupArr] ax.plot(RupArr, cd_mlpL,line_style, color=colorL[i], label='%s/%s, Pc=%g'%(oxName, fuelName, Pc) ) plt.legend() plt.title('Cd Throat') plt.ylabel('Cd') plt.xlabel('Upstream Radius Ratio (RupThroat)') # ------------------------ show ----------------------- plt.show()
class CoreStream: """ Core stream tube of liquid bipropellant thruster. :param geomObj: Geometry that describes thruster :param effObj: Efficiencies object to hold individual efficiencies :param oxName: name of oxidizer (e.g. N2O4, LOX) :param fuelName: name of fuel (e.g. MMH, LH2) :param MRcore: mixture ratio of core flow (ox flow rate / fuel flow rate) :param Pc: psia, chamber pressure :param CdThroat: Cd of throat (RocketThruster object may override) :param Pamb: psia, ambient pressure (for example sea level is 14.7 psia) :param adjCstarODE: multiplier on NASA CEA code value of cstar ODE (default is 1.0) :param adjIspIdeal: multiplier on NASA CEA code value of Isp ODE (default is 1.0) :param pcentFFC: percent fuel film cooling (if > 0 then add BarrierStream) :param ko: entrainment constant (passed to BarrierStream object, range from 0.03 to 0.06) :param ignore_noz_sep: flag to force nozzle flow separation to be ignored (USE WITH CAUTION) :type geomObj: Geometry :type effObj: Efficiencies :type oxName: str :type fuelName: str :type MRcore: float :type Pc: float :type CdThroat: float :type Pamb: float :type adjCstarODE: float :type adjIspIdeal: float :type pcentFFC: float :type ko: float :type ignore_noz_sep: bool :return: CoreStream object :rtype: CoreStream :ivar FvacTotal: lbf, total vacuum thrust :ivar FvacCore: lbf, vacuum thrust due to core stream tube :ivar MRthruster: total thruster mixture ratio') :ivar IspDel: sec, <=== thruster delivered vacuum Isp ===> :ivar Pexit: psia, nozzle exit pressure :ivar IspDel_core: sec, delivered Isp of core stream tube :ivar IspODF: sec, core frozen Isp :ivar IspODK: sec, core one dimensional kinetic Isp :ivar IspODE: sec, core one dimensional equilibrium Isp :ivar cstarERE: ft/s, delivered core cstar :ivar cstarODE: ft/s, core ideal cstar :ivar CfVacIdeal: ideal vacuum thrust coefficient :ivar CfVacDel: delivered vacuum thrust coefficient :ivar CfAmbDel: delivered ambient thrust coefficient :ivar wdotTot: lbm/s, total propellant flow rate (ox+fuel) :ivar wdotOx: lbm/s, total oxidizer flow rate :ivar wdotFl: lbm/s, total fuel flow rate :ivar TcODE: degR, ideal core gas temperature :ivar MWchm: g/gmole, core gas molecular weight :ivar gammaChm: core gas ratio of specific heats (Cp/Cv) """ def __init__( self, geomObj=Geometry(), effObj=Efficiencies(), #ERE=0.98, Noz=0.97), oxName='N2O4', fuelName='MMH', MRcore=1.9, Pc=500, CdThroat=0.995, Pamb=0.0, adjCstarODE=1.0, adjIspIdeal=1.0, pcentFFC=0.0, ko=0.035, ignore_noz_sep=False): self.geomObj = geomObj self.effObj = effObj self.oxName = oxName self.fuelName = fuelName self.MRcore = MRcore self.Pc = Pc self.Pamb = Pamb # ambient pressure self.noz_mode = '' self.CdThroat = CdThroat self.CdThroat_method = 'default' self.ignore_noz_sep = ignore_noz_sep # ignore any nozzle separation self.adjCstarODE = adjCstarODE # may want to adjust ODE cstar value self.adjIspIdeal = adjIspIdeal # may want to adjust ODE and ODF Isp values # make CEA object self.ceaObj = CEA_Obj(oxName=oxName, fuelName=fuelName) # ... if pcentFFC > 0.0, then there's barrier cooling if pcentFFC > 0.0: self.add_barrier = True else: self.add_barrier = False # barrier might need some performance parameters from CoreStream self.calc_cea_perf_params() if self.add_barrier: self.barrierObj = BarrierStream(self, pcentFFC=pcentFFC, ko=ko) else: self.barrierObj = None self.evaluate() # get input descriptions and units from doc string self.inp_descD, self.inp_unitsD, self.is_inputD = get_desc_and_units( self.__doc__) def __call__(self, name): return getattr(self, name) # let it raise exception if no name attr. def reset_CdThroat(self, value, method_name='RocketIsp', re_evaluate=True): """ reset the value of CdThroat If re_evaluate is True, then call self.evaluate() after resetting the efficiency. """ self.CdThroat = value self.CdThroat_method = method_name if re_evaluate: self.evaluate() def reset_attr(self, name, value, re_evaluate=True): """ reset the value of any existing attribute of CoreStream instance. If re_evaluate is True, then call self.evaluate() after resetting the value of the attribute. """ if hasattr(self, name): setattr(self, name, value) else: raise Exception( 'Attempting to set un-authorized CoreStream attribute named "%s"' % name) if name in ['oxName', 'fuelName']: # make CEA object self.ceaObj = CEA_Obj(oxName=self.oxName, fuelName=self.fuelName) if re_evaluate: self.evaluate() def calc_cea_perf_params(self): """Calc basic Isp values from CEA and calc implied IspODK from current effKin value.""" # calc ideal CEA performance parameters self.IspODE, self.cstarODE, self.TcODE, self.MWchm, self.gammaChm = \ self.ceaObj.get_IvacCstrTc_ChmMwGam( Pc=self.Pc, MR=self.MRcore, eps=self.geomObj.eps) self.cstarODE *= self.adjCstarODE self.IspODE *= self.adjIspIdeal self.IspODF, _, _ = self.ceaObj.getFrozen_IvacCstrTc( Pc=self.Pc, MR=self.MRcore, eps=self.geomObj.eps) self.IspODF *= self.adjIspIdeal # use user effKin to set IspODK (or most recent update) self.IspODK = self.IspODE * self.effObj('Kin') #self.IspODK = calc_IspODK(self.ceaObj, Pc=self.Pc, eps=self.geomObj.eps, # Rthrt=self.geomObj.Rthrt, # pcentBell=self.geomObj.pcentBell, # MR=self.MRcore) # fraction of equilibrium kinetics obtained self.fracKin = (self.IspODK - self.IspODF) / (self.IspODE - self.IspODF) self.Pexit = self.Pc / self.ceaObj.get_PcOvPe( Pc=self.Pc, MR=self.MRcore, eps=self.geomObj.eps) self.CfVacIdeal = 32.174 * self.IspODE / self.cstarODE def evaluate(self): """ Assume that all efficiencies have been set, either by original user value or an update by an efficiency model. """ self.effObj.evaluate() self.calc_cea_perf_params() # make final summary efficiencies effNoz = self.effObj('Noz') # want a Core-Only ERE in case a barrier calc is done effERE_core = self.effObj('ERE') if not self.add_barrier: # if no barrier, user may have input FFC effERE_core = effERE_core * self.effObj('FFC') cstarERE_core = self.cstarODE * effERE_core effIsp_core = effNoz * effERE_core self.IspDel_core = effIsp_core * self.IspODE if self.add_barrier: self.barrierObj.evaluate() fAtc = solve_At_split(self.MRcore, self.barrierObj.MRbarrier, self.barrierObj.pcentFFC / 100.0, cstarERE_core, self.barrierObj.cstarERE_b) self.frac_At_core = fAtc # core shares throat area with barrier stream self.frac_At_barrier = 1.0 - self.frac_At_core self.At_b = self.frac_At_barrier * self.geomObj.At self.wdotTot_b = self.Pc * self.At_b * self.CdThroat * 32.174 / self.barrierObj.cstarERE_b self.wdotOx_b = self.wdotTot_b * self.barrierObj.MRbarrier / ( 1.0 + self.barrierObj.MRbarrier) self.wdotFl_b = self.wdotTot_b - self.wdotOx_b self.FvacBarrier = self.wdotTot_b * self.barrierObj.IspDel_b self.MRthruster = self.MRcore * (1.0 - self.barrierObj.pcentFFC / 100.0) else: self.frac_At_core = 1.0 # core gets all of throat area if no barrier stream self.frac_At_barrier = 0.0 self.FvacBarrier = 0.0 self.MRthruster = self.MRcore self.wdotTot_b = 0.0 self.wdotOx_b = 0.0 self.wdotFl_b = 0.0 self.Atcore = self.frac_At_core * self.geomObj.At self.wdotTot_c = self.Pc * self.Atcore * self.CdThroat * 32.174 / cstarERE_core self.wdotOx_c = self.wdotTot_c * self.MRcore / (1.0 + self.MRcore) self.wdotFl_c = self.wdotTot_c - self.wdotOx_c self.FvacCore = self.wdotTot_c * self.IspDel_core self.FvacTotal = self.FvacCore + self.FvacBarrier self.wdotTot = self.wdotTot_c + self.wdotTot_b self.wdotOx = self.wdotOx_c + self.wdotOx_b self.wdotFl = self.wdotFl_c + self.wdotFl_b if self.add_barrier: self.wdotFlFFC = (self.barrierObj.pcentFFC / 100.0) * self.wdotFl self.wdotFl_cInit = self.wdotFl - self.wdotFlFFC self.wdotTot_cInit = self.wdotOx + self.wdotFl_cInit else: self.wdotFlFFC = 0.0 self.wdotFl_cInit = self.wdotFl self.wdotTot_cInit = self.wdotTot self.IspDel = self.FvacTotal / self.wdotTot self.IspDelPulse = self.IspDel * self.effObj('Pulse') if self.add_barrier: # if barrier is analysed, assume it is in addition to user input effERE effFFC = self.IspDel / self.IspDel_core self.effObj.set_value('FFC', effFFC, value_src='barrier calc') self.cstarERE = self.cstarODE * self.effObj('ERE') #self.cstarDel = self.Pc * self.Atcore * self.CdThroat * 32.174 / self.wdotTot # do any nozzle ambient performance calcs here if self.Pamb < 0.000001: self.IspAmb = self.IspDel self.noz_mode = '(Pexit=%g psia)' % self.Pexit else: CfOvCfvacAtEsep, CfOvCfvac, Cfsep, CfiVac, CfiAmbSimple, CfVac, self.epsSep, self.Psep = \ sepNozzleCf(self.gammaChm, self.geomObj.eps, self.Pc, self.Pamb) #print('epsSep=%g, Psep=%g'%(self.epsSep, self.Psep)) #print('========= Pexit=%g'%self.Pexit, ' Psep=%g'%self.Psep, ' epsSep=%g'%self.epsSep) if self.Pexit > self.Psep or self.geomObj.eps < self.epsSep or self.ignore_noz_sep: # if not separated, use theoretical equation for back-pressure correction self.IspAmb = self.IspDel - self.cstarERE * self.Pamb * self.geomObj.eps / self.Pc / 32.174 #print('----------------> subtraction term =', self.cstarERE * self.Pamb * self.geomObj.eps / self.Pc / 32.174) else: # if separated, use Kalt and Badal estimate of ambient thrust coefficient # NOTE: there are better, more modern methods available IspODEepsSep, CstarODE, Tc = \ self.ceaObj.get_IvacCstrTc(Pc=self.Pc, MR=self.MRcore, eps=self.epsSep) IspODEepsSep = IspODEepsSep - self.cstarERE * self.Pamb * self.epsSep / self.Pc / 32.174 effPamb = IspODEepsSep / self.IspODE #print('--------------> effPamb=%g'%effPamb, ' IspODEepsSep=%g'%IspODEepsSep, ' IspODE=%g'%self.IspODE) self.IspAmb = effPamb * self.IspDel #print('========= Pamb=%g'%self.Pamb, ' IspAmb=%g'%self.IspAmb) # figure out mode of nozzle operation if self.Pexit > self.Psep or self.geomObj.eps < self.epsSep: if self.Pexit > self.Pamb + 0.05: self.noz_mode = 'UnderExpanded (Pexit=%g)' % self.Pexit elif self.Pexit < self.Pamb - 0.05: self.noz_mode = 'OverExpanded (Pexit=%g)' % self.Pexit else: self.noz_mode = 'Pexit=%g' % self.Pexit else: self.noz_mode = 'Separated (Psep=%g, epsSep=%g)' % ( self.Psep, self.epsSep) self.Fambient = self.FvacTotal * self.IspAmb / self.IspDel self.CfVacDel = self.FvacTotal / (self.geomObj.At * self.Pc ) # includes impact of CdThroat self.CfAmbDel = self.Fambient / (self.geomObj.At * self.Pc ) # includes impact of CdThroat def summ_print(self): """ print to standard output, the current state of CoreStream instance. """ print(self.get_summ_str()) def get_summ_str(self, alpha_ordered=True, numbered=False, add_trailer=True, fillchar='.', max_banner=76, intro_str=''): """ return string of the current state of CoreStream instance. """ M = self.get_model_summ_obj() Me = self.effObj.get_model_summ_obj() se = '\n' + Me.summ_str( alpha_ordered=False, fillchar=' ', assumptions_first=False) if self.add_barrier: Mb = self.barrierObj.get_model_summ_obj() sb = '\n' + Mb.summ_str(alpha_ordered=alpha_ordered, numbered=numbered, add_trailer=add_trailer, fillchar=fillchar, max_banner=max_banner, intro_str=intro_str) else: sb = '' return M.summ_str(alpha_ordered=alpha_ordered, numbered=numbered, add_trailer=add_trailer, fillchar=fillchar, max_banner=max_banner, intro_str=intro_str) + se + sb def get_html_str(self, alpha_ordered=True, numbered=False, intro_str=''): M = self.get_model_summ_obj() Me = self.effObj.get_model_summ_obj() se = '\n' + Me.html_table_str(alpha_ordered=False, assumptions_first=False) if self.add_barrier: Mb = self.barrierObj.get_model_summ_obj() sb = '\n' + Mb.html_table_str(alpha_ordered=alpha_ordered, numbered=numbered, intro_str=intro_str) else: sb = '' return M.html_table_str( alpha_ordered=alpha_ordered, numbered=numbered, intro_str=intro_str)\ + se + sb def get_model_summ_obj(self): """ return ModelSummary object for current state of CoreStream instance. """ M = ModelSummary('%s/%s Core Stream Tube' % (self.oxName, self.fuelName)) M.add_alt_units('psia', ['MPa', 'atm', 'bar']) M.add_alt_units('lbf', 'N') M.add_alt_units('lbm/s', 'kg/s') M.add_alt_units('ft/s', 'm/s') M.add_alt_units('sec', ['N-sec/kg', 'km/sec']) M.add_alt_units('degR', ['degK', 'degC', 'degF']) M.add_param_fmt('Pexit', '%.4f') M.add_param_fmt('Pc', '%.1f') M.add_out_category('') # show unlabeled category 1st def add_param(name, desc='', fmt='', units='', value=None, category=''): if name in self.inp_unitsD: units = self.inp_unitsD[name] if desc == '' and name in self.inp_descD: desc = self.inp_descD[name] if value is None: value = getattr(self, name) if self.is_inputD.get(name, False): M.add_inp_param(name, value, units, desc, fmt=fmt) else: M.add_out_param(name, value, units, desc, fmt=fmt, category=category) for name in self.is_inputD.keys(): if name not in ['pcentFFC', 'ko', 'geomObj', 'effObj']: add_param(name) # parameters that are NOT attributes OR are conditional if self.add_barrier: add_param('FvacBarrier', units='lbf', desc='vacuum thrust due to barrier stream tube') if self.Pamb > 14.5: add_param('Fambient', units='lbf', desc='total sea level thrust') add_param('IspAmb', units='sec', desc='delivered sea level Isp') M.add_out_comment('Fambient', '%s' % self.noz_mode) M.add_out_comment('IspAmb', '%s' % self.noz_mode) elif self.Pamb > 0.0: add_param('Fambient', units='lbf', desc='total ambient thrust') add_param('IspAmb', units='sec', desc='delivered ambient Isp') M.add_out_comment('Fambient', '%s' % self.noz_mode) M.add_out_comment('IspAmb', '%s' % self.noz_mode) if self.effObj('Pulse') < 1.0: add_param('IspDelPulse', units='sec', desc='delivered pulsing Isp') if self.CdThroat_method != 'default': M.add_inp_comment('CdThroat', '(%s)' % self.CdThroat_method) if self.add_barrier: add_param('wdotFlFFC', units='lbm/s', desc='fuel film coolant flow rate injected at perimeter', category='At Injector Face') add_param( 'wdotFl_cInit', units='lbm/s', desc='initial core fuel flow rate (before any entrainment)', category='At Injector Face') add_param( 'wdotTot_cInit', units='lbm/s', desc='initial core total flow rate (before any entrainment)', category='At Injector Face') add_param( 'wdotTot_b', units='lbm/s', desc='total barrier propellant flow rate (includes entrained)', category='After Entrainment') add_param('wdotOx_b', units='lbm/s', desc='barrier oxidizer flow rate (all entrained)', category='After Entrainment') add_param('wdotFl_b', units='lbm/s', desc='barrier fuel flow rate (FFC + entrained)', category='After Entrainment') add_param( 'wdotTot_c', units='lbm/s', desc= 'total final core propellant flow rate (injected - entrained)', category='After Entrainment') add_param( 'wdotOx_c', units='lbm/s', desc='final core oxidizer flow rate (injected - entrained)', category='After Entrainment') add_param('wdotFl_c', units='lbm/s', desc='final core fuel flow rate (injected - entrained)', category='After Entrainment') #add_param('xxx', units='xxx', desc='xxx') return M
from rocketcea import separated_Cf from rocketcea import xlChart from rocketcea.cea_obj import CEA_Obj pc = 108.0 eps = 5.0 oxName = 'N2O4' fuelName = 'MMH' mr = 1.65 Nsteps = 20 ispObj = CEA_Obj(oxName=oxName, fuelName=fuelName) IspODE, Cstar, Tcomb, mw, gam = ispObj.get_IvacCstrTc_ChmMwGam(Pc=pc, MR=mr, eps=eps) pcArr = [100.0, 150.0, 200.0] rs = [['Pamb', 'Cf/Cfvac', 'Pc', 'mode']] for pc in pcArr: for i in range(Nsteps + 1): Pamb = 14.7 * i / Nsteps Cf, CfOverCfvac, mode = separated_Cf.ambientCf(gam=gam, epsTot=eps, Pc=pc, Pamb=Pamb) rs.append([Pamb, CfOverCfvac, pc, mode]) rs.append(['', '', '', ''])
class CEA: def __init__(self, oxName, fuelName): self.oxName = oxName self.fuelName = fuelName # dictionary containing the standard heat of formation for all species in [kJ/mol] # you can find this data in thermo.inp in the rocketCEA library folder self.heatDict = { "ABS": 62.719, "Acrylic": 382.0, "N2O": 82.05, "LO2": 0, "*CO": -110.53, "*CO2": -393.5, "*H": 217.998, "HCO": 42.397, "HO2": 12.02, "*H2": 0, "C(gr)": 0, "H2O": -241.826, "*N": 472.680, "*NO": 91.271, "*N2": 0, "*O": 249.175, "*OH": 37.278, "*O2": 0, "COOH": -213, "H2O2": -135.88, "O3": 141.8, "CH3": 146.658, "CH4": -74.6, "C2H2,acetylene": 228.2, "CH2CO,ketene": -49.576, "C2H4": 52.5, "HCN": 133.082, "HNC": 194.378, "NH3": -54.752, "CH3CN": 31.38, "C4H2,butadiyne": 450, "C2N2": 283.209, "*CN": 438.683, "HNCO": -118.056, "C3H3,2-propynl": 331.8, "HNO": 102.032, "NO2": 34.193, "C2H6": -103.819, "HCHO,formaldehy": -108.58, "C3H6,propylene": 20.0 } # Dictionary holding molar masses for reactants [g/mol] self.MMDict = { "LO2": 15.999, "N2O": 44.013, "ABS": 57.07, "Acrylic": 100.12 } self.addCustomSpecies() self.C = CEA_Obj(oxName=oxName, fuelName=fuelName) def getOutput(self, Pc, OFRatio, ExpansionRatio, printOutput): output = self.C.get_full_cea_output(Pc=Pc, MR=OFRatio, eps=ExpansionRatio, short_output=0, output='siunits') if printOutput: print(output) def getChamberEquilibrium(self, Pc, OFRatio, ExpansionRatio, location): # gets all of the properties of the thingy (make sure not to ask for too much, you will upset him) # location: 0-injector (not supported) 1-chamber 2-throat 3-exit if location == 0: print("ERROR: properties at injector not supported") elif location == 1: self.Isp_Vac, self.C_star, self.T_flame, self.MW, self.gamma = self.C.get_IvacCstrTc_ChmMwGam(Pc=Pc, MR=OFRatio, eps=ExpansionRatio) # get ISP [s], C* [ft/s], T [R], MW [g/mol], gamma [-] self.Cp, self.visc, self.thermCond, self.prandtl = self.C.get_Chamber_Transport(Pc, OFRatio, ExpansionRatio) # get heat capacity [cal/g*K], viscosity[milliPoise], thermal conductivity [mcal/cm*s*K], Prandtl Number [-] elif location == 2: self.Isp_Vac, self.C_star, self.T_flame, self.MW, self.gamma = self.C.get_IvacCstrTc_ThtMwGam(Pc=Pc, MR=OFRatio, eps=ExpansionRatio) # get ISP [s], C* [ft/s], T [R], MW [g/mol], gamma [-] self.Cp, self.visc, self.thermCond, self.prandtl = self.C.get_Throat_Transport(Pc, OFRatio, ExpansionRatio) # get heat capacity [cal/g*K], viscosity[milliPoise], thermal conductivity [mcal/cm*s*K], Prandtl Number [-] elif location == 3: self.Isp_Vac, self.C_star, self.T_flame, self.MW, self.gamma = self.C.get_IvacCstrTc_exitMwGam(Pc=Pc, MR=OFRatio, eps=ExpansionRatio) # get ISP [s], C* [ft/s], T [R], MW [g/mol], gamma [-] self.Cp, self.visc, self.thermCond, self.prandtl = self.C.get_Exit_Transport(Pc, OFRatio, ExpansionRatio) # get heat capacity [cal/g*K], viscosity[milliPoise], thermal conductivity [mcal/cm*s*K], Prandtl Number [-] else: print("ERROR: location index out of bounds") self.T_flame = self.T_flame/1.8 # convert to Kelvin self.C_star = self.C_star / 3.28084 # convert characteristic velocity to [m/s] self.Cp = self.Cp * 4.186798 # get specific heat capacity [j/g*C] self.visc = self.visc/1000 # convert from milliPoise to Poise self.thermCond = self.thermCond * 418000 # convert to [W/m*K] return self.Isp_Vac, self.C_star, self.T_flame, self.MW, self.gamma, self.Cp, self.visc, self.thermCond, self.prandtl def getReactionHeat(self, Pc, OFRatio, ExpansionRatio, location): h_products = self.getProductsEnthalpy(Pc, OFRatio, ExpansionRatio, location) h_fuel = self.findHeatOfFormation(self.fuelName)/self.MMDict[self.fuelName] h_ox = self.findHeatOfFormation(self.oxName)/self.MMDict[self.oxName] X_fuel = 1/(OFRatio+1) # fuel mass fraction X_ox = OFRatio/(OFRatio+1) # oxidizer mass fraction h_reactants = X_fuel*h_fuel + X_ox*h_ox Q_total = h_products - h_reactants # assuming adiabatic circumstances, Q_total = deltaH return Q_total def getProductsEnthalpy(self, Pc, OFRatio, ExpansionRatio, location): # calculates the enthalpy per gram of products # location: 0-injector 1-chamber 2-throat 3-exit molarMass, massFraction = self.C.get_SpeciesMassFractions(Pc=Pc, MR=OFRatio, eps=ExpansionRatio) # convert molarMass and massFraction into lists with species name in first column, and data in second molarMass = list(molarMass), list(molarMass.values()) massFraction = list(massFraction), list(massFraction.values()) # create an array containing the standard heat of formations of all species h_f = molarMass h_products = 0 for i in range(len(molarMass[0])): h_f[1][i] = self.findHeatOfFormation(molarMass[0][i]) / molarMass[1][i] # heat of formation [kJ/g] h_products += h_f[1][i] * massFraction[1][i][location] return h_products def findHeatOfFormation(self, species): try: return self.heatDict[species] except: print("ERROR:", species, "is not defined in heat of formation dictionary. Look in the init of the CEA class") def addCustomSpecies(self): # Add custom species to CEA card_str = """ fuel ABS C 3.85 H 4.85 N 0.43 wt%=100.00 h,cal=14990 t(k)=298.15 rho=0.975 """ add_new_fuel('ABS', card_str) card_str = """ fuel Acrylic C 5 H 8 O 2 wt%=100.00 h,cal=91396 t(k)=298.15 rho=1.18 """ add_new_fuel('Acrylic', card_str)
import matplotlib.pyplot as plt import numpy as np from rocketisp.nozzle.cd_throat import get_Cd from calc_full_Cd import calc_Cd from rocketcea.cea_obj import CEA_Obj prop_cycle = plt.rcParams['axes.prop_cycle'] colors = prop_cycle.by_key()['color'] colorL = [c for c in colors] ceaObj = CEA_Obj(oxName='N2O4', fuelName='MMH') _, _, TcCham, MolWt, gammaInit = ceaObj.get_IvacCstrTc_ChmMwGam(Pc=500, MR=1.5, eps=20) RupArr = np.linspace(0.75, 3, 50) cd_simpL = [get_Cd(Rup=Rup, gamma=gammaInit) for Rup in RupArr] # ----------- CR ----------------------- fig, ax = plt.subplots() ax.plot(RupArr, cd_simpL, '-k', label='Simple, gam=%g' % gammaInit) for CR in [2, 2.5, 3, 4]: cd_mlpL = [ calc_Cd(ceaObj, Pc=500, eps=20, Rthrt=1, pcentBell=80, MR=1.5, THETAI=30.0,
def main(): print('Python Version:', sys.version, ' RocketCEA Version:', __version__) C = CEA_Obj(oxName='GOX', fuelName='GH2') Pc = 40.0 eps = 5.0 MR = 5.0 print( ' Pc(psia) AreaRatio MR IspVac(sec) Cstar(fps) Tc(degR) MolWt gamma' ) IspVac, Cstar, Tc, MW, gamma = C.get_IvacCstrTc_ChmMwGam(Pc=Pc, MR=MR, eps=eps) print( '%8.1f %8.1f %3.1f %8.1f %8.1f %5.1f %8.2f %8.4f '%\ (Pc, eps, MR, IspVac, Cstar, Tc, MW, gamma)) print('py_cea.indx.npt =', py_cea.indx.npt) #print( py_cea.comp.en ) #print( py_cea.cdata.prod ) massFracD = {} # index=species: value=[massfrac1, massfrac2, ...] molWtD = {} # index=species: value=molecular weight print(' ROCKETCEA MASS FRACTIONS') for k, p in enumerate(py_cea.cdata.prod): p = p.decode("utf-8").strip() if p: sL = [] mfL = [] gt_zero = False for i in range(3): en = py_cea.comp.en[k - 1, i] mw = py_cea.therm.mw[k - 1] sL.append('%7.5f' % (en * mw, )) mfL.append(en * mw) if mfL[-1] >= 0.000005: gt_zero = True if gt_zero: print('%-17s' % p, ' '.join(sL), ' MW=%7.4f' % mw) massFracD[p] = mfL molWtD[p] = mw print(""" CEA OUTPUT: MASS FRACTIONS *H 0.00637 0.00531 0.00081 HO2 0.00002 0.00001 0.00000 *H2 0.06108 0.06063 0.06109 H2O 0.85269 0.87387 0.93445 *O 0.00703 0.00463 0.00005 *OH 0.06416 0.04962 0.00352 *O2 0.00865 0.00593 0.00008 """) print(molWtD) print(massFracD) moleFracD = {} # index=species: value=[molefrac1, molefrac2, ...] molWtD = {} # index=species: value=molecular weight print(' ROCKETCEA MOLE FRACTIONS') for k, p in enumerate(py_cea.cdata.prod): p = p.decode("utf-8").strip() if p: sL = [] mfL = [] gt_zero = False for i in range(3): en = py_cea.comp.en[k - 1, i] totn = py_cea.prtout.totn[i] sL.append('%7.5f' % (en / totn, )) mfL.append(en / totn) if mfL[-1] >= 0.000005: gt_zero = True if gt_zero: print('%-17s' % p, ' '.join(sL)) moleFracD[p] = mfL molWtD[p] = mw print(""" CEA OUTPUT MOLE FRACTIONS *H 0.07147 0.06044 0.00962 HO2 0.00001 0.00000 0.00000 *H2 0.34261 0.34471 0.36428 H2O 0.53522 0.55597 0.62354 *O 0.00497 0.00332 0.00004 *OH 0.04266 0.03344 0.00249 *O2 0.00306 0.00212 0.00003 """) print(molWtD) print(moleFracD)