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
def test_incompatible(self): gas2 = ct.Solution('h2o2.xml') q1 = ct.Quantity(self.gas) q2 = ct.Quantity(gas2) with self.assertRaises(ValueError): q1 + q2
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)
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)
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)
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
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)
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])
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
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
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
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
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
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
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
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
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
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)
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
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
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())
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