Esempio n. 1
0
 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
Esempio n. 2
0
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))
Esempio n. 3
0
    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
Esempio n. 4
0
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
Esempio n. 5
0
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()
Esempio n. 6
0
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
Esempio n. 7
0
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(['', '', '', ''])
Esempio n. 8
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)
Esempio n. 9
0
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)