diff --git a/src/libecalc/core/consumers/legacy_consumer/system/consumer_function.py b/src/libecalc/core/consumers/legacy_consumer/system/consumer_function.py index 5963bab35d..41f756099f 100644 --- a/src/libecalc/core/consumers/legacy_consumer/system/consumer_function.py +++ b/src/libecalc/core/consumers/legacy_consumer/system/consumer_function.py @@ -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) diff --git a/src/libecalc/fixtures/cases/consumer_system_v2/data/consumer_system_v2.yaml b/src/libecalc/fixtures/cases/consumer_system_v2/data/consumer_system_v2.yaml index bdbe578d20..8a755ff3a5 100644 --- a/src/libecalc/fixtures/cases/consumer_system_v2/data/consumer_system_v2.yaml +++ b/src/libecalc/fixtures/cases/consumer_system_v2/data/consumer_system_v2.yaml @@ -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 @@ -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 diff --git a/src/libecalc/presentation/yaml/yaml_types/components/legacy/energy_usage_model/yaml_energy_usage_model_consumer_system.py b/src/libecalc/presentation/yaml/yaml_types/components/legacy/energy_usage_model/yaml_energy_usage_model_consumer_system.py index 6503cfe98a..7efa8ce76f 100644 --- a/src/libecalc/presentation/yaml/yaml_types/components/legacy/energy_usage_model/yaml_energy_usage_model_consumer_system.py +++ b/src/libecalc/presentation/yaml/yaml_types/components/legacy/energy_usage_model/yaml_energy_usage_model_consumer_system.py @@ -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 ( @@ -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" + "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" + ) + + 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( diff --git a/tests/libecalc/integration/snapshots/test_consumer_system_v2/test_compressor_system_v2_results/consumer_system_v2-consumer_system_v2_yaml/consumer_system_v2.json b/tests/libecalc/integration/snapshots/test_consumer_system_v2/test_compressor_system_v2_results/consumer_system_v2-consumer_system_v2_yaml/consumer_system_v2.json index 02b7c6aeb5..8960a86318 100644 --- a/tests/libecalc/integration/snapshots/test_consumer_system_v2/test_compressor_system_v2_results/consumer_system_v2-consumer_system_v2_yaml/consumer_system_v2.json +++ b/tests/libecalc/integration/snapshots/test_consumer_system_v2/test_compressor_system_v2_results/consumer_system_v2-consumer_system_v2_yaml/consumer_system_v2.json @@ -1460,10 +1460,10 @@ }, "unit": "Sm3/d", "values": [ - NaN, - NaN, - NaN, - NaN + 13000.0, + 13000.0, + 13000.0, + 13000.0 ] }, "failure_status": [ @@ -1551,14 +1551,14 @@ }, "unit": "N/A", "values": [ - false, - false, - false, - false + true, + true, + true, + true ] }, "max_standard_rate": null, - "name": "compressor1", + "name": "compressor2", "outlet_stream_condition": { "actual_rate_before_asv_m3_per_hr": [ NaN, @@ -1658,17 +1658,17 @@ }, "unit": "MW", "values": [ - NaN, - NaN, - NaN, - NaN + 4.0, + 4.0, + 4.0, + 4.0 ] }, "rate_sm3_day": [ - 5000000.0, - 5000000.0, - 5000000.0, - 5000000.0 + 4000000.0, + 4000000.0, + 4000000.0, + 4000000.0 ], "stage_results": [ { @@ -1686,10 +1686,10 @@ "NOT_CALCULATED" ], "energy_usage": [ - NaN, - NaN, - NaN, - NaN + 13000.0, + 13000.0, + 13000.0, + 13000.0 ], "energy_usage_unit": "Sm3/d", "fluid_composition": {}, @@ -1756,10 +1756,10 @@ ] }, "is_valid": [ - false, - false, - false, - false + true, + true, + true, + true ], "mass_rate_before_asv_kg_per_hr": [ NaN, @@ -1854,10 +1854,10 @@ NaN ], "power": [ - NaN, - NaN, - NaN, - NaN + 4.0, + 4.0, + 4.0, + 4.0 ], "power_unit": "MW", "pressure_is_choked": [ @@ -2010,7 +2010,7 @@ ] }, "max_standard_rate": null, - "name": "compressor2", + "name": "compressor3", "outlet_stream_condition": { "actual_rate_before_asv_m3_per_hr": [ NaN, @@ -2364,10 +2364,10 @@ }, "unit": "Sm3/d", "values": [ - 13000.0, - 13000.0, - 13000.0, - 13000.0 + NaN, + NaN, + NaN, + NaN ] }, "failure_status": [ @@ -2455,14 +2455,14 @@ }, "unit": "N/A", "values": [ - true, - true, - true, - true + false, + false, + false, + false ] }, "max_standard_rate": null, - "name": "compressor3", + "name": "compressor1", "outlet_stream_condition": { "actual_rate_before_asv_m3_per_hr": [ NaN, @@ -2562,17 +2562,17 @@ }, "unit": "MW", "values": [ - 4.0, - 4.0, - 4.0, - 4.0 + NaN, + NaN, + NaN, + NaN ] }, "rate_sm3_day": [ - 4000000.0, - 4000000.0, - 4000000.0, - 4000000.0 + 5000000.0, + 5000000.0, + 5000000.0, + 5000000.0 ], "stage_results": [ { @@ -2590,10 +2590,10 @@ "NOT_CALCULATED" ], "energy_usage": [ - 13000.0, - 13000.0, - 13000.0, - 13000.0 + NaN, + NaN, + NaN, + NaN ], "energy_usage_unit": "Sm3/d", "fluid_composition": {}, @@ -2660,10 +2660,10 @@ ] }, "is_valid": [ - true, - true, - true, - true + false, + false, + false, + false ], "mass_rate_before_asv_kg_per_hr": [ NaN, @@ -2758,10 +2758,10 @@ NaN ], "power": [ - 4.0, - 4.0, - 4.0, - 4.0 + NaN, + NaN, + NaN, + NaN ], "power_unit": "MW", "pressure_is_choked": [ @@ -2818,10 +2818,10 @@ }, "unit": "Sm3/d", "values": [ - 11000.0, - 11000.0, - 11000.0, - NaN + 13000.0, + 13000.0, + 13000.0, + 13000.0 ] }, "failure_status": [ @@ -2912,11 +2912,11 @@ true, true, true, - false + true ] }, "max_standard_rate": null, - "name": "compressor1", + "name": "compressor2", "outlet_stream_condition": { "actual_rate_before_asv_m3_per_hr": [ NaN, @@ -3016,17 +3016,17 @@ }, "unit": "MW", "values": [ - 2.0, - 2.0, - 2.0, - NaN + 4.0, + 4.0, + 4.0, + 4.0 ] }, "rate_sm3_day": [ - 2000000.0, - 2000000.0, - 2000000.0, - 6000000.0 + 4000000.0, + 4000000.0, + 4000000.0, + 4000000.0 ], "stage_results": [ { @@ -3044,10 +3044,10 @@ "NOT_CALCULATED" ], "energy_usage": [ - 11000.0, - 11000.0, - 11000.0, - NaN + 13000.0, + 13000.0, + 13000.0, + 13000.0 ], "energy_usage_unit": "Sm3/d", "fluid_composition": {}, @@ -3117,7 +3117,7 @@ true, true, true, - false + true ], "mass_rate_before_asv_kg_per_hr": [ NaN, @@ -3212,10 +3212,10 @@ NaN ], "power": [ - 2.0, - 2.0, - 2.0, - NaN + 4.0, + 4.0, + 4.0, + 4.0 ], "power_unit": "MW", "pressure_is_choked": [ @@ -3368,7 +3368,7 @@ ] }, "max_standard_rate": null, - "name": "compressor2", + "name": "compressor3", "outlet_stream_condition": { "actual_rate_before_asv_m3_per_hr": [ NaN, @@ -3722,10 +3722,10 @@ }, "unit": "Sm3/d", "values": [ - 13000.0, - 13000.0, - 13000.0, - 13000.0 + 11000.0, + 11000.0, + 11000.0, + NaN ] }, "failure_status": [ @@ -3816,11 +3816,11 @@ true, true, true, - true + false ] }, "max_standard_rate": null, - "name": "compressor3", + "name": "compressor1", "outlet_stream_condition": { "actual_rate_before_asv_m3_per_hr": [ NaN, @@ -3920,17 +3920,17 @@ }, "unit": "MW", "values": [ - 4.0, - 4.0, - 4.0, - 4.0 + 2.0, + 2.0, + 2.0, + NaN ] }, "rate_sm3_day": [ - 4000000.0, - 4000000.0, - 4000000.0, - 4000000.0 + 2000000.0, + 2000000.0, + 2000000.0, + 6000000.0 ], "stage_results": [ { @@ -3948,10 +3948,10 @@ "NOT_CALCULATED" ], "energy_usage": [ - 13000.0, - 13000.0, - 13000.0, - 13000.0 + 11000.0, + 11000.0, + 11000.0, + NaN ], "energy_usage_unit": "Sm3/d", "fluid_composition": {}, @@ -4021,7 +4021,7 @@ true, true, true, - true + false ], "mass_rate_before_asv_kg_per_hr": [ NaN, @@ -4116,10 +4116,10 @@ NaN ], "power": [ - 4.0, - 4.0, - 4.0, - 4.0 + 2.0, + 2.0, + 2.0, + NaN ], "power_unit": "MW", "pressure_is_choked": [ @@ -4176,10 +4176,10 @@ }, "unit": "Sm3/d", "values": [ - 12000.0, - 12000.0, - 12000.0, - 12000.0 + 13000.0, + 13000.0, + 13000.0, + 13000.0 ] }, "failure_status": [ @@ -4274,7 +4274,7 @@ ] }, "max_standard_rate": null, - "name": "compressor1", + "name": "compressor2", "outlet_stream_condition": { "actual_rate_before_asv_m3_per_hr": [ NaN, @@ -4374,17 +4374,17 @@ }, "unit": "MW", "values": [ - 3.0, - 3.0, - 3.0, - 3.0 + 4.0, + 4.0, + 4.0, + 4.0 ] }, "rate_sm3_day": [ - 3000000.0, - 3000000.0, - 3000000.0, - 3000000.0 + 4000000.0, + 4000000.0, + 4000000.0, + 4000000.0 ], "stage_results": [ { @@ -4402,10 +4402,10 @@ "NOT_CALCULATED" ], "energy_usage": [ - 12000.0, - 12000.0, - 12000.0, - 12000.0 + 13000.0, + 13000.0, + 13000.0, + 13000.0 ], "energy_usage_unit": "Sm3/d", "fluid_composition": {}, @@ -4570,10 +4570,10 @@ NaN ], "power": [ - 3.0, - 3.0, - 3.0, - 3.0 + 4.0, + 4.0, + 4.0, + 4.0 ], "power_unit": "MW", "pressure_is_choked": [ @@ -4726,7 +4726,7 @@ ] }, "max_standard_rate": null, - "name": "compressor2", + "name": "compressor3", "outlet_stream_condition": { "actual_rate_before_asv_m3_per_hr": [ NaN, @@ -5080,10 +5080,10 @@ }, "unit": "Sm3/d", "values": [ - 13000.0, - 13000.0, - 13000.0, - 13000.0 + 12000.0, + 12000.0, + 12000.0, + 12000.0 ] }, "failure_status": [ @@ -5178,7 +5178,7 @@ ] }, "max_standard_rate": null, - "name": "compressor3", + "name": "compressor1", "outlet_stream_condition": { "actual_rate_before_asv_m3_per_hr": [ NaN, @@ -5278,17 +5278,17 @@ }, "unit": "MW", "values": [ - 4.0, - 4.0, - 4.0, - 4.0 + 3.0, + 3.0, + 3.0, + 3.0 ] }, "rate_sm3_day": [ - 4000000.0, - 4000000.0, - 4000000.0, - 4000000.0 + 3000000.0, + 3000000.0, + 3000000.0, + 3000000.0 ], "stage_results": [ { @@ -5306,10 +5306,10 @@ "NOT_CALCULATED" ], "energy_usage": [ - 13000.0, - 13000.0, - 13000.0, - 13000.0 + 12000.0, + 12000.0, + 12000.0, + 12000.0 ], "energy_usage_unit": "Sm3/d", "fluid_composition": {}, @@ -5474,10 +5474,10 @@ NaN ], "power": [ - 4.0, - 4.0, - 4.0, - 4.0 + 3.0, + 3.0, + 3.0, + 3.0 ], "power_unit": "MW", "pressure_is_choked": [ @@ -5615,10 +5615,10 @@ }, "unit": "Sm3/d", "values": [ - 11000.0, - 11000.0, - 11000.0, - 12000.0 + 13000.0, + 13000.0, + 13000.0, + 13000.0 ] }, "failure_status": [ @@ -5713,7 +5713,7 @@ ] }, "max_standard_rate": null, - "name": "compressor1", + "name": "compressor2", "outlet_stream_condition": { "actual_rate_before_asv_m3_per_hr": [ NaN, @@ -5813,17 +5813,17 @@ }, "unit": "MW", "values": [ - 2.0, - 2.0, - 2.0, - 3.0 + 4.0, + 4.0, + 4.0, + 4.0 ] }, "rate_sm3_day": [ - 2000000.0, - 2000000.0, - 2000000.0, - 3000000.0 + 4000000.0, + 4000000.0, + 4000000.0, + 4000000.0 ], "stage_results": [ { @@ -5841,10 +5841,10 @@ "NOT_CALCULATED" ], "energy_usage": [ - 11000.0, - 11000.0, - 11000.0, - 12000.0 + 13000.0, + 13000.0, + 13000.0, + 13000.0 ], "energy_usage_unit": "Sm3/d", "fluid_composition": {}, @@ -6009,10 +6009,10 @@ NaN ], "power": [ - 2.0, - 2.0, - 2.0, - 3.0 + 4.0, + 4.0, + 4.0, + 4.0 ], "power_unit": "MW", "pressure_is_choked": [ @@ -6165,7 +6165,7 @@ ] }, "max_standard_rate": null, - "name": "compressor2", + "name": "compressor3", "outlet_stream_condition": { "actual_rate_before_asv_m3_per_hr": [ NaN, @@ -6519,10 +6519,10 @@ }, "unit": "Sm3/d", "values": [ - 13000.0, - 13000.0, - 13000.0, - 13000.0 + 11000.0, + 11000.0, + 11000.0, + 12000.0 ] }, "failure_status": [ @@ -6617,7 +6617,7 @@ ] }, "max_standard_rate": null, - "name": "compressor3", + "name": "compressor1", "outlet_stream_condition": { "actual_rate_before_asv_m3_per_hr": [ NaN, @@ -6717,17 +6717,17 @@ }, "unit": "MW", "values": [ - 4.0, - 4.0, - 4.0, - 4.0 + 2.0, + 2.0, + 2.0, + 3.0 ] }, "rate_sm3_day": [ - 4000000.0, - 4000000.0, - 4000000.0, - 4000000.0 + 2000000.0, + 2000000.0, + 2000000.0, + 3000000.0 ], "stage_results": [ { @@ -6745,10 +6745,10 @@ "NOT_CALCULATED" ], "energy_usage": [ - 13000.0, - 13000.0, - 13000.0, - 13000.0 + 11000.0, + 11000.0, + 11000.0, + 12000.0 ], "energy_usage_unit": "Sm3/d", "fluid_composition": {}, @@ -6913,10 +6913,10 @@ NaN ], "power": [ - 4.0, - 4.0, - 4.0, - 4.0 + 2.0, + 2.0, + 2.0, + 3.0 ], "power_unit": "MW", "pressure_is_choked": [ @@ -10034,10 +10034,10 @@ ] }, "inlet_liquid_rate_m3_per_day": [ - 14995200.0, - 14995200.0, - 14995200.0, - 14995200.0 + 2400.0, + 2400.0, + 2400.0, + 2400.0 ], "inlet_pressure_bar": [ 50.0, @@ -10074,7 +10074,7 @@ false ] }, - "name": "pump1", + "name": "pump2", "operational_head": [ 10000000.0, 10000000.0, @@ -10208,7 +10208,7 @@ false ] }, - "name": "pump2", + "name": "pump3", "operational_head": [ 10000000.0, 10000000.0, @@ -10302,10 +10302,10 @@ ] }, "inlet_liquid_rate_m3_per_day": [ - 2400.0, - 2400.0, - 2400.0, - 2400.0 + 14995200.0, + 14995200.0, + 14995200.0, + 14995200.0 ], "inlet_pressure_bar": [ 50.0, @@ -10342,7 +10342,7 @@ false ] }, - "name": "pump3", + "name": "pump1", "operational_head": [ 10000000.0, 10000000.0, @@ -10438,10 +10438,10 @@ ] }, "inlet_liquid_rate_m3_per_day": [ - 7495200.0, - 7495200.0, - 7495200.0, - 7495200.0 + 2400.0, + 2400.0, + 2400.0, + 2400.0 ], "inlet_pressure_bar": [ 50.0, @@ -10478,7 +10478,7 @@ false ] }, - "name": "pump1", + "name": "pump2", "operational_head": [ 3750000.0, 3750000.0, @@ -10612,7 +10612,7 @@ false ] }, - "name": "pump2", + "name": "pump3", "operational_head": [ 3750000.0, 3750000.0, @@ -10706,10 +10706,10 @@ ] }, "inlet_liquid_rate_m3_per_day": [ - 2400.0, - 2400.0, - 2400.0, - 2400.0 + 7495200.0, + 7495200.0, + 7495200.0, + 7495200.0 ], "inlet_pressure_bar": [ 50.0, @@ -10746,7 +10746,7 @@ false ] }, - "name": "pump3", + "name": "pump1", "operational_head": [ 3750000.0, 3750000.0, @@ -10923,10 +10923,10 @@ ] }, "inlet_liquid_rate_m3_per_day": [ - 7495200.0, - 7495200.0, - 7495200.0, - 7495200.0 + 2400.0, + 2400.0, + 2400.0, + 2400.0 ], "inlet_pressure_bar": [ 50.0, @@ -10963,7 +10963,7 @@ false ] }, - "name": "pump1", + "name": "pump2", "operational_head": [ 3750000.0, 3750000.0, @@ -11097,7 +11097,7 @@ false ] }, - "name": "pump2", + "name": "pump3", "operational_head": [ 3750000.0, 3750000.0, @@ -11191,10 +11191,10 @@ ] }, "inlet_liquid_rate_m3_per_day": [ - 2400.0, - 2400.0, - 2400.0, - 2400.0 + 7495200.0, + 7495200.0, + 7495200.0, + 7495200.0 ], "inlet_pressure_bar": [ 50.0, @@ -11231,7 +11231,7 @@ false ] }, - "name": "pump3", + "name": "pump1", "operational_head": [ 3750000.0, 3750000.0,