Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions .github/workflows/rms-opm-ert-notebook-validation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: Validate RMS OPM ERT notebook

on:
workflow_dispatch:
pull_request:
paths:
- notebooks/reservoir/rms_to_opm_flow_agent_ert.ipynb
- scripts/generate_rms_agent_opm_ert_notebook.py
- .github/workflows/rms-opm-ert-notebook-validation.yml

permissions:
contents: read

jobs:
execute-and-validate:
runs-on: ubuntu-latest
timeout-minutes: 120
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: pip
- name: Install notebook runner
run: |
python -m pip install --quiet nbformat==5.10.4 nbconvert==7.16.6 jupyter-client ipykernel
python -m ipykernel install --user --name python3 --display-name 'Python 3'
- name: Generate notebook source
run: python scripts/generate_rms_agent_opm_ert_notebook.py
- name: Execute notebook from a clean kernel
run: >-
jupyter nbconvert --to notebook --execute --inplace
--ExecutePreprocessor.timeout=4200
--ExecutePreprocessor.iopub_timeout=120
notebooks/reservoir/rms_to_opm_flow_agent_ert.ipynb
- name: Validate execution and repository contracts
run: |
python scripts/check_notebook.py notebooks/reservoir/rms_to_opm_flow_agent_ert.ipynb --require-main-source
python - <<'PY'
import json
from pathlib import Path
path = Path('notebooks/reservoir/rms_to_opm_flow_agent_ert.ipynb')
notebook = json.loads(path.read_text(encoding='utf-8'))
code = [cell for cell in notebook['cells'] if cell['cell_type'] == 'code']
missing = [i for i, cell in enumerate(code, 1) if cell.get('execution_count') is None]
errors = [output for cell in code for output in cell.get('outputs', []) if output.get('output_type') == 'error']
images = sum('image/png' in output.get('data', {}) for cell in code for output in cell.get('outputs', []))
assert not missing, f'Unexecuted code cells: {missing}'
assert not errors, f'Stored errors: {errors}'
assert images >= 11, f'Expected at least 11 retained PNG outputs, found {images}'
print({'code_cells': len(code), 'retained_png_outputs': images, 'stored_errors': len(errors)})
PY
- name: Render HTML for visual review
run: >-
jupyter nbconvert --to html
--output rms_to_opm_flow_agent_ert.html
notebooks/reservoir/rms_to_opm_flow_agent_ert.ipynb
- uses: actions/upload-artifact@v4
with:
name: rms-opm-ert-executed-notebook
path: |
notebooks/reservoir/rms_to_opm_flow_agent_ert.ipynb
notebooks/reservoir/rms_to_opm_flow_agent_ert.html
if-no-files-found: error
retention-days: 14
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Advanced notebooks use the released Python distribution only as the JPype bridge

* [LNG process simulation and benchmark comparison](notebooks/process/LNG_Process_Benchmark_Comparison.ipynb) – Run closed-loop SMR, C3MR, DMR, and nitrogen-expander models with common KPIs, literature checks, and an exchanger grid-convergence study.
* [IoT and Industry 4.0 with NeqSim](notebooks/AI/IoT_and_Industry4.0_with_NeqSim.ipynb) – Build an instrumented digital twin, stream dynamic simulation data, and explore Industry 4.0 workflows backed by NeqSim measurements.
* [RMS-origin reservoir to OPM Flow, ERT, and NeqSim](notebooks/reservoir/rms_to_opm_flow_agent_ert.ipynb) – Audit public Reek ROFF exports, demonstrate blocking and property spreading, run OPM Flow and ERT, and define a governed RMS-agent contract.

## Getting Started
See the [NeqSim Colab page](https://colab.research.google.com/github/EvenSol/NeqSim-Colab/blob/master/notebooks/examples_of_NeqSim_in_Colab.ipynb) for how to start using NeqSim in Colab/Python.
Expand Down
9 changes: 9 additions & 0 deletions notebooks/examples_of_NeqSim_in_Colab.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,15 @@
"* [NeqSim Thermodynamics](https://colab.research.google.com/drive/1c6OY3O1xX8nmaU5JadF3CIjaj4CSYb1Q?usp=sharing)\n",
"* [Pandas + NeqSim — Data‑driven Thermodynamics](https://colab.research.google.com/drive/1ngKz_Ry8PkJwENdNXIkZpO8PmARiqyGr?usp=sharing)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## RMS-origin reservoir automation\n",
"\n",
"* [RMS-origin Reek to OPM Flow, ERT, and NeqSim](reservoir/rms_to_opm_flow_agent_ert.ipynb): blocking, property spreading, real simulation, uncertainty, and a governed RMS-agent contract.\n"
]
}
],
"metadata": {
Expand Down
120 changes: 120 additions & 0 deletions notebooks/maintenance_ledger/rms_opm_ert_agent_20260831.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
{
"schema_version": 1,
"shard": "rms-opm-ert-agent-20260831",
"updated_at": "2026-08-31T17:17:00Z",
"notebooks": [
{
"path": "notebooks/reservoir/rms_to_opm_flow_agent_ert.ipynb",
"verified_date": "2026-08-31",
"verified_at_utc": "2026-08-31T17:15:07Z",
"neqsim_version": "3.18.0 Python bridge with current source-built Java master",
"neqsim_commit": "1f7a01b06307d9d56451e43bb8d6023d28d14007",
"neqsim_jar_sha256": "39e1de9738baaef18726c5d7a3f9cccf3a8af29a8e39761f90d92b870b0a857a",
"python_version": "3.12.14",
"xtgeo_version": "4.25.1",
"opm_version": "2026.4",
"ert_version": "23.0.1",
"execution_status": "passed",
"execution_method": "Clean GitHub Actions Python 3.12 kernel; all cells executed top-to-bottom; NeqSim Java master built from source; OPM Flow base case and four ERT realizations completed.",
"code_cells": 42,
"substantive_code_cells": 42,
"markdown_cells": 20,
"git_blob_sha1": "1501daf688f19b19e6f65e777e5a3259c7184098",
"notebook_bytes": 2747005,
"publication": {
"branch": "codex/rms-agent-opm-ert-notebook",
"mode": "focused draft pull request",
"files": [
"notebooks/reservoir/rms_to_opm_flow_agent_ert.ipynb",
"README.md",
"notebooks/examples_of_NeqSim_in_Colab.ipynb",
"notebooks/notebook_maintenance_ledger.json",
"notebooks/maintenance_ledger/rms_opm_ert_agent_20260831.json",
".github/workflows/rms-opm-ert-notebook-validation.yml",
"scripts/generate_rms_agent_opm_ert_notebook.py"
]
},
"open_data": {
"repository": "equinor/xtgeo-testdata",
"commit": "cad17f24e22c19c6cefe6f647185395cc0a11add",
"license": "LGPL-3.0",
"dataset": "Public Reek geological and simulation ROFF exports with RMS-origin provenance",
"integrity": "Seven immutable files verified by embedded SHA-256 and byte counts."
},
"capabilities_demonstrated": [
"XTGeo ROFF ingestion, grid QC, 2x2x4 blocking, facies spreading, GRDECL export",
"NeqSim master-source SRK characterization and black-oil PVT generation",
"OPM Flow corner-point simulation with summary and restart-state inspection",
"ERT four-realization ensemble experiment using the FLOW forward model",
"NeqSim surface-process handover and governed RMS-agent job contract"
],
"engineering_validation": {
"named_assertions_passed": 26,
"assertions_failed": 0,
"retained_png_figures": 13
},
"result_summary": {
"data_commit": "cad17f24e22c19c6cefe6f647185395cc0a11add",
"neqsim_commit": "1f7a01b06307d9d56451e43bb8d6023d28d14007",
"neqsim_jar_sha256": "39e1de9738baaef18726c5d7a3f9cccf3a8af29a8e39761f90d92b870b0a857a",
"grid_dimensions": [
40,
64,
14
],
"active_cells": 35838,
"blocking": [
2,
2,
4
],
"porosity_blocking_rmse": 0.0918770723782011,
"bubble_pressure_bara": 193.24040031433105,
"base_final_pressure_bara": 223.61802673339844,
"base_final_cumulative_oil_million_sm3": 7.305,
"ert_realizations": 4,
"ert_final_oil_range_million_sm3": [
7.305,
7.305
],
"ert_final_pressure_range_bara": [
219.46754455566406,
230.8283233642578
],
"ert_final_water_rate_range_sm3_day": [
0.008757241070270538,
0.010717831552028656
],
"selected_process_realization": 0,
"compressor_power_MW": 2.680346000234267,
"process_mass_residual_kg_s": 5.423572702056845e-11,
"figures": [
"workflow_architecture.png",
"reek_structure_and_static_maps.png",
"reek_property_distributions.png",
"reek_blocking_comparison.png",
"reek_property_spreading_layers.png",
"reek_well_screening.png",
"neqsim_black_oil_pvt.png",
"opm_flow_forecast.png",
"opm_final_restart_maps.png",
"opm_3d_water_front.png",
"ert_flow_ensemble.png",
"ert_parameter_response.png",
"integrated_process_workflow.png"
],
"validation_checks_passed": 26,
"validation_checks_total": 26
},
"rendered_visual_validation": {
"renderer": "nbconvert 7.16.6 HTML with MathJax source and 13 retained Matplotlib PNG outputs",
"display_equations_inspected": 2,
"figures_inspected": 13,
"result": "passed",
"notes": "All retained figures were inspected at original resolution for titles, units, legends, color scales, clipping, overlap, physical sign conventions, and agreement with stored numerical tables. Visual QA replaced a misleading offset oil-rate ensemble panel with injection, pressure, and water-front responses and made the zero gas-saturation scale explicitly non-negative. Display equations use Colab-safe dollar delimiters and passed the notebook checker."
},
"known_upstream_issue": null,
"issue_handling": "No upstream defect is claimed; limitations distinguish teaching assumptions from decision-grade RMS studies."
}
]
}
4 changes: 2 additions & 2 deletions notebooks/notebook_maintenance_ledger.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"schema_version": 3,
"updated_at": "2026-08-24T16:40:49Z",
"active_notebook_count": 294,
"updated_at": "2026-08-31T17:15:07Z",
"active_notebook_count": 295,
"shards_glob": "maintenance_ledger/*.json",
"retired_notebooks": [
{
Expand Down
Loading
Loading