haqlLabs

haql-engine · Simulation audit

A forecast is not evidence. An audit is.

haql-engine is a from-scratch three-phase black-oil engine and an independent audit for Eclipse and OPM runs. It checks the run's own mass balance, convergence, reproduction and input integrity — and publishes the misses, including the ones it finds in public field data.

Not a faster simulator: on SPE1 the engine is about 10× slower than OPM Flow at its loosest setting and 25–40× slower at the tolerance that passes its mass-balance gate. Its value is independent verification, not speed.

one audit
# audit a delivered run, with an optional reference
python3 verify/audit.py \
  --deck NORNE.DATA \
  --run norne_run/ \
  --reference opm_reference/ \
  --out audit.md --pdf audit.pdf

# Norne B1H, 113,344 cells — the run's own numbers
material balance  PASS  oil 3.46e-7   gate 1e-6
solver log        PASS  no explicit failures
verdict           PASS WITH FINDINGS  0 high, 1 medium, 4 info

# the same run against OPM's reference
pressure          PASS  max 0.051 psi
saturation        FAIL  SGAS 0.792 at (24,24,2)
verdict           FAIL  1 high

Real output from the public Norne field case, not a mock-up. The audit names the cell, the values on both sides and the gate that failed. The Markdown is the source of truth; the PDF is a designed rendering.

What it is

An engine for checking the physics. An audit for checking the run.

Two pieces, one purpose: make a simulation result something a reviewer can sign. The engine is the independent implementation; the audit reads a delivered deck and run and tests what the simulator itself claims.

The engine

Three-phase black oil — oil, water, free gas and dissolved gas — with implicit finite volumes, TPFA fluxes, upstream mobility, Peaceman wells, and variable switching between Sg and Rs. Python/NumPy, one CPU thread, Cartesian grids. It is a verification instrument, not a production simulator.

The audit

Reads the deck and the run's own summary/restart output. Checks field material balance at 1e-6, convergence and solver-log health, cell-by-cell reproduction against a reference, and input integrity (PVT, relperm, grid, units, schedule, duplicate well definitions). Emits Markdown, PDF and JSON with a SHA-256 provenance manifest, and a report ID derived from the content of the inputs — not from wherever the audit happened to run.

The audit does not simulate. When a run lacks balance vectors, it can instrument the deck with output-only vectors and re-run it in OPM Flow — and it records both runs. When a gate cannot be evaluated, it reports UNKNOWN; it never passes by default.

Reproducible by construction

Same evidence, same verdict, on any machine.

An audit that cannot be re-run years later is an opinion. The toolchain now proves its own reproducibility, in your environment, on the evidence you sent.

Provenance receipts

Every run writes a manifest: SHA-256 of the deck, every INCLUDE file, the pre-registered gates — and with --hash-run, the entire run and reference tree. Paths are recorded machine-independently (relative, forward-slash), so the same evidence tree hashes identically on Linux, Windows and macOS.

Content-derived report ID

The report ID is the hash of what was audited, not of where it sat on a filesystem. Relocate the evidence tree, or re-run the audit on a different machine, and the ID still matches.

No hidden clock

By default no wall-clock timestamp enters the report — re-runs are byte-stable. If the client wants a date on the deliverable, it is passed explicitly (--stamp), never picked up from the environment.

Selfcheck and doctor

--selfcheck runs the complete audit twice and requires byte-identical Markdown and JSON — on your machine, in front of you. doctor.py prints the environment passport and validates the invariants the audit depends on.

Revision diff

deckdiff.py answers the real quarterly question: what changed between forecasts. Every changed keyword is classed into GRID / PVT / relperm / SOLUTION / schedule, and a physics-class change hard-fails — a silent model swap cannot be waved through as "minor updates".

Ensembles and pinned references

ensemble.py audits every history-match realisation with the identical pre-registered gates and reports the worst run, not the average — plus the residual spread. Your ground-truth run is pinned by SHA in the reference library with drift detection, so every later audit can be proved to use the same reference.

Try it on your own machine: python3 verify/doctor.py, then python3 verify/audit.py --deck CASE.DATA --run RUN/ --selfcheck. The selfcheck runs the audit twice and fails loudly if the outputs differ by a single byte.

Measured, not claimed

The scorecard, including the failures.

4.6e-7SPE1 oil mass balance, 3,285 days — gate 1e-6
3.14%SPE1 cumulative oil vs OPM Flow — RMS 1.6%
3.6%SPE1 flowing BHP RMS vs OPM Flow
113,344Norne cells audited — 44,927 active

SPE1 is a comparison, not a pass of the pre-registered 1 psi / 1e-3 saturation gate: the 3.14% cumulative-oil gap is real and largest late in the run. The engine is 10× slower than OPM Flow at the loose setting that fails its own mass-balance gate, and 25–40× slower at the setting that passes. That is the price of a finite-difference Jacobian in Python; the value is an independent, conservative check, not a speed record.

Norne B1H — clean run

Material balance passes 1e-6: oil 3.46e-7, gas 3.20e-7, water 5.41e-8. No explicit solver failures; the release log does not print scaled residuals, so the residual gate is UNKNOWN. Verdict: PASS WITH FINDINGS — 0 high, 1 medium, 4 info.

Norne full 10-year — mass balance

The run fails the 1e-6 gate: oil 2.18e-4 (~35,044 stb), gas 1.53e-4 (~4.13e6 scf), water 3.33e-6. The PRT records NewtonTolerance=0.01; the report calls it a tolerance/accumulation gap, not a proven conservation bug.

Norne comparative — one cell

Pressure passes at 0.051 psi max, BHP at 0.56 psi RMS, oil rate at 2.6e-5. Saturation fails in one cell: SGAS 0.792 at (24,24,2) where the reference has free gas and the candidate has oil; RS differs by 0.15. The audit names the cell; the engineer decides whether the phase appearance is acceptable.

Norne full reference log — convergence

20 solver failures (15 phase-specific) and 20 timestep cuts over 1,625 Newton iterations. The audit flags solver-log health High. The public log has no summary, so material balance is UNKNOWN, not passed.

Honest limits

What this is not.

  • Not a replacement simulator. SPE1 only; no SPE9, no corner-point/EGRID, no real field grids yet. Cartesian grids, single-threaded Python. The engine is a cross-check, not a development-planning tool.
  • Not faster. 10× slower than OPM Flow at the loose setting; 25–40× slower at the tolerance that passes the mass-balance gate. A speed claim would be false.
  • Not a geology or reserves audit. The audit checks numerical and input integrity. It does not judge upscaling, SCAL, hysteresis, history match, or whether the field will produce what the model says.
  • No client field audit yet. The Norne case is public; it is not a client engagement. The first client audit is priced and scoped as a pilot, with success criteria signed before work starts.
  • UNKNOWN is not PASS. OPM's release log does not print scaled residuals, so convergence is often UNKNOWN; the audit says so and reports the log-health proxy separately.

The engagement

$50k per audit. A verdict you can sign, not a completion message.

One run, one report, one readout. The first engagement is a pilot, scoped to what the samples demonstrate; the standard audit is the full scope below.

  1. SendThe deck with all INCLUDE files, the run directory (SMSPEC/UNSMRY, UNRST for cell comparisons), and a reference run if reproduction is in scope.
  2. AuditMass balance, convergence and log health, cell-by-cell reproduction, and input integrity. Same-day for SPE1-class; 2–3 days for a 10⁴–10⁵-cell sector; 1–2 weeks for a 10⁶-cell full field.
  3. ReadoutA PDF/Markdown report with severity-ranked findings and quoted evidence, a JSON record, a SHA-256 provenance manifest covering the deck, its INCLUDE closure and the gates, and the exact reproduction command. Re-running it is covered: the audit self-checks byte-identical output on any machine.
  4. Sign-offA named reviewer is recorded on the report and signs off on the readout. Pass opens the next conversation; fail gets a written failure analysis, not a sales call.

Pilot

$5–10k

First engagement only. One run, scoped to what the public samples demonstrate. Success criteria and deliverables agreed in writing before work starts.

Standard audit

$50k/engagement

One run, one report, one readout. PDF + JSON + provenance manifest + the exact reproduction command. The decision at stake is usually larger: a 1% error on a $100M development is $1M.

Retainer

$50k/month

One audit per month, priority scheduling, named reviewer — and the calendar layer: quarterly deck-diff audits of every forecast revision, pinned reference runs for your evidence history, and ensemble audits of history-match sweeps. Offered after a completed pilot — not before.

The $50k figure is the offer, not a claim of market demand. The public Norne case is not a client engagement. The first client audit is a pilot; the retainer is offered only after a completed pilot and a named reviewer.

FAQ

Straight answers.

Does haql-engine replace Eclipse or CMG?

No. It audits their output and cross-checks the physics. The engine is an independent implementation for verification, not a production simulator; it supports SPE1-class Cartesian decks today, not full-field corner-point models.

Is it faster?

No. On SPE1 it is about 10× slower than OPM Flow at the loose setting and 25–40× slower at the tolerance that passes its 1e-6 mass-balance gate. The value is independent verification, not speed.

What exactly does the audit check?

Field material balance from the run's own in-place and cumulative vectors; Newton convergence and solver-log health; cell-by-cell pressure, saturation, BHP, oil rate and water cut against a reference; and input integrity — PVT, relperm, grid, units and schedule. It does not judge geology, upscaling, SCAL or history match.

What if my run has no balance vectors?

The audit can instrument the deck with output-only FOIP/FWIP/FGIP vectors and re-run it in OPM Flow, then audit the re-run. The report records both runs and says the re-run is an independent reproduction, not your original run. Without that, the gate is UNKNOWN, not passed.

Can we reproduce an audit years later?

Yes, and it is designed for that. Every audited input is hashed into a provenance manifest (deck, every INCLUDE file, the gates; the full run tree with --hash-run). The report ID is derived from that content, so relocating the evidence or moving machines does not change it. --selfcheck re-runs the audit twice and requires byte-identical output; doctor.py prints the environment passport. No wall clock enters the report unless you explicitly stamp a date.

We re-run our history match every quarter. Can you audit all of it?

That is the intended cadence. ensemble.py audits every realisation with the same pre-registered gates in sorted, auditable order and reports the worst run and the residual spread — a match fair on average but loose on individual realisations is flagged. deckdiff.py then diffs this quarter's deck against the last: input or schedule changes are listed value-by-value, and any physics-class change fails the audit so a silent model swap cannot pass. Your pinned reference run is stored by SHA and proved unchanged at every use.

What if a forecast revision quietly changed the model?

The diff audit classes every changed keyword (grid, PVT, relperm, solution section versus schedule) and exits as a failure when the physics class moved. Value-level tables show exactly which numbers moved and by how much, including repetition defaults.

Has a client used it?

Not yet. The evidence on this page is from the public SPE1 benchmark and Equinor's public Norne field case. The first client engagement is a pilot, with success criteria signed before work starts.

Next

Send the deck and the run.

Tell us the simulator, the model size and the decision at stake. If the audit fits, you'll have a fixed price and success criteria within a week.

kunleaz100@gmail.com