Skip to content

feat: add Pump and LiquidStream to process domain#1516

Draft
kjbrak wants to merge 10 commits intomainfrom
feature/pump-process-unit-v2
Draft

feat: add Pump and LiquidStream to process domain#1516
kjbrak wants to merge 10 commits intomainfrom
feature/pump-process-unit-v2

Conversation

@kjbrak
Copy link
Copy Markdown
Contributor

@kjbrak kjbrak commented Apr 29, 2026

Summary

Adds pump and liquid stream support to the process domain, enabling pump trains to use the same solver infrastructure as compressor trains — speed solving, anti-surge recirculation, and pressure control.

This is Phase 1: the domain layer entities, protocols, and solver integration. YAML wiring (schema, mapper, result assembly) is Phase 2 and will follow in a separate PR.

What's included

New entities

  • Pump — process unit implementing ProcessUnit protocol. Variable-speed, chart-based head/efficiency lookup, propagate_stream(LiquidStream) → LiquidStream
  • LiquidStream — frozen dataclass for incompressible fluids (pressure, density, mass rate). Implements MixableStream and StreamWithPressure protocols
  • LiquidProcessUnit — ABC for process units operating on liquid streams

Protocol generalisation

  • ProcessUnit protocol made stream-agnostic via StreamWithPressure (was hardcoded to FluidStream)
  • RecirculatingUnit protocol extracted for units that expose capacity boundaries (compressor + pump)
  • ShaftConnectable protocol so Shaft works with both Compressor and Pump
  • MixableStream protocol so DirectMixer/DirectSplitter work with both gas and liquid streams
  • Renamed old ProcessUnit ABC → GasProcessUnit to avoid collision with the protocol

Solver support

  • OutletPressureSolver, anti-surge strategies, and pressure control strategies all work with pumps — no pump-specific solver code needed
  • RecirculationLoop, DirectMixer, DirectSplitter support liquid streams via protocol dispatch

Tests

  • 3 pump unit tests (chart lookup, speed solving, edge cases)
  • 3 pump integration tests (outlet pressure solver with speed, recirculation, pressure control)
  • Legacy vs new pump comparison test (validates against existing PumpSingleSpeed calculations)
  • Liquid recirculation loop + solver tests
  • All existing compressor tests updated for renames and passing (53 total process solver tests)

What's NOT included (Phase 2)

  • YAML schema for pump stages
  • Mapper to create Pump from YAML config
  • Result assembly (Pump → PumpModelResult)
  • PumpFeasibilitySolver for parallel pump systems

Type of Work

  • Minor: X.Y+1.Z — adds new domain entities, backwards-compatible, no YAML/output changes yet

olelod and others added 9 commits April 29, 2026 11:35
- LiquidProcessUnit ABC: typed boundary for incompressible liquid units
- LiquidStream value object: pressure, density, mass rate; volumetric_rate,
  standard_density_gas_phase_after_flash, standard_rate_sm3_per_day, with_mass_rate()
- Pump: LiquidProcessUnit backed by UserDefinedChartData, computes head/efficiency
  from chart interpolation, raises RateTooLowError / RateTooHighError, exposes
  get_shaft_power_mw()
…w control

- RecirculationLoop now accepts Pump (LiquidProcessUnit) as inner process, in
  addition to Compressor and ProcessSystem
- DirectMixer/DirectSplitter work with both FluidStream and LiquidStream via
  duck-typed standard_density_gas_phase_after_flash / with_mass_rate()
- LiquidStream.standard_density_gas_phase_after_flash returns density_kg_per_m3
  (standard ≈ actual for incompressible liquids, consistent with legacy PumpModel)
- RecirculationLoop.get_shaft_power_mw() delegates to inner Pump
- All test files updated to use RecirculationLoop/DirectMixer/DirectSplitter directly
  with Sm3/day rates
…bounds to Pump

- ShaftConnectable Protocol: minimum_speed, maximum_speed, set_speed()
- Shaft is now generic Shaft[T: ShaftConnectable] — a shaft drives either
  compressors or pumps, never a mix of both; enforced at the type level
- Shaft._compressors renamed to _units; connect()/get_speed_boundary()
  use the protocol instead of importing Compressor directly
- Compressor gains minimum_speed / maximum_speed properties (delegates to
  compressor_chart) to satisfy ShaftConnectable
- Pump gains minimum_speed / maximum_speed properties (delegates to pump_chart)
  to satisfy ShaftConnectable — a pump shaft is now a VariableSpeedShaft[Pump]
…otocol

- Add RecirculatingUnit protocol (get_id, maximum_flow_rate, get_recirculation_range)
- Pump implements RecirculatingUnit via minimum_flow_rate, maximum_flow_rate, get_recirculation_range()
- Replace Compressor with RecirculatingUnit in all strategy classes:
  - anti_surge/common_asv.py: first_compressor → first_unit
  - anti_surge/individual_asv.py: compressors → units
  - pressure_control/common_asv.py: first_compressor → first_unit
  - pressure_control/individual_asv.py: compressors → units
- Replace FluidStream with Any in all solver/strategy method signatures:
  - outlet_pressure_solver.py, anti_surge_strategy.py, pressure_control_strategy.py
  - common_asv.py (both anti_surge and pressure_control), individual_asv.py (both)
- ProcessRunner.run() and ProcessSystemRunner._propagate_stream_to_id() accept Any stream
- Update all call sites in mapper and tests (first_compressor= → first_unit=, compressors= → units=)
- Fix pump._head_and_efficiency → _head_and_efficiency_at_rate rename
…t to GasProcessUnit

- ProcessUnit is now the stream-agnostic protocol (get_id + propagate_stream)
- GasProcessUnit is the gas-specific ABC extending Entity
- Detach DirectMixer/DirectSplitter from ABC hierarchy (standalone, uuid7)
- Move protocol from stream_protocol.py to process_pipeline/process_unit.py
- Add pump integration tests (speed solver, shaft power, recirculation)
- Clean up FluidStream.standard_density docstring
- Rename first_compressor → first_unit in new ASV test factories
- Fix FluidStream → StreamWithPressure type annotation in individual_asv.py
- xfail pump recirculation test pending boundary calculation investigation
The regression test from PR #1515 used first_compressor= kwarg which was
renamed to first_unit= on this branch. Also remove xfail from pump
recirculation test since the underlying bug is now fixed on main.
Widen choke solver and pressure control strategy signatures from
FluidStream to StreamWithPressure for consistency. Add pyright ignore
comments where cached_property on FluidStream prevents structural
protocol matching (a known basedpyright limitation with cached_property
vs @Property in protocols). Add propagate_stream to RecirculatingUnit
protocol.
Replace Generic[_T] with PEP 695 class Shaft[T: ShaftConnectable] syntax,
as required by ruff UP046.
@kjbrak kjbrak force-pushed the feature/pump-process-unit-v2 branch from 071ad44 to 35faa36 Compare April 29, 2026 12:19
Convert remaining Generic[T]/TypeVar usages to PEP 695 syntax:
- Shaft, SingleSpeedShaft, VariableSpeedShaft
- Overflow, CommonStreamDistribution
- Builder (yaml_builder)
Remove unused TYamlClass TypeVar and YamlBase import.
Fix import sorting (ruff I001) and UP035 (typing_extensions).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants