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>
164 lines
4.8 KiB
JSON
164 lines
4.8 KiB
JSON
{
|
||
"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 10–25 %. 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)."
|
||
}
|
||
}
|
||
}
|
||
}
|