Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow cross overs both in and out of the same compressor train … #709

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ def calculate_operational_settings_after_cross_over(
f" {type(energy_usage_model).__name__} has not been implemented."
f" This should not happen. Please contact eCalc support."
)
transfer_rate = requested_rates[consumer_index] - consumer_maximum_rate
transfer_rate = rates_after_cross_over[consumer_index] - consumer_maximum_rate
# Only transfer when max rate is exceeded
transfer_rate = np.where(transfer_rate > 0, transfer_rate, 0)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,23 +50,23 @@ INSTALLATIONS:
TYPE: PUMP_SYSTEM
CONDITION: true
PUMPS:
- NAME: pump1
CHART: pump_single_speed
- NAME: pump2
CHART: pump_single_speed
- NAME: pump3
CHART: pump_single_speed
- NAME: pump1
CHART: pump_single_speed
FLUID_DENSITY: 2
POWERLOSSFACTOR: 0.0
OPERATIONAL_SETTINGS:
- RATES: [ 4000000, 5000000, 6000000 ]
- RATES: [ 5000000, 6000000, 4000000 ]
SUCTION_PRESSURES: [ 50, 50, 50 ]
DISCHARGE_PRESSURES: [ 250, 250, 250 ]
CROSSOVER: [ 0, 1, 1 ]
- RATES: [ 2000000, 2500000, 3000000 ]
CROSSOVER: [ 3, 3, 0 ]
- RATES: [ 2500000, 3000000, 2000000 ]
SUCTION_PRESSURES: [ 50, 50, 50 ]
DISCHARGE_PRESSURES: [ 125, 125, 125 ]
CROSSOVER: [ 0, 1, 1 ]
CROSSOVER: [ 3, 3, 0 ]
- NAME: pump_system_v2
CATEGORY: PUMP
TYPE: CONSUMER_SYSTEM@v2
Expand Down Expand Up @@ -161,25 +161,25 @@ INSTALLATIONS:
ENERGY_USAGE_MODEL:
TYPE: COMPRESSOR_SYSTEM
COMPRESSORS:
- NAME: compressor1
COMPRESSOR_MODEL: compressor_sampled_1d
- NAME: compressor2
COMPRESSOR_MODEL: compressor_sampled_1d
- NAME: compressor3
COMPRESSOR_MODEL: compressor_sampled_1d
- NAME: compressor1
COMPRESSOR_MODEL: compressor_sampled_1d
OPERATIONAL_SETTINGS:
- RATES: [ 1000000, 6000000, 6000000 ]
- RATES: [ 6000000, 6000000, 1000000 ]
SUCTION_PRESSURES: [ 50, 50, 50 ]
DISCHARGE_PRESSURES: [ 250, 250, 250 ]
CROSSOVER: [ 0, 1, 1 ]
- RATES: [ "$var.compressor1", 5000000, 5000000 ]
CROSSOVER: [ 3, 3, 0 ]
- RATES: [ 5000000, 5000000, "$var.compressor1" ]
SUCTION_PRESSURES: [ 50, 50, 50 ]
DISCHARGE_PRESSURES: [ 125, 125, 125 ]
CROSSOVER: [ 0, 1, 1 ]
- RATES: [ 1000000, 5000000, 5000000 ]
CROSSOVER: [ 3, 3, 0 ]
- RATES: [ 5000000, 5000000, 1000000 ]
SUCTION_PRESSURES: [ 50, 50, 50 ]
DISCHARGE_PRESSURES: [ 125, 125, 125 ]
CROSSOVER: [ 0, 1, 1 ]
CROSSOVER: [ 3, 3, 0 ]
- NAME: compressor_system_v2
CATEGORY: COMPRESSOR
TYPE: CONSUMER_SYSTEM@v2
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Literal

from pydantic import Field
from pydantic import Field, model_validator

from libecalc.presentation.yaml.yaml_types import YamlBase
from libecalc.presentation.yaml.yaml_types.components.legacy.energy_usage_model.common import (
Expand Down Expand Up @@ -65,6 +65,36 @@ class YamlCompressorSystemOperationalSetting(YamlBase):
description="Set suction pressure equal for all consumers in a consumer system operational setting. \n\n$ECALC_DOCS_KEYWORDS_URL/SUCTION_PRESSURE",
)

@model_validator(mode="after")
def ensure_increasing_cross_over(self):
if self.crossover is None:
return self
for compressor_train_index, crossover_to in enumerate(self.crossover):
crossover_to_compressor_train_index = (
crossover_to - 1
) # compressor_train_index is 0-indexed, crossover_to is 1-indexed
no_crossover = crossover_to == 0
if crossover_to_compressor_train_index > compressor_train_index or no_crossover:
pass # passing excess rate to a comp. train not yet evaluated or no crossover defined for this comp. train
else:
raise ValueError(
f"Crossover: {self.crossover}\n"
"The compressor trains in the compressor system are not defined in the correct order, according to "
"the way the crossovers are set up. eCalc can now try to pass excess rates to compressor trains in "
"the system that has already been evaluated. \n\n"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this correct? Or should it be not evaluated?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way it works now if you have crossover: [0, 1, 0], you first evaluate the first consumer (here it has no crossover). The next consumers can pass excess rate to the first one, potentially exceeding the maximum rate there, and the operational setting will be chosen even if it is invalid.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sentence eCalc can now try to pass excess rates to compressor trains the system that has already been evaluated confused me. Is the intention to inform the user why the current crossover setting isn't allowed? So If we were to allow this crossover setup, eCalc™ could try to pass excess rates to compressor trains in the system that has already been evaluated?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Poorly phrased, I guess... Yes, that was happening in one model. The first train is within capacity, the second one outside capacity, so rate was passed to the first one (which then with the additional rate was outside capacity).

"To avoid loops and to avoid passing rates to compressor trains that have already been "
"processed, the index of the crossovers should be either 0 (no crossover) or larger than the index "
"of the current compressor train (passing excess rate to a compressor train not yet evaluated). \n\n"
"CROSSOVER: [2, 3, 0] is valid, but CROSSOVER: [2, 1, 0] is not. \n"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

v2 does the sorting for the user, just sayin'

)

return self

def train_not_evaluated(self, index: int):
if self.crossover is None:
return False
return self.crossover[index] == 0


class YamlPumpSystemOperationalSettings(YamlCompressorSystemOperationalSetting):
fluid_densities: list[YamlExpressionType] = Field(
Expand Down
Loading