Reservoir Simulation History Match Review

A reservoir engineer history matches a field before a development plan goes in. Each iteration is a full simulation run, and the simulator writes a set of files sharing one base name: an EGRID of geometry, an INIT of static properties, a UNRST restart file with one set of arrays per report step, and a SMSPEC naming the well vectors. Two runs land a day apart, four files each, 37248 array elements in total. One reader serves all four file types because the rows are long form, one per array element carrying its keyword, occurrence and index: a wide table would need a column per keyword and there is no fixed set of them. The load pivots that into one row per cell per report step, joining the restart file's pressure to the initialisation file's porosity on the element index, because the element index IS the cell index. The grid is 1152 cells against a 1000-element record limit, so every property array spans two records: a reader that assumes one returns the first thousand cells and no error. The review is the last query. HM12 has the aquifer too weak and misses the observed decline by 20 bar on average and 37 at the final step; HM13 lands within 4 and 8.

Category: subsurface

Syntax

-- ============================================================================
-- Reservoir Simulation History Match Review - Setup Script
-- ============================================================================
-- A reservoir engineer is history matching a field before a development plan
-- goes in. Each iteration of the match is a full simulation run, and the
-- simulator writes a set of files sharing one base name:
--
--   .EGRID    grid geometry and which cells are active
--   .INIT     static properties, written once at initialisation
--   .UNRST    the restart file, one set of arrays per report step
--   .SMSPEC   the summary specification, naming the well vectors
--
-- Two runs land, a day apart. Run HM12 has the aquifer too weak and its
-- pressure falls away from the observed decline; HM13 strengthens it. Deciding
-- which is closer is the whole job, and it is a SQL question once the files
-- are readable at all.
--
--   11 March   HM12   four files, 18624 array elements
--   12 March   HM13   four files, 18624 array elements
--
--   1. sim_arrays     external, DISCOVER over the landing folder
--   2. cell_pressure  DELTA, pressure and saturation per cell per step
-- ============================================================================

-- ----------------------------------------------------------------------------
-- STEP 1: Zone and schema
-- ----------------------------------------------------------------------------

CREATE ZONE IF NOT EXISTS {{zone_name}} TYPE EXTERNAL
    COMMENT 'External tables - demo datasets and file-backed data';

CREATE SCHEMA IF NOT EXISTS {{zone_name}}.simulation
    COMMENT 'ECLIPSE simulator output read in place, pivoted into Delta';


-- ----------------------------------------------------------------------------
-- STEP 2: Register the landing folder with DISCOVER
-- ----------------------------------------------------------------------------
-- One reader serves the whole family. An EGRID, an INIT, a UNRST and a SMSPEC
-- hold completely different things, so the rows are LONG FORM: one row per
-- array element, carrying the keyword it came from, which occurrence of that
-- keyword, its index within the array, and its value or its text.
--
-- That is what lets a single external table span all eight files. A wide
-- table would need a column per keyword and there is no fixed set of them:
-- a restart file's keywords depend on what the engineer asked the simulator
-- to output.
-- ----------------------------------------------------------------------------

DROP EXTERNAL TABLE IF EXISTS {{zone_name}}.simulation.sim_arrays;

DISCOVER {{zone_name}}.simulation.sim_arrays
    PATH '{{data_subdir}}/landing'
    WITH (FILE_METADATA = true);


-- ----------------------------------------------------------------------------
-- STEP 3: The curated Delta table
-- ----------------------------------------------------------------------------
-- Long form is right for reading the files and wrong for asking questions of
-- them, so the load pivots. One row per cell per report step, with the
-- dynamic properties from the restart file and the static porosity from the
-- initialisation file beside them.
--
-- Those come from two different files, and they line up because the element
-- index IS the cell index: array element 500 of PRESSURE and array element
-- 500 of PORO are the same cell. That is the contract the format guarantees
-- and the reason the join needs no geometry.
-- ----------------------------------------------------------------------------

CREATE DELTA TABLE IF NOT EXISTS {{zone_name}}.simulation.cell_pressure (
    run           VARCHAR,
    delivered_on  VARCHAR,
    source_file   VARCHAR,
    report_step   INTEGER,
    cell_index    INTEGER,
    pressure      DOUBLE,
    swat          DOUBLE,
    poro          DOUBLE
) LOCATION '{{data_subdir}}/curated/cell_pressure';

Description

## What this demo does A reservoir engineer history matches a field before a development plan goes in. Each iteration is a full simulation run, and the simulator writes a set of files sharing one base name: an EGRID of geometry, an INIT of static properties, a UNRST restart file with one set of arrays per report step, and a SMSPEC naming the well vectors. Two runs land a day apart, four files each, 37248 array elements in total. One reader serves all four file types because the rows are long form, one per array element carrying its keyword, occurrence and index: a wide table would need a column per keyword and there is no fixed set of them. The load pivots that into one row per cell per report step, joining the restart file's pressure to the initialisation file's porosity on the element index, because the element index IS the cell index. The grid is 1152 cells against a 1000-element record limit, so every property array spans two records: a reader that assumes one returns the first thousand cells and no error. The review is the last query. HM12 has the aquifer too weak and misses the observed decline by 20 bar on average and 37 at the final step; HM13 lands within 4 and 8. ## What it creates - `{{zone_name}}.simulation.sim_arrays` (external table) - `{{zone_name}}.simulation.cell_pressure` (delta table) ## Running it The demo ships `setup.sql`, `queries.sql` and `cleanup.sql` under `demos/subsurface/eclipse-history-match-review`. The queries carry their own `ASSERT`s, so a run that completes has verified its own numbers. Data: 8 files, 0.1 MB.

See Also

Open in interactive docs →   DeltaForge home →