Complete the state-dependent equation-of-state family: temperature, cubic Hugoniot, Vinet, 6-equation model, and the remaining fences - #1811
Conversation
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.
…eck passes from worktrees (cherry picked from commit 5ad5c85)
…ristic BCs, probes and post-process c
Isentropic release of a JWL fluid lands on the closed-form isentrope to 7.5e-5 at N = 200 and 9e-7 at N = 800; goldens for JWL beside an ideal gas, Mie-Gruneisen under Wood's law, and Mie-Gruneisen with characteristic walls. The acoustic pulse now comes from a rectangle patch and is tracked by its centroid: an analytic IC is compiled in and every distinct one costs the suite a full rebuild.
One reference-curve routine with a Gruneisen closure Gamma_G = Gamma_0 + a mu, one coefficient conversion, one sound-speed formula and one RK4 stepper for the phasic isentrope and the reference temperature. Adds the temperature T = T_ref + (e - e_ref)/c_v and its T_wrt output, the cubic Hugoniot, the Vinet cold curve, the 6-equation model on the phasic isentrope, and helpers that fetch their own coefficients so no feature reads gammas(i) directly: hypoelasticity, IBM, acoustic sources and the reactive burn open up. The validator refuses initial states outside a state-dependent EOS and keeps qv as the shared formation-energy zero.
Goldens for Vinet, the cubic Hugoniot, MG with hypoelasticity, with IBM, and a MG reactant burning to JWL products; the isentropic release now serves JWL and Vinet and the Hugoniot recovery a quadratic fit. The convergence harness runs a private copy of each case in a temporary directory without rebuilding, so specs that share a case file can run concurrently.
There was a problem hiding this comment.
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
Completes integration of state-dependent equation-of-state (EOS) families across the solver and toolchain, including new per-phase coefficient paths, temperature output, and tooling/test updates to support the extended EOS selector set.
Changes:
- Add/select new EOS families (Mie–Grüneisen, JWL, Vinet) in parameters, validation, and toolchain mirror logic.
- Route simulation/post-process paths through per-phase coefficients (sound speed, internal energy, bulk modulus, isentropes, relaxation, burn temperature).
- Improve test tooling robustness (coverage-map git isolation) and update examples/docs for ideal-gas stiffness ownership and new
T_wrtoutput.
Reviewed changes
Copilot reviewed 181 out of 184 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| toolchain/mfc/test_case_validator.py | Adds selector/constraint tests for new state-dependent EOS families and T_wrt requirements |
| toolchain/mfc/test/test_coverage_unit.py | Updates unit tests to reuse git-env scrubbing helper from coverage module |
| toolchain/mfc/test/coverage.py | Ensures git subprocess calls scrub inherited GIT_* env to avoid hook-induced repo corruption |
| toolchain/mfc/test/case.py | Removes ideal-gas pi_inf override from test case defaults |
| toolchain/mfc/params_tests/test_eos_selector.py | Updates ideal-gas stiffness ownership expectations and error messaging assertions |
| toolchain/mfc/params/descriptions.py | Documents new T_wrt output parameter |
| toolchain/mfc/params/definitions.py | Registers T_wrt, expands EOS enum to include mie_gruneisen/jwl/vinet, and registers new EOS parameters |
| toolchain/mfc/eos.py | Adds Python mirror implementations for reference curves, coefficients, sound speed, RK4, and temperature |
| .github/scripts/check_coverage_map_health.py | Switches git calls to shared helper for consistent env scrubbing |
| docs/documentation/case.md | Documents T_wrt in case-file output options |
| src/common/m_constants.fpp | Adds EOS constants and RK4/ODE identifiers for state-dependent EOS support |
| src/common/m_derived_types.fpp | Extends physical_parameters with MG/JWL/Vinet curve and temperature reference fields |
| src/common/m_global_parameters_common.fpp | Adds per-fluid EOS selector and state-dependent curve parameter arrays and GPU declarations |
| src/pre_process/m_global_parameters.fpp | Initializes new state-dependent EOS parameter defaults in pre-process |
| src/simulation/m_global_parameters.fpp | Initializes new state-dependent EOS parameter defaults in simulation |
| src/post_process/m_global_parameters.fpp | Initializes new state-dependent EOS parameter defaults and introduces T_wrt default in post-process |
| src/simulation/m_sim_helpers.fpp | Extends s_compute_cell_state to output alpha_rho alongside alpha |
| src/simulation/m_time_steppers.fpp | Plumbs alpha_rho through CFL computation and sound-speed evaluation |
| src/simulation/m_start_up.fpp | Switches internal energy initialization to per-phase EOS lookup (f_phase_internal_energy(..., i)) |
| src/simulation/m_riemann_solver_hllc.fpp | Uses per-phase isentropes and per-phase internal energy; plumbs alpha_rho into sound speed paths |
| src/simulation/m_riemann_solver_hll.fpp | Plumbs alpha_rho into mixture sound-speed evaluation |
| src/simulation/m_riemann_solver_lf.fpp | Plumbs alpha_rho into mixture sound-speed evaluation |
| src/simulation/m_riemann_solver_hypo_hlld.fpp | Replaces stiffened-gas bulk-modulus usage with per-phase bulk modulus |
| src/simulation/m_rhs.fpp | Replaces stiffened-gas bulk modulus calls with per-phase bulk modulus in hypoelastic coupling |
| src/simulation/m_ibm.fpp | Switches IBM internal-energy recovery to per-phase EOS lookup |
| src/simulation/m_hypoelastic.fpp | Uses per-phase bulk modulus for hypoelastic K computation |
| src/simulation/m_pressure_relaxation.fpp | Extends relaxation Newton to use phasic isentrope density inversion for state-dependent EOS |
| src/simulation/m_reactive_burn.fpp | Uses per-phase temperature (f_phase_temperature) for Arrhenius branch |
| src/simulation/m_data_output.fpp | Threads alpha_rho through stability criteria and sound speed computations |
| src/simulation/m_cbc.fpp | Threads alpha_rho into sound-speed evaluation and mixture-coefficients time-derivative call |
| src/simulation/m_acoustic_src.fpp | Inlines frozen mixing of per-phase bulk moduli when any state-dependent EOS is present |
| src/post_process/m_start_up.fpp | Threads alpha_rho into sound speed post-processing and adds T_wrt field outputs |
| src/post_process/m_derived_variables.fpp | Removes dead s_derive_sound_speed code path from derived variables |
| src/post_process/m_data_output.fpp | Uses per-phase internal energy and threads alpha_rho into sound speed computation |
| tests/ED75D01D/golden-metadata.txt | Adds new golden metadata for updated EOS behavior |
| tests/A6846AD4/golden-metadata.txt | Adds new golden metadata for updated EOS behavior |
| tests/A421E318/golden-metadata.txt | Adds new golden metadata for updated EOS behavior |
| tests/7853BD45/golden-metadata.txt | Adds new golden metadata for updated EOS behavior |
| tests/6AE3FB4E/golden-metadata.txt | Adds new golden metadata for updated EOS behavior |
| tests/61AF4509/golden-metadata.txt | Adds new golden metadata for updated EOS behavior |
| tests/6191C8D0/golden-metadata.txt | Adds new golden metadata for updated EOS behavior |
| tests/590E4427/golden-metadata.txt | Adds new golden metadata for updated EOS behavior |
| tests/4A0CDF9C/golden-metadata.txt | Adds new golden metadata for updated EOS behavior |
| tests/471270BB/golden-metadata.txt | Adds new golden metadata for updated EOS behavior |
| tests/120043F6/golden-metadata.txt | Adds new golden metadata for updated EOS behavior |
| tests/5AC2F65D/golden-metadata.txt | Adds new golden metadata for updated EOS behavior |
| examples/1D_mg_impact/case.py | Adds MG symmetric impact validation case generator |
| examples/1D_mg_acoustic/case.py | Adds MG acoustic pulse validation case generator |
| examples/1D_isentropic_release/case.py | Adds isentropic release validation case generator (JWL/Vinet) |
| examples/3D_turb_mixing/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_sphbubcollapse/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_rotating_sphere/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_recovering_sphere/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_rayleigh_taylor_muscl/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_rayleigh_taylor/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_performance_test/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_patch_spherical_harmonic/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_moving_lag_particles/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_mibm_sphere_head_on_collision/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_mibm_periodic_collision/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_lagrange_shbubcollapse/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_lagrange_bubblescreen/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_icpp_stl_cube/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_ibm_stl_test/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_ibm_stl_pyramid/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_ibm_stl_ellipsoid/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_ibm_bowshock/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_brio_wu/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_advection_convergence/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_TaylorGreenVortex_analytical/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_TaylorGreenVortex/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_IGR_jet_1fluid/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_IGR_jet/case.py | Removes ideal-gas pi_inf setting (both fluids) |
| examples/3D_IGR_TaylorGreenVortex_nvidia/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_IGR_TaylorGreenVortex/case.py | Removes ideal-gas pi_inf setting |
| examples/3D_IGR_33jet/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_zero_circ_vortex_analytical/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_zero_circ_vortex/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_viscous_shock_tube/case.py | Removes ideal-gas pi_inf setting (both fluids) |
| examples/2D_tumbling_rectangle/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_triple_point/case.py | Removes ideal-gas pi_inf setting (both fluids) |
| examples/2D_synthetic_turbulence/case.py | Removes ideal-gas pi_inf setting (both fluids) |
| examples/2D_shockdroplet_muscl/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_shockdroplet/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_shockbubble/case.py | Removes ideal-gas pi_inf setting (both fluids) |
| examples/2D_shock_cloud_rmhd/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_riemann_test_muscl/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_riemann_test/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_richtmyer_meshkov/case.py | Removes ideal-gas pi_inf setting (both fluids) |
| examples/2D_rayleigh_taylor/case.py | Removes ideal-gas pi_inf setting (both fluids) |
| examples/2D_poiseuille_thickening_nn/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_poiseuille_nn/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_patch_modal_shape_exp/case.py | Removes ideal-gas pi_inf setting (both fluids) |
| examples/2D_patch_modal_shape/case.py | Removes ideal-gas pi_inf setting (both fluids) |
| examples/2D_orszag_tang_hyper_cleaning/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_orszag_tang/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_moving_lag_bubs/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_mibm_shock_cylinder/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_mibm_particle_cloud/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_mibm_cylinder_in_cross_flow/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_mhd_rotor/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_mhd_magnetic_vortex/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_lid_driven_cavity_nn/case.py | Removes ideal-gas pi_inf setting (both fluids) |
| examples/2D_lid_driven_cavity/case.py | Removes ideal-gas pi_inf setting (both fluids) |
| examples/2D_laplace_pressure_jump/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_lagrange_rising_bubble/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_lagrange_in_crossflow/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_lagrange_bubblescreen/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_kelvin_helmholtz/case.py | Removes ideal-gas pi_inf setting (both fluids) |
| examples/2D_jet/case.py | Removes ideal-gas pi_inf setting (both fluids) |
| examples/2D_isentropicvortex_analytical/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_isentropicvortex/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_icpp_stl_circle/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_ibm_viscous_drag_over_cylinder/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_ibm_stl_wedge/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_ibm_stl_test/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_ibm_stl_MFCCharacter/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_ibm_poiseuille_nn/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_ibm_multiphase/case.py | Removes ideal-gas pi_inf setting (both fluids) |
| examples/2D_ibm_ellipse/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_ibm_cfl_dt/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_ibm_airfoil/case.py | Removes ideal-gas pi_inf setting (both fluids) |
| examples/2D_ibm/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_hypo_shear_contact/case.py | Removes ideal-gas pi_inf setting (both fluids) |
| examples/2D_herschel_bulkley_poiseuille_nn/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_hardcoded_ic/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_forward_facing_step/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_bingham_poiseuille_nn/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_backward_facing_step/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_axisym_shockbubble/case.py | Removes ideal-gas pi_inf setting (both fluids) |
| examples/2D_advection_muscl/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_advection_convergence/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_advection/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_acoustic_pulse_analytical/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_acoustic_pulse/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_acoustic_broadband/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_TaylorGreenVortex/case.py | Removes ideal-gas pi_inf setting |
| examples/2D_IGR_triple_point/case.py | Removes ideal-gas pi_inf setting (both fluids) |
| examples/2D_IGR_2fluid/case.py | Removes ideal-gas pi_inf setting (both fluids) |
| examples/2D_GreshoVortex/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_vacuum_restart/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_vacuum/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_titarevtorro_analytical/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_titarevtorro/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_sodshocktube_muscl/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_sodshocktube/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_sod_convergence/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_shuosher_wenoz5/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_shuosher_wenom5/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_shuosher_wenojs5/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_shuosher_teno7/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_shuosher_teno5/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_shuosher_old/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_shuosher_analytical/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_mhd_smooth_alfven_wave/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_laxshocktube/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_kapilashocktube/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_hypo_2materials/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_euler_convergence/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_dai_woodward_hlld/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_dai_woodward/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_convergence/case.py | Removes ideal-gas pi_inf setting (both fluids) |
| examples/1D_brio_wu_rmhd/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_brio_wu_hlld/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_brio_wu/case.py | Removes ideal-gas pi_inf setting |
| examples/1D_advection_convergence/case.py | Removes ideal-gas pi_inf setting (both fluids) |
Suppressed comments (3)
toolchain/mfc/test_case_validator.py:1
- The
unittest.main()call now appears before newly-added test classes, so running this file directly won’t discover/execute the new tests. Move theif __name__ == "__main__": unittest.main()block to the end of the file (after all test class definitions).
src/simulation/m_pressure_relaxation.fpp:1 - This skips the stiffened-gas pressure lower bound for all fluids whenever any fluid is state-dependent. In mixed-EOS runs (some stiffened gas, some state-dependent), stiffened-gas phases can end up with invalid initial pressures and break the Saurel isentrope inversion. Apply the bound per fluid (e.g., skip only when that fluid’s EOS is state-dependent, using
f_is_state_dependent(eoss(i))) rather than gating on the globalany_state_dependent_eos.
toolchain/mfc/test_case_validator.py:1 - The docstring refers to
fluid_pp(i)%eos = 'mie_gruneisen', but the tests setfluid_pp(1)%eosusing the integer selector (3). To keep the tests self-describing, either adjust the docstring to mention the numeric selector (and/or the mapping), or use the string form consistently in the new test cases.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
|
||
| sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "toolchain")) | ||
| from mfc.test.coverage import COVERAGE_MAP_PATH, load_map, map_health # noqa: E402 | ||
| from mfc.test.coverage import COVERAGE_MAP_PATH, _git, load_map, map_health # noqa: E402 |
Stacked on #1805, #1809 and #1810; review the last two commits. Completes the state-dependent equation-of-state family (#1638).
Structure.
s_reference_curveis the only place a reference curve lives: each family is onecasereturningp_ref, e_refand their density derivatives; the Grüneisen closureΓ_G = Γ₀ + aμis one line after theselect.s_eos_coefficientsconverts a curve to(Γ, Π, Π′, Γ′);s_phase_coefficientsis the only place that chooses per-cell evaluation over the init-time constants (stiffened and ideal gas stay bit-identical);f_c2_from_coefficientsis the only sound-speed formula;f_rk4is the only integrator, serving both the phasic isentrope and the reference temperature.f_phase_internal_energyandf_phase_bulk_modulusfetch their own coefficients, so no feature readsgammas(i)directly any more (the fenced QBMM excepted).Added.
Γ_G(ρ)viamg_gruneisen_a(vinet_gruneisen_a); the−pΓ′term in the sound speed and the characteristic-BC coefficient derivative.T = T_ref(ρ) + (e − e_ref)/c_v, withT_reffrom the Maxwell-relation ODEdT/dV = (e_ref′ + p_ref)/c_v − Γ_G T/V(closed-formT₀(ρ/ρ₀)^Γ_Gwhen the reference is an isentrope).T_wrtwrites each fluid's temperature; the reactive burn's Arrhenius branch uses it.u_s = c₀ + s u_p + s₂u_p² + s₃u_p³(mg_s2,mg_s3): Newton foru_p(μ)with implicit-differentiation derivatives; the linear fit stays the closed-form path.vinet_k0, vinet_k0p, vinet_rho0, vinet_gruneisen), an isentrope reference like JWL.qvis allowed on state-dependent fluids as the shared formation-energy zero between an MG reactant and JWL products. Still refused: bubbles, IGR (its flux carries no phasic volume fractions), relativity, MHD, chemistry (species-based EOS), phase change.ρe > 0andc² > 0(replaces the pole warning);T_wrtneedsc_v > 0. Dead code removed: the post-processs_derive_sound_speed, the pre-process fluid-1 shortcuts.Verification.
model_eqns = 315/15, Reactive Burn 5/5 (each set includes its new MG golden).Π′, the two 6-equation cases had been generated on a stale binary). Hugoniot recovery 1.4e-3 (bound 5e-3); acoustic speed 2.5e-4 (bound 1e-3).s₂ = 0.3): shock speed and plateau density within 1.5e-3 of the exact jump relations over four closing speeds (bound 5e-3).toolchain/mfc/eos.py): reference-curve derivatives vs finite differences,c²vs a numerical isentrope witha ≠ 0, RK4 vs the closed-form JWL isentrope (1e-8 over ±25%), the Maxwell relation for the Hugoniot temperature,de_c/dρ = p_c/ρ²for Vinet. 140 unit tests; all 760 test definitions validate.Temperature has no consumer in the dynamics yet; it is wired to output and the burn so the EOS is complete, and it is validated in the mirror rather than by a golden.
Also fixed in the convergence harness: each run now executes a private copy of its case file in a temporary directory with
--no-build; specs sharing one case file used to clobber each other'spre_processoutput and race on the install step when run concurrently.