Depth Surface Handover and Gross Rock Volume

A geophysicist depth-converts a seismic interpretation and hands the result to the mapping team as ZMAP+ grids, who load them to compute gross rock volume, the number a prospect is sized on. Three grids over two days: a first pass at the top reservoir, then a revised top after the velocity model was corrected, and the base surface that turns the pair into a volume. Each grid is 45 rows by 60 columns on a 200 m spacing, so 2700 nodes of which 1441 fall inside the mapped polygon. Two properties of the format decide whether a reader gets it right and both are asserted: values run column by column rather than row by row, so a row-major reader produces a grid of exactly the right size where every node holds a neighbour's value, and nodes outside the polygon carry a 1e30 sentinel which, read as a number, does not merely skew an average but obliterates it. The grid is 45 by 60 rather than square on purpose, so a transposed read runs off the end instead of quietly succeeding. The file holds no coordinates at all, only a corner and an extent, so the demo checks the arithmetic the reader does. It closes on two billion cubic metres of rock, computed against the corrected top.

Category: subsurface

Syntax

-- ============================================================================
-- Depth Surface Handover and Gross Rock Volume - Setup Script
-- ============================================================================
-- A geophysicist depth-converts a seismic interpretation and hands the result
-- to the mapping team as ZMAP+ grids. The team loads them to compute gross
-- rock volume, which is the number a prospect is sized on, and to compare one
-- depth-conversion iteration against the next.
--
--   11 March   TOP_HUGIN_V1                  the first pass
--   12 March   TOP_HUGIN_V2, BASE_HUGIN      the corrected top, and the base
--
-- Each grid is 45 rows by 60 columns on a 200 m spacing, so 2700 nodes of
-- which 1441 fall inside the mapped polygon and 1259 were never interpreted.
--
--   1. depth_grids     external, DISCOVER over the landing folder
--   2. all_nodes       external, the same first grid with its blanks kept
--   3. depth_surfaces  DELTA, the curated surfaces
-- ============================================================================

-- ----------------------------------------------------------------------------
-- 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}}.mapping
    COMMENT 'ZMAP+ depth grids read in place, curated into Delta';


-- ----------------------------------------------------------------------------
-- STEP 2: Register the landing folder with DISCOVER
-- ----------------------------------------------------------------------------
-- One row per grid node, with the real-world coordinate already computed from
-- the header's extent and the node's position in the stream. The file itself
-- holds no coordinates at all: it holds a corner, an extent and a run of
-- numbers, and the reader does the arithmetic.
--
-- Nodes outside the mapped polygon carry a null sentinel of 1e30 and are
-- dropped by default, which is almost always what a query wants: read as a
-- number, one of them in an average destroys the answer.
-- ----------------------------------------------------------------------------

DROP EXTERNAL TABLE IF EXISTS {{zone_name}}.mapping.depth_grids;

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


-- ----------------------------------------------------------------------------
-- STEP 3: The same grid with its blank nodes kept
-- ----------------------------------------------------------------------------
-- include_null_nodes turns the sentinel into a real NULL and keeps the row,
-- which is what a query about the SHAPE of the mapped area needs: the blanks
-- are where the interpretation stops, and that outline is data.
-- ----------------------------------------------------------------------------

DROP EXTERNAL TABLE IF EXISTS {{zone_name}}.mapping.all_nodes;

DISCOVER {{zone_name}}.mapping.all_nodes
    PATH '{{data_subdir}}/landing/2026-03-11_top_hugin_v1.zmap'
    WITH (include_null_nodes = 'true');


-- ----------------------------------------------------------------------------
-- STEP 4: The curated Delta surfaces
-- ----------------------------------------------------------------------------
-- The grid indices are renamed here. `row` and `column` are reserved words,
-- and a curated table nobody has to quote to query is worth the rename.
-- ----------------------------------------------------------------------------

CREATE DELTA TABLE IF NOT EXISTS {{zone_name}}.mapping.depth_surfaces (
    surface       VARCHAR,
    iteration     INTEGER,
    delivered_on  VARCHAR,
    source_file   VARCHAR,
    grid_row      INTEGER,
    grid_column   INTEGER,
    x             DOUBLE,
    y             DOUBLE,
    depth_m       DOUBLE
) LOCATION '{{data_subdir}}/curated/depth_surfaces';

Description

## What this demo does A geophysicist depth-converts a seismic interpretation and hands the result to the mapping team as ZMAP+ grids, who load them to compute gross rock volume, the number a prospect is sized on. Three grids over two days: a first pass at the top reservoir, then a revised top after the velocity model was corrected, and the base surface that turns the pair into a volume. Each grid is 45 rows by 60 columns on a 200 m spacing, so 2700 nodes of which 1441 fall inside the mapped polygon. Two properties of the format decide whether a reader gets it right and both are asserted: values run column by column rather than row by row, so a row-major reader produces a grid of exactly the right size where every node holds a neighbour's value, and nodes outside the polygon carry a 1e30 sentinel which, read as a number, does not merely skew an average but obliterates it. The grid is 45 by 60 rather than square on purpose, so a transposed read runs off the end instead of quietly succeeding. The file holds no coordinates at all, only a corner and an extent, so the demo checks the arithmetic the reader does. It closes on two billion cubic metres of rock, computed against the corrected top. ## What it creates - `{{zone_name}}.mapping.depth_grids` (external table) - `{{zone_name}}.mapping.all_nodes` (external table) - `{{zone_name}}.mapping.depth_surfaces` (delta table) ## Running it The demo ships `setup.sql`, `queries.sql` and `cleanup.sql` under `demos/subsurface/zmap-depth-surfaces`. The queries carry their own `ASSERT`s, so a run that completes has verified its own numbers. Data: 3 files, 0.2 MB.

See Also

Open in interactive docs →   DeltaForge home →