Skip to content

Commit

Permalink
feat: multiple streams in system (#242)
Browse files Browse the repository at this point in the history
Multiple streams can be used to handle crossover streams individually in
a train. Currently no additional streams can be given, as the system
does not support providing several rates/streams per consumer.
  • Loading branch information
jsolaas authored Oct 19, 2023
1 parent 8b97673 commit 419c2e9
Show file tree
Hide file tree
Showing 13 changed files with 342 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/libecalc/common/stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Config:
alias_generator = to_camel_case
allow_population_by_field_name = True

name: Optional[str]
rate: TimeSeriesRate
pressure: TimeSeriesFloat
fluid_density: Optional[TimeSeriesFloat] = None
Expand Down
1 change: 1 addition & 0 deletions src/libecalc/core/consumers/consumer_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ def _get_operational_settings_adjusted_for_crossover(
if has_crossover_out:
max_rate = consumer.get_max_rate(consumer_operational_settings)
crossover_stream, inlet_streams = ConsumerSystem._get_crossover_streams(max_rate, inlet_streams)
crossover_stream.name = crossover_stream_definition.stream_name
crossover_streams_map[crossover_stream_definition.to_component_id].append(crossover_stream)

consumer_operational_settings.inlet_streams = [*inlet_streams, *crossover_streams_map[consumer.id]]
Expand Down
1 change: 1 addition & 0 deletions src/libecalc/core/models/compressor/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def _create_variable_speed_compressor_train_multiple_streams_and_pressures_strea
) -> FluidStreamObjectForMultipleStreams:
is_inlet_stream = stream_data.typ == dto.types.FluidStreamType.INGOING
return FluidStreamObjectForMultipleStreams(
name=stream_data.name,
fluid=FluidStream(fluid_model=stream_data.fluid_model) if stream_data.fluid_model else None,
is_inlet_stream=is_inlet_stream,
connected_to_stage_no=stream_references[stream_data.name],
Expand Down
1 change: 1 addition & 0 deletions src/libecalc/core/models/compressor/train/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class FluidStreamObjectForMultipleStreams(BaseModel):
Outlet stream is what comes out of the compressor.
"""

name: Optional[str]
fluid: Optional[FluidStream]
is_inlet_stream: bool
connected_to_stage_no: int = 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from libecalc import dto
from libecalc.common.exceptions import EcalcError, IllegalStateException
from libecalc.common.logger import logger
from libecalc.common.stream import Stream
from libecalc.common.units import Unit, UnitConstants
from libecalc.core.models.compressor.results import CompressorTrainResultSingleTimeStep
from libecalc.core.models.compressor.train.base import CompressorTrainModel
Expand Down Expand Up @@ -95,6 +96,54 @@ def __init__(
# previous time step to recirculate. This will take care of that.
self.fluid_to_recirculate_in_stage_when_inlet_rate_is_zero = [None] * len(self.stages)

def evaluate_streams(
self,
inlet_streams: List[Stream],
outlet_stream: Stream,
) -> CompressorTrainResult:
"""
Evaluate model based on inlet streams and the expected outlet stream.
Args:
inlet_streams:
outlet_stream:
Returns:
"""

if len(inlet_streams) != len(self.streams):
named_streams = [inlet_stream.name for inlet_stream in inlet_streams if inlet_stream.name]
raise EcalcError(
title="Validation error",
message=f"Mismatch in streams. "
f'Required streams are {", ".join(stream.name for stream in self.streams)}. '
f'Received named streams are {", ".join(named_streams) if len(named_streams) > 0 else "none"}'
f" + {len(inlet_streams) - len(named_streams)} unnamed stream(s).",
)

# Order streams either based on name or use index
stream_index_counter = 0
ordered_streams: List[Stream] = []
for stream_definition in self.streams:
try:
inlet_stream = next(
inlet_stream for inlet_stream in inlet_streams if inlet_stream.name == stream_definition.name
)
ordered_streams.append(inlet_stream)
except StopIteration:
ordered_streams.append(inlet_streams[stream_index_counter])
stream_index_counter += 1

# Currently ignoring pressures in intermediate streams

return self.evaluate_rate_ps_pd(
rate=np.asarray(
[inlet_stream.rate.values for inlet_stream in ordered_streams]
), # TODO: This can also contain rates defined as outlet streams
suction_pressure=np.asarray(inlet_streams[0].pressure.values),
discharge_pressure=np.asarray(outlet_stream.pressure.values),
)

@staticmethod
def _check_intermediate_pressure_stage_number_is_valid(
_stage_number_intermediate_pressure: int,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
DATE, rate
2022-01-01, 0
2024-01-01, 0
2025-01-01, 0
2026-01-01, 4000000
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
RATE,FUEL,POWER
0,0,0
1000000,10000,1.0
2000000,11000,2.0
3000000,12000,3.0
4000000,13000,4.0

Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
START: 2022-01-01
END: 2026-01-01

FUEL_TYPES:
- NAME: fuel_gas
PRICE: 1.5 # NOK/Sm3
CATEGORY: FUEL-GAS
EMISSIONS:
- NAME: co2
FACTOR: "2.20" #kg/Sm3
TAX: 1.51 # NOK/Sm3

FACILITY_INPUTS:
- NAME: compressor_sampled_1d
FILE: compressor_sampled_1d.csv
TYPE: COMPRESSOR_TABULAR

TIME_SERIES:
- NAME: compressor1
TYPE: DEFAULT
FILE: 'compressor1.csv'

VARIABLES:
compressor1:
VALUE: "compressor1;rate"

MODELS:
- NAME: medium_gas
TYPE: FLUID
FLUID_MODEL_TYPE: PREDEFINED
EOS_MODEL: SRK
GAS_TYPE: MEDIUM
- NAME: rich_gas
TYPE: FLUID
FLUID_MODEL_TYPE: PREDEFINED
EOS_MODEL: SRK
GAS_TYPE: RICH
- NAME: predefined_compressor_chart_curves_from_file
TYPE: COMPRESSOR_CHART
CHART_TYPE: VARIABLE_SPEED
UNITS:
RATE: AM3_PER_HOUR
HEAD: M # M or KJ_PER_KG
EFFICIENCY: FRACTION
CURVES:
FILE: einput/predefined_compressor_chart_curves.csv
- NAME: advanced_variable_speed_compressor_train
TYPE: VARIABLE_SPEED_COMPRESSOR_TRAIN_MULTIPLE_STREAMS_AND_PRESSURES
STREAMS: # TODO: Not possible to define other streams than crossover (at least ingoing) as we don't allow several rates in system per consumer
- NAME: in_stream_stage_1
TYPE: INGOING
FLUID_MODEL: rich_gas
- NAME: in_stream_crossover_from_2
TYPE: INGOING
FLUID_MODEL: medium_gas
- NAME: in_stream_crossover_from_3
TYPE: INGOING
FLUID_MODEL: medium_gas # TODO: Requiring fluid model for crossover streams does not make sense here, should be part of the stream definition in compressor 3 or optional. Use a simplified mix if not provided maybe?
STAGES:
- INLET_TEMPERATURE: 30 # TODO: INLET_TEMPERATURE should be part of the stream definition also, riiight?
COMPRESSOR_CHART: predefined_compressor_chart_curves_from_file
STREAM:
- in_stream_stage_1
- in_stream_crossover_from_2
- INLET_TEMPERATURE: 30
COMPRESSOR_CHART: predefined_compressor_chart_curves_from_file
STREAM:
- in_stream_crossover_from_3
- INLET_TEMPERATURE: 30
COMPRESSOR_CHART: predefined_compressor_chart_curves_from_file
- INLET_TEMPERATURE: 30
COMPRESSOR_CHART: predefined_compressor_chart_curves_from_file
PRESSURE_CONTROL: INDIVIDUAL_ASV_RATE
POWER_ADJUSTMENT_CONSTANT: 1
- NAME: turbine
TYPE: TURBINE
LOWER_HEATING_VALUE: 38 # MJ/Sm3
TURBINE_LOADS: [ 0, 2.352, 4.589, 6.853, 9.125, 11.399, 13.673, 15.947, 18.223, 20.496, 22.767 ] # MW
TURBINE_EFFICIENCIES: [ 0, 0.138, 0.210, 0.255, 0.286, 0.310, 0.328, 0.342, 0.353, 0.360, 0.362 ]
POWER_ADJUSTMENT_CONSTANT: 1
- NAME: compressor_with_turbine
TYPE: COMPRESSOR_WITH_TURBINE
COMPRESSOR_MODEL: advanced_variable_speed_compressor_train
TURBINE_MODEL: turbine


INSTALLATIONS:
- NAME: installation
HCEXPORT: 17
FUEL: fuel_gas
CATEGORY: FIXED
FUELCONSUMERS:
- NAME: compressor_system_v2
CATEGORY: COMPRESSOR
TYPE: COMPRESSOR_SYSTEM@v2
CONSUMERS:
- NAME: compressor1
ENERGY_USAGE_MODEL: compressor_with_turbine
- NAME: compressor2
ENERGY_USAGE_MODEL: compressor_sampled_1d
- NAME: compressor3
ENERGY_USAGE_MODEL: compressor_sampled_1d
COMPONENT_CONDITIONS:
CROSSOVER:
- NAME: in_stream_crossover_1
FROM: compressor2
TO: compressor1
- NAME: in_stream_crossover_from_3
FROM: compressor3
TO: compressor1
OPERATIONAL_SETTINGS:
- RATES: [ 1000000, 6000000, 7000000 ]
INLET_PRESSURE: 50
OUTLET_PRESSURE: 250
- RATES: [ "$var.compressor1", 6000000, 7000000 ]
INLET_PRESSURE: 50
OUTLET_PRESSURE: 125
- RATES: [ 1000000, 6000000, 7000000 ]
INLET_PRESSURE: 50
OUTLET_PRESSURE: 125
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
SPEED,RATE,HEAD,EFFICIENCY
7689,2900.0666,8412.9156,0.723
7689,3503.8068,7996.2541,0.7469
7689,4002.5554,7363.8161,0.7449
7689,4595.0148,6127.1702,0.7015
8787,3305.5723,10950.9557,0.7241
8787,4000.1546,10393.3867,0.7449
8787,4499.2342,9707.491,0.7464
8787,4996.8728,8593.8586,0.722
8787,5241.9892,7974.6002,0.7007
9886,3708.8713,13845.3808,0.723
9886,4502.2531,13182.6922,0.7473
9886,4993.5959,12425.3699,0.748
9886,5507.8114,11276.3984,0.7306
9886,5924.3308,10054.3539,0.704
10435,3928.0389,15435.484,0.7232
10435,4507.4654,14982.7351,0.7437
10435,5002.1249,14350.2222,0.7453
10435,5498.9912,13361.3245,0.7414
10435,6248.5937,11183.0276,0.701
10984,4138.6974,17078.8952,0.7226
10984,5002.4758,16274.9249,0.7462
10984,5494.3704,15428.5063,0.7468
10984,6008.6962,14261.7156,0.7349
10984,6560.148,12382.7538,0.7023
11533,4327.9175,18882.3055,0.7254
11533,4998.517,18235.1912,0.7444
11533,5505.8851,17531.6259,0.745
11533,6027.6167,16489.7195,0.7466
11533,6506.9064,15037.1474,0.7266
11533,6908.2832,13618.7919,0.7019
10767,4052.9057,16447,0.724
10767,4500.6637,16081,0.738
10767,4999.41,15546,0.7479
10767,5492.822,14640,0.74766
10767,6000.6263,13454,0.7298
10767,6439.4876,11973,0.7014
Loading

0 comments on commit 419c2e9

Please sign in to comment.