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)
Exemple #2
0
    def calculate_combustion_parameters_at_chamber(self, phi):
        """ Uses RocketCEA, which wraps NASA CEA, to calculate 4 parameters at
        the combustion chamber:

            OF_ratio : Oxidizer/fuel mass ratio.
            k : exhaust gasses cp/cv = gamma.
            M : exhaust gasses moleculaer weight.
            To : adiabatic flame temperature.

        Parameters
        ----------
        phi : float
            Equivalence ratio: phi = (fuel-to-oxidizer ratio) /
            (fuel-to-oxidizer ratio)st.

        Returns
        -------
        OF_ratio : float
            Oxidizer/fuel mass ratio based on given phi.
        gamma : float
            Exhaust gasses cp/cv.
        molecular_weight : float
            Exhaust gasses moleculaer weight.
        flame_temperature : float
            Adiabatic flame temperature.
        """
        cea_analysis = CEA_Obj(
            oxName=self.oxidizer.name,
            fuelName=self.fuel.name,
            isp_units="sec",
            cstar_units="m/sec",
            pressure_units="bar",
            temperature_units="K",
            sonic_velocity_units="m/sec",
            enthalpy_units="kJ/kg",
            density_units="kg/m^3",
            specific_heat_units="kJ/kg-K",
            viscosity_units="millipoise",
            thermal_cond_units="W/cm-degC",
        )

        # Get OF ratio based on equivalence ratio
        OF_ratio = cea_analysis.getMRforER(ERphi=phi)

        # Calculate outputs
        area_ratio = cea_analysis.get_eps_at_PcOvPe(Pc=self.p_chamber,
                                                    MR=OF_ratio,
                                                    PcOvPe=self.p_chamber /
                                                    self.Pa)
        (
            Isp,
            cstar,
            flame_temperature,
            molecular_weight,
            gamma,
        ) = cea_analysis.get_IvacCstrTc_ChmMwGam(Pc=self.p_chamber,
                                                 MR=OF_ratio,
                                                 eps=area_ratio)

        return OF_ratio, gamma, molecular_weight, flame_temperature
Exemple #3
0
    def __init__(self):
        self.datapathname = './.lookup.npy'
        self.configpathname = './.lookupconfig.json'
        self.data = None
        self.config = None
        self.__loaded = False

        # This str provides molecular structure, wt% of fuel, heat of formation, and density information to underlying CEA code
        fuel_str = """
        fuel ABS(S) C 3.85 H 4.85 N 0.43 wt%=100.0
        h,kJ=62.63 t(k)=298.15 rho,kg=1224
        """

        add_new_fuel('ABS', fuel_str)
        self.cea = CEA_Obj(oxName='N2O',
                           fuelName='ABS',
                           cstar_units='m/s',
                           pressure_units='Pa',
                           temperature_units='K',
                           sonic_velocity_units='m/s',
                           enthalpy_units='J/kg',
                           density_units='kg/m^3',
                           specific_heat_units='J/kg-K',
                           viscosity_units='poise',
                           thermal_cond_units='W/cm-degC',
                           make_debug_prints=True)
 def test_use_Mpa_as_input_Pc(self):
     """test use Mpa as input Pc"""
     
     C = CEA_Obj( oxName='LOX', fuelName='LH2', fac_CR=None)
     CwU = CEA_Obj_w_units( oxName='LOX', fuelName='LH2', pressure_units='MPa', fac_CR=None)
     
     a = C.get_Isp(Pc=1000.0, MR=6.0, eps=40.0)
     b = CwU.get_Isp(Pc=1000.0/145.037738, MR=6.0, eps=40.0)
     self.assertAlmostEqual(a, b, delta=0.01)
Exemple #5
0
    def print_cea_output(self, subar=None, supar=None):
        """Prints NASA CEA output file."""
        cea_analysis = CEA_Obj(
            oxName=self.oxidizer.name,
            fuelName=self.fuel.name,
            isp_units="sec",
            cstar_units="m/sec",
            pressure_units="bar",
            temperature_units="K",
            sonic_velocity_units="m/sec",
            enthalpy_units="kJ/kg",
            density_units="kg/m^3",
            specific_heat_units="kJ/kg-K",
            viscosity_units="millipoise",
            thermal_cond_units="W/cm-degC",
        )

        cea_output = cea_analysis.cea_obj.get_full_cea_output(
            Pc=self.p_chamber,
            MR=self.OF_ratio,
            PcOvPe=self.p_chamber / self.Pa,
            subar=subar,
            eps=supar,
            show_transport=1,
            pc_units="bar",
            output="siunits",
            show_mass_frac=True,
            frozen=0,
            frozenAtThroat=1,
            #fac_CR=2,
        )
        print(cea_output)
Exemple #6
0
def rocket_vars(fu, ox, pcham):
    C = CEA_Obj(
        oxName=ox, fuelName=fu, isp_units='sec',
        cstar_units='m/s')  # define CEA object to operate on for rocketCEA
    OFratio = np.linspace(0.1, 5., 50, endpoint=True)  # OF ratio by mass
    ISP = np.zeros(OFratio.shape)  # isp
    Cstar = np.zeros(OFratio.shape)  # cstar efficiency
    PCPE = np.zeros(OFratio.shape)  # p_chamber / p_exit
    supAR = 1  # supersonic area ratio (1 = converging nozzle only)
    for i in range(50):
        ISP[i] = C.get_Isp(pcham, MR=OFratio[i], eps=supAR)  # ISP vacuum
        Cstar[i] = C.get_Cstar(pcham, MR=OFratio[i])  # Cstar efficiency
        PCPE[i] = C.get_Throat_PcOvPe(
            pcham, MR=OFratio[i]
        )  # throat Pc/Pe (we will be using a converging nozzle)

    return ISP, Cstar, PCPE
Exemple #7
0
def getCeaObj(fuelName, oxName):
    #print(type(fuelName),type(oxName))
    return CEA_Obj(oxName=oxName,
                   fuelName=fuelName,
                   pressure_units='Pa',
                   temperature_units='K',
                   density_units='kg/m^3',
                   sonic_velocity_units='m/s',
                   specific_heat_units='J/kg-K')
def OFtrade(fu, ox, P, N, OFratio,
            pltname):  # O/F ratio trade (OFratio needs to be a vector array)
    # fu: name of fuel (string, as defined in rocketcea documentation or newly added fuels)
    # ox: name of ox (string, as defined in rocketcea documentation of newly added fuels)
    # P: chamber pressure (either a single number, list of numbers, or range())
    # N: number of desired O/F ratios to sweep over
    # OFratio: values of O/F ratios (length of this list must match value of N)
    # supAR: fixed nozzle expansion ratio
    C = CEA_Obj(
        oxName=ox, fuelName=fu, isp_units='sec',
        cstar_units='m/s')  # define CEA object to operate on for rocketCEA
    if isinstance(P, int) == True:  # if P is only one value
        y = 1
    else:
        y = len(P)
    # preallocate vars
    ISP = np.zeros([y, OFratio.shape[0]])  # isp
    Cstar = np.zeros([y, OFratio.shape[0]])  # cstar eff
    PCPE = np.zeros([y, OFratio.shape[0]])  # pc/pe
    cpcv = np.zeros([y, OFratio.shape[0]
                     ])  # ratio of specific heats in thrust chamber
    fe_pcpe = np.zeros([y, OFratio.shape[0]
                        ])  # nozzle area ratio for fully expanded flow
    for x in range(y):
        if y == 1:
            Pc = P  # integers can't be called :(
            legends = str(Pc)
        else:
            Pc = P[x]  # chamber pressure
            legends = P
        pr = Pc / 14.7  # pc/pe for fully expanded flo
        for i in range(N):
            fe_pcpe[x, :] = C.get_eps_at_PcOvPe(Pc=Pc,
                                                MR=OFratio[i],
                                                PcOvPe=pr)
            ISP[x, i] = C.get_Isp(Pc=Pc, MR=OFratio[i],
                                  eps=fe_pcpe[x, i])  # ISP vacuum
            Cstar[x, i] = C.get_Cstar(Pc=Pc, MR=OFratio[i])  # Cstar efficiency
            fe_pcpe[x, i] = C.get_PcOvPe(Pc=Pc,
                                         MR=OFratio[i],
                                         eps=fe_pcpe[x, i])  # Pc/Pe
            cpcv[x, i] = C.get_Chamber_Cp(Pc=Pc,
                                          MR=OFratio[i],
                                          eps=fe_pcpe[x, i])  # cp/cv

    # generate plots for ISP, Cstar, and Pchamb/Pexit
    # plots(OFratio,ISP,"O/F ratio","ISP (s)",    pltname+"isp.png"   , legends     ) # isp plot
    # plots(OFratio,Cstar,"O/F ratio","Cstar",    pltname+"cstar.png" , legends     ) # Cstar plot
    # plots(OFratio,PCPE,"O/F ratio","Pc/Pe",     pltname+"pcpe.png"  , legends     ) # Pc/Pe plot
    return ISP, Cstar, fe_pcpe, cpcv
def ARtrade(fu, ox, P, N, OFratio, supAR, pltname):  # expansion ratio trade
    # fu: name of fuel (string, as defined in rocketcea documentation or newly added fuels)
    # ox: name of ox (string, as defined in rocketcea documentation of newly added fuels)
    # P: chamber pressure (either a single number, list of numbers, or range())
    # N: number of desired supersonic area ratios (nozzle expansion ratio) to sweep over
    # OFratio: fixed O/F ratio for this trade
    # supAR: values of supersonic area ratios (length of this list must match value of N)
    C = CEA_Obj(
        oxName=ox, fuelName=fu, isp_units='sec',
        cstar_units='m/s')  # define CEA object to operate on for rocketCEA
    if isinstance(P, int) == True:  # if P is only one value
        y = 1
    else:
        y = len(P)
    # preallocate vars
    ISP = np.zeros([y, supAR.shape[0]])  # isp
    Cstar = np.zeros([y, supAR.shape[0]])  # cstar eff
    PCPE = np.zeros([y, supAR.shape[0]])  # pc/pe
    cpcv = np.zeros([y, supAR.shape[0]
                     ])  # ratio of specific heats in thrust chamber
    for x in range(y):
        if y == 1:
            Pc = P  # integers can't be called :(
            legends = str(Pc)
        else:
            Pc = P[x]  # chamber pressure
            legends = P
        for i in range(N):
            ISP[x, i] = C.get_Isp(Pc=Pc, MR=OFratio,
                                  eps=supAR[i])  # ISP vacuum
            Cstar[x, i] = C.get_Cstar(Pc=Pc, MR=OFratio)  # Cstar efficiency
            PCPE[x, i] = C.get_PcOvPe(Pc=Pc, MR=OFratio, eps=supAR[i])  # Pc/Pe
            cpcv[x, i] = C.get_Chamber_Cp(Pc=Pc, MR=OFratio,
                                          eps=supAR[i])  # cp/cv

    # generate plots for ISP, Cstar, and Pchamb/Pexit. Replace the last input with the vectory array of pressures
    # plots(supAR,ISP,"Ae/At","ISP (s)",  pltname+"isp.png"   , legends     ) # isp plot
    # plots(supAR,Cstar,"Ae/At","Cstar",  pltname+"cstar.png" , legends     ) # Cstar plot
    # plots(supAR,PCPE,"Ae/At","Pc/Pe",   pltname+"pcpe.png"  , legends     ) # Pc/Pe plot
    return ISP, Cstar, PCPE, cpcv
  def getPerformanceParameters(self, combustionPressure, ambientPressure, oxidizerTemperature, expansionRatio, mixtureRatio):
    import CoolProp.CoolProp as CP
    from rocketcea.cea_obj import CEA_Obj, add_new_fuel, add_new_oxidizer, add_new_propellant
    from rocketcea.cea_obj_w_units import CEA_Obj as CEA_Obj_W_Units
    from rocketcea.blends import makeCardForNewTemperature

    combustionPressure = max(10, combustionPressure) # Limitation of the library...
    fuelTemperature = 293

    HMOLAR = CP.PropsSI('HMOLAR','T',oxidizerTemperature,'P',combustionPressure,"N2O") / 1e3
    oxidizerDensity = CP.PropsSI('D','T',oxidizerTemperature,'P',combustionPressure,"N2O")
    RHO = oxidizerDensity * 1e3 / (1e2 * 1e2 * 1e2)

    oxid_card_str = """
    oxid=NITROUS wt=1.0 t,K={:.2f} h,kj/mol={:.2f} rho,g/cc={:.2f} N 2 O 1
    """.format(oxidizerTemperature, HMOLAR, RHO)
    fuel_card_str = """
    fuel=C(gr) wt={:.4f} t,K={:.2f}
    fuel=SASOL907 wt={:.4f} t,K={:.2f} h,kj/mol={:.2f} rho,g/cc={:.3f} C 50 H 102
    """.format(
      assumptions.carbonBlackFraction.get(), 
      fuelTemperature, 
      1 - assumptions.carbonBlackFraction.get(),
      fuelTemperature, 
      assumptions.fuelEnthalpyOfFormation.get(), 
      assumptions.fuelDensityLiquid.get() / 1e3)

    problemString = "Pc={:.2f},Pa={:.2f},To={:.2f},Tf={:.2f},ER={:.2f},MR={:.2f},oxid={:},fuel={:}".format(
      combustionPressure,
      ambientPressure,
      oxidizerTemperature,
      fuelTemperature,
      expansionRatio,
      mixtureRatio,
      oxid_card_str,
      fuel_card_str
    )
    strHash = hashlib.md5(problemString.encode()).hexdigest()
    NasaCEA.totalHits = NasaCEA.totalHits + 1
    if options.enableCeaLookup and strHash in NasaCEA.inMemoryCache:
      # print("Hit cache")
      NasaCEA.cacheHits = NasaCEA.cacheHits + 1
      return NasaCEA.inMemoryCache[strHash]
    

    # print(HMOLAR, RHO)

    add_new_oxidizer('NITROUS_COOLPROP', oxid_card_str)
    add_new_fuel('SASOLWAX907_CARBONBLACK', fuel_card_str)

    with hiddenPrints:
      combustionPressure = round(combustionPressure, 2)
      mixtureRatio = round(mixtureRatio, 2)
      expansionRatio = round(expansionRatio, 2)
      ambientPressure = round(ambientPressure, 2)

      cea = CEA_Obj_W_Units(
        oxName="NITROUS_COOLPROP", 
        fuelName="SASOLWAX907_CARBONBLACK", 
        pressure_units='Pa', 
        cstar_units='m/s', 
        temperature_units='K', 
        sonic_velocity_units='m/s', 
        enthalpy_units='J/kg', 
        density_units='kg/m^3', 
        specific_heat_units='J/kg-K', 
        viscosity_units='poise', 
        thermal_cond_units="W/cm-degC"
      )
      Isp,mode = cea.estimate_Ambient_Isp(Pc=combustionPressure, MR=mixtureRatio, eps=expansionRatio, Pamb=ambientPressure)
      IspVac, Cstar, Tc, MW, gamma = cea.get_IvacCstrTc_ThtMwGam(Pc=combustionPressure, MR=mixtureRatio, eps=expansionRatio)
      Cp = cea.get_Chamber_Cp(Pc=combustionPressure, MR=mixtureRatio, eps=expansionRatio)
      rho = cea.get_Chamber_Density(Pc=combustionPressure, MR=mixtureRatio, eps=expansionRatio)
      CfVac, Cf, mode = cea.get_PambCf(Pc=combustionPressure, MR=mixtureRatio, eps=expansionRatio)
      PcOvPe = cea.get_PcOvPe(Pc=combustionPressure, MR=mixtureRatio, eps=expansionRatio)
      exitPressure = combustionPressure / PcOvPe

      result = (Isp, Cp, MW, Cstar, Tc, gamma, rho, Cf, exitPressure, oxidizerDensity)
      if options.enableCeaLookup:
        NasaCEA.inMemoryCache[strHash] = result
      return result
Exemple #11
0
    def optimize_combustion_parameters_at_chamber(self):
        """ Uses RocketCEA, which wraps NASA CEA, to calculate 4 parameters at
        the combustion chamber:

            OF_ratio : Oxidizer/fuel mass ratio.
            k : exhaust gasses cp/cv = gamma.
            M : exhaust gasses moleculaer weight.
            To : adiabatic flame temperature.

        OF_ratio is calculated by optimizing the specific impulse of the motor.

        Returns
        -------
        optimal_OF_ratio : float
            Optimized oxidizer/fuel mass ratio generating optimum specific
            impulse.
        gamma : float
            Exhaust gasses cp/cv.
        molecular_weight : float
            Exhaust gasses moleculaer weight.
        flame_temperature : float
            Adiabatic flame temperature.
        """
        # ---------------Calculated Inputs----------------#
        # Calculate input parameters from oxidiser and fuel combustion
        # Initialize CEA analysis
        cea_analysis = CEA_Obj(
            oxName=self.oxidizer.name,
            fuelName=self.fuel.name,
            # Units
            isp_units="sec",
            cstar_units="m/sec",
            pressure_units="bar",
            temperature_units="K",
            sonic_velocity_units="m/sec",
            enthalpy_units="kJ/kg",
            density_units="kg/m^3",
            specific_heat_units="kJ/kg-K",
            viscosity_units="millipoise",
            thermal_cond_units="W/cm-degC",
        )

        # Get stoichiometric equivalence ratio
        stoichiometric_OF_ratio = cea_analysis.getMRforER(ERphi=1.0)

        # Find optimal specific impulse
        def minus_specific_impulse_function(OF_ratio):
            area_ratio = cea_analysis.get_eps_at_PcOvPe(Pc=self.p_chamber,
                                                        MR=OF_ratio,
                                                        PcOvPe=self.p_chamber /
                                                        self.Pa)
            Isp, cstar, To, M, k = cea_analysis.get_IvacCstrTc_ChmMwGam(
                Pc=self.p_chamber, MR=OF_ratio, eps=area_ratio)
            return -Isp

        res = minimize(
            fun=minus_specific_impulse_function,
            x0=stoichiometric_OF_ratio,
            method="Powell",
            bounds=[[
                stoichiometric_OF_ratio * 0.5, stoichiometric_OF_ratio * 2
            ]],
        )

        # Optimization sequence complete, store results
        optimal_OF_ratio = res.x[0]
        optimal_area_ratio = cea_analysis.get_eps_at_PcOvPe(
            Pc=self.p_chamber,
            MR=optimal_OF_ratio,
            PcOvPe=self.p_chamber / self.Pa)
        (
            optimal_Isp,
            cstar,
            flame_temperature,
            molecular_weight,
            gamma,
        ) = cea_analysis.get_IvacCstrTc_ChmMwGam(Pc=self.p_chamber,
                                                 MR=optimal_OF_ratio,
                                                 eps=optimal_area_ratio)

        return optimal_OF_ratio, gamma, molecular_weight, flame_temperature
    def getPerformanceParameters(self, combustionPressure, ambientPressure,
                                 oxidizerTemperature, expansionRatio,
                                 mixtureRatio):
        CpAve = CP.PropsSI('CP0MOLAR', 'T', oxidizerTemperature, 'P',
                           combustionPressure, "N2O")
        MolWt = CP.PropsSI('M', 'T', oxidizerTemperature, 'P',
                           combustionPressure, "N2O") * 1e3
        HMOLAR = CP.PropsSI('HMOLAR', 'T', oxidizerTemperature, 'P',
                            combustionPressure, "N2O") / 1e3
        RHO = CP.PropsSI('D', 'T', oxidizerTemperature, 'P',
                         combustionPressure, "N2O") * 1e3 / (1e2 * 1e2 * 1e2)

        # print(HMOLAR, RHO)

        card_str = """
    oxid=NITROUS wt=1.0 t,K={:.4f} h,kj/mol={:.4f} rho,g/cc={:.4f} N 2 O 1
    """.format(oxidizerTemperature, HMOLAR, RHO)
        add_new_oxidizer('NITROUS_COOLPROP',
                         card_str.format(oxidizerTemperature))

        fuelTemperature = 293
        card_str = """
    fuel=C(gr) wt=0.02 t,K={:.4f}
    fuel=SASOL907 wt=0.98 t,K={:.4f} h,kj/mol=-1438.200 rho,g/cc=0.720 C 50 H 102
    """.format(fuelTemperature, fuelTemperature)
        add_new_fuel('SASOLWAX907_CARBONBLACK', card_str)

        #    cea = CEA_Obj(
        #      oxName="NITROUS_COOLPROP",
        #      fuelName="SASOLWAX907_CARBONBLACK"
        #    )
        #    s = cea.get_full_cea_output(Pc=combustionPressure/1e5, MR=mixtureRatio, eps=expansionRatio, pc_units="bar", output='siunits')
        #    print(s)
        #
        #    pass

        with hiddenPrints:
            cea = CEA_Obj_W_Units(oxName="NITROUS_COOLPROP",
                                  fuelName="SASOLWAX907_CARBONBLACK",
                                  pressure_units='Pa',
                                  cstar_units='m/s',
                                  temperature_units='K',
                                  sonic_velocity_units='m/s',
                                  enthalpy_units='J/kg',
                                  density_units='kg/m^3',
                                  specific_heat_units='J/kg-K',
                                  viscosity_units='poise',
                                  thermal_cond_units="W/cm-degC")
            Isp, mode = cea.estimate_Ambient_Isp(Pc=combustionPressure,
                                                 MR=mixtureRatio,
                                                 eps=expansionRatio,
                                                 Pamb=ambientPressure)
            IspVac, Cstar, Tc, MW, gamma = cea.get_IvacCstrTc_ChmMwGam(
                Pc=combustionPressure, MR=mixtureRatio, eps=expansionRatio)

            # cea = CEA_Obj(
            #   oxName=oxidizerCard,
            #   fuelName="SASOLWAX907_CARBONBLACK"
            # )
            # s = cea.get_full_cea_output(Pc=combustionPressure/1e5, MR=mixtureRatio, eps=expansionRatio, pc_units="bar", output='siunits')
            # print(s)
            return Isp, CpAve, MolWt, Cstar, Tc, gamma

# globals
FORMAT    = 'png'
PSI_TO_PA = 6894.7572931783
M_TO_IN   = 39.3701
G0        = 9.81
# define PMMA
card_str = '''
fuel PMMA C 5 H 8 O 2
h,kj=-430.5 t(k)=299.82
''' # Greg Zilliac's recommendation for modeling PMMA
add_new_fuel('PMMA', card_str) # rocketCEA function to add PMMA to possible inputs
CEA_object = CEA_Obj(oxName='GOX', fuelName='PMMA',
    isp_units='sec',
    cstar_units='m/s',
    sonic_velocity_units='m/s',
    temperature_units='k')


def get_initial_guess(config):
    Pc_0     = config.getfloat('Params', 'initial_pc') * PSI_TO_PA
    P0       = config.getfloat('Params', 'p0')
    OF_0     = config.getfloat('Params', 'initial_of')
    AR       = config.getfloat('Params', 'area_ratio')
    rho_fuel = config.getfloat('Params', 'rho_fuel')
    a        = config.getfloat('Params', 'a')
    n        = config.getfloat('Params', 'n')
    L        = config.getfloat('Params', 'fuel_length') / M_TO_IN
    Rt       = config.getfloat('Params', 'throat_radius')
    throat_area = np.pi * Rt**2
Exemple #14
0
from rocketcea.cea_obj_w_units import CEA_Obj
from pylab import *

Pc = 500.0

P90 = CEA_Obj(
    propName='Peroxide90',
    pressure_units='psia',
    temperature_units='degK',
)

epsL = []
TceqL = []
TcfrzL = []
for ieps in range(5, 21):

    TcEq = P90.get_Temperatures(Pc=Pc, eps=float(ieps))[2]

    TcFrz = P90.get_Temperatures(Pc=Pc,
                                 eps=float(ieps),
                                 frozen=1,
                                 frozenAtThroat=0)[2]

    epsL.append(float(ieps))
    TceqL.append(TcEq)
    TcfrzL.append(TcFrz)

plot(epsL, TceqL, label='Equilibrium')
plot(epsL, TcfrzL, label='Frozen')

legend(loc='best')
Exemple #15
0
class HybridCEALookup():
    """
        Class to generate and manage N2O-ABS Hybrid engine CEA data for Pc and o/f ratios
    """
    __depth = 10

    def __init__(self):
        self.datapathname = './.lookup.npy'
        self.configpathname = './.lookupconfig.json'
        self.data = None
        self.config = None
        self.__loaded = False

        # This str provides molecular structure, wt% of fuel, heat of formation, and density information to underlying CEA code
        fuel_str = """
        fuel ABS(S) C 3.85 H 4.85 N 0.43 wt%=100.0
        h,kJ=62.63 t(k)=298.15 rho,kg=1224
        """

        add_new_fuel('ABS', fuel_str)
        self.cea = CEA_Obj(oxName='N2O',
                           fuelName='ABS',
                           cstar_units='m/s',
                           pressure_units='Pa',
                           temperature_units='K',
                           sonic_velocity_units='m/s',
                           enthalpy_units='J/kg',
                           density_units='kg/m^3',
                           specific_heat_units='J/kg-K',
                           viscosity_units='poise',
                           thermal_cond_units='W/cm-degC',
                           make_debug_prints=True)

    def generate(self,
                 pcmin=1,
                 pcmax=1000,
                 ofmin=1,
                 ofmax=40,
                 pcint=1,
                 ofint=1):
        """
            Generate NxMx8 array of chamber thermodynamic and transport properties from min to max (inclusive).\n
            Use CEA to produce the following data at each pc + ofratio combination (8 values)\n
            pc      :   chamber pressure (Pa)\n
            of      :   mixture ratio\n
            Tc      :   chamber temperature (K)\n
            k       :   specific heat ratio\n
            MW      :   molecular weight (g / mol)\n
            Pr      :   Prandtl number\n
            Cp      :   specific heat capacity (J/kg-K)\n
            mu      :   viscocity (poise)\n
            cstar   :   characteristic velocity (m/s)\n
            isp     :   isp (s)
        """

        print('Using N2O, ABS, with SI units')

        if not self.uses(pcmin=pcmin,
                         pcmax=pcmax,
                         pcint=pcint,
                         ofmin=ofmin,
                         ofmax=ofmax,
                         ofint=ofint):
            try:
                # Construct NxMx8 numpy array to hold all data
                xdim, ydim = self.__getDim(pcmin, pcmax, pcint, ofmin, ofmax,
                                           ofint)
                data = np.zeros(shape=(xdim, ydim, HybridCEALookup.__depth),
                                dtype=float)

                print(
                    f'Generating lookup table, {xdim}x{ydim}x{HybridCEALookup.__depth}'
                )

                # Enumerate over pressure and ofratio ranges and compute CEA results
                for (pc_i, pc) in enumerate(np.linspace(pcmin, pcmax, xdim)):
                    for (of_i,
                         of) in enumerate(np.linspace(ofmin, ofmax, ydim)):
                        (cp, mu, _,
                         pr) = self.cea.get_Chamber_Transport(pc, of)
                        (mw, k) = self.cea.get_Chamber_MolWt_gamma(pc, of)
                        (isp, cstar, tc) = self.cea.get_IvacCstrTc(pc, of)
                        data[pc_i, of_i, :] = np.array(
                            [pc, of, tc, k, mw, pr, cp, mu, cstar, isp],
                            dtype=float)

                # assign data to obj and save to cache
                self.data = data
                try:
                    config = {
                        "pcmin": pcmin,
                        "pcmax": pcmax,
                        "pcint": pcint,
                        "ofmin": ofmin,
                        "ofmax": ofmax,
                        "ofint": ofint,
                        "pcnum": xdim,
                        "ofnum": ydim,
                        "depth": HybridCEALookup.__depth
                    }
                    self.config = config
                    with open(os.path.abspath(self.datapathname), 'wb') as f:
                        np.save(f, data, allow_pickle=True)
                    with open(os.path.abspath(self.configpathname), 'w') as f:
                        json.dump(config, f)
                    print(
                        f'Lookup table cached, pcrange: {pcmin}-{pcmax}, ofrange: {ofmin}-{ofmax}'
                    )
                except IOError as ioerror:
                    print(ioerror)
                    print("uh oh")
            except Exception as exception:
                raise exception
        else:
            print(
                f'Using lookup table from cached:\npcrange: {pcmin}-{pcmax}\nofrange: {ofmin}-{ofmax}'
            )

    def open(self):
        """
            Open cached lookup table
        """
        try:
            with open(os.path.abspath(self.datapathname), 'rb') as f:
                self.data = np.load(f, allow_pickle=True)
            with open(os.path.abspath(self.configpathname), 'r') as f:
                self.config = json.load(f)
            self.__loaded = True
            return True
        except Exception:
            # Catch all and return false
            return False

    def flushCache(self):
        """
        """
        try:
            with open(os.path.abspath(self.datapathname), 'wb') as f:
                np.save(f, [])
            with open(os.path.abspath(self.configpathname), 'w') as f:
                json.dump({}, f)
        except Exception as exception:
            print(exception)

    def get(self, pc, of):
        """
            Retrieve CEA outputs at any chamber pressure
        """
        if pc < self.config["pcmin"] or pc > self.config["pcmax"]:
            print(
                f'Pc: {pc}, Pcmin: {self.config["pcmin"]}, Pcmax: {self.config["pcmax"]}'
            )
            raise Exception("Chamber pressure out of bounds")
        elif of < self.config["ofmin"] or of > self.config["ofmax"]:
            print(
                f'OF: {of}, OFmin: {self.config["ofmin"]}, OFmax: {self.config["ofmax"]}'
            )
            raise Exception("OF ratio out of bounds")

        # Convert to chamber pressure and OF ratio floating point index
        pc_i = (pc - self.config["pcmin"]) / (self.config["pcmax"] -
                                              self.config["pcmin"]) * (
                                                  self.config["pcnum"] - 1)
        of_i = (of - self.config["ofmin"]) / (self.config["ofmax"] -
                                              self.config["ofmin"]) * (
                                                  self.config["ofnum"] - 1)

        # Get chamber pressure lower and upper bounds (1d arr)
        pc_li = floor(pc_i)
        pc_hi = ceil(pc_i)

        # OF ratio lower and upper bounds (1d arr)
        of_li = floor(of_i)
        of_hi = ceil(of_i)

        # Get distance of chamber pressure and OF ratio from closest lower index
        pc_x = (pc_i - pc_li)  # / self.config["pcint"]
        of_x = (of_i - of_li)  # / self.config["ofint"]

        # Interpolate between pressure data
        pc_lerp_of_l = self.data[pc_li, of_li, :] + pc_x * (
            self.data[pc_hi, of_li, :] - self.data[pc_li, of_li, :])
        pc_lerp_of_h = self.data[pc_li, of_hi, :] + pc_x * (
            self.data[pc_hi, of_hi, :] - self.data[pc_li, of_hi, :])

        # Interpolate between OF ratio data and return result
        return pc_lerp_of_l + of_x * (pc_lerp_of_h - pc_lerp_of_l)

    def getPc(self, pc):
        """
            Return a row vector of OF Ratio results at a provided chamber pressure
        """
        if pc < self.config["pcmin"] or pc > self.config["pcmax"]:
            raise Exception("Chamber pressure out of bounds")

        pc_i = (pc - self.config["pcmin"]) / (self.config["pcmax"] -
                                              self.config["pcmin"]) * (
                                                  self.config["pcnum"] - 1)

        # Get chamber pressure lower and upper bounds (1d arr)
        pc_li = floor(pc_i)
        pc_hi = ceil(pc_i)
        pc_x = (pc_i - pc_li)  # / self.config["pcint"]

        return self.data[pc_li, :, :] + pc_x * (self.data[pc_hi, :, :] -
                                                self.data[pc_li, :, :])

    def uses(self, pcmin=200, pcmax=800, pcint=10, ofmin=1, ofmax=30, ofint=1):
        """
            Check the cached lookup table configuration against specified options\n
        """
        if self.__loaded:
            xdim, ydim = self.__getDim(pcmin, pcmax, pcint, ofmin, ofmax,
                                       ofint)
            useConfig = {
                "pcmin": pcmin,
                "pcmax": pcmax,
                "pcint": pcint,
                "ofmin": ofmin,
                "ofmax": ofmax,
                "ofint": ofint,
                "pcnum": xdim,
                "ofnum": ydim,
                "depth": HybridCEALookup.__depth
            }
            return useConfig == self.config
        return False

    def getConfig(self):
        """
            Get current lookup table configuration
        """
        if self.__loaded:
            return self.config
        else:
            return None

    def __getDim(self, pcmin, pcmax, pcint, ofmin, ofmax, ofint):
        xdim = ceil((pcmax - pcmin) / pcint) + 1
        ydim = ceil((ofmax - ofmin) / ofint) + 1
        return xdim, ydim
        p1 = round((p / 20) * 19, 1)
        p2 = round((p / 20), 1)
        WT0 = j
        WT1 = k
        WT2 = p1
        WT3 = p2

        # same name runs affoul of memoized cache.
        prop_name = "Propellant"  # "prop_{0}_{1}_{2}_{3}".format(WT0, WT1, WT2, WT3)

        card_str = """
        name pbt C 37.33 H 66.73 N 24.89 O 8.48 wt%={0}
        h,cal= 36728.486 t(k)=298.15 rho=1.3
        name a3 C 2.4 H 4.1 O 3.1 N 1.3 wt%={1}
        h,cal= -46358.545 t(k)=298.15 rho=1.38
        name an N 1.0 H 4.0 N 1.0 O 3.0 wt%={2}
        h,cal= -87332.284 t(k)=298.15 rho=1.725
        name kn K 1.0 N 1.0 O 3.0 wt%={3}
        h,cal= -118167.824 t(k)=298.15 rho=2.109
        """.format(WT0, WT1, WT2, WT3)
        add_new_propellant(prop_name, card_str)

        C = CEA_Obj(propName=prop_name,
                    pressure_units='bar',
                    cstar_units='m/s',
                    temperature_units='K',
                    isp_units='N-s/kg')
        tem = C.get_Tcomb(Pc=200)

        print(prop_name, tem)
from rocketcea.cea_obj_w_units import CEA_Obj
from pylab import *

Pc = 1000.0 / 145.037738  # convert to MPa
eps = 100.0
mrMin = 3.0
mrStep = 0.05
mrMax = 8.0

oxName = 'LOX'
fuelName = 'LH2'

ispObj = CEA_Obj(propName='',
                 oxName=oxName,
                 fuelName=fuelName,
                 pressure_units='MPa',
                 isp_units='km/s')

ispArr = []
MR = mrMin
mrArr = []
while MR < mrMax:
    ispArr.append(ispObj(Pc, MR, eps))
    mrArr.append(MR)
    MR += mrStep
plot(mrArr, ispArr, label='%s/%s' % (oxName, fuelName), linewidth=2)

legend(loc='best')
grid(True)
title('%s Performance at Eps=%g, Pc=%g %s' %
      (ispObj.desc, eps, Pc, ispObj.isp_units))
from rocketcea.cea_obj_w_units import CEA_Obj, CEA_Obj_default
from rocketcea.cea_obj import get_rocketcea_data_dir, set_rocketcea_data_dir

test_dir = r'D:\temp\cea w spaces'
print('ROCKETCEA_DATA_DIR =', get_rocketcea_data_dir())

set_rocketcea_data_dir(test_dir)

print('ROCKETCEA_DATA_DIR =', get_rocketcea_data_dir())

# compare 200 psia (13.7895 bar) results

C = CEA_Obj(oxName='LOX',
            fuelName='LH2',
            pressure_units='bar',
            cstar_units='m/s',
            temperature_units='K',
            isp_units='N-s/kg')
IspVac, Cstar, Tcomb = C.get_IvacCstrTc(Pc=13.7895,
                                        MR=1.0,
                                        eps=40.0,
                                        frozen=0,
                                        frozenAtThroat=0)
print('IspVac=%g, Cstar=%g, Tcomb=%g' % (IspVac, Cstar, Tcomb))
print('  .... converted to English ....')
print('IspVac=%g, Cstar=%g, Tcomb=%g' %
      (IspVac * 0.101972, Cstar * 3.28084, Tcomb * 1.8))

Cd = CEA_Obj_default(oxName='LOX', fuelName='LH2')
IspVac, Cstar, Tcomb = Cd.get_IvacCstrTc(Pc=200.0,
                                         MR=1.0,