Skip to content

Export the melt drainage quantities at the basic nodes - #66

Merged
timlichtenberg merged 6 commits into
mainfrom
tl/trapping-exports
Oct 3, 2026
Merged

timlichtenberg merged 6 commits into
mainfrom
tl/trapping-exports

Conversation

@timlichtenberg

Copy link
Copy Markdown
Member

Description

Exposes the quantities that the melt-solid separation velocity is built from, for consumers that compute melt drainage outside the solver.

  • mobility_function(porosity, grain_size) in aragog.eos is the three-regime permeability factor F = k(phi)/phi (Blake-Kozeny-Carman, Rumpf-Gupte, Stokes; Abe 1995, Bower et al. 2018). EntropyPhaseEvaluator.porosity() and phase_boundary_densities() return the density-derived porosity and the solid and melt densities at the phase boundary. relative_velocity now calls these three; the expressions are unchanged.
  • SolverOutput and the NetCDF file carry four new basic-node arrays: porosity_b, rho_solid_b, rho_melt_b and g_b. They are computed once from the final state, after the integration, on every backend.
  • The docs state what porosity_b is and is not: it is the porosity the separation velocity uses, not the melt fraction. Where the melt is denser than the solid it is about 0 although the node holds melt, so a drainage calculation tests the sign of rho_solid_b - rho_melt_b first and uses phi_basic for the presence of melt. The grain size enters as a radius (Stokes prefactor 2/9).

No solver result changes.

Validation of changes

  • The separation velocity is bit-identical to main on 20000 random states (pressure, entropy, gravity) for both separation viscosity modes, and a test pins it to values frozen from main.
  • Standalone runs on main and on this branch (3 with the NumPy solver, 3 with JAX) give identical values for all 54 NetCDF variables that existed before; the solve time is unchanged.
  • New tests: the three permeability regimes against their closed forms, the porosity formula with its floor band on both sides, the exports against a recomputation from the returned state, units and copies of the four arrays, a stub-EOS case that needs no tables, and the constant-properties case. 28 of them run in the unit tier without EOS tables; 35 with tables.
  • Patch coverage 100 % (44 of 44 changed source statements).

Tested on macOS 26 with Python 3.12.

Checklist

  • I have followed the contributing guidelines
  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • My changes generate no new warnings or errors
  • I have checked that the tests still pass on my computer
  • I have updated the docs, as appropriate
  • I have added tests for these changes, as appropriate
  • I have checked that all dependencies have been updated, as required

SolverOutput and the NetCDF snapshot now carry porosity_b, rho_solid_b, rho_melt_b and g_b, for consumers that compute melt drainage. They are read from the basic-node phase evaluator after get_state refreshes the state at the final entropy, so they describe the returned state.

The three-regime permeability over porosity moves to a module-level mobility_function, and the density-derived porosity to EntropyPhaseEvaluator.porosity, so a consumer evaluates the same expressions the separation velocity uses. relative_velocity calls both and its result is unchanged. Under const_properties the porosity is 1 and both densities equal const_rho.
Below the solidus the soft-clipped porosity lies in [-2.5e-7, 5e-4], reaching 5e-4 at the solidus; the docstring and netcdf.md now say so, and relative_velocity's docstring says that where the melt is denser the porosity goes to the lower or the upper clip limit depending on the node density. mobility_function is exported from aragog.eos, and usage.md lists the four new SolverOutput fields.

The solve-based export tests carry the smoke marker. New tests pin both blend centres of mobility_function, the porosity bound at the solidus, and g_b against an external gravity profile.
The exported porosity is (rho_s - rho)/(rho_s - rho_l), soft-clipped, not the melt fraction. A solid node whose density is below rho_s, which happens in tables where the solid density rises with entropy towards the solidus, gives values up to 1, and where the melt is denser the floored denominator gives a band about 1 kg/m^3 wide in which any value occurs. The labels, the porosity() and relative_velocity docstrings and netcdf.md now say this and point consumers to phi_basic for the presence of melt.

Tests pin the clip value at the solidus, the porosity formula across the dense-melt band, and g_b against a non-linear external gravity profile. The export tests keep the unit marker, like the other short EOS-backed solves that PR CI runs.
The porosity denominator is floored at about 1 kg/m^3 wherever rho_s - rho_l is below that, a lighter melt included. There the porosity is (rho_s - rho)/(1 kg/m^3) clipped, so the intermediate band lies within 1 kg/m^3 below rho_s and a node at or above rho_s is about 0. The relative_velocity and mobility_function docstrings, netcdf.md and two_phase_flow.md now say this; two_phase_flow.md also notes that j_grav carries phi(1 - phi) of the melt fraction.

The porosity formula test covers both sides of the band, the lighter-melt floor and the lower clip limit at 1e-12. Solve-based tests are smoke and formula tests unit, as build_tests.md defines the tiers.
relative_velocity is compared bit for bit with values computed before the extraction, for a normal and a dense-melt contrast in both separation modes, using a stub EOS so the unit tier runs it without tables. Unit tests also cover the order of phase_boundary_densities, the porosity ratio, the floor band for a melt lighter or denser by 0.5 kg/m^3, mobility_function at the negative clip values, and the const_properties copies; the NetCDF round trip checks the units of the four exports.

Under const_properties phase_boundary_densities returns copies of the node density. The porosity() docstring and netcdf.md state that porosity_b is about 0 in a mush where rho_s <= rho_l, so drainage must test the sign of the contrast first, and that Phi_global_vol uses the unfloored ratio. The mobility_function docstring says the grain size enters as the radius of Stokes' law and notes the 4.4 percent overshoot of the upper blend; netcdf.md describes g_b.
@timlichtenberg
timlichtenberg requested a review from a team as a code owner October 3, 2026 17:39
Copilot AI balanced review requested due to automatic review settings October 3, 2026 17:39

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟢 Approval recommended

The implementation preserves existing calculations while consistently exposing and testing the new diagnostics.

Review effort: Balanced
Findings: None

What changed in this PR

Exposes melt-drainage inputs at basic nodes without changing solver results.

Changes:

  • Adds public porosity, phase-density, and mobility APIs.
  • Exports drainage arrays through SolverOutput and NetCDF.
  • Adds documentation and comprehensive regression coverage.
File Description
src/​aragog/​eos/​entropy_phase.py Extracts drainage calculations into public APIs.
src/​aragog/​eos/​__init__.py Exports mobility_function.
src/​aragog/​solver/​entropy_solver.py Adds final-state drainage arrays and serialization.
tests/​test_drainage_exports.py Tests formulas, exports, and solver modes.
tests/​test_solver_output_netcdf.py Tests NetCDF values, dimensions, and units.
docs/​Reference/​api/​aragog.eos.md Documents the mobility API.
docs/​How-to/​usage.md Lists new output fields.
docs/​How-to/​netcdf.md Explains drainage output semantics.
docs/​Explanations/​two_phase_flow.md Clarifies density-crossing behavior.

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

@timlichtenberg
timlichtenberg merged commit 287403d into main Oct 3, 2026
10 checks passed
@timlichtenberg
timlichtenberg deleted the tl/trapping-exports branch October 3, 2026 19:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants