Follow-up to #1821, which added heterogeneous surface chemistry. Not a defect in that PR — a structural observation about where its code ended up.
The asymmetry
For the gas phase, MFC's toolchain generates Fortran in one line (toolchain/mfc/run/input.py:516):
thermochem_code = pyro.FortranCodeGenerator().generate("m_thermochem", sol, ...)
For the surface phase, #1821 added ~400 lines of hand-written Fortran emitted by string concatenation (generate_surface_thermochem, input.py:141-560). It produces get_surface_net_production_rates and get_surface_reaction_heat_flux — the direct analogues of pyrometheus's own get_net_production_rates.
That is a code generator for Cantera mechanisms living in a CFD solver's build toolchain.
Why this matters beyond tidiness
nongas_h_rt_expressions (input.py:240-264) takes a Cantera species' coeffs, splits it at tmid into low/high ranges, and evaluates the NASA 7-coefficient enthalpy polynomial — reimplementing what pyrometheus already generates as get_species_enthalpies_rt, only for bulk/surface species, because pyrometheus does not know those exist.
Two bugs already came out of that duplicated surface: a hasattr(rate, "pre_exponential_factor") guard that silently accepted sticking-coefficient rates and emitted them as plain Arrhenius (wrong by orders of magnitude — a sticking coefficient is a dimensionless probability, not a prefactor), and silently-dropped coverage dependencies. Both are fixed, but they are the failure mode of maintaining a second, partial chemistry code generator.
What would move upstream
ct.Interface loading and phase resolution
- Interface-Arrhenius rate expressions with explicit reaction orders
- Sticking-coefficient conversion:
gamma/(1 - gamma/2) * sqrt(RT/(2*pi*W)) / site_density^n
- Blowers-Masel rates (activation energy shifted by reaction enthalpy at runtime)
- Coverage-dependent rates
- NASA thermo for bulk/surface species
I checked pyrometheus (installed version): no surface support — ct.Interface, InterfaceKinetics, coverage and sticking have zero hits outside an unrelated flamelets/ module. So this is a genuine upstream feature, not a port.
It also belongs there on the merits: sticking-coefficient conversion and Blowers-Masel shifts are properties of a Cantera mechanism, not of MFC. Any pyrometheus consumer doing catalysis or ablation wants them.
Payoff
toolchain/mfc/run/input.py loses ~400 lines and goes back to delegating both phases. The surface generator gets pyrometheus's own test suite instead of MFC's integration tests as its only coverage.
Sequencing: this should land upstream before the MFC-side splits (#TBD), since it deletes the most code.
Tracked in #1893.
Follow-up to #1821, which added heterogeneous surface chemistry. Not a defect in that PR — a structural observation about where its code ended up.
The asymmetry
For the gas phase, MFC's toolchain generates Fortran in one line (
toolchain/mfc/run/input.py:516):For the surface phase, #1821 added ~400 lines of hand-written Fortran emitted by string concatenation (
generate_surface_thermochem,input.py:141-560). It producesget_surface_net_production_ratesandget_surface_reaction_heat_flux— the direct analogues of pyrometheus's ownget_net_production_rates.That is a code generator for Cantera mechanisms living in a CFD solver's build toolchain.
Why this matters beyond tidiness
nongas_h_rt_expressions(input.py:240-264) takes a Cantera species'coeffs, splits it attmidinto low/high ranges, and evaluates the NASA 7-coefficient enthalpy polynomial — reimplementing what pyrometheus already generates asget_species_enthalpies_rt, only for bulk/surface species, because pyrometheus does not know those exist.Two bugs already came out of that duplicated surface: a
hasattr(rate, "pre_exponential_factor")guard that silently accepted sticking-coefficient rates and emitted them as plain Arrhenius (wrong by orders of magnitude — a sticking coefficient is a dimensionless probability, not a prefactor), and silently-dropped coverage dependencies. Both are fixed, but they are the failure mode of maintaining a second, partial chemistry code generator.What would move upstream
ct.Interfaceloading and phase resolutiongamma/(1 - gamma/2) * sqrt(RT/(2*pi*W)) / site_density^nI checked pyrometheus (installed version): no surface support —
ct.Interface,InterfaceKinetics, coverage and sticking have zero hits outside an unrelatedflamelets/module. So this is a genuine upstream feature, not a port.It also belongs there on the merits: sticking-coefficient conversion and Blowers-Masel shifts are properties of a Cantera mechanism, not of MFC. Any pyrometheus consumer doing catalysis or ablation wants them.
Payoff
toolchain/mfc/run/input.pyloses ~400 lines and goes back to delegating both phases. The surface generator gets pyrometheus's own test suite instead of MFC's integration tests as its only coverage.Sequencing: this should land upstream before the MFC-side splits (#TBD), since it deletes the most code.
Tracked in #1893.