Skip to content

Commit e1b2009

Browse files
authored
Pypsa e2e tests (#114)
* starting work for e2e tests with Antares-Modeler * e2e tests * remove series * refacto * refacto * refacto * format * format
1 parent d8bac2f commit e1b2009

8 files changed

Lines changed: 145 additions & 3610 deletions

File tree

src/andromede/libs/pypsa_models/pypsa_models.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,10 @@ library:
7474
#- id : type # This parameter is not used in the Gems model
7575
- id: p_set
7676
time-dependent: true
77-
scenario-dependent: true
77+
scenario-dependent: false # Since PyPSA v0.x does not manage simultaneous scenarios at this point
7878
- id: q_set
7979
time-dependent: true
80-
scenario-dependent: true
80+
scenario-dependent: false # Since PyPSA v0.x does not manage simultaneous scenarios at this point
8181
- id: sign #default value = -1
8282
time-dependent: false
8383
scenario-dependent: false
@@ -338,7 +338,7 @@ library:
338338
scenario-dependent: false
339339
- id: inflow
340340
time-dependent: true
341-
scenario-dependent: true
341+
scenario-dependent: false
342342
##Additional parameters that are not stored in the PyPSA object, but in a Carrier object
343343
- id: emission_factor
344344
time_dependent: false

src/andromede/pypsa_converter/pypsa_converter.py

Lines changed: 63 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from math import inf
1515
from pathlib import Path
1616

17+
import numpy as np
1718
import pandas as pd
1819
from pandas import DataFrame
1920
from pypsa import Network
@@ -68,6 +69,7 @@ def __init__(
6869
logger: logging.Logger,
6970
system_dir: Path,
7071
series_dir: Path,
72+
series_file_format: str,
7173
):
7274
"""
7375
Initialize processor
@@ -79,13 +81,25 @@ def __init__(
7981
self.pypsalib_id = "pypsa_models"
8082
self.null_carrier_id = "null"
8183
self.system_name = pypsa_network.name
84+
self.series_file_format = series_file_format
8285

86+
self.pypsa_components = [
87+
"buses",
88+
"loads",
89+
"generators",
90+
"stores",
91+
"storage_units",
92+
"links",
93+
"lines",
94+
"transformers",
95+
]
8396
self._pypsa_network_assertion()
8497
self._pypsa_network_preprocessing()
85-
self._preprocess_pypsa_components("generators", "p_nom")
86-
self._preprocess_pypsa_components("stores", "e_nom")
87-
self._preprocess_pypsa_components("storage_units", "p_nom")
88-
self._preprocess_pypsa_components("links", "p_nom")
98+
self._preprocess_pypsa_components("loads", False, "/")
99+
self._preprocess_pypsa_components("generators", True, "p_nom")
100+
self._preprocess_pypsa_components("stores", True, "e_nom")
101+
self._preprocess_pypsa_components("storage_units", True, "p_nom")
102+
self._preprocess_pypsa_components("links", True, "p_nom")
89103

90104
self.pypsa_components_data: dict[str, PyPSAComponentData] = {}
91105
self._register_pypsa_components()
@@ -111,6 +125,9 @@ def _pypsa_network_assertion(self) -> None:
111125
### PyPSA components : Links
112126
if not (all((self.pypsa_network.links["active"] == 1))):
113127
raise ValueError(f"Converter supports only Links with active = 1")
128+
### PyPSA components : Lines
129+
if not len(self.pypsa_network.lines) == 0:
130+
raise ValueError(f"Converter does not support Lines yet")
114131
### PyPSA components : Storage Units
115132
if not (all((self.pypsa_network.links["active"] == 1))):
116133
raise ValueError(f"Converter supports only Storage Units with active = 1")
@@ -146,6 +163,22 @@ def _pypsa_network_assertion(self) -> None:
146163
== "co2_emissions"
147164
)
148165

166+
def _rename_buses(self) -> None:
167+
### Rename PyPSA buses, to delete spaces
168+
if len(self.pypsa_network.buses) > 0:
169+
self.pypsa_network.buses.index = self.pypsa_network.buses.index.str.replace(
170+
" ", "_"
171+
)
172+
for _, val in self.pypsa_network.buses_t.items():
173+
val.columns = val.columns.str.replace(" ", "_")
174+
### Update the 'bus' columns for the different types of PyPSA components
175+
for component_type in self.pypsa_components:
176+
df = getattr(self.pypsa_network, component_type)
177+
if len(df) > 0:
178+
for col in ["bus", "bus0", "bus1"]:
179+
if col in df.columns:
180+
df[col] = df[col].str.replace(" ", "_")
181+
149182
def _pypsa_network_preprocessing(self) -> None:
150183
###Add fictitious carrier
151184
self.pypsa_network.add(
@@ -157,32 +190,31 @@ def _pypsa_network_preprocessing(self) -> None:
157190
self.pypsa_network.carriers[
158191
"carrier"
159192
] = self.pypsa_network.carriers.index.values
160-
### Rename PyPSA components, to make sure that the names are uniques (used as id in the Gems model)
161-
self.pypsa_network.loads.index = (
162-
self.pypsa_network.loads.index.astype(str) + "_load"
163-
)
164-
for key, val in self.pypsa_network.loads_t.items():
165-
val.columns = val.columns + "_load"
166-
167-
self.pypsa_network.generators.index = (
168-
self.pypsa_network.generators.index.astype(str) + "_generator"
169-
)
170-
for key, val in self.pypsa_network.generators_t.items():
171-
val.columns = val.columns + "_generator"
193+
self._rename_buses()
172194

173-
self.pypsa_network.storage_units.index = (
174-
self.pypsa_network.storage_units.index.astype(str) + "_storage"
175-
)
176-
for key, val in self.pypsa_network.storage_units_t.items():
177-
val.columns = val.columns + "_storage"
195+
def _rename_pypsa_components(self, component_type: str) -> None:
196+
df = getattr(self.pypsa_network, component_type)
197+
if len(df) == 0:
198+
return
199+
### Rename PyPSA components, to make sure that the names are uniques (used as id in the Gems model)
200+
prefix = component_type[:-1]
201+
df.index = prefix + "_" + df.index.str.replace(" ", "_")
202+
dictionnary = getattr(self.pypsa_network, component_type + "_t")
203+
for _, val in dictionnary.items():
204+
val.columns = prefix + "_" + val.columns.str.replace(" ", "_")
178205

179-
self.pypsa_network.stores.index = (
180-
self.pypsa_network.stores.index.astype(str) + "_store"
181-
)
182-
for key, val in self.pypsa_network.stores_t.items():
183-
val.columns = val.columns + "_store"
206+
def _fix_capacities(self, component_type: str, capa_str: str) -> None:
207+
df = getattr(self.pypsa_network, component_type)
208+
if len(df) == 0:
209+
return
210+
### Adding min and max capacities to non-extendable objects
211+
for field in [capa_str + "_min", capa_str + "_max"]:
212+
df.loc[df[capa_str + "_extendable"] == False, field] = df[capa_str]
213+
df.loc[df[capa_str + "_extendable"] == False, "capital_cost"] = 0.0
184214

185-
def _preprocess_pypsa_components(self, component_type: str, capa_str: str) -> None:
215+
def _preprocess_pypsa_components(
216+
self, component_type: str, extendable: bool, capa_str: str
217+
) -> None:
186218
### Handling PyPSA objects without carriers
187219
df = getattr(self.pypsa_network, component_type)
188220
for comp in df.index:
@@ -198,11 +230,9 @@ def _preprocess_pypsa_components(self, component_type: str, capa_str: str) -> No
198230
rsuffix="_carrier",
199231
),
200232
)
201-
df = getattr(self.pypsa_network, component_type)
202-
### Adding min and max capacities to non-extendable objects
203-
for field in [capa_str + "_min", capa_str + "_max"]:
204-
df.loc[df[capa_str + "_extendable"] == False, field] = df[capa_str]
205-
df.loc[df[capa_str + "_extendable"] == False, "capital_cost"] = 0.0
233+
self._rename_pypsa_components(component_type)
234+
if extendable:
235+
self._fix_capacities(component_type, capa_str)
206236

207237
def _register_pypsa_components(self) -> None:
208238
### PyPSA components : Generators
@@ -507,7 +537,7 @@ def _write_and_register_timeseries(
507537
timeseries_name = self.system_name + "_" + component + "_" + param
508538
comp_param_to_timeseries_name[(component, param)] = timeseries_name
509539
param_df[[component]].to_csv(
510-
self.series_dir / Path(timeseries_name + ".txt"),
540+
self.series_dir / Path(timeseries_name + self.series_file_format),
511541
index=False,
512542
header=False,
513543
)

src/andromede/pypsa_converter/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import yaml
1717
from pydantic import BaseModel
1818

19-
PYPSA_CONVERTER_MAX_FLOAT = 1e20
19+
PYPSA_CONVERTER_MAX_FLOAT = 100000000000
2020

2121

2222
def any_to_float(el: Any) -> float:
37.8 KB
Binary file not shown.

0 commit comments

Comments
 (0)