Files
generalFunctions/src/configs/diffuser.json
znetsixe c59da5ca98 refactor(curves): canonical axis Nm³/(h·m² membrane) for all diffuser suppliers
Previously each curve file stored x in whatever convention the vendor
used (per-element Nm³/h for Jäger/GVA, per-element Sm³/h for PIK/PRK,
per-m² for Aerostrip). That meant the diffuser physics couldn't read
the data uniformly — selecting Aerostrip vs Jäger would feed wildly
different axes to the same interpolator.

All five curves now use the same canonical X: specific air flux in
Nm³/(h·m² membrane). Y stays SSOTR in g O₂/(Nm³·m); coverage % is the
parametric key.

Per-file conversions:
- jaeger-jetflex-td-65-2-g-epdm-1000: x divided by 0.18 m² perforated
  area (stated on the data sheet).
- gva-elastox-r: x divided by 0.18 m² placeholder mirroring Jäger
  TD-65 (no real GVA sheet exists — see _meta note).
- aerostrip-phoenix: native already in Nm³/(h·m²) — no x change. _meta
  area normalised to 1.0 m² per "element" so users set `elements` =
  total installed membrane area in m².
- pik300, prk300 (Sulzer ABS 300 mm disc): native was Sm³/h/disc on
  X and g O₂/(Sm³·m) on Y. Converted to canonical Nm³ basis (DIN-1343)
  by X × 0.9319 / 0.07, Y × 1.0732. Each disc = 0.07 m² membrane.

Supplier naming fixed: pikprk → sulzer, aquaconsult → aquaconsult-entec.
PIK = perforated EPDM, PRK = perforated PUR.

Config schema: new diffuser.membraneAreaPerElement field (nullable,
default null) so a node can override the curve's stored area. When
null, specificClass reads _meta.membraneArea_m2_per_element from the
resolved curve.

246/246 generalFunctions tests still pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 18:16:34 +02:00

164 lines
4.8 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"general": {
"name": {
"default": "Diffuser",
"rules": {
"type": "string",
"description": "A human-readable name for this diffuser zone."
}
},
"id": {
"default": null,
"rules": {
"type": "string",
"nullable": true,
"description": "Unique identifier for this diffuser node."
}
},
"unit": {
"default": "Nm3/h",
"rules": {
"type": "string",
"description": "Default airflow unit for this diffuser."
}
},
"logging": {
"logLevel": {
"default": "info",
"rules": {
"type": "enum",
"values": [
{ "value": "debug", "description": "Verbose diagnostic messages." },
{ "value": "info", "description": "General informational messages." },
{ "value": "warn", "description": "Warning messages." },
{ "value": "error", "description": "Error level messages only." }
]
}
},
"enabled": {
"default": true,
"rules": {
"type": "boolean",
"description": "Enable or disable logging."
}
}
}
},
"asset": {
"model": {
"default": "gva-elastox-r",
"rules": {
"type": "string",
"description": "Asset model id resolved via assetResolver.resolve('curves', model). Selected from the asset-menu cascade in the editor; defaults to GVA ELASTOX-R for backward compatibility with the legacy hardcoded curve."
}
},
"assetTagNumber": {
"default": "",
"rules": {
"type": "string",
"description": "External asset registry tag number (e.g. Bedrijfsmiddelenregister), assigned by the asset-menu sync to the WBD asset API."
}
}
},
"functionality": {
"softwareType": {
"default": "diffuser",
"rules": {
"type": "string",
"description": "Software type identifier for parent-child registration."
}
},
"role": {
"default": "Aeration diffuser",
"rules": {
"type": "string",
"description": "Describes the functional role of this node."
}
},
"positionVsParent": {
"default": "atEquipment",
"rules": {
"type": "enum",
"values": [
{ "value": "upstream", "description": "Upstream of parent equipment." },
{ "value": "atEquipment", "description": "At equipment level." },
{ "value": "downstream", "description": "Downstream of parent equipment." }
]
}
}
},
"diffuser": {
"number": {
"default": 1,
"rules": {
"type": "number",
"description": "Sequential diffuser zone number."
}
},
"elements": {
"default": 1,
"rules": {
"type": "number",
"description": "Number of diffuser elements in the zone."
}
},
"membraneAreaPerElement": {
"default": null,
"rules": {
"type": "number",
"nullable": true,
"description": "Membrane area per element [m²] used to convert total airflow to canonical specific flux Nm³/(h·m² membrane) before curve lookup. Defaults to the selected curve's _meta.membraneArea_m2_per_element (Jäger 0.18, Sulzer 0.07, Aerostrip 1.0 normalisation). Set explicitly only to override the curve metadata."
}
},
"density": {
"default": 15,
"rules": {
"type": "number",
"description": "Bottom coverage [%] — fraction of the tank floor area occupied by diffuser membrane. Typical fine-bubble installs run 1025 %. Used as the curve-family key in the supplier curve files (multi-coverage curves are interpolated; single-coverage curves are clamped). Replaces the legacy 'elements per m²' semantics, which was an incorrect re-tagging by an earlier refactor."
}
},
"waterHeight": {
"default": 0,
"rules": {
"type": "number",
"description": "Water column height above the diffuser."
}
},
"alfaFactor": {
"default": 0.7,
"rules": {
"type": "number",
"description": "Alpha factor used for oxygen transfer correction."
}
},
"headerPressure": {
"default": 0,
"rules": {
"type": "number",
"description": "Header gauge pressure above atmospheric (mbar)."
}
},
"localAtmPressure": {
"default": 1013.25,
"rules": {
"type": "number",
"description": "Local atmospheric pressure (mbar)."
}
},
"waterDensity": {
"default": 997,
"rules": {
"type": "number",
"description": "Water density used in head-pressure calculation (kg/m3)."
}
},
"zoneVolume": {
"default": 0,
"rules": {
"type": "number",
"description": "Aeration zone volume used to convert oxygen output to reactor OTR (m3)."
}
}
}
}