Skip to content

Commit

Permalink
feat(thermals): new fields for v8.7 are named cost_generation, `eff…
Browse files Browse the repository at this point in the history
…iciency` and `variable_o_m_cost`
  • Loading branch information
laurent-laporte-pro committed Mar 11, 2024
1 parent b3b4bc0 commit 4e3beda
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 33 deletions.
33 changes: 25 additions & 8 deletions antarest/study/storage/rawstudy/model/filesystem/config/thermal.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class LocalTSGenerationBehavior(EnumIgnoreCase):
FORCE_NO_GENERATION = "force no generation"
FORCE_GENERATION = "force generation"

def __repr__(self) -> str:
def __repr__(self) -> str: # pragma: no cover
return f"{self.__class__.__name__}.{self.name}"


Expand All @@ -49,7 +49,7 @@ class LawOption(EnumIgnoreCase):
UNIFORM = "uniform"
GEOMETRIC = "geometric"

def __repr__(self) -> str:
def __repr__(self) -> str: # pragma: no cover
return f"{self.__class__.__name__}.{self.name}"


Expand All @@ -70,7 +70,7 @@ class ThermalClusterGroup(EnumIgnoreCase):
OTHER3 = "Other 3"
OTHER4 = "Other 4"

def __repr__(self) -> str:
def __repr__(self) -> str: # pragma: no cover
return f"{self.__class__.__name__}.{self.name}"

@classmethod
Expand Down Expand Up @@ -274,16 +274,29 @@ class Thermal860Properties(ThermalProperties):
)


# noinspection SpellCheckingInspection
class Thermal870Properties(Thermal860Properties):
"""
Thermal cluster configuration model for study in version 8.7 or above.
"""

costgeneration: ThermalCostGeneration = Field(default=ThermalCostGeneration.SET_MANUALLY)
efficiency: float = Field(default=100.0, ge=0, description="Efficiency (%)")
variableomcost: float = Field(
default=0, description="Operating and Maintenance Cost (€/MWh)"
) # Even if it's a cost it could be negative.
cost_generation: ThermalCostGeneration = Field(
default=ThermalCostGeneration.SET_MANUALLY,
alias="costgeneration",
description="Cost generation option",
)
efficiency: float = Field(
default=100.0,
ge=0,
le=100,
description="Efficiency (%)",
)
# Even if `variableomcost` is a cost it could be negative.
variable_o_m_cost: float = Field(
default=0.0,
description="Operating and Maintenance Cost (€/MWh)",
alias="variableomcost",
)


class ThermalConfig(ThermalProperties, IgnoreCaseIdentifier):
Expand Down Expand Up @@ -350,6 +363,10 @@ class Thermal870Config(Thermal870Properties, IgnoreCaseIdentifier):
0.0
>>> cl.efficiency
97.0
>>> cl.variable_o_m_cost
0.0
>>> cl.cost_generation == ThermalCostGeneration.SET_MANUALLY
True
"""


Expand Down
21 changes: 11 additions & 10 deletions tests/integration/study_data_blueprint/test_thermal.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,25 +289,26 @@ def test_lifecycle(

assert task.status == TaskStatus.COMPLETED, task

# =============================
# =================================
# UPDATE EXPECTED POLLUTANTS LIST
# =============================
# =================================

# noinspection SpellCheckingInspection
pollutants_names = ["nh3", "nmvoc", "nox", "op1", "op2", "op3", "op4", "op5", "pm10", "pm25", "pm5", "so2"]
pollutants_values = 0.0 if version >= 860 else None
for existing_cluster in EXISTING_CLUSTERS:
existing_cluster.update({p: pollutants_values for p in pollutants_names})
existing_cluster.update(
{
"costgeneration": "SetManually" if version == 870 else None,
"costGeneration": "SetManually" if version == 870 else None,
"efficiency": 100.0 if version == 870 else None,
"variableomcost": 0.0 if version == 870 else None,
"variableOMCost": 0.0 if version == 870 else None,
}
)

# =============================
# ==========================
# THERMAL CLUSTER CREATION
# =============================
# ==========================

area_id = transform_name_to_id("FR")
fr_gas_conventional = "FR_Gas conventional"
Expand Down Expand Up @@ -358,9 +359,9 @@ def test_lifecycle(
fr_gas_conventional_cfg = {
**fr_gas_conventional_cfg,
**{
"costgeneration": "SetManually" if version == 870 else None,
"costGeneration": "SetManually" if version == 870 else None,
"efficiency": 100.0 if version == 870 else None,
"variableomcost": 0.0 if version == 870 else None,
"variableOMCost": 0.0 if version == 870 else None,
},
}
assert res.json() == fr_gas_conventional_cfg
Expand All @@ -373,9 +374,9 @@ def test_lifecycle(
assert res.status_code == 200, res.json()
assert res.json() == fr_gas_conventional_cfg

# =============================
# ==========================
# THERMAL CLUSTER MATRICES
# =============================
# ==========================

matrix = np.random.randint(0, 2, size=(8760, 1)).tolist()
matrix_path = f"input/thermal/prepro/{area_id}/{fr_gas_conventional_id.lower()}/data"
Expand Down
4 changes: 2 additions & 2 deletions tests/integration/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -1780,9 +1780,9 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id:
"op3": 3,
"op4": 2.4,
"op5": 0,
"costgeneration": "SetManually",
"costGeneration": "SetManually",
"efficiency": 100.0,
"variableomcost": 0.0,
"variableOMCost": 0.0,
}
res = client.put(
# This URL is deprecated, but we must check it for backward compatibility.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
Thermal860Config,
Thermal870Config,
ThermalConfig,
ThermalCostGeneration,
)
from tests.storage.business.assets import ASSETS_DIR

Expand Down Expand Up @@ -347,7 +348,13 @@ def test_parse_thermal_860(tmp_path: Path, version, caplog) -> None:
expected = [
Thermal870Config(id="t1", name="t1"),
Thermal870Config(
id="t2", name="t2", co2=156, nh3=456, costgeneration="SetManually", efficiency=100.0, variableomcost=0
id="t2",
name="t2",
co2=156,
nh3=456,
cost_generation=ThermalCostGeneration.SET_MANUALLY,
efficiency=100.0,
variable_o_m_cost=0,
),
]
assert not caplog.text
Expand Down
52 changes: 40 additions & 12 deletions tests/study/business/areas/test_thermal_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,34 @@
from tests.study.business.areas.assets import ASSETS_DIR


class TestThermalClusterGroup:
"""
Tests for the `ThermalClusterGroup` enumeration.
"""

def test_nominal_case(self):
"""
When a group is read from a INI file, the group should be the same as the one in the file.
"""
group = ThermalClusterGroup("gas") # different case: original is "Gas"
assert group == ThermalClusterGroup.GAS

def test_unknown(self):
"""
When an unknown group is read from a INI file, the group should be `OTHER1`.
Note that this is the current behavior in Antares Solver.
"""
group = ThermalClusterGroup("unknown")
assert group == ThermalClusterGroup.OTHER1

def test_invalid_type(self):
"""
When an invalid type is used to create a group, a `ValueError` should be raised.
"""
with pytest.raises(ValueError):
ThermalClusterGroup(123)


@pytest.fixture(name="zip_legacy_path")
def zip_legacy_path_fixture(tmp_path: Path) -> Path:
target_dir = tmp_path.joinpath("resources")
Expand Down Expand Up @@ -142,9 +170,9 @@ def test_get_cluster__study_legacy(
"op4": None,
"op5": None,
# These values are also None as they are defined in v8.7+
"costgeneration": None,
"costGeneration": None,
"efficiency": None,
"variableomcost": None,
"variableOMCost": None,
}
assert actual == expected

Expand Down Expand Up @@ -207,9 +235,9 @@ def test_get_clusters__study_legacy(
"op3": None,
"op4": None,
"op5": None,
"costgeneration": None,
"costGeneration": None,
"efficiency": None,
"variableomcost": None,
"variableOMCost": None,
},
{
"id": "on and must 2",
Expand Down Expand Up @@ -246,9 +274,9 @@ def test_get_clusters__study_legacy(
"op3": None,
"op4": None,
"op5": None,
"costgeneration": None,
"costGeneration": None,
"efficiency": None,
"variableomcost": None,
"variableOMCost": None,
},
{
"id": "2 avail and must 2",
Expand Down Expand Up @@ -285,9 +313,9 @@ def test_get_clusters__study_legacy(
"op3": None,
"op4": None,
"op5": None,
"costgeneration": None,
"costGeneration": None,
"efficiency": None,
"variableomcost": None,
"variableOMCost": None,
},
]
assert actual == expected
Expand Down Expand Up @@ -356,9 +384,9 @@ def test_create_cluster__study_legacy(
"pm25": None,
"pm5": None,
"so2": None,
"costgeneration": None,
"costGeneration": None,
"efficiency": None,
"variableomcost": None,
"variableOMCost": None,
"spinning": 0.0,
"spreadCost": 0.0,
"startupCost": 0.0,
Expand Down Expand Up @@ -424,9 +452,9 @@ def test_update_cluster(
"op4": None,
"op5": None,
# These values are also None as they are defined in v8.7+
"costgeneration": None,
"costGeneration": None,
"efficiency": None,
"variableomcost": None,
"variableOMCost": None,
}
assert actual == expected

Expand Down

0 comments on commit 4e3beda

Please sign in to comment.