diff --git a/CaseStudy.py b/CaseStudy.py
index 8f1bb5f..25e0697 100644
--- a/CaseStudy.py
+++ b/CaseStudy.py
@@ -19,14 +19,18 @@
class CaseStudy:
# Lists of dataframes based on their dependencies - every table should only be present in one of these lists
- rpk_dependent_dataframes: list[str] = ["dPower_Demand",
+ rpk_dependent_dataframes: list[str] = ["dHeat_P2H_Conversion_Factors"
+ "dHeat_Demand",
+ "dPower_Demand",
"dPower_Hindex",
"dPower_ImportExport",
"dPower_Inflows",
"dPower_VRESProfiles"]
rp_only_dependent_dataframes: list[str] = ["dPower_WeightsRP"]
k_only_dependent_dataframes: list[str] = ["dPower_WeightsK"]
- non_time_dependent_dataframes: list[str] = ["dPower_BusInfo",
+ non_time_dependent_dataframes: list[str] = ["dHeat_Nodes",
+ "dHeat_P2H_Technologies",
+ "dPower_BusInfo",
"dPower_Network",
"dPower_Storage",
"dPower_ThermalGen",
@@ -48,19 +52,23 @@ def __init__(self,
n_jobs: int = 4,
global_parameters_file: str = "Global_Parameters.xlsx", dGlobal_Parameters: pd.DataFrame = None,
global_scenarios_file: str = "Global_Scenarios.xlsx", dGlobal_Scenarios: pd.DataFrame = None,
- power_parameters_file: str = "Power_Parameters.xlsx", dPower_Parameters: pd.DataFrame = None,
+ heat_demand_file: str = "Heat_Demand.xlsx", dHeat_Demand: pd.DataFrame = None,
+ heat_nodes_file: str = "Heat_Nodes.xlsx", dHeat_Nodes: pd.DataFrame = None,
+ heat_p2h_conversion_factors_file: str = "Heat_P2H_Conversion_Factors.xlsx", dHeat_P2H_Conversion_Factors: pd.DataFrame = None,
+ heat_p2h_technologies_file: str = "Heat_P2H_Technologies.xlsx", dHeat_P2H_Technologies: pd.DataFrame = None,
power_businfo_file: str = "Power_BusInfo.xlsx", dPower_BusInfo: pd.DataFrame = None,
+ power_demand_file: str = "Power_Demand.xlsx", dPower_Demand: pd.DataFrame = None,
+ power_hindex_file: str = "Power_Hindex.xlsx", dPower_Hindex: pd.DataFrame = None,
+ power_importexport_file: str = "Power_ImportExport.xlsx", dPower_ImportExport: pd.DataFrame = None,
+ power_inflows_file: str = "Power_Inflows.xlsx", dPower_Inflows: pd.DataFrame = None,
power_network_file: str = "Power_Network.xlsx", dPower_Network: pd.DataFrame = None,
+ power_parameters_file: str = "Power_Parameters.xlsx", dPower_Parameters: pd.DataFrame = None,
+ power_storage_file: str = "Power_Storage.xlsx", dPower_Storage: pd.DataFrame = None,
power_thermalgen_file: str = "Power_ThermalGen.xlsx", dPower_ThermalGen: pd.DataFrame = None,
power_vres_file: str = "Power_VRES.xlsx", dPower_VRES: pd.DataFrame = None,
- power_demand_file: str = "Power_Demand.xlsx", dPower_Demand: pd.DataFrame = None,
- power_inflows_file: str = "Power_Inflows.xlsx", dPower_Inflows: pd.DataFrame = None,
power_vresprofiles_file: str = "Power_VRESProfiles.xlsx", dPower_VRESProfiles: pd.DataFrame = None,
- power_storage_file: str = "Power_Storage.xlsx", dPower_Storage: pd.DataFrame = None,
- power_weightsrp_file: str = "Power_WeightsRP.xlsx", dPower_WeightsRP: pd.DataFrame = None,
power_weightsk_file: str = "Power_WeightsK.xlsx", dPower_WeightsK: pd.DataFrame = None,
- power_hindex_file: str = "Power_Hindex.xlsx", dPower_Hindex: pd.DataFrame = None,
- power_importexport_file: str = "Power_ImportExport.xlsx", dPower_ImportExport: pd.DataFrame = None,
+ power_weightsrp_file: str = "Power_WeightsRP.xlsx", dPower_WeightsRP: pd.DataFrame = None,
clip_method: str = "none", clip_value: float = 0):
self.data_folder = str(data_folder) if str(data_folder).endswith("/") else str(data_folder) + "/"
self.do_not_scale_units = do_not_scale_units
@@ -131,6 +139,34 @@ def __init__(self,
self.dPower_WeightsK = dPower_WeightsK
# Add conditional tasks (dependent on dPower_Parameters)
+ if self.dGlobal_Parameters["pEnableHeat"]:
+ self.heat_demand_file = heat_demand_file
+ if dHeat_Demand is None:
+ tasks.append(("dHeat_Demand", ExcelReader.get_Heat_Demand, (self.data_folder + self.heat_demand_file,)))
+ else:
+ self.dHeat_Demand = dHeat_Demand
+
+ if self.dGlobal_Parameters["pEnableHeat"]:
+ self.heat_p2h_conversion_factors_file = heat_p2h_conversion_factors_file
+ if dHeat_P2H_Conversion_Factors is None:
+ tasks.append(("dHeat_P2H_Conversion_Factors", ExcelReader.get_Heat_P2H_Conversion_Factors, (self.data_folder + self.heat_p2h_conversion_factors_file,)))
+ else:
+ self.dHeat_P2H_Conversion_Factors = dHeat_P2H_Conversion_Factors
+
+ if self.dGlobal_Parameters["pEnableHeat"]:
+ self.heat_nodes_file = heat_nodes_file
+ if dHeat_Nodes is None:
+ tasks.append(("dHeat_Nodes", ExcelReader.get_Heat_Nodes, (self.data_folder + self.heat_nodes_file,)))
+ else:
+ self.dHeat_Nodes = dHeat_Nodes
+
+ if self.dGlobal_Parameters["pEnableHeat"]:
+ self.heat_p2h_technologies_file = heat_p2h_technologies_file
+ if dHeat_P2H_Technologies is None:
+ tasks.append(("dHeat_P2H_Technologies", ExcelReader.get_Heat_P2H_Technologies, (self.data_folder + self.heat_p2h_technologies_file,)))
+ else:
+ self.dHeat_P2H_Technologies = dHeat_P2H_Technologies
+
if self.dPower_Parameters["pEnableThermalGen"]:
self.power_thermalgen_file = power_thermalgen_file
if dPower_ThermalGen is None:
@@ -305,6 +341,9 @@ def scale_CaseStudy(self):
if self.dPower_Parameters["pEnablePowerImportExport"]:
self.scale_dPower_ImportExport()
+ if self.dGlobal_Parameters["pEnableHeat"]:
+ self.scale_dHeat_Demand()
+
def remove_scaling(self):
self.power_scaling_factor = 1 / self.power_scaling_factor
self.cost_scaling_factor = 1 / self.cost_scaling_factor
@@ -316,6 +355,13 @@ def remove_scaling(self):
self.cost_scaling_factor = 1 / self.cost_scaling_factor
self.angle_to_rad_scaling_factor = 1 / self.angle_to_rad_scaling_factor
+ def scale_dHeat_Demand(self):
+ self.dHeat_Demand["value"] *= self.power_scaling_factor
+
+ def scale_dHeat_P2H_Technologies(self):
+ self.dHeat_P2H_Technologies["InstCap"] *= self.power_scaling_factor
+ self.dHeat_P2H_Technologies["ImpStoCap"] *= self.power_scaling_factor
+
def scale_dPower_Parameters(self):
self.dPower_Parameters["pSBase"] *= self.power_scaling_factor
self.dPower_Parameters["pENSCost"] *= self.cost_scaling_factor / self.power_scaling_factor
@@ -410,7 +456,7 @@ def scale_dPower_ImportExport(self):
def get_dGlobal_Parameters(self):
file_path = self.data_folder + self.global_parameters_file
- version_spec = "v0.1.0"
+ version_spec = "v0.1.1"
fail_on_wrong_version = False
try:
@@ -430,7 +476,7 @@ def get_dGlobal_Parameters(self):
dGlobal_Parameters = dGlobal_Parameters.drop(dGlobal_Parameters.columns[0], axis=1)
dGlobal_Parameters = dGlobal_Parameters.set_index('Solver Options')
- self.yesNo_to_bool(dGlobal_Parameters, ['pEnableRMIP'])
+ self.yesNo_to_bool(dGlobal_Parameters, ['pEnableRMIP', 'pEnableHeat'])
# Transform to make it easier to access values
dGlobal_Parameters = dGlobal_Parameters.drop(dGlobal_Parameters.columns[1:], axis=1) # Drop all columns but "Value" (rest is just for information in the Excel)
diff --git a/ExcelReader.py b/ExcelReader.py
index 6ae4ab9..409d5b4 100644
--- a/ExcelReader.py
+++ b/ExcelReader.py
@@ -145,6 +145,64 @@ def get_Global_Scenarios(excel_file_path: str, keep_excluded_entries: bool = Fal
return dGlobal_Scenarios
+def get_Heat_Demand(excel_file_path: str, keep_excluded_entries: bool = False, fail_on_wrong_version: bool = False) -> pd.DataFrame:
+ """
+ Read the dHeat_Demand data from the Excel file.
+ :param excel_file_path: Path to the Excel file
+ :param keep_excluded_entries: Unused but kept for compatibility with other functions
+ :param fail_on_wrong_version: If True, raise an error if the version of the Excel file does not match the expected version
+ :return: dHeat_Demand
+ """
+ dHeat_Demand = __read_pivoted_file(excel_file_path, "v0.0.1", ['rp', 'k', 'hn', 'dt'], 'k', ['rp', 'hn', 'dt', 'dataPackage', 'dataSource', 'id'], False, False, fail_on_wrong_version)
+
+ if keep_excluded_entries:
+ printer.warning("'keep_excluded_entries' is set for 'get_Heat_Demand', although nothing is excluded anyway - please check if this is intended.")
+
+ return dHeat_Demand
+
+
+def get_Heat_Nodes(excel_file_path: str, keep_excluded_entries: bool = False, fail_on_wrong_version: bool = False) -> pd.DataFrame:
+ """
+ Read the dHeat_Node_Links data from the Excel file.
+ :param excel_file_path: Path to the Excel file
+ :param keep_excluded_entries: Do not exclude any entries which are marked to be excluded in the Excel file
+ :param fail_on_wrong_version: If True, raise an error if the version of the Excel file does not match the expected version
+ :return: dHeat_Node_Links
+ """
+ dHeat_Node_Links = __read_non_pivoted_file(excel_file_path, "v0.0.1", ["i", "hn"], True, keep_excluded_entries, fail_on_wrong_version)
+
+ return dHeat_Node_Links
+
+
+def get_Heat_P2H_Conversion_Factors(excel_file_path: str, keep_excluded_entries: bool = False, fail_on_wrong_version: bool = False) -> pd.DataFrame:
+ """
+ Read the dHeat_P2H_Conversion_Factors data from the Excel file.
+ :param excel_file_path: Path to the Excel file
+ :param keep_excluded_entries: Unused but kept for compatibility with other functions
+ :param fail_on_wrong_version: If True, raise an error if the version of the Excel file does not match the expected version
+ :return: dHeat_P2H_Conversion_Factors
+ """
+ dHeat_P2H_Conversion_Factors = __read_pivoted_file(excel_file_path, "v0.0.1", ['rp', 'k', 'hn', 'dt', 'htec'], 'k', ['rp', 'hn', 'dt', 'htec', 'dataPackage', 'dataSource', 'id'], False, False, fail_on_wrong_version)
+
+ if keep_excluded_entries:
+ printer.warning("'keep_excluded_entries' is set for 'dHeat_P2H_Conversion_Factors', although nothing is excluded anyway - please check if this is intended.")
+
+ return dHeat_P2H_Conversion_Factors
+
+
+def get_Heat_P2H_Technologies(excel_file_path: str, keep_excluded_entries: bool = False, fail_on_wrong_version: bool = False) -> pd.DataFrame:
+ """
+ Read the dHeat_P2H_Technologies data from the Excel file.
+ :param excel_file_path: Path to the Excel file
+ :param keep_excluded_entries: Do not exclude any entries which are marked to be excluded in the Excel file
+ :param fail_on_wrong_version: If True, raise an error if the version of the Excel file does not match the expected version
+ :return: dHeat_P2H_Technologies
+ """
+ dHeat_P2H_Technologies = __read_non_pivoted_file(excel_file_path, "v0.0.1", ["hn", "dt", "htec"], False, keep_excluded_entries, fail_on_wrong_version)
+
+ return dHeat_P2H_Technologies
+
+
def get_Power_BusInfo(excel_file_path: str, keep_excluded_entries: bool = False, fail_on_wrong_version: bool = False) -> pd.DataFrame:
"""
Read the dPower_BusInfo data from the Excel file.
diff --git a/ExcelWriter.py b/ExcelWriter.py
index f1ee83e..7abff1d 100644
--- a/ExcelWriter.py
+++ b/ExcelWriter.py
@@ -298,6 +298,46 @@ def write_Global_Scenarios(self, dGlobal_Scenarios: pd.DataFrame, folder_path: s
"""
self._write_Excel_from_definition(dGlobal_Scenarios, folder_path, "Global_Scenarios")
+ def write_Heat_Demand(self, dHeat_Demand: pd.DataFrame, folder_path: str) -> None:
+ """
+ Write the dHeat_Demand DataFrame to an Excel file in LEGO format.
+ :param dHeat_Demand: DataFrame containing the dHeat_Demand data.
+ :param folder_path: Path to the folder where the Excel file will be saved.
+ :return: None
+ """
+
+ self._write_Excel_from_definition(dHeat_Demand, folder_path, "Heat_Demand")
+
+ def write_Heat_Nodes(self, dHeat_Nodes: pd.DataFrame, folder_path: str) -> None:
+ """
+ Write the dHeat_Nodes DataFrame to an Excel file in LEGO format.
+ :param dHeat_Nodes: DataFrame containing the dHeat_Demand data.
+ :param folder_path: Path to the folder where the Excel file will be saved.
+ :return: None
+ """
+
+ self._write_Excel_from_definition(dHeat_Nodes, folder_path, "Heat_Nodes")
+
+ def write_Heat_P2H_Technologies(self, dHeat_P2H_Technologies: pd.DataFrame, folder_path: str) -> None:
+ """
+ Write the dHeat_P2H_Technologies DataFrame to an Excel file in LEGO format.
+ :param dHeat_P2H_Technologies: DataFrame containing the dHeat_Demand data.
+ :param folder_path: Path to the folder where the Excel file will be saved.
+ :return: None
+ """
+
+ self._write_Excel_from_definition(dHeat_P2H_Technologies, folder_path, "Heat_P2H_Technologies")
+
+ def write_Heat_P2H_Conversion_Factors(self, dHeat_P2H_Conversion_Factors: pd.DataFrame, folder_path: str) -> None:
+ """
+ Write the dHeat_P2H_Conversion_Factors DataFrame to an Excel file in LEGO format.
+ :param dHeat_P2H_Conversion_Factors: DataFrame containing the dHeat_Demand data.
+ :param folder_path: Path to the folder where the Excel file will be saved.
+ :return: None
+ """
+
+ self._write_Excel_from_definition(dHeat_P2H_Conversion_Factors, folder_path, "Heat_P2H_Conversion_Factors")
+
def write_Power_BusInfo(self, dPower_BusInfo: pd.DataFrame, folder_path: str) -> None:
"""
Write the dPower_BusInfo DataFrame to an Excel file in LEGO format.
@@ -534,6 +574,10 @@ def model_to_excel(model: pyomo.core.Model, target_path: str) -> None:
("Data_Packages", f"{args.caseStudyFolder}Data_Packages.xlsx", ExcelReader.get_Data_Packages, ew.write_Data_Packages),
("Data_Sources", f"{args.caseStudyFolder}Data_Sources.xlsx", ExcelReader.get_Data_Sources, ew.write_Data_Sources),
("Global_Scenarios", f"{args.caseStudyFolder}Global_Scenarios.xlsx", ExcelReader.get_Global_Scenarios, ew.write_Global_Scenarios),
+ ("Heat_Demand", f"{args.caseStudyFolder}Heat_Demand.xlsx", ExcelReader.get_Heat_Demand, ew.write_Heat_Demand),
+ ("Heat_Nodes", f"{args.caseStudyFolder}Heat_Nodes.xlsx", ExcelReader.get_Heat_Nodes, ew.write_Heat_Nodes),
+ ("Heat_P2H_Technologies", f"{args.caseStudyFolder}Heat_P2H_Technologies.xlsx", ExcelReader.get_Heat_P2H_Technologies, ew.write_Heat_P2H_Technologies),
+ ("Heat_P2H_Conversion_Factors", f"{args.caseStudyFolder}Heat_P2H_Conversion_Factors.xlsx", ExcelReader.get_Heat_P2H_Conversion_Factors, ew.write_Heat_P2H_Conversion_Factors),
("Power_BusInfo", f"{args.caseStudyFolder}Power_BusInfo.xlsx", ExcelReader.get_Power_BusInfo, ew.write_Power_BusInfo),
("Power_Demand", f"{args.caseStudyFolder}Power_Demand.xlsx", ExcelReader.get_Power_Demand, ew.write_Power_Demand),
("Power_Demand_KInRows", f"{args.caseStudyFolder}Power_Demand_KInRows.xlsx", ExcelReader.get_Power_Demand_KInRows, ew.write_Power_Demand_KInRows),
diff --git a/TableDefinitions.xml b/TableDefinitions.xml
index 18771ac..e3cea04 100644
--- a/TableDefinitions.xml
+++ b/TableDefinitions.xml
@@ -39,6 +39,70 @@
+
+ v0.0.1
+ Heat - Demand
+ 30.0
+
+
+
+
+
+
+
+
+
+
+
+
+ v0.0.1
+ Heat - Node Links
+ 45.0
+
+
+
+
+
+
+
+
+
+
+
+
+ v0.0.1
+ Heat - P2H Conversion Factors
+ 30.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+ v0.0.1
+ Heat - P2H Technologies
+ 60.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
v0.1.2
Power - Bus information
@@ -426,6 +490,13 @@
21.0
rightFloat2
+
+ Heat Demand Type
+ Type of Heat Demand
+ [residential, industry, ...]
+ 22.0
+ general
+
Efficiency
Efficiency calculated as 1/input for 1 MWh, i.e. 0.5 (or 50%) if 2 MWh fuel are required for 1 MWh electricity
@@ -489,6 +560,20 @@
15.0
general
+
+ Heat Node
+ Name of heat node
+ [hn]
+ 15.0
+ general
+
+
+ Heat Conversion Technology
+ Type of Conversion Technology
+ [ASHP, WSHP, electric, …]
+ 27.0
+ general
+
Hub Height
Heigth of the turbine
@@ -510,6 +595,13 @@
19.00
dbKey
+
+ Implicit Thermal Storage Capacity
+ Implicit thermal storage capacity
+ [MWh_thermal]
+ 30.0
+ rightFloat2
+
InertiaConst
Inertia constant H of the unit
@@ -524,6 +616,13 @@
15.0
rightFloat2
+
+ Installed Capacity
+ Installed Capacity termal
+ [MW_thermal]
+ 17.0
+ rightFloat2
+
InvestCost
Annualized investment cost per MW
@@ -853,6 +952,13 @@
41.0
general
+
+ Self Discharge Thermal
+ Self-discharge rate of thermal storage unit
+ [%, 0-1]
+ 20.0
+ rightFloat2
+
Self Discharge
Self discharge of the storage unit
@@ -881,6 +987,13 @@
15.0
general
+
+ Heating technology share
+ Share of conversion technology at hn for dt
+ [%, 0-1]
+ 24.0
+ rightFloat2
+
Vmax
Cut-out wind speed
@@ -991,6 +1104,14 @@
10.57
rightFloat2
+
+
+ k
+ Conversion Efficiency at this representative time step k
+ [-]
+ 10.57
+ rightFloat2
+
i
@@ -1007,6 +1128,22 @@
10.57
rightInt
+
+
+ k
+ Heat Demand at this representative time step k
+ [MW]
+ 10.57
+ rightInt
+
+
+
+ k
+ Heat Conversion Efficiency at this representative time step k
+ [-]
+ 10.57
+ rightFloat2
+
g
diff --git a/data/example/Global_Parameters.xlsx b/data/example/Global_Parameters.xlsx
new file mode 100644
index 0000000..0ff5a7d
Binary files /dev/null and b/data/example/Global_Parameters.xlsx differ
diff --git a/data/example/Heat_Demand.xlsx b/data/example/Heat_Demand.xlsx
new file mode 100644
index 0000000..a9d8e90
Binary files /dev/null and b/data/example/Heat_Demand.xlsx differ
diff --git a/data/example/Heat_Nodes.xlsx b/data/example/Heat_Nodes.xlsx
new file mode 100644
index 0000000..d2906c4
Binary files /dev/null and b/data/example/Heat_Nodes.xlsx differ
diff --git a/data/example/Heat_P2H_Conversion_Factors.xlsx b/data/example/Heat_P2H_Conversion_Factors.xlsx
new file mode 100644
index 0000000..4a53dac
Binary files /dev/null and b/data/example/Heat_P2H_Conversion_Factors.xlsx differ
diff --git a/data/example/Heat_P2H_Technologies.xlsx b/data/example/Heat_P2H_Technologies.xlsx
new file mode 100644
index 0000000..7af9875
Binary files /dev/null and b/data/example/Heat_P2H_Technologies.xlsx differ