1414from math import inf
1515from pathlib import Path
1616
17+ import numpy as np
1718import pandas as pd
1819from pandas import DataFrame
1920from 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 )
0 commit comments