oemof / tespy

Thermal Engineering Systems in Python (TESPy). This package provides a powerful simulation toolkit for thermal engineering plants such as power plants, district heating systems or heat pumps.
https://tespy.readthedocs.io
MIT License
272 stars 85 forks source link

Add n-Dodecane to combustion chamber component #272

Closed IdoMarzel closed 3 years ago

IdoMarzel commented 3 years ago

Hi!

I'm trying to model an aviation jet-prop, which uses Jet A-1 fuel, using TESPy.

Using n-Dodecane C12H26 instead of Jet A should be good enough, and it's included in CoolProp, however the combustion chamber component does not support it.

I've tried to add it myself, by adding it to the list of allowable fuels in combustion_chamber.setup_reaction_parameters, and adding the enthalpy of formation hf['Dodecane'] = -352.1 to combustion_chamber.calc_lhv. The LHV calculation was pretty good, got ~44 MJ/kg.

When running a simple model with source --> compressor --> combustion chamber --> sink, the calculation can't seem to converge, no matter the starting conditions, so I guess I'm missing something else (the same model works with CH4 just fine).

What else is missing that will enable me to use this fuel in the model?

fwitte commented 3 years ago

Hi, thank you for your suggestion. Currently the fuels allowed for combustion were restricted (to what I frequently used, I guess). I'll add the fuel to the component and let you know once finished. Also, a warning might be useful to indicate this. Best regards

fwitte commented 3 years ago

P.S.: Can you provide the Python code you are trying to run?

IdoMarzel commented 3 years ago

Sure! Thanks for being this quick!

I just got it to work. It's something to do with the starting temperature of the fuel source. If I set it to 15 °C, it won't converge, but at 25 °C it will. Code below for the model that does converge. tespyi is a copy of your library with the changed combustion chamber component to add Dodecane:

from tespyi.networks import Network
from tespyi import components
from tespyi.connections import Connection, Bus, Ref
from tespyi.tools.characteristics import CharLine
from tespyi.tools import document_model
import numpy as np

# KEY PARAMETER
eta_b = 0.99 # burn efficiency
m = 2.75 #mass flow in kg/s
Q = 2387579.829*eta_b # inserted heat in Watts

fluid_list = ['Ar', 'N2', 'O2', 'CO2', 'n-C12H26', 'H2O']
fuel_fraction = 0.977

nw = Network(fluids=fluid_list,
             p_unit='bar', T_unit='C', h_unit='kJ / kg', m_unit='kg / s')

# %% Components

compressor = components.Compressor('compressor')
comb_chamber = components.CombustionChamber('combustion chamber')

fuel_in = components.Source('fuel source')
air_in = components.Source('ambient air')
air_out = components.Sink('exhaust')

# %% Connections

air_in__compressor = Connection(air_in, 'out1', compressor, 'in1')
compressor__comb_chamber = Connection(compressor, 'out1', comb_chamber, 'in1')
comb_chamber__air_out = Connection(comb_chamber, 'out1', air_out, 'in1')

fuel_in__comb_chamber = Connection(fuel_in, 'out1', comb_chamber, 'in2')

nw.add_conns(air_in__compressor,
             compressor__comb_chamber,
             comb_chamber__air_out,
             fuel_in__comb_chamber)

# %% Component parameters
compressor.set_attr(pr=6.55, eta_s=0.8,
                    design=['pr', 'eta_s'],
                    offdesign=['eta_s_char'])
comb_chamber.set_attr(ti=Q)

# %% Connection parameters
# ['Ar', 'N2', 'O2', 'CO2', 'n-C12H26', 'H2O']
air_in__compressor.set_attr(
    T=15, p=1.01325, m=m,
    fluid={'Ar': 0.0129, 'N2': 0.7553, 'H2O': 0, 'CO2': 0.0004, 'O2': 0.2314, 'n-C12H26': 0},
    design=['m'])

fuel_in__comb_chamber.set_attr(
    T=25,
    m0=0.001,
    fluid={'Ar': 0, 'N2': 0, 'H2O': 0, 'CO2': 1 - fuel_fraction, 'O2': 0, 'n-C12H26': fuel_fraction})

# %%
fmt = {
    'latex_body': True,  # adds LaTeX body to compile report out of the box
    'include_results': True,  # include parameter specification and results
    'Compressor': {
        'params': ['P', 'eta_s', 'pr']},
    'HeatExchanger': {  # for components of class HeatExchanger
        'params': ['Q', 'ttd_l', 'ttd_u', 'pr1', 'pr2']},  # change columns displayed
    'Condenser': {  # for components of class HeatExchanger
        'params': ['Q', 'ttd_l', 'ttd_u', 'pr1', 'pr2'],
        'float_fmt': '{:,.2f}'},  # change float format of data
    'Connection': {  # for Connection instances
        'p': {'float_fmt': '{:,.2f}'},  # change float format of pressure
        's': {'float_fmt': '{:,.2f}'},
        'h': {'float_fmt': '{:,.2f}'},
        'params': ['m', 'p', 'h', 's', 'state'],  # list results of mass flow, ...
        'fluid': {'include_results': True}  # include results of fluid composition
                    },
    'draft': False  # disable draft mode
    }

nw.solve(mode='design')
nw.print_results()
nw.save('design_point')
document_model(nw, filename='report_design.tex', fmt=fmt)
fwitte commented 3 years ago

I already linked a PR, see #273. So you'll be able to use that version of tespy if you like to (check out the feature/combustion_fuels branch). Next time you can of course fork this repo, make the changes and upload to your fork on github, then the PR can be started form there (and you do not need to rename the package ;)).

As I never really used fuels in liquid state, I need to double check, if the energy balance is solved correctly. Or did you that already? There is also another issue: The equations of state implemented in TESPy do not yet support liquid-gas binary mixtures. Thus, I am not sure, whether the mixture state of CO2 and nDodecane is computed correctly (I would be surprised actually...).

fwitte commented 3 years ago

I checked your code, thanks for providing it. It indeed is a starting value issue. You can however run the 15 °C case, if you run based on the 25 °C solution. Simply add

fuel_in__comb_chamber.set_attr(T=15)
nw.solve(mode='design')
nw.print_results()

at the end of your script.

Generating generic starting values is not very robust at the moment, this is one of the major tasks regarding improvements of the software :).

IdoMarzel commented 3 years ago

That's amazing, thanks!

re: energy balance, I did not check it yet. I have some preliminary calculations, and they give results in the same area as the model's results +-15 °C, but they're not very accurate either so I can't tell which is right. It's in the ballpark, though.

The fuel is likely coming in hotter than that, I just used 15 °C as a starting point to see if the model works at all, following the combined cycle example.

fwitte commented 3 years ago

Hi @IdoMarzel, I checked the energy balance:

grafik

Due to the change of composition, a common reference state must be used for the different fluids entering and leaving the combustion chamber (25 °C, 1 bar). For water, the heat of formation of water vapor instead of liquid is used to calculate the LHV. Therefor, the water in the flue gas reference state must as well be in vapor state. Depending on the amount of water, this is not necessarily the case (if saturation temperature at partial pressure of the water is lower than the reference state), therefore all fluids are forced gaseous.

https://github.com/oemof/tespy/blob/dev/src/tespy/components/combustion/combustion_chamber.py#L780-L786

This has been the case for the inlet reference state, too. However, I am not sure, if this restriction can, should or even must be discarded for the inlet states. In the current state, the heat of formation for gaseous nDodecane (288.1) must be used instead of liquid (349.3) according to NIST data https://webbook.nist.gov/cgi/cbook.cgi?ID=C112403&Mask=1EFF#Thermo-Gas.

I'll try to check back with some colleagues as I am not fully sure, what the correct solution is. However, using force_gas=False on the inlet state with the liquid heat of formation yields the same combustion chamber outlet temperature as force_gas=True with the formation enthalpy of gaseous nDodecane (given same lambda and fuel mass flow). Both ways seem possible, but regarding the lower heating value, the liquid state as reference seems to be the way to go.

Do you by chance have more insight here?

Best regards Francesco

IdoMarzel commented 3 years ago

Hi @fwitte!

Since LHV in literature is calculated with standard sea-level conditions, they'll use the liquid state for calculations. But for our needs, I don't think it matters much.

If it works without forcing gas state, then the advantage can be in terms of using measured volumetric flow at the inlet, or something along those lines. Otherwise, at least for myself as a user, I don't see a difference between force_gas=False with liquid Hf or force_gas=True and gaseous Hf.

If there is a simple way for the CombustionChamber to use the correct LHV based on the inlet fuel's state, that would of course be ideal, but if that's not possible then maybe it's better to use force_gas=True to be sure that the LHV value is correct?

fwitte commented 3 years ago

Hi, just wanted to let you know, that I am currently somewhat out of office. I will take car of the PR next week :). Best regards, have a nice day

fwitte commented 3 years ago

Hi, I added the fuel with gaseous reference state for now. Updated version of TESPy will go live later today. Best regards Francesco