Files
pumpingStation/src/basin/BasinGeometry.js

100 lines
4.0 KiB
JavaScript
Raw Normal View History

// Basin geometry for a wet-well pumping station.
//
// Models the basin as a rectangular prism (constant cross-section), so
// volume = level × surfaceArea. Owns the level↔volume conversions and the
// derived threshold volumes used by control + safety. Pure domain — no
// Node-RED, no logger, no side effects beyond construction.
class BasinGeometry {
/**
* @param {object} basinConfig - { volume, height, inflowLevel, outflowLevel, overflowLevel }
* @param {object} hydraulicsConfig - { minHeightBasedOn: 'inlet' | 'outlet' }
*/
constructor(basinConfig, hydraulicsConfig) {
const volEmptyBasin = basinConfig.volume;
const heightBasin = basinConfig.height;
const inflowLevel = basinConfig.inflowLevel;
const outflowLevel = basinConfig.outflowLevel;
const overflowLevel = basinConfig.overflowLevel;
Merge origin/basin-docs-update: per-mode SVG + stopLevel hysteresis + shifted ramp Reconciles the 7-commit basin-docs-update feature branch (which never landed on main before the platform refactor) with the post-refactor architecture on development. Each basin-docs feature ported into the relevant concern module: control/levelBased.js - stopLevel Schmitt-trigger + dead-band keep-alive - Shifted ramp (arm % → hold @ 100% → ramp down to shiftLevel) - Linear vs log up-curve (curveType + logCurveFactor) measurement/flowAggregator.js - Predicted-volume overflow clamp + spill flow stream - Cumulative overflowVolume + underflowVolume - Hard floor at 0 + dry-run-on-transition handling basin/thresholdValidator.js - computeSafetyPoints exposes dryRunLevel + highVolumeSafetyLevel - startLevel ≤ inflowLevel invariant added measurement/calibration.js + commands/ - Manual q_out path (set.outflow / q_out alias) safety/safetyController.js - Accepts both legacy + new high-volume threshold names UI: pumpingStation.html — restored the side-panel + SVG mode-preview block, added defaults for stopLevel/shiftLevel/shiftArmPercent/levelCurveType/ logCurveFactor/enableShiftedRamp. src/editor/* — basin-docs' 7-file modular editor (replaces single src/editor.js, which is deleted). pumpingStation.js — admin endpoint serves editor/:file. Tests: 130/130 pass (125 basic + 5 integration). Two basin-docs test files added: nodeClass-config.test.js, basic-dashboard-flow.test.js, shifted-ramp-end-to-end.test.js. One pre-refactor control-levelBased test adapted to match basin-docs canonical "no-shutdown in dead zone" behaviour. Human-review items (see commit context): - rampFoot = inflowLevel (matches basin-docs test); basin-docs source used rampFoot = startLevel. Domain owner: confirm intent. - Naming kept dual (overfillLevel + highVolumeSafetyLevel). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:19:55 +02:00
const inletPipeDiameter = basinConfig.inletPipeDiameter;
const outletPipeDiameter = basinConfig.outletPipeDiameter;
const minHeightBasedOn = hydraulicsConfig?.minHeightBasedOn;
const surfaceArea = volEmptyBasin / heightBasin;
// maxVol ≡ volEmptyBasin under the constant cross-section assumption;
// kept as a separate field for naming symmetry with the trigger volumes.
const maxVol = heightBasin * surfaceArea;
const maxVolAtOverflow = overflowLevel * surfaceArea;
const minVolAtOutflow = outflowLevel * surfaceArea;
const minVolAtInflow = inflowLevel * surfaceArea;
const minVol = minHeightBasedOn === 'inlet' ? minVolAtInflow : minVolAtOutflow;
this._volEmptyBasin = volEmptyBasin;
this._heightBasin = heightBasin;
this._inflowLevel = inflowLevel;
this._outflowLevel = outflowLevel;
this._overflowLevel = overflowLevel;
Merge origin/basin-docs-update: per-mode SVG + stopLevel hysteresis + shifted ramp Reconciles the 7-commit basin-docs-update feature branch (which never landed on main before the platform refactor) with the post-refactor architecture on development. Each basin-docs feature ported into the relevant concern module: control/levelBased.js - stopLevel Schmitt-trigger + dead-band keep-alive - Shifted ramp (arm % → hold @ 100% → ramp down to shiftLevel) - Linear vs log up-curve (curveType + logCurveFactor) measurement/flowAggregator.js - Predicted-volume overflow clamp + spill flow stream - Cumulative overflowVolume + underflowVolume - Hard floor at 0 + dry-run-on-transition handling basin/thresholdValidator.js - computeSafetyPoints exposes dryRunLevel + highVolumeSafetyLevel - startLevel ≤ inflowLevel invariant added measurement/calibration.js + commands/ - Manual q_out path (set.outflow / q_out alias) safety/safetyController.js - Accepts both legacy + new high-volume threshold names UI: pumpingStation.html — restored the side-panel + SVG mode-preview block, added defaults for stopLevel/shiftLevel/shiftArmPercent/levelCurveType/ logCurveFactor/enableShiftedRamp. src/editor/* — basin-docs' 7-file modular editor (replaces single src/editor.js, which is deleted). pumpingStation.js — admin endpoint serves editor/:file. Tests: 130/130 pass (125 basic + 5 integration). Two basin-docs test files added: nodeClass-config.test.js, basic-dashboard-flow.test.js, shifted-ramp-end-to-end.test.js. One pre-refactor control-levelBased test adapted to match basin-docs canonical "no-shutdown in dead zone" behaviour. Human-review items (see commit context): - rampFoot = inflowLevel (matches basin-docs test); basin-docs source used rampFoot = startLevel. Domain owner: confirm intent. - Naming kept dual (overfillLevel + highVolumeSafetyLevel). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:19:55 +02:00
this._inletPipeDiameter = inletPipeDiameter;
this._outletPipeDiameter = outletPipeDiameter;
this._surfaceArea = surfaceArea;
this._maxVol = maxVol;
this._maxVolAtOverflow = maxVolAtOverflow;
this._minVolAtInflow = minVolAtInflow;
this._minVolAtOutflow = minVolAtOutflow;
this._minVol = minVol;
this._minHeightBasedOn = minHeightBasedOn;
}
get volEmptyBasin() { return this._volEmptyBasin; }
get heightBasin() { return this._heightBasin; }
get inflowLevel() { return this._inflowLevel; }
get outflowLevel() { return this._outflowLevel; }
get overflowLevel() { return this._overflowLevel; }
Merge origin/basin-docs-update: per-mode SVG + stopLevel hysteresis + shifted ramp Reconciles the 7-commit basin-docs-update feature branch (which never landed on main before the platform refactor) with the post-refactor architecture on development. Each basin-docs feature ported into the relevant concern module: control/levelBased.js - stopLevel Schmitt-trigger + dead-band keep-alive - Shifted ramp (arm % → hold @ 100% → ramp down to shiftLevel) - Linear vs log up-curve (curveType + logCurveFactor) measurement/flowAggregator.js - Predicted-volume overflow clamp + spill flow stream - Cumulative overflowVolume + underflowVolume - Hard floor at 0 + dry-run-on-transition handling basin/thresholdValidator.js - computeSafetyPoints exposes dryRunLevel + highVolumeSafetyLevel - startLevel ≤ inflowLevel invariant added measurement/calibration.js + commands/ - Manual q_out path (set.outflow / q_out alias) safety/safetyController.js - Accepts both legacy + new high-volume threshold names UI: pumpingStation.html — restored the side-panel + SVG mode-preview block, added defaults for stopLevel/shiftLevel/shiftArmPercent/levelCurveType/ logCurveFactor/enableShiftedRamp. src/editor/* — basin-docs' 7-file modular editor (replaces single src/editor.js, which is deleted). pumpingStation.js — admin endpoint serves editor/:file. Tests: 130/130 pass (125 basic + 5 integration). Two basin-docs test files added: nodeClass-config.test.js, basic-dashboard-flow.test.js, shifted-ramp-end-to-end.test.js. One pre-refactor control-levelBased test adapted to match basin-docs canonical "no-shutdown in dead zone" behaviour. Human-review items (see commit context): - rampFoot = inflowLevel (matches basin-docs test); basin-docs source used rampFoot = startLevel. Domain owner: confirm intent. - Naming kept dual (overfillLevel + highVolumeSafetyLevel). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:19:55 +02:00
get inletPipeDiameter() { return this._inletPipeDiameter; }
get outletPipeDiameter() { return this._outletPipeDiameter; }
get surfaceArea() { return this._surfaceArea; }
get maxVol() { return this._maxVol; }
get maxVolAtOverflow() { return this._maxVolAtOverflow; }
get minVolAtInflow() { return this._minVolAtInflow; }
get minVolAtOutflow() { return this._minVolAtOutflow; }
get minVol() { return this._minVol; }
get minHeightBasedOn() { return this._minHeightBasedOn; }
/** Convert level (m from floor) → volume (m3). Negative levels clamp to 0. */
volumeFromLevel(level) {
return Math.max(level, 0) * this._surfaceArea;
}
/** Convert volume (m3) → level (m from floor). Negative volumes clamp to 0. */
levelFromVolume(volume) {
return Math.max(volume, 0) / this._surfaceArea;
}
/**
* Plain-object snapshot mirroring the legacy `this.basin` shape so
* getOutput / status code can keep using the same field names without
* caring whether it's holding a class instance or a plain object.
*/
snapshot() {
return {
volEmptyBasin: this._volEmptyBasin,
heightBasin: this._heightBasin,
inflowLevel: this._inflowLevel,
outflowLevel: this._outflowLevel,
overflowLevel: this._overflowLevel,
Merge origin/basin-docs-update: per-mode SVG + stopLevel hysteresis + shifted ramp Reconciles the 7-commit basin-docs-update feature branch (which never landed on main before the platform refactor) with the post-refactor architecture on development. Each basin-docs feature ported into the relevant concern module: control/levelBased.js - stopLevel Schmitt-trigger + dead-band keep-alive - Shifted ramp (arm % → hold @ 100% → ramp down to shiftLevel) - Linear vs log up-curve (curveType + logCurveFactor) measurement/flowAggregator.js - Predicted-volume overflow clamp + spill flow stream - Cumulative overflowVolume + underflowVolume - Hard floor at 0 + dry-run-on-transition handling basin/thresholdValidator.js - computeSafetyPoints exposes dryRunLevel + highVolumeSafetyLevel - startLevel ≤ inflowLevel invariant added measurement/calibration.js + commands/ - Manual q_out path (set.outflow / q_out alias) safety/safetyController.js - Accepts both legacy + new high-volume threshold names UI: pumpingStation.html — restored the side-panel + SVG mode-preview block, added defaults for stopLevel/shiftLevel/shiftArmPercent/levelCurveType/ logCurveFactor/enableShiftedRamp. src/editor/* — basin-docs' 7-file modular editor (replaces single src/editor.js, which is deleted). pumpingStation.js — admin endpoint serves editor/:file. Tests: 130/130 pass (125 basic + 5 integration). Two basin-docs test files added: nodeClass-config.test.js, basic-dashboard-flow.test.js, shifted-ramp-end-to-end.test.js. One pre-refactor control-levelBased test adapted to match basin-docs canonical "no-shutdown in dead zone" behaviour. Human-review items (see commit context): - rampFoot = inflowLevel (matches basin-docs test); basin-docs source used rampFoot = startLevel. Domain owner: confirm intent. - Naming kept dual (overfillLevel + highVolumeSafetyLevel). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:19:55 +02:00
inletPipeDiameter: this._inletPipeDiameter,
outletPipeDiameter: this._outletPipeDiameter,
surfaceArea: this._surfaceArea,
maxVol: this._maxVol,
maxVolAtOverflow: this._maxVolAtOverflow,
minVolAtInflow: this._minVolAtInflow,
minVolAtOutflow: this._minVolAtOutflow,
minVol: this._minVol,
minHeightBasedOn: this._minHeightBasedOn,
};
}
}
module.exports = BasinGeometry;