SiliciclasticReservoirs
1,000,000 synthetic 3D siliciclastic-reservoir geology cubes generated from rule-based sedimentological simulations (turbidite lobes + 6 fluvial-channel architectures + delta-fan distributary). Cubes are voxelized at (64, 64, 32) cells. Each sample carries facies, porosity, permeability, and a structured set of geological conditioning parameters.
Designed to train conditional generative models (flow matching, diffusion, etc.) of subsurface geology under interpretable physical conditioning.
Quick stats
- 1,000,000 samples across 8 reservoir architectures
- Cube shape:
(64, 64, 32)voxels —(x, y, z),zis depth (0 = base) - 4 voxel arrays per sample: binary facies, 6-class facies, porosity, permeability
- Compact slim parquet (9–12 cols) and full reproducibility parquet (25–75 cols)
- Captions for text-conditioning experiments
- Fully reproducible — every sample regenerable from
(seed, params)
File structure
SiliciclasticReservoirs/
├── README.md ← this file
├── DATASHEET.md ← Datasheet for Datasets (Gebru et al. 2018)
├── splits/ ← deterministic 90/5/5 split, stratified by layer_type
│ ├── train.parquet ← 900,000 rows
│ ├── validation.parquet ← 50,000 rows
│ └── test.parquet ← 50,000 rows
├── lobe/ ← 200,000 samples
│ ├── shard_0000/
│ │ ├── facies.npy (n, 64, 64, 32) int8 — binary 0/1
│ │ ├── facies_alluvsim.npy (n, 64, 64, 32) int8 — 6-class -1..4
│ │ ├── poro.npy (n, 64, 64, 32) float16 — porosity in [0, 0.5]
│ │ ├── perm.npy (n, 64, 64, 32) float16 — permeability in mD [0, 60000]
│ │ ├── params_slim.parquet ← training conditioning (use this)
│ │ └── params.parquet ← full physics for reproducibility
│ ├── shard_0001/
│ └── … 256 shards total
├── channel_pv_shoestring/ ← 100,000 samples, 256 shards
├── channel_cb_labyrinth/ ← 100,000 samples, 256 shards
├── channel_cb_jigsaw/ ← 150,000 samples, 256 shards
├── channel_sh_distal/ ← 100,000 samples, 256 shards
├── channel_sh_proximal/ ← 100,000 samples, 256 shards
├── channel_meander_oxbow/ ← 100,000 samples, 256 shards
└── delta/ ← 150,000 samples, 256 shards
256 shards per preset, each ~380 MB – 1.2 GB depending on per-shard sample count.
Layer types
layer_type | architecture | samples |
|---|---|---|
lobe | turbidite lobe (deep-water gravity-flow deposit) | 200,000 |
channel:PV_SHOESTRING | paleo-valley shoestring sandstone | 100,000 |
channel:CB_JIGSAW | channel-and-bar bodies, jigsaw connectivity | 150,000 |
channel:CB_LABYRINTH | channel-and-bar bodies, labyrinthine connectivity | 100,000 |
channel:SH_DISTAL | distal sheet-sandstone | 100,000 |
channel:SH_PROXIMAL | proximal sheet-sandstone | 100,000 |
channel:MEANDER_OXBOW | multi-storey meander-belt with oxbow plugs | 100,000 |
delta | prograding distributary-fan delta | 150,000 |
These follow Pyrcz & Deutsch's standard fluvial-architecture taxonomy ("User Guide to the Alluvsim Program", 2004).
Voxel arrays per sample
| file | dtype | shape | description |
|---|---|---|---|
facies.npy | int8 | (N, 64, 64, 32) | binary facies: 0 = mud, 1 = sand. Primary signal for generative training. |
facies_alluvsim.npy | int8 | (N, 64, 64, 32) | 6-class facies preserving architectural sub-detail: -1 = FF (overbank fines), 0 = FFCH (mud plug), 1 = CS (crevasse splay), 2 = LV (levee), 3 = LA (lateral-accretion / point-bar), 4 = CH (active channel). Lobe samples only contain {-1, 3}. |
poro.npy | float16 | (N, 64, 64, 32) | porosity, range [0, 0.5] |
perm.npy | float16 | (N, 64, 64, 32) | permeability in millidarcies (mD), range [0, 60000]. Use log10(perm + 1e-3) for ML — perm spans 5+ decades. |
All four arrays are row-aligned within a shard (sample i of facies corresponds to row i of the parquets and to sample i of all other arrays).
Slim parquet (params_slim.parquet) — the training conditioning
This is what you train on as conditioning. It carries the geological parameters that vary across samples.
Universal columns (all 8 layer types)
| column | dtype | description |
|---|---|---|
layer_type | str | one of the 8 strings above |
caption | str | human-readable description, e.g. "Paleo-valley shoestring reservoir with sinuosity 1.55, channel depth 9.7 m, …". Useful for text-conditioned variants. |
ntg | float32 | realized net-to-gross over active cells (post-crop), range [0, 1] |
poro_ave | float32 | realized mean porosity over active cells |
perm_ave | float32 | realized mean of log10(perm in mD) over active cells |
azimuth | float32 | regional flow direction, compass-CW degrees [0, 360) |
width_cells | float32 | characteristic horizontal extent in cells. Lobe = 2 × semi-minor diameter. Channel/delta = full channel width. |
depth_cells | float32 | characteristic vertical extent in cells. Lobe = thickness dh_ave. Channel/delta = mCHdepth. |
Family-specific columns (NULL outside family)
| column | dtype | family | description |
|---|---|---|---|
asp | float32 | lobe | ellipse aspect ratio (major/minor), [1.0, 2.5] |
mCHsinu | float32 | channel + delta | sinuosity (path / straight-line), [1.05, 1.85] |
probAvulInside | float32 | channel + delta | per-event in-belt avulsion probability, [0, 0.8] |
mFFCHprop | float32 | channel + delta | abandoned-channel mud-plug fraction, [0, 0.7] |
trunk_length_fraction | float32 | delta | proximal-trunk fraction protected from avulsion (controls fan-apex position), [0.1, 0.5] |
Total: 9 cols for lobe rows, 11 for channel rows, 12 for delta rows. Rows from different families share the universal columns and have NULL in non-applicable family columns.
Full parquet (params.parquet) — for reproducibility
25 columns for lobe rows, 73 for channel rows, 75 for delta rows. Includes the per-realization seeds, the per-event statistical knob widths (stdev*), the engine-internal event-budget knobs (ntime*), and the FACIES_PROPS extras. Don't train on this — most columns are constant or redundant. Useful for:
- Re-generating a specific sample bit-for-bit (
ChannelLayer(...).create_geology(**row.to_dict())with the saved seed) - Diagnostic analysis of the engine's behavior
Splits
splits/{train,validation,test}.parquet define a deterministic 90 / 5 / 5 partition stratified by layer_type (each split has all 8 architectures in proportion). Generated with seed 42.
Each row is (layer_type, shard_dir, sample_idx) pointing into one of the data shards.
Cell-physical-size note
Cube shape is identical (64×64×32) but the physical cell size differs by family:
| family | dx = dy | dz | physical extent |
|---|---|---|---|
lobe | 100 m | 1 m | 6.4 km × 6.4 km × 32 m |
channel:* and delta | 10 m | 1 m | 640 m × 640 m × 32 m |
For training in cell-units, this difference is hidden inside width_cells / depth_cells. The model can ignore physical scale and just train on the cube as-is.
Loading example (PyTorch)
import numpy as np
import pyarrow.parquet as pq
from pathlib import Path
import torch
from torch.utils.data import IterableDataset
class ReservoirShardDataset(IterableDataset):
"""One worker walks an assigned subset of shards, yields (cube, params)."""
def __init__(self, root: Path, split: str = "train"):
self.root = Path(root)
# Read split index
self.index = pq.read_table(self.root / f"splits/{split}.parquet").to_pylist()
def __iter__(self):
worker = torch.utils.data.get_worker_info()
my_rows = (self.index if worker is None
else self.index[worker.id::worker.num_workers])
cur_shard = None; cur_data = None
for row in my_rows:
shard_dir = self.root / row["shard_dir"]
if shard_dir != cur_shard:
cur_shard = shard_dir
cur_data = {
"facies": np.load(shard_dir / "facies.npy", mmap_mode="r"),
"poro": np.load(shard_dir / "poro.npy", mmap_mode="r"),
"perm": np.load(shard_dir / "perm.npy", mmap_mode="r"),
"params": pq.read_table(
shard_dir / "params_slim.parquet").to_pylist(),
}
i = row["sample_idx"]
yield {
"facies": np.asarray(cur_data["facies"][i], dtype=np.int8),
"poro": np.asarray(cur_data["poro"][i], dtype=np.float32),
"perm": np.asarray(cur_data["perm"][i], dtype=np.float32),
"params": cur_data["params"][i],
}
ds = ReservoirShardDataset("/path/to/SiliciclasticReservoirs", split="train")
loader = torch.utils.data.DataLoader(ds, batch_size=8, num_workers=4)
Recommended preprocessing for flow-matching training
facies→[0, 1]float: justcube.astype(np.float32)poro→ standardized:(poro - 0.15) / 0.10keeps it roughly N(0, 1)-ish for sand cellsperm→ log-perm:np.log10(np.maximum(perm, 1e-3)), then maybe standardizelayer_type→ categorical embedding (8 classes). Uselayer_type.split(":")[0]for family-level (3 classes) or full string for fine-grained (8 classes).- Other slim columns → continuous embeddings, with
null→ learned sentinel or per-family mask.
Geological caveats
- Channel topology is tree-like, not anastomosing. Avulsions split channels but never re-merge. The braided / jigsaw look in CB_LABYRINTH / CB_JIGSAW comes from heavily overlapping stamps in the cube, not from explicit topological merging. For facies-based generative training this doesn't matter; for downstream flow simulation, be aware.
- Per-cell poro/perm follow a Walker-1992 upward-fining ramp (highest at thalweg base, decaying upward and laterally toward banks) plus a per-event Kozeny-Carman-coupled draw plus a per-realization "regional rock quality" multiplier. Channels in the same cube vary in quality (different events had different sediment supply); different cubes span the full quality range.
- Channels have FACIES_PROPS-driven base poro/perm values that are conservative midpoints from fluvial-reservoir literature (Pyrcz & Deutsch 2002, Allen 1965, Walker 1992); they're not from a specific reservoir analog.
- Delta has no mouth bars painted (
paint_mouth_bars=False). The delta is a distributary network, not a clinoform with bar deposits. - Cubes are post-cropped (8 cells trimmed from each lateral edge, 9 from top + 9 from bottom of z) to remove engine boundary artifacts. The internal engine ran on a slightly larger grid before cropping.
See DATASHEET.md for full documentation.
Citation
@misc{SiliciclasticReservoirs_2026,
author = {Anonymous},
title = {{SiliciclasticReservoirs}: 1M Synthetic 3D Reservoir Geology Cubes for Conditional Generative Modeling},
year = {2026},
publisher = {HuggingFace},
howpublished = {\url{https://huggingface.co/datasets/AnonymouScientist/SiliciclasticReservoirs}}
}
License
Creative Commons Attribution 4.0 International (CC-BY-4.0). Use, share, modify, redistribute — just attribute the source.
Contact / Issues
File issues at the dataset repository on HuggingFace.