Skip to content

Evaluate Mie-Gruneisen coefficients per cell along the 5-equation path - #1809

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

Evaluate Mie-Gruneisen coefficients per cell along the 5-equation path#1809
sbryngelson wants to merge 6 commits into
MFlowCode:masterfrom
sbryngelson:feature/mie-gruneisen-solver

Conversation

@sbryngelson

Copy link
Copy Markdown
Member

Stacked on #1805 (the backend) and overlapping #1808 (the ideal-gas cleanup); review the last three commits. Third step of #1638.

What changes. When any fluid's equation of state is state dependent, the mixture loop in s_compute_mixture_coefficients evaluates s_eos_coefficients per phase at that phase's own density; the stiffened-gas arithmetic is untouched, and the existing 27-case gate is bit-identical. s_compute_speed_of_sound takes the partial densities as an optional trailing argument and, under the same flag, mixes frozen per-phase moduli with the derivative term -rho_i Pi_i'/Gamma_i applied at that one site, so f_bulk_modulus and its twenty other callers do not change. The Riemann kernels, the cell-state helper and the post-process energy integral pass the densities through; everything that cannot is refused by the validator (5-equation model, HLL/HLLC/LF, no bubbles, hypoelasticity, IBM, IGR, relativity, MHD, chemistry, acoustic source, probes, post-process c, characteristic BCs or Wood's law). Those fences come out one by one in follow-ups; the 6-equation model needs the phasic isentrope generalized first and is its own PR.

Parameter ownership. A Mie-Gruneisen fluid has neither gamma, pi_inf nor qv and an ideal gas has no pi_inf; the validator refuses them, the suite's base fluid and every example drop the dead values, and all 744 test definitions validate. The reference-curve maths moves into toolchain/mfc/eos.py, one definition shared by the unit tests and the validation runners.

Validation (both registered as convergence-kind tests):

  • 1D_mg_impact: symmetric impact of two slabs; shock speed and plateau density match the Hugoniot u_s = c0 + s u_p to 1.4e-3 across four closing speeds (bound 5e-3).
  • 1D_mg_acoustic: a small simple-wave pulse travels at the analytic c to 1.9e-4 (bound 1e-3). This is the one observable that isolates the derivative term: without it the speed is 24% off.
  • Golden 5AC2F65D: a Mie-Gruneisen fluid beside an ideal gas, so one kernel carries both paths.

Also deletes the gamma = gammas(1) block in both output routines, which was assigned and never read.

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.
A Mie-Gruneisen fluid has neither gamma, pi_inf nor qv, and an ideal gas has no pi_inf: the validator now refuses them, and the suite's base fluid and every example drop the dead values. The ideal-gas half duplicates MFlowCode#1808 and drops out once it merges.
The mixture loop calls s_eos_coefficients per phase when any fluid's EOS is state dependent; the stiffened-gas arithmetic is untouched (27/27 bit-identical on the gate). The sound speed takes the partial densities as an optional argument and mixes frozen per-phase moduli, with the derivative term applied at that one site. Callers that cannot supply them are refused by the validator: 5-equation, HLL/HLLC/LF only, no bubbles, hypoelasticity, IBM, IGR, relativity, MHD, chemistry, acoustic source, probes, post-process c, characteristic BCs or Wood's law. Validation: symmetric-impact shock speed and plateau density match the Hugoniot to 1.4e-3, and a small pulse travels at the analytic sound speed to 1.9e-4 (the missing derivative term would give 24%).
gamma = gammas(1) and friends were assigned and never read; lit_gamma was assigned in both output routines and read in neither.
Copilot AI lite review requested due to automatic review settings September 3, 2026 01:57

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

This PR extends the 5-equation path to support state-dependent EOS coefficients (Mie–Grüneisen) by evaluating EOS coefficients per phase at each cell’s phasic density, updating sound-speed mixing accordingly, and tightening parameter ownership/validation (e.g., ideal gas no longer “accepts” pi_inf).

Changes:

  • Add Mie–Grüneisen EOS selector/parameters and implement per-phase, per-cell EOS coefficient evaluation plus frozen-modulus mixture sound speed with the derivative term.
  • Update case validation and tests (new unit/manufactured tests + convergence tests + new MG examples) and introduce a golden kernel covering mixed MG/ideal-gas paths.
  • Remove redundant/forbidden ideal-gas pi_inf settings across examples and test configs; harden coverage tooling’s git invocations.

Reviewed changes

Copilot reviewed 148 out of 148 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
toolchain/mfc/test_eos_mie_gruneisen.py Adds manufactured/unit checks for MG reference curve mapping and sound-speed identity.
toolchain/mfc/test_case_validator.py Adds validator tests specifically for MG selection/constraints and ideal-gas pi_inf behavior.
toolchain/mfc/test/test_coverage_unit.py Uses shared git-env scrubber from coverage module for hermetic git tests.
toolchain/mfc/test/coverage.py Scrubs GIT_* env for all git subprocess calls to avoid hook-induced repo contamination.
toolchain/mfc/test/convergence.py Adds convergence-style runners for MG acoustic speed and MG Hugoniot impact checks.
toolchain/mfc/test/cases.py Registers new MG convergence tests; adds MG selector coverage case; removes ideal-gas pi_inf from test cases.
toolchain/mfc/test/case.py Removes ideal-gas pi_inf from post-process base test config.
toolchain/mfc/params_tests/test_eos_selector.py Updates EOS selector tests to require pi_inf unset for ideal gas.
toolchain/mfc/params/definitions.py Registers mie_gruneisen EOS and MG parameters in toolchain parameter definitions.
toolchain/mfc/eos.py Implements MG reference curve + EOS coefficients + sound speed + Hugoniot helpers for tests/harness.
toolchain/mfc/case_validator.py Enforces EOS parameter ownership; adds MG constraints, warnings, and scope fences.
tests/5AC2F65D/golden.txt Adds new golden output for mixed MG/ideal-gas kernel coverage.
tests/5AC2F65D/golden-metadata.txt Adds metadata describing environment/settings used to generate the new golden.
src/simulation/m_time_steppers.fpp Threads alpha_rho into cell-state and sound-speed computations for MG path.
src/simulation/m_sim_helpers.fpp Extends s_compute_cell_state signature to return alpha_rho.
src/simulation/m_riemann_solver_lf.fpp Passes partial densities into s_compute_speed_of_sound.
src/simulation/m_riemann_solver_hllc.fpp Passes partial densities into s_compute_speed_of_sound/_avg.
src/simulation/m_riemann_solver_hll.fpp Passes partial densities into s_compute_speed_of_sound/_avg.
src/simulation/m_global_parameters.fpp Initializes MG parameters in fluid_pp defaults.
src/simulation/m_data_output.fpp Uses alpha_rho in stability criteria and removes dead gamma block.
src/pre_process/m_global_parameters.fpp Initializes MG parameters in fluid_pp defaults.
src/pre_process/m_data_output.fpp Removes unused lit_gamma handling in output.
src/post_process/m_global_parameters.fpp Initializes MG parameters in fluid_pp defaults.
src/post_process/m_data_output.fpp Threads alpha_rho into sound-speed call for MG-capable post processing.
src/common/m_variables_conversion.fpp Implements s_eos_coefficients; supports per-phase EOS coefficients and MG sound-speed mixing.
src/common/m_global_parameters_common.fpp Adds global arrays for EOS selectors and MG curve parameters plus any_state_dependent_eos.
src/common/m_derived_types.fpp Adds MG parameters to fluid_parameters derived type.
src/common/m_constants.fpp Adds eos_mie_gruneisen constant.
.github/scripts/check_coverage_map_health.py Uses shared _git wrapper instead of raw subprocess for consistent env handling.
examples/3D_turb_mixing/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_sphbubcollapse/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_rotating_sphere/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_recovering_sphere/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_rayleigh_taylor_muscl/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_rayleigh_taylor/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_performance_test/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_patch_spherical_harmonic/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_moving_lag_particles/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_mibm_sphere_head_on_collision/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_mibm_periodic_collision/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_lagrange_shbubcollapse/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_lagrange_bubblescreen/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_icpp_stl_cube/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_ibm_stl_test/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_ibm_stl_pyramid/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_ibm_stl_ellipsoid/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_ibm_bowshock/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_brio_wu/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_advection_convergence/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_TaylorGreenVortex_analytical/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_TaylorGreenVortex/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_IGR_jet_1fluid/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_IGR_jet/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_IGR_TaylorGreenVortex_nvidia/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_IGR_TaylorGreenVortex/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/3D_IGR_33jet/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_zero_circ_vortex_analytical/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_zero_circ_vortex/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_viscous_shock_tube/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_tumbling_rectangle/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_triple_point/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_synthetic_turbulence/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_shockdroplet_muscl/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_shockdroplet/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_shockbubble/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_shock_cloud_rmhd/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_riemann_test_muscl/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_riemann_test/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_richtmyer_meshkov/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_rayleigh_taylor/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_poiseuille_thickening_nn/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_poiseuille_nn/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_patch_modal_shape_exp/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_patch_modal_shape/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_orszag_tang_hyper_cleaning/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_orszag_tang/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_moving_lag_bubs/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_mibm_shock_cylinder/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_mibm_particle_cloud/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_mibm_cylinder_in_cross_flow/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_mhd_rotor/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_mhd_magnetic_vortex/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_lid_driven_cavity_nn/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_lid_driven_cavity/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_laplace_pressure_jump/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_lagrange_rising_bubble/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_lagrange_in_crossflow/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_lagrange_bubblescreen/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_kelvin_helmholtz/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_jet/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_isentropicvortex_analytical/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_isentropicvortex/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_icpp_stl_circle/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_ibm_viscous_drag_over_cylinder/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_ibm_stl_wedge/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_ibm_stl_test/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_ibm_stl_MFCCharacter/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_ibm_poiseuille_nn/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_ibm_multiphase/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_ibm_ellipse/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_ibm_cfl_dt/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_ibm_airfoil/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_ibm/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_hypo_shear_contact/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_herschel_bulkley_poiseuille_nn/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_hardcoded_ic/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_forward_facing_step/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_bingham_poiseuille_nn/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_backward_facing_step/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_axisym_shockbubble/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_advection_muscl/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_advection_convergence/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_advection/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_acoustic_pulse_analytical/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_acoustic_pulse/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_acoustic_broadband/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_TaylorGreenVortex/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_IGR_triple_point/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_IGR_2fluid/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/2D_GreshoVortex/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_vacuum_restart/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_vacuum/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_titarevtorro_analytical/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_titarevtorro/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_sodshocktube_muscl/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_sodshocktube/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_sod_convergence/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_shuosher_wenoz5/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_shuosher_wenom5/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_shuosher_wenojs5/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_shuosher_teno7/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_shuosher_teno5/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_shuosher_old/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_shuosher_analytical/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_mhd_smooth_alfven_wave/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_mg_impact/case.py Adds MG symmetric-impact example used by Hugoniot convergence harness.
examples/1D_mg_acoustic/case.py Adds MG acoustic-pulse example used by wave-speed convergence harness.
examples/1D_laxshocktube/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_kapilashocktube/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_hypo_2materials/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_euler_convergence/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_dai_woodward_hlld/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_dai_woodward/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_convergence/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_brio_wu_rmhd/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_brio_wu_hlld/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_brio_wu/case.py Removes ideal-gas pi_inf per new ownership rule.
examples/1D_advection_convergence/case.py Removes ideal-gas pi_inf per new ownership rule.
Suppressed comments (4)

toolchain/mfc/eos.py:1

  • Using x ** 0.5 can silently produce a complex value if roundoff makes the argument slightly negative (Python will return a complex instead of raising). Prefer math.sqrt(...) (and optionally clamp/validate the argument) so failures are explicit and type-stable for the convergence harness.
    toolchain/mfc/test/convergence.py:1
  • Parsing the base pressure via split('+')[0] is brittle (format/whitespace changes, negative terms, or a different expression shape will break the harness). A more robust approach is to have the example emit a dedicated numeric parameter (e.g., p0) in the JSON, or store patch_icpp(1)%pres as a plain float and encode the perturbation elsewhere.
    src/common/m_variables_conversion.fpp:1
  • s_eos_coefficients is newly exposed on the module's public interface here. If it’s intended to be an internal helper (especially given it depends on global arrays like eoss, mg_*s), consider keeping it private to avoid creating a supported external API surface (or add a clear module-level contract/docstring if it must be public).
    tests/5AC2F65D/golden-metadata.txt:1
  • The committed golden metadata indicates it was generated from a dirty working tree. To improve reproducibility/auditability of goldens, regenerate from a clean state (or omit the dirty marker/branch annotation if the metadata is used programmatically).

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

Comment on lines 6 to 8
@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 1196 +68
src/simulation/m_data_output.fpp 1305 -5
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/pre_process/m_data_output.fpp 627 -2
src/simulation/m_time_steppers.fpp 829 +2
src/common/m_constants.fpp 88 +1
src/simulation/m_riemann_solver_hllc.fpp 1269 +1
Directory Lines Diff
common 10023 +77
pre_process 4499 +2
simulation 27670 +2
post_process 3331 +4
total 45523 +85

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