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

refactor(thermal, renewable): create user classes #79

Merged
merged 41 commits into from
Feb 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
d4f24d3
refactor(thermal, renewable): create user classes
MartinBelthle Feb 11, 2025
c1233a4
moving thigns
MartinBelthle Feb 11, 2025
275df55
commit
MartinBelthle Feb 11, 2025
93a1cc3
continue work on thermal
MartinBelthle Feb 11, 2025
6c788a2
a
MartinBelthle Feb 11, 2025
005a308
eh
MartinBelthle Feb 11, 2025
06ff10d
continue work
MartinBelthle Feb 11, 2025
4e91640
Merge branch 'main' into refactor/create_user_class_for_thermal
MartinBelthle Feb 11, 2025
6e81d5d
ifx issues with thermal
MartinBelthle Feb 11, 2025
1c5abfa
ifx issues with thermal
MartinBelthle Feb 11, 2025
0496e8c
use update class for update
MartinBelthle Feb 11, 2025
77f9fd7
start work on renewables
MartinBelthle Feb 11, 2025
9b79290
refactor
MartinBelthle Feb 11, 2025
77645c2
refactor
MartinBelthle Feb 11, 2025
98d5d3f
refactor
MartinBelthle Feb 11, 2025
8ae5953
hello
MartinBelthle Feb 11, 2025
827a4fa
we're seeing the end
MartinBelthle Feb 11, 2025
81d710d
fix imports
MartinBelthle Feb 11, 2025
37e47d8
fix imports
MartinBelthle Feb 11, 2025
07d874a
aagaib
MartinBelthle Feb 11, 2025
6c20c72
ref
MartinBelthle Feb 11, 2025
5052b55
ref
MartinBelthle Feb 11, 2025
5f970c4
mypy is okay :)
MartinBelthle Feb 11, 2025
cd2eb1e
fix imports inside tests
MartinBelthle Feb 11, 2025
b855dbd
12 test failing
MartinBelthle Feb 11, 2025
602f6b3
a bit better
MartinBelthle Feb 11, 2025
0022542
continue
MartinBelthle Feb 11, 2025
5062442
11 test failing
MartinBelthle Feb 11, 2025
99eafd7
8 local test failing
MartinBelthle Feb 11, 2025
0af1a40
fix some
MartinBelthle Feb 11, 2025
18730a0
4 failing tests
MartinBelthle Feb 11, 2025
73e796d
2 failing tests
MartinBelthle Feb 11, 2025
45819eb
fix one test
MartinBelthle Feb 11, 2025
3d5f7b3
fix one test
MartinBelthle Feb 11, 2025
ca87674
fix test
MartinBelthle Feb 11, 2025
46e222e
tets
MartinBelthle Feb 11, 2025
df8b7f8
tets
MartinBelthle Feb 11, 2025
5824dce
tets
MartinBelthle Feb 11, 2025
52ba8a5
make the tets work
MartinBelthle Feb 11, 2025
f0f353d
merge with main
MartinBelthle Feb 11, 2025
fe1c5bc
merge with main
MartinBelthle Feb 11, 2025
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
25 changes: 9 additions & 16 deletions src/antares/craft/model/area.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,24 +256,17 @@ def ui(self) -> AreaUi:
return self._ui

def create_thermal_cluster(
self, thermal_name: str, properties: Optional[ThermalClusterProperties] = None
) -> ThermalCluster:
thermal = self._area_service.create_thermal_cluster(self.id, thermal_name, properties)
self._thermals[thermal.id] = thermal
return thermal

def create_thermal_cluster_with_matrices(
self,
cluster_name: str,
parameters: ThermalClusterProperties,
prepro: Optional[pd.DataFrame],
modulation: Optional[pd.DataFrame],
series: Optional[pd.DataFrame],
CO2Cost: Optional[pd.DataFrame],
fuelCost: Optional[pd.DataFrame],
thermal_name: str,
properties: Optional[ThermalClusterProperties] = None,
prepro: Optional[pd.DataFrame] = None,
modulation: Optional[pd.DataFrame] = None,
series: Optional[pd.DataFrame] = None,
co2_cost: Optional[pd.DataFrame] = None,
fuel_cost: Optional[pd.DataFrame] = None,
) -> ThermalCluster:
thermal = self._area_service.create_thermal_cluster_with_matrices(
self.id, cluster_name, parameters, prepro, modulation, series, CO2Cost, fuelCost
thermal = self._area_service.create_thermal_cluster(
self.id, thermal_name, properties, prepro, modulation, series, co2_cost, fuel_cost
)
self._thermals[thermal.id] = thermal
return thermal
Expand Down
27 changes: 12 additions & 15 deletions src/antares/craft/model/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,31 @@
# SPDX-License-Identifier: MPL-2.0
#
# This file is part of the Antares project.

from dataclasses import dataclass
from typing import Optional

from pydantic import BaseModel
from pydantic.alias_generators import to_camel


class ClusterProperties(BaseModel, extra="forbid", populate_by_name=True, alias_generator=to_camel):
@dataclass
class ClusterProperties:
"""
Common properties for thermal and renewable clusters
"""

# Activity status:
# - True: the plant may generate.
# - False: not yet commissioned, moth-balled, etc.
enabled: bool = True

unit_count: int = 1
nominal_capacity: float = 0

@property
def installed_capacity(self) -> Optional[float]:
if self.unit_count is None or self.nominal_capacity is None:
return None
def installed_capacity(self) -> float:
return self.unit_count * self.nominal_capacity

@property
def enabled_capacity(self) -> Optional[float]:
if self.enabled is None or self.installed_capacity is None:
return None
def enabled_capacity(self) -> float:
return self.enabled * self.installed_capacity


@dataclass
class ClusterPropertiesUpdate:
enabled: Optional[bool] = None
unit_count: Optional[int] = None
nominal_capacity: Optional[float] = None
42 changes: 9 additions & 33 deletions src/antares/craft/model/renewable.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,14 @@
# SPDX-License-Identifier: MPL-2.0
#
# This file is part of the Antares project.

from dataclasses import dataclass
from enum import Enum
from typing import Optional

import pandas as pd

from antares.craft.model.cluster import ClusterProperties
from antares.craft.model.cluster import ClusterProperties, ClusterPropertiesUpdate
from antares.craft.service.base_services import BaseRenewableService
from antares.craft.tools.all_optional_meta import all_optional_model
from antares.craft.tools.contents_tool import transform_name_to_id


Expand Down Expand Up @@ -55,39 +54,16 @@ class TimeSeriesInterpretation(Enum):
PRODUCTION_FACTOR = "production-factor"


class DefaultRenewableClusterProperties(ClusterProperties):
"""
Properties of a renewable cluster read from the configuration files.
"""

@dataclass
class RenewableClusterProperties(ClusterProperties):
group: RenewableClusterGroup = RenewableClusterGroup.OTHER1
ts_interpretation: TimeSeriesInterpretation = TimeSeriesInterpretation.POWER_GENERATION


@all_optional_model
class RenewableClusterProperties(DefaultRenewableClusterProperties):
pass


class RenewableClusterPropertiesLocal(DefaultRenewableClusterProperties):
renewable_name: str

@property
def ini_fields(self) -> dict[str, dict[str, str]]:
return {
self.renewable_name: {
"name": self.renewable_name,
"group": self.group.value,
"enabled": f"{self.enabled}".lower(),
"nominalcapacity": f"{self.nominal_capacity:.6f}",
"unitcount": f"{self.unit_count}",
"ts-interpretation": self.ts_interpretation.value,
}
}

def yield_renewable_cluster_properties(self) -> RenewableClusterProperties:
excludes = {"renewable_name", "ini_fields"}
return RenewableClusterProperties.model_validate(self.model_dump(mode="json", exclude=excludes))
@dataclass
class RenewableClusterPropertiesUpdate(ClusterPropertiesUpdate):
group: Optional[RenewableClusterGroup] = None
ts_interpretation: Optional[TimeSeriesInterpretation] = None


class RenewableCluster:
Expand Down Expand Up @@ -122,7 +98,7 @@ def id(self) -> str:
def properties(self) -> RenewableClusterProperties:
return self._properties

def update_properties(self, properties: RenewableClusterProperties) -> None:
def update_properties(self, properties: RenewableClusterPropertiesUpdate) -> None:
new_properties = self._renewable_service.update_renewable_properties(self, properties)
self._properties = new_properties

Expand Down
105 changes: 39 additions & 66 deletions src/antares/craft/model/thermal.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,14 @@
# SPDX-License-Identifier: MPL-2.0
#
# This file is part of the Antares project.

from dataclasses import dataclass
from enum import Enum
from typing import Optional

import pandas as pd

from antares.craft.model.cluster import ClusterProperties
from antares.craft.model.cluster import ClusterProperties, ClusterPropertiesUpdate
from antares.craft.service.base_services import BaseThermalService
from antares.craft.tools.all_optional_meta import all_optional_model
from antares.craft.tools.contents_tool import transform_name_to_id


Expand Down Expand Up @@ -65,12 +64,8 @@ class ThermalCostGeneration(Enum):
USE_COST_TIME_SERIES = "useCostTimeseries"


class DefaultThermalProperties(ClusterProperties):
"""
Thermal cluster configuration model.
This model describes the configuration parameters for a thermal cluster.
"""

@dataclass
class ThermalClusterProperties(ClusterProperties):
group: ThermalClusterGroup = ThermalClusterGroup.OTHER1
gen_ts: LocalTSGenerationBehavior = LocalTSGenerationBehavior.USE_GLOBAL
min_stable_power: float = 0
Expand All @@ -88,7 +83,6 @@ class DefaultThermalProperties(ClusterProperties):
startup_cost: float = 0
market_bid_cost: float = 0
co2: float = 0
# version 860
nh3: float = 0
so2: float = 0
nox: float = 0
Expand All @@ -101,66 +95,45 @@ class DefaultThermalProperties(ClusterProperties):
op3: float = 0
op4: float = 0
op5: float = 0
# version 870
cost_generation: ThermalCostGeneration = ThermalCostGeneration.SET_MANUALLY
efficiency: float = 100
variable_o_m_cost: float = 0


@all_optional_model
class ThermalClusterProperties(DefaultThermalProperties):
pass


class ThermalClusterPropertiesLocal(DefaultThermalProperties):
thermal_name: str

@property
def list_ini_fields(self) -> dict[str, dict[str, str]]:
return {
f"{self.thermal_name}": {
"group": self.group.value,
"name": self.thermal_name,
"enabled": f"{self.enabled}",
"unitcount": f"{self.unit_count}",
"nominalcapacity": f"{self.nominal_capacity:.6f}",
"gen-ts": self.gen_ts.value,
"min-stable-power": f"{self.min_stable_power:.6f}",
"min-up-time": f"{self.min_up_time}",
"min-down-time": f"{self.min_down_time}",
"must-run": f"{self.must_run}",
"spinning": f"{self.spinning:.6f}",
"volatility.forced": f"{self.volatility_forced:.6f}",
"volatility.planned": f"{self.volatility_planned:.6f}",
"law.forced": self.law_forced.value,
"law.planned": self.law_planned.value,
"marginal-cost": f"{self.marginal_cost:.6f}",
"spread-cost": f"{self.spread_cost:.6f}",
"fixed-cost": f"{self.fixed_cost:.6f}",
"startup-cost": f"{self.startup_cost:.6f}",
"market-bid-cost": f"{self.market_bid_cost:.6f}",
"co2": f"{self.co2:.6f}",
"nh3": f"{self.nh3:.6f}",
"so2": f"{self.so2:.6f}",
"nox": f"{self.nox:.6f}",
"pm2_5": f"{self.pm2_5:.6f}",
"pm5": f"{self.pm5:.6f}",
"pm10": f"{self.pm10:.6f}",
"nmvoc": f"{self.nmvoc:.6f}",
"op1": f"{self.op1:.6f}",
"op2": f"{self.op2:.6f}",
"op3": f"{self.op3:.6f}",
"op4": f"{self.op4:.6f}",
"op5": f"{self.op5:.6f}",
"costgeneration": self.cost_generation.value,
"efficiency": f"{self.efficiency:.6f}",
"variableomcost": f"{self.variable_o_m_cost:.6f}",
}
}

def yield_thermal_cluster_properties(self) -> ThermalClusterProperties:
excludes = {"thermal_name", "list_ini_fields"}
return ThermalClusterProperties.model_validate(self.model_dump(mode="json", exclude=excludes))
@dataclass
class ThermalClusterPropertiesUpdate(ClusterPropertiesUpdate):
group: Optional[ThermalClusterGroup] = None
gen_ts: Optional[LocalTSGenerationBehavior] = None
min_stable_power: Optional[float] = None
min_up_time: Optional[int] = None
min_down_time: Optional[int] = None
must_run: Optional[bool] = None
spinning: Optional[float] = None
volatility_forced: Optional[float] = None
volatility_planned: Optional[float] = None
law_forced: Optional[LawOption] = None
law_planned: Optional[LawOption] = None
marginal_cost: Optional[float] = None
spread_cost: Optional[float] = None
fixed_cost: Optional[float] = None
startup_cost: Optional[float] = None
market_bid_cost: Optional[float] = None
co2: Optional[float] = None
nh3: Optional[float] = None
so2: Optional[float] = None
nox: Optional[float] = None
pm2_5: Optional[float] = None
pm5: Optional[float] = None
pm10: Optional[float] = None
nmvoc: Optional[float] = None
op1: Optional[float] = None
op2: Optional[float] = None
op3: Optional[float] = None
op4: Optional[float] = None
op5: Optional[float] = None
cost_generation: Optional[ThermalCostGeneration] = None
efficiency: Optional[float] = None
variable_o_m_cost: Optional[float] = None


class ThermalClusterMatrixName(Enum):
Expand Down Expand Up @@ -203,7 +176,7 @@ def id(self) -> str:
def properties(self) -> ThermalClusterProperties:
return self._properties

def update_properties(self, properties: ThermalClusterProperties) -> None:
def update_properties(self, properties: ThermalClusterPropertiesUpdate) -> None:
new_properties = self._thermal_service.update_thermal_properties(self, properties)
self._properties = new_properties

Expand Down
Loading