- tools/physics-sanity/ — JS library of cross-node balance helpers
(mass / hydraulic / hydraulic-power / oxygen-transfer / energy) with
7 unit tests + a CLI demo. Designed for `require()` from per-node
integration tests where shape-based unit tests miss physically-
impossible plant states.
- tools/docker-compose.yml + tools/mcp/{node-red-admin,influxdb,browser}
scaffolding — placeholder Dockerfiles + a ROADMAP.md for the Node-RED
admin MCP. Compose file is the target shape for the Q3-2026 migration
to the central MCP server; the per-service Dockerfile stays in this
repo as the canonical definition either way. Implementations are TODO.
- tools/README.md — top-level tooling index; documents the CI order for
running every tool on a PR.
- .gitignore: ignore tools/.env (developer-specific MCP endpoints).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
81 lines
2.9 KiB
Markdown
81 lines
2.9 KiB
Markdown
# @evolv/physics-sanity
|
||
|
||
Cross-node physical-balance helpers. Import from any node's test files
|
||
to assert that scenario states close mass, hydraulic, hydraulic-power,
|
||
oxygen-transfer, or energy balances within a stated tolerance.
|
||
|
||
## Why
|
||
|
||
Per-node unit tests verify shape and behaviour. They don't catch
|
||
physically impossible plant states that arise from cross-node coupling
|
||
— e.g. a pumpingStation reporting outflow > inflow + accumulation, or a
|
||
diffuser reporting OTR inconsistent with its KLa × ΔC × V.
|
||
|
||
These helpers don't replace per-node tests. They sit on top of an
|
||
integration scenario and assert the closing balance.
|
||
|
||
## Usage
|
||
|
||
```js
|
||
const sanity = require('../../../tools/physics-sanity');
|
||
|
||
test('three-pump station closes the hydraulic balance', () => {
|
||
// … drive the scenario, take a snapshot …
|
||
const r = sanity.assertHydraulicBalance({
|
||
headerSuctionPa: ps.suctionPressurePa,
|
||
headerDischargePa: ps.dischargePressurePa,
|
||
pumpHeadPa: sumOfPumpHeads,
|
||
frictionPa: pipeFrictionEstimate,
|
||
});
|
||
assert.equal(r.ok, true, sanity.reportToString(r));
|
||
});
|
||
```
|
||
|
||
## Helpers exported
|
||
|
||
| Function | Asserts |
|
||
|---|---|
|
||
| `assertMassBalance({ inflowKgPerS, outflowKgPerS, accumulationKgPerS })` | `in - out - accumulation ≈ 0` |
|
||
| `assertHydraulicBalance({ headerSuctionPa, headerDischargePa, pumpHeadPa, frictionPa, staticHeadPa })` | `ΔP_headers ≈ pumpHead - friction - static` |
|
||
| `assertHydraulicPower({ flowM3PerS, headPa, shaftPowerW, efficiency })` | `shaft ≈ Q·H / η` |
|
||
| `assertOxygenTransfer({ klaPerS, csMgPerL, cMgPerL, otrKgPerS, volumeM3 })` | `OTR ≈ KLa · (Cs - C) · V` |
|
||
| `assertEnergyBalance({ heatInW, workInW, heatOutW, workOutW, accumulationW })` | `Q_in + W_in ≈ Q_out + W_out + ΔE` |
|
||
|
||
Each returns `{ ok, label, ...residuals }`. `reportToString(r)` formats
|
||
for human-readable failure messages.
|
||
|
||
## CLI demo
|
||
|
||
```bash
|
||
node tools/physics-sanity/bin/physics-sanity.js
|
||
```
|
||
|
||
Runs four sanity-check scenarios against the helpers (smoke-test for
|
||
the library itself).
|
||
|
||
## Tolerance defaults
|
||
|
||
| Domain | Absolute | Relative |
|
||
|---|---|---|
|
||
| mass | 1e-6 kg/s | 0.1 % |
|
||
| hydraulic ΔP | 50 Pa (0.5 mbar) | 0.1 % |
|
||
| hydraulic power | 1 W | 0.5 % |
|
||
| OTR | 1e-4 kg/s | 0.5 % |
|
||
| energy | 1 W | 0.1 % |
|
||
|
||
Override per call with `absTol` / `relTol`.
|
||
|
||
## Where to use this
|
||
|
||
Out-of-the-box destinations:
|
||
|
||
| Scenario | Where to add | Calls |
|
||
|---|---|---|
|
||
| pumpingStation hydraulic closure | `nodes/pumpingStation/test/integration/` | `assertHydraulicBalance`, `assertHydraulicPower` |
|
||
| reactor → settler mass balance | `nodes/reactor/test/integration/` | `assertMassBalance` |
|
||
| diffuser OTR vs reactor uptake | `nodes/diffuser/test/integration/` | `assertOxygenTransfer` |
|
||
| machineGroupControl efficiency sanity | `nodes/machineGroupControl/test/integration/` | `assertHydraulicPower` |
|
||
|
||
A future tool can scan integration tests and report which scenarios do
|
||
or don't have a closing-balance assertion.
|