Files
diffuser/wiki/Home.md
znetsixe 8c03fe774c docs(wiki): full 5-page wiki matching the rotatingMachine reference format
Replaces the prior stub/partial wiki with a Home + Reference-{Architecture,
Contracts,Examples,Limitations} + _Sidebar structure. Topic-contract and
data-model sections wrapped in AUTOGEN markers for the future wiki-gen tool.
Source-vs-spec contradictions surfaced and flagged inline (not silently
fixed). Pending-review notes mark sections that need a full node review.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 09:42:13 +02:00

8.5 KiB
Raw Blame History

diffuser

code-ref s88 status

A diffuser models a single aeration-diffuser zone — the gas-side dynamics of a fine-bubble grid sitting under a reactor's water column. Given a header pressure, water height, alpha factor, element count and incoming air flow, it normalises the air to Nm³/h, interpolates a supplier OTR curve (oxygen transfer rate vs specific flux) plus a ΔP curve, and emits oxygen-transfer power (kg O₂/h), efficiency, per-element flow, and a reactor-zone OTR. Used as a leaf Equipment Module under a reactor (or any aeration train).

Note

Pending full node review (2026-05). Content reflects CONTRACT.md, src/commands/index.js, src/specificClass.js and generalFunctions/src/configs/diffuser.json only. Test scaffolding under test/basic/, test/integration/, test/edge/ is still placeholder-level — a domain-test pass remains TODO.


At a glance

Thing Value
What it represents One aeration-diffuser zone — the gas-side OTR + ΔP model of a fine-bubble grid
S88 level Equipment Module
Use it when You have a supplier OTR / ΔP curve and need oxygen-transfer + head-loss telemetry from a measured air flow
Don't use it for Coarse-bubble / jet aeration without a fine-bubble curve, or when the blower already publishes OTR (you'd duplicate the calc)
Children it accepts None — diffuser is a leaf
Parents it talks to reactor (typical), or any node that consumes child.register from Port 2

How it fits

flowchart LR
    blower[blower / MGC /<br/>dashboard slider]:::unit -->|data.flow<br/>Nm³/h| diff[diffuser<br/>Equipment]:::equip
    setters[dashboard setters /<br/>setup tab]:::ctrl -->|set.density<br/>set.water-height<br/>set.header-pressure<br/>set.elements<br/>set.alfa-factor| diff
    diff -->|child.register<br/>positionVsParent=atEquipment| reactor[reactor / parent<br/>Unit]:::unit
    diff -.->|Port 0: oOtr,<br/>oKgo2H, oZoneOtr,<br/>efficiency, slope| reactor
    classDef unit fill:#50a8d9,color:#000
    classDef equip fill:#86bbdd,color:#000
    classDef ctrl fill:#a9daee,color:#000

S88 colours are anchored in .claude/rules/node-red-flow-layout.md. Per the layout rule, diffuser lives on lane L3 of the Process Plant tab, wrapped in a #86bbdd Node-RED group.


Try it — 3-minute demo

Import the basic example flow, deploy, and drive a single diffuser zone through the OTR curve.

curl -X POST -H 'Content-Type: application/json' \
  --data @nodes/diffuser/examples/basic.flow.json \
  http://localhost:1880/flow

Note

Example flows currently shipped: examples/basic.flow.json, examples/integration.flow.json, examples/edge.flow.json. The examples/README.md is a one-line placeholder ("Placeholder structure"); a proper per-tier README following the rotatingMachine template is TODO.

What to send after deploy (each inject maps one-to-one to a topic in Reference — Contracts):

  1. set.water-height = 5 — sets a 5 m column above the diffuser. Static head pressure is recomputed; oPLoss updates.
  2. set.elements = 100 — declares 100 elements in this zone. Per-element flow + specific flux now scale by this denominator.
  3. set.density = 15 — bottom-coverage percentage; selects which curve family is interpolated.
  4. set.header-pressure = 600 — gauge pressure above atmospheric (mbar). Air-density correction kicks in.
  5. set.alfa-factor = 0.7 — the α correction used in the kg O₂/h calculation.
  6. data.flow = 200 — push 200 Nm³/h into the model. Watch Port 0: oOtr, oKgo2H, oFluxPerM2, efficiency, slope all populate. Setting data.flow = 0 flips idle back to true and resets the derived outputs.

Important

GIF needed. Demo recording of steps 16 with the live status badge. Save as wiki/_partial-gifs/diffuser/01-basic-demo.gif, target ≤ 1 MB after gifsicle -O3 --lossy=80.


The six things you'll send

Topic Aliases Payload What it does
data.flow air_flow number — Nm³/h Pushes the measured air flow into the model. Clamped to ≥ 0. Triggers a full recompute.
set.density density number — bottom-coverage % Selects the curve family used for OTR interpolation. Curves multi-keyed by coverage get linearly interpolated; single-key curves are clamped.
set.water-height height_water number — m Sets the water column above the diffuser. Recomputes static head + total ΔP. Clamped to ≥ 0.
set.header-pressure header_pressure number — mbar gauge Header (supply) pressure above atmospheric. Feeds air-density correction.
set.elements elements number — integer > 0 Active element count. Drives per-element flow + total membrane area used for specific flux.
set.alfa-factor alfaFactor number (typically 01) Alpha correction used in the kg O₂/h calculation.

Aliases log a one-time deprecation warning the first time they fire. There are no query topics today (the entire state is on Port 0).


What you'll see come out

Sample Port 0 message (delta-compressed, while operational with flow = 200 Nm³/h, 100 elements, water height 5 m):

{
  "topic": "diffuser_1",
  "payload": {
    "iFlow": 200,
    "iPressure": 600,
    "iMWater": 5,
    "nFlow": 218.42,
    "oFlowElement": 2.18,
    "oFluxPerM2": 12.13,
    "oOtr": 16.4,
    "oPLoss": 540.7,
    "oKgo2H": 12.51,
    "oZoneOtr": 6.0,
    "efficiency": 73.2,
    "slope": 0.044,
    "idle": false,
    "warning": [],
    "alarm": []
  }
}

Note

The numbers above are illustrative — the exact values depend on the loaded supplier curve (gva-elastox-r by default). Run the basic example flow to see real values for your asset.

Field Meaning
iFlow / iPressure / iMWater Echo of the current setter inputs (Nm³/h, mbar, m).
nFlow Air flow normalised to standard conditions (Nm³/h, T=20 °C, p=1.01325 bar, RH=0).
oFlowElement nFlow / elements — flow per element.
oFluxPerM2 Specific flux through the membrane (Nm³/(h·m²)) — the canonical x-axis of every supplier curve.
oOtr Interpolated oxygen transfer rate (g O₂ / Nm³).
oPLoss Total head loss in mbar — static head from the water column plus diffuser ΔP.
oKgo2H kg O₂ per hour at the current operating point. Uses α-factor and water height.
oZoneOtr Reactor-zone OTR in kg O₂ / m³ / day. Computed from oKgo2H against diffuser.zoneVolume; zero when zone volume is unset.
efficiency Combined OTR / ΔP efficiency (0100). High OTR + low ΔP → high score.
slope Local OTR-vs-flux slope (g O₂/Nm³ per Nm³/(h·m²)). Useful as a "we're near the curve knee" indicator.
idle true when iFlow ≤ 0 — derived predicates only, no FSM.
warning / alarm String arrays describing flow-per-element band excursions (±2 % warn / ±10 % alarm hysteresis, hardcoded).

Not the same shape as rotatingMachine / measurement

Where rotatingMachine emits per-measurement keys (<type>.<variant>.<position>.<childId>), diffuser uses a flat camelCase schema (oOtr, oKgo2H, oFlowElement, …). The diffuser does not currently publish typed MeasurementContainer series — parents must consume Port 0 directly. Promoting oOtr / oZoneOtr to typed measurement series is tracked in Reference — Limitations.


Need more?

Page What you'll find
Reference — Contracts Full topic contract, config schema, parent registration handshake
Reference — Architecture Code map, OTR / ΔP pipeline, idle behaviour, output ports
Reference — Examples Shipped example flows + debug recipes
Reference — Limitations When not to use, known limitations, open questions

EVOLV master wiki · Topology Patterns · Topic Conventions