A personal learning project on a simple question: how much of a turbulent flame survives when you reduce it to a few chemical reactors? I set it up as four steps, each with a check before the next. I built the CFD, built reactor networks from it, measured what the reduction throws away, and tested ways to put it back. The networks are scored against my own parent CFD. Only the CFD and the tabulated chemistry are scored against the experiment.
Reactor networks carry detailed chemistry at almost no cost. Our group’s RQL combustor model uses one [8]. That speed matters to me for a practical reason: I run everything on an ASUS TUF F15 laptop with an RTX 3050 Ti. A fine 3-D LES of a flame is out of reach, so reduced-order models are how I get detailed chemistry at all. Honestly, it sucks, but it also makes for a fun problem.
Sandia Flame D is the right test case. It is a piloted methane/air jet flame with temperature, species and velocity measured across the whole flame [1]. Other groups have also built reactor networks for it [6]. I planned four steps:
Every network result had to pass three checks. It must hold at the physical flow rate, use measured boundary conditions, and hold on data it was not fitted to. These checks turned out to be the most useful part of the project.

I set up a steady RANS simulation in OpenFOAM on a 5° axisymmetric wedge of 5,170 cells. It uses standard k–ε turbulence and the Eddy Dissipation Concept, with a 36-species GRI-3.0 subset [2, 3, 4]. The mesh is coarse on purpose, because the laptop has to solve it with detailed chemistry.

The four fields show the structure a network has to represent. Mixture fraction marks where fuel and air meet. The hot sheath sits on the stoichiometric surface. CO forms in a tongue on the rich side, and OH lives in a thin sheet where burnout happens.
Against the TNF measurements, velocity (centerline R² 0.93) and mixture fraction (R² 0.91) agree well. Temperature is too high by 283 K on average (R² 0.40) and worst at x/D = 15. I attribute this to the known tendency of k–ε to over-mix the near field. CO reaches only R² 0.20. This is therefore a converged baseline with a known near-field bias. Every surrogate inherits that bias, so I scored the networks against the CFD and kept the experiment as a separate check.
![Radial temperature and mixture fraction at five stations: the RANS/EDC solution (line) against the Barlow & Frank measurements [[1]] (circles).](fig/sandia-cfd-vs-tnf.png)
I cluster the cells into eight reactors. The reactor volumes come from the cell volumes, and the connections come from the CFD face fluxes. A turbulent Damköhler number sets each reactor as stirred or plug-flow [8]. The Method view at the top shows the two clustering choices I compared: by composition and by mass flow.
Any network has two built-in losses. A reactor computes chemistry only at its own mean state, and one interface carries one state for every cell face it replaces:
Chemistry at the mean is not the mean of the chemistry, because reaction rates are strongly nonlinear [9]. Exchange computed from two cluster means is not the sum of the face exchanges it replaces (\(K_f\) is the turbulent conductance of each face).

The three checks did their job. They caught three results that looked good for the wrong reasons:
Clustering by mass flow instead of composition removed the first problem, because the network then carried the real flow through the flame. The result is the network in the Result view: measured boundary fluxes, mass closed to 4×10⁻¹⁹ kg/s, no fitted parameters, and R²(T) = 0.71. That score is against the parent CFD. Most of the remaining error sits in two reactors.
These network scores are R² over eight cluster means at one operating condition, so one cluster can dominate them. They measure agreement with the parent CFD. Agreement with the experiment is a separate question.
Exchange between two clusters splits exactly into a part the network keeps (the difference of the cluster means) and a part it discards (how far each cluster’s edge state is from its own mean):
Exact to \(6.5\times10^{-19}\) kg/s. A cluster shows a different state to each neighbor, so no single mean can represent all of them.
The discarded part is large: the lumped model over-states the gradient at the interfaces by about 14×. A first-order reconstruction inside each cluster (P1) puts much of it back with no fitted parameter. I also gave the network the true edge states (an “oracle”) to see the ceiling.

P1 has limits. It is not bounded (one cluster solves at a slightly negative mixture fraction), and it is sensitive to its weighting. Mean-state reactors also have a hard limit: with realistic turbulent mixing between them, every reactor except the pilot extinguishes. R²(T) against the CFD falls from 0.71 to 0.39. Hot and cold starts give the same answer, so this is a real fixed point of the model. Within the network family I tested, mean-state reactors cannot represent this flame at realistic mixing rates.
The other way to recover what averaging loses is to never compute chemistry at a mean. I tabulated well-stirred-reactor solutions in mixture fraction and residence time. Then I averaged them over a presumed β-PDF and blended fresh and burnt states with a progress variable [5]:
β-PDF average over the mixture-fraction fluctuations, and the blend between unburnt and burnt states with progress variable \(c\).

Four table versions raised temperature agreement with the experiment from R² 0.40 to 0.61 (0.57 when each measurement station is held out). CO did not follow. It reached 0.18, just below the EDC baseline of 0.20.
These are a-priori tests. I applied the table to the frozen CFD fields, and its progress variable comes from the CFD species. The table is therefore a conditioned reconstruction. It also uses one calibrated constant, and its grid in mixture fraction and residence time is not converged.

My explanation for the CO failure comes from reactor calculations. I have not proven it. CO rises past its burnt value before it burns out, almost all through CO + OH → CO₂ + H. At the CO peak, OH sits at 2.4× its equilibrium value. A surrogate that assumes an equilibrium burnt state therefore uses the wrong radicals. Coarse networks also average away this produce-then-consume structure. Published work on this flame needs hundreds to thousands of reactors to resolve CO [7].
Tracking down that explanation was the best part of the project. I think it is kind of sick that one reaction path accounts for so much of the failure.
A learned model can predict the discarded edge states inside this flame (skill 0.86), but it fails on an axial region it has not seen (−0.12). For that reason, I did not use a learned closure. All results here are for one flame at one operating condition.