From 0e6b2489c97878a848a486faabfa07895d1483ab Mon Sep 17 00:00:00 2001
From: Frode Helgetun Krogh <70878501+frodehk@users.noreply.github.com>
Date: Tue, 7 May 2024 15:56:01 +0200
Subject: [PATCH] fix: ensure regularity is evaluated for all installations
 when only venting emitters (#468)

* fix: ensure regularity is evaluated for all installations

ECALC-1061
---
 src/libecalc/application/graph_result.py      |  7 +--
 .../venting_emitters/venting_emitter_yaml.py  | 11 +---
 src/tests/libecalc/output/results/test_ltp.py | 50 +++++++++++++++++--
 3 files changed, 52 insertions(+), 16 deletions(-)

diff --git a/src/libecalc/application/graph_result.py b/src/libecalc/application/graph_result.py
index a4c08b7619..da9813fe0f 100644
--- a/src/libecalc/application/graph_result.py
+++ b/src/libecalc/application/graph_result.py
@@ -1249,9 +1249,10 @@ def get_asset_result(self) -> libecalc.dto.result.EcalcModelResult:
 
             sub_components.append(obj)
 
-        # When only venting emitters are specified, without a generator set: the installation result is empty.
-        # Ensure that the installation regularity is found, even if only venting emitters are defined:
-        if not installation_results:
+        # When only venting emitters are specified, without a generator set: the installation result
+        # is empty for this installation. Ensure that the installation regularity is found, even if only
+        # venting emitters are defined for one installation:
+        if len(installation_results) < len(asset.installations):
             regularities = {
                 installation.id: TimeSeriesFloat(
                     values=TemporalExpression.evaluate(
diff --git a/src/libecalc/fixtures/cases/venting_emitters/venting_emitter_yaml.py b/src/libecalc/fixtures/cases/venting_emitters/venting_emitter_yaml.py
index aa7c23218e..e600812f1e 100644
--- a/src/libecalc/fixtures/cases/venting_emitters/venting_emitter_yaml.py
+++ b/src/libecalc/fixtures/cases/venting_emitters/venting_emitter_yaml.py
@@ -27,6 +27,7 @@ def venting_emitter_yaml_factory(
     emitter_types: List[str] = None,
     categories: List[str] = None,
     emission_keyword_name: str = "EMISSIONS",
+    installation_name: str = "minimal_installation",
     emission_factors: List[float] = None,
     oil_rates: List[float] = None,
     units_oil_rates: List[Unit] = None,
@@ -46,14 +47,6 @@ def venting_emitter_yaml_factory(
     if emission_rates is None:
         emission_rates = [10] * len(names)
 
-    f"""
-        {create_venting_emitters_yaml(
-        categories=categories, rate_types=rate_types, emitter_names=names, emission_names=emission_names,
-        emission_rates=emission_rates, units=units, emission_keyword_name=emission_keyword_name, include_emitters=include_emitters,
-        emitter_types=emitter_types, oil_rates=oil_rates, emission_factors=emission_factors, units_oil_rates=units_oil_rates,
-    )}
-    """
-
     input_text = f"""
         FACILITY_INPUTS:
           - NAME: generator_energy_function
@@ -69,7 +62,7 @@ def venting_emitter_yaml_factory(
         END: 2029-01-01
 
         INSTALLATIONS:
-        - NAME: minimal_installation
+        - NAME: {installation_name}
           HCEXPORT: 0
           FUEL: fuel
           CATEGORY: FIXED
diff --git a/src/tests/libecalc/output/results/test_ltp.py b/src/tests/libecalc/output/results/test_ltp.py
index 6a045972dd..8dccbd4d3f 100644
--- a/src/tests/libecalc/output/results/test_ltp.py
+++ b/src/tests/libecalc/output/results/test_ltp.py
@@ -296,7 +296,8 @@ def test_only_venting_emitters_no_fuelconsumers():
 
     variables = dto.VariablesMap(time_vector=time_vector, variables={})
 
-    dto_case = venting_emitter_yaml_factory(
+    # Installation with only venting emitters:
+    dto_case_emitters = venting_emitter_yaml_factory(
         emission_rates=[emission_rate],
         regularity=regularity,
         units=[Unit.KILO_PER_DAY],
@@ -305,20 +306,61 @@ def test_only_venting_emitters_no_fuelconsumers():
         include_emitters=True,
         include_fuel_consumers=False,
         names=["Venting emitter 1"],
+        installation_name="Venting emitter installation",
         path=Path(venting_emitters.__path__[0]),
     )
+
     venting_emitter_results = get_consumption(
-        model=dto_case.ecalc_model, variables=variables, time_vector=time_vector_yearly
+        model=dto_case_emitters.ecalc_model, variables=variables, time_vector=time_vector_yearly
     )
 
-    # Verify that eCalc, is not failing in get_asset_result, with only venting emitters -
+    # Verify that eCalc is not failing in get_asset_result with only venting emitters -
     # when installation result is empty, i.e. with no genset and fuel consumers:
-    assert isinstance(get_consumption_asset_result(model=dto_case.ecalc_model, variables=variables), EcalcModelResult)
+    assert isinstance(
+        get_consumption_asset_result(model=dto_case_emitters.ecalc_model, variables=variables), EcalcModelResult
+    )
 
     # Verify correct emissions:
     emissions_ch4 = get_sum_ltp_column(venting_emitter_results, installation_nr=0, ltp_column_nr=0)
     assert emissions_ch4 == (emission_rate / 1000) * 365 * regularity
 
+    # Installation with only fuel consumers:
+    dto_case_fuel = venting_emitter_yaml_factory(
+        emission_rates=[emission_rate],
+        regularity=regularity,
+        units=[Unit.KILO_PER_DAY],
+        emission_names=["ch4"],
+        rate_types=[RateType.STREAM_DAY],
+        include_emitters=False,
+        include_fuel_consumers=True,
+        names=["Venting emitter 1"],
+        installation_name="Fuel consumer installation",
+        path=Path(venting_emitters.__path__[0]),
+    )
+
+    asset_multi_installations = dto.Asset(
+        name="Multi installations",
+        installations=[dto_case_emitters.ecalc_model.installations[0], dto_case_fuel.ecalc_model.installations[0]],
+    )
+
+    # Verify that eCalc is not failing in get_asset_result, with only venting emitters -
+    # when installation result is empty for one installation, i.e. with no genset and fuel consumers.
+    # Include asset with two installations, one with only emitters and one with only fuel consumers -
+    # ensure that get_asset_result returns a result:
+
+    assert isinstance(
+        get_consumption_asset_result(model=asset_multi_installations, variables=variables), EcalcModelResult
+    )
+
+    asset_ltp_result = get_consumption(
+        model=asset_multi_installations, variables=variables, time_vector=time_vector_yearly
+    )
+    # Check that the results are the same: For the case with only one installation (only venting emitters),
+    # compared to the multi-installation case with two installations. The fuel-consumer installation should
+    # give no CH4-contribution (only CO2)
+    emissions_ch4_asset = get_sum_ltp_column(asset_ltp_result, installation_nr=0, ltp_column_nr=0)
+    assert emissions_ch4 == emissions_ch4_asset
+
 
 def test_no_emitters_or_fuelconsumers():
     """