Skip to content

Commit

Permalink
chore: move evaluation of conditions before calculations (#24)
Browse files Browse the repository at this point in the history
chore: add consumer function utils
chore: move conditions for direct consumer function
chore: move conditions for compressor consumer function
chore: move conditions in pump consumer function
chore: remove energy_usage_before_conditioning from results
chore: remove energy usage before conditioning from tests
chore: move conditioning for consumer system consumer function
chore: add testing of condition in consumer system consumer function
chore: conditions in tabular consumer function
  • Loading branch information
olelod committed May 24, 2023
1 parent a7b22e2 commit 50e2d66
Show file tree
Hide file tree
Showing 11 changed files with 260 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
ConsumerFunctionResult,
)
from libecalc.core.consumers.legacy_consumer.consumer_function.utils import (
calculate_energy_usage_with_conditions_and_power_loss,
apply_condition,
apply_power_loss_factor,
get_condition_from_expression,
get_power_loss_factor_from_expression,
)
from libecalc.core.models.compressor.base import CompressorModel
from libecalc.core.models.compressor.train.variable_speed_compressor_train_common_shaft_multiple_streams_and_pressures import (
Expand Down Expand Up @@ -107,42 +110,55 @@ def evaluate(
if self._discharge_pressure_expression is not None
else None
)

# Do conditioning first - set rates to zero if conditions are not met
condition = get_condition_from_expression(
variables_map=variables_map,
condition_expression=self._condition_expression,
)
stream_day_rate_after_condition = apply_condition(
input_array=stream_day_rate,
condition=condition,
)

compressor_train_result: CompressorTrainResult
# Do not input regularity to compressor function. Handled outside
# intermediate_pressure will only be different from None when we have a MultipleStreamsAndPressures train
if intermediate_pressure is not None:
compressor_train_result = self._compressor_function.evaluate_rate_ps_pint_pd(
rate=stream_day_rate,
rate=stream_day_rate_after_condition,
suction_pressure=suction_pressure,
discharge_pressure=discharge_pressure,
intermediate_pressure=intermediate_pressure,
)
else:
compressor_train_result = self._compressor_function.evaluate_rate_ps_pd(
rate=stream_day_rate,
rate=stream_day_rate_after_condition,
suction_pressure=suction_pressure,
discharge_pressure=discharge_pressure,
)

conditions_and_power_loss_results = calculate_energy_usage_with_conditions_and_power_loss(
power_loss_factor = get_power_loss_factor_from_expression(
variables_map=variables_map,
energy_usage=np.asarray(compressor_train_result.energy_usage),
condition_expression=self._condition_expression,
power_loss_factor_expression=self._power_loss_factor_expression,
power_usage=np.asarray(compressor_train_result.power)
if compressor_train_result.power is not None
else None,
)

consumer_function_result = ConsumerFunctionResult(
time_vector=np.array(variables_map.time_vector),
is_valid=np.asarray(compressor_train_result.is_valid),
energy_function_result=compressor_train_result,
energy_usage_before_conditioning=np.asarray(compressor_train_result.energy_usage),
condition=conditions_and_power_loss_results.condition,
energy_usage_before_power_loss_factor=conditions_and_power_loss_results.energy_usage_after_condition_before_power_loss_factor,
power_loss_factor=conditions_and_power_loss_results.power_loss_factor,
energy_usage=conditions_and_power_loss_results.resulting_energy_usage,
power=conditions_and_power_loss_results.resulting_power_usage,
condition=condition,
energy_usage_before_power_loss_factor=np.asarray(compressor_train_result.energy_usage),
power_loss_factor=power_loss_factor,
energy_usage=apply_power_loss_factor(
energy_usage=np.asarray(compressor_train_result.energy_usage),
power_loss_factor=power_loss_factor,
),
power=apply_power_loss_factor(
energy_usage=np.asarray(compressor_train_result.power),
power_loss_factor=power_loss_factor,
)
if compressor_train_result.power is not None
else None,
)
return consumer_function_result
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
ConsumerFunctionResult,
)
from libecalc.core.consumers.legacy_consumer.consumer_function.utils import (
calculate_energy_usage_with_conditions_and_power_loss,
apply_condition,
apply_power_loss_factor,
get_condition_from_expression,
get_power_loss_factor_from_expression,
)
from libecalc.core.models.tabulated import (
ConsumerTabularEnergyFunction,
Expand Down Expand Up @@ -65,23 +68,44 @@ def evaluate(
variables=list(variables_for_calculation.values()),
)

conditions_and_power_loss_results = calculate_energy_usage_with_conditions_and_power_loss(
variables_map=variables_map,
energy_usage=np.asarray(energy_function_result.energy_usage),
condition = get_condition_from_expression(
condition_expression=self._condition_expression,
variables_map=variables_map,
)
# for tabular, is_valid is based on energy_usage being NaN. This will also (correctly) change potential
# invalid points to valid where the condition sets energy_usage to zero
energy_function_result.energy_usage = list(
apply_condition(
input_array=np.asarray(energy_function_result.energy_usage),
condition=condition,
)
)
energy_function_result.power = (
list(
apply_condition(
input_array=np.asarray(energy_function_result.power),
condition=condition,
)
)
if energy_function_result.power is not None
else None
)

power_loss_factor = get_power_loss_factor_from_expression(
variables_map=variables_map,
power_loss_factor_expression=self._power_loss_factor_expression,
)

tabulated_consumer_function_result = ConsumerFunctionResult(
return ConsumerFunctionResult(
time_vector=np.array(variables_map.time_vector),
is_valid=np.asarray(energy_function_result.is_valid),
energy_function_result=energy_function_result,
energy_usage_before_conditioning=np.asarray(energy_function_result.energy_usage),
condition=conditions_and_power_loss_results.condition,
energy_usage_before_power_loss_factor=conditions_and_power_loss_results.energy_usage_after_condition_before_power_loss_factor,
condition=condition,
energy_usage_before_power_loss_factor=np.asarray(energy_function_result.energy_usage),
# noqa
power_loss_factor=conditions_and_power_loss_results.power_loss_factor,
energy_usage=conditions_and_power_loss_results.resulting_energy_usage,
power_loss_factor=power_loss_factor,
energy_usage=apply_power_loss_factor(
energy_usage=np.asarray(energy_function_result.energy_usage),
power_loss_factor=power_loss_factor,
),
)

return tabulated_consumer_function_result
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from copy import deepcopy
from typing import List, Optional

import numpy as np
Expand All @@ -10,7 +9,10 @@
ConsumerFunctionResult,
)
from libecalc.core.consumers.legacy_consumer.consumer_function.utils import (
calculate_energy_usage_with_conditions_and_power_loss,
apply_condition,
apply_power_loss_factor,
get_condition_from_expression,
get_power_loss_factor_from_expression,
)
from libecalc.core.models.results import EnergyFunctionGenericResult
from libecalc.dto.types import RateType
Expand Down Expand Up @@ -69,13 +71,20 @@ def evaluate(
variables=variables_map.variables, fill_length=len(variables_map.time_vector)
)

energy_usage = (
Rates.to_stream_day(
# Do conditioning first - set rates to zero if conditions are not met
condition = get_condition_from_expression(
variables_map=variables_map,
condition_expression=self._condition_expression,
)

energy_usage = apply_condition(
input_array=Rates.to_stream_day(
calendar_day_rates=energy_usage_expression_evaluated,
regularity=regularity,
)
if self._convert_to_stream_day
else energy_usage_expression_evaluated
else energy_usage_expression_evaluated,
condition=condition,
)

energy_function_result = EnergyFunctionGenericResult(
Expand All @@ -85,22 +94,22 @@ def evaluate(
power_unit=self.power_unit if self.is_electrical_consumer else None,
)

conditions_and_power_loss_results = calculate_energy_usage_with_conditions_and_power_loss(
power_loss_factor = get_power_loss_factor_from_expression(
variables_map=variables_map,
energy_usage=deepcopy(energy_usage),
condition_expression=self._condition_expression,
power_loss_factor_expression=self._power_loss_factor_expression,
)

consumer_function_result = ConsumerFunctionResult(
time_vector=np.array(variables_map.time_vector),
is_valid=np.asarray(energy_function_result.is_valid),
energy_function_result=energy_function_result,
energy_usage_before_conditioning=deepcopy(energy_usage),
condition=conditions_and_power_loss_results.condition,
energy_usage_before_power_loss_factor=conditions_and_power_loss_results.energy_usage_after_condition_before_power_loss_factor,
power_loss_factor=conditions_and_power_loss_results.power_loss_factor,
energy_usage=conditions_and_power_loss_results.resulting_energy_usage,
condition=condition,
energy_usage_before_power_loss_factor=np.asarray(energy_function_result.energy_usage),
power_loss_factor=power_loss_factor,
energy_usage=apply_power_loss_factor(
energy_usage=np.asarray(energy_function_result.energy_usage),
power_loss_factor=power_loss_factor,
),
)

return consumer_function_result
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,31 @@
ConsumerFunctionResult,
)
from libecalc.core.consumers.legacy_consumer.consumer_function.utils import (
calculate_energy_usage_with_conditions_and_power_loss,
apply_condition,
apply_power_loss_factor,
get_condition_from_expression,
get_power_loss_factor_from_expression,
)
from libecalc.core.models.pump import PumpModel
from libecalc.dto import VariablesMap
from libecalc.expression import Expression


class PumpConsumerFunction(ConsumerFunction):
"""
The pump consumer function defining the energy usage.
Args:
pump_function: The pump model
rate_expression: Rate expression [Sm3/h]
suction_pressure_expression: Suction pressure expression [bara]
discharge_pressure_expression: Discharge pressure expression [bara]
fluid_density_expression: Fluid density expression [kg/m3]
condition_expression: Optional condition expression
power_loss_factor_expression: Optional power loss factor expression.
Typically used for power line loss subsea et.c.
"""

def __init__(
self,
pump_function: Union[PumpModel],
Expand All @@ -40,13 +57,29 @@ def evaluate(
variables_map: VariablesMap,
regularity: List[float],
) -> ConsumerFunctionResult:
"""Evaluate the pump consumer function
Args:
variables_map: Variables map is the VariablesMap-object holding all the data to be evaluated.
regularity: The regularity of the pump consumer function (same as for installation pump is part of)
Returns:
Pump consumer function result
"""
condition = get_condition_from_expression(
variables_map=variables_map,
condition_expression=self._condition_expression,
)
calendar_day_rate = self._rate_expression.evaluate(
variables=variables_map.variables, fill_length=len(variables_map.time_vector)
)
# if regularity is 0 for a calendar day rate, set stream day rate to 0 for that step
stream_day_rate = Rates.to_stream_day(
calendar_day_rates=calendar_day_rate,
regularity=regularity,
stream_day_rate = apply_condition(
input_array=Rates.to_stream_day(
calendar_day_rates=calendar_day_rate,
regularity=regularity,
),
condition=condition,
)
suction_pressure = self._suction_pressure_expression.evaluate(
variables=variables_map.variables, fill_length=len(variables_map.time_vector)
Expand All @@ -66,20 +99,21 @@ def evaluate(
fluid_density=fluid_density,
)

conditions_and_power_loss_results = calculate_energy_usage_with_conditions_and_power_loss(
power_loss_factor = get_power_loss_factor_from_expression(
variables_map=variables_map,
energy_usage=np.asarray(energy_function_result.energy_usage),
condition_expression=self._condition_expression,
power_loss_factor_expression=self._power_loss_factor_expression,
)

pump_consumer_function_result = ConsumerFunctionResult(
time_vector=np.array(variables_map.time_vector),
is_valid=np.asarray(energy_function_result.is_valid),
energy_function_result=energy_function_result,
energy_usage_before_conditioning=np.asarray(energy_function_result.energy_usage),
condition=conditions_and_power_loss_results.condition,
energy_usage_before_power_loss_factor=conditions_and_power_loss_results.energy_usage_after_condition_before_power_loss_factor,
power_loss_factor=conditions_and_power_loss_results.power_loss_factor,
energy_usage=conditions_and_power_loss_results.resulting_energy_usage,
energy_usage_before_power_loss_factor=np.asarray(energy_function_result.energy_usage),
condition=condition,
power_loss_factor=power_loss_factor,
energy_usage=apply_power_loss_factor(
energy_usage=np.asarray(energy_function_result.energy_usage),
power_loss_factor=power_loss_factor,
),
)
return pump_consumer_function_result
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ class ConsumerFunctionResultBase(BaseModel):
time_vector: np.ndarray
is_valid: np.ndarray
energy_usage: np.ndarray
energy_usage_before_conditioning: Optional[np.ndarray]
energy_usage_before_power_loss_factor: Optional[np.ndarray]
condition: Optional[np.ndarray]
power_loss_factor: Optional[np.ndarray]
Expand All @@ -54,6 +53,7 @@ class ConsumerFunctionResult(ConsumerFunctionResultBase):
typ: Literal[ConsumerFunctionType.SINGLE] = ConsumerFunctionType.SINGLE # type: ignore[valid-type]

def extend(self, other) -> ConsumerFunctionResult:
"""This is used when merging different time slots when the energy function of a consumer changes over time."""
if not isinstance(self, type(other)):
msg = f"{self.__repr_name__()} Mixing CONSUMER_SYSTEM with non-CONSUMER_SYSTEM is no longer supported."
logger.warning(msg)
Expand Down Expand Up @@ -88,4 +88,5 @@ def extend(self, other) -> ConsumerFunctionResult:

@classmethod
def create_empty(cls) -> ConsumerFunctionResult:
"""Create empty consumer function result"""
return cls(time_vector=np.array([]), is_valid=np.array([]), energy_usage=np.array([]))
Loading

0 comments on commit 50e2d66

Please sign in to comment.