# petekTools — locked public API (GATE 0)
> **This file is the contract.** The build must expose exactly these signatures
> (names, arguments, return types). Bodies are the implementer's; the *surface*
> is fixed. Changing a signature here requires sign-off. See `SPEC.md` for the
> design constitution.
Conventions: `Result<T> = std::result::Result<T, AlgoError>`; grids are
`ndarray::Array2<f64>` shaped `(ncol, nrow)`; undefined node = `NaN`. Kernels are
**type-agnostic** — they speak `Lattice` + `[[f64; 3]]`, never a consumer type.
---
## foundation
```rust
pub type Result<T> = std::result::Result<T, AlgoError>;
#[derive(Debug, thiserror::Error)]
pub enum AlgoError {
EmptyInput(&'static str), // a kernel got no data
InvalidGeometry(&'static str), // degenerate lattice (e.g. zero spacing)
}
pub struct BBox { pub xmin: f64, pub ymin: f64, pub xmax: f64, pub ymax: f64 }
/// Regular, rotatable areal lattice (IRAP/RMS model). Field- and behaviour-
/// identical to petekio's `GridGeometry` so adoption is a 1:1 map.
pub struct Lattice {
pub xori: f64, pub yori: f64, // origin (node 0,0)
pub xinc: f64, pub yinc: f64, // node spacing
pub ncol: usize, pub nrow: usize, // node counts (i along x, j along y)
pub rotation_deg: f64, // CCW of the I-axis from East
pub yflip: bool,
}
impl Lattice {
pub fn regular(xori: f64, yori: f64, xinc: f64, yinc: f64,
ncol: usize, nrow: usize) -> Lattice; // unrotated, unflipped
pub fn yflip_factor(&self) -> f64;
pub fn node_xy(&self, i: usize, j: usize) -> (f64, f64);
pub fn xy_to_ij(&self, x: f64, y: f64) -> Option<(f64, f64)>; // fractional; None if degenerate
pub fn bbox(&self) -> BBox;
}
```
## gridding
```rust
pub enum GridMethod { Nearest, InverseDistance, MinimumCurvature }
/// Interpolate scattered `[x, y, z]` rows onto `lattice`. Returns the
/// `(ncol × nrow)` node array (NaN where undefined). Errs only on empty input.
pub fn grid(coords: &[[f64; 3]], lattice: &Lattice, method: GridMethod)
-> Result<ndarray::Array2<f64>>;
```
The three methods mirror petekio's so its `PointSet::to_surface(geom, method)`
can later delegate here by mapping `GridGeometry → Lattice`.
---
## gridding — warm-start (LOCKED; signed off by petekio + petekSim 2026-06-29)
> Requested firm by both consumers (petekio L1, petekSim L2) and **signed off by
> both** on 2026-06-29 — now part of the locked surface. **Additive and
> non-breaking** — `grid()` is unchanged. See
> `dev-docs/designs/warm-start-gridding.md`.
```rust
// L1 — seeded minimum-curvature primitive (parity with petekio's
// `grid_min_curvature(.., seed)`). Relax the SOR from `seed` (lattice-shaped)
// instead of the cold IDW seed; `None`/wrong-shape → current cold behaviour.
// Re-solves the WHOLE field from the seed (no region restriction) — this is
// what guarantees warm == cold to tolerance + determinism.
pub fn grid_min_curvature_seeded(
coords: &[[f64; 3]], lattice: &Lattice, seed: Option<&ndarray::Array2<f64>>,
) -> Result<ndarray::Array2<f64>>;
// L2 — stateful convergent gridder for interactive/iterative re-gridding
// (petekSim's refinement loop). Holds the lattice, the current solved field,
// and the node-indexed control set; each add warm-starts from the held field
// via L1. NB: re-solves the whole field warm (fast: far fewer iters), NOT a
// region-restricted solve — diverges from the "affected region only" wording
// to preserve the warm == cold continuity guarantee.
pub struct ConvergentGridder { /* private: Lattice + Array2<f64> + controls */ }
impl ConvergentGridder {
pub fn new(coords: &[[f64; 3]], lattice: &Lattice) -> Result<ConvergentGridder>;
pub fn add_control(&mut self, ip: usize, jp: usize, z: f64) -> &ndarray::Array2<f64>;
pub fn add_controls(&mut self, controls: &[(usize, usize, f64)]) -> &ndarray::Array2<f64>;
pub fn field(&self) -> &ndarray::Array2<f64>;
}
```
## Roadmap (NOT yet locked — sketches for direction; see `SPEC.md`)
```rust
// Pluggable backends via a trait, once kriging/RBF land:
// pub trait Gridder { fn grid(&self, coords: &[[f64;3]], lattice: &Lattice) -> Result<Array2<f64>>; }
// Curated front-door modules (re-exporting / thinly wrapping mature crates):
// stats — weighted stats, percentiles (over statrs)
// sampling — distribution sampling (over rand_distr)
```