From 8d038221c88946730e3badbcc4a4c9ab4d082c16 Mon Sep 17 00:00:00 2001 From: Frode Helgetun Krogh <70878501+frodehk@users.noreply.github.com> Date: Wed, 29 Nov 2023 09:39:42 +0100 Subject: [PATCH] refactor: change name from direct to venting emitter (#303) * refactor: change name from direct to venting emitter --- docs/docs/about/migration_guides/v7_to_v8.md | 2 +- .../modelling/setup/installations/index.md | 4 +- .../references/keywords/EMISSION_NAME.md | 6 +- .../references/keywords/EMITTER_MODEL.md | 2 +- ...DIRECT_EMITTERS.md => VENTING_EMITTERS.md} | 14 +- examples/simple_python_model.ipynb | 2 +- .../{direct_emitter.py => venting_emitter.py} | 24 ++-- src/libecalc/core/ecalc.py | 6 +- src/libecalc/core/graph_result.py | 14 +- src/libecalc/dto/__init__.py | 2 +- src/libecalc/dto/base.py | 2 +- src/libecalc/dto/components.py | 14 +- src/libecalc/dto/result/__init__.py | 2 +- src/libecalc/dto/result/results.py | 6 +- .../cases/all_energy_usage_models/__init__.py | 2 +- .../all_energy_usage_models/all_models_dto.py | 14 +- .../data/all_energy_usage_models.yaml | 4 +- .../consumer_system_v2_dto.py | 2 +- .../cases/consumer_with_time_slots_models.py | 2 +- .../cases/ltp_export/installation_setup.py | 2 +- .../fixtures/cases/minimal/minimal_dto.py | 2 +- .../yaml/mappers/component_mapper.py | 32 ++--- .../presentation/yaml/yaml_keywords.py | 8 +- .../components/yaml_installation.py | 8 +- ...ect_emitter.py => yaml_venting_emitter.py} | 2 +- .../core/consumers/test_direct_emitter.py | 12 +- src/tests/libecalc/dto/test_categories.py | 22 ++-- .../libecalc/dto/utils/test_aggregators.py | 2 +- .../test_json_schema_changed/schemas.json | 122 +++++++++--------- .../all_energy_usage_models_v3.json | 2 +- 30 files changed, 169 insertions(+), 169 deletions(-) rename docs/docs/about/references/keywords/{DIRECT_EMITTERS.md => VENTING_EMITTERS.md} (77%) rename src/libecalc/core/consumers/{direct_emitter.py => venting_emitter.py} (70%) rename src/libecalc/presentation/yaml/yaml_types/emitters/{yaml_direct_emitter.py => yaml_venting_emitter.py} (96%) diff --git a/docs/docs/about/migration_guides/v7_to_v8.md b/docs/docs/about/migration_guides/v7_to_v8.md index b13fedbe36..e2a6ff83ee 100644 --- a/docs/docs/about/migration_guides/v7_to_v8.md +++ b/docs/docs/about/migration_guides/v7_to_v8.md @@ -123,7 +123,7 @@ See [INSTALLATION](../references/keywords/INSTALLATIONS.md), [GENERATORSET](../references/keywords/GENERATORSETS.md), [CONSUMERS](../references/keywords/CONSUMERS.md), [FUELCONSUMERS](../references/keywords/FUELCONSUMERS.md), -[DIRECT_EMITTER](../references/keywords/DIRECT_EMITTERS.md) +[VENTING_EMITTER](../references/keywords/VENTING_EMITTERS.md) for more details about the relevant keywords. :::tip Are you using power from shore? diff --git a/docs/docs/about/modelling/setup/installations/index.md b/docs/docs/about/modelling/setup/installations/index.md index bb8f5968b7..83e909fe18 100644 --- a/docs/docs/about/modelling/setup/installations/index.md +++ b/docs/docs/about/modelling/setup/installations/index.md @@ -60,7 +60,7 @@ INSTALLATIONS: FUEL: HCEXPORT: REGULARITY: - DIRECT_EMITTERS: + VENTING_EMITTERS: CATEGORY: - NAME: GENERATORSETS: @@ -68,7 +68,7 @@ INSTALLATIONS: FUEL: HCEXPORT: REGULARITY: - DIRECT_EMITTERS: + VENTING_EMITTERS: CATEGORY: - ... ~~~~~~~~ diff --git a/docs/docs/about/references/keywords/EMISSION_NAME.md b/docs/docs/about/references/keywords/EMISSION_NAME.md index 16dd2f3ed7..924fac564e 100644 --- a/docs/docs/about/references/keywords/EMISSION_NAME.md +++ b/docs/docs/about/references/keywords/EMISSION_NAME.md @@ -5,7 +5,7 @@ | Required | Child of | Children/Options | |------------|---------------------------|------------------------------------| -| Yes | `DIRECT_EMITTERS` | None | +| Yes | `VENTING_EMITTERS` | None | ## Description Name of an entity. @@ -16,10 +16,10 @@ EMISSION_NAME: ~~~~~~~~ ## Example -Usage in [DIRECT_EMITTERS](/about/references/keywords/DIRECT_EMITTERS.md): +Usage in [VENTING_EMITTERS](/about/references/keywords/VENTING_EMITTERS.md): ~~~~~~~~yaml -DIRECT_EMITTERS: +VENTING_EMITTERS: - EMISSION_NAME: CH4 ~~~~~~~~ diff --git a/docs/docs/about/references/keywords/EMITTER_MODEL.md b/docs/docs/about/references/keywords/EMITTER_MODEL.md index 5852597cc5..fac9a8a8a8 100644 --- a/docs/docs/about/references/keywords/EMITTER_MODEL.md +++ b/docs/docs/about/references/keywords/EMITTER_MODEL.md @@ -6,7 +6,7 @@ | Required | Child of | Children/Options | |------------|---------------------------|-------------------| -| No | `DIRECT_EMITTERS` | `EMISSION_RATE` | +| No | `VENTING_EMITTERS` | `EMISSION_RATE` | ## Description The emitter model specifies the data to calculate the direct emissions on an installation. This data is used to set up diff --git a/docs/docs/about/references/keywords/DIRECT_EMITTERS.md b/docs/docs/about/references/keywords/VENTING_EMITTERS.md similarity index 77% rename from docs/docs/about/references/keywords/DIRECT_EMITTERS.md rename to docs/docs/about/references/keywords/VENTING_EMITTERS.md index 42df011e62..c167392992 100644 --- a/docs/docs/about/references/keywords/DIRECT_EMITTERS.md +++ b/docs/docs/about/references/keywords/VENTING_EMITTERS.md @@ -1,7 +1,7 @@ -# DIRECT_EMITTERS +# VENTING_EMITTERS [INSTALLATIONS](/about/references/keywords/INSTALLATIONS.md) / -[DIRECT_EMITTERS](/about/references/keywords/DIRECT_EMITTERS.md) +[VENTING_EMITTERS](/about/references/keywords/VENTING_EMITTERS.md) | Required | Child of | Children/Options | @@ -10,14 +10,14 @@ ## Description -The [DIRECT_EMITTERS](/about/references/keywords/DIRECT_EMITTERS.md) keyword covers the direct emissions on the installation +The [VENTING_EMITTERS](/about/references/keywords/VENTING_EMITTERS.md) keyword covers the direct emissions on the installation that are not consuming energy. The attributes [NAME](/about/references/keywords/NAME.md), [EMISSION_NAME](/about/references/keywords/EMISSION_NAME.md), [CATEGORY](/about/references/keywords/CATEGORY.md) and [EMITTER_MODEL](/about/references/keywords/EMITTER_MODEL.md) are required. ## Format ~~~~~~~~yaml -DIRECT_EMITTER: +VENTING_EMITTER: - NAME: EMISSION_NAME: CATEGORY: @@ -26,14 +26,14 @@ DIRECT_EMITTER: ## Example ~~~~~~~~yaml -DIRECT_EMITTER: - - NAME: SomeDirectEmitter +VENTING_EMITTER: + - NAME: SomeVentingEmitter EMISSION_NAME: CH4 CATEGORY: COLD-VENTING-FUGITIVE EMITTER_MODEL: ... - - NAME: SomeOtherDirectEmitter + - NAME: SomeOtherVentingEmitter EMISSION_NAME: C2H6 CATEGORY: COLD-VENTING-FUGITIVE EMITTER_MODEL: diff --git a/examples/simple_python_model.ipynb b/examples/simple_python_model.ipynb index eaf13d8a3c..d0b677a7eb 100644 --- a/examples/simple_python_model.ipynb +++ b/examples/simple_python_model.ipynb @@ -727,7 +727,7 @@ " generator_set_a,\n", " flare,\n", " ],\n", - " direct_emitters=[],\n", + " venting_emitters=[],\n", " )\n", " ],\n", ")\n" diff --git a/src/libecalc/core/consumers/direct_emitter.py b/src/libecalc/core/consumers/venting_emitter.py similarity index 70% rename from src/libecalc/core/consumers/direct_emitter.py rename to src/libecalc/core/consumers/venting_emitter.py index 0919c6f8f5..eba5e9df7e 100644 --- a/src/libecalc/core/consumers/direct_emitter.py +++ b/src/libecalc/core/consumers/venting_emitter.py @@ -15,41 +15,41 @@ from libecalc.expression import Expression -class DirectEmitter: +class VentingEmitter: """A class for direct (not fuel based) emissions.""" - def __init__(self, direct_emitter_dto: dto.DirectEmitter): - """We model a Direct Emitter as a Fuel Consumer, where the emission rate (kg/day) and + def __init__(self, venting_emitter_dto: dto.VentingEmitter): + """We model a Venting Emitter as a Fuel Consumer, where the emission rate (kg/day) and the fuel rate (unit-less) are handled as 1 to 1. This means that we can simulate a direct emission as a normal fuel consumer the same, but using the simplification mentioned above. """ - logger.debug(f"Creating DirectEmitter: {direct_emitter_dto.name}") + logger.debug(f"Creating VentingEmitter: {venting_emitter_dto.name}") - self.direct_emitter_dto = direct_emitter_dto + self.venting_emitter_dto = venting_emitter_dto self.temporal_fuel_model = FuelModel( { start_time: FuelType( - name=direct_emitter_dto.name, - # This is the DIRECT-EMITTER CATEGORY which is fed into the fuel modet -> fuel validation error + name=venting_emitter_dto.name, + # This is the VENTING-EMITTER CATEGORY which is fed into the fuel modet -> fuel validation error # Commented out, meaning the fuel model has CATEGORY set to None - # user_defined_category=direct_emitter_dto.user_defined_category, + # user_defined_category=venting_emitter_dto.user_defined_category, emissions=[ Emission( - name=direct_emitter_dto.emission_name, + name=venting_emitter_dto.emission_name, factor=Expression.setup_from_expression(1), # See docstring. # See docstring ) ], ) - for start_time, emitter_model in direct_emitter_dto.emitter_model.items() + for start_time, emitter_model in venting_emitter_dto.emitter_model.items() } ) self.temporal_emission_rate_model = TemporalModel( { start_time: emitter_model.emission_rate - for start_time, emitter_model in direct_emitter_dto.emitter_model.items() + for start_time, emitter_model in venting_emitter_dto.emitter_model.items() } ) @@ -57,7 +57,7 @@ def evaluate( self, variables_map: VariablesMap, ) -> Dict[str, EmissionResult]: - logger.debug(f"Evaluating DirectEmitter: {self.direct_emitter_dto.name}") + logger.debug(f"Evaluating VentingEmitter: {self.venting_emitter_dto.name}") fuel_rate = self.evaluate_fuel_rate(variables_map=variables_map) return self.temporal_fuel_model.evaluate_emissions( variables_map=variables_map, diff --git a/src/libecalc/core/ecalc.py b/src/libecalc/core/ecalc.py index ae320f5103..61cf57509e 100644 --- a/src/libecalc/core/ecalc.py +++ b/src/libecalc/core/ecalc.py @@ -13,10 +13,10 @@ from libecalc.common.units import Unit from libecalc.common.utils.rates import TimeSeriesInt, TimeSeriesString from libecalc.core.consumers.consumer_system import ConsumerSystem -from libecalc.core.consumers.direct_emitter import DirectEmitter from libecalc.core.consumers.factory import create_consumer from libecalc.core.consumers.generator_set import Genset from libecalc.core.consumers.legacy_consumer.component import Consumer +from libecalc.core.consumers.venting_emitter import VentingEmitter from libecalc.core.models.fuel import FuelModel from libecalc.core.result import ComponentResult, EcalcModelResult from libecalc.core.result.emission import EmissionResult @@ -169,6 +169,6 @@ def evaluate_emissions( emission_results[consumer_dto.id] = fuel_model.evaluate_emissions( variables_map=variables_map, fuel_rate=np.asarray(energy_usage.values) ) - elif isinstance(consumer_dto, dto.DirectEmitter): - emission_results[consumer_dto.id] = DirectEmitter(consumer_dto).evaluate(variables_map=variables_map) + elif isinstance(consumer_dto, dto.VentingEmitter): + emission_results[consumer_dto.id] = VentingEmitter(consumer_dto).evaluate(variables_map=variables_map) return emission_results diff --git a/src/libecalc/core/graph_result.py b/src/libecalc/core/graph_result.py index 430a74e060..ce20e966ba 100644 --- a/src/libecalc/core/graph_result.py +++ b/src/libecalc/core/graph_result.py @@ -1147,7 +1147,7 @@ def get_asset_result(self) -> libecalc.dto.result.EcalcModelResult: consumer_result.component_result.energy_usage, regularity=regularity ).to_stream_day(), ) - else: # COMPRESSOR_SYSTEM, PUMP_SYSTEM, GENERIC, TURBINE, DIRECT_EMITTER + else: # COMPRESSOR_SYSTEM, PUMP_SYSTEM, GENERIC, TURBINE, VENTING_EMITTER obj = parse_obj_as( libecalc.dto.result.ComponentResult, { @@ -1191,7 +1191,7 @@ def get_asset_result(self) -> libecalc.dto.result.EcalcModelResult: for installation in asset.installations: regularity = regularities[installation.id] # Already evaluated regularities - for direct_emitter in installation.direct_emitters: + for venting_emitter in installation.venting_emitters: energy_usage = TimeSeriesRate( timesteps=self.variables_map.time_vector, values=[0.0] * self.variables_map.length, @@ -1200,13 +1200,13 @@ def get_asset_result(self) -> libecalc.dto.result.EcalcModelResult: rate_type=RateType.CALENDAR_DAY, ) sub_components.append( - libecalc.dto.result.DirectEmitterResult( - id=direct_emitter.id, - name=direct_emitter.name, - componentType=direct_emitter.component_type, + libecalc.dto.result.VentingEmitterResult( + id=venting_emitter.id, + name=venting_emitter.name, + componentType=venting_emitter.component_type, component_level=ComponentLevel.CONSUMER, parent=installation.id, - emissions=self._parse_emissions(self.emission_results[direct_emitter.id], regularity), + emissions=self._parse_emissions(self.emission_results[venting_emitter.id], regularity), timesteps=self.variables_map.time_vector, is_valid=TimeSeriesBoolean( timesteps=self.variables_map.time_vector, diff --git a/src/libecalc/dto/__init__.py b/src/libecalc/dto/__init__.py index 226fe178cc..6d693721a3 100644 --- a/src/libecalc/dto/__init__.py +++ b/src/libecalc/dto/__init__.py @@ -1,12 +1,12 @@ from libecalc.dto.components import ( Asset, BaseConsumer, - DirectEmitter, ElectricityConsumer, EmitterModel, FuelConsumer, GeneratorSet, Installation, + VentingEmitter, ) from libecalc.dto.emission import Emission from libecalc.dto.models import ( diff --git a/src/libecalc/dto/base.py b/src/libecalc/dto/base.py index f6213ca765..99088882bf 100644 --- a/src/libecalc/dto/base.py +++ b/src/libecalc/dto/base.py @@ -26,7 +26,7 @@ class ComponentType(str, Enum): PUMP_V2 = "PUMP@v2" GENERIC = "GENERIC" # TURBINE = "TURBINE" - DIRECT_EMITTER = "DIRECT_EMITTER" + VENTING_EMITTER = "VENTING_EMITTER" TRAIN_V2 = "TRAIN@V2" def __lt__(self, other: "ComponentType"): # type: ignore[override] diff --git a/src/libecalc/dto/components.py b/src/libecalc/dto/components.py index 00199bd856..55004edc4d 100644 --- a/src/libecalc/dto/components.py +++ b/src/libecalc/dto/components.py @@ -143,8 +143,8 @@ class EmitterModel(EcalcBaseModel): _default_emission_rate = validator("emission_rate", allow_reuse=True, pre=True)(convert_expression) -class DirectEmitter(BaseEquipment): - component_type = ComponentType.DIRECT_EMITTER +class VentingEmitter(BaseEquipment): + component_type = ComponentType.VENTING_EMITTER emission_name: EmissionNameStr emitter_model: Dict[datetime, EmitterModel] @@ -335,7 +335,7 @@ class Installation(BaseComponent): user_defined_category: Optional[InstallationUserDefinedCategoryType] = None hydrocarbon_export: Dict[datetime, Expression] fuel_consumers: List[Union[GeneratorSet, FuelConsumer, ConsumerSystem]] = Field(default_factory=list) - direct_emitters: List[DirectEmitter] = Field(default_factory=list) + venting_emitters: List[VentingEmitter] = Field(default_factory=list) @property def id(self) -> str: @@ -365,7 +365,7 @@ def check_user_defined_category(cls, user_defined_category, values): def get_graph(self) -> ComponentGraph: graph = ComponentGraph() graph.add_node(self) - for component in [*self.fuel_consumers, *self.direct_emitters]: + for component in [*self.fuel_consumers, *self.venting_emitters]: if hasattr(component, "get_graph"): graph.add_subgraph(component.get_graph()) else: @@ -399,7 +399,7 @@ def get_component_ids_for_installation_id(self, installation_id: str) -> List[st for electricity_consumer in fuel_consumer.consumers: component_ids.append(electricity_consumer.id) - for emitter in installation.direct_emitters: + for emitter in installation.venting_emitters: component_ids.append(emitter.id) return component_ids @@ -415,9 +415,9 @@ def validate_unique_names(cls, values): for installation in values["installations"]: names.append(installation.name) fuel_consumers = installation.fuel_consumers - direct_emitters = installation.direct_emitters + venting_emitters = installation.venting_emitters - names.extend([direct_emitter.name for direct_emitter in direct_emitters]) + names.extend([venting_emitter.name for venting_emitter in venting_emitters]) for fuel_consumer in fuel_consumers: names.append(fuel_consumer.name) if isinstance(fuel_consumer, GeneratorSet): diff --git a/src/libecalc/dto/result/__init__.py b/src/libecalc/dto/result/__init__.py index a706bd625f..7fec878608 100644 --- a/src/libecalc/dto/result/__init__.py +++ b/src/libecalc/dto/result/__init__.py @@ -6,7 +6,6 @@ CompressorResult, ConsumerModelResult, ConsumerSystemResult, - DirectEmitterResult, EcalcModelResult, GeneratorSetResult, GenericConsumerResult, @@ -14,4 +13,5 @@ InstallationResult, PumpModelResult, PumpResult, + VentingEmitterResult, ) diff --git a/src/libecalc/dto/result/results.py b/src/libecalc/dto/result/results.py index 1ea9e76a62..cedc977b0d 100644 --- a/src/libecalc/dto/result/results.py +++ b/src/libecalc/dto/result/results.py @@ -139,8 +139,8 @@ class CompressorResult(EquipmentResultBase): streams: List[TimeSeriesStreamConditions] = None # Optional because only in v2 -class DirectEmitterResult(EquipmentResultBase): - componentType: Literal[ComponentType.DIRECT_EMITTER] +class VentingEmitterResult(EquipmentResultBase): + componentType: Literal[ComponentType.VENTING_EMITTER] class ConsumerModelResultBase(NodeInfo, CommonResultBase): @@ -242,7 +242,7 @@ class GenericModelResult(ConsumerModelResultBase): CompressorResult, PumpResult, GenericConsumerResult, - DirectEmitterResult, + VentingEmitterResult, ], Field(discriminator="componentType"), ] diff --git a/src/libecalc/fixtures/cases/all_energy_usage_models/__init__.py b/src/libecalc/fixtures/cases/all_energy_usage_models/__init__.py index 5e3b61c655..9da9992868 100644 --- a/src/libecalc/fixtures/cases/all_energy_usage_models/__init__.py +++ b/src/libecalc/fixtures/cases/all_energy_usage_models/__init__.py @@ -18,7 +18,7 @@ genset_sampled, late_start_consumer, late_start_consumer_evolving_type, - methane_direct, + methane_venting, pump_system_el_consumer, salt_water_injection_tabular, simplified_compressor_system, diff --git a/src/libecalc/fixtures/cases/all_energy_usage_models/all_models_dto.py b/src/libecalc/fixtures/cases/all_energy_usage_models/all_models_dto.py index 2229edbf56..7edfb79d38 100644 --- a/src/libecalc/fixtures/cases/all_energy_usage_models/all_models_dto.py +++ b/src/libecalc/fixtures/cases/all_energy_usage_models/all_models_dto.py @@ -971,10 +971,10 @@ def variable_speed_compressor_train_multiple_input_streams_and_interstage_pressu @pytest.fixture -def methane_direct(regularity) -> dto.DirectEmitter: - return dto.DirectEmitter( - name="methane_direct", - component_type=ComponentType.DIRECT_EMITTER, +def methane_venting(regularity) -> dto.VentingEmitter: + return dto.VentingEmitter( + name="methane_venting", + component_type=ComponentType.VENTING_EMITTER, user_defined_category={datetime(1900, 1, 1): ConsumerUserDefinedCategoryType.COLD_VENTING_FUGITIVE}, emission_name="CH4", emitter_model={ @@ -1046,7 +1046,7 @@ def all_energy_usage_models_dto( compressor_system, turbine_driven_compressor_train, compressor_system_variable_speed_compressor_trains, - methane_direct, + methane_venting, flare, all_energy_usage_models_variables, ) -> DTOCase: @@ -1103,8 +1103,8 @@ def all_energy_usage_models_dto( turbine_driven_compressor_train, compressor_system_variable_speed_compressor_trains, ], - direct_emitters=[ - methane_direct, + venting_emitters=[ + methane_venting, ], ) ], diff --git a/src/libecalc/fixtures/cases/all_energy_usage_models/data/all_energy_usage_models.yaml b/src/libecalc/fixtures/cases/all_energy_usage_models/data/all_energy_usage_models.yaml index a3a6b187b7..1ecc8703cd 100644 --- a/src/libecalc/fixtures/cases/all_energy_usage_models/data/all_energy_usage_models.yaml +++ b/src/libecalc/fixtures/cases/all_energy_usage_models/data/all_energy_usage_models.yaml @@ -613,8 +613,8 @@ INSTALLATIONS: - SIM1;GAS_PROD {/} 2 SUCTION_PRESSURE: 50 DISCHARGE_PRESSURE: 250 - DIRECT_EMITTERS: - - NAME: methane_direct + VENTING_EMITTERS: + - NAME: methane_venting EMISSION_NAME: CH4 CATEGORY: COLD-VENTING-FUGITIVE EMITTER_MODEL: diff --git a/src/libecalc/fixtures/cases/consumer_system_v2/consumer_system_v2_dto.py b/src/libecalc/fixtures/cases/consumer_system_v2/consumer_system_v2_dto.py index 5086a9ffe0..7d1c77c09f 100644 --- a/src/libecalc/fixtures/cases/consumer_system_v2/consumer_system_v2_dto.py +++ b/src/libecalc/fixtures/cases/consumer_system_v2/consumer_system_v2_dto.py @@ -625,7 +625,7 @@ def consumer_system_v2_dto() -> DTOCase: compressor_system, compressor_system_v2, ], - direct_emitters=[], + venting_emitters=[], ) ], ), diff --git a/src/libecalc/fixtures/cases/consumer_with_time_slots_models.py b/src/libecalc/fixtures/cases/consumer_with_time_slots_models.py index f2a8743b7a..424eb95f4f 100644 --- a/src/libecalc/fixtures/cases/consumer_with_time_slots_models.py +++ b/src/libecalc/fixtures/cases/consumer_with_time_slots_models.py @@ -288,7 +288,7 @@ def consumer_with_time_slots_models_dto( ), tabulated_fuel_consumer_with_time_slots(fuel_gas), ], - direct_emitters=[], + venting_emitters=[], ) ], ), diff --git a/src/libecalc/fixtures/cases/ltp_export/installation_setup.py b/src/libecalc/fixtures/cases/ltp_export/installation_setup.py index e8dd74b471..5ae772e627 100644 --- a/src/libecalc/fixtures/cases/ltp_export/installation_setup.py +++ b/src/libecalc/fixtures/cases/ltp_export/installation_setup.py @@ -244,7 +244,7 @@ def compressor_sampled(): def boiler_heater() -> dto.FuelConsumer: return dto.FuelConsumer( name="boiler", - component_type=dto.base.ComponentType.DIRECT_EMITTER, + component_type=dto.base.ComponentType.VENTING_EMITTER, fuel={date1: fuel_turbine()}, user_defined_category={ date1: ConsumerUserDefinedCategoryType.BOILER, diff --git a/src/libecalc/fixtures/cases/minimal/minimal_dto.py b/src/libecalc/fixtures/cases/minimal/minimal_dto.py index 35b180b643..f8a1d509fb 100644 --- a/src/libecalc/fixtures/cases/minimal/minimal_dto.py +++ b/src/libecalc/fixtures/cases/minimal/minimal_dto.py @@ -19,7 +19,7 @@ def minimal_installation_dto( return dto.Installation( name=installation_name, regularity=regularity, - direct_emitters=[], + venting_emitters=[], hydrocarbon_export={start: Expression.setup_from_expression(0)}, user_defined_category=InstallationUserDefinedCategoryType.FIXED, fuel_consumers=[ diff --git a/src/libecalc/presentation/yaml/mappers/component_mapper.py b/src/libecalc/presentation/yaml/mappers/component_mapper.py index 5e509c8fd7..465f730028 100644 --- a/src/libecalc/presentation/yaml/mappers/component_mapper.py +++ b/src/libecalc/presentation/yaml/mappers/component_mapper.py @@ -233,7 +233,7 @@ def from_yaml_to_dto( class EmitterModelMapper: - """EmitterModel used by DirectEmitters.""" + """EmitterModel used by VentingEmitters.""" def __init__(self, references: References, target_period: Period): self._target_period = target_period @@ -243,7 +243,7 @@ def __init__(self, references: References, target_period: Period): def create_model(model: Dict, regularity: Dict[datetime, Expression]): name = model.get(EcalcYamlKeywords.name, "") user_defined_category = model.get(EcalcYamlKeywords.user_defined_tag, "") - emission_rate = model.get(EcalcYamlKeywords.installation_direct_emitter_emission_rate) + emission_rate = model.get(EcalcYamlKeywords.installation_venting_emitter_emission_rate) try: return dto.EmitterModel( @@ -265,8 +265,8 @@ def from_yaml_to_dto( } -class DirectEmittersMapper: - """Mapping DirectEmitters and the corresponding EmitterModel.""" +class VentingEmittersMapper: + """Mapping VentingEmitters and the corresponding EmitterModel.""" def __init__(self, references: References, target_period: Period): self.__references = references @@ -277,19 +277,19 @@ def from_yaml_to_dto( self, data: Dict[str, Dict], regularity: Dict[datetime, Expression], - ) -> dto.DirectEmitter: + ) -> dto.VentingEmitter: emitter_model = self.__emitter_model_mapper.from_yaml_to_dto( - data.get(EcalcYamlKeywords.installation_direct_emitter_model), + data.get(EcalcYamlKeywords.installation_venting_emitter_model), regularity=regularity, ) try: - direct_emitter_name = data.get(EcalcYamlKeywords.name) - return dto.DirectEmitter( - name=direct_emitter_name, + venting_emitter_name = data.get(EcalcYamlKeywords.name) + return dto.VentingEmitter( + name=venting_emitter_name, user_defined_category=define_time_model_for_period( data.get(EcalcYamlKeywords.user_defined_tag), target_period=self._target_period ), - emission_name=data.get(EcalcYamlKeywords.installation_direct_emitter_emission_name), + emission_name=data.get(EcalcYamlKeywords.installation_venting_emitter_emission_name), emitter_model=emitter_model, regularity=regularity, ) @@ -303,7 +303,7 @@ def __init__(self, references: References, target_period: Period): self._target_period = target_period self.__generator_set_mapper = GeneratorSetMapper(references=references, target_period=target_period) self.__consumer_mapper = ConsumerMapper(references=references, target_period=target_period) - self.__direct_emitters_mapper = DirectEmittersMapper(references=references, target_period=target_period) + self.__venting_emitters_mapper = VentingEmittersMapper(references=references, target_period=target_period) def from_yaml_to_dto(self, data: Dict) -> dto.Installation: fuel_data = data.get(EcalcYamlKeywords.fuel) @@ -330,12 +330,12 @@ def from_yaml_to_dto(self, data: Dict) -> dto.Installation: ) for fuel_consumer in data.get(EcalcYamlKeywords.fuel_consumers, []) ] - direct_emitters = [ - self.__direct_emitters_mapper.from_yaml_to_dto( - direct_emitters, + venting_emitters = [ + self.__venting_emitters_mapper.from_yaml_to_dto( + venting_emitters, regularity=regularity, ) - for direct_emitters in data.get(EcalcYamlKeywords.installation_direct_emitters, []) + for venting_emitters in data.get(EcalcYamlKeywords.installation_venting_emitters, []) ] hydrocarbon_export = define_time_model_for_period( @@ -352,7 +352,7 @@ def from_yaml_to_dto(self, data: Dict) -> dto.Installation: regularity=regularity, hydrocarbon_export=hydrocarbon_export, fuel_consumers=[*generator_sets, *fuel_consumers], - direct_emitters=direct_emitters, + venting_emitters=venting_emitters, user_defined_category=data.get(EcalcYamlKeywords.user_defined_tag), ) except ValidationError as e: diff --git a/src/libecalc/presentation/yaml/yaml_keywords.py b/src/libecalc/presentation/yaml/yaml_keywords.py index 92cc5ea73e..9a20de7a8f 100644 --- a/src/libecalc/presentation/yaml/yaml_keywords.py +++ b/src/libecalc/presentation/yaml/yaml_keywords.py @@ -66,10 +66,10 @@ class EcalcYamlKeywords: fuel_consumers = "FUELCONSUMERS" fuel_rate = "FUELRATE" generator_sets = "GENERATORSETS" - installation_direct_emitters = "DIRECT_EMITTERS" - installation_direct_emitter_emission_name = "EMISSION_NAME" - installation_direct_emitter_emission_rate = "EMISSION_RATE" - installation_direct_emitter_model = "EMITTER_MODEL" + installation_venting_emitters = "VENTING_EMITTERS" + installation_venting_emitter_emission_name = "EMISSION_NAME" + installation_venting_emitter_emission_rate = "EMISSION_RATE" + installation_venting_emitter_model = "EMITTER_MODEL" hydrocarbon_export = "HCEXPORT" installations = "INSTALLATIONS" load = "LOAD" diff --git a/src/libecalc/presentation/yaml/yaml_types/components/yaml_installation.py b/src/libecalc/presentation/yaml/yaml_types/components/yaml_installation.py index bcae004d09..57cb949e81 100644 --- a/src/libecalc/presentation/yaml/yaml_types/components/yaml_installation.py +++ b/src/libecalc/presentation/yaml/yaml_types/components/yaml_installation.py @@ -22,8 +22,8 @@ YamlGeneratorSet, ) from libecalc.presentation.yaml.yaml_types.components.yaml_pump import YamlPump -from libecalc.presentation.yaml.yaml_types.emitters.yaml_direct_emitter import ( - YamlDirectEmitter, +from libecalc.presentation.yaml.yaml_types.emitters.yaml_venting_emitter import ( + YamlVentingEmitter, ) from libecalc.presentation.yaml.yaml_types.yaml_temporal_model import YamlTemporalModel @@ -70,8 +70,8 @@ class Config: title="FUELCONSUMERS", description="Defines fuel consumers on the installation which are not generators.\n\n$ECALC_DOCS_KEYWORDS_URL/FUELCONSUMERS", ) - direct_emitters: List[YamlDirectEmitter] = Field( + venting_emitters: List[YamlVentingEmitter] = Field( None, - title="DIRECT_EMITTERS", + title="VENTING_EMITTERS", description="Covers the direct emissions on the installation that are not consuming energy", ) diff --git a/src/libecalc/presentation/yaml/yaml_types/emitters/yaml_direct_emitter.py b/src/libecalc/presentation/yaml/yaml_types/emitters/yaml_venting_emitter.py similarity index 96% rename from src/libecalc/presentation/yaml/yaml_types/emitters/yaml_direct_emitter.py rename to src/libecalc/presentation/yaml/yaml_types/emitters/yaml_venting_emitter.py index 9994b5fab7..6f21c9f30c 100644 --- a/src/libecalc/presentation/yaml/yaml_types/emitters/yaml_direct_emitter.py +++ b/src/libecalc/presentation/yaml/yaml_types/emitters/yaml_venting_emitter.py @@ -17,7 +17,7 @@ class YamlEmitterModel(YamlBase): ) -class YamlDirectEmitter(YamlBase): +class YamlVentingEmitter(YamlBase): name: str = Field( ..., title="NAME", diff --git a/src/tests/libecalc/core/consumers/test_direct_emitter.py b/src/tests/libecalc/core/consumers/test_direct_emitter.py index 0487df5e8b..4d00c8de2b 100644 --- a/src/tests/libecalc/core/consumers/test_direct_emitter.py +++ b/src/tests/libecalc/core/consumers/test_direct_emitter.py @@ -2,15 +2,15 @@ import pytest from libecalc import dto -from libecalc.core.consumers.direct_emitter import DirectEmitter +from libecalc.core.consumers.venting_emitter import VentingEmitter from libecalc.dto.base import ConsumerUserDefinedCategoryType from libecalc.expression import Expression -def test_direct_emitter(variables_map, temporal_emitter_model): - emitter_name = "direct_emitter" - direct_emitter = DirectEmitter( - dto.DirectEmitter( +def test_venting_emitter(variables_map, temporal_emitter_model): + emitter_name = "venting_emitter" + venting_emitter = VentingEmitter( + dto.VentingEmitter( name=emitter_name, emitter_model=temporal_emitter_model, user_defined_category={datetime(1900, 1, 1): ConsumerUserDefinedCategoryType.COLD_VENTING_FUGITIVE}, @@ -19,7 +19,7 @@ def test_direct_emitter(variables_map, temporal_emitter_model): ) ) - emissions = direct_emitter.evaluate(variables_map=variables_map) + emissions = venting_emitter.evaluate(variables_map=variables_map) emissions_ch4 = emissions["ch4"] diff --git a/src/tests/libecalc/dto/test_categories.py b/src/tests/libecalc/dto/test_categories.py index 204a583f2d..f1b1dfec5e 100644 --- a/src/tests/libecalc/dto/test_categories.py +++ b/src/tests/libecalc/dto/test_categories.py @@ -15,7 +15,7 @@ class TestCategories: - def test_direct_emitter_categories(self): + def test_venting_emitter_categories(self): emitter_model = EmitterModel( regularity={datetime(2000, 1, 1): Expression.setup_from_expression(1)}, emission_rate=Expression.setup_from_expression(4), @@ -23,22 +23,22 @@ def test_direct_emitter_categories(self): # Check that illegal category raises error with pytest.raises(ValidationError) as exc_info: - dto.components.DirectEmitter( + dto.components.VentingEmitter( name="test", regularity={datetime(2000, 1, 1): Expression.setup_from_expression(1)}, emission_name="CH4", emitter_model={datetime(2000, 1, 1): emitter_model}, - user_defined_category={datetime(2000, 1, 1): "DIRECT-EMISSIONS"}, + user_defined_category={datetime(2000, 1, 1): "VENTING-EMISSIONS"}, ) exception: ValidationError = typing.cast(ValidationError, exc_info.value) assert ( exception.errors()[0]["msg"] - == "CATEGORY: DIRECT-EMISSIONS is not allowed for DirectEmitter with the name test. Valid categories are: ['BASE-LOAD', 'COLD-VENTING-FUGITIVE', 'COMPRESSOR', 'FIXED-PRODUCTION-LOAD', 'FLARE', 'MISCELLANEOUS', 'PUMP', 'GAS-DRIVEN-COMPRESSOR', 'TURBINE-GENERATOR', 'POWER-FROM-SHORE', 'OFFSHORE-WIND', 'LOADING', 'STORAGE', 'STEAM-TURBINE-GENERATOR', 'BOILER', 'HEATER']" + == "CATEGORY: VENTING-EMISSIONS is not allowed for VentingEmitter with the name test. Valid categories are: ['BASE-LOAD', 'COLD-VENTING-FUGITIVE', 'COMPRESSOR', 'FIXED-PRODUCTION-LOAD', 'FLARE', 'MISCELLANEOUS', 'PUMP', 'GAS-DRIVEN-COMPRESSOR', 'TURBINE-GENERATOR', 'POWER-FROM-SHORE', 'OFFSHORE-WIND', 'LOADING', 'STORAGE', 'STEAM-TURBINE-GENERATOR', 'BOILER', 'HEATER']" ) # Check that lower case raises error with pytest.raises(ValidationError) as exc_info: - dto.components.DirectEmitter( + dto.components.VentingEmitter( name="test", regularity={datetime(2000, 1, 1): Expression.setup_from_expression(1)}, emission_name="CH4", @@ -49,12 +49,12 @@ def test_direct_emitter_categories(self): exception: ValidationError = typing.cast(ValidationError, exc_info.value) assert ( exception.errors()[0]["msg"] - == "CATEGORY: fuel-gas is not allowed for DirectEmitter with the name test. Valid categories are: ['BASE-LOAD', 'COLD-VENTING-FUGITIVE', 'COMPRESSOR', 'FIXED-PRODUCTION-LOAD', 'FLARE', 'MISCELLANEOUS', 'PUMP', 'GAS-DRIVEN-COMPRESSOR', 'TURBINE-GENERATOR', 'POWER-FROM-SHORE', 'OFFSHORE-WIND', 'LOADING', 'STORAGE', 'STEAM-TURBINE-GENERATOR', 'BOILER', 'HEATER']" + == "CATEGORY: fuel-gas is not allowed for VentingEmitter with the name test. Valid categories are: ['BASE-LOAD', 'COLD-VENTING-FUGITIVE', 'COMPRESSOR', 'FIXED-PRODUCTION-LOAD', 'FLARE', 'MISCELLANEOUS', 'PUMP', 'GAS-DRIVEN-COMPRESSOR', 'TURBINE-GENERATOR', 'POWER-FROM-SHORE', 'OFFSHORE-WIND', 'LOADING', 'STORAGE', 'STEAM-TURBINE-GENERATOR', 'BOILER', 'HEATER']" ) # Check that empty raises error with pytest.raises(ValidationError) as exc_info: - dto.components.DirectEmitter( + dto.components.VentingEmitter( name="test", regularity={datetime(2000, 1, 1): Expression.setup_from_expression(1)}, emission_name="CH4", @@ -65,12 +65,12 @@ def test_direct_emitter_categories(self): exception: ValidationError = typing.cast(ValidationError, exc_info.value) assert ( exception.errors()[0]["msg"] - == "CATEGORY: is not allowed for DirectEmitter with the name test. Valid categories are: ['BASE-LOAD', 'COLD-VENTING-FUGITIVE', 'COMPRESSOR', 'FIXED-PRODUCTION-LOAD', 'FLARE', 'MISCELLANEOUS', 'PUMP', 'GAS-DRIVEN-COMPRESSOR', 'TURBINE-GENERATOR', 'POWER-FROM-SHORE', 'OFFSHORE-WIND', 'LOADING', 'STORAGE', 'STEAM-TURBINE-GENERATOR', 'BOILER', 'HEATER']" + == "CATEGORY: is not allowed for VentingEmitter with the name test. Valid categories are: ['BASE-LOAD', 'COLD-VENTING-FUGITIVE', 'COMPRESSOR', 'FIXED-PRODUCTION-LOAD', 'FLARE', 'MISCELLANEOUS', 'PUMP', 'GAS-DRIVEN-COMPRESSOR', 'TURBINE-GENERATOR', 'POWER-FROM-SHORE', 'OFFSHORE-WIND', 'LOADING', 'STORAGE', 'STEAM-TURBINE-GENERATOR', 'BOILER', 'HEATER']" ) # Check that underscore raises error with pytest.raises(ValidationError) as exc_info: - dto.components.DirectEmitter( + dto.components.VentingEmitter( name="test", regularity={datetime(2000, 1, 1): Expression.setup_from_expression(1)}, emission_name="CH4", @@ -81,12 +81,12 @@ def test_direct_emitter_categories(self): exception: ValidationError = typing.cast(ValidationError, exc_info.value) assert ( exception.errors()[0]["msg"] - == "CATEGORY: FUEL_GAS is not allowed for DirectEmitter with the name test. Valid categories are: ['BASE-LOAD', 'COLD-VENTING-FUGITIVE', 'COMPRESSOR', 'FIXED-PRODUCTION-LOAD', 'FLARE', 'MISCELLANEOUS', 'PUMP', 'GAS-DRIVEN-COMPRESSOR', 'TURBINE-GENERATOR', 'POWER-FROM-SHORE', 'OFFSHORE-WIND', 'LOADING', 'STORAGE', 'STEAM-TURBINE-GENERATOR', 'BOILER', 'HEATER']" + == "CATEGORY: FUEL_GAS is not allowed for VentingEmitter with the name test. Valid categories are: ['BASE-LOAD', 'COLD-VENTING-FUGITIVE', 'COMPRESSOR', 'FIXED-PRODUCTION-LOAD', 'FLARE', 'MISCELLANEOUS', 'PUMP', 'GAS-DRIVEN-COMPRESSOR', 'TURBINE-GENERATOR', 'POWER-FROM-SHORE', 'OFFSHORE-WIND', 'LOADING', 'STORAGE', 'STEAM-TURBINE-GENERATOR', 'BOILER', 'HEATER']" ) # Check that correct category is ok assert ( - dto.components.DirectEmitter( + dto.components.VentingEmitter( name="test", regularity={datetime(2000, 1, 1): Expression.setup_from_expression(1)}, emission_name="CH4", diff --git a/src/tests/libecalc/dto/utils/test_aggregators.py b/src/tests/libecalc/dto/utils/test_aggregators.py index aae8f1ddff..b1993447d0 100644 --- a/src/tests/libecalc/dto/utils/test_aggregators.py +++ b/src/tests/libecalc/dto/utils/test_aggregators.py @@ -78,7 +78,7 @@ def direct_fuel_consumer(name: str, name_fuel: str, co2_factor: float, fuel_rate return dto.FuelConsumer( name=name, - component_type=dto.components.ComponentType.DIRECT_EMITTER, + component_type=dto.components.ComponentType.VENTING_EMITTER, fuel={datetime(2024, 1, 1): fuel(name=name_fuel, co2_factor=co2_factor)}, regularity={datetime(1900, 1, 1): Expression.setup_from_expression(1)}, user_defined_category={datetime(2024, 1, 1): dto.components.ConsumerUserDefinedCategoryType.MISCELLANEOUS}, diff --git a/src/tests/libecalc/input/validation/snapshots/test_validation_json_schemas/test_json_schema_changed/schemas.json b/src/tests/libecalc/input/validation/snapshots/test_validation_json_schemas/test_json_schema_changed/schemas.json index 2544437ec8..7e646ddfb5 100644 --- a/src/tests/libecalc/input/validation/snapshots/test_validation_json_schemas/test_json_schema_changed/schemas.json +++ b/src/tests/libecalc/input/validation/snapshots/test_validation_json_schemas/test_json_schema_changed/schemas.json @@ -453,59 +453,6 @@ "title": "Density", "type": "object" }, - "YamlDirectEmitter": { - "additionalProperties": false, - "properties": { - "CATEGORY": { - "anyOf": [ - { - "$ref": "#/definitions/ConsumerUserDefinedCategoryType" - }, - { - "additionalProperties": { - "$ref": "#/definitions/ConsumerUserDefinedCategoryType" - }, - "type": "object" - } - ], - "description": "Output category/tag.\n\nhttps://test.ecalc.equinor.com/docs/docs/modelling/keywords/CATEGORY", - "title": "CATEGORY" - }, - "EMISSION_NAME": { - "description": "Name of emission", - "title": "EMISSION_NAME", - "type": "string" - }, - "EMITTER_MODEL": { - "anyOf": [ - { - "$ref": "#/definitions/YamlEmitterModel" - }, - { - "additionalProperties": { - "$ref": "#/definitions/YamlEmitterModel" - }, - "type": "object" - } - ], - "description": "The emitter model.\n\nhttps://test.ecalc.equinor.com/docs/docs/modelling/keywords/EMITTER_MODEL", - "title": "EMITTER_MODEL" - }, - "NAME": { - "description": "Name of the emitter.\n\nhttps://test.ecalc.equinor.com/docs/docs/modelling/keywords/NAME", - "title": "NAME", - "type": "string" - } - }, - "required": [ - "NAME", - "CATEGORY", - "EMISSION_NAME", - "EMITTER_MODEL" - ], - "title": "YamlDirectEmitter", - "type": "object" - }, "YamlElectricityConsumer": { "additionalProperties": false, "properties": { @@ -851,14 +798,6 @@ "description": "Output category/tag.\n\nhttps://test.ecalc.equinor.com/docs/docs/modelling/keywords/CATEGORY", "title": "CATEGORY" }, - "DIRECT_EMITTERS": { - "description": "Covers the direct emissions on the installation that are not consuming energy", - "items": { - "$ref": "#/definitions/YamlDirectEmitter" - }, - "title": "DIRECT_EMITTERS", - "type": "array" - }, "FUEL": { "anyOf": [ { @@ -1001,6 +940,14 @@ ], "description": "Regularity of the installation can be specified by a single number or as an expression. USE WITH CARE.\n\nhttps://test.ecalc.equinor.com/docs/docs/modelling/keywords/REGULARITY", "title": "REGULARITY" + }, + "VENTING_EMITTERS": { + "description": "Covers the direct emissions on the installation that are not consuming energy", + "items": { + "$ref": "#/definitions/YamlVentingEmitter" + }, + "title": "VENTING_EMITTERS", + "type": "array" } }, "required": [ @@ -1546,6 +1493,59 @@ ], "title": "YamlTrain[YamlCompressor]", "type": "object" + }, + "YamlVentingEmitter": { + "additionalProperties": false, + "properties": { + "CATEGORY": { + "anyOf": [ + { + "$ref": "#/definitions/ConsumerUserDefinedCategoryType" + }, + { + "additionalProperties": { + "$ref": "#/definitions/ConsumerUserDefinedCategoryType" + }, + "type": "object" + } + ], + "description": "Output category/tag.\n\nhttps://test.ecalc.equinor.com/docs/docs/modelling/keywords/CATEGORY", + "title": "CATEGORY" + }, + "EMISSION_NAME": { + "description": "Name of emission", + "title": "EMISSION_NAME", + "type": "string" + }, + "EMITTER_MODEL": { + "anyOf": [ + { + "$ref": "#/definitions/YamlEmitterModel" + }, + { + "additionalProperties": { + "$ref": "#/definitions/YamlEmitterModel" + }, + "type": "object" + } + ], + "description": "The emitter model.\n\nhttps://test.ecalc.equinor.com/docs/docs/modelling/keywords/EMITTER_MODEL", + "title": "EMITTER_MODEL" + }, + "NAME": { + "description": "Name of the emitter.\n\nhttps://test.ecalc.equinor.com/docs/docs/modelling/keywords/NAME", + "title": "NAME", + "type": "string" + } + }, + "required": [ + "NAME", + "CATEGORY", + "EMISSION_NAME", + "EMITTER_MODEL" + ], + "title": "YamlVentingEmitter", + "type": "object" } }, "description": "An eCalc\u2122 yaml file", diff --git a/src/tests/libecalc/integration/snapshots/test_all_energy_usage_models/test_all_results/all_energy_usage_models_v3.json b/src/tests/libecalc/integration/snapshots/test_all_energy_usage_models/test_all_results/all_energy_usage_models_v3.json index a792c41e4d..ded328834f 100644 --- a/src/tests/libecalc/integration/snapshots/test_all_energy_usage_models/test_all_results/all_energy_usage_models_v3.json +++ b/src/tests/libecalc/integration/snapshots/test_all_energy_usage_models/test_all_results/all_energy_usage_models_v3.json @@ -23438,7 +23438,7 @@ ] } }, - "0dd5488b915db39da83975816044443e": { + "2f86c1c7d7c2d739da3ed294d8ae88ca": { "ch4": { "name": "ch4", "rate": {