def test_chamber_transport_props(self): """test chamber transport props""" C = CEA_Obj( oxName='LOX', fuelName='LH2', fac_CR=None) CwU = CEA_Obj_w_units( oxName='LOX', fuelName='LH2', pressure_units='MPa', specific_heat_units='kJ/kg-K', # note: cal/g K == BTU/lbm degR viscosity_units='poise', thermal_cond_units='BTU/s-in-degF', fac_CR=None) Cp1, v1, con1, P1 = C.get_Chamber_Transport(Pc=1000.0, MR=6.0, eps=40.0, frozen=0) Cp2, v2, con2, P2 = CwU.get_Chamber_Transport(Pc=1000.0/145.037738, MR=6.0, eps=40.0, frozen=0) Cp3 = C.get_Chamber_Cp(Pc=1000.0, MR=6.0, eps=40.0, frozen=0) # look at heat capacity self.assertAlmostEqual(Cp1, 2.0951, delta=0.001) self.assertAlmostEqual(Cp2, 8.771346, delta=0.001) self.assertAlmostEqual(Cp1, Cp3, delta=0.001) # look at viscosity self.assertAlmostEqual(v1, 1.0588, delta=0.001) self.assertAlmostEqual(v2, 0.0010588, delta=0.000001) # look at conductivity self.assertAlmostEqual(con1, 4.1444, delta=0.0001) self.assertAlmostEqual(con2, 2.3192E-5, delta=1.0E-9)
class CEA(): def __init__(self, fuel, oxidiser, chamber_pressure): """[summary] Calcualtes hot gas properties using CEA and converts to SI units. If errors occur with FORTRAN, resart and try again! :param chamber_pressure in [Pa] :type fuel = string :type oxidiser = string """ self.chamber_pressure = chamber_pressure self.imperial_pressure = 0.000145038 * self.chamber_pressure #conversion to psia self.ispObj = CEA_Obj(oxName=oxidiser, fuelName=fuel) self.ispObj.get_full_cea_output() def chamber_gas_properties(self, mixture_ratio, expansion_ratio): self.Cp, self.visc, self.cond, self.Pr = self.ispObj.get_Chamber_Transport( Pc=self.imperial_pressure, MR=mixture_ratio, frozen=1) self.MW, self.gamma = self.ispObj.get_Chamber_MolWt_gamma( Pc=self.imperial_pressure, MR=mixture_ratio, eps=expansion_ratio) def throat_gas_properties(self, mixture_ratio, expansion_ratio): self.Cp, self.visc, self.cond, self.Pr = self.ispObj.get_Throat_Transport( Pc=self.imperial_pressure, MR=mixture_ratio, frozen=1) self.MW, self.gamma = self.ispObj.get_Throat_MolWt_gamma( Pc=self.imperial_pressure, MR=mixture_ratio, eps=expansion_ratio) def exit_gas_properties(self, mixture_ratio, expansion_ratio): self.Cp, self.visc, self.cond, self.Pr = self.ispObj.get_Exit_Transport( Pc=self.imperial_pressure, MR=mixture_ratio, frozen=1) self.MW, self.gamma = self.ispObj.get_exit_MolWt_gamma( Pc=self.imperial_pressure, MR=mixture_ratio, eps=expansion_ratio) def metric_cea_output(self, location, mixture_ratio, expansion_ratio): if location == 'chamber': self.chamber_gas_properties(mixture_ratio, expansion_ratio) elif location == 'throat': self.throat_gas_properties(mixture_ratio, expansion_ratio) elif location == 'exit': self.exit_gas_properties(mixture_ratio, expansion_ratio) else: raise ValueError( 'Invalid location, use "chamber," "throat" or "exit"') self.isp, self.cstar, _ = self.ispObj.getFrozen_IvacCstrTc( Pc=self.imperial_pressure, MR=mixture_ratio, eps=expansion_ratio) self.cstar = self.cstar * 0.3048 # coversion to m/s self.mole_fractions = self.ispObj.get_SpeciesMoleFractions( Pc=self.imperial_pressure, MR=mixture_ratio, eps=expansion_ratio, frozen=0, frozenAtThroat=0, min_fraction=5e-05) self.Cp = self.Cp * 4186.8 # coversion to J/gk/K self.mu = self.visc * 0.0001 # coversion to Pa*s self.k = self.cond * 418.4e-3 # coversion to W/m/K self.T_static = self.ispObj.get_Tcomb( Pc=self.imperial_pressure, MR=mixture_ratio) * 0.555556 # coversion to K
velChm = Mchm * sonicL[0] velTht = sonicL[1] print( 'velChm=%g ft/sec(%g m/s), velTht=%g ft/sec(%g m/s)'%(velChm, velChm*0.3048, velTht, velTht*0.3048 ) ) densityL = ispObj.get_Densities( Pc=Pc, MR=MR, eps=eps, frozen=frozen) densChm = densityL[0] densTht = densityL[1] print( 'densChm=%g lbm/cuft, densTht=%g lbm/cuft'%(densChm, densTht ) ) Dt = 2.0*Rt Dchm = Dt * fac_CR**0.5 print( 'Dchm=%g in(%g cm), Dt=%g in(%g cm)'%(Dchm, Dchm*2.54, Dt, Dt*2.54 ) ) Cpchm, viscchm, condchm, Prandtlchm = ispObj.get_Chamber_Transport( Pc=Pc, MR=MR, eps=eps, frozen=frozen) Cpt, visct, condt, Prandtlt = ispObj.get_Throat_Transport( Pc=Pc, MR=MR, eps=eps, frozen=frozen) print('Cpchm=%g, viscchm=%g, condchm=%g, Prandtlchm=%g'%(Cpchm, viscchm, condchm, Prandtlchm) ) print(' Cpt=%g, visct=%g, condt=%g, Prandtlt=%g'%(Cpt, visct, condt, Prandtlt) ) print('================') viscchm *= 0.067196898 / 1000 # convert from millipoise to lbm/s-ft visct *= 0.067196898 / 1000 ReyChm = densChm * velChm * Dchm / viscchm / 12.0 ReyTht = densTht * velTht * Dt / visct / 12.0 print( 'ReyChm=%g , ReyTht=%g '%(ReyChm, ReyTht ) )
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
WITH EQUILIBRIUM REACTIONS Cp, CAL/(G)(K) 2.0951 1.9171 0.7308 CONDUCTIVITY 4.1444 3.6272 0.5411 PRANDTL NUMBER 0.5352 0.5366 0.7123 WITH FROZEN REACTIONS Cp, CAL/(G)(K) 0.9029 0.8950 0.7302 CONDUCTIVITY 1.3519 1.2760 0.5398 PRANDTL NUMBER 0.7071 0.7121 0.7135 ====================================================""") cpEch, visEch, conEch, prEch = ispObj.get_Chamber_Transport(Pc=1000.0, MR=6.0, eps=40.0) cpFch, visFch, conFch, prFch = ispObj.get_Chamber_Transport(Pc=1000.0, MR=6.0, eps=40.0, frozen=1) cpEth, visEth, conEth, prEth = ispObj.get_Throat_Transport(Pc=1000.0, MR=6.0, eps=40.0) cpFth, visFth, conFth, prFth = ispObj.get_Throat_Transport(Pc=1000.0, MR=6.0, eps=40.0, frozen=1) cpEex, visEex, conEex, prEex = ispObj.get_Exit_Transport(Pc=1000.0,
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)