Skip to content

Commit

Permalink
chore: warn user about full recirculation of fluids in a compressor s…
Browse files Browse the repository at this point in the history
…tage in a multiple streams and pressures compressor train (#196)

chore: add NO_FLOW ChartAreaFlag

chore: add chart area flag to test of full recirculation
  • Loading branch information
olelod authored Oct 10, 2023
1 parent 445fc9d commit 0c45251
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 15 deletions.
3 changes: 3 additions & 0 deletions docs/docs/changelog/next.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ sidebar_position: 1

## New Features

- Added chart area flag NO_FLOW_RATE to the possible statuses for an operational point in a variable speed compressor chart. The chart area flags can currently only be found in the json result file, but we will also try to find a way of displaying this information in the WebApp as well.
- Whenever there is a variable speed compressor only recirculation fluid (can happen in a multiple streams and pressures compressor train) a warning will be logged.


## Fixes

Expand Down
19 changes: 13 additions & 6 deletions src/libecalc/core/models/compressor/results.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,15 +290,22 @@ def set_failure_status(cls, v, values):

@property
def chart_area_status(self) -> ChartAreaFlag:
chart_area_failure = [
stage.chart_area_flag
for stage in self.stage_results
if stage.chart_area_flag != ChartAreaFlag.INTERNAL_POINT
]
"""Checks where the operational points are placed in relation to the compressor charts in a compressor train.
Returns:
A chart area flag describing the placement of the operational points in the compressor train.
If several of the compressors in the compressor train is out of capacity, only the first failure will
be returned.
"""
chart_area_failure = [stage.chart_area_flag for stage in self.stage_results if not stage.point_is_valid]
if len(chart_area_failure) > 0:
return chart_area_failure[0]
else:
return [stage.chart_area_flag for stage in self.stage_results][0]
chart_area_flag = [stage.chart_area_flag for stage in self.stage_results if stage.point_is_valid]
if ChartAreaFlag.NO_FLOW_RATE in chart_area_flag:
return ChartAreaFlag.NO_FLOW_RATE
else:
return chart_area_flag[0]

@property
def is_valid(self) -> bool:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,10 +292,18 @@ def _evaluate_point_validity_chart_area_flag_and_adjusted_speed_and_rate(
further out in iterations to meet pressure targets, and one need to get information about if the point
is valid (within capacity) or not.
:param speed: [rpm]
:param increase_speed_below_assuming_choke: True or False
:param rate: [Am3/h]
:param increase_rate_left_of_minimum_flow_assuming_asv: True or False
Args:
speed: the speed related to the operation point [rpm]
increase_speed_below_assuming_choke: boolean telling whether the speed related to an operation point should
be changed to the minimum speed if the speed is below the minimum speed (assumes up/down-stream choking)
rate: the actual inlet flow rate of the operation point [Am3/h]
recirculated_rate: potential additional flow rate introduced by the anti-surge valve for pressure control
increase_rate_left_of_minimum_flow_assuming_asv: boolean telling whether the actual flow rate should be
automatically changed to the minimum flow rate for the compressor chart when below the minimum flow rate
Returns:
A tuple of values describing if the operation point is valid, information about where the operation
point is placed relative to the compressor chart, and the (potentially updated) values for speed and rate
"""
point_is_valid = True
chart_area_flag = ChartAreaFlag.INTERNAL_POINT
Expand All @@ -317,16 +325,21 @@ def _evaluate_point_validity_chart_area_flag_and_adjusted_speed_and_rate(
# Todo: Need to QA this logic. Below minimum speed requires speed < minimum_speed, but this is not enforced?
minimum_flow_rate_for_speed = self.minimum_rate_as_function_of_speed(speed_to_use)
maximum_flow_rate_for_speed = self.maximum_rate_as_function_of_speed(speed_to_use)
if rate < minimum_flow_rate_for_speed:
# first update rate_to_use when below minimum flow if increase_rate_left_of_minimum_flow_assuming_asv
if rate_to_use < minimum_flow_rate_for_speed:
if increase_rate_left_of_minimum_flow_assuming_asv:
rate_to_use = minimum_flow_rate_for_speed
else:
point_is_valid = False
# second, decide ChartAreaFlag based on the original rate input
if rate == 0:
chart_area_flag = ChartAreaFlag.NO_FLOW_RATE
elif rate < minimum_flow_rate_for_speed:
chart_area_flag = (
ChartAreaFlag.BELOW_MINIMUM_SPEED_AND_BELOW_MINIMUM_FLOW_RATE
if speed_is_increased
else ChartAreaFlag.BELOW_MINIMUM_FLOW_RATE
)
if increase_rate_left_of_minimum_flow_assuming_asv:
rate_to_use = max(minimum_flow_rate_for_speed, rate_to_use)
else:
point_is_valid = False
elif rate > maximum_flow_rate_for_speed:
chart_area_flag = (
ChartAreaFlag.BELOW_MINIMUM_SPEED_AND_ABOVE_MAXIMUM_FLOW_RATE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,11 @@ def calculate_compressor_train_given_rate_ps_speed(
stage_number=stage_number
)
if fluid_to_recirculate:
logger.warning(
f"For stage number {stage_number}, there is no fluid entering the stage at at this time step. "
f"The compressor is only recirculating fluid. Standard rates are "
f"{std_rates_std_m3_per_day_per_stream}."
)
inlet_stream = fluid_to_recirculate
else:
raise ValueError(
Expand Down
1 change: 1 addition & 0 deletions src/libecalc/dto/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,4 @@ class ChartAreaFlag(str, Enum):
BELOW_MINIMUM_SPEED_AND_BELOW_MINIMUM_FLOW_RATE = "BELOW_MINIMUM_SPEED_AND_BELOW_MINIMUM_FLOW_RATE"
BELOW_MINIMUM_SPEED_AND_ABOVE_MAXIMUM_FLOW_RATE = "BELOW_MINIMUM_SPEED_AND_ABOVE_MAXIMUM_FLOW_RATE"
NOT_CALCULATED = "NOT_CALCULATED"
NO_FLOW_RATE = "NO_FLOW_RATE"
Original file line number Diff line number Diff line change
Expand Up @@ -707,3 +707,11 @@ def test_recirculate_mixing_streams_with_zero_mass_rate(
assert result.recirculation_loss[2] < result.recirculation_loss[3]
assert result.recirculation_loss[4] < result.recirculation_loss[5]
assert result.power[0] < result.power[2] < result.power[4] # more and more of the heavy fluid
assert result.stage_results[1].chart_area_flags == [
ChartAreaFlag.BELOW_MINIMUM_FLOW_RATE.value,
ChartAreaFlag.NO_FLOW_RATE.value,
ChartAreaFlag.BELOW_MINIMUM_FLOW_RATE.value,
ChartAreaFlag.NO_FLOW_RATE.value,
ChartAreaFlag.BELOW_MINIMUM_FLOW_RATE.value,
ChartAreaFlag.NO_FLOW_RATE.value,
]

0 comments on commit 0c45251

Please sign in to comment.