Add BakedSatfuncTables: exact baked-table saturation-function evaluation - #5284
Add BakedSatfuncTables: exact baked-table saturation-function evaluation#5284hnil wants to merge 1 commit into
Conversation
For the ECL-default three-phase law, bake each cell's scaled material law (EPS included) into minimal exact piecewise-linear tables on three axes (Sw, Sg, S=Sw+Sg), deduplicated across cells by the shape of the scaled endpoints. Vertical endpoint scales (maxKr*, maxPc*, e.g. from SWATINIT) are linear in the ordinate and factored into per-cell multipliers instead of keying tables; with 3pt vertical scaling active the residual/max ratio keys the shape. Node placement is discovered by midpoint refinement with kink snapping and collinear pruning, so the representation is exact without reimplementing any EPS semantics; build-time validation compares against the installed law. Evaluation is one hint-grid-accelerated segment lookup per axis with the node values interleaved per cache line and derivatives constructed analytically. On Norne (44k cells, SWATINIT) this yields 7 unique tables in 31 KB and evaluates ~2-4x faster than the generic law stack. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
7baa38c to
b1f53dc
Compare
|
Two follow-up results that bear on how this should be judged. Hysteresis is where the table representation gains most, not where it struggles. Norne runs
Pool 33.7 → 49.3 KB, per-cell 60 → 92 B. Not in this branch yet; the imbibition branch still needs end-to-end validation against a reversed state. A cheaper, independent step exists. Deriving the two-phase arguments once, with no representation change at all, gives 89.9 → 59.8 ns/cell — about a third of the win for none of the machinery here. That is now #5287, and it is worth landing on its own merits regardless of what happens to this PR. For calibration, the ladder on Norne (eval3, identical checksums): generic 89.9, fused arguments 59.8, baked 20.6; with hysteresis 201.6 → 24.6. |
Bakes each cell's scaled material law (endpoint scaling included, ECL-default three-phase) into minimal exact piecewise-linear tables on three saturation axes, deduplicated across cells. Vertical endpoint scales (maxKr*, maxPc*, e.g. from SWATINIT) are linear in the ordinate and factored into per-cell multipliers instead of keying tables. Node placement is found by midpoint refinement with kink snapping against the installed law, so no endpoint-scaling semantics are reimplemented and the build validates itself (max rel err ~1e-10).
Norne, 44 927 cells, eval3, identical states and checksums:
7 unique tables, 33.7 KB pool for the whole field; 60 B per cell; bake < 0.01 s. Wired into flow it cut Props/update 10.9 → 8.5 s (−23 %) with unchanged iteration counts. Consumer-side hook: OPM/opm-simulators#7304.
Scope of this branch: ECL-default approach, no hysteresis, no directional relperm. A prototype adding Carlson KR hysteresis (second pool for the two hysteretic columns, four scalars per cell, one compare and one add) measures 201.6 → 24.6 ns/cell on Norne with EHYSTR active; it is not in this PR yet. Stone 1/2 should be cheaper still — both put the oil constituents on the sw and sg axes — but is not implemented.
Draft: feedback welcome on where this belongs and how the fallback should be gated.
🤖 Generated with Claude Code