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