Skip to content

Commit 3f089e1

Browse files
committed
refactor: rename Mixer/Splitter to Legacy, introduce single-stream ProcessUnit variants
- Rename Mixer → LegacyMixer (mixer/mixer.py → legacy_mixer/legacy_mixer.py) - Rename Splitter → LegacySplitter (splitter/splitter.py → legacy_splitter/legacy_splitter.py) - Introduce Mixer(ProcessUnit) in process_units/mixer.py: adds one external stream to a through-stream - Introduce Splitter(ProcessUnit) in process_units/splitter.py: removes a fixed rate from a through-stream - Add tests for new Mixer and Splitter
1 parent 9ad1cce commit 3f089e1

13 files changed

Lines changed: 274 additions & 33 deletions

File tree

src/libecalc/domain/process/compressor/core/train/stage.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414
from libecalc.domain.process.compressor.core.train.utils.numeric_methods import find_root
1515
from libecalc.domain.process.entities.process_units.choke import Choke
1616
from libecalc.domain.process.entities.process_units.legacy_compressor.legacy_compressor import LegacyCompressor
17+
from libecalc.domain.process.entities.process_units.legacy_mixer.legacy_mixer import LegacyMixer
18+
from libecalc.domain.process.entities.process_units.legacy_splitter.legacy_splitter import (
19+
LegacySplitter,
20+
)
1721
from libecalc.domain.process.entities.process_units.liquid_remover import LiquidRemover
18-
from libecalc.domain.process.entities.process_units.mixer.mixer import Mixer
1922
from libecalc.domain.process.entities.process_units.rate_modifier.rate_modifier import RateModifier
20-
from libecalc.domain.process.entities.process_units.splitter.splitter import Splitter
2123
from libecalc.domain.process.entities.process_units.temperature_setter import TemperatureSetter
2224
from libecalc.domain.process.value_objects.chart.chart_area_flag import ChartAreaFlag
2325
from libecalc.domain.process.value_objects.fluid_stream import FluidService, FluidStream
@@ -29,8 +31,8 @@ class CompressorTrainStage:
2931
3032
The stage is composed of a series of process units that modify the inlet stream before it enters the compressor.
3133
The process units are:
32-
- Splitter: Splits the inlet stream if required. One stream goes towards the compressor, the other(s) are taken out.
33-
- Mixer: Mixes the inlet stream with other streams if required.
34+
- LegacySplitter: Splits the inlet stream if required. One stream goes towards the compressor, the other(s) are taken out.
35+
- LegacyMixer: Mixes the inlet stream with other streams if required.
3436
- TemperatureSetter: Cools the inlet stream to a required temperature. Often termed an intercooler.
3537
- LiquidRemover: Removes liquid from the inlet stream if required. Often termed a scrubber.
3638
- Choke: Chokes the inlet stream if a choke valve is defined (pressure drop ahead of stage).
@@ -48,8 +50,8 @@ def __init__(
4850
liquid_remover: LiquidRemover | None,
4951
rate_modifier: RateModifier,
5052
fluid_service: FluidService,
51-
splitter: Splitter | None = None,
52-
mixer: Mixer | None = None,
53+
splitter: LegacySplitter | None = None,
54+
mixer: LegacyMixer | None = None,
5355
choke: Choke | None = None,
5456
interstage_pressure_control: InterstagePressureControl | None = None,
5557
):
@@ -105,7 +107,7 @@ def get_compressor_inlet_stream(
105107
rates_out_of_splitter: list[float] | None = None,
106108
streams_in_to_mixer: list[FluidStream] | None = None,
107109
):
108-
# First the stream passes through the Splitter (if defined)
110+
# First the stream passes through the LegacySplitter (if defined)
109111
if self.splitter is not None:
110112
self.splitter.rates_out_of_splitter = rates_out_of_splitter
111113
inlet_stream_after_splitter = self.split(
@@ -114,7 +116,7 @@ def get_compressor_inlet_stream(
114116
else:
115117
inlet_stream_after_splitter = inlet_stream_stage
116118

117-
# Then the stream passes through the Mixer (if defined)
119+
# Then the stream passes through the LegacyMixer (if defined)
118120
if self.mixer is not None:
119121
if streams_in_to_mixer is None:
120122
raise IllegalStateException("streams_in_to_mixer cannot be None when a mixer is defined")
@@ -157,9 +159,9 @@ def evaluate(
157159
158160
Args:
159161
inlet_stream_stage (FluidStream): The conditions of the inlet fluid stream. If there are several inlet streams,
160-
the first one is the stage inlet stream, the others enter the stage at the Mixer.
161-
rates_out_of_splitter (list[float] | None, optional): Additional rates to the Splitter if defined.
162-
streams_in_to_mixer (list[FluidStream] | None, optional): Additional streams to the Mixer if defined.
162+
the first one is the stage inlet stream, the others enter the stage at the LegacyMixer.
163+
rates_out_of_splitter (list[float] | None, optional): Additional rates to the LegacySplitter if defined.
164+
streams_in_to_mixer (list[FluidStream] | None, optional): Additional streams to the LegacyMixer if defined.
163165
164166
Returns:
165167
CompressorTrainStageResultSingleTimeStep: The result of the evaluation for the compressor stage
@@ -256,8 +258,8 @@ def mix(
256258
assert streams_in_to_mixer is not None
257259
if self.mixer.number_of_inputs != len(streams_in_to_mixer) + 1:
258260
raise IllegalStateException(
259-
f"Number of additional rates to Mixer ({len(streams_in_to_mixer)}) "
260-
f"does not match number of Mixer inputs ({self.mixer.number_of_inputs})."
261+
f"Number of additional rates to LegacyMixer ({len(streams_in_to_mixer)}) "
262+
f"does not match number of LegacyMixer inputs ({self.mixer.number_of_inputs})."
261263
)
262264

263265
all_streams_to_mixer = [inlet_stream_stage] + streams_in_to_mixer

src/libecalc/domain/process/entities/process_units/mixer/__init__.py renamed to src/libecalc/domain/process/entities/process_units/legacy_mixer/__init__.py

File renamed without changes.

src/libecalc/domain/process/entities/process_units/mixer/mixer.py renamed to src/libecalc/domain/process/entities/process_units/legacy_mixer/legacy_mixer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from libecalc.domain.process.value_objects.fluid_stream import FluidService, FluidStream
55

66

7-
class Mixer:
7+
class LegacyMixer:
88
def __init__(self, number_of_inputs: int, fluid_service: FluidService):
99
self.number_of_inputs = number_of_inputs
1010
self._stream_mixer = SimplifiedStreamMixer(fluid_service)

src/libecalc/domain/process/entities/process_units/splitter/__init__.py renamed to src/libecalc/domain/process/entities/process_units/legacy_splitter/__init__.py

File renamed without changes.

src/libecalc/domain/process/entities/process_units/splitter/splitter.py renamed to src/libecalc/domain/process/entities/process_units/legacy_splitter/legacy_splitter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from libecalc.domain.process.value_objects.fluid_stream import FluidStream
33

44

5-
class Splitter:
5+
class LegacySplitter:
66
"""
77
A class representing a splitter that divides a fluid stream into multiple output streams.
88
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from libecalc.domain.process.entities.process_units.simplified_stream_mixer.simplified_stream_mixer import (
2+
SimplifiedStreamMixer,
3+
)
4+
from libecalc.domain.process.process_system.process_unit import ProcessUnit, ProcessUnitId
5+
from libecalc.domain.process.value_objects.fluid_stream import FluidService, FluidStream
6+
7+
8+
class Mixer(ProcessUnit):
9+
"""Mixes one external stream into the through-stream.
10+
11+
The external stream is set via `set_stream` before propagation. This models
12+
a sidestream injection point in an interstage manifold.
13+
"""
14+
15+
def __init__(self, process_unit_id: ProcessUnitId, fluid_service: FluidService):
16+
self._id = process_unit_id
17+
self._mixer = SimplifiedStreamMixer(fluid_service)
18+
self._external_stream: FluidStream | None = None
19+
20+
def get_id(self) -> ProcessUnitId:
21+
return self._id
22+
23+
def set_stream(self, stream: FluidStream) -> None:
24+
self._external_stream = stream
25+
26+
def propagate_stream(self, inlet_stream: FluidStream) -> FluidStream:
27+
if self._external_stream is None:
28+
raise ValueError("Mixer has no external stream set; call set_stream() before propagating.")
29+
return self._mixer.mix_streams([inlet_stream, self._external_stream])

src/libecalc/domain/process/entities/process_units/recirculation_loop.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from collections.abc import Sequence
22

33
from libecalc.domain.component_validation_error import DomainValidationException
4-
from libecalc.domain.process.entities.process_units.mixer.mixer import Mixer
5-
from libecalc.domain.process.entities.process_units.splitter.splitter import Splitter
4+
from libecalc.domain.process.entities.process_units.mixer import Mixer
5+
from libecalc.domain.process.entities.process_units.splitter import Splitter
66
from libecalc.domain.process.process_system.process_system import ProcessSystem, ProcessSystemId
77
from libecalc.domain.process.process_system.process_unit import ProcessUnit, ProcessUnitId, create_process_unit_id
88
from libecalc.domain.process.value_objects.fluid_stream import FluidService, FluidStream
@@ -79,7 +79,7 @@ def __init__(
7979
def _validate_inner_process(self):
8080
assert isinstance(self._inner_process, ProcessSystem), "Recirculation loop should contain a ProcessSystem"
8181
for process_unit in self._inner_process.get_process_units():
82-
if isinstance(process_unit, Splitter | Mixer):
82+
if isinstance(process_unit, Mixer | Splitter):
8383
raise DomainValidationException("Recirculation loop cannot contain splitters or mixers")
8484

8585
def get_id(self) -> ProcessSystemId:
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from libecalc.domain.process.process_system.process_unit import ProcessUnit, ProcessUnitId
2+
from libecalc.domain.process.value_objects.fluid_stream import FluidService, FluidStream
3+
4+
5+
class Splitter(ProcessUnit):
6+
"""Removes a fixed standard rate from the through-stream.
7+
8+
The split rate is set via `set_rate` before propagation. This models a gas
9+
offtake point (e.g. fuel gas) in an interstage manifold. The remainder
10+
continues downstream.
11+
"""
12+
13+
def __init__(self, process_unit_id: ProcessUnitId, fluid_service: FluidService, rate: float = 0.0):
14+
self._id = process_unit_id
15+
self._fluid_service = fluid_service
16+
self._rate = rate
17+
18+
def get_id(self) -> ProcessUnitId:
19+
return self._id
20+
21+
def set_rate(self, rate: float) -> None:
22+
self._rate = rate
23+
24+
def get_rate(self) -> float:
25+
return self._rate
26+
27+
def propagate_stream(self, inlet_stream: FluidStream) -> FluidStream:
28+
remaining_rate = inlet_stream.standard_rate_sm3_per_day - self._rate
29+
return self._fluid_service.create_stream_from_standard_rate(
30+
fluid_model=inlet_stream.fluid_model,
31+
pressure_bara=inlet_stream.pressure_bara,
32+
temperature_kelvin=inlet_stream.temperature_kelvin,
33+
standard_rate_m3_per_day=remaining_rate,
34+
)
35+
36+
def get_split_stream(self, inlet_stream: FluidStream) -> FluidStream:
37+
"""Return the stream that was split off, at the same conditions as the inlet."""
38+
return self._fluid_service.create_stream_from_standard_rate(
39+
fluid_model=inlet_stream.fluid_model,
40+
pressure_bara=inlet_stream.pressure_bara,
41+
temperature_kelvin=inlet_stream.temperature_kelvin,
42+
standard_rate_m3_per_day=self._rate,
43+
)

src/libecalc/presentation/yaml/mappers/consumer_function_mapper.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,12 @@
4444
from libecalc.domain.process.compressor.core.train.stage import CompressorTrainStage
4545
from libecalc.domain.process.entities.process_units.choke import Choke
4646
from libecalc.domain.process.entities.process_units.legacy_compressor.legacy_compressor import LegacyCompressor
47+
from libecalc.domain.process.entities.process_units.legacy_mixer.legacy_mixer import LegacyMixer
48+
from libecalc.domain.process.entities.process_units.legacy_splitter.legacy_splitter import (
49+
LegacySplitter,
50+
)
4751
from libecalc.domain.process.entities.process_units.liquid_remover import LiquidRemover
48-
from libecalc.domain.process.entities.process_units.mixer.mixer import Mixer
4952
from libecalc.domain.process.entities.process_units.rate_modifier.rate_modifier import RateModifier
50-
from libecalc.domain.process.entities.process_units.splitter.splitter import Splitter
5153
from libecalc.domain.process.entities.process_units.temperature_setter import TemperatureSetter
5254
from libecalc.domain.process.entities.shaft import Shaft, SingleSpeedShaft, VariableSpeedShaft
5355
from libecalc.domain.process.evaluation_input import (
@@ -377,10 +379,12 @@ def _create_compressor_train_stage(
377379
),
378380
interstage_pressure_control=interstage_pressure_control,
379381
splitter=(
380-
Splitter(number_of_splitter_ports_this_stage + 1) if number_of_splitter_ports_this_stage > 0 else None
382+
LegacySplitter(number_of_splitter_ports_this_stage + 1)
383+
if number_of_splitter_ports_this_stage > 0
384+
else None
381385
),
382386
mixer=(
383-
Mixer(number_of_mixer_ports_this_stage + 1, fluid_service=fluid_service)
387+
LegacyMixer(number_of_mixer_ports_this_stage + 1, fluid_service=fluid_service)
384388
if number_of_mixer_ports_this_stage > 0
385389
else None
386390
),

tests/libecalc/conftest.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@
1515
from libecalc.domain.process.entities.process_units.choke import Choke
1616
from libecalc.domain.process.entities.process_units.compressor import Compressor
1717
from libecalc.domain.process.entities.process_units.legacy_compressor.legacy_compressor import LegacyCompressor
18+
from libecalc.domain.process.entities.process_units.legacy_mixer.legacy_mixer import LegacyMixer
19+
from libecalc.domain.process.entities.process_units.legacy_splitter.legacy_splitter import (
20+
LegacySplitter,
21+
)
1822
from libecalc.domain.process.entities.process_units.liquid_remover import LiquidRemover
19-
from libecalc.domain.process.entities.process_units.mixer.mixer import Mixer
2023
from libecalc.domain.process.entities.process_units.rate_modifier.rate_modifier import RateModifier
2124
from libecalc.domain.process.entities.process_units.recirculation_loop import RecirculationLoop
22-
from libecalc.domain.process.entities.process_units.splitter.splitter import Splitter
2325
from libecalc.domain.process.entities.process_units.temperature_setter import TemperatureSetter
2426
from libecalc.domain.process.entities.shaft import Shaft, SingleSpeedShaft, VariableSpeedShaft
2527
from libecalc.domain.process.process_solver.process_system_runner import ProcessSystemRunner
@@ -299,10 +301,10 @@ def create_compressor_stage(
299301
fluid_service=fluid_service,
300302
choke=choke_factory(pressure_change=pressure_drop_ahead_of_stage) if pressure_drop_ahead_of_stage else None,
301303
interstage_pressure_control=interstage_pressure_control,
302-
splitter=Splitter(number_of_outputs=number_of_output_ports_stage + 1)
304+
splitter=LegacySplitter(number_of_outputs=number_of_output_ports_stage + 1)
303305
if number_of_output_ports_stage > 0
304306
else None,
305-
mixer=Mixer(number_of_inputs=number_of_input_ports_stage + 1, fluid_service=fluid_service)
307+
mixer=LegacyMixer(number_of_inputs=number_of_input_ports_stage + 1, fluid_service=fluid_service)
306308
if number_of_input_ports_stage > 0
307309
else None,
308310
)

0 commit comments

Comments
 (0)