Initial commit: establish deterministic rod-string solver stack.
Set up the C solver core, Node API orchestration, TS GUI workflow, and engineering documentation with cleaned repo hygiene for private Git hosting. Made-with: Cursor
This commit is contained in:
70
docs/engineering/architecture.md
Normal file
70
docs/engineering/architecture.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Architecture and requirement traceability
|
||||
|
||||
Owner: Rods Project Team
|
||||
Status: Active
|
||||
Last Updated: 2026-04-16
|
||||
Version: 0.2.0
|
||||
|
||||
## Module boundaries
|
||||
|
||||
- **`solver-c`:** Authoritative numerics — FDM, FEA, diagnostic FDM, trajectory preprocess, distributed side-load/friction coupling, valve/gas dynamic diagnostics, optional Fourier analytical baseline, gravity/buoyancy, variable \(E(x), A(x), \rho(x)\), JSON **stdin** contract (`schemaVersion: 2`). No HTTP/XML.
|
||||
- **`solver-api`:** Local HTTP service — parse XML, convert to **SI**, surface-card QA, spawn C binaries with JSON pipe, attach `verbose`, `comparison`, `pumpMovement`, `schemaVersion`.
|
||||
- **`gui-ts`:** Workflow and visualization (tabbed case editor, XML round-trip, dynacards, engineering checks, 3D wellbore preview); not the primary PDE solver.
|
||||
- **`data/cases`:** Canonical inputs and regression cases.
|
||||
- **`data/golden`:** Fingerprints for deterministic API regression.
|
||||
- **`references/papers/README.md`:** Citation index for external literature used by `Agents/MATH_SPEC.md`.
|
||||
|
||||
## C driver contract
|
||||
|
||||
Executables read **one JSON object from stdin** (UTF-8). Required top-level keys are produced by `solver-api/src/solverClient.js` — see that file for the exact shape (`workflow`, `model`, optional `surfaceCard`, optional `options`).
|
||||
|
||||
`options` supports:
|
||||
- `enableProfiles` — includes trajectory + side-load + friction profile payloads.
|
||||
- `enableDiagnosticsDetail` — includes valve-state and chamber/gas time-series.
|
||||
- `enableFourierBaseline` — computes analytical Fourier baseline in C.
|
||||
- `fourierHarmonics` — harmonic count for baseline reconstruction.
|
||||
|
||||
Legacy argv-based invocation has been **removed** to avoid drift between CLI and API.
|
||||
|
||||
## MVP requirement traceability
|
||||
|
||||
| Requirement | Module | Notes |
|
||||
|-------------|--------|--------|
|
||||
| Real C solver path | `solver-c`, `solver-api` | JSON pipe; no mock-only solve |
|
||||
| XML inspectability | `solver-api`, `gui-ts` | `rawFields`, `unsupportedFields` |
|
||||
| Output cards primary | `solver-c`, `gui-ts` | Polished + downhole series |
|
||||
| Determinism | `solver-c`, `solver-api` | Golden hash; no randomness |
|
||||
| Warnings / numerics | `solver-c`, `solver-api` | `warnings`, `verbose.numerics`, CFL |
|
||||
| 3D survey visibility | `gui-ts` | Results tab includes projected 3D wellbore with DLS/side-load overlay modes + rod/pump overlays + interactive camera controls |
|
||||
|
||||
## System flow
|
||||
|
||||
1. GUI or client sends XML (+ options) to API.
|
||||
2. API parses to canonical **SI** model + preserves unknown fields.
|
||||
3. Optional: `POST /solve/validate-card` runs QA only.
|
||||
4. API builds JSON and runs `solver_main` / `solver_fea_main` with stdin.
|
||||
5. C returns JSON stdout; API merges `parsed`, `comparison`, `runMetadata`.
|
||||
6. GUI renders cards, survey, inspection panels.
|
||||
|
||||
## Execution guidelines for upcoming hardening
|
||||
|
||||
- Keep defaults stable; grow contract additively behind options.
|
||||
- Treat C as numerical source-of-truth; API orchestrates and validates.
|
||||
- Require test evidence for every new equation term:
|
||||
- unit-level numeric sanity,
|
||||
- integration-level behavior,
|
||||
- deterministic regression impact.
|
||||
- Pair every new feature with:
|
||||
- one "happy path" case,
|
||||
- one edge/stress case,
|
||||
- one regression gate entry.
|
||||
|
||||
## GUI guardrails and thresholds
|
||||
|
||||
- Pump-depth consistency gate: solver run is blocked when `abs(PumpDepth - totalRodLength) > 15 m`.
|
||||
- DLS bad-section threshold: `15 deg/100` used both for warning logic and 3D contour highlighting.
|
||||
- Thresholds are intentionally fixed (not user-configurable) to keep deterministic behavior.
|
||||
- Diagnostic GUI path is now wired:
|
||||
- measured card input + QA call in Kinematics tab,
|
||||
- `workflow=diagnostic` run from Solver tab with `surfaceCard` payload.
|
||||
- Results now include trajectory segment analytics and artifact export actions (3D SVG/PNG, summary JSON).
|
||||
62
docs/engineering/case-schema.md
Normal file
62
docs/engineering/case-schema.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# Case schema and import contract
|
||||
|
||||
Owner: Rods Project Team
|
||||
Status: Active
|
||||
Last Updated: 2026-04-16
|
||||
Version: 0.2.0
|
||||
|
||||
## Canonical input
|
||||
|
||||
- Root: `INPRoot/Case`
|
||||
- Example: `data/cases/base-case.xml`
|
||||
|
||||
## Parsed fields used by solver (SI after `xmlParser`)
|
||||
|
||||
### Core (required)
|
||||
|
||||
- `PumpingSpeed` — SPM
|
||||
- `PumpDepth` — MD to pump (case units → m)
|
||||
- `MeasuredDepthArray`, `InclinationFromVerticalArray` — trajectory (`:` separated)
|
||||
- `AzimuthFromNorthArray` — optional for vertical; required for full 3D curvature in API validation
|
||||
|
||||
### Friction / contact
|
||||
|
||||
- `RodFrictionCoefficient` — Coulomb \(\mu\) baseline
|
||||
- `StuffingBoxFriction`, `PumpFriction` — case force units → N
|
||||
- `MoldedGuideFrictionRatio`, `WheeledGuideFrictionRatio`, `OtherGuideFrictionRatio` — scale effective \(\mu\) along string (`heuristic` blend)
|
||||
|
||||
### Rod string / materials
|
||||
|
||||
- `TaperDiameterArray`, `TaperLengthArray`, `TaperModulusArray`, `TaperWeightArray`, `TaperMTSArray`
|
||||
- `RodTypeArray` — maps to steel vs fiberglass density/modulus defaults when modulus not set
|
||||
- `TubingAnchorLocation`
|
||||
- `SinkerBarDiameter`, `SinkerBarLength`
|
||||
- `RodGuideTypeArray`, `RodGuideWeightArray` — metadata / future contact
|
||||
|
||||
### Damping
|
||||
|
||||
- `UpStrokeDampingFactor`, `DownStrokeDampingFactor`
|
||||
- `NonDimensionalFluidDamping` — Gibbs-style dimensionless damping input
|
||||
|
||||
### Pump / fluid (valve + buoyancy helpers)
|
||||
|
||||
- `PumpDiameter`, `PumpIntakePressure`, `PumpFillageOption`, `PercentPumpFillage`
|
||||
- `WaterCut`, `WaterSpecGravity`, `FluidLevelOilGravity`, `TubingGradient`, `TubingSize`
|
||||
- `PercentageUpstrokeTime`, `PercentageDownstrokeTime`
|
||||
- `PumpingUnitID`, `PumpingSpeedOption` — metadata for future kinematics
|
||||
|
||||
### Units
|
||||
|
||||
- `UnitsSelection` — drives internal conversion (see `units.md`)
|
||||
|
||||
## Unknown / unsupported field policy
|
||||
|
||||
- Parse immediate `Case` children into `rawFields`.
|
||||
- Fields outside the MVP subset used for **solver** remain in `unsupportedFields` but are **preserved** in API responses.
|
||||
- Do not silently drop imported tags.
|
||||
|
||||
## Validation rules
|
||||
|
||||
- Required for parse: `PumpingSpeed`, `PumpDepth`, `MeasuredDepthArray`, `InclinationFromVerticalArray`.
|
||||
- Trajectory arrays must have equal lengths after parse.
|
||||
- Numeric parse failures throw explicit errors.
|
||||
84
docs/engineering/field-traceability.md
Normal file
84
docs/engineering/field-traceability.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# Field Traceability Matrix
|
||||
|
||||
Last Updated: 2026-04-17
|
||||
|
||||
## Scope
|
||||
|
||||
This matrix tracks how `data/cases/base-case.xml` fields flow through the solver:
|
||||
|
||||
1. XML parse (`solver-api/src/xmlParser.js`)
|
||||
2. SI conversion (`normalizeToSi`)
|
||||
3. C payload (`solver-api/src/solverClient.js`)
|
||||
4. Equation/physics use (`solver-c/src/*.c`)
|
||||
|
||||
## Coverage summary (base-case)
|
||||
|
||||
- Total XML fields: **165**
|
||||
- Fields present in MVP schema and present in base-case: **41**
|
||||
- Unsupported/preserved fields: **124**
|
||||
|
||||
## A) Fully used in solver equations
|
||||
|
||||
| XML field | Parsed + SI | Payload key(s) | Equation use |
|
||||
|---|---|---|---|
|
||||
| `PumpingSpeed` | yes | `pumping_speed` | time step / period in FDM/FEA |
|
||||
| `PumpDepth` | yes | `pump_depth` | rod length, hydrostatic terms |
|
||||
| `TubingAnchorLocation` | yes | `tubing_anchor_location` | rod length |
|
||||
| `RodFrictionCoefficient` | yes | `rod_friction_coefficient` | Coulomb friction scaling |
|
||||
| `StuffingBoxFriction` | yes | `stuffing_box_friction` | polished-load boundary friction |
|
||||
| `PumpFriction` | yes | `pump_friction` | downhole boundary friction |
|
||||
| `MeasuredDepthArray` | yes | `survey_md_m` | trajectory/node mapping |
|
||||
| `InclinationFromVerticalArray` | yes | `survey_inc_rad` | trajectory + gravity projection |
|
||||
| `AzimuthFromNorthArray` | yes | `survey_azi_rad` | trajectory curvature |
|
||||
| `TaperDiameterArray` | yes | `area_m2` | axial stiffness/mass terms |
|
||||
| `TaperLengthArray` | yes | rod-node assembly | rod section distribution |
|
||||
| `TaperModulusArray` | yes | `modulus_pa` | stiffness terms |
|
||||
| `RodTypeArray` | yes | density/modulus defaults | mass/stiffness terms |
|
||||
| `UpStrokeDampingFactor` | yes | `upstroke_damping` | FEA damping calibration |
|
||||
| `DownStrokeDampingFactor` | yes | `downstroke_damping` | damping (path-level) |
|
||||
| `NonDimensionalFluidDamping` | yes | `non_dim_damping` | FEA damping factor |
|
||||
| `MoldedGuideFrictionRatio` | yes | `molded_guide_mu_scale` | friction scaling |
|
||||
| `WheeledGuideFrictionRatio` | yes | `wheeled_guide_mu_scale` | friction scaling |
|
||||
| `OtherGuideFrictionRatio` | yes | `other_guide_mu_scale` | friction scaling |
|
||||
| `PumpDiameter` | yes | `pump_diameter_m` | chamber pressure / valve logic |
|
||||
| `PumpIntakePressure` | yes | `pump_intake_pressure_pa` | hydro/chamber pressure |
|
||||
| `PumpFillageOption` | yes | `pump_fillage_option` | gas-interference logic |
|
||||
| `PercentPumpFillage` | yes | `percent_pump_fillage` | gas-fraction logic |
|
||||
| `WaterCut` + `WaterSpecGravity` + `FluidLevelOilGravity` | yes | `fluid_density_kg_m3` | buoyancy/hydrostatic terms |
|
||||
| `TaperWeightArray` | yes | `weight_n_per_m` | node buoyed-weight in side-load |
|
||||
| `TaperMTSArray` | yes | `mts_n` | friction scaling term |
|
||||
| `RodGuideWeightArray` | yes | `guide_weight_n_per_m` | side-load normal-force term |
|
||||
| `SinkerBarDiameter` + `SinkerBarLength` | yes | `sinker_bar_*` | added sinker side-load contribution |
|
||||
|
||||
## B) Parsed/payloaded but not yet active in governing equations
|
||||
|
||||
| XML field | Current state | Planned use |
|
||||
|---|---|---|
|
||||
| `TubingSize` | parsed + converted to `tubing_id_m` + payloaded | annular buoyancy/contact refinements |
|
||||
| `TubingGradient` | parsed + converted to `tubingGradientPaM`; not payloaded to C math | hydraulic pressure model |
|
||||
| `PercentageUpstrokeTime` | payloaded (`percent_upstroke_time`) | non-harmonic kinematics timing |
|
||||
| `PercentageDownstrokeTime` | payloaded (`percent_downstroke_time`) | non-harmonic kinematics timing |
|
||||
| `PumpingUnitID` | parsed only | pumping-unit geometry/kinematics tables |
|
||||
| `PumpingSpeedOption` | parsed only | drive/kinematics modes |
|
||||
| `RodGuideTypeArray` | parsed only | type-specific contact/friction law |
|
||||
|
||||
## C) Unsupported but preserved in API
|
||||
|
||||
All non-MVP fields from base-case remain in `rawFields` and are listed in `unsupportedFields`; they are not currently used in C equations.
|
||||
|
||||
Representative examples:
|
||||
|
||||
- `ActualCounterbalance`
|
||||
- `BulkModulus`
|
||||
- `CasingHeadPressure`
|
||||
- `PumpEfficiency`
|
||||
- `IPRInputMode`
|
||||
- `VogalPointList`
|
||||
- `SeparatorPressure`
|
||||
- `PowerLineFrequency`
|
||||
|
||||
## D) Contract notes
|
||||
|
||||
- Heavy output blocks (`profiles`, `diagnostics`, `fourierBaseline`) are emitted by C.
|
||||
- Fourier baseline is computed when `options.enableFourierBaseline=true`.
|
||||
- Default deterministic golden hash updated after physics/field-wiring changes.
|
||||
46
docs/engineering/units.md
Normal file
46
docs/engineering/units.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Units and internal conventions
|
||||
|
||||
Owner: Rods Project Team
|
||||
Status: Active
|
||||
Last Updated: 2026-04-16
|
||||
|
||||
## Principle
|
||||
|
||||
All values passed from `solver-api` to `solver-c` **JSON** are **SI**:
|
||||
|
||||
| Quantity | SI unit |
|
||||
|----------|---------|
|
||||
| Length | m |
|
||||
| Force | N |
|
||||
| Pressure | Pa |
|
||||
| Mass density | kg/m³ |
|
||||
| Time | s |
|
||||
| Angle | rad (stored in JSON as rad; XML may be degrees) |
|
||||
| SPM | 1/min (dimensionally s⁻¹ scale; kept as `pumping_speed` scalar per stroke period \(T = 60/\text{SPM}\) s) |
|
||||
|
||||
## `UnitsSelection` (XML)
|
||||
|
||||
`base-case.xml` uses `<UnitsSelection>2</UnitsSelection>` (example). Parser maps:
|
||||
|
||||
| Code | Assumption in parser |
|
||||
|------|----------------------|
|
||||
| `0` / missing | Field units match legacy **oilfield mixed** inch–ft–lbf where applicable (see below) |
|
||||
| `2` | **Imperial oilfield** — lengths in **ft**, diameters in **in**, moduli in **Mpsi** (×10⁶ psi), forces in **lbf**, pressures in **psi** |
|
||||
| Other | Treated like `2` with warning in `parsed.warnings` (`heuristic`) |
|
||||
|
||||
### Conversion factors (exact)
|
||||
|
||||
- `1 in = 0.0254 m`
|
||||
- `1 ft = 0.3048 m`
|
||||
- `1 lbf = 4.4482216152605 N`
|
||||
- `1 psi = 6894.757293168 Pa`
|
||||
- `1 Mpsi = 6.894757293168e9 Pa`
|
||||
- `deg → rad`: multiply by \(\pi/180\)
|
||||
|
||||
### Fluid density helper
|
||||
|
||||
Mixture density from `WaterCut`, `WaterSpecGravity`, `FluidLevelOilGravity` uses simplified API formula for buoyancy; tagged `heuristic` in `model.fluidDensityHeuristic`.
|
||||
|
||||
## JSON to C
|
||||
|
||||
`SolverInputs` receives only SI. GUI may show field units; API documentation states SI in solve payload.
|
||||
83
docs/engineering/validation.md
Normal file
83
docs/engineering/validation.md
Normal file
@@ -0,0 +1,83 @@
|
||||
# Validation plan
|
||||
|
||||
Last Updated: 2026-04-16
|
||||
|
||||
## Determinism
|
||||
|
||||
- Same XML + same `solverModel` + `workflow` → identical `solver.card` arrays (bitwise for floats at printed precision in C stdout path).
|
||||
- API responses include `runMetadata.generatedAt` — **stripped** before golden hash in tests.
|
||||
|
||||
## Golden file
|
||||
|
||||
- File: `data/golden/default.solve.sha256`
|
||||
- Content: SHA-256 of **canonical JSON** string from `GET /solve/default?solverModel=fdm` with `generatedAt` removed and stable key ordering (`stableStringify` in tests).
|
||||
|
||||
## Unit coverage
|
||||
|
||||
- XML parser: numeric + array + unit conversion.
|
||||
- `cardQa.js`: min samples, cycle closure, spike rejection.
|
||||
- C: `test_solver` — determinism, bounds, static equilibrium helper, undamped wave CFL identity, FDM vs FEA peak tolerance.
|
||||
|
||||
## Cross-model (FDM vs FEA)
|
||||
|
||||
- C unit gate (`solver-c/tests/test_solver.c`): `|maxPolishedLoad_FDM - maxPolishedLoad_FEA| < 7e5 N` on an SI-normalized fixture (interim; tighten when BC parity improves).
|
||||
|
||||
## Integration
|
||||
|
||||
- `solver-api/tests/api.test.js` — solve routes, diagnostic path, golden hash, `validate-card`, `both` comparison keys.
|
||||
- `comparison` schema v2 includes:
|
||||
- `peakLoadDeltas` for Pmax/Pmin and Dmax/Dmin
|
||||
- `pointwiseResiduals.series[]` (position + polished/downhole residuals)
|
||||
- `residualSummary` RMS
|
||||
- `fourier` optional baseline block (`null` unless `options.enableFourierBaseline=true`)
|
||||
|
||||
## Extended physics validation
|
||||
|
||||
- `options.enableProfiles=true` must return `solver.profiles` with `nodeCount > 0` and finite trajectory/side-load/friction arrays.
|
||||
- `options.enableDiagnosticsDetail=true` must return `solver.diagnostics` with valve-state booleans and finite chamber/gas series.
|
||||
- `options.enableFourierBaseline=true` must return non-null `comparison.fourier` and finite residual RMS metrics.
|
||||
|
||||
## Priority validation roadmap (1–5)
|
||||
|
||||
### 1) Correctness gates (mandatory)
|
||||
|
||||
- Field sensitivity checks: each mapped physics input gets ±1% perturbation and expected directional assertions.
|
||||
- Invariant checks:
|
||||
- finite loads/stresses/profiles,
|
||||
- gas fraction within bounds,
|
||||
- consistent valve-state transitions,
|
||||
- no malformed profile/diagnostic arrays.
|
||||
- Deterministic checks on multi-case golden set.
|
||||
|
||||
### 2) Fidelity checks
|
||||
|
||||
- Equation-backed vs heuristic term audit must be explicit in docs.
|
||||
- Stability checks under high-deviation/high-friction cases.
|
||||
|
||||
### 3) Cross-model checks
|
||||
|
||||
- Case matrix compares FDM vs FEA on:
|
||||
- peak polished load,
|
||||
- peak downhole load,
|
||||
- net stroke,
|
||||
- residual RMS.
|
||||
|
||||
### 4) Contract checks
|
||||
|
||||
- Default `/solve` and `/solve/default` responses remain backward compatible.
|
||||
- Option-gated payload behavior is tested for on/off combinations.
|
||||
|
||||
### 5) CI checks
|
||||
|
||||
- C sanitizers (ASan/UBSan) lane.
|
||||
- Performance budget lane (fixed representative cases).
|
||||
- Artifact lane emits comparison/drift summaries.
|
||||
|
||||
## Analytical targets (C tests)
|
||||
|
||||
- **Static rod:** uniform bar vertical hang — numerical mean tension trend vs \(\sum \rho g A \Delta x\) (approximate check).
|
||||
- **Wave CFL:** \(a \Delta t / \Delta x \le 1\) for explicit scheme after clamp.
|
||||
|
||||
## GUI
|
||||
|
||||
- Smoke: import `base-case.xml`, run solver — manual / Playwright future.
|
||||
Reference in New Issue
Block a user