# Changelog
All notable changes to petekSim are documented here. The format is based on
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres
to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [0.1.13] - 2026-07-14
### Changed
- Added executable acceptance for the updated viewer design schema: coherent
typed map, volume, polyline/AlongBore section, orientation, well-tie, contact,
pinch-out, sugar-cube, and zero-spread realization artifacts now round-trip
through petekSim's save/serve delivery seam.
- Added an exact registry-seam acceptance mode that verifies real out-of-core
map/section/volume exports and captures petekStatic's actual spill notice.
- Raised release-train dependency floors to `petektools 0.2.15`,
`petekio 0.3.15`, and `petekstatic 0.1.13` for Rust and the Python wheel.
## [0.1.12] - 2026-07-13
### Changed
- Contributor guidance now describes repository-local research references as
internal study material; runtime behaviour and public APIs are unchanged.
## [0.1.11] - 2026-07-10
### Changed
- CI now builds the abi3 wheel once and validates that exact artifact on Python
3.10–3.14, with the installed-wheel Python suite retained on Python 3.12.
- Release artifacts build in parallel with the Rust gates, while publication
remains blocked on both the gates and release tag.
- The world-coordinate fallback regression keeps the same boundary conditions on
a compact grid, avoiding a production-sized interpolation solve in unit tests.
- petekStatic's optional petekIO compatibility adapter is no longer compiled or
retested by petekSim; normal product builds consume petekStatic's independent
core, while each library retains tests for the seam it owns.
## [0.1.10] - 2026-07-09
### Fixed
- `examples/model_build_v2.py` now runs end to end; the showcased model-build
flow had drifted from the current facade API.
### Changed
- Release-train dependency floor: `petekio 0.3.9` (Rust and Python wheel). That
release changes what `PointSet.infer_geometry(edge="occupied")` returns and
removes the `concave_hull`/`trimesh` edge aliases; petekSim does not use
`GeometryEdge`, so nothing in this package changes behaviour.
## [0.1.9] - 2026-07-08
### Changed
- Updated release-train dependency floors to `petektools 0.2.7`,
`petekio 0.3.8`, and `petekstatic 0.1.11`; the Python wheel now requires
those published floors so petekSim consumes the current topology-aware
point-edge, corrected 2-D viewer point/geometry rendering, and downstream
static workflow coherence releases.
## [0.1.8] - 2026-07-08
### Changed
- Updated release-train dependency floors to `petektools 0.2.6`,
`petekio 0.3.7`, and `petekstatic 0.1.10`; the Python wheel now requires
those published floors so petekSim consumes the current point-edge,
structured mesh surface, and viewer topology-grid QA releases.
- Hardened CI/release wheel install checks with retrying binary-only installs
and added a PyPI visibility verification job before GitHub Release creation.
## [0.1.7] - 2026-07-08
### Changed
- Updated release-train dependency floors to `petektools 0.2.5`,
`petekio 0.3.6`, and `petekstatic 0.1.9`; the Python wheel now requires
those published floors so petekSim consumes the current project/object,
interpolation, and static workflow releases.
## [0.1.6] - 2026-07-08
### Changed
- Updated release-train dependency floors to `petekio 0.3.5` and
`petekstatic 0.1.8`; the Python wheel now requires `petekio>=0.3.5` and
`petekstatic>=0.1.8`.
- Updated public docs to use petekIO's current raw-import API:
`petekio.Project.import_data(..., settings=petekio.ImportSettings(...))`.
## [0.1.5] - 2026-07-07
### Changed
- Updated release-train dependency floors to `petekio 0.3.4` and
`petekstatic 0.1.7`; the Python wheel now requires `petekio>=0.3.4` and
`petekstatic>=0.1.7`.
## [0.1.4] - 2026-07-07
### Changed
- Removed public project-loading/project-handling exports from `peteksim`; the
project container and loading API now live in `petekio`.
- Updated docs and tests so examples use `petekio.Project.load(...)` and
`project.wells.logs` instead of project handling through petekSim.
- Updated release-train dependency floors to `petekio 0.3.3`,
`petektools 0.2.4`, and `petekstatic 0.1.6`; the Python wheel requires
`petektools>=0.2.4`, `petekio>=0.3.3`, and `petekstatic>=0.1.6`.
- Updated CI and release workflows to current action versions and the
Actions-owned release flow.
## [0.1.3] - 2026-07-07
### Changed
- **Static property workflow compatibility now delegates to petekStatic.**
`peteksim.upscale`, `peteksim.distributions`, `peteksim.Var`,
`peteksim.Grid`, `peteksim.PropertyPipelineSpec`, `peteksim.WellLogSpec`,
`peteksim.PropertyPipeline`, and `peteksim.WellLog` are a narrow shim to the
canonical petekStatic workflow API. Legacy `ps.Prop(...)` / `ps.Props(...)`
constructors still work for existing petekSim specs, but emit deprecation
guidance toward petekStatic.
- **Release-train dependency floors are current.** The Rust crate resolves
against `petekio 0.3.2`, `petektools 0.2.3`, and `petekstatic 0.1.5`; the
Python wheel requires `petektools>=0.2.3` and `petekstatic>=0.1.5`.
## [0.1.2] - 2026-07-06
### Changed
- **Consume the fortified petekIO/petekTools foundations.** Project ingest now
classifies files through `petekio::detect()` with legacy fallback only for
`Unknown`, loads detected well files anywhere under the project root, and reads
Petrel `Type == "Other"` fluid contacts from petekIO's bore-contact seam instead
of the old facade-side parser.
- **`peteksim.synth_asset` is now a compatibility shim over
`petektools.synth_asset`.** The petekSim-owned `spill_recipe` helper remains,
and the shim preserves the manifest `spill_recipe` key for existing callers.
### Fixed
- **Outline resolution is loud.** An explicit missing `outline="Name"` now errors
with the loaded polygon inventory. An omitted outline still tries `ModelEdge`,
then falls back to the framework bbox with a visible warning if `ModelEdge` is
absent.
## [0.1.1] - 2026-07-05
### Changed
- **Require `petektools>=0.2.1` in the wheel.** The published 0.1.0 wheel's
metadata allowed petektools 0.2.0, whose wheels are unimportable on Python
3.10/3.11 — so upgraders could keep the broken viewer dependency. The 0.1.1
floor forces the fixed release, repairing `model.view()` / `save_view()`
imports on Python 3.10/3.11 for anyone upgrading.
- **Release workflow is now gated on CI.** The tag-triggered Release run
executes the same fmt / clippy / test bar as CI in a `gates` job before any
build or publish job starts — a red gate blocks the release by construction.
### Fixed
- **Clippy `manual_option_zip` (Rust 1.96).** Lint fix only; no behaviour
change.
## [0.1.0] - 2026-07-05
First public release of **`peteksim`** — the Python-facing appraisal toolkit: a
pure-Rust reservoir core with thin bindings that presents the whole
subsurface-modelling stack (ingest → geomodel → volumetrics → uncertainty) as one
facade. From a Petrel export to a STOIIP P-curve in a handful of calls.
All inputs and outputs are **SI/metric**: areas in km², lengths/depths in metres
(positive-down), volumes in Sm³ (reported in MSm³ for oil, bcm for gas), GRV in
mcm (10⁶ m³), FVF as dimensionless Rm³/Sm³. Imperial is opt-in on your side, never
a default.
### Added — the declarative modelling API (v2, the primary surface)
- **Specs applied at explicit moments.** A model is built from immutable, declarative
**spec** values that say WHAT (`Horizons`, `Subzones`, `Layering`, `Contacts`,
`Props`, `Mc`) or HOW (`TieSettings`, `Gridding`, `Run`, `ViewSettings`).
A spec holds **names**, not project objects — so it is
project-independent, reusable across re-exports and synthetic assets. It is applied
at three explicit moments: `proj.grid_geometry(...)` → `geom.build(...)` →
`grid.model(...)` → `model.zoned_uncertainty(...)`.
- **Loud at apply.** Errors when a spec is applied name **both** the missing project
object and the spec entry. A spec field the engine cannot yet honour raises
`NotYetSupported` (never a silent no-op); an unresolvable name raises `ApplyError`.
- **Value semantics.** Every spec round-trips through a dict (`to_dict` / `from_dict`
/ `ps.spec_from_dict`), compares and hashes by value, derives with `.replace(...)`,
and pretty-prints as its own domain table — so a scenario is a savable, diffable
file. `ps.AssetSpec` bundles a whole scenario (load + structure + props + mc) into
one durable value.
- **Structure specs:** `ps.Horizons(ps.hz(...), zones=[...])` (the ordered
stratigraphic column + the zones between horizons; per-row well ties and structural
uncertainty via `ps.hz(tie=, sd=, vgm=)`), `ps.Subzones` / `ps.splits` (intra-zone
splits + conformity), `ps.Layering(dz= | nk=)`, `ps.Contacts({zone: {...}})`, and
`ps.zone(name, color=)`.
- **Property specs:** `ps.Props(ps.Prop("PORO", net_only=True, propagate=...))` — a
visible per-property pipeline of well upscaling then SGS propagation
(`ps.Propagate` + `ps.variogram(...)` + optional `ps.collocated(name, corr=)` trend,
`level_shift` / `resimulate` MC modes).
### Added — volumetrics, zoned Monte-Carlo, and P-curves
- **In-place volumes.** `grid.model(...)` returns a populated model; `model.summary()`
reports STOIIP / GIIP (MSm³) and GRV (mcm). Two-contact columns (gas cap + oil rim)
split automatically from the contact picks.
- **Zoned uncertainty.** `model.zoned_uncertainty(ps.Mc(...))` runs Monte-Carlo over
static-model realizations — per-zone contact draws and per-zone property level shifts
— and returns per-zone and total **P-curves** (`p90` / `p50` / `p10` / `mean`, with
`*_msm3` reporting scales) plus the full per-realization sample vectors.
- **Multi-zone stacks.** A multi-horizon stack unlocks per-zone layering, per-zone
contacts (a contactless zone contributes GRV with zero hydrocarbon), and per-zone
property pipelines. `model.in_place_by_zone()`, `model.zone_stats(prop)`, and
`model.well_tie_residuals()` report the breakdown; well ties tie each horizon to its
tops picks.
- **Tornado + aggregation.** A flat `model.uncertainty(...)` result exposes
`.tornado()` (ranked input swings); `ps.aggregate([...], correlation=...)` sums
segment realizations under an explicit dependence assumption.
### Added — the analytic box model
- **`ps.run_box_model(...)`** — a quick STOIIP/GIIP estimate with Monte-Carlo on each
volumetric input (a constant, a `(min, mode, max)` triangular, or a tagged
`{"normal"|"lognormal"|"uniform"|"triangular": [...]}` distribution). Returns
P90/P50/P10/mean/deterministic plus the full sample vector.
- **`ps.Model(...)`** — a structured box with real structural relief built in code
(`add_control(i, j, depth_m)` seeds a high), for a first look before a full project.
### Added — the browser viewer
- **`model.view()`** opens a tabbed, bundle-driven inspection viewer: **Map** (areal
rasters, outline, contact subcrop masks, well markers, draw-a-fence to cut a
section), **Intersection** (the vertical cross-section with horizon + contact traces
and the bore path), and **Volume** (the corner-point mesh in three.js with property
colouring, threshold, zone toggles, i/j/k clip planes). `view()` is non-blocking
(prints a URL and returns).
- **`model.save_view("m.html")`** writes ONE self-contained HTML file that opens off
`file://` with all data + JS inlined — no server, no network (confidential-data
safe). Bundle accessors `map_bundle` / `intersection_bundle` / `volume_bundle`
return the JSON directly. The renderer is petekTools' horizontal `petektools.viewer`
unit, which `peteksim` consumes.
### Added — resources and out-of-core
- **`ps.Run(memory_budget=<bytes>, workers=N)`** carries the run resources: `workers`
shards the MC realize loop; `memory_budget` forwards to the engine's out-of-core
switch (a larger-than-memory model spills to disk with a loud notice, never an OOM
kill).
### Deprecated
- **The v1 eight-call model-build chain** (`proj.framework(...)` → `set_zones` →
`build_grid` → per-property `upscale`/`propagate` → `grid.model` → `uncertainty` →
`tornado`) is deprecated in favour of the declarative v2 API, with a two-minor
window. It keeps working and emits a `DeprecationWarning`; new code should use
`proj.grid_geometry(...).build(ps.Horizons(...))`.
### Changed — packaging (internal, behaviour-neutral)
- **Consolidated the three published library crates into one.** `srs-units`,
`srs-pvt` and `srs-core` were merged into a single crate, **`peteksim`**
(0.1.0), at the repo root. Their boundaries are preserved as modules —
`peteksim::{units, pvt, core}` — and the headline Rust API (`run_model`, the
appraisal facade types, the `Distribution` seam, the view bundles) is
re-exported at the crate root. File moves + mechanical path rewrites only; no
logic changed. The workspace keeps its `crates/srs-py` member (the `peteksim`
wheel source), which now binds the `peteksim` crate; the published PyPI wheel
surface (`peteksim`) is unchanged.
- **Repointed the geomodel dependency at petekStatic's consolidated crate.** The
former per-crate path deps on petekStatic's `srs-*` crates are now a single
`petekstatic = "0.1.0"`; the `srs_model::` / `srs_grid::` / `srs_wireframe::`
(…) imports rewrote to `petekstatic::{model, grid, wireframe, …}::`.
petekio / petekTools pins unchanged.
### Licensing
- petekSim is licensed under the **Business Source License 1.1** (BUSL-1.1); each
released version converts to Apache-2.0 four years after publication. See `LICENSE`.
[Unreleased]: https://github.com/kkollsga/peteksim/compare/v0.1.13...HEAD
[0.1.13]: https://github.com/kkollsga/peteksim/compare/v0.1.12...v0.1.13
[0.1.1]: https://github.com/kkollsga/peteksim/compare/v0.1.0...v0.1.1
[0.1.0]: https://github.com/kkollsga/peteksim/releases/tag/v0.1.0