Beispiel #1
0
def setstate(multiindex):
    T,P,X=gas.TPX
    if(args.adiabatic == 1):
        try:
            gas.UVX=refenergy/refmass,refvol/refmass,multiindex
            quant=ct.Quantity(gas, moles=np.sum(multiindex)/ct.avogadro)
            if(quant.T > args.Tmin):
                T=quant.T
                P=quant.P
            else:
                gas.TPX=T,P,X
                return 0,0
        except:
            gas.TPX=T,P,X
            return 0,0
    elif(args.adiabatic == 2):
        try:
            gas.HPX=(refenth+np.dot(multiindex-refmultiindex,refpotentials)/(1000*ct.avogadro))/refmass,args.pressure*ct.one_atm,multiindex
            quant=ct.Quantity(gas, moles=np.sum(multiindex)/ct.avogadro)
            if(quant.T > args.Tmin):
                T=quant.T
                P=quant.P
            else:
                gas.TPX=T,P,X
                return 0,0
        except:
            gas.TPX=T,P,X
            return 0,0
    return T,P/ct.one_atm
Beispiel #2
0
    def test_incompatible(self):
        gas2 = ct.Solution('h2o2.xml')
        q1 = ct.Quantity(self.gas)
        q2 = ct.Quantity(gas2)

        with self.assertRaises(ValueError):
            q1 + q2
Beispiel #3
0
    def test_add(self):
        q1 = ct.Quantity(self.gas, mass=5)
        q2 = ct.Quantity(self.gas, mass=5)
        q2.TPX = 500, 101325, 'CH4:1.0'

        q3 = q1 + q2
        self.assertNear(q1.mass + q2.mass, q3.mass)
        # addition is at constant UV
        self.assertNear(q1.U + q2.U, q3.U)
        self.assertNear(q1.V + q2.V, q3.V)
        self.assertArrayNear(q1.X * q1.moles + q2.X * q2.moles,
                             q3.X * q3.moles)
Beispiel #4
0
 def test_multiply(self):
     q1 = ct.Quantity(self.gas, mass=5)
     q2 = q1 * 2.5
     self.assertNear(q1.mass * 2.5, q2.mass)
     self.assertNear(q1.moles * 2.5, q2.moles)
     self.assertNear(q1.entropy * 2.5, q2.entropy)
     self.assertArrayNear(q1.X, q2.X)
Beispiel #5
0
    def test_equilibrate(self):
        self.gas.TPX = 300, 101325, 'CH4:1.0, O2:0.2, N2:1.0'
        q1 = ct.Quantity(self.gas)
        self.gas.equilibrate('HP')
        T2 = self.gas.T

        self.assertNear(q1.T, 300)
        q1.equilibrate('HP')
        self.assertNear(q1.T, T2)
Beispiel #6
0
def premix(phi=0.4, fuel={'CH4': 1}, ox={'N2': 0.79, 'O2': 0.21}, mech='gri30.xml', P=25*101325, T_fuel=300, T_ox=650, M_total=1):

    """Function that premixes air and fuel at a prescribed equivalence ratio, phi

    Keyword Arguments:
        phi {float} -- [Equivalence ratio at which fuel and oxidizer are mixed] (default: {0.4})
        fuel {dict} -- [Dictionary containing the fuel composition] (default: {{'CH4':1}})
        ox {dict} -- [Dictionary containing air composition] (default: {{'N2':0.79, 'O2':0.21}})
        mech {str} -- [String that contains the mechanism file. Don't change unless absolutely necessary!] (default: {'gri30.xml'})
        P {float} -- [Pressure in Pa] (default: {25*101325})
        T_fuel {int} -- [Preheat temperature of the fuel in Kelvin] (default: {300})
        T_ox {int} -- [Preheat temperature of the oxidizer in Kelvin. Normally this is the temperature of the air coming in from the compressor] (default: {650})
        M_total {int} -- [Total mass; arbitrarily set to 1] (default: {1})

    Returns:
        [type] -- [description]
    """
    airGas = ct.Solution(mech)
    airGas.TPX = [T_ox, P, ox]
    fuelGas = ct.Solution(mech)
    fuelGas.TPX = T_fuel, P, fuel

    # Temporary ThermoPhase object to get mass flow rates:
    temp = ct.Solution('gri30.xml')
    temp.set_equivalence_ratio(phi, fuel, ox)

    # Find the fuel and oxidizer mass flow rates for the given equivalence ratio:
    # here, temp[fuel.keys()].Y returns an array containing the mass fraction of all fuel species:
    mdot_fuel = M_total * sum(temp[fuel.keys()].Y)
    mdot_ox = M_total * sum(temp[ox.keys()].Y)

    fuel = ct.Quantity(fuelGas)
    fuel.mass = mdot_fuel

    air = ct.Quantity(airGas)
    air.mass = mdot_ox

    fuel.constant = air.constant = 'HP'  # keep enthalpy and pressure constant

    fuel_air_mixture = fuel + air  # mix at constant HP

    # Output mixer gas:
    return fuel_air_mixture.phase
Beispiel #7
0
    def test_mass_moles(self):
        q1 = ct.Quantity(self.gas, mass=5)
        self.assertNear(q1.mass, 5)
        self.assertNear(q1.moles, 5 / q1.mean_molecular_weight)

        q1.mass = 7
        self.assertNear(q1.moles, 7 / q1.mean_molecular_weight)

        q1.moles = 9
        self.assertNear(q1.moles, 9)
        self.assertNear(q1.mass, 9 * q1.mean_molecular_weight)
Beispiel #8
0
def equil(phi, T_air = 650, T_fuel = 300, P = 25*ct.one_atm, mech="gri30.xml"): 
    gas = ct.Solution(mech)  
    fs_CH4 = 0.058387057492574147288255659304923028685152530670166015625

    fuelGas = ct.Solution('gri30.xml')
    fuelGas.TPX = T_fuel, P, {'CH4':1}
    fuel = ct.Quantity(fuelGas)
    fuel.mass = phi*fs_CH4

    airGas = ct.Solution('gri30.xml')
    airGas.TPX = T_air, P, {'N2':0.79, 'O2':0.21}
    air = ct.Quantity(airGas)
    air.mass = 1

    fuel.constant = air.constant = 'HP'  # keep enthalpy and pressure constant
    mixture = fuel + air  # mix at constant HP
    mixture = mixture.phase

    mixture.equilibrate('HP');  
    CO_ppmvd = correctNOx(mixture['CO'].X, mixture['H2O'].X, mixture['O2'].X) 
    NO_ppmvd = correctNOx(mixture['NO'].X, mixture['H2O'].X, mixture['O2'].X) 
    return np.hstack([mixture.T, CO_ppmvd, NO_ppmvd]) 
Beispiel #9
0
    def test_extensive(self):
        q1 = ct.Quantity(self.gas, mass=5)
        self.assertNear(q1.mass, 5)

        self.assertNear(q1.volume * q1.density, q1.mass)
        self.assertNear(q1.V * q1.density, q1.mass)
        self.assertNear(q1.int_energy, q1.moles * q1.int_energy_mole)
        self.assertNear(q1.enthalpy, q1.moles * q1.enthalpy_mole)
        self.assertNear(q1.entropy, q1.moles * q1.entropy_mole)
        self.assertNear(q1.gibbs, q1.moles * q1.gibbs_mole)
        self.assertNear(q1.int_energy, q1.U)
        self.assertNear(q1.enthalpy, q1.H)
        self.assertNear(q1.entropy, q1.S)
        self.assertNear(q1.gibbs, q1.G)
def get_reaction(data):
  rr = np.zeros((data.shape[0],54))
  for i in range(0,data.shape[0]):
    comp = dict(zip(specs,data[i,0:53]))
    gas.TPY = data[i,53],6079500,comp
    q1 = ct.Quantity(gas)
    rr[i,:]=q1.net_production_rates
  specs_cantera=gas.species_names
  specs_cantera.remove('AR')
  rr = np.delete(rr,1,1)
  map_spec=[]
  for i in range(0,53):
     for j in range(0,53):
         if(specs[i]==specs_cantera[j]):
             map_spec.append(j)
  rr = rr[:,map_spec]
  return rr    
Beispiel #11
0
    def stream(self, properties=None, values=None, stp_air=False):
        """Build a mixture of species with certain properties

        Parameters
        ----------
        properties : str
            a string of keys used in building a cantera Quantity (e.g., 'TPX' or 'TP' or 'X', etc.)
        values : tuple
            the values of the properties
        stp_air : bool
            special option to make a stream of air at standard temperature and pressure (default: False)
            This produces a stream of 3.74 mol N2 per mole O2 at 300 K and one atmosphere
        Returns
        -------
        mix : cantera.Quantity
            a cantera Quantity object with the specified properties

        """
        q = ct.Quantity(self._cantera_wrapper.solution)
        if stp_air:
            if properties is not None or values is not None:
                print(
                    'Warning in building a stream of air at standard conditions!'
                    'The properties and values arguments will be ignored because stp_air=True was set.'
                )
            q.TPX = 300., 101325., 'o2:1 n2:3.74'
        else:
            if properties is None:
                raise ValueError(
                    'ChemicalMechanismSpec.stream() was called improperly.\n'
                    'There are two ways to build streams:\n'
                    ' 1)  stream(stp_air=True)\n'
                    ' 2)  stream(properties, values), e.g. stream(\'X\', \'O2:1, N2:1\')\n'
                    '                                   '
                    'or stream(\'TPY\', (300., 101325., \'O2:1, N2:1\'))\n')
            else:
                if properties is not None and values is None:
                    raise ValueError(
                        'ChemicalMechanismSpec.stream() expects two arguments '
                        'if properties are set in the construction')
                setattr(q, properties, values)
        return q
def compute_primary_mixture(m_dot_frac_CO, m_dot_frac_CO2, m_dot_frac_H2,
                            m_dot_frac_H2O, m_dot_frac_CH4,
                            mol_dot_primary_air):
    """
    Mixing two streams using `Quantity` objects.

    In this example, air and methane are mixed in stoichiometric proportions. This
    is a simpler, steady-state version of the example ``reactors/mix1.py``.

    Since the goal is to simulate a continuous flow system, the mixing takes place
    at constant enthalpy and pressure.
    """

    gas = ct.Solution('gri30.xml')

    # Stream A (air)
    A = ct.Quantity(gas, constant='HP')
    A.TPX = 300.0, ct.one_atm, 'O2:0.21, N2:0.79'

    # Stream B (methane)
    B = ct.Quantity(gas, constant='HP')
    #B.TPX = 300.0, ct.one_atm, 'CH4:1'

    # Converting mass flow rates per species into molar flow rates:
    MW_CO = 0.02801  # kg/mol
    MW_CO2 = 0.04401  # kg/mol
    MW_H2 = 0.00201588  # kg/mol
    MW_H2O = 0.01802  # kg/mol
    MW_CH4 = 0.01604  # kg/mol

    # molar flow rates of fuel. (mol/s)
    mol_dot_co = m_dot_frac_CO / Decimal(MW_CO)
    mol_dot_co2 = m_dot_frac_CO2 / Decimal(MW_CO2)
    mol_dot_h2 = m_dot_frac_H2 / Decimal(MW_H2)
    mol_dot_h2o = m_dot_frac_H2O / Decimal(MW_H2O)
    mol_dot_ch4 = m_dot_frac_CH4 / Decimal(MW_CH4)

    total_molar_flow_rate = mol_dot_co + mol_dot_co2 + mol_dot_h2 + mol_dot_h2 + mol_dot_h2o + mol_dot_ch4

    mol_frac_co = mol_dot_co / total_molar_flow_rate
    mol_frac_co2 = mol_dot_co2 / total_molar_flow_rate
    mol_frac_h2 = mol_dot_h2 / total_molar_flow_rate
    mol_frac_h2o = mol_dot_h2o / total_molar_flow_rate
    mol_frac_ch4 = mol_dot_ch4 / total_molar_flow_rate

    print("total molar flow rate of fuel")
    print(total_molar_flow_rate)

    print("mole fraction co:")
    print(mol_frac_co)

    print("mole fraction co2:")
    print(mol_frac_co2)

    print("mol fraction of h2:")
    print(mol_frac_h2)

    print("mol fraction of h2o:")
    print(mol_frac_h2o)

    print("mole fraction of ch4:")
    print(mol_frac_ch4)

    B.TPX = 748, ct.one_atm, {
        'H2': mol_frac_h2,
        'H2O': mol_frac_h2o,
        'CH4': mol_frac_ch4,
        'CO': mol_frac_co,
        'CO2': mol_frac_co2
    }

    # Set molar flow rates:
    # CH4 + 2 O2 -> CO2 + 2 H2O

    # PREVIOUS LINES:
    #A.moles = 0.011 # mol/s
    #nO2 = A.X[A.species_index('O2')]

    # NEW LINES: air properties.
    mol_frac_n2_atm = 0.79
    mol_frac_o2_atm = 0.21
    A.TPX = 748, ct.one_atm, {'N2': mol_frac_n2_atm, 'O2': mol_frac_o2_atm}

    B.moles = float(total_molar_flow_rate)
    A.moles = float(mol_dot_primary_air)  # chosen randomly for now.

    # Compute the mixed state
    M = A + B
    print(M.report())

    gas = M  # assign the mixture to gas solution object

    # Show that this state corresponds to stoichiometric combustion
    gas.equilibrate(
        'HP')  # equilibrate the mixture with constant enthaly and pressure
    print("here is the gas")
    print(gas.report())  # print the gas solution object report

    mol_fractions = gas.X
    mol_fractions_numpy = np.array(mol_fractions)
    print(mol_fractions)

    #gas.write_csv('mol_fractions_numpy.csv', quiet=False)

    return mol_fractions_numpy
Beispiel #13
0
 def copy_stream(self, stream):
     """Make a duplicate of a stream - use this to avoid inadvertently modifying a stream by reference."""
     q = ct.Quantity(self._cantera_wrapper.solution)
     q.TPX = stream.TPX
     return q
Beispiel #14
0
def compressor(__gas_composition,
               __pv1,
               __tv1,
               __mv1,
               __piv,
               __etav,
               __menext=0):
    """ Generic numeric Model of compressor parametrized by input values
        __gas_composition, __pv1, __tv1, __mv1, __piv, __menext

    Type: Function

    Sub functions: gas_object, create_state_dataframe, cantera function

    Input:
    __gas_composition_input_format - Gas object composition in format
    [[species_1, ... , species_n], [molar_fraction_1, ... , molar_fraction_n]]
    __pv1 - Compressor inlet pressure in [Pa]
    __tv1 - Compressor inlet temperature in [K]
    __mv1 - Compressor inlet mass flow in [kg/s]
    __piv - Compressor pressure ratio [-]
    __etav - Compressor isentropic efficiency decimal unit e.g. 0.85
    __menext - Cooling air equivalent in [%]

    Output:

    bulk_vector:

        compressor_inlet_bulk - Cantera gas quantity object based on phase object and quantity scalar (e.g. kg) for
                                medium at compressor inlet
        compressor_outlet_bulk - Cantera gas quantity object based on phase object and quantity scalar (e.g. kg) for
                                 medium at compressor inlet

    attribute_vector:
        __mv1 - Compressor inlet mass flow in [kg/s]
        mv1_eq - Equivalent compressor inlet mass flow in [kg/s]
        __pv1 - Compressor inlet pressure in [Pa]
        pv2 - Compressor outlet pressure in [Pa]
        __piv - Compressor pressure ratio [-]
        __tv1 - Compressor inlet temperature in [K]
        tv2 - Compressor outlet temperature in [K]
        tv2_is - Compressor outlet temperature for isentropic compression in [K]
        compressor_power - Mechanical power for given compressor mass flow in [kg/s]
        compressor_power_equivalent - - Mechanical power for equivalent compressor mass flow in [kg/s]

    gas_properties - dataframe w/ relevant thermodynamic data for compressor inlet, compressor outlet
    """

    m_eq = Symbol('m_eq')

    md = __menext / 100

    eq1 = sym.Eq((__mv1 / m_eq - 1), md)

    mv1_eq = solve(eq1, m_eq)[0]

    gas_phase = gas_object(__gas_composition, __tv1, __pv1)

    compressor_inlet_bulk = ct.Quantity(gas_phase, mass=__mv1)

    compressor_outlet_bulk = ct.Quantity(gas_phase, mass=__mv1)

    pv2 = __piv * __pv1
    sv1 = compressor_outlet_bulk.phase.s
    hv1 = compressor_outlet_bulk.phase.h

    compressor_outlet_bulk.SP = sv1, pv2
    tv2_is = compressor_outlet_bulk.phase.T
    hv2_is = compressor_outlet_bulk.phase.h
    hv2 = (hv2_is - hv1) / __etav + hv1

    compressor_outlet_bulk.HP = hv2, pv2
    tv2 = compressor_outlet_bulk.phase.T
    compressor_power = -__mv1 * (hv2 - hv1) / 1000
    compressor_power_equivalent = -mv1_eq * (hv2 - hv1) / 1000

    bulk_vector = [compressor_inlet_bulk, compressor_outlet_bulk]

    attribute_vector = [
        __mv1, mv1_eq, __pv1, pv2, __piv, __tv1, tv2, tv2_is, compressor_power,
        compressor_power_equivalent
    ]

    df1 = create_state_dataframe(compressor_inlet_bulk, "Compressor Inlet")
    df2 = create_state_dataframe(compressor_outlet_bulk, "Compressor Outlet")
    gas_properties = pd.concat([df1, df2], axis=1)

    return bulk_vector, attribute_vector, gas_properties
Beispiel #15
0
def combustion_chamber3(__compressor_in_bulk, __combustor_in_bulk,
                        __fuel_phase, __menext, __m_cooler, __p_booster,
                        __t_hex_out, __eta_cc, __dp_cc, __tt1, __m_fuel,
                        __controller):
    """ Generic numeric Model of combustion chamber for Gas Turbine w/ external ccoling systen
     parametrized by input values __compressor_in_bulk, __combustor_in_bulk, __fuel_phase, __menext, __m_cooler, __p_booster,
                        __t_hex_out, __eta_cc, __dp_cc, __tt1, __m_fuel, __controller

    Type: Function

    Sub functions: gas_object, sensible_enthalpy, fuel_to_air_ratio2, object_to_composition, heating_value_mix
    create_state_dataframe, cantera function

    Input:
    __compressor_in_bulk - Compressor Inlet Cantera Quantity Object
    __combustor_in_bulk - Compressor Outlet/Oxidizer Combustion Chamber Inlet Cantera Quantity Object
    __fuel_phase - Fuel Combustion Chamber Inlet Cantera Phase Object
    __menext - Cooling air equivalent in [%]
    __m_cooler - Mass Flow in Cooling Air Line [kg/s]
    __p_booster - Power of Cooling Air Booster [kW]
    __t_hex_out - Temperature of Cooling Air after Heat Exchanger [K]
    __eta_cc - Efficiency Combustion Chamber []
    __dp_cc - Differential Pressure Combustion Chamber [Pa]
    __tt1 - Turbine Inlet Temperature [K]
    __m_fuel - Fuel Mass Flow [kg/s]
    __controller - controller value:
        1 - Fuel Mass Flow Given Value, TT1 calculated Value
        2 - TT1 Given Value, Fuel Mass Flow calculated Value


    Output:

    bulk_vector - vector of following Cantera Objects:

        1 - __compressor_in_bulk - Cantera Object representing Compressor Inlet bulk
        2 - __combustor_in_bulk - Cantera Object representing Compressor Outlet bulk
        3 - cooler_in_bulk - Cantera Object representing Cooler Inlet bulk
        4 - cooler_out_bulk - Cantera Object representing Cooler Outlet bulk
        5 - fuel_bulk - Cantera Object representing Fuel Combustor Inlet bulk
        6 - flue_gas_bulk - Cantera Object representing Flue Combustor Outlet bulk

    attribute_vector:
        __m_fuel - Fuel mass flow [kg/s]
        lhv - Lower heat value [kJ/kgK]
        fuel_heat_power - Fuel Heat Power [kJ]
        pt1 - Combustor inlet pressure [Pa]
        __tt1 - Combustor outlet temperature [K]

    gas_properties - dataframe w/ relevant thermodynamic data for compressor inlet, compressor outlet
    """

    hv1 = sensible_enthalpy(__compressor_in_bulk.phase, ref_type=1)[0] / 1000
    mv1 = __compressor_in_bulk.mass

    hv2 = sensible_enthalpy(__combustor_in_bulk.phase, ref_type=1)[0] / 1000
    mv2 = __combustor_in_bulk.mass
    pv2 = __combustor_in_bulk.phase.P

    cooler_in_bulk = ct.Quantity(__combustor_in_bulk.phase, mass=__m_cooler)
    cooler_out_bulk = ct.Quantity(__combustor_in_bulk.phase, mass=__m_cooler)
    cooler_out_bulk.TP = __t_hex_out, pv2

    h_hex_out = sensible_enthalpy(cooler_out_bulk.phase, ref_type=1)[0] / 1000

    phi = 1

    fuel_to_air_ratio_stoech = fuel_to_air_ratio2(__combustor_in_bulk.phase,
                                                  __fuel_phase, phi)
    __m_fuel_stoechiometric = float(mv2) * float(fuel_to_air_ratio_stoech)

    fuel_bulk = ct.Quantity(__fuel_phase, mass=__m_fuel_stoechiometric)

    enthalpy = []
    temperature = []
    n = 100

    for i in range(n + 1):

        fuel_bulk.mass = __m_fuel_stoechiometric * i / n
        flue_gas_bulk = __combustor_in_bulk + fuel_bulk
        flue_gas_bulk.equilibrate('HP')
        enthalpy.append(
            sensible_enthalpy(flue_gas_bulk.phase, ref_type=1)[0] / 1000)
        temperature.append(flue_gas_bulk.phase.T)

    interpolation_t_h_flue_gas = interpolate.interp1d(temperature, enthalpy)
    interpolation_h_t_flue_gas = interpolate.interp1d(enthalpy, temperature)

    m_eq = Symbol('m_eq')

    md = __menext / 100

    eq1 = sym.Eq((mv1 / m_eq - 1), md)

    mv1_eq = solve(eq1, m_eq)[0]

    m_ext = 0
    m_w = 0
    h_w = 0

    h_sens_fuel = sensible_enthalpy(__fuel_phase, ref_type=1)[0] / 1000

    fuel_composition = object_to_composition(__fuel_phase)
    lhv = heating_value_mix(fuel_composition)[0]

    flue_gas_bulk = 'self'

    if __controller == 1:

        fuel_bulk.mass = __m_fuel
        ht1 = Symbol('ht1')

        eq3 = sym.Eq(
            ((mv1 * hv1) + mv1_eq *
             (hv2 - hv1) - m_ext * hv2 + m_w * h_w - __m_cooler *
             (hv2 - h_hex_out) + __m_fuel * __eta_cc *
             (lhv + h_sens_fuel) + __p_booster) / (mv1 + __m_fuel + m_w), ht1)

        ht1_calc = float(solve(eq3, ht1)[0])

        __tt1 = interpolation_h_t_flue_gas(ht1_calc)

        flue_gas_bulk = __combustor_in_bulk + fuel_bulk
        flue_gas_bulk.equilibrate('HP')

        pt1 = pv2 - __dp_cc
        flue_gas_bulk.TP = __tt1, pt1

    elif __controller == 2:

        __m_fuel = Symbol('__m_fuel')

        ht1 = interpolation_t_h_flue_gas(__tt1)

        eq2 = sym.Eq(
            ((mv1 * hv1) + mv1_eq *
             (hv2 - hv1) - m_ext * hv2 + m_w * h_w - __m_cooler *
             (hv2 - h_hex_out) + __m_fuel * __eta_cc *
             (lhv + h_sens_fuel) + __p_booster) / (mv1 + __m_fuel + m_w), ht1)

        __m_fuel_calc = solve(eq2, __m_fuel)[0]
        fuel_bulk.mass = __m_fuel_calc
        flue_gas_bulk = __combustor_in_bulk + fuel_bulk
        flue_gas_bulk.equilibrate('HP')

        pt1 = pv2 - __dp_cc
        flue_gas_bulk.TP = __tt1, pt1

    __m_fuel = fuel_bulk.mass

    fuel_heat_power = lhv * __m_fuel

    bulk_vector = [
        __compressor_in_bulk, __combustor_in_bulk, cooler_in_bulk,
        cooler_out_bulk, fuel_bulk, flue_gas_bulk
    ]

    attribute_vector = [__m_fuel, lhv, fuel_heat_power, pt1, __tt1]

    df1 = create_state_dataframe(__combustor_in_bulk,
                                 "Oxidator Combustion Chamber Inlet")
    df2 = create_state_dataframe(cooler_in_bulk, "Cooler Inlet")
    df3 = create_state_dataframe(cooler_out_bulk, "Cooler Outlet")
    df4 = create_state_dataframe(fuel_bulk, "Fuel Combustion Chamber Inlet")
    df5 = create_state_dataframe(flue_gas_bulk,
                                 "Flue Gas Combustion Chamber Outlet")
    gas_properties = pd.concat([df1, df2, df3, df4, df5], axis=1)

    return bulk_vector, attribute_vector, gas_properties
Beispiel #16
0
def turbine(__turbine_inlet_bulk, __pt2, __etat):
    """ Generic numeric Model of turbine for Gas Turbine parametrized by input values
        __turbine_inlet_bulk, __pt2, __etat

     Type: Function

     Sub functions: create_state_dataframe, cantera function

     Input:
     __turbine_inlet_bulk - Turbine Inlet Cantera Quantity Object
     __pt2 - Pressure Turbine Inlet [Pa]
     __etat - Efficiency Turbine Section [-]

     Output:

     bulk_vector - vector of following Cantera Objects:

         1 - __turbine_inlet_bulk - Cantera Object representing Turbine Inlet bulk
         2 - turbine_outlet_bulk - Cantera Object representing Turbine Outlet bulk

     attribute_vector:

         mt1 - Turbine Inlet Mass flow [kg/s]
         pt1 - Turbine Inlet Pressure [Pa]
         tt1 - Turbine Inlet Temperature [K]
         __pt2 - Turbine Inlet Pressure [Pa]
         tt2_is - Isentropic Turbine Outlet Temperature [K]
         tt2 - Turbine Outlet Temperature [K]
         turbine_power - turbine power [kW]

     gas_properties - dataframe w/ relevant thermodynamic data for compressor inlet, compressor outlet
     """

    tt1 = __turbine_inlet_bulk.phase.T
    pt1 = __turbine_inlet_bulk.phase.P
    mt1 = __turbine_inlet_bulk.mass
    st1 = __turbine_inlet_bulk.phase.s
    ht1 = __turbine_inlet_bulk.phase.h

    turbine_outlet_bulk = ct.Quantity(__turbine_inlet_bulk.phase, mass=mt1)
    turbine_outlet_bulk.SP = st1, __pt2
    tt2_is = turbine_outlet_bulk.phase.T
    ht2_is = turbine_outlet_bulk.phase.h

    ht2 = (ht2_is - ht1) * __etat + ht1

    turbine_outlet_bulk.HP = ht2, __pt2
    tt2 = turbine_outlet_bulk.phase.T

    turbine_power = -mt1 * (ht2 - ht1) / 1000

    df1 = create_state_dataframe(__turbine_inlet_bulk, "Turbine Inlet")
    df2 = create_state_dataframe(turbine_outlet_bulk, "Turbine Outlet")

    bulk_vector = [__turbine_inlet_bulk, turbine_outlet_bulk]

    attribute_vector = [mt1, pt1, tt1, __pt2, tt2_is, tt2, turbine_power]

    gas_properties = pd.concat([df1, df2], axis=1)

    return bulk_vector, attribute_vector, gas_properties
Beispiel #17
0
def combustion_2(pv1,
                 tv1,
                 mv1,
                 __dp_cc,
                 eta_cc,
                 compressor_outlet_phase,
                 fuel_phase,
                 menext=0,
                 m_fuel=None,
                 tt1=None,
                 phi=None,
                 controller=None):
    t1 = time.time()

    # compressor_outlet_phase - compressor outlet phase object contents compostion in molar fractions of species, temperature in K, pressure in Pa etc.
    # fuel_phase - fuel phase object contents composition in molar fractions of species, temperature in K, pressure in Pa etc.
    # mv1 - Mass Flow of oxidator enters compressor inlet in kg/s
    # __dp_cc - Combustion Chamber pressure loss in bar
    # eta_cc - Combustion chamber efficiency by normalization of radiation/heat losses
    # m_fuel - Fuel Mass Flow (only needed if Controller is set to 1 - Fuel mass controller)
    # tt1 - Combustion Chamber Exhaust Tempertaure (only needed if Controller is set to 2 - Exhaust temperature controller)
    # phi - Combustion Chamber airnumeber/equivalent ratio control (only needed if Controller is set to 3 - Phi controller)
    #
    # controller - control principle to determine combustion chamber operation point:
    # None - No controller select
    # 1 - Mass Flow Controller -  determination of operation point by given m_fuel, t3 and phi will be ignored
    # 2 - Temperature Exhaust Controller - determination of operation point by given combustion outlet temperature t3 as target value
    # 3 - Phi Controller - determination of operation point by given equivalence (air to fuel mass ratio) phi

    if compressor_outlet_phase == None:
        print(
            "Bitte Oxidator als Cantera Phase-Objekt (oxidator_phase) angeben")
        print(
            "combustion(oxidator_phase, fuel_phase, m_oxi, __dp_cc, m_fuel, t3, phi, controller)"
        )
    if fuel_phase == None:
        print("Bitte Brennstoff als Cantera Phase-Objekt (fuel_phase) angeben")
        print(
            "combustion(oxidator_phase, fuel_phase, m_oxi, __dp_cc, m_fuel, t3, phi, controller)"
        )
    if mv1 == None:
        print(
            "Bitte Oxidatormassenstrom als Fließkommazahl oder Integer (m_oxi) in kg/s angeben"
        )
        print(
            "combustion(oxidator_phase, fuel_phase, m_oxi, __dp_cc, m_fuel, t3, phi, controller)"
        )
    if m_fuel == None:
        pass
    if __dp_cc == None:
        print(
            "Bitte Brennkammerdruckverlust als Fließkommazahl oder Integer (__dp_cc) in mbar angeben"
        )
        print(
            "combustion(oxidator_phase, fuel_phase, m_oxi, __dp_cc, m_fuel, t3, phi, controller)"
        )
    if controller == None:
        print(
            "Bitte Regelung (controller) als Integer angeben:\n"
            "1 - Mass Flow Controller -  determination of operation point by given m_fuel, t3 and phi will be ignored\n"
            "2 - Temperature Exhaust Controller - determination of operation point by given combustion outlet temperature t3 as target value\n"
            "3 - Phi Controller - determination of operation point by given equivalence (air to fuel mass ratio) phi"
        )
        print(
            "combustion(oxidator_phase, fuel_phase, m_oxi, __dp_cc, m_fuel, t3, phi, controller)"
        )

    if controller == 2 and tt1 == None:
        print(
            "Bitte Brennkammeraustrittstemperatur t3 bei Controllerstellung 2 in kg/s angeben"
        )
        print(
            "combustion(oxidator_phase, fuel_phase, m_oxi, __dp_cc, m_fuel, t3, phi, controller)"
        )

    fuel_composition = object_to_composition(fuel_phase)
    compressor_outlet_composition = object_to_composition(
        compressor_outlet_phase)

    compressor_inlet_phase = gas_object(compressor_outlet_composition, tv1,
                                        pv1)

    tv2 = compressor_outlet_phase.T
    pv2 = compressor_outlet_phase.P
    pt1 = pv2 - __dp_cc

    hv1 = sensible_enthalpy(compressor_inlet_phase, ref_type=1)[0] / 1000
    hv2 = sensible_enthalpy(compressor_outlet_phase, ref_type=1)[0] / 1000
    h_sens_fuel = sensible_enthalpy(fuel_phase, ref_type=1)[0] / 1000

    m_eq = Symbol('m_eq')
    md = menext / 100

    eq1 = sym.Eq((mv1 / m_eq - 1), md)
    mv1_eq = solve(eq1, m_eq)[0]

    h_water = 0
    __m_cooler = 0
    __p_booster = 0

    m_water = 0
    m_ex_discharge = 0
    m_leakage = 0

    m_fuel_target_value = m_fuel
    phi_target_value = phi
    t_fuel = fuel_phase.T
    p_fuel = fuel_phase.P

    h_cooler_out = 0

    lhv = heating_value_mix(fuel_composition)[0]
    # lhv=50000

    # identify limits of combustion chamber operation tempoperature limits by Inlet Temperature as minimum and stoeciometric operation point as maximum

    # Minimum Temperature at phi=0

    tt1_min = tv2

    # Maximum Temperature at phi=1 (stoechiometric combustion)
    # calculating w/ fuel mass flow at phi=1
    phi = 1
    m_fuel_stoech = fuel_to_air_ratio(compressor_outlet_composition,
                                      fuel_composition, phi) * mv1_eq

    t2 = time.time()

    compressor_outlet_phase = gas_object(compressor_outlet_composition, tv2,
                                         pv2)

    fuel_phase = gas_object(fuel_composition, t_fuel, p_fuel)

    compressor_outlet_bulk = ct.Quantity(compressor_outlet_phase, mass=mv1_eq)

    fuel_bulk = ct.Quantity(fuel_phase, mass=m_fuel_stoech)

    stoechiometric_mix = compressor_outlet_bulk + fuel_bulk
    stoechiometric_mix.equilibrate('HP')
    tt1_max = stoechiometric_mix.phase.T

    #################################################################################################
    # Calculation of exhaust flue gas properties based on fuel mass flow target value
    if controller == 1:
        # print(mv1)
        if m_fuel == None:
            print(
                "Bitte Brennstoffmassenstrom m_fuel bei Controllerstellung 1 in kg/s angeben"
            )
            print(
                "combustion(oxidator_phase, fuel_phase, m_oxi, __dp_cc, m_fuel, t3, phi, controller)"
            )

        compressor_outlet_phase = gas_object(compressor_outlet_composition,
                                             tv2, pv2)
        fuel_phase = gas_object(fuel_composition, t_fuel, p_fuel)

        compressor_outlet_bulk = ct.Quantity(compressor_outlet_phase, mass=mv1)
        fuel_bulk = ct.Quantity(fuel_phase, mass=m_fuel_target_value)

        flue_gas_bulk = compressor_outlet_bulk + fuel_bulk
        phi = flue_gas_bulk.get_equivalence_ratio()
        flue_gas_bulk.equilibrate('HP')

        tt1 = flue_gas_bulk.TP[0]
        flue_gas_bulk.TP = tt1, pt1

    t3 = time.time()
    #################################################################################################
    # Calculation of exhaust flue gas properties based on reverse air numer/equivalent ratio target value
    if controller == 3:

        if phi == None:
            print(
                "Bitte Äquivalenzverhältnis phi bei Controllerstellung 3 angeben"
            )
            print(
                "combustion(oxidator_phase, fuel_phase, m_oxi, __dp_cc, m_fuel, t3, phi, controller)"
            )

        compressor_outlet_phase = gas_object(compressor_outlet_composition,
                                             tv2, pv2)
        fuel_phase = gas_object(fuel_composition, t_fuel, p_fuel)

        m_fuel_target_value = phi_target_value * m_fuel_stoech
        # print(phi_target_value, m_fuel_stoech)
        compressor_outlet_bulk = ct.Quantity(oxidator_phase, mass=mv1_eq)
        fuel_bulk = ct.Quantity(fuel_phase, mass=m_fuel_target_value)

        flue_gas_bulk = oxidator_bulk + fuel_bulk
        phi = flue_gas_bulk.get_equivalence_ratio()
        flue_gas_bulk.equilibrate('HP')

        tt1 = flue_gas_bulk.TP[0]
        flue_gas_bulk.TP = tt1, pt1

    ##################################################################################################
    t4 = time.time()

    # Calculation of exhaust flue gas properties based on temperature target value
    if controller == 2:

        if tt1 == None:
            print(
                "Bitte Brennkammeraustrittstemperatur t3 bei Controllerstellung 2 in kg/s angeben"
            )
            print(
                "combustion(oxidator_phase, fuel_phase, m_oxi, __dp_cc, m_fuel, t3, phi, controller)"
            )

        if tt1 < tt1_min:
            print(
                "Temperaturzielwert Brennkammeraustritt ist kleiner als Brennkammerientrittstemperatur"
            )

        if tt1 > tt1_max:
            print(
                "Temperaturzielwert Brennkammeraustritt ist größer maximal erreichbare Temperatur bei stöchiometrischer Verbrennung"
            )

        if tt1_min < tt1 < tt1_max:

            ht1 = Symbol('ht1')
            m_fuel = Symbol('m_fuel')

            mv2 = mv1 - m_ex_discharge

            m_fuel_ini = 0.35 * m_fuel_stoech
            compressor_outlet_phase = gas_object(compressor_outlet_composition,
                                                 tv2, pv2)

            compressor_outlet_bulk_eq = ct.Quantity(compressor_outlet_phase,
                                                    mass=mv1_eq)
            fuel_bulk = ct.Quantity(fuel_phase, mass=m_fuel_ini)
            # print(tt1, pt1)
            flue_gas_bulk_eq = compressor_outlet_bulk_eq + fuel_bulk
            flue_gas_bulk_eq.equilibrate('HP')
            flue_gas_bulk_eq.TP = tt1, pt1
            ht1 = sensible_enthalpy(flue_gas_bulk_eq.phase,
                                    ref_type=1)[0] / 1000

            delta_h = 1

            # print('mv1: ' + str(mv1))
            # print('mv1_eq: ' + str(mv1_eq))
            # print('pv1: ' + str(pv1))
            # print('tv1: ' + str(tv1))
            # print('hv1: ' + str(hv1))

            # print('tv2: ' + str(tv2))
            # print('pv2: ' + str(pv2))
            # print('hv2: ' + str(hv2))

            # print('lhv: ' + str(lhv))
            # print('h_sens_fuel: ' + str(h_sens_fuel))

            # print('eta_cc: ' + str(eta_cc))

            while delta_h > 0.1:
                compressor_outlet_phase = gas_object(
                    compressor_outlet_composition, tv2, pv2)
                fuel_phase = gas_object(fuel_composition, t_fuel, p_fuel)

                energy_balance_cc = sym.Eq(
                    (mv1 + m_fuel + m_water - m_ex_discharge - m_leakage) * ht1
                    + hv2 * __m_cooler + (1 - eta_cc) *
                    (lhv + h_sens_fuel) * m_fuel,
                    (mv1_eq - m_ex_discharge) * hv2 +
                    (lhv + h_sens_fuel) * m_fuel + h_cooler_out * __m_cooler +
                    h_water * m_water + (mv1 - mv1_eq) * hv1 + __p_booster)

                m_fuel_ini = solve(energy_balance_cc, m_fuel)[0]
                # print(m_fuel_ini)
                compressor_outlet_phase = gas_object(
                    compressor_outlet_composition, tv2, pv2)
                compressor_outlet_bulk_eq = ct.Quantity(
                    compressor_outlet_phase, mass=mv1_eq)
                fuel_bulk = ct.Quantity(fuel_phase, mass=m_fuel_ini)

                flue_gas_bulk = compressor_outlet_bulk_eq + fuel_bulk
                flue_gas_bulk.equilibrate('HP')
                flue_gas_bulk.TP = tt1, pt1
                ht1_j = sensible_enthalpy(flue_gas_bulk.phase,
                                          ref_type=1)[0] / 1000

                delta_h = abs(ht1_j - ht1)
                ht1 = ht1_j

            m_fuel_target_value = m_fuel_ini
            fuel_bulk = ct.Quantity(fuel_phase, mass=m_fuel_target_value)
            compressor_outlet_phase = gas_object(compressor_outlet_composition,
                                                 tv2, pv2)
            compressor_outlet_bulk = ct.Quantity(compressor_outlet_phase,
                                                 mass=mv2)
            flue_gas_bulk = compressor_outlet_bulk + fuel_bulk
            flue_gas_bulk.equilibrate('HP')
            flue_gas_bulk.TP = tt1, pt1

    tt1 = flue_gas_bulk.phase.T
    pt1 = flue_gas_bulk.phase.P
    mt1 = flue_gas_bulk.mass

    t4 = time.time()

    df1 = create_state_dataframe(fuel_bulk, "Fuel")
    df2 = create_state_dataframe(compressor_outlet_bulk,
                                 "Combustion Chamber Inlet")
    df3 = create_state_dataframe(flue_gas_bulk, "Combustion Chamber Outlet")
    gas_properties = pd.concat([df1, df2, df3], axis=1)

    ht1 = sensible_enthalpy(flue_gas_bulk.phase, ref_type=1)[0] / 1000

    heat_power = fuel_bulk.mass * lhv
    t5 = time.time()

    return flue_gas_bulk, tt1, pt1, mt1, fuel_bulk.mass, lhv, heat_power, gas_properties
Beispiel #18
0
cti_file = '~/Dokumenty/nasa.cti'

mgp = 0.002  #[kg] mass of gunpowder
area = 0.05  #[m^2] frontal area of a piston
mpiston = 2.0  #[kg] mass of the piston
tstep = 0.001  #[s] time step of a simulation
lengthstart = 0.2  #[m] initial length of a reactor
lengthstop = 0.4  #[m] final length of a reactor

air = ct.Solution(cti_file, 'gas')
air.TP = 300.0, 1.0 * ct.one_atm

KNO3 = ct.Solution(cti_file, 'ox')
KNO3.TP = 300.0, 1.0 * ct.one_atm
q1 = ct.Quantity(KNO3, mass=0.75 * mgp)

S = ct.Solution(cti_file, 'sulfur')
S.TP = 300.0, 1.0 * ct.one_atm
q2 = ct.Quantity(S, mass=0.1 * mgp)

C = ct.Solution(cti_file, 'carbon')
C.TP = 300.0, 1.0 * ct.one_atm
q3 = ct.Quantity(C, mass=0.15 * mgp)

products = ct.Solution(cti_file, 'products')
products.TP = 300.0, 1.0 * ct.one_atm
q4 = ct.Quantity(products, mass=0)

K2S = ct.Solution(cti_file, 'potsulf')
K2S.TP = 300.0, 1.0 * ct.one_atm
Beispiel #19
0
import sys
import os
import math
import csv
import numpy as np

import cantera as ct

#combustion chamber volume and mass flows assesment based on the dimensions of Rolls Royce AE3007

lambda_air = 1.5 #air–fuel equivalence ratio

air = ct.Solution('air.cti')
air.TP = 800, 1.4e+06 #typical temperature and pressure behind HPC
air_in=ct.Reservoir(air)
air_mdot=ct.Quantity(air, mass=20)

fuel = ct.Solution('Dagaut_Ori.cti')
fuel.TPY = 300, 3e+05, 'NC10H22:0.74,PHC3H7:0.15,CYC9H18:0.11'
fuel_in=ct.Reservoir(fuel)
fuel_mdot = ct.Quantity(fuel, mass=1)
fuel_mdot.mass=air_mdot.mass/lambda_air/14.9

#igniter (like in "combustor.py")
fuel.TPX = 1500, 2e+06, 'H:1.0'
igniter = ct.Reservoir(fuel)

fuel.TPX = 1100, 1.2e+6, 'N2:1.0' #combustion chamber already hot, otherwise some mechanims doesn't integrate properly when combustor temperature is below 1000 K
combustor = ct.IdealGasReactor(fuel, energy='on')
combustor.volume = 0.2
Beispiel #20
0
 def mix_for_equivalence_ratio(self, phi, fuel, oxy):
     """Mix a stream of fuel and oxidizer such that the mixture has a specified equivalence ratio."""
     self._cantera_wrapper.solution.set_equivalence_ratio(
         phi, fuel.X, oxy.X)
     return ct.Quantity(self._cantera_wrapper.solution)
Beispiel #21
0
def sofc3(fuel_phase, cathode_in_phase, cathode_massflow_max, cathode_massflow,
          t_reformer, t_sofc, airnumber, fu_stack, fu_system_min, s_to_c_ratio,
          dp_sofc):

    fuel_active_species_vector = ['CH4', 'H2', 'CO']

    t_fuel, p_fuel = fuel_phase.TP
    t_air_preheater, p_air_preheater = cathode_in_phase.TP

    # print(cathode_in_phase.TP)

    p_sofc = p_air_preheater
    p_reformer = p_sofc

    i_max = 0.9  # A/cm2
    nominal_factor = 0.9

    i_nominal = i_max * nominal_factor

    i_absolute_max = oxygen_to_current(cathode_in_phase, cathode_massflow_max,
                                       airnumber)[0]
    i_absolute = oxygen_to_current(cathode_in_phase, cathode_massflow,
                                   airnumber)[0]

    a = i_absolute_max / i_nominal
    i = i_absolute / a
    # print(fuel_phase)
    result = recirculation(fuel_phase, s_to_c_ratio, fu_system_min, fu_stack,
                           t_reformer, p_reformer)

    recirculation_phase = result[0][0]
    recirculation_parameter_vector = result[1]
    anode_in_phase = result[0][1]

    steam_to_carbon_ratio = result[1][0]
    recirculation_rate = result[1][1]
    fuel_utilization_stack = result[1][2]
    fuel_utilization_system = result[1][3]

    anode_in_bulk = anode_inlet_bulk(anode_in_phase,
                                     fuel_active_species_vector, i_absolute,
                                     fu_stack)
    anode_in_bulk.TP = t_sofc, p_sofc

    anode_out_bulk = anode_outlet_bulk(anode_in_bulk,
                                       fuel_active_species_vector, i_absolute)
    anode_out_bulk.TP = t_sofc, p_sofc

    anode_out_phase = anode_out_bulk.phase

    cathode_in_bulk = cathode_inlet_bulk(anode_in_phase, cathode_in_phase,
                                         fuel_active_species_vector,
                                         i_absolute, airnumber)
    cathode_in_bulk.TP = t_sofc, p_sofc

    # cathode_in_bulk_composition

    sofc_bulk_in_cathode_composition = object_to_composition(
        cathode_in_bulk.phase)
    sofc_bulk_in_cathode_phase = gas_object(sofc_bulk_in_cathode_composition,
                                            t_air_preheater, p_air_preheater)

    sofc_bulk_in_cathode_side = ct.Quantity(sofc_bulk_in_cathode_phase,
                                            mass=cathode_in_bulk.mass)
    sofc_bulk_in_cathode_side.TP = t_air_preheater, p_air_preheater

    # print(sofc_bulk_in_cathode_side.report())

    cathode_out_bulk = cathode_outlet_bulk(anode_in_phase, cathode_in_phase,
                                           fuel_active_species_vector,
                                           i_absolute, airnumber)
    cathode_out_bulk.TP = t_sofc, p_sofc

    rec_mass = recirculation_rate * anode_out_bulk.mass
    fuel_mass = anode_in_bulk.mass - rec_mass
    reformate_mass = anode_in_bulk.mass

    reformate_bulk = ct.Quantity(anode_in_phase, mass=reformate_mass)
    reformate_bulk.TP = t_reformer, p_reformer

    fuel_bulk_sofc_in = ct.Quantity(fuel_phase, mass=fuel_mass)
    fuel_bulk_sofc_in.TP = t_fuel, p_fuel

    fuel_bulk_reformer_in = ct.Quantity(fuel_phase, mass=fuel_mass)
    fuel_bulk_reformer_in.TP = t_reformer, p_reformer

    recirculation_bulk = ct.Quantity(recirculation_phase, mass=rec_mass)
    recirculation_bulk.TP = t_sofc, p_sofc

    afterburner_in_anode_mass = (1 - recirculation_rate) * anode_out_bulk.mass
    afterburner_in_anode_bulk = ct.Quantity(anode_out_phase,
                                            mass=afterburner_in_anode_mass)

    afterburner_in_cathode_bulk = ct.Quantity(cathode_out_bulk.phase,
                                              mass=cathode_out_bulk.mass)

    afterburner_in_bulk = afterburner_in_anode_bulk + afterburner_in_cathode_bulk

    afterburner_out_bulk = ct.Quantity(afterburner_in_bulk.phase,
                                       mass=afterburner_in_bulk.mass)
    afterburner_out_bulk.equilibrate('HP')

    h_sofc_in_cathode_side = sensible_enthalpy(sofc_bulk_in_cathode_side.phase,
                                               ref_type=None)[0] / 1000
    m_sofc_in_cathode_side = sofc_bulk_in_cathode_side.mass

    h_cathode_in = sensible_enthalpy(cathode_in_bulk.phase,
                                     ref_type=None)[0] / 1000
    m_cathode_in = cathode_in_bulk.mass

    h_recirculation = sensible_enthalpy(recirculation_bulk.phase,
                                        ref_type=None)[0] / 1000
    m_recirculation = recirculation_bulk.mass

    h_fuel_reformer_in = sensible_enthalpy(fuel_bulk_reformer_in.phase,
                                           ref_type=None)[0] / 1000
    m_fuel_reformer_in = fuel_bulk_reformer_in.mass

    h_fuel_sofc_in = sensible_enthalpy(fuel_bulk_sofc_in.phase,
                                       ref_type=None)[0] / 1000
    m_fuel_sofc_in = fuel_bulk_sofc_in.mass

    h_reformate = sensible_enthalpy(reformate_bulk.phase,
                                    ref_type=None)[0] / 1000
    m_reformate = reformate_bulk.mass

    h_anode_in = sensible_enthalpy(anode_in_bulk.phase,
                                   ref_type=None)[0] / 1000
    m_anode_in = anode_in_bulk.mass

    reaction_enthalpy_steam_reforming = 1000 * 164.4
    # combination of:
    # 1) SR - steam reforming of methane and steam with +206 [kJ/kmol] result in carbon monooxide and hydrogen
    # 2) WGS - water gas shift reaction of carbon monooxide and steam with -41.6 [kJ/kmol] result in carbon mdioxide and hydrogen
    # summarize to +206 [kJ/kmol] + (-41.6) [kJ/kmol] => 164.4

    ##########################################################################################################
    u_inlet = cell_voltage_local(cathode_in_bulk.phase, anode_in_bulk.phase,
                                 t_sofc, p_sofc, i)
    u_outlet = cell_voltage_local(cathode_out_bulk.phase, anode_out_bulk.phase,
                                  t_sofc, p_sofc, i)

    u0_inlet = cell_voltage_local(cathode_in_bulk.phase, anode_in_bulk.phase,
                                  t_sofc, p_sofc, 0)
    u0_outlet = cell_voltage_local(cathode_out_bulk.phase,
                                   anode_out_bulk.phase, t_sofc, p_sofc, 0)

    u = (u_inlet + u_outlet) / 2
    u0 = (u0_inlet + u0_outlet) / 2

    p_absolute = u * i_absolute / 1000

    delta_u = u0 - u

    #################################################################################################################
    q_cathode = m_sofc_in_cathode_side * h_sofc_in_cathode_side - m_cathode_in * h_cathode_in
    q_anode_fuel = m_fuel_sofc_in * h_fuel_sofc_in - m_fuel_reformer_in * h_fuel_reformer_in
    q_reformer = m_recirculation * h_recirculation + m_fuel_sofc_in * h_fuel_reformer_in - m_reformate * h_reformate
    q_steam_reforming = -fuel_bulk_reformer_in.phase[
        'CH4'].X * fuel_bulk_reformer_in.moles * reaction_enthalpy_steam_reforming
    q_reformer_anode = m_reformate * h_reformate - m_anode_in * h_anode_in
    q_sofc_ohmic_losses = delta_u * i_absolute / 1000
    # q_sofc_ohmic_losses = 0.2*i_absolute/1000
    q_losses = 0
    q_deficite = q_anode_fuel + q_cathode + q_reformer + q_steam_reforming[
        0] + q_reformer_anode + q_sofc_ohmic_losses + q_losses

    dh_deficite = q_deficite / afterburner_out_bulk.mass

    sofc_out_bulk = ct.Quantity(afterburner_out_bulk.phase,
                                mass=afterburner_out_bulk.mass)

    h_out_sofc = afterburner_out_bulk.phase.enthalpy_mass / 1000
    sofc_out_bulk.HP = (h_out_sofc + dh_deficite) * 1000, (p_sofc - dp_sofc)

    h_sofc_exit = sensible_enthalpy(sofc_out_bulk.phase,
                                    ref_type=None)[0] / 1000

    #####################################################################################################
    fuel_composition = object_to_composition(fuel_phase)
    reformate_composition = object_to_composition(anode_in_phase)

    lhv_fuel = heating_value_mix(fuel_composition)[0]
    lhv_reformate = heating_value_mix(reformate_composition)[0]

    t_sofc_out = sofc_out_bulk.T

    dt = 30

    if t_sofc_out < t_air_preheater + dt:

        sofc_out_bulk.TP = t_air_preheater + dt, sofc_out_bulk.P
        h_sofc_exit_2 = sensible_enthalpy(sofc_out_bulk.phase,
                                          ref_type=None)[0] / 1000

        m_sofc_out = sofc_out_bulk.mass

        dh = h_sofc_exit_2 - h_sofc_exit

        m_fuel_add = m_sofc_out * dh / lhv_fuel

        auxiliary_fuel = ct.Quantity(fuel_phase, mass=m_fuel_add)
        auxiliary_fuel.TP = t_fuel, p_fuel

    elif t_sofc_out > t_air_preheater + dt or t_sofc_out == t_air_preheater + dt:
        m_fuel_add = 0
        auxiliary_fuel = ct.Quantity(fuel_phase, mass=m_fuel_add)
        auxiliary_fuel.TP = t_fuel, p_fuel

    fuel_power = fuel_mass * lhv_fuel
    fuel_add_power = (fuel_mass + m_fuel_add) * lhv_fuel
    reformate_power = reformate_mass * lhv_reformate

    eta_fuel = p_absolute / fuel_power
    eta_add_fuel = p_absolute / fuel_add_power
    eta_reformate = p_absolute / reformate_power

    ##########################################################################################################

    df1 = create_state_dataframe(sofc_bulk_in_cathode_side,
                                 "SOFC Inlet Cathode Side")
    df2 = create_state_dataframe(fuel_bulk_sofc_in, "SOFC Inlet Fuel Side")
    df3 = create_state_dataframe(recirculation_bulk,
                                 "Reformer Inlet recirculation")
    df4 = create_state_dataframe(fuel_bulk_reformer_in,
                                 "Reformer Inlet Fuel Side")
    df5 = create_state_dataframe(reformate_bulk, "Reformer Outlet Bulk")
    df6 = create_state_dataframe(anode_in_bulk, "Anode Inlet")
    df7 = create_state_dataframe(cathode_in_bulk, "Cathode Inlet")
    df8 = create_state_dataframe(anode_out_bulk, "Anode Outlet")
    df9 = create_state_dataframe(cathode_out_bulk, "Cathode Outlet")
    df10 = create_state_dataframe(auxiliary_fuel, "Auxiliary Fuel")
    df11 = create_state_dataframe(afterburner_in_bulk, "Afterburner Inlet")
    df12 = create_state_dataframe(afterburner_out_bulk, "Afterburner Outlet")
    df13 = create_state_dataframe(sofc_out_bulk, "SOFC Outlet Bulk")

    gas_properties = pd.concat(
        [df1, df2, df3, df4, df5, df6, df7, df8, df9, df10, df11, df12, df13],
        axis=1)

    bulk_vector = [
        fuel_bulk_sofc_in, fuel_bulk_reformer_in, recirculation_bulk,
        reformate_bulk, anode_in_bulk, anode_out_bulk,
        sofc_bulk_in_cathode_side, cathode_in_bulk, cathode_out_bulk,
        afterburner_in_bulk, afterburner_out_bulk, sofc_out_bulk
    ]
    heat_vector = [
        q_cathode, q_anode_fuel, q_reformer, q_steam_reforming[0],
        q_reformer_anode, q_sofc_ohmic_losses, q_losses, q_deficite
    ]
    performance_vector = [
        p_absolute, i_absolute, fuel_add_power, reformate_power, eta_add_fuel,
        eta_reformate, lhv_fuel, lhv_reformate
    ]
    sofc_electrical_vector = [
        u, u0, u_inlet, u_outlet, u0_inlet, u0_outlet, i_max, nominal_factor,
        i_nominal, i_absolute_max, i_absolute, i, a
    ]

    return bulk_vector, heat_vector, performance_vector, sofc_electrical_vector, recirculation_parameter_vector, gas_properties
Beispiel #22
0
print(inspect.getfile(ct))
#圧力kPa,温度K
P1=101.325
T1=288.15
phi=0.8
P2=P1*1

E2=0.75
E4=0.82
P4=P1


inigas = ct.Solution('gri30.xml')

 #初期条件を設定(Air)
gas1 = ct.Quantity(inigas)
gas1.TPX = T1,P1*1000,{'O2':1, 'N2':3.76}
H1=gas1.h
#print(gas1.report())
#初期条件を設定(H2)


gas2 = ct.Quantity(inigas)
gas2.TPX = T1,P2*1000,{'H2':2*phi}

gas1.moles = 1
nO2 = gas1.X[gas1.species_index('O2')]
gas2.moles = nO2 * 2*phi

inigas = gas1 + gas2
Beispiel #23
0
In this example, air and methane are mixed in stoichiometric proportions. This
is a simpler, steady-state version of the example ``reactors/mix1.py``.

Since the goal is to simulate a continuous flow system, the mixing takes place
at constant enthalpy and pressure.

Requires: cantera >= 2.5.0
"""

import cantera as ct

gas = ct.Solution('gri30.yaml')

# Stream A (air)
A = ct.Quantity(gas, constant='HP')
A.TPX = 300.0, ct.one_atm, 'O2:0.21, N2:0.78, AR:0.01'

# Stream B (methane)
B = ct.Quantity(gas, constant='HP')
B.TPX = 300.0, ct.one_atm, 'CH4:1'

# Set the molar flow rates corresponding to stoichiometric reaction,
# CH4 + 2 O2 -> CO2 + 2 H2O
A.moles = 1
nO2 = A.X[A.species_index('O2')]
B.moles = nO2 * 0.5

# Compute the mixed state
M = A + B
print(M.report())
Beispiel #24
0
    print("refspecies and refcounts must be the same length")
for i in range(len(args.refspecies)):
    index=np.where([name ==  args.refspecies[i] for name in gas.species_names])[0][0]
    refmultiindex[index]=args.refcounts[i]

sp_atoms=[]
for i in range(ns):
    sp_atoms.append(np.array([int(gas.species()[i].composition[el] if el in gas.species()[i].composition.keys() else 0) for el in elements]))
sp_atoms=np.array(sp_atoms)
atoms=np.zeros(len(elements),dtype=int)
for i in range(len(refmultiindex)):
    atoms += refmultiindex[i]*sp_atoms[i]

atoms=np.array(atoms)
gas.TPX=args.temperature,args.pressure*ct.one_atm,refmultiindex
refquant=ct.Quantity(gas,moles=np.sum(refmultiindex)/ct.avogadro)
refenth=refquant.enthalpy
refentr=refquant.entropy
refenergy=refquant.int_energy
refmass=refquant.mass
refvol=refquant.volume
refpotentials=refquant.chemical_potentials
rstois=np.array(np.transpose(gas.reactant_stoich_coeffs()),dtype=int)
pstois=np.array(np.transpose(gas.product_stoich_coeffs()),dtype=int)


runtime1=0
runtime2=0
runtime3=0
runtime4=0
#Calculate the space of possible states