Skip to content

[PH-Flash] Add mixture enthalpy models with cited caloric data and baseline flash tests - #5297

Open
arturcastiel wants to merge 5 commits into
OPM:masterfrom
arturcastiel:mixture-enthalpy-foundation
Open

[PH-Flash] Add mixture enthalpy models with cited caloric data and baseline flash tests#5297
arturcastiel wants to merge 5 commits into
OPM:masterfrom
arturcastiel:mixture-enthalpy-foundation

Conversation

@arturcastiel

Copy link
Copy Markdown
Member

The compositional path in opm-common cannot evaluate the enthalpy of a flashed mixture. This PR adds that capability — the groundwork for an isenthalpic (P–H) compositional flash, which follows in a separate PR.

What this adds

  • ComponentCp — cubic ideal-gas heat-capacity polynomial and its closed-form enthalpy integral. The coefficients live on the component classes (C1, C10, SimpleCO2) as cited identity cards, each fitted to the species' reference EoS (Setzmann & Wagner 1991; Lemmon & Span 2006; Span & Wagner 1996) over 250–600 K, with cross-checked triple points.
  • IdealGasCaloricData — the shared enthalpy datum (H = 0 at 298.15 K) and a name-keyed lookup of the cards. Unknown components throw instead of silently receiving another species' data.
  • MixtureEnthalpy — molar enthalpy of a flashed state under two models: caloric (ideal-gas; independent of the phase split by material balance) and eos_departure (adds the per-phase residual H_res = -R T² Σ w_i ∂lnφ_i/∂T). The temperature derivative is computed by automatic differentiation: temperature is seeded as a one-variable DenseAd::Evaluation and ∂lnφ_i/∂T is read from the fluid system's own fugacityCoefficient — no hand-derived EoS calculus, so every EoS variant the fluid system supports is covered. The AD is internal to this evaluation; results are plain values.
  • Baseline tests for the existing isothermal flash on a new synthetic two-component (C1/nC10) fixture: phase labels, material balance, equal fugacity, K-consistency, and ssi/newton/ssi+newton parity.

Testing

About 65% of the diff is tests:

  • every heat-capacity card is pinned against tabulated reference-EoS values, so a corrupt coefficient row fails loudly instead of passing self-consistent checks;
  • the AD derivative is verified against an independent finite difference of lnφ, per phase and per component (the seam phaseDLnPhiDT exists for exactly this);
  • ideal-gas limit of the residual, split-cancellation and monotonicity of the caloric model, the reference datum, and the model-name parser.

Additive only — no existing behavior changes.

Introduce a test-local two-component (methane/n-decane) Peng-Robinson
fluid system and a data-driven case harness (FlashCase/runFlash) that
applies the full PTFlash input contract, and pin the isothermal flash
on it: single-phase labels, two-phase invariants (material balance,
equal fugacity, K-consistency) and iteration-method parity (ssi,
newton, ssi+newton). A ternary case reuses the in-tree
ThreeComponentFluidSystem.
ComponentCp holds the species-blind caloric equations: a cubic
ideal-gas heat-capacity polynomial and its closed-form enthalpy
integral, zero at the reference datum. The coefficients live on the
component classes (C1, C10, SimpleCO2) next to the species' other
constants, each fitted to the ideal-gas part of the cited reference
EoS over 250-600 K, with CoolProp-cross-checked triple points added
alongside. A pin suite guards every card against tabulated
reference-EoS values, so a corrupt coefficient row fails loudly
instead of passing self-consistent tests.
…arture

IdealGasCaloricData owns the shared enthalpy reference datum and the
deck-style name lookup over the component caloric cards; unknown
components fail loudly rather than receive somebody else's heat
capacity. MixtureEnthalpy evaluates the molar enthalpy of a flashed
compositional state behind a two-model seam: the caloric (ideal-gas)
model, where the phase split cancels exactly by material balance, and
the EoS-consistent departure model, where the residual enthalpy is
obtained per phase from AD temperature-derivatives of the fluid
system's own fugacity coefficients — no hand-derived EoS calculus.
Tests cover monotonicity, the reference datum, analytic cp against a
finite difference, split-cancellation, the AD derivative against a
finite difference of ln(phi), the ideal-gas limit, split coupling of
the departure model, and the shared model-name parser.
@arturcastiel
arturcastiel marked this pull request as draft August 17, 2026 12:13
@arturcastiel

Copy link
Copy Markdown
Member Author

jenkins build this please

@arturcastiel arturcastiel added manual:enhancement This is an enhancement/improvent that needs to be documented in the manual and removed enhancement labels Aug 17, 2026
@akva2

akva2 commented Aug 17, 2026

Copy link
Copy Markdown
Member

jenkins build this please

2 similar comments
@akva2

akva2 commented Aug 18, 2026

Copy link
Copy Markdown
Member

jenkins build this please

@akva2

akva2 commented Aug 18, 2026

Copy link
Copy Markdown
Member

jenkins build this please

@arturcastiel

Copy link
Copy Markdown
Member Author

@akva2 thank you.

@arturcastiel
arturcastiel marked this pull request as ready for review August 18, 2026 09:45
@arturcastiel
arturcastiel requested a review from GitPaean August 18, 2026 09:45
@GitPaean
GitPaean requested a balanced review from Copilot August 19, 2026 07:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds compositional mixture-enthalpy evaluation as groundwork for P–H flash support.

Changes:

  • Adds ideal-gas heat-capacity data and enthalpy integrals.
  • Implements caloric and EoS-departure mixture enthalpy models.
  • Adds binary flash fixtures and baseline tests.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
CMakeLists_files.cmake Registers headers and tests.
opm/material/components/C1.hpp Adds methane caloric and triple-point data.
opm/material/components/C10.hpp Adds decane caloric and triple-point data.
opm/material/components/ComponentCp.hpp Defines heat-capacity polynomial integration.
opm/material/components/SimpleCO2.hpp Adds CO₂ caloric data.
opm/material/constraintsolvers/IdealGasCaloricData.hpp Provides caloric presets and name lookup.
opm/material/constraintsolvers/MixtureEnthalpy.hpp Implements mixture enthalpy models.
tests/material/flashTestFixtures.hpp Adds shared compositional flash fixtures.
tests/material/test_mixture_enthalpy.cpp Tests caloric and departure behavior.
tests/material/test_twocomponents_ptflash.cpp Adds P–T flash baseline tests.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

* there is deliberately NO silent fallback — an unknown component must
* fail loudly rather than receive somebody else's heat capacity.
*/
static ComponentCp<Scalar> byName(const std::string_view name)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added ByNameAliasesAndUnknownName to test_mixture_enthalpy.cpp: every documented alias is pinned coefficient-wise against its card (mixed-case spellings included), and unknown/empty names are checked to throw. In 2e64598.

Comment on lines +292 to +299
FluidSystemF1::ParameterCache<double> paramCache(EOSType::PR);
paramCache.updatePhase(fs, phaseIdx);
return std::log(FluidSystemF1::fugacityCoefficient(fs, paramCache, phaseIdx, compIdx));
};

const double T = Opm::FlashTest::f1Temperature;
for (int compIdx = 0; compIdx < numComponentsF1; ++compIdx) {
const double ad = EnthalpyF1::phaseDLnPhiDT(outcome.state, phaseIdx, compIdx, EOSType::PR);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — the AD-vs-FD check now loops over PR, PRCORR, SRK and RK, passing the EoS type through both the scalar finite-difference path and phaseDLnPhiDT. The flashed composition is only a probe point (the AD == FD identity holds at any state), so the one state serves every EoS. In 2e64598.

Comment thread tests/material/flashTestFixtures.hpp Outdated
Comment on lines +90 to +93
//! C1/nC10 Peng-Robinson binary interaction parameter — the value this
//! library's compositional tests use (cf. ThreeComponentFluidSystem). The
//! unequal-index shortcut in interactionCoefficient() is valid only
//! because the system is binary.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right — interactionCoefficient() there returns 0.0 for every pair and cannot establish this value. Reworded: 0.0411 is a pinned fixture value within the range of published C1/nC10 PR coefficients (roughly 0.04-0.05, source-dependent); the two-phase baselines built on it were cross-validated against an independent PR implementation (CoolProp) using this same value. Value unchanged. In 55a10ee.

…alpy tests

Review follow-up on the mixture-enthalpy tests. byName() promises
case-insensitive deck-style aliases and a loud throw on unknown
components, but neither promise was exercised; and the AD-vs-finite-
difference derivative check ran only under PR while the alpha-function
temperature dependence branches per EoS type. Pin every documented
alias coefficient-wise plus the unknown-name throw, and run the
derivative identity over PR, PRCORR, SRK and RK — the flashed
composition is only a probe point, so the one state serves every EoS.
The comment pointed at ThreeComponentFluidSystem::interactionCoefficient(),
which returns zero for every pair and so cannot establish 0.0411. State
the actual provenance instead: a pinned fixture value within the range
of published C1/nC10 PR coefficients, cross-validated against an
independent PR implementation with this same value. Value unchanged.
@arturcastiel

Copy link
Copy Markdown
Member Author

Addressed all three review findings: alias + unknown-name coverage for the caloric-data lookup and the AD temperature-derivative check now running over all four supported EoS types (2e64598), plus a corrected provenance comment on the C1/nC10 interaction coefficient (55a10ee). Test-only changes.

@arturcastiel

Copy link
Copy Markdown
Member Author

jenkins build this please

@arturcastiel

Copy link
Copy Markdown
Member Author

@akva2 is there a reason why I cannot call jenkins?

@akva2

akva2 commented Aug 20, 2026

Copy link
Copy Markdown
Member

github is being troublesome and queues up my api calls and stalls for 30m-1h at times. it will likely trigger, it just takes time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

manual:enhancement This is an enhancement/improvent that needs to be documented in the manual

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants