Static Model Deck Ingestion

A static-model archive receives ECLIPSE GRDECL decks from two places and the simulation team loads both to check the property distributions before building a run. The first is real: the published model of the Norne field, offshore Norway, under the Open Database License, 46 by 112 by 22 and 113,344 cells of which only 44,927 are solved. The second is a coarse sector model, 30 by 24 by 10. They are written in opposite styles, which is why one reader handling both is the thing worth showing. A GRDECL property is run-length encoded, so 720*0.263 is seven hundred and twenty cells rather than one; the sector deck writes 36,000 values as 62 numeric tokens in a kilobyte, and the Norne deck uses no repeats at all, writing 453,376 values as 453,376 tokens in 5.7 MB. A reader that skips the expansion gets Norne exactly right and turns the sector model into 62 cells with no error. Real data brings real structure with it: layer 3 of Norne is entirely inactive, and layer 0 holds 2221 cells with 2221 distinct porosities, 2220 distinct permeabilities because exactly one pair collides, and 1981 distinct net-to-gross values. Inactive cells are dropped by default because their values are in the file and mean nothing, and a second table with include_inactive answers the different question of what the model covers. The i, j and k indices are derived from the grid header rather than read, so separate keywords line up on the same cell without a join. It closes on the number a static model exists to produce: net-to-gross takes 13 percent off the Norne pore volume and 24 percent off the sector model.

Category: subsurface

Syntax

-- ============================================================================
-- Static Model Deck Ingestion - Setup Script
-- ============================================================================
-- A static-model archive receives ECLIPSE GRDECL decks from two places, and
-- the simulation team loads both to check the property distributions before
-- building a run: is the porosity sensible layer by layer, does permeability
-- follow it, and how many cells does the model actually solve.
--
--   11 March   norne_2004     the Norne field's own model, 46 x 112 x 22
--   12 March   sector_model   a coarse sector model, 30 x 24 x 10
--
-- The two decks are written completely differently, which is the point of
-- loading them through one reader:
--
--   norne_2004     453,376 values, written out one per cell, 5.7 MB
--   sector_model    36,000 values, written as 62 tokens, 1.1 kB
--
-- A GRDECL property is RUN-LENGTH ENCODED: `720*0.263` is seven hundred and
-- twenty cells of 0.263, not one cell holding a string. The Norne deck happens
-- to use no repeats at all and the sector deck is almost nothing but repeats,
-- so between them they exercise both halves of the parser.
--
-- The Norne deck is real. See ATTRIBUTION.md in the parent folder: it is the
-- published Norne model under the Open Database License, assembled from the
-- property files it ships as separate INCLUDE files with its own grid
-- dimensions in front, which is what a simulator sees once it has resolved
-- those includes. The property blocks are byte for byte the files they came
-- from, licence headers and all.
--
--   1. norne        external, DISCOVER over the real deck
--   2. norne_all    external, the same deck with its inactive cells kept
--   3. sector       external, DISCOVER over the run-length encoded deck
--   4. static_model DELTA, the curated model
-- ============================================================================

-- ----------------------------------------------------------------------------
-- 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}}.static_modelling
    COMMENT 'GRDECL static model decks read in place, curated into Delta';


-- ----------------------------------------------------------------------------
-- STEP 2: Register both decks with DISCOVER
-- ----------------------------------------------------------------------------
-- One row per cell, one column per property keyword, with i, j and k derived
-- from the grid dimensions. That derivation is what makes several properties
-- of one model line up on the same cell without a join: porosity and
-- permeability are different keywords in the file and the same row here.
--
-- The decks are registered separately because they are different grids with
-- different keywords, and a curated table that holds both is the right place
-- to reconcile that rather than the scan.
--
-- Inactive cells are dropped by default. A cell outside the model has property
-- values in the file and no meaning, and averaging it in is how a model's
-- porosity quietly drifts. On Norne that matters more than it sounds: three
-- cells in five are inactive.
-- ----------------------------------------------------------------------------

DROP EXTERNAL TABLE IF EXISTS {{zone_name}}.static_modelling.norne;

DISCOVER {{zone_name}}.static_modelling.norne
    PATH '{{data_subdir}}/landing/2026-03-11_norne_2004.grdecl'
    WITH (FILE_METADATA = true);

DROP EXTERNAL TABLE IF EXISTS {{zone_name}}.static_modelling.sector;

DISCOVER {{zone_name}}.static_modelling.sector
    PATH '{{data_subdir}}/landing/2026-03-12_sector_model.grdecl'
    WITH (FILE_METADATA = true);

-- (excerpt; run the demo for the full script)

Description

## What this demo does A static-model archive receives ECLIPSE GRDECL decks from two places and the simulation team loads both to check the property distributions before building a run. The first is real: the published model of the Norne field, offshore Norway, under the Open Database License, 46 by 112 by 22 and 113,344 cells of which only 44,927 are solved. The second is a coarse sector model, 30 by 24 by 10. They are written in opposite styles, which is why one reader handling both is the thing worth showing. A GRDECL property is run-length encoded, so 720*0.263 is seven hundred and twenty cells rather than one; the sector deck writes 36,000 values as 62 numeric tokens in a kilobyte, and the Norne deck uses no repeats at all, writing 453,376 values as 453,376 tokens in 5.7 MB. A reader that skips the expansion gets Norne exactly right and turns the sector model into 62 cells with no error. Real data brings real structure with it: layer 3 of Norne is entirely inactive, and layer 0 holds 2221 cells with 2221 distinct porosities, 2220 distinct permeabilities because exactly one pair collides, and 1981 distinct net-to-gross values. Inactive cells are dropped by default because their values are in the file and mean nothing, and a second table with include_inactive answers the different question of what the model covers. The i, j and k indices are derived from the grid header rather than read, so separate keywords line up on the same cell without a join. It closes on the number a static model exists to produce: net-to-gross takes 13 percent off the Norne pore volume and 24 percent off the sector model. ## What it creates - `{{zone_name}}.static_modelling.norne` (external table) - `{{zone_name}}.static_modelling.norne_all` (external table) - `{{zone_name}}.static_modelling.sector` (external table) - `{{zone_name}}.static_modelling.static_model` (delta table) ## Running it The demo ships `setup.sql`, `queries.sql` and `cleanup.sql` under `demos/subsurface/grdecl-static-model`. The queries carry their own `ASSERT`s, so a run that completes has verified its own numbers. Data: 2 files, 5.5 MB.

See Also

Open in interactive docs →   DeltaForge home →