# Compute handoff — Rods Cursor **Owner:** Agent team **Status:** Active **Last updated:** 2026-04-16 (audit hardening pass) **Canonical math:** [MATH_SPEC.md](MATH_SPEC.md) **Agent rules:** [AGENTS.md](../AGENTS.md) at repo root **Reference bibliography:** [references/papers/README.md](../references/papers/README.md) --- ## 1. Session context Math-first rod-string / dynamometer stack: - **C (`solver-c`)** — Authoritative FDM + FEA + diagnostic transfer + trajectory preprocess. **JSON on stdin** to `solver_main` / `solver_fea_main` (`schemaVersion: 2`). - **Node (`solver-api`)** — XML → SI model, surface-card QA, orchestration, `comparison` / `verbose` / `pumpMovement`, `schemaVersion` in responses. - **GUI (`gui-ts`)** — Workflow / plots, XML round-trip editor, engineering checks, and 3D wellbore visualization. User goals: SROD-like transparency, measured card → downhole + pump movement, FDM vs FEA comparison, no invented physics. --- ## 2. Repository map | Path | Role | |------|------| | `solver-c/src/solver.c` | FDM predictive + gravity/buoyancy + variable \(EA\rho\) + side-load Coulomb | | `solver-c/src/solver_fea.c` | FEA predictive + Rayleigh damping + diagnostic bisection (Eisner-style) | | `solver-c/src/solver_diagnostic.c` | Diagnostic FDM from surface card | | `solver-c/src/trajectory.c` | Survey → curvature / inclination on rod grid | | `solver-c/src/json_stdin.c` | stdin JSON → `SolverInputs` | | `solver-api/src/xmlParser.js` | Parse + **SI** normalization | | `solver-api/src/solverClient.js` | Build JSON, run C | | `solver-api/src/cardQa.js` | Surface card validation | | `solver-api/src/app.js` | HTTP, extended `comparison`, `validate-card` | | `data/cases/base-case.xml` | Canonical case | | `data/golden/default.solve.sha256` | Golden fingerprint for `/solve/default` | --- ## 3. Status vs MATH_SPEC (gap table) | Item | MATH_SPEC § | Code status | |------|-------------|-------------| | Variable \(EA\) FDM | §1–3 | **Done** — per-node `area_m2`, `modulus_pa`, `density_kg_m3` | | Gravity + buoyancy | §1 | **Done** — distributed \(f = \rho g A - \rho_f g A\) (simplified annulus = rod area) | | Explicit FD + CFL | §3 | **Done** — `verbose.numerics` | | 3D survey / curvature | §5 | **Partial** — `trajectory.c` resamples MD/inc/azi; full Araujo Eqs. 14–18 system = future refinement | | Lukasiewicz lateral PDE | §4 | **Partial** — side load from \(T,\kappa,\phi\) proxy + Coulomb (`heuristic` tag in verbose) | | Valve state machine | §7 | **Partial** — simplified phase + `gasInterference` flag from load plateau heuristic | | Diagnostic FDM in C | §7 | **Done** — `solver_diagnostic.c` | | Diagnostic FEA + iteration | §6–7 | **Done** — bisection on bottom load in `solver_fea.c` when `workflow=diagnostic` | | Rayleigh \(\alpha,\beta\) from XML damping | §2 | **Done** — tied to rod length + damping factors | | Multi-material taper | §1 | **Done** — `RodTypeArray` / modulus arrays in JSON | | Fourier analytical baseline | §3 | **Deferred** | | Full tube–tube contact (Eisner) | §6 | **Deferred** | ### Tubing gradient (GUI helper) The **Fluid** tab can fill `TubingGradient` from a **heuristic** bulk-liquid hydrostatic estimate (water cut, oil API, water SG), aligned with the simplified mixture density used in `solver-api/src/xmlParser.js#computeFluidDensityKgM3`. `TubingGradient` is still parsed to `tubingGradientPaM` in Node but is **not** forwarded on the C JSON stdin payload today (`docs/engineering/field-traceability.md`). Wiring it into the damped-wave / pressure BC model would require `MATH_SPEC.md` + C changes + golden refresh. --- ## 4. API (quick reference) ```http POST /solve Content-Type: application/json { "xml": "...", "solverModel": "fdm|fea|both", "workflow": "predictive|diagnostic", "surfaceCard": { "position": [], "load": [], "time": [] }, "options": { "schemaVersion": 2 } } ``` - `GET /solve/default` — predictive only; supports `?solverModel=`. - `POST /solve/validate-card` — QA only (no solve). - Response: `schemaVersion`, `units: "SI"`, `solver`, `solvers?`, `comparison` (extended), `pumpMovement?`, `verbose`, `runMetadata`. --- ## 5. Runbook ```bash make test ./solver-c/test_solver cd solver-api && npm test # Docker docker compose up -d --build make smoke ``` `docker-compose.yml` gcc lines must list all `solver-c/src/*.c` objects used by `main.c` / `main_fea.c`. --- ## 6. Deferred (explicit) | Topic | Notes | |-------|--------| | Full **Costa / SPE-173970** 3D wave with \(K_1,K_2\) lateral load PDE in C | Currently curvature + side-load **proxy**; implement from paper, not ad hoc | | **Torsion** | Not in current four-paper backbone | | **Pumping-unit kinematics** (Svinos tables, crank motion from `PumpingUnitID`) | Harmonic default; unit geometry unused | | **Inverse calibration** | Fit damping / friction to measured downhole card | | **Fourier** analytical diagnostic | Optional `comparison.fourier` | | **GUI** 3D survey + layout | **Partial done** — Results tab includes 3D projected wellbore + rod/pump overlay, depth-hue and side-load overlays; not a full 3D engine (no camera controls / mesh terrain yet) | | **GUI Pump / Fluid / Kinematics first-class mapping** | Tabs render editable fields but rely on `rawFields` round-trip rather than dedicated serializer logic; audit once solver-api adds explicit fields for `PumpFillageOption`, pumping-unit kinematics, etc. | | **GUI fatigue / API RP 11BR table** | Backend does not emit a fatigue payload yet; surface in Results tab when `solver.fatigue` exists | --- ## 6.1 GUI checks/visualization shipped - Fixed engineering gate in Solver tab: - run blocked when `|PumpDepth - sum(TaperLengthArray)| > 15 m`. - survey MD monotonicity and minimum station-count checks. - Results tab now shows: - uPlot dynacard overlays, - 3D projected wellbore with rod gradient and pump marker, - depth-hue and side-load risk overlays, - segment highlight + clear-highlight controls, - trajectory analytics table with row↔3D segment cross-highlight, - pump-placement diagnostics panel + navigation actions, - export actions (3D SVG, 3D PNG, summary JSON). - keyboard-accessible trajectory segment selection (`Enter`/`Space`) and clear-highlight control. - Kinematics/Solver workflow now supports diagnostic execution end-to-end in GUI: - measured card paste input (`position,load` rows), - `POST /solve/validate-card` QA call from Kinematics tab, - diagnostic solve payload wiring (`workflow=diagnostic`, `surfaceCard`), - solve options include profile generation for visualization overlays. --- ## 7. Jump table | Task | Start | |------|--------| | FDM numerics | `solver-c/src/solver.c` | | FEA + diagnostic bisection | `solver-c/src/solver_fea.c` | | Diagnostic FDM | `solver-c/src/solver_diagnostic.c` | | Trajectory | `solver-c/src/trajectory.c` | | JSON CLI | `solver-c/src/json_stdin.c`, `main.c`, `main_fea.c` | | SI + XML | `solver-api/src/xmlParser.js` | | Run C | `solver-api/src/solverClient.js` | | Card QA | `solver-api/src/cardQa.js` | | HTTP | `solver-api/src/app.js` | | Tests | `solver-api/tests/api.test.js`, `solver-c/tests/test_solver.c` | --- ## 8. Quality Program (next execution block) This section is the execution plan for the next pass, optimized for "feature-rich but solid". ### 8.1 Priority 1 — Correctness gates first - Build a field-sensitivity harness (per mapped input field, ±1% perturbation). - Implemented in this pass: - safer stdin/file JSON ingestion guards in `solver-c/src/json_stdin.c`, `solver-c/src/main.c`, `solver-c/src/main_fea.c`, - API 4xx envelope normalization with machine-readable `code`, - GUI stale-run guard for async solve execution. - Enforce invariants in solver outputs: - finite values everywhere, - gas fraction bounds, - physically valid valve-state transitions, - profile array length consistency. - Expand deterministic goldens beyond base case. **Acceptance gate:** no merge if sensitivity/invariant tests fail. ### 8.2 Priority 2 — Solver fidelity - Reduce remaining heuristic terms toward equation-backed Costa/Araujo + Lukasiewicz formulations. - Harden valve/gas state model transitions with explicit edge-case fixtures. - Add stability fallback behavior and numerical-health reporting. **Acceptance gate:** documented equation coverage increases; no stability regressions. ### 8.3 Priority 3 — Validation depth - Add cross-model agreement matrix (FDM vs FEA) across canonical cases. - Add synthetic/analytical sanity cases where expected trends are known. - Track residual drift trends over commits. **Acceptance gate:** tolerance matrix passes for all canonical cases. ### 8.4 Priority 4 — Contract hardening - Keep `schemaVersion: 2` additive contract stable by default. - Enforce option-gated heavy payloads (`profiles`, `diagnostics`, `fourier`) — **implemented in C stdout** (`enableProfiles`, `enableDiagnosticsDetail`, `enableFourierBaseline`); default API responses omit heavy blocks. - Traceability metadata — **`fieldTraceability` on `GET /case/default`, `POST /case/parse`, `POST /solve`, `GET /solve/default`** via [`solver-api/src/fieldTraceability.js`](../solver-api/src/fieldTraceability.js). **Acceptance gate:** backward-compat tests pass on default endpoints. ### 8.5 Priority 5 — CI/release readiness - Add sanitizer runs (ASan/UBSan) for C paths — **`make test-solver-sanitize`** in root [`Makefile`](../Makefile). - Add runtime/performance budgets on representative cases. - Enforce quality artifact generation in CI (comparison summaries + drift reports). **Acceptance gate:** CI quality lane green. ### 8.6 Multi-agent execution split - Agent A: solver numerics/fidelity. - Agent B: GUI integration + import/export + rendering. - Agent C: verification harness + CI guardrails + independent audit. --- *Extend §3 and §8 together whenever milestones ship.*