Skip to content

Add a Mie-Gruneisen equation-of-state backend - #1805

Open
sbryngelson wants to merge 2 commits into
MFlowCode:masterfrom
sbryngelson:feature/mie-gruneisen
Open

Add a Mie-Gruneisen equation-of-state backend#1805
sbryngelson wants to merge 2 commits into
MFlowCode:masterfrom
sbryngelson:feature/mie-gruneisen

Conversation

@sbryngelson

Copy link
Copy Markdown
Member

First step of the Mie-Gruneisen path in #1638: the backend and its maths, with nothing wired into the
solver yet. Every existing answer is bit-identical.

The mapping

Any Mie-Gruneisen equation of state, p = p_ref(rho) + rho Gamma_G (e - e_ref(rho)), is already MFC's
form rho e = Gamma p + Pi with

Gamma = 1/Gamma_G        Pi = rho e_ref - p_ref/Gamma_G

so the operators #1762 centralized need only the two coefficients plus dPi/drho for the sound speed.
Stiffened gas is the degenerate member, p_ref = -gamma pi_inf, e_ref = 0, Gamma_G = gamma - 1, which
reproduces the stored gammas(i) and pi_infs(i) exactly.

What is added

s_eos_coefficients(rho, i, gamma, pi_inf, dpi) - one dispatch on the fluid's EOS. The Mie-Gruneisen
case supplies a linear-Hugoniot reference curve, u_s = c0 + s u_p, extended linearly on release; a shared
conversion turns any reference curve into Gamma, Pi, dPi/drho. Adding JWL is one more case.
Stiffened and ideal gas return the constants resolved at init and never enter the per-cell path.

Parameters fluid_pp(i)%mg_rho0, mg_c0, mg_s, mg_G0, flat like gamma and pi_inf. The validator
requires all four under eos = 'mie_gruneisen', forbids them otherwise, requires positivity and s >= 1,
and forbids qv there because e_ref already carries the formation energy.

Gamma_G is constant, which is exact for JWL; the p dGamma/drho term is kept in the sound-speed
expression so a density-dependent form later is a one-function change.

Verification

  • toolchain/mfc/test_eos_mie_gruneisen.py, 30 checks, no solver run: reference-curve derivatives against
    central differences; the Gamma/Pi form inverting to the Mie-Gruneisen pressure to 1e-12; analytic
    c^2 = [((Gamma+1)p + Pi)/rho - dPi/drho]/Gamma against a numerically integrated isentrope to 1e-6;
    stiffened gas as the degenerate member; C^1 continuity of the reference curve at rho0.
  • 27 stiffened-gas cases across every Riemann solver, 6-equation, bubbles, chemistry, IBM, CBC and MHD:
    bit-identical.
  • Full toolchain pytest, 586 passed.

Deliberately not here

Solver wiring - per-cell evaluation in the mixture coefficients, the derivative terms in
f_bulk_modulus, Wood's law for N fluids, frozen mixing for Mie-Gruneisen under the five-equation
model - and the two validation problems, Hugoniot recovery and isentropic release as convergence cases.
Those follow in a second PR once this backend is reviewed. The reference curve has a pole at
rho/rho0 = s/(s - 1); the validator warning for it lands with the cases, since it needs the initial state.

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.

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Pull request overview

Adds a new Mie–Grüneisen EOS backend (linear-Hugoniot reference curve mapped to MFC’s rho e = Gamma p + Pi form), along with toolchain parameter support, validation, and math-focused tests, without wiring it into solver paths.

Changes:

  • Introduces EOS selector value mie_gruneisen + new fluid_pp%mg_* parameters (toolchain + Fortran derived types + initialization).
  • Adds s_eos_coefficients to compute (Gamma, Pi, dPi/drho) for Mie–Grüneisen while keeping stiffened/ideal behavior unchanged.
  • Adds a pytest suite to pin the reference-curve derivatives, mapping identity, and sound-speed relation.

Reviewed changes

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

Show a summary per file
File Description
toolchain/mfc/test_eos_mie_gruneisen.py New manufactured-math tests for the MG backend and mapping identity.
toolchain/mfc/params/definitions.py Registers EOS selector value 3 and new mg_* parameters for fluid_pp.
toolchain/mfc/case_validator.py Validates mg_* presence/absence and constraints; forbids qv for MG.
src/simulation/m_global_parameters.fpp Initializes new fluid_pp%mg_* fields to defaults.
src/pre_process/m_global_parameters.fpp Initializes new fluid_pp%mg_* fields to defaults.
src/post_process/m_global_parameters.fpp Initializes new fluid_pp%mg_* fields to defaults.
src/common/m_variables_conversion.fpp Adds device-side storage of EOS selectors/params and introduces s_eos_coefficients.
src/common/m_global_parameters_common.fpp Adds global arrays for EOS selectors/mg_* params + GPU_DECLARE.
src/common/m_derived_types.fpp Extends fluid_pp derived type with mg_* fields.
src/common/m_constants.fpp Adds eos_mie_gruneisen = 3 constant.

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

Comment on lines +1306 to +1315
real(wp) :: mu, d, p_ref, e_ref, dp_dmu, de_dmu, G0

select case (eoss(i))
case (eos_mie_gruneisen)
! Linear-Hugoniot reference curve, u_s = c0 + s u_p: p_H = rho0 c0^2 mu (1 + mu)/(1 - (s - 1) mu)^2 on
! compression, extended linearly on release, with the Hugoniot energy e_H = p_H mu/(2 rho0 (1 + mu)).
! Pole at mu = 1/(s - 1); the validator warns near it.
mu = rho/mg_rho0s(i) - 1._wp
if (mu >= 0._wp) then
d = 1._wp - (mg_ss(i) - 1._wp)*mu

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 that the comment claimed a warning that didn't exist in this PR - that was a deferred item I left documented as done. Fixed in 3ffde53: the comment now states the singularity plainly as a validity limit (mu = 1/(s - 1), the Hugoniot's maximum compression) with no runtime guard, and the validator gains an initial-state check that warns when any patch starts a Mie-Gruneisen fluid within 20% of rho0*s/(s - 1). A runtime clamp is deliberately not added: a state past the pole is outside the EOS, and clamping would return a wrong pressure silently - the same reasoning as #1793. The solver's per-step NaN check is the runtime backstop, and it only sees the Inf once it has become a NaN; that gap is real and now documented rather than implied to be closed.

Comment on lines +296 to +301
eoss(i) = fluid_pp(i)%eos
mg_rho0s(i) = fluid_pp(i)%mg_rho0
mg_c0s(i) = fluid_pp(i)%mg_c0
mg_ss(i) = fluid_pp(i)%mg_s
mg_G0s(i) = fluid_pp(i)%mg_G0
if (fluid_pp(i)%eos == eos_mie_gruneisen) any_state_dependent_eos = .true.

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.

Fixed in 3ffde53b. Also dropped the initializer, which made the flag an implicit save; it is now set at the top of init.

Comment thread src/common/m_derived_types.fpp Outdated
real(wp) :: mg_rho0 !< Mie-Gruneisen reference density
real(wp) :: mg_c0 !< Mie-Gruneisen bulk sound speed at mg_rho0
real(wp) :: mg_s !< Mie-Gruneisen linear Hugoniot slope, u_s = c0 + s u_p
real(wp) :: mg_G0 !< Mie-Gruneisen coefficient

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.

Renamed mg_G0 -> mg_gruneisen in 3ffde53b. The stronger reason than Gamma-vs-Gamma_G: fluid_pp%G is already the shear modulus, so mg_G0 sat one line from an unrelated G.

Comment thread toolchain/mfc/case_validator.py Outdated
"title": "Equation of State Selector",
"category": "Thermodynamic Constraints",
"math": r"\Pi_\infty = 0 \;\; \text{for an ideal gas}",
"math": r"\rho e = \Gamma(\rho)\,p + \Pi(\rho), \quad \Gamma = 1/\Gamma_G, \quad \Pi = \rho e_{\mathrm{ref}} - p_{\mathrm{ref}}/\Gamma_G",

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.

Fixed in 3ffde53b: Gamma is constant, Pi(rho) carries the density dependence, and the string now says exactly that.

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

Claude Code Review

Head SHA: a25b84d

Files changed:

  • 10
  • src/common/m_constants.fpp
  • src/common/m_derived_types.fpp
  • src/common/m_global_parameters_common.fpp
  • src/common/m_variables_conversion.fpp
  • src/post_process/m_global_parameters.fpp
  • src/pre_process/m_global_parameters.fpp
  • src/simulation/m_global_parameters.fpp
  • toolchain/mfc/case_validator.py
  • toolchain/mfc/params/definitions.py
  • toolchain/mfc/test_eos_mie_gruneisen.py

Findings:

  • src/common/m_variables_conversion.fpp: s_eos_coefficients computes the linear-Hugoniot reference curve with d = 1 - (mg_s(i)-1)*mu in the denominator (d*d, d*d*d); as mu -> 1/(s-1) this pole drives p_ref, e_ref, and therefore gamma/pi_inf/dpi to ±infinity with no bound or clamp, and would silently propagate Inf/NaN pressure into the solver. The added comment on that line states "the validator warns near it," but the check_eos_selector changes in toolchain/mfc/case_validator.py only validate that mg_rho0, mg_c0, mg_G0 are positive and mg_s >= 1 — there is no check bounding how close a run's density can get to the pole mu = 1/(s-1) (and this can't really be caught at case-validation time anyway, since mu depends on the runtime density, not the case parameters). This is exactly the "silently wrong answer" failure mode CLAUDE.md calls out: either add the guard the comment claims exists, or correct the comment so the unguarded singularity is documented as a known limitation rather than implied to be handled.

Any Mie-Gruneisen EOS p = p_ref + rho Gamma_G (e - e_ref) is MFC's rho e = Gamma p + Pi with Gamma = 1/Gamma_G and Pi = rho e_ref - p_ref/Gamma_G, so the existing operators need only the coefficients and dPi/drho. s_eos_coefficients is the single dispatch: the Mie-Gruneisen case supplies a linear-Hugoniot reference curve (u_s = c0 + s u_p, linear release) and one shared conversion produces Gamma, Pi and dPi/drho; a second family is one more case. Stiffened and ideal gas return the constants resolved at init, and no caller invokes the routine yet, so every existing answer is bit-identical - 27-case gate. Parameters mg_rho0, mg_c0, mg_s, mg_G0 follow the flat per-fluid style; the validator requires all four under mie_gruneisen, forbids them otherwise, and forbids qv there because e_ref carries the formation energy. Thirty pytest checks pin the maths against finite differences and a numerically integrated isentrope.
@sbryngelson

Copy link
Copy Markdown
Member Author

The pole finding in the Claude Code Review is addressed in 3ffde53b: the source comment no longer claims a guard that did not exist, and the validator now warns when a patch starts a Mie-Gruneisen fluid within 20% of the Hugoniot pole. Details in the reply to the matching Copilot thread.

@sbryngelson
sbryngelson force-pushed the feature/mie-gruneisen branch from a25b84d to 3ffde53 Compare September 2, 2026 23:32
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

Lines of Code

File Lines Diff
src/common/m_variables_conversion.fpp 1168 +40
src/common/m_derived_types.fpp 444 +4
src/common/m_global_parameters_common.fpp 243 +4
src/post_process/m_global_parameters.fpp 362 +4
src/pre_process/m_global_parameters.fpp 433 +4
src/simulation/m_global_parameters.fpp 752 +4
src/common/m_constants.fpp 88 +1
Directory Lines Diff
common 9995 +49
pre_process 4501 +4
simulation 27672 +4
post_process 3331 +4
total 45499 +61

@codecov

codecov Bot commented Sep 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 48.64865% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 62.24%. Comparing base (814f7a5) to head (420caf7).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
src/common/m_variables_conversion.fpp 24.00% 19 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1805      +/-   ##
==========================================
- Coverage   62.26%   62.24%   -0.03%     
==========================================
  Files          84       84              
  Lines       21558    21595      +37     
  Branches     3188     3196       +8     
==========================================
+ Hits        13423    13441      +18     
- Misses       5937     5956      +19     
  Partials     2198     2198              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants