Skip to content

Add nox generation in combustion#904

Merged
fwitte merged 38 commits into
oemof:devfrom
HaSchneider:add-Nox-generation-in-combustion
May 5, 2026
Merged

Add nox generation in combustion#904
fwitte merged 38 commits into
oemof:devfrom
HaSchneider:add-Nox-generation-in-combustion

Conversation

@HaSchneider
Copy link
Copy Markdown
Contributor

This pull request implements optional NO creation in combustion component. When the f_nox parameter is set, NO is created in the combustion, as long as enough oxygen and nitrogen is available. f_nox is the ratio of mass flow of created NO in relation to the fuel mass flow.

But there are still some issues...

Issues:

  1. coolprop does not have NO fluid implemented

  2. combustion component does not allow other fluid property engines than coolprop. I solved that as described in Not possible to use other fluid property engines than coolprop in combustion component #887.

  3. Pyromat wrapper can be used instead, but:

    • Pyromat NO fluid does not include T_crit and p_crit values.
    • it must be defined manually

    I solved that in the example by creating my own pyromat wrapper with the needed values and by adding a dummy NO flow in the inputs with the corresponding pyromat wrapper as fluid property engine. I think it would be better if this can be done automaticaly in the combustion component, but I have no idea how.

  4. following components might fail, due to missing fluid properties in the pyromat wrapper engine. This is demonstrated in the test_CombustionChamber_NO. I think this cant be solved proper as long as pyromat does not contain all needed properties and coolprop does not contain NO. So missing properties must be added manualy to the pyromat wrapper.

Example

from tespy.components import (
    Source, Sink, 
    SimpleHeatExchanger, 
    DiabaticCombustionChamber,
)
from tespy.tools.fluid_properties.wrappers import PyromatWrapper

from tespy.connections import Connection

from rva_classes import ModelTemplate

class my_PyromatWrapper(PyromatWrapper):
    def _set_constants(self):
        self._p_min, self._p_max = 100, 1000e5
        self._T_crit, self._p_crit = 180.15, 6400000 #self.AS.critical() not supported by pyromat
        self._T_min, self._T_max = self.AS.Tlim()
        self._molar_mass = self.AS.mw()



class create_solvent_combustion(ModelTemplate):
        
    def _create_network(self) -> None:
        super()._create_network()
        amb = Source('ambient air')
        sf = Source('fuel')
        fg = Sink('flue gas outlet')
        self.comb = DiabaticCombustionChamber('combustion chamber')
        self.hex = SimpleHeatExchanger('heat exchanger')
        
        
        self.amb_comb = Connection(amb, 'out1', self.comb, 'in1')
        self.sf_comb = Connection(sf, 'out1', self.comb, 'in2')
        self.comb_hex = Connection(self.comb, 'out1', self.hex, 'in1')
        self.hex_fg = Connection(self.hex, 'out1', fg, 'in1')
        self.nw.add_conns(self.sf_comb, self.amb_comb, self.comb_hex, self.hex_fg, 
        )
        self.comb.set_attr(ti=500000, pr=0.95, eta=1, lamb=4, f_nox= 0.00025)
        self.amb_comb.set_attr(
            p=1.2, T=20,
            fluid={'Ar': 0.0129, 'N2': 0.7553, 'CO2': 0.0004, 'O2': 0.2314, 'ig::NO':0},
            fluid_engines={"NO": my_PyromatWrapper}, 
        )
        self.sf_comb.set_attr(
            p=1.3, T=25, fluid={'CO2': 0.03, 'H2': 0.01, 'CH4': 0.96, 'ig::NO':0},
            fluid_engines={"NO": my_PyromatWrapper}, 
        )
        
        
        self.hex.set_attr(pr=0.95)

        #self.comb_hex.set_attr(T=1200)
        self.hex_fg.set_attr(T=200)

rva= create_solvent_combustion()

rva.nw.solve('design')
print(rva.comb_hex.fluid.val)
{'CO2': 0.03923764451245059, 
'Ar': 0.012711828022584415, 
'H2': 0.0, 
'N2': 0.7442833087203439, 
'NO': 1.8229232332386296e-06, 
'O2': 0.17101940248021757, 
'H2O': 0.03274599334117038, 
'CH4': 0.0}
  • Documentation
  • Implement an example and a system test

@fwitte
Copy link
Copy Markdown
Member

fwitte commented Feb 7, 2026

Hi @HaSchneider, thank you very much for bringing this up, very cool addition! I will review it in the next weeks :)

@fwitte fwitte mentioned this pull request Apr 19, 2026
4 tasks
@fwitte
Copy link
Copy Markdown
Member

fwitte commented Apr 24, 2026

The open todos are now:

  • somehow implant the NO stream in the outlet that uses a PyromatWrapper (this can be hardcoded for now, but should be done flexibly)
  • correct the energy balance equation by considering endothermal reaction of N2 and O2 to NO

Comment thread src/tespy/components/combustion/base.py Outdated
Comment thread src/tespy/components/combustion/base.py Outdated
@fwitte
Copy link
Copy Markdown
Member

fwitte commented May 4, 2026

Thank you for the additions, I will add one more test and then everything looks good!

Update @HaSchneider: Test fails, I guess I did something wrong or there is maybe a typo in the stoichiometry formulation? I'll have a look in the coming days. If you see it before me feel free to post it here :)

@HaSchneider
Copy link
Copy Markdown
Contributor Author

I fixed one sign error in the stoichiometry formulation. The test_CombustionChamberNO seems to work now. But there are other tests which fail. It seems to have something to do with the exergy calculation, but two of the tests not even use a combustion component.

@fwitte
Copy link
Copy Markdown
Member

fwitte commented May 5, 2026

I fixed one sign error in the stoichiometry formulation. The test_CombustionChamberNO seems to work now. But there are other tests which fail. It seems to have something to do with the exergy calculation, but two of the tests not even use a combustion component.

Thank you. The other two tests are related to a different issue with API incompatibility of the new HeatConnection to exerpy. The can be left to fail for now... :)

@fwitte fwitte merged commit 9fb2786 into oemof:dev May 5, 2026
5 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants