openTEPES 4.18.4__py3-none-any.whl → 4.18.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openTEPES/9n_PTDF/oT_Data_Demand_9n_PTDF.csv +8737 -0
- openTEPES/9n_PTDF/oT_Data_Duration_9n_PTDF.csv +8737 -0
- openTEPES/9n_PTDF/oT_Data_Emission_9n_PTDF.csv +2 -0
- openTEPES/9n_PTDF/oT_Data_EnergyInflows_9n_PTDF.csv +8737 -0
- openTEPES/9n_PTDF/oT_Data_EnergyOutflows_9n_PTDF.csv +8737 -0
- openTEPES/9n_PTDF/oT_Data_Generation_9n_PTDF.csv +17 -0
- openTEPES/9n_PTDF/oT_Data_Inertia_9n_PTDF.csv +8737 -0
- openTEPES/9n_PTDF/oT_Data_Network_9n_PTDF.csv +14 -0
- openTEPES/9n_PTDF/oT_Data_NodeLocation_9n_PTDF.csv +10 -0
- openTEPES/9n_PTDF/oT_Data_OperatingReserveDown_9n_PTDF.csv +8737 -0
- openTEPES/9n_PTDF/oT_Data_OperatingReserveUp_9n_PTDF.csv +8737 -0
- openTEPES/9n_PTDF/oT_Data_Option_9n_PTDF.csv +2 -0
- openTEPES/9n_PTDF/oT_Data_Parameter_9n_PTDF.csv +2 -0
- openTEPES/9n_PTDF/oT_Data_Period_9n_PTDF.csv +2 -0
- openTEPES/9n_PTDF/oT_Data_RESEnergy_9n_PTDF.csv +2 -0
- openTEPES/9n_PTDF/oT_Data_ReserveMargin_9n_PTDF.csv +2 -0
- openTEPES/9n_PTDF/oT_Data_Scenario_9n_PTDF.csv +2 -0
- openTEPES/9n_PTDF/oT_Data_Stage_9n_PTDF.csv +2 -0
- openTEPES/9n_PTDF/oT_Data_VariableEmissionCost_9n_PTDF.csv +8737 -0
- openTEPES/9n_PTDF/oT_Data_VariableFuelCost_9n_PTDF.csv +8737 -0
- openTEPES/9n_PTDF/oT_Data_VariableMaxConsumption_9n_PTDF.csv +8737 -0
- openTEPES/9n_PTDF/oT_Data_VariableMaxEnergy_9n_PTDF.csv +8737 -0
- openTEPES/9n_PTDF/oT_Data_VariableMaxGeneration_9n_PTDF.csv +8737 -0
- openTEPES/9n_PTDF/oT_Data_VariableMaxStorage_9n_PTDF.csv +8737 -0
- openTEPES/9n_PTDF/oT_Data_VariableMinConsumption_9n_PTDF.csv +8737 -0
- openTEPES/9n_PTDF/oT_Data_VariableMinEnergy_9n_PTDF.csv +8737 -0
- openTEPES/9n_PTDF/oT_Data_VariableMinGeneration_9n_PTDF.csv +8737 -0
- openTEPES/9n_PTDF/oT_Data_VariableMinStorage_9n_PTDF.csv +8737 -0
- openTEPES/9n_PTDF/oT_Data_VariablePTDF_9n_PTDF.csv +8740 -0
- openTEPES/9n_PTDF/oT_Data_VariableTTCBck_9n_PTDF.csv +8739 -0
- openTEPES/9n_PTDF/oT_Data_VariableTTCFrw_9n_PTDF.csv +8739 -0
- openTEPES/9n_PTDF/oT_Dict_AreaToRegion_9n_PTDF.csv +2 -0
- openTEPES/9n_PTDF/oT_Dict_Area_9n_PTDF.csv +2 -0
- openTEPES/9n_PTDF/oT_Dict_Circuit_9n_PTDF.csv +3 -0
- openTEPES/9n_PTDF/oT_Dict_Generation_9n_PTDF.csv +17 -0
- openTEPES/9n_PTDF/oT_Dict_Line_9n_PTDF.csv +3 -0
- openTEPES/9n_PTDF/oT_Dict_LoadLevel_9n_PTDF.csv +8737 -0
- openTEPES/9n_PTDF/oT_Dict_NodeToZone_9n_PTDF.csv +10 -0
- openTEPES/9n_PTDF/oT_Dict_Node_9n_PTDF.csv +10 -0
- openTEPES/9n_PTDF/oT_Dict_Period_9n_PTDF.csv +2 -0
- openTEPES/9n_PTDF/oT_Dict_Region_9n_PTDF.csv +31 -0
- openTEPES/9n_PTDF/oT_Dict_Scenario_9n_PTDF.csv +2 -0
- openTEPES/9n_PTDF/oT_Dict_Stage_9n_PTDF.csv +2 -0
- openTEPES/9n_PTDF/oT_Dict_Storage_9n_PTDF.csv +3 -0
- openTEPES/9n_PTDF/oT_Dict_Technology_9n_PTDF.csv +7 -0
- openTEPES/9n_PTDF/oT_Dict_ZoneToArea_9n_PTDF.csv +10 -0
- openTEPES/9n_PTDF/oT_Dict_Zone_9n_PTDF.csv +10 -0
- openTEPES/RTS-GMLC/oT_Data_VariableMinGeneration_RTS-GMLC.csv +1 -1
- openTEPES/RTS-GMLC_6y/oT_Data_VariableFuelCost_RTS-GMLC_6y.csv +1 -1
- openTEPES/RTS-GMLC_6y/oT_Dict_AreaToRegion_RTS-GMLC_6y.csv +4 -4
- openTEPES/RTS-GMLC_6y/oT_Dict_Area_RTS-GMLC_6y.csv +4 -4
- openTEPES/RTS-GMLC_6y/oT_Dict_Circuit_RTS-GMLC_6y.csv +5 -5
- openTEPES/RTS-GMLC_6y/oT_Dict_Line_RTS-GMLC_6y.csv +3 -3
- openTEPES/RTS-GMLC_6y/oT_Dict_NodeToZone_RTS-GMLC_6y.csv +74 -74
- openTEPES/RTS-GMLC_6y/oT_Dict_Region_RTS-GMLC_6y.csv +2 -2
- openTEPES/RTS-GMLC_6y/oT_Dict_Scenario_RTS-GMLC_6y.csv +2 -2
- openTEPES/RTS-GMLC_6y/oT_Dict_Storage_RTS-GMLC_6y.csv +3 -3
- openTEPES/RTS-GMLC_6y/oT_Dict_Technology_RTS-GMLC_6y.csv +10 -10
- openTEPES/RTS-GMLC_6y/oT_Dict_ZoneToArea_RTS-GMLC_6y.csv +22 -22
- openTEPES/RTS-GMLC_6y/oT_Dict_Zone_RTS-GMLC_6y.csv +22 -22
- openTEPES/__init__.py +1 -1
- openTEPES/openTEPES.py +26 -17
- openTEPES/openTEPES_InputData.py +1335 -1188
- openTEPES/openTEPES_Main.py +3 -3
- openTEPES/openTEPES_ModelFormulation.py +413 -156
- openTEPES/openTEPES_OutputResults.py +263 -206
- openTEPES/openTEPES_ProblemSolving.py +35 -28
- openTEPES/sSEP/oT_Data_DemandHydrogen_sSEP.csv +8736 -8736
- openTEPES/sSEP/oT_Data_Generation_sSEP.csv +1 -1
- openTEPES/sSEP/oT_Data_HydroOutflows_sSEP.csv +1 -1
- {opentepes-4.18.4.dist-info → opentepes-4.18.6.dist-info}/METADATA +65 -46
- {opentepes-4.18.4.dist-info → opentepes-4.18.6.dist-info}/RECORD +75 -28
- {opentepes-4.18.4.dist-info → opentepes-4.18.6.dist-info}/WHEEL +1 -1
- {opentepes-4.18.4.dist-info → opentepes-4.18.6.dist-info}/entry_points.txt +0 -0
- {opentepes-4.18.4.dist-info → opentepes-4.18.6.dist-info/licenses}/LICENSE +0 -0
openTEPES/openTEPES_InputData.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) -
|
|
2
|
+
Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - September 17, 2025
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
import datetime
|
|
@@ -9,6 +9,7 @@ import os
|
|
|
9
9
|
import pandas as pd
|
|
10
10
|
from collections import defaultdict
|
|
11
11
|
from pyomo.environ import DataPortal, Set, Param, Var, Binary, NonNegativeReals, NonNegativeIntegers, PositiveReals, PositiveIntegers, Reals, UnitInterval, Any
|
|
12
|
+
from pyomo.environ import Block, Boolean
|
|
12
13
|
|
|
13
14
|
def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
14
15
|
print('Input data ****')
|
|
@@ -16,214 +17,164 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
16
17
|
_path = os.path.join(DirName, CaseName)
|
|
17
18
|
StartTime = time.time()
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
dfEmission = pd.read_csv(f'{_path}/oT_Data_Emission_' f'{CaseName}.csv', header=0, index_col=[0,1 ])
|
|
28
|
-
dfRESEnergy = pd.read_csv(f'{_path}/oT_Data_RESEnergy_' f'{CaseName}.csv', header=0, index_col=[0,1 ])
|
|
29
|
-
dfDemand = pd.read_csv(f'{_path}/oT_Data_Demand_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
|
|
30
|
-
dfInertia = pd.read_csv(f'{_path}/oT_Data_Inertia_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
|
|
31
|
-
dfUpOperatingReserve = pd.read_csv(f'{_path}/oT_Data_OperatingReserveUp_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
|
|
32
|
-
dfDwOperatingReserve = pd.read_csv(f'{_path}/oT_Data_OperatingReserveDown_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
|
|
33
|
-
dfGeneration = pd.read_csv(f'{_path}/oT_Data_Generation_' f'{CaseName}.csv', header=0, index_col=[0 ])
|
|
34
|
-
dfVariableMinPower = pd.read_csv(f'{_path}/oT_Data_VariableMinGeneration_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
|
|
35
|
-
dfVariableMaxPower = pd.read_csv(f'{_path}/oT_Data_VariableMaxGeneration_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
|
|
36
|
-
dfVariableMinCharge = pd.read_csv(f'{_path}/oT_Data_VariableMinConsumption_'f'{CaseName}.csv', header=0, index_col=[0,1,2])
|
|
37
|
-
dfVariableMaxCharge = pd.read_csv(f'{_path}/oT_Data_VariableMaxConsumption_'f'{CaseName}.csv', header=0, index_col=[0,1,2])
|
|
38
|
-
dfVariableMinStorage = pd.read_csv(f'{_path}/oT_Data_VariableMinStorage_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
|
|
39
|
-
dfVariableMaxStorage = pd.read_csv(f'{_path}/oT_Data_VariableMaxStorage_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
|
|
40
|
-
dfVariableMinEnergy = pd.read_csv(f'{_path}/oT_Data_VariableMinEnergy_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
|
|
41
|
-
dfVariableMaxEnergy = pd.read_csv(f'{_path}/oT_Data_VariableMaxEnergy_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
|
|
42
|
-
dfVariableFuelCost = pd.read_csv(f'{_path}/oT_Data_VariableFuelCost_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
|
|
43
|
-
dfVariableEmissionCost = pd.read_csv(f'{_path}/oT_Data_VariableEmissionCost_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
|
|
44
|
-
dfEnergyInflows = pd.read_csv(f'{_path}/oT_Data_EnergyInflows_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
|
|
45
|
-
dfEnergyOutflows = pd.read_csv(f'{_path}/oT_Data_EnergyOutflows_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
|
|
46
|
-
dfNodeLocation = pd.read_csv(f'{_path}/oT_Data_NodeLocation_' f'{CaseName}.csv', header=0, index_col=[0 ])
|
|
47
|
-
dfNetwork = pd.read_csv(f'{_path}/oT_Data_Network_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
|
|
20
|
+
set_definitions = {
|
|
21
|
+
'pp': ('Period', 'p' ), 'scc': ('Scenario', 'sc'), 'stt': ('Stage', 'st'),
|
|
22
|
+
'nn': ('LoadLevel', 'n' ), 'gg': ('Generation','g'), 'gt': ('Technology', 'gt'),
|
|
23
|
+
'nd': ('Node', 'nd'), 'ni': ('Node', 'nd'), 'nf': ('Node', 'nd'),
|
|
24
|
+
'zn': ('Zone', 'zn'), 'ar': ('Area', 'ar'), 'rg': ('Region', 'rg'),
|
|
25
|
+
'cc': ('Circuit', 'cc'), 'c2': ('Circuit', 'cc'), 'lt': ('Line', 'lt'),
|
|
26
|
+
'ndzn': ('NodeToZone', 'ndzn'), 'znar': ('ZoneToArea', 'znar'), 'arrg': ('AreaToRegion', 'arrg'),
|
|
27
|
+
}
|
|
48
28
|
|
|
49
|
-
|
|
50
|
-
dfReservoir = pd.read_csv(f'{_path}/oT_Data_Reservoir_' f'{CaseName}.csv', header=0, index_col=[0 ])
|
|
51
|
-
dfVariableMinVolume = pd.read_csv(f'{_path}/oT_Data_VariableMinVolume_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
|
|
52
|
-
dfVariableMaxVolume = pd.read_csv(f'{_path}/oT_Data_VariableMaxVolume_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
|
|
53
|
-
dfHydroInflows = pd.read_csv(f'{_path}/oT_Data_HydroInflows_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
|
|
54
|
-
dfHydroOutflows = pd.read_csv(f'{_path}/oT_Data_HydroOutflows_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
|
|
55
|
-
pIndHydroTopology = 1
|
|
56
|
-
except:
|
|
57
|
-
pIndHydroTopology = 0
|
|
58
|
-
print('**** No hydropower topology')
|
|
29
|
+
dictSets = DataPortal()
|
|
59
30
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
31
|
+
# Reading dictionaries from CSV and adding elements to the dictSets
|
|
32
|
+
for set_name, (file_set_name, set_key) in set_definitions.items():
|
|
33
|
+
filename = f'oT_Dict_{file_set_name}_{CaseName}.csv'
|
|
34
|
+
dictSets.load(filename=os.path.join(_path, filename), set=set_key, format='set')
|
|
35
|
+
is_ordered = set_name not in {'gt', 'nd', 'ni', 'nf', 'cc', 'c2', 'ndzn', 'znar', 'arrg'}
|
|
36
|
+
setattr(mTEPES, set_name, Set(initialize=dictSets[set_key], ordered=is_ordered, doc=f'{file_set_name}'))
|
|
37
|
+
|
|
38
|
+
# # Defining sets in the model
|
|
39
|
+
# for set_name, (file_set_name, set_key) in set_definitions.items():
|
|
40
|
+
# is_ordered = set_name not in {'stt', 'gt', 'nd', 'ni', 'nf', 'cc', 'c2', 'ndzn', 'znar', 'arrg'}
|
|
41
|
+
# setattr(model, set_name, Set(initialize=dictSets[set_key], ordered=is_ordered, doc=f'{file_set_name}'))
|
|
42
|
+
|
|
43
|
+
# Constants
|
|
44
|
+
DEFAULT_IDX_COLS = ['Period', 'Scenario', 'LoadLevel', 'Area', 'Generator', 'InitialNode', 'FinalNode', 'Circuit', 'Node', 'Stage']
|
|
45
|
+
SPECIAL_IDX_COLS = {'Generation': ['Generator'], 'Reservoir': ['Reservoir']}
|
|
46
|
+
HEADER_LEVELS = {
|
|
47
|
+
'VariableTTCFrw': [0, 1, 2 ],
|
|
48
|
+
'VariableTTCBck': [0, 1, 2 ],
|
|
49
|
+
'VariablePTDF' : [0, 1, 2, 3],
|
|
50
|
+
}
|
|
51
|
+
FLAG_MAPPING = {
|
|
52
|
+
'VariableTTCFrw' : ('pIndVarTTC' , None, 'No variable transmission line TTCs' ),
|
|
53
|
+
'VariableTTCBck' : ('pIndVarTTC' , None, 'No variable transmission line TTCs' ),
|
|
54
|
+
'VariablePTDF' : ('pIndPTDF' , None, 'No flow-based market coupling method'),
|
|
55
|
+
'Reservoir' : ('pIndHydroTopology', None, 'No hydropower topology' ),
|
|
56
|
+
'VariableMinVolume': ('pIndHydroTopology', None, 'No hydropower topology' ),
|
|
57
|
+
'VariableMaxVolume': ('pIndHydroTopology', None, 'No hydropower topology' ),
|
|
58
|
+
'HydroInflows' : ('pIndHydroTopology', None, 'No hydropower topology' ),
|
|
59
|
+
'HydroOutflows' : ('pIndHydroTopology', None, 'No hydropower topology' ),
|
|
60
|
+
'DemandHydrogen' : ('pIndHydrogen' , None, 'No hydrogen energy carrier' ),
|
|
61
|
+
'NetworkHydrogen' : ('pIndHydrogen' , None, 'No hydrogen energy carrier' ),
|
|
62
|
+
'DemandHeat' : ('pIndHeat' , None, 'No heat energy carrier' ),
|
|
63
|
+
'ReserveMarginHeat': ('pIndHeat' , None, 'No heat energy carrier' ),
|
|
64
|
+
'NetworkHeat' : ('pIndHeat' , None, 'No heat energy carrier' ),
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
factor_1 = 1e-3
|
|
68
|
+
factor_2 = 1e-6
|
|
69
|
+
|
|
70
|
+
def load_csv_with_index(path, file_name, idx_cols, header_levels=None):
|
|
71
|
+
"""
|
|
72
|
+
Load a CSV file into a DataFrame and set its index based on provided columns.
|
|
73
|
+
"""
|
|
74
|
+
full_path = os.path.join(path, file_name)
|
|
75
|
+
if header_levels:
|
|
76
|
+
df = pd.read_csv(full_path, header=header_levels, index_col=[0, 1, 2])
|
|
77
|
+
else:
|
|
78
|
+
df = pd.read_csv(full_path)
|
|
79
|
+
|
|
80
|
+
present_idx = [col for col in df.columns if col in idx_cols]
|
|
81
|
+
file_key = file_name.split('_')[2]
|
|
82
|
+
idx_to_set = SPECIAL_IDX_COLS.get(file_key, present_idx)
|
|
83
|
+
if file_key == 'Duration':
|
|
84
|
+
idx_to_set = idx_to_set[:-1] # Exclude 'Stage' for Duration
|
|
85
|
+
df.set_index(idx_to_set, inplace=True, drop=True)
|
|
86
|
+
return df
|
|
67
87
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
88
|
+
def read_input_data(path, case_name):
|
|
89
|
+
"""
|
|
90
|
+
Read all oT_Data files from the given directory, returning
|
|
91
|
+
a dict of DataFrames and a dict of flags for loaded data.
|
|
92
|
+
"""
|
|
93
|
+
dfs = {}
|
|
94
|
+
par = {}
|
|
95
|
+
|
|
96
|
+
# Identify unique file types
|
|
97
|
+
files = [f for f in os.listdir(path) if 'oT_Data' in f]
|
|
98
|
+
file_sets = set(f.split('_')[2] for f in files)
|
|
99
|
+
|
|
100
|
+
for fs in file_sets:
|
|
101
|
+
file_name = f'oT_Data_{fs}_{case_name}.csv'
|
|
102
|
+
dp_key, _, error_msg = FLAG_MAPPING.get(fs, (None, None, None))
|
|
103
|
+
header = HEADER_LEVELS.get(fs)
|
|
104
|
+
|
|
105
|
+
try:
|
|
106
|
+
if fs in ('Option', 'Parameter'):
|
|
107
|
+
dfs[f'df{fs}'] = pd.read_csv(os.path.join(path, file_name))
|
|
108
|
+
else:
|
|
109
|
+
dfs[f'df{fs}'] = load_csv_with_index(path, file_name, DEFAULT_IDX_COLS, header)
|
|
110
|
+
|
|
111
|
+
if dp_key:
|
|
112
|
+
par[dp_key] = 1
|
|
113
|
+
except FileNotFoundError:
|
|
114
|
+
print(f'WARNING: File not found: {file_name}')
|
|
115
|
+
if dp_key:
|
|
116
|
+
par[dp_key] = 0
|
|
117
|
+
except Exception as e:
|
|
118
|
+
print(f'No file {file_name}')
|
|
119
|
+
if dp_key:
|
|
120
|
+
par[dp_key] = 0
|
|
121
|
+
|
|
122
|
+
return dfs, par
|
|
123
|
+
|
|
124
|
+
dfs, par = read_input_data(_path, CaseName)
|
|
125
|
+
# if 'pIndVarTTC', 'pIndPTDF', 'pIndHydroTopology', 'pIndHydrogen', 'pIndHeat' not in par include them and set value to zero
|
|
126
|
+
for key in ['pIndVarTTC', 'pIndPTDF', 'pIndHydroTopology', 'pIndHydrogen', 'pIndHeat']:
|
|
127
|
+
if key not in par.keys():
|
|
128
|
+
par[key] = 0
|
|
76
129
|
|
|
77
130
|
# substitute NaN by 0
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
if pIndHydrogen == 1:
|
|
115
|
-
dfDemandHydrogen.fillna (0.0, inplace=True)
|
|
116
|
-
dfNetworkHydrogen.fillna (0.0, inplace=True)
|
|
117
|
-
|
|
118
|
-
if pIndHeat == 1:
|
|
119
|
-
dfDemandHeat.fillna (0.0, inplace=True)
|
|
120
|
-
dfReserveMarginHeat.fillna(0.0, inplace=True)
|
|
121
|
-
dfNetworkHeat.fillna (0.0, inplace=True)
|
|
122
|
-
|
|
123
|
-
dfReserveMargin = dfReserveMargin.where (dfReserveMargin > 0.0, 0.0)
|
|
124
|
-
dfEmission = dfEmission.where (dfEmission > 0.0, 0.0)
|
|
125
|
-
dfRESEnergy = dfRESEnergy.where (dfRESEnergy > 0.0, 0.0)
|
|
126
|
-
dfInertia = dfInertia.where (dfInertia > 0.0, 0.0)
|
|
127
|
-
dfUpOperatingReserve = dfUpOperatingReserve.where (dfUpOperatingReserve > 0.0, 0.0)
|
|
128
|
-
dfDwOperatingReserve = dfDwOperatingReserve.where (dfDwOperatingReserve > 0.0, 0.0)
|
|
129
|
-
dfVariableMinPower = dfVariableMinPower.where (dfVariableMinPower > 0.0, 0.0)
|
|
130
|
-
dfVariableMaxPower = dfVariableMaxPower.where (dfVariableMaxPower > 0.0, 0.0)
|
|
131
|
-
dfVariableMinCharge = dfVariableMinCharge.where (dfVariableMinCharge > 0.0, 0.0)
|
|
132
|
-
dfVariableMaxCharge = dfVariableMaxCharge.where (dfVariableMaxCharge > 0.0, 0.0)
|
|
133
|
-
dfVariableMinStorage = dfVariableMinStorage.where (dfVariableMinStorage > 0.0, 0.0)
|
|
134
|
-
dfVariableMaxStorage = dfVariableMaxStorage.where (dfVariableMaxStorage > 0.0, 0.0)
|
|
135
|
-
dfVariableMinEnergy = dfVariableMinEnergy.where (dfVariableMinEnergy > 0.0, 0.0)
|
|
136
|
-
dfVariableMaxEnergy = dfVariableMaxEnergy.where (dfVariableMaxEnergy > 0.0, 0.0)
|
|
137
|
-
dfVariableFuelCost = dfVariableFuelCost.where (dfVariableFuelCost > 0.0, 0.0)
|
|
138
|
-
dfVariableEmissionCost = dfVariableEmissionCost.where(dfVariableEmissionCost > 0.0, 0.0)
|
|
139
|
-
dfEnergyInflows = dfEnergyInflows.where (dfEnergyInflows > 0.0, 0.0)
|
|
140
|
-
dfEnergyOutflows = dfEnergyOutflows.where (dfEnergyOutflows > 0.0, 0.0)
|
|
141
|
-
|
|
142
|
-
if pIndHydroTopology == 1:
|
|
143
|
-
dfVariableMinVolume = dfVariableMinVolume.where (dfVariableMinVolume > 0.0, 0.0)
|
|
144
|
-
dfVariableMaxVolume = dfVariableMaxVolume.where (dfVariableMaxVolume > 0.0, 0.0)
|
|
145
|
-
dfHydroInflows = dfHydroInflows.where (dfHydroInflows > 0.0, 0.0)
|
|
146
|
-
dfHydroOutflows = dfHydroOutflows.where (dfHydroOutflows > 0.0, 0.0)
|
|
147
|
-
|
|
148
|
-
# show some statistics of the data
|
|
149
|
-
if pIndLogConsole == 1:
|
|
150
|
-
print('Reserve margin electricity \n', dfReserveMargin.describe (), '\n')
|
|
151
|
-
print('Maximum CO2 emission \n', dfEmission.describe (), '\n')
|
|
152
|
-
print('Minimum RES energy \n', dfRESEnergy.describe (), '\n')
|
|
153
|
-
print('Electricity demand \n', dfDemand.describe (), '\n')
|
|
154
|
-
print('Inertia \n', dfInertia.describe (), '\n')
|
|
155
|
-
print('Upward operating reserves \n', dfUpOperatingReserve.describe (), '\n')
|
|
156
|
-
print('Downward operating reserves \n', dfDwOperatingReserve.describe (), '\n')
|
|
157
|
-
print('Generation \n', dfGeneration.describe (), '\n')
|
|
158
|
-
print('Variable minimum generation \n', dfVariableMinPower.describe (), '\n')
|
|
159
|
-
print('Variable maximum generation \n', dfVariableMaxPower.describe (), '\n')
|
|
160
|
-
print('Variable minimum consumption \n', dfVariableMinCharge.describe (), '\n')
|
|
161
|
-
print('Variable maximum consumption \n', dfVariableMaxCharge.describe (), '\n')
|
|
162
|
-
print('Variable minimum storage \n', dfVariableMinStorage.describe (), '\n')
|
|
163
|
-
print('Variable maximum storage \n', dfVariableMaxStorage.describe (), '\n')
|
|
164
|
-
print('Variable minimum energy \n', dfVariableMinEnergy.describe (), '\n')
|
|
165
|
-
print('Variable maximum energy \n', dfVariableMaxEnergy.describe (), '\n')
|
|
166
|
-
print('Variable fuel cost \n', dfVariableFuelCost.describe (), '\n')
|
|
167
|
-
print('Variable emission cost \n', dfVariableEmissionCost.describe(), '\n')
|
|
168
|
-
print('Energy inflows \n', dfEnergyInflows.describe (), '\n')
|
|
169
|
-
print('Energy outflows \n', dfEnergyOutflows.describe (), '\n')
|
|
170
|
-
print('Electric network \n', dfNetwork.describe (), '\n')
|
|
171
|
-
|
|
172
|
-
if pIndHydroTopology == 1:
|
|
173
|
-
print('Reservoir \n', dfReservoir.describe (), '\n')
|
|
174
|
-
print('Variable minimum reservoir volume \n', dfVariableMinVolume.describe (), '\n')
|
|
175
|
-
print('Variable maximum reservoir volume \n', dfVariableMaxVolume.describe (), '\n')
|
|
176
|
-
print('Hydro inflows \n', dfHydroInflows.describe (), '\n')
|
|
177
|
-
print('Hydro outflows \n', dfHydroOutflows.describe (), '\n')
|
|
178
|
-
|
|
179
|
-
if pIndHydrogen == 1:
|
|
180
|
-
print('Hydrogen demand \n', dfDemandHydrogen.describe (), '\n')
|
|
181
|
-
print('Hydrogen pipeline network \n', dfNetworkHydrogen.describe (), '\n')
|
|
182
|
-
|
|
183
|
-
if pIndHeat == 1:
|
|
184
|
-
print('Heat demand \n', dfDemandHeat.describe (), '\n')
|
|
185
|
-
print('Reserve margin heat \n', dfReserveMarginHeat.describe (), '\n')
|
|
186
|
-
print('Heat pipe network \n', dfNetworkHeat.describe (), '\n')
|
|
131
|
+
for key, df in dfs.items():
|
|
132
|
+
if 'dfEmission' in key:
|
|
133
|
+
df.fillna(math.inf, inplace=True)
|
|
134
|
+
elif 'dfGeneration' in key:
|
|
135
|
+
# build a dict that gives 1.0 for 'Efficiency', 0.0 for everything else
|
|
136
|
+
fill_values = {col: (1.0 if col == 'Efficiency' else 0.0) for col in df.columns}
|
|
137
|
+
# one pass over the DataFrame
|
|
138
|
+
df.fillna(fill_values, inplace=True)
|
|
139
|
+
else:
|
|
140
|
+
df.fillna(0.0, inplace=True)
|
|
141
|
+
|
|
142
|
+
# Define prefixes and suffixes
|
|
143
|
+
mTEPES.gen_frames_suffixes = ['VariableMinGeneration', 'VariableMaxGeneration',
|
|
144
|
+
'VariableMinConsumption', 'VariableMaxConsumption',
|
|
145
|
+
'VariableMinStorage', 'VariableMaxStorage',
|
|
146
|
+
'EnergyInflows',
|
|
147
|
+
'EnergyOutflows',
|
|
148
|
+
'VariableMinEnergy', 'VariableMaxEnergy',
|
|
149
|
+
'VariableFuelCost',
|
|
150
|
+
'VariableEmissionCost',]
|
|
151
|
+
mTEPES.node_frames_suffixes = ['Demand', 'Inertia']
|
|
152
|
+
mTEPES.area_frames_suffixes = ['OperatingReserveUp', 'OperatingReserveDown', 'ReserveMargin', 'Emission', 'RESEnergy']
|
|
153
|
+
mTEPES.hydro_frames_suffixes = ['Reservoir', 'VariableMinVolume', 'VariableMaxVolume', 'HydroInflows', 'HydroOutflows']
|
|
154
|
+
mTEPES.hydrogen_frames_suffixes = ['DemandHydrogen']
|
|
155
|
+
mTEPES.heat_frames_suffixes = ['DemandHeat', 'ReserveMarginHeat']
|
|
156
|
+
mTEPES.frames_suffixes = (mTEPES.gen_frames_suffixes + mTEPES.node_frames_suffixes + mTEPES.area_frames_suffixes +
|
|
157
|
+
mTEPES.hydro_frames_suffixes+ mTEPES.hydrogen_frames_suffixes + mTEPES.heat_frames_suffixes)
|
|
158
|
+
|
|
159
|
+
# Apply the condition to each specified column
|
|
160
|
+
for keys, df in dfs.items():
|
|
161
|
+
if [1 for suffix in mTEPES.gen_frames_suffixes if suffix in keys]:
|
|
162
|
+
dfs[keys] = df.where(df > 0.0, 0.0)
|
|
163
|
+
|
|
164
|
+
reading_time = round(time.time() - StartTime)
|
|
165
|
+
print('Reading the CSV files ... {} s'.format(reading_time))
|
|
166
|
+
StartTime = time.time()
|
|
187
167
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
dictSets.load(filename=f'{_path}/oT_Dict_Stage_' f'{CaseName}.csv', set='st' , format='set')
|
|
193
|
-
dictSets.load(filename=f'{_path}/oT_Dict_LoadLevel_' f'{CaseName}.csv', set='n' , format='set')
|
|
194
|
-
dictSets.load(filename=f'{_path}/oT_Dict_Generation_' f'{CaseName}.csv', set='g' , format='set')
|
|
195
|
-
dictSets.load(filename=f'{_path}/oT_Dict_Technology_' f'{CaseName}.csv', set='gt' , format='set')
|
|
196
|
-
dictSets.load(filename=f'{_path}/oT_Dict_Storage_' f'{CaseName}.csv', set='et' , format='set')
|
|
197
|
-
dictSets.load(filename=f'{_path}/oT_Dict_Node_' f'{CaseName}.csv', set='nd' , format='set')
|
|
198
|
-
dictSets.load(filename=f'{_path}/oT_Dict_Zone_' f'{CaseName}.csv', set='zn' , format='set')
|
|
199
|
-
dictSets.load(filename=f'{_path}/oT_Dict_Area_' f'{CaseName}.csv', set='ar' , format='set')
|
|
200
|
-
dictSets.load(filename=f'{_path}/oT_Dict_Region_' f'{CaseName}.csv', set='rg' , format='set')
|
|
201
|
-
dictSets.load(filename=f'{_path}/oT_Dict_Circuit_' f'{CaseName}.csv', set='cc' , format='set')
|
|
202
|
-
dictSets.load(filename=f'{_path}/oT_Dict_Line_' f'{CaseName}.csv', set='lt' , format='set')
|
|
203
|
-
|
|
204
|
-
dictSets.load(filename=f'{_path}/oT_Dict_NodeToZone_' f'{CaseName}.csv', set='ndzn', format='set')
|
|
205
|
-
dictSets.load(filename=f'{_path}/oT_Dict_ZoneToArea_' f'{CaseName}.csv', set='znar', format='set')
|
|
206
|
-
dictSets.load(filename=f'{_path}/oT_Dict_AreaToRegion_' f'{CaseName}.csv', set='arrg', format='set')
|
|
207
|
-
|
|
208
|
-
mTEPES.pp = Set(initialize=dictSets['p' ], doc='periods', within=PositiveIntegers)
|
|
209
|
-
mTEPES.scc = Set(initialize=dictSets['sc' ], doc='scenarios' )
|
|
210
|
-
mTEPES.stt = Set(initialize=dictSets['st' ], doc='stages' )
|
|
211
|
-
mTEPES.nn = Set(initialize=dictSets['n' ], doc='load levels' )
|
|
212
|
-
mTEPES.gg = Set(initialize=dictSets['g' ], doc='units' )
|
|
213
|
-
mTEPES.gt = Set(initialize=dictSets['gt' ], doc='technologies' )
|
|
214
|
-
mTEPES.nd = Set(initialize=dictSets['nd' ], doc='nodes' )
|
|
215
|
-
mTEPES.ni = Set(initialize=dictSets['nd' ], doc='nodes' )
|
|
216
|
-
mTEPES.nf = Set(initialize=dictSets['nd' ], doc='nodes' )
|
|
217
|
-
mTEPES.zn = Set(initialize=dictSets['zn' ], doc='zones' )
|
|
218
|
-
mTEPES.ar = Set(initialize=dictSets['ar' ], doc='areas' )
|
|
219
|
-
mTEPES.rg = Set(initialize=dictSets['rg' ], doc='regions' )
|
|
220
|
-
mTEPES.cc = Set(initialize=dictSets['cc' ], doc='circuits' )
|
|
221
|
-
mTEPES.c2 = Set(initialize=dictSets['cc' ], doc='circuits' )
|
|
222
|
-
mTEPES.lt = Set(initialize=dictSets['lt' ], doc='electric line types' )
|
|
223
|
-
mTEPES.ndzn = Set(initialize=dictSets['ndzn'], doc='node to zone' )
|
|
224
|
-
mTEPES.znar = Set(initialize=dictSets['znar'], doc='zone to area' )
|
|
225
|
-
mTEPES.arrg = Set(initialize=dictSets['arrg'], doc='area to region' )
|
|
168
|
+
if (dfs['dfGeneration']['Efficiency'] == 0).any():
|
|
169
|
+
print('WARNING: Efficiency values of 0.0 are not valid. They have been changed to 1.0.')
|
|
170
|
+
print("If you want to disable charging, set 'MaximumCharge' to 0.0 or leave it empty.")
|
|
171
|
+
dfs['dfGeneration']['Efficiency'] = dfs['dfGeneration']['Efficiency'].where(dfs['dfGeneration']['Efficiency'] != 0.0, 1.0)
|
|
226
172
|
|
|
173
|
+
# show some statistics of the data
|
|
174
|
+
for key, df in dfs.items():
|
|
175
|
+
if pIndLogConsole == 1 and [1 for suffix in mTEPES.frames_suffixes if suffix in key]:
|
|
176
|
+
print(f'{key}:\n', df.describe(), '\n')
|
|
177
|
+
# reading additional data sets related to reservoirs and hydro
|
|
227
178
|
try:
|
|
228
179
|
import csv
|
|
229
180
|
def count_lines_in_csv(csv_file_path):
|
|
@@ -266,76 +217,64 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
266
217
|
except:
|
|
267
218
|
pass
|
|
268
219
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
pIndBinRsrInvest = dfOption ['IndBinRsrInvest' ].iloc[0].astype('int') # Indicator of binary reservoir expansion decisions, 0 continuous - 1 binary - 2 no investment variables
|
|
273
|
-
pIndBinNetElecInvest = dfOption ['IndBinNetInvest' ].iloc[0].astype('int') # Indicator of binary electric network expansion decisions, 0 continuous - 1 binary - 2 no investment variables
|
|
274
|
-
pIndBinNetH2Invest = dfOption ['IndBinNetH2Invest' ].iloc[0].astype('int') # Indicator of binary hydrogen pipeline expansion decisions, 0 continuous - 1 binary - 2 no investment variables
|
|
275
|
-
pIndBinNetHeatInvest = dfOption ['IndBinNetHeatInvest'].iloc[0].astype('int') # Indicator of binary heat pipe expansion decisions, 0 continuous - 1 binary - 2 no investment variables
|
|
276
|
-
pIndBinGenOperat = dfOption ['IndBinGenOperat' ].iloc[0].astype('int') # Indicator of binary generation operation decisions, 0 continuous - 1 binary
|
|
277
|
-
pIndBinSingleNode = dfOption ['IndBinSingleNode' ].iloc[0].astype('int') # Indicator of single node although with electric network, 0 electric network - 1 single node
|
|
278
|
-
pIndBinGenRamps = dfOption ['IndBinGenRamps' ].iloc[0].astype('int') # Indicator of ramp constraints, 0 no ramps - 1 ramp constraints
|
|
279
|
-
pIndBinGenMinTime = dfOption ['IndBinGenMinTime' ].iloc[0].astype('int') # Indicator of minimum up/downtime constraints, 0 no min time - 1 min time constraints
|
|
280
|
-
pIndBinLineCommit = dfOption ['IndBinLineCommit' ].iloc[0].astype('int') # Indicator of binary electric network switching decisions, 0 continuous - 1 binary
|
|
281
|
-
pIndBinNetLosses = dfOption ['IndBinNetLosses' ].iloc[0].astype('int') # Indicator of electric network losses, 0 lossless - 1 ohmic losses
|
|
282
|
-
pENSCost = dfParameter['ENSCost' ].iloc[0] * 1e-3 # cost of energy not served [MEUR/GWh]
|
|
283
|
-
pH2NSCost = dfParameter['HNSCost' ].iloc[0] * 1e-3 # cost of hydrogen not served [MEUR/tH2]
|
|
284
|
-
pHeatNSCost = dfParameter['HTNSCost' ].iloc[0] * 1e-3 # cost of heat not served [MEUR/GWh]
|
|
285
|
-
pCO2Cost = dfParameter['CO2Cost' ].iloc[0] # cost of CO2 emission [EUR/tCO2]
|
|
286
|
-
pEconomicBaseYear = dfParameter['EconomicBaseYear' ].iloc[0] # economic base year [year]
|
|
287
|
-
pAnnualDiscRate = dfParameter['AnnualDiscountRate' ].iloc[0] # annual discount rate [p.u.]
|
|
288
|
-
pUpReserveActivation = dfParameter['UpReserveActivation'].iloc[0] # upward reserve activation [p.u.]
|
|
289
|
-
pDwReserveActivation = dfParameter['DwReserveActivation'].iloc[0] # downward reserve activation [p.u.]
|
|
290
|
-
pMinRatioDwUp = dfParameter['MinRatioDwUp' ].iloc[0] # minimum ratio down up operating reserves [p.u.]
|
|
291
|
-
pMaxRatioDwUp = dfParameter['MaxRatioDwUp' ].iloc[0] # maximum ratio down up operating reserves [p.u.]
|
|
292
|
-
pSBase = dfParameter['SBase' ].iloc[0] * 1e-3 # base power [GW]
|
|
293
|
-
pReferenceNode = dfParameter['ReferenceNode' ].iloc[0] # reference node
|
|
294
|
-
pTimeStep = dfParameter['TimeStep' ].iloc[0].astype('int') # duration of the unit time step [h]
|
|
295
|
-
|
|
296
|
-
pPeriodWeight = dfPeriod ['Weight' ].astype('int') # weights of periods [p.u.]
|
|
297
|
-
pScenProb = dfScenario ['Probability' ].astype('float64') # probabilities of scenarios [p.u.]
|
|
298
|
-
pStageWeight = dfStage ['Weight' ].astype('float64') # weights of stages
|
|
299
|
-
pDuration = dfDuration ['Duration' ] * pTimeStep # duration of load levels [h]
|
|
300
|
-
pLevelToStage = dfDuration ['Stage' ] # load levels assignment to stages
|
|
301
|
-
pReserveMargin = dfReserveMargin['ReserveMargin' ] # minimum adequacy reserve margin [p.u.]
|
|
302
|
-
pEmission = dfEmission ['CO2Emission' ] # maximum CO2 emission [MtCO2]
|
|
303
|
-
pRESEnergy = dfRESEnergy ['RESEnergy' ] # minimum RES energy [GWh]
|
|
304
|
-
pDemandElec = dfDemand.reindex (columns=mTEPES.nd, fill_value=0.0) * 1e-3 # electric demand [GW]
|
|
305
|
-
pSystemInertia = dfInertia.reindex (columns=mTEPES.ar, fill_value=0.0) # inertia [s]
|
|
306
|
-
pOperReserveUp = dfUpOperatingReserve.reindex (columns=mTEPES.ar, fill_value=0.0) * 1e-3 # upward operating reserve [GW]
|
|
307
|
-
pOperReserveDw = dfDwOperatingReserve.reindex (columns=mTEPES.ar, fill_value=0.0) * 1e-3 # downward operating reserve [GW]
|
|
308
|
-
|
|
309
|
-
pVariableMinPowerElec = dfVariableMinPower.reindex (columns=mTEPES.gg, fill_value=0.0) * 1e-3 # dynamic variable minimum power [GW]
|
|
310
|
-
pVariableMaxPowerElec = dfVariableMaxPower.reindex (columns=mTEPES.gg, fill_value=0.0) * 1e-3 # dynamic variable maximum power [GW]
|
|
311
|
-
pVariableMinCharge = dfVariableMinCharge.reindex (columns=mTEPES.gg, fill_value=0.0) * 1e-3 # dynamic variable minimum charge [GW]
|
|
312
|
-
pVariableMaxCharge = dfVariableMaxCharge.reindex (columns=mTEPES.gg, fill_value=0.0) * 1e-3 # dynamic variable maximum charge [GW]
|
|
313
|
-
pVariableMinStorage = dfVariableMinStorage.reindex (columns=mTEPES.gg, fill_value=0.0) # dynamic variable minimum storage [GWh]
|
|
314
|
-
pVariableMaxStorage = dfVariableMaxStorage.reindex (columns=mTEPES.gg, fill_value=0.0) # dynamic variable maximum storage [GWh]
|
|
315
|
-
pVariableMinEnergy = dfVariableMinEnergy.reindex (columns=mTEPES.gg, fill_value=0.0) * 1e-3 # dynamic variable minimum energy [GW]
|
|
316
|
-
pVariableMaxEnergy = dfVariableMaxEnergy.reindex (columns=mTEPES.gg, fill_value=0.0) * 1e-3 # dynamic variable maximum energy [GW]
|
|
317
|
-
pVariableFuelCost = dfVariableFuelCost.reindex (columns=mTEPES.gg, fill_value=0.0) # dynamic variable fuel cost [EUR/Mcal]
|
|
318
|
-
pVariableEmissionCost = dfVariableEmissionCost.reindex(columns=mTEPES.gg, fill_value=0.0) # dynamic variable emission cost [EUR/tCO2]
|
|
319
|
-
pEnergyInflows = dfEnergyInflows.reindex (columns=mTEPES.gg, fill_value=0.0) * 1e-3 # dynamic energy inflows [GW]
|
|
320
|
-
pEnergyOutflows = dfEnergyOutflows.reindex (columns=mTEPES.gg, fill_value=0.0) * 1e-3 # dynamic energy outflows [GW]
|
|
321
|
-
|
|
322
|
-
if pIndHydroTopology == 1:
|
|
323
|
-
pVariableMinVolume = dfVariableMinVolume.reindex (columns=mTEPES.rs, fill_value=0.0) # dynamic variable minimum reservoir volume [hm3]
|
|
324
|
-
pVariableMaxVolume = dfVariableMaxVolume.reindex (columns=mTEPES.rs, fill_value=0.0) # dynamic variable maximum reservoir volume [hm3]
|
|
325
|
-
pHydroInflows = dfHydroInflows.reindex (columns=mTEPES.rs, fill_value=0.0) # dynamic hydro inflows [m3/s]
|
|
326
|
-
pHydroOutflows = dfHydroOutflows.reindex (columns=mTEPES.rs, fill_value=0.0) # dynamic hydro outflows [m3/s]
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
if pIndHydrogen == 1:
|
|
331
|
-
pDemandH2 = dfDemandHydrogen [mTEPES.nd] # hydrogen demand [tH2/h]
|
|
332
|
-
|
|
333
|
-
if pIndHeat == 1:
|
|
334
|
-
pReserveMarginHeat = dfReserveMarginHeat ['ReserveMargin'] # minimum adequacy reserve margin [p.u.]
|
|
335
|
-
pDemandHeat = dfDemandHeat [mTEPES.nd] * 1e-3 # heat demand [GW]
|
|
336
|
-
|
|
337
|
-
if pTimeStep > 1:
|
|
220
|
+
# load parameters from dfOption
|
|
221
|
+
for col in dfs['dfOption'].columns:
|
|
222
|
+
par[f'p{col}'] = dfs['dfOption'][col].iloc[0].astype('int')
|
|
338
223
|
|
|
224
|
+
# load parameters from dfParameter
|
|
225
|
+
for col in dfs['dfParameter'].columns:
|
|
226
|
+
if col in ['ENSCost', 'HNSCost', 'HTNSCost', 'SBase']:
|
|
227
|
+
par[f'p{col}'] = dfs['dfParameter'][col].iloc[0] * factor_1
|
|
228
|
+
elif col in ['TimeStep']:
|
|
229
|
+
par[f'p{col}'] = dfs['dfParameter'][col].iloc[0].astype('int')
|
|
230
|
+
else:
|
|
231
|
+
par[f'p{col}'] = dfs['dfParameter'][col].iloc[0]
|
|
232
|
+
|
|
233
|
+
par['pPeriodWeight'] = dfs['dfPeriod'] ['Weight' ].astype('int') # weights of periods [p.u.]
|
|
234
|
+
par['pScenProb'] = dfs['dfScenario'] ['Probability' ].astype('float64') # probabilities of scenarios [p.u.]
|
|
235
|
+
par['pStageWeight'] = dfs['dfStage'] ['Weight' ].astype('float64') # weights of stages
|
|
236
|
+
par['pDuration'] = dfs['dfDuration'] ['Duration' ] * par['pTimeStep'] # duration of load levels [h]
|
|
237
|
+
par['pLevelToStage'] = dfs['dfDuration'] ['Stage' ] # load levels assignment to stages
|
|
238
|
+
par['pReserveMargin'] = dfs['dfReserveMargin']['ReserveMargin' ] # minimum adequacy reserve margin [p.u.]
|
|
239
|
+
par['pEmission'] = dfs['dfEmission'] ['CO2Emission' ] # maximum CO2 emission [MtCO2]
|
|
240
|
+
par['pRESEnergy'] = dfs['dfRESEnergy'] ['RESEnergy' ] # minimum RES energy [GWh]
|
|
241
|
+
par['pDemandElec'] = dfs['dfDemand'].reindex (columns=mTEPES.nd, fill_value=0.0) * 1e-3 # electric demand [GW]
|
|
242
|
+
par['pSystemInertia'] = dfs['dfInertia'].reindex (columns=mTEPES.ar, fill_value=0.0) # inertia [s]
|
|
243
|
+
par['pOperReserveUp'] = dfs['dfOperatingReserveUp'].reindex (columns=mTEPES.ar, fill_value=0.0) * 1e-3 # upward operating reserve [GW]
|
|
244
|
+
par['pOperReserveDw'] = dfs['dfOperatingReserveDown'].reindex (columns=mTEPES.ar, fill_value=0.0) * 1e-3 # downward operating reserve [GW]
|
|
245
|
+
par['pVariableMinPowerElec'] = dfs['dfVariableMinGeneration'].reindex (columns=mTEPES.gg, fill_value=0.0) * 1e-3 # dynamic variable minimum power [GW]
|
|
246
|
+
par['pVariableMaxPowerElec'] = dfs['dfVariableMaxGeneration'].reindex (columns=mTEPES.gg, fill_value=0.0) * 1e-3 # dynamic variable maximum power [GW]
|
|
247
|
+
par['pVariableMinCharge'] = dfs['dfVariableMinConsumption'].reindex(columns=mTEPES.gg, fill_value=0.0) * 1e-3 # dynamic variable minimum charge [GW]
|
|
248
|
+
par['pVariableMaxCharge'] = dfs['dfVariableMaxConsumption'].reindex(columns=mTEPES.gg, fill_value=0.0) * 1e-3 # dynamic variable maximum charge [GW]
|
|
249
|
+
par['pVariableMinStorage'] = dfs['dfVariableMinStorage'].reindex (columns=mTEPES.gg, fill_value=0.0) # dynamic variable minimum storage [GWh]
|
|
250
|
+
par['pVariableMaxStorage'] = dfs['dfVariableMaxStorage'].reindex (columns=mTEPES.gg, fill_value=0.0) # dynamic variable maximum storage [GWh]
|
|
251
|
+
par['pVariableMinEnergy'] = dfs['dfVariableMinEnergy'].reindex (columns=mTEPES.gg, fill_value=0.0) * 1e-3 # dynamic variable minimum energy [GW]
|
|
252
|
+
par['pVariableMaxEnergy'] = dfs['dfVariableMaxEnergy'].reindex (columns=mTEPES.gg, fill_value=0.0) * 1e-3 # dynamic variable maximum energy [GW]
|
|
253
|
+
par['pVariableFuelCost'] = dfs['dfVariableFuelCost'].reindex (columns=mTEPES.gg, fill_value=0.0) # dynamic variable fuel cost [EUR/MJ]
|
|
254
|
+
par['pVariableEmissionCost'] = dfs['dfVariableEmissionCost'].reindex (columns=mTEPES.gg, fill_value=0.0) # dynamic variable emission cost [EUR/tCO2]
|
|
255
|
+
par['pEnergyInflows'] = dfs['dfEnergyInflows'].reindex (columns=mTEPES.gg, fill_value=0.0) * 1e-3 # dynamic energy inflows [GW]
|
|
256
|
+
par['pEnergyOutflows'] = dfs['dfEnergyOutflows'].reindex (columns=mTEPES.gg, fill_value=0.0) * 1e-3 # dynamic energy outflows [GW]
|
|
257
|
+
|
|
258
|
+
if par['pIndVarTTC'] == 1:
|
|
259
|
+
par['pVariableNTCFrw'] = dfs['dfVariableTTCFrw'] * 1e-3 # variable TTC forward [GW]
|
|
260
|
+
par['pVariableNTCBck'] = dfs['dfVariableTTCBck'] * 1e-3 # variable TTC backward [GW]
|
|
261
|
+
if par['pIndPTDF'] == 1:
|
|
262
|
+
par['pVariablePTDF'] = dfs['dfVariablePTDF'] # variable PTDF [p.u.]
|
|
263
|
+
|
|
264
|
+
if par['pIndHydroTopology'] == 1:
|
|
265
|
+
par['pVariableMinVolume'] = dfs['dfVariableMinVolume'].reindex (columns=mTEPES.rs, fill_value=0.0) # dynamic variable minimum reservoir volume [hm3]
|
|
266
|
+
par['pVariableMaxVolume'] = dfs['dfVariableMaxVolume'].reindex (columns=mTEPES.rs, fill_value=0.0) # dynamic variable maximum reservoir volume [hm3]
|
|
267
|
+
par['pHydroInflows'] = dfs['dfHydroInflows'].reindex (columns=mTEPES.rs, fill_value=0.0) # dynamic hydro inflows [m3/s]
|
|
268
|
+
par['pHydroOutflows'] = dfs['dfHydroOutflows'].reindex (columns=mTEPES.rs, fill_value=0.0) # dynamic hydro outflows [m3/s]
|
|
269
|
+
|
|
270
|
+
if par['pIndHydrogen'] == 1:
|
|
271
|
+
par['pDemandH2'] = dfs['dfDemandHydrogen'] [mTEPES.nd] # hydrogen demand [tH2/h]
|
|
272
|
+
|
|
273
|
+
if par['pIndHeat'] == 1:
|
|
274
|
+
par['pReserveMarginHeat'] = dfs['dfReserveMarginHeat'] ['ReserveMargin'] # minimum adequacy reserve margin [p.u.]
|
|
275
|
+
par['pDemandHeat'] = dfs['dfDemandHeat'] [mTEPES.nd] * 1e-3 # heat demand [GW]
|
|
276
|
+
|
|
277
|
+
if par['pTimeStep'] > 1:
|
|
339
278
|
# compute the demand as the mean over the time step load levels and assign it to active load levels. Idem for the remaining parameters
|
|
340
279
|
# Skip mean calculation for empty DataFrames (either full of 0s or NaNs)
|
|
341
280
|
def ProcessParameter(pDataFrame: pd.DataFrame, pTimeStep: int) -> pd.DataFrame:
|
|
@@ -343,254 +282,269 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
343
282
|
pDataFrame = pDataFrame.rolling(pTimeStep).mean()
|
|
344
283
|
pDataFrame.fillna(0.0, inplace=True)
|
|
345
284
|
return pDataFrame
|
|
346
|
-
# Apply the ProcessParameter function to each DataFrame
|
|
347
|
-
pDemandElec = ProcessParameter(pDemandElec, pTimeStep)
|
|
348
|
-
pSystemInertia = ProcessParameter(pSystemInertia, pTimeStep)
|
|
349
|
-
pOperReserveUp = ProcessParameter(pOperReserveUp, pTimeStep)
|
|
350
|
-
pOperReserveDw = ProcessParameter(pOperReserveDw, pTimeStep)
|
|
351
|
-
pVariableMinPowerElec = ProcessParameter(pVariableMinPowerElec, pTimeStep)
|
|
352
|
-
pVariableMaxPowerElec = ProcessParameter(pVariableMaxPowerElec, pTimeStep)
|
|
353
|
-
pVariableMinCharge = ProcessParameter(pVariableMinCharge, pTimeStep)
|
|
354
|
-
pVariableMaxCharge = ProcessParameter(pVariableMaxCharge, pTimeStep)
|
|
355
|
-
pVariableMinStorage = ProcessParameter(pVariableMinStorage, pTimeStep)
|
|
356
|
-
pVariableMaxStorage = ProcessParameter(pVariableMaxStorage, pTimeStep)
|
|
357
|
-
pVariableMinEnergy = ProcessParameter(pVariableMinEnergy, pTimeStep)
|
|
358
|
-
pVariableMaxEnergy = ProcessParameter(pVariableMaxEnergy, pTimeStep)
|
|
359
|
-
pVariableFuelCost = ProcessParameter(pVariableFuelCost, pTimeStep)
|
|
360
|
-
pVariableEmissionCost = ProcessParameter(pVariableEmissionCost, pTimeStep)
|
|
361
|
-
pEnergyInflows = ProcessParameter(pEnergyInflows, pTimeStep)
|
|
362
|
-
pEnergyOutflows = ProcessParameter(pEnergyOutflows, pTimeStep)
|
|
363
285
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
286
|
+
# Apply the ProcessParameter function to each DataFrame
|
|
287
|
+
par['pDemandElec'] = ProcessParameter(par['pDemandElec'], par['pTimeStep'])
|
|
288
|
+
par['pSystemInertia'] = ProcessParameter(par['pSystemInertia'], par['pTimeStep'])
|
|
289
|
+
par['pOperReserveUp'] = ProcessParameter(par['pOperReserveUp'], par['pTimeStep'])
|
|
290
|
+
par['pOperReserveDw'] = ProcessParameter(par['pOperReserveDw'], par['pTimeStep'])
|
|
291
|
+
par['pVariableMinPowerElec'] = ProcessParameter(par['pVariableMinPowerElec'], par['pTimeStep'])
|
|
292
|
+
par['pVariableMaxPowerElec'] = ProcessParameter(par['pVariableMaxPowerElec'], par['pTimeStep'])
|
|
293
|
+
par['pVariableMinCharge'] = ProcessParameter(par['pVariableMinCharge'], par['pTimeStep'])
|
|
294
|
+
par['pVariableMaxCharge'] = ProcessParameter(par['pVariableMaxCharge'], par['pTimeStep'])
|
|
295
|
+
par['pVariableMinStorage'] = ProcessParameter(par['pVariableMinStorage'], par['pTimeStep'])
|
|
296
|
+
par['pVariableMaxStorage'] = ProcessParameter(par['pVariableMaxStorage'], par['pTimeStep'])
|
|
297
|
+
par['pVariableMinEnergy'] = ProcessParameter(par['pVariableMinEnergy'], par['pTimeStep'])
|
|
298
|
+
par['pVariableMaxEnergy'] = ProcessParameter(par['pVariableMaxEnergy'], par['pTimeStep'])
|
|
299
|
+
par['pVariableFuelCost'] = ProcessParameter(par['pVariableFuelCost'], par['pTimeStep'])
|
|
300
|
+
par['pVariableEmissionCost'] = ProcessParameter(par['pVariableEmissionCost'], par['pTimeStep'])
|
|
301
|
+
par['pEnergyInflows'] = ProcessParameter(par['pEnergyInflows'], par['pTimeStep'])
|
|
302
|
+
par['pEnergyOutflows'] = ProcessParameter(par['pEnergyOutflows'], par['pTimeStep'])
|
|
303
|
+
|
|
304
|
+
if par['pIndVarTTC'] == 1:
|
|
305
|
+
par['pVariableNTCFrw'] = ProcessParameter(par['pVariableNTCFrw'], par['pTimeStep'])
|
|
306
|
+
par['pVariableNTCBck'] = ProcessParameter(par['pVariableNTCBck'], par['pTimeStep'])
|
|
307
|
+
if par['pIndPTDF'] == 1:
|
|
308
|
+
par['pVariablePTDF'] = ProcessParameter(par['pVariablePTDF'], par['pTimeStep'])
|
|
309
|
+
|
|
310
|
+
if par['pIndHydroTopology'] == 1:
|
|
311
|
+
par['pVariableMinVolume'] = ProcessParameter(par['pVariableMinVolume'], par['pTimeStep'])
|
|
312
|
+
par['pVariableMaxVolume'] = ProcessParameter(par['pVariableMaxVolume'], par['pTimeStep'])
|
|
313
|
+
par['pHydroInflows'] = ProcessParameter(par['pHydroInflows'], par['pTimeStep'])
|
|
314
|
+
par['pHydroOutflows'] = ProcessParameter(par['pHydroOutflows'], par['pTimeStep'])
|
|
315
|
+
|
|
316
|
+
if par['pIndHydrogen'] == 1:
|
|
317
|
+
par['pDemandH2'] = ProcessParameter(par['pDemandH2'], par['pTimeStep'])
|
|
318
|
+
|
|
319
|
+
if par['pIndHeat'] == 1:
|
|
320
|
+
par['pDemandHeat'] = ProcessParameter(par['pDemandHeat'], par['pTimeStep'])
|
|
321
|
+
|
|
322
|
+
# assign duration 0 to load levels not being considered; active load levels are at the end of every pTimeStep
|
|
323
|
+
for n in range(par['pTimeStep']-2,-1,-1):
|
|
324
|
+
par['pDuration'].iloc[[range(n,len(mTEPES.pp)*len(mTEPES.scc)*len(mTEPES.nn),par['pTimeStep'])]] = 0
|
|
325
|
+
|
|
326
|
+
for psn in par['pDuration'].index:
|
|
381
327
|
p,sc,n = psn
|
|
382
|
-
if pPeriodWeight[p] == 0:
|
|
383
|
-
pDuration.loc[p,sc,n] = 0
|
|
384
|
-
if pScenProb[p,sc] == 0:
|
|
385
|
-
pDuration.loc[p,sc,n] = 0
|
|
328
|
+
if par['pPeriodWeight'][p] == 0:
|
|
329
|
+
par['pDuration'].loc[p,sc,n] = 0
|
|
330
|
+
if par['pScenProb'][p,sc] == 0:
|
|
331
|
+
par['pDuration'].loc[p,sc,n] = 0
|
|
386
332
|
|
|
387
333
|
#%% generation parameters
|
|
388
|
-
pGenToNode = dfGeneration ['Node' ]
|
|
389
|
-
pGenToTechnology = dfGeneration ['Technology' ]
|
|
390
|
-
pGenToExclusiveGen = dfGeneration ['MutuallyExclusive' ]
|
|
391
|
-
pIndBinUnitInvest = dfGeneration ['BinaryInvestment' ]
|
|
392
|
-
pIndBinUnitRetire = dfGeneration ['BinaryRetirement' ]
|
|
393
|
-
pIndBinUnitCommit = dfGeneration ['BinaryCommitment' ]
|
|
394
|
-
pIndBinStorInvest = dfGeneration ['StorageInvestment' ]
|
|
395
|
-
pIndOperReserve = dfGeneration ['NoOperatingReserve' ]
|
|
396
|
-
pIndOutflowIncomp = dfGeneration ['OutflowsIncompatibility' ]
|
|
397
|
-
pMustRun = dfGeneration ['MustRun' ]
|
|
398
|
-
pInertia = dfGeneration ['Inertia' ]
|
|
399
|
-
pElecGenPeriodIni = dfGeneration ['InitialPeriod' ]
|
|
400
|
-
pElecGenPeriodFin = dfGeneration ['FinalPeriod' ]
|
|
401
|
-
pAvailability = dfGeneration ['Availability' ]
|
|
402
|
-
pEFOR = dfGeneration ['EFOR' ]
|
|
403
|
-
pRatedMinPowerElec = dfGeneration ['MinimumPower' ] * 1e-3 * (1.0-dfGeneration['EFOR']) # rated minimum electric power [GW]
|
|
404
|
-
pRatedMaxPowerElec = dfGeneration ['MaximumPower' ] * 1e-3 * (1.0-dfGeneration['EFOR']) # rated maximum electric power [GW]
|
|
405
|
-
pRatedMinPowerHeat = dfGeneration ['MinimumPowerHeat' ] * 1e-3 * (1.0-dfGeneration['EFOR']) # rated minimum heat power [GW]
|
|
406
|
-
pRatedMaxPowerHeat = dfGeneration ['MaximumPowerHeat' ] * 1e-3 * (1.0-dfGeneration['EFOR']) # rated maximum heat power [GW]
|
|
407
|
-
pRatedLinearFuelCost = dfGeneration ['LinearTerm' ] * 1e-3 * dfGeneration['FuelCost'] # fuel term variable cost [MEUR/GWh]
|
|
408
|
-
pRatedConstantVarCost = dfGeneration ['ConstantTerm' ] * 1e-6 * dfGeneration['FuelCost'] # constant term variable cost [MEUR/h]
|
|
409
|
-
pLinearOMCost = dfGeneration ['OMVariableCost' ] * 1e-3
|
|
410
|
-
pOperReserveCost = dfGeneration ['OperReserveCost' ] * 1e-3
|
|
411
|
-
pStartUpCost = dfGeneration ['StartUpCost' ]
|
|
412
|
-
pShutDownCost = dfGeneration ['ShutDownCost' ]
|
|
413
|
-
pRampUp = dfGeneration ['RampUp' ] * 1e-3
|
|
414
|
-
pRampDw = dfGeneration ['RampDown' ] * 1e-3
|
|
415
|
-
pEmissionCost = dfGeneration ['CO2EmissionRate' ] * 1e-3 * pCO2Cost # CO2 emission cost [MEUR/GWh]
|
|
416
|
-
pEmissionRate = dfGeneration ['CO2EmissionRate' ]
|
|
417
|
-
pUpTime = dfGeneration ['UpTime' ]
|
|
418
|
-
pDwTime = dfGeneration ['DownTime' ]
|
|
419
|
-
pStableTime = dfGeneration ['StableTime' ]
|
|
420
|
-
pShiftTime = dfGeneration ['ShiftTime' ]
|
|
421
|
-
pGenInvestCost = dfGeneration ['FixedInvestmentCost' ] * dfGeneration['FixedChargeRate'] # generation fixed cost [MEUR]
|
|
422
|
-
pGenRetireCost = dfGeneration ['FixedRetirementCost' ] * dfGeneration['FixedChargeRate'] # generation fixed retirement cost [MEUR]
|
|
423
|
-
pRatedMinCharge = dfGeneration ['MinimumCharge' ] * 1e-3
|
|
424
|
-
pRatedMaxCharge = dfGeneration ['MaximumCharge' ] * 1e-3
|
|
425
|
-
pRatedMinStorage = dfGeneration ['MinimumStorage' ]
|
|
426
|
-
pRatedMaxStorage = dfGeneration ['MaximumStorage' ]
|
|
427
|
-
pInitialInventory = dfGeneration ['InitialStorage' ]
|
|
428
|
-
pProductionFunctionHydro = dfGeneration ['ProductionFunctionHydro' ]
|
|
429
|
-
pProductionFunctionH2 = dfGeneration ['ProductionFunctionH2' ] * 1e-3
|
|
430
|
-
pProductionFunctionHeat = dfGeneration ['ProductionFunctionHeat' ]
|
|
431
|
-
pProductionFunctionH2ToHeat = dfGeneration ['ProductionFunctionH2ToHeat'] * 1e-3
|
|
432
|
-
pEfficiency = dfGeneration ['Efficiency' ]
|
|
433
|
-
pStorageType = dfGeneration ['StorageType' ]
|
|
434
|
-
pOutflowsType = dfGeneration ['OutflowsType' ]
|
|
435
|
-
pEnergyType = dfGeneration ['EnergyType' ]
|
|
436
|
-
pRMaxReactivePower = dfGeneration ['MaximumReactivePower' ] * 1e-3
|
|
437
|
-
pGenLoInvest = dfGeneration ['InvestmentLo' ]
|
|
438
|
-
pGenUpInvest = dfGeneration ['InvestmentUp' ]
|
|
439
|
-
pGenLoRetire = dfGeneration ['RetirementLo' ]
|
|
440
|
-
pGenUpRetire = dfGeneration ['RetirementUp' ]
|
|
441
|
-
|
|
442
|
-
pRatedLinearOperCost = pRatedLinearFuelCost + pEmissionCost
|
|
443
|
-
pRatedLinearVarCost = pRatedLinearFuelCost + pLinearOMCost
|
|
444
|
-
|
|
445
|
-
if pIndHydroTopology == 1:
|
|
446
|
-
pReservoirType = dfReservoir ['StorageType' ]
|
|
447
|
-
pWaterOutfType = dfReservoir ['OutflowsType' ]
|
|
448
|
-
pRatedMinVolume = dfReservoir ['MinimumStorage' ]
|
|
449
|
-
pRatedMaxVolume = dfReservoir ['MaximumStorage' ]
|
|
450
|
-
pInitialVolume = dfReservoir ['InitialStorage' ]
|
|
451
|
-
pIndBinRsrvInvest = dfReservoir ['BinaryInvestment' ]
|
|
452
|
-
pRsrInvestCost = dfReservoir ['FixedInvestmentCost' ] * dfReservoir['FixedChargeRate'] # reservoir fixed cost [MEUR]
|
|
453
|
-
pRsrPeriodIni = dfReservoir ['InitialPeriod' ]
|
|
454
|
-
pRsrPeriodFin = dfReservoir ['FinalPeriod' ]
|
|
455
|
-
|
|
456
|
-
pNodeLat = dfNodeLocation['Latitude' ]
|
|
457
|
-
pNodeLon = dfNodeLocation['Longitude' ]
|
|
458
|
-
|
|
459
|
-
pLineType = dfNetwork ['LineType' ]
|
|
460
|
-
pLineLength = dfNetwork ['Length' ]
|
|
461
|
-
pLineVoltage = dfNetwork ['Voltage' ]
|
|
462
|
-
pElecNetPeriodIni = dfNetwork ['InitialPeriod' ]
|
|
463
|
-
pElecNetPeriodFin = dfNetwork ['FinalPeriod' ]
|
|
464
|
-
pLineLossFactor = dfNetwork ['LossFactor' ]
|
|
465
|
-
pLineR = dfNetwork ['Resistance' ]
|
|
466
|
-
pLineX = dfNetwork ['Reactance' ].sort_index()
|
|
467
|
-
pLineBsh = dfNetwork ['Susceptance' ]
|
|
468
|
-
pLineTAP = dfNetwork ['Tap' ]
|
|
469
|
-
pLineNTCFrw = dfNetwork ['TTC' ] * 1e-3 * dfNetwork['SecurityFactor' ] # net transfer capacity in forward direction [GW]
|
|
470
|
-
pLineNTCBck = dfNetwork ['TTCBck' ] * 1e-3 * dfNetwork['SecurityFactor' ] # net transfer capacity in backward direction [GW]
|
|
471
|
-
pNetFixedCost = dfNetwork ['FixedInvestmentCost' ] * dfNetwork['FixedChargeRate'] # electric network fixed cost [MEUR]
|
|
472
|
-
pIndBinLineSwitch = dfNetwork ['Switching' ]
|
|
473
|
-
pIndBinLineInvest = dfNetwork ['BinaryInvestment' ]
|
|
474
|
-
pSwitchOnTime = dfNetwork ['SwOnTime' ].astype('int')
|
|
475
|
-
pSwitchOffTime = dfNetwork ['SwOffTime' ].astype('int')
|
|
476
|
-
pAngMin = dfNetwork ['AngMin' ] * math.pi / 180
|
|
477
|
-
pAngMax = dfNetwork ['AngMax' ] * math.pi / 180
|
|
478
|
-
pNetLoInvest = dfNetwork ['InvestmentLo' ]
|
|
479
|
-
pNetUpInvest = dfNetwork ['InvestmentUp' ]
|
|
334
|
+
par['pGenToNode'] = dfs['dfGeneration'] ['Node' ] # generator location in node
|
|
335
|
+
par['pGenToTechnology'] = dfs['dfGeneration'] ['Technology' ] # generator association to technology
|
|
336
|
+
par['pGenToExclusiveGen'] = dfs['dfGeneration'] ['MutuallyExclusive' ] # mutually exclusive generator
|
|
337
|
+
par['pIndBinUnitInvest'] = dfs['dfGeneration'] ['BinaryInvestment' ] # binary unit investment decision [Yes]
|
|
338
|
+
par['pIndBinUnitRetire'] = dfs['dfGeneration'] ['BinaryRetirement' ] # binary unit retirement decision [Yes]
|
|
339
|
+
par['pIndBinUnitCommit'] = dfs['dfGeneration'] ['BinaryCommitment' ] # binary unit commitment decision [Yes]
|
|
340
|
+
par['pIndBinStorInvest'] = dfs['dfGeneration'] ['StorageInvestment' ] # storage linked to generation investment [Yes]
|
|
341
|
+
par['pIndOperReserve'] = dfs['dfGeneration'] ['NoOperatingReserve' ] # no contribution to operating reserve [Yes]
|
|
342
|
+
par['pIndOutflowIncomp'] = dfs['dfGeneration'] ['OutflowsIncompatibility' ] # outflows incompatibility with charging
|
|
343
|
+
par['pMustRun'] = dfs['dfGeneration'] ['MustRun' ] # must-run unit [Yes]
|
|
344
|
+
par['pInertia'] = dfs['dfGeneration'] ['Inertia' ] # inertia constant [s]
|
|
345
|
+
par['pElecGenPeriodIni'] = dfs['dfGeneration'] ['InitialPeriod' ] # initial period [year]
|
|
346
|
+
par['pElecGenPeriodFin'] = dfs['dfGeneration'] ['FinalPeriod' ] # final period [year]
|
|
347
|
+
par['pAvailability'] = dfs['dfGeneration'] ['Availability' ] # unit availability for adequacy [p.u.]
|
|
348
|
+
par['pEFOR'] = dfs['dfGeneration'] ['EFOR' ] # EFOR [p.u.]
|
|
349
|
+
par['pRatedMinPowerElec'] = dfs['dfGeneration'] ['MinimumPower' ] * 1e-3 * (1.0-dfs['dfGeneration']['EFOR']) # rated minimum electric power [GW]
|
|
350
|
+
par['pRatedMaxPowerElec'] = dfs['dfGeneration'] ['MaximumPower' ] * 1e-3 * (1.0-dfs['dfGeneration']['EFOR']) # rated maximum electric power [GW]
|
|
351
|
+
par['pRatedMinPowerHeat'] = dfs['dfGeneration'] ['MinimumPowerHeat' ] * 1e-3 * (1.0-dfs['dfGeneration']['EFOR']) # rated minimum heat power [GW]
|
|
352
|
+
par['pRatedMaxPowerHeat'] = dfs['dfGeneration'] ['MaximumPowerHeat' ] * 1e-3 * (1.0-dfs['dfGeneration']['EFOR']) # rated maximum heat power [GW]
|
|
353
|
+
par['pRatedLinearFuelCost'] = dfs['dfGeneration'] ['LinearTerm' ] * 1e-3 * dfs['dfGeneration']['FuelCost'] # fuel term variable cost [MEUR/GWh]
|
|
354
|
+
par['pRatedConstantVarCost'] = dfs['dfGeneration'] ['ConstantTerm' ] * 1e-6 * dfs['dfGeneration']['FuelCost'] # constant term variable cost [MEUR/h]
|
|
355
|
+
par['pLinearOMCost'] = dfs['dfGeneration'] ['OMVariableCost' ] * 1e-3 # O&M term variable cost [MEUR/GWh]
|
|
356
|
+
par['pOperReserveCost'] = dfs['dfGeneration'] ['OperReserveCost' ] * 1e-3 # operating reserve cost [MEUR/GW]
|
|
357
|
+
par['pStartUpCost'] = dfs['dfGeneration'] ['StartUpCost' ] # startup cost [MEUR]
|
|
358
|
+
par['pShutDownCost'] = dfs['dfGeneration'] ['ShutDownCost' ] # shutdown cost [MEUR]
|
|
359
|
+
par['pRampUp'] = dfs['dfGeneration'] ['RampUp' ] * 1e-3 # ramp up rate [GW/h]
|
|
360
|
+
par['pRampDw'] = dfs['dfGeneration'] ['RampDown' ] * 1e-3 # ramp down rate [GW/h]
|
|
361
|
+
par['pEmissionCost'] = dfs['dfGeneration'] ['CO2EmissionRate' ] * 1e-3 * par['pCO2Cost'] # CO2 emission cost [MEUR/GWh]
|
|
362
|
+
par['pEmissionRate'] = dfs['dfGeneration'] ['CO2EmissionRate' ] # CO2 emission rate [tCO2/MWh]
|
|
363
|
+
par['pUpTime'] = dfs['dfGeneration'] ['UpTime' ] # minimum up time [h]
|
|
364
|
+
par['pDwTime'] = dfs['dfGeneration'] ['DownTime' ] # minimum down time [h]
|
|
365
|
+
par['pStableTime'] = dfs['dfGeneration'] ['StableTime' ] # minimum stable time [h]
|
|
366
|
+
par['pShiftTime'] = dfs['dfGeneration'] ['ShiftTime' ] # maximum shift time for DSM [h]
|
|
367
|
+
par['pGenInvestCost'] = dfs['dfGeneration'] ['FixedInvestmentCost' ] * dfs['dfGeneration']['FixedChargeRate'] # generation fixed cost [MEUR]
|
|
368
|
+
par['pGenRetireCost'] = dfs['dfGeneration'] ['FixedRetirementCost' ] * dfs['dfGeneration']['FixedChargeRate'] # generation fixed retirement cost [MEUR]
|
|
369
|
+
par['pRatedMinCharge'] = dfs['dfGeneration'] ['MinimumCharge' ] * 1e-3 # rated minimum ESS charge [GW]
|
|
370
|
+
par['pRatedMaxCharge'] = dfs['dfGeneration'] ['MaximumCharge' ] * 1e-3 # rated maximum ESS charge [GW]
|
|
371
|
+
par['pRatedMinStorage'] = dfs['dfGeneration'] ['MinimumStorage' ] # rated minimum ESS storage [GWh]
|
|
372
|
+
par['pRatedMaxStorage'] = dfs['dfGeneration'] ['MaximumStorage' ] # rated maximum ESS storage [GWh]
|
|
373
|
+
par['pInitialInventory'] = dfs['dfGeneration'] ['InitialStorage' ] # initial ESS storage [GWh]
|
|
374
|
+
par['pProductionFunctionHydro'] = dfs['dfGeneration'] ['ProductionFunctionHydro' ] # production function of a hydropower plant [kWh/m3]
|
|
375
|
+
par['pProductionFunctionH2'] = dfs['dfGeneration'] ['ProductionFunctionH2' ] * 1e-3 # production function of an electrolyzer [kWh/gH2]
|
|
376
|
+
par['pProductionFunctionHeat'] = dfs['dfGeneration'] ['ProductionFunctionHeat' ] # production function of a heat pump [kWh/kWh]
|
|
377
|
+
par['pProductionFunctionH2ToHeat'] = dfs['dfGeneration'] ['ProductionFunctionH2ToHeat'] * 1e-3 # production function of a boiler using H2 [gH2/kWh]
|
|
378
|
+
par['pEfficiency'] = dfs['dfGeneration'] ['Efficiency' ] # ESS round-trip efficiency [p.u.]
|
|
379
|
+
par['pStorageType'] = dfs['dfGeneration'] ['StorageType' ] # ESS storage type
|
|
380
|
+
par['pOutflowsType'] = dfs['dfGeneration'] ['OutflowsType' ] # ESS outflows type
|
|
381
|
+
par['pEnergyType'] = dfs['dfGeneration'] ['EnergyType' ] # unit energy type
|
|
382
|
+
par['pRMaxReactivePower'] = dfs['dfGeneration'] ['MaximumReactivePower' ] * 1e-3 # rated maximum reactive power [Gvar]
|
|
383
|
+
par['pGenLoInvest'] = dfs['dfGeneration'] ['InvestmentLo' ] # Lower bound of the investment decision [p.u.]
|
|
384
|
+
par['pGenUpInvest'] = dfs['dfGeneration'] ['InvestmentUp' ] # Upper bound of the investment decision [p.u.]
|
|
385
|
+
par['pGenLoRetire'] = dfs['dfGeneration'] ['RetirementLo' ] # Lower bound of the retirement decision [p.u.]
|
|
386
|
+
par['pGenUpRetire'] = dfs['dfGeneration'] ['RetirementUp' ] # Upper bound of the retirement decision [p.u.]
|
|
387
|
+
|
|
388
|
+
par['pRatedLinearOperCost'] = par['pRatedLinearFuelCost'] + par['pEmissionCost']
|
|
389
|
+
par['pRatedLinearVarCost'] = par['pRatedLinearFuelCost'] + par['pLinearOMCost']
|
|
390
|
+
|
|
391
|
+
if par['pIndHydroTopology'] == 1:
|
|
392
|
+
par['pReservoirType'] = dfs['dfReservoir'] ['StorageType' ] # reservoir type
|
|
393
|
+
par['pWaterOutfType'] = dfs['dfReservoir'] ['OutflowsType' ] # water outflow type
|
|
394
|
+
par['pRatedMinVolume'] = dfs['dfReservoir'] ['MinimumStorage' ] # rated minimum reservoir volume [hm3]
|
|
395
|
+
par['pRatedMaxVolume'] = dfs['dfReservoir'] ['MaximumStorage' ] # rated maximum reservoir volume [hm3]
|
|
396
|
+
par['pInitialVolume'] = dfs['dfReservoir'] ['InitialStorage' ] # initial reservoir volume [hm3]
|
|
397
|
+
par['pIndBinRsrvInvest'] = dfs['dfReservoir'] ['BinaryInvestment' ] # binary reservoir investment decision [Yes]
|
|
398
|
+
par['pRsrInvestCost'] = dfs['dfReservoir'] ['FixedInvestmentCost' ] * dfs['dfReservoir']['FixedChargeRate'] # reservoir fixed cost [MEUR]
|
|
399
|
+
par['pRsrPeriodIni'] = dfs['dfReservoir'] ['InitialPeriod' ] # initial period [year]
|
|
400
|
+
par['pRsrPeriodFin'] = dfs['dfReservoir'] ['FinalPeriod' ] # final period [year]
|
|
401
|
+
|
|
402
|
+
par['pNodeLat'] = dfs['dfNodeLocation']['Latitude' ] # node latitude [º]
|
|
403
|
+
par['pNodeLon'] = dfs['dfNodeLocation']['Longitude' ] # node longitude [º]
|
|
404
|
+
|
|
405
|
+
par['pLineType'] = dfs['dfNetwork'] ['LineType' ] # electric line type
|
|
406
|
+
par['pLineLength'] = dfs['dfNetwork'] ['Length' ] # electric line length [km]
|
|
407
|
+
par['pLineVoltage'] = dfs['dfNetwork'] ['Voltage' ] # electric line voltage [kV]
|
|
408
|
+
par['pElecNetPeriodIni'] = dfs['dfNetwork'] ['InitialPeriod' ] # initial period
|
|
409
|
+
par['pElecNetPeriodFin'] = dfs['dfNetwork'] ['FinalPeriod' ] # final period
|
|
410
|
+
par['pLineLossFactor'] = dfs['dfNetwork'] ['LossFactor' ] # electric line loss factor [p.u.]
|
|
411
|
+
par['pLineR'] = dfs['dfNetwork'] ['Resistance' ] # electric line resistance [p.u.]
|
|
412
|
+
par['pLineX'] = dfs['dfNetwork'] ['Reactance' ].sort_index() # electric line reactance [p.u.]
|
|
413
|
+
par['pLineBsh'] = dfs['dfNetwork'] ['Susceptance' ] # electric line susceptance [p.u.]
|
|
414
|
+
par['pLineTAP'] = dfs['dfNetwork'] ['Tap' ] # tap changer [p.u.]
|
|
415
|
+
par['pLineNTCFrw'] = dfs['dfNetwork'] ['TTC' ] * 1e-3 * dfs['dfNetwork']['SecurityFactor' ] # net transfer capacity in forward direction [GW]
|
|
416
|
+
par['pLineNTCBck'] = dfs['dfNetwork'] ['TTCBck' ] * 1e-3 * dfs['dfNetwork']['SecurityFactor' ] # net transfer capacity in backward direction [GW]
|
|
417
|
+
par['pNetFixedCost'] = dfs['dfNetwork'] ['FixedInvestmentCost' ] * dfs['dfNetwork']['FixedChargeRate'] # electric network fixed cost [MEUR]
|
|
418
|
+
par['pIndBinLineSwitch'] = dfs['dfNetwork'] ['Switching' ] # binary electric line switching decision [Yes]
|
|
419
|
+
par['pIndBinLineInvest'] = dfs['dfNetwork'] ['BinaryInvestment' ] # binary electric line investment decision [Yes]
|
|
420
|
+
par['pSwitchOnTime'] = dfs['dfNetwork'] ['SwOnTime' ].astype('int') # minimum on time [h]
|
|
421
|
+
par['pSwitchOffTime'] = dfs['dfNetwork'] ['SwOffTime' ].astype('int') # minimum off time [h]
|
|
422
|
+
par['pAngMin'] = dfs['dfNetwork'] ['AngMin' ] * math.pi / 180 # Min phase angle difference [rad]
|
|
423
|
+
par['pAngMax'] = dfs['dfNetwork'] ['AngMax' ] * math.pi / 180 # Max phase angle difference [rad]
|
|
424
|
+
par['pNetLoInvest'] = dfs['dfNetwork'] ['InvestmentLo' ] # Lower bound of the investment decision [p.u.]
|
|
425
|
+
par['pNetUpInvest'] = dfs['dfNetwork'] ['InvestmentUp' ] # Upper bound of the investment decision [p.u.]
|
|
480
426
|
|
|
481
427
|
# replace PeriodFin = 0.0 by year 3000
|
|
482
|
-
pElecGenPeriodFin = pElecGenPeriodFin.where(pElecGenPeriodFin != 0.0, 3000 )
|
|
483
|
-
if pIndHydroTopology == 1:
|
|
484
|
-
pRsrPeriodFin = pRsrPeriodFin.where (pRsrPeriodFin != 0.0, 3000 )
|
|
485
|
-
pElecNetPeriodFin = pElecNetPeriodFin.where(pElecNetPeriodFin != 0.0, 3000 )
|
|
428
|
+
par['pElecGenPeriodFin'] = par['pElecGenPeriodFin'].where(par['pElecGenPeriodFin'] != 0.0, 3000 )
|
|
429
|
+
if par['pIndHydroTopology'] == 1:
|
|
430
|
+
par['pRsrPeriodFin'] = par['pRsrPeriodFin'].where (par['pRsrPeriodFin'] != 0.0, 3000 )
|
|
431
|
+
par['pElecNetPeriodFin'] = par['pElecNetPeriodFin'].where(par['pElecNetPeriodFin'] != 0.0, 3000 )
|
|
486
432
|
# replace pLineNTCBck = 0.0 by pLineNTCFrw
|
|
487
|
-
pLineNTCBck = pLineNTCBck.where (pLineNTCBck > 0.0, pLineNTCFrw)
|
|
433
|
+
par['pLineNTCBck'] = par['pLineNTCBck'].where (par['pLineNTCBck'] > 0.0, par['pLineNTCFrw'])
|
|
488
434
|
# replace pLineNTCFrw = 0.0 by pLineNTCBck
|
|
489
|
-
pLineNTCFrw = pLineNTCFrw.where (pLineNTCFrw > 0.0, pLineNTCBck)
|
|
435
|
+
par['pLineNTCFrw'] = par['pLineNTCFrw'].where (par['pLineNTCFrw'] > 0.0, par['pLineNTCBck'])
|
|
490
436
|
# replace pGenUpInvest = 0.0 by 1.0
|
|
491
|
-
pGenUpInvest = pGenUpInvest.where (pGenUpInvest > 0.0, 1.0
|
|
437
|
+
par['pGenUpInvest'] = par['pGenUpInvest'].where (par['pGenUpInvest'] > 0.0, 1.0 )
|
|
492
438
|
# replace pGenUpRetire = 0.0 by 1.0
|
|
493
|
-
pGenUpRetire = pGenUpRetire.where (pGenUpRetire > 0.0, 1.0
|
|
439
|
+
par['pGenUpRetire'] = par['pGenUpRetire'].where (par['pGenUpRetire'] > 0.0, 1.0 )
|
|
494
440
|
# replace pNetUpInvest = 0.0 by 1.0
|
|
495
|
-
pNetUpInvest = pNetUpInvest.where (pNetUpInvest > 0.0, 1.0
|
|
441
|
+
par['pNetUpInvest'] = par['pNetUpInvest'].where (par['pNetUpInvest'] > 0.0, 1.0 )
|
|
496
442
|
|
|
497
443
|
# minimum up- and downtime converted to an integer number of time steps
|
|
498
|
-
pSwitchOnTime = round(pSwitchOnTime /pTimeStep).astype('int')
|
|
499
|
-
pSwitchOffTime = round(pSwitchOffTime/pTimeStep).astype('int')
|
|
500
|
-
|
|
501
|
-
if pIndHydrogen == 1:
|
|
502
|
-
pH2PipeLength = dfNetworkHydrogen['Length' ]
|
|
503
|
-
pH2PipePeriodIni = dfNetworkHydrogen['InitialPeriod' ]
|
|
504
|
-
pH2PipePeriodFin = dfNetworkHydrogen['FinalPeriod' ]
|
|
505
|
-
pH2PipeNTCFrw = dfNetworkHydrogen['TTC' ] * dfNetworkHydrogen['SecurityFactor' ] # net transfer capacity in forward direction [tH2]
|
|
506
|
-
pH2PipeNTCBck = dfNetworkHydrogen['TTCBck' ] * dfNetworkHydrogen['SecurityFactor' ] # net transfer capacity in backward direction [tH2]
|
|
507
|
-
pH2PipeFixedCost = dfNetworkHydrogen['FixedInvestmentCost'] * dfNetworkHydrogen['FixedChargeRate'] # hydrogen network fixed cost [MEUR]
|
|
508
|
-
pIndBinH2PipeInvest = dfNetworkHydrogen['BinaryInvestment' ]
|
|
509
|
-
pH2PipeLoInvest = dfNetworkHydrogen['InvestmentLo' ]
|
|
510
|
-
pH2PipeUpInvest = dfNetworkHydrogen['InvestmentUp' ]
|
|
511
|
-
|
|
512
|
-
pH2PipePeriodFin = pH2PipePeriodFin.where(pH2PipePeriodFin != 0.0, 3000 )
|
|
444
|
+
par['pSwitchOnTime'] = round(par['pSwitchOnTime'] /par['pTimeStep']).astype('int')
|
|
445
|
+
par['pSwitchOffTime'] = round(par['pSwitchOffTime']/par['pTimeStep']).astype('int')
|
|
446
|
+
|
|
447
|
+
if par['pIndHydrogen'] == 1:
|
|
448
|
+
par['pH2PipeLength'] = dfs['dfNetworkHydrogen']['Length' ] # hydrogen line length [km]
|
|
449
|
+
par['pH2PipePeriodIni'] = dfs['dfNetworkHydrogen']['InitialPeriod' ] # initial period
|
|
450
|
+
par['pH2PipePeriodFin'] = dfs['dfNetworkHydrogen']['FinalPeriod' ] # final period
|
|
451
|
+
par['pH2PipeNTCFrw'] = dfs['dfNetworkHydrogen']['TTC' ] * dfs['dfNetworkHydrogen']['SecurityFactor' ] # net transfer capacity in forward direction [tH2]
|
|
452
|
+
par['pH2PipeNTCBck'] = dfs['dfNetworkHydrogen']['TTCBck' ] * dfs['dfNetworkHydrogen']['SecurityFactor' ] # net transfer capacity in backward direction [tH2]
|
|
453
|
+
par['pH2PipeFixedCost'] = dfs['dfNetworkHydrogen']['FixedInvestmentCost'] * dfs['dfNetworkHydrogen']['FixedChargeRate'] # hydrogen network fixed cost [MEUR]
|
|
454
|
+
par['pIndBinH2PipeInvest'] = dfs['dfNetworkHydrogen']['BinaryInvestment' ] # binary hydrogen pipeline investment decision [Yes]
|
|
455
|
+
par['pH2PipeLoInvest'] = dfs['dfNetworkHydrogen']['InvestmentLo' ] # Lower bound of the investment decision [p.u.]
|
|
456
|
+
par['pH2PipeUpInvest'] = dfs['dfNetworkHydrogen']['InvestmentUp' ] # Upper bound of the investment decision [p.u.]
|
|
457
|
+
|
|
458
|
+
par['pH2PipePeriodFin'] = par['pH2PipePeriodFin'].where(par['pH2PipePeriodFin'] != 0.0, 3000 )
|
|
513
459
|
# replace pH2PipeNTCBck = 0.0 by pH2PipeNTCFrw
|
|
514
|
-
pH2PipeNTCBck
|
|
460
|
+
par['pH2PipeNTCBck'] = par['pH2PipeNTCBck'].where (par['pH2PipeNTCBck'] > 0.0, par['pH2PipeNTCFrw'])
|
|
515
461
|
# replace pH2PipeNTCFrw = 0.0 by pH2PipeNTCBck
|
|
516
|
-
pH2PipeNTCFrw
|
|
462
|
+
par['pH2PipeNTCFrw'] = par['pH2PipeNTCFrw'].where (par['pH2PipeNTCFrw'] > 0.0, par['pH2PipeNTCBck'])
|
|
517
463
|
# replace pH2PipeUpInvest = 0.0 by 1.0
|
|
518
|
-
pH2PipeUpInvest
|
|
519
|
-
|
|
520
|
-
if pIndHeat == 1:
|
|
521
|
-
pHeatPipeLength = dfNetworkHeat['Length' ]
|
|
522
|
-
pHeatPipePeriodIni = dfNetworkHeat['InitialPeriod' ]
|
|
523
|
-
pHeatPipePeriodFin = dfNetworkHeat['FinalPeriod' ]
|
|
524
|
-
pHeatPipeNTCFrw = dfNetworkHeat['TTC' ] * 1e-3 * dfNetworkHeat ['SecurityFactor' ] # net transfer capacity in forward direction [GW]
|
|
525
|
-
pHeatPipeNTCBck = dfNetworkHeat['TTCBck' ] * 1e-3 * dfNetworkHeat ['SecurityFactor' ] # net transfer capacity in backward direction [GW]
|
|
526
|
-
pHeatPipeFixedCost = dfNetworkHeat['FixedInvestmentCost'] * dfNetworkHeat ['FixedChargeRate'] # heat network fixed cost [MEUR]
|
|
527
|
-
pIndBinHeatPipeInvest = dfNetworkHeat['BinaryInvestment' ]
|
|
528
|
-
pHeatPipeLoInvest = dfNetworkHeat['InvestmentLo' ]
|
|
529
|
-
pHeatPipeUpInvest = dfNetworkHeat['InvestmentUp' ]
|
|
530
|
-
|
|
531
|
-
pHeatPipePeriodFin
|
|
464
|
+
par['pH2PipeUpInvest'] = par['pH2PipeUpInvest'].where(par['pH2PipeUpInvest'] > 0.0, 1.0 )
|
|
465
|
+
|
|
466
|
+
if par['pIndHeat'] == 1:
|
|
467
|
+
par['pHeatPipeLength'] = dfs['dfNetworkHeat']['Length' ] # heat pipe length [km]
|
|
468
|
+
par['pHeatPipePeriodIni'] = dfs['dfNetworkHeat']['InitialPeriod' ] # initial period
|
|
469
|
+
par['pHeatPipePeriodFin'] = dfs['dfNetworkHeat']['FinalPeriod' ] # final period
|
|
470
|
+
par['pHeatPipeNTCFrw'] = dfs['dfNetworkHeat']['TTC' ] * 1e-3 * dfs['dfNetworkHeat'] ['SecurityFactor' ] # net transfer capacity in forward direction [GW]
|
|
471
|
+
par['pHeatPipeNTCBck'] = dfs['dfNetworkHeat']['TTCBck' ] * 1e-3 * dfs['dfNetworkHeat'] ['SecurityFactor' ] # net transfer capacity in backward direction [GW]
|
|
472
|
+
par['pHeatPipeFixedCost'] = dfs['dfNetworkHeat']['FixedInvestmentCost'] * dfs['dfNetworkHeat'] ['FixedChargeRate'] # heat network fixed cost [MEUR]
|
|
473
|
+
par['pIndBinHeatPipeInvest'] = dfs['dfNetworkHeat']['BinaryInvestment' ] # binary heat pipe investment decision [Yes]
|
|
474
|
+
par['pHeatPipeLoInvest'] = dfs['dfNetworkHeat']['InvestmentLo' ] # Lower bound of the investment decision [p.u.]
|
|
475
|
+
par['pHeatPipeUpInvest'] = dfs['dfNetworkHeat']['InvestmentUp' ] # Upper bound of the investment decision [p.u.]
|
|
476
|
+
|
|
477
|
+
par['pHeatPipePeriodFin'] = par['pHeatPipePeriodFin'].where(par['pHeatPipePeriodFin'] != 0.0, 3000 )
|
|
532
478
|
# replace pHeatPipeNTCBck = 0.0 by pHeatPipeNTCFrw
|
|
533
|
-
pHeatPipeNTCBck
|
|
479
|
+
par['pHeatPipeNTCBck'] = par['pHeatPipeNTCBck'].where (par['pHeatPipeNTCBck'] > 0.0, par['pHeatPipeNTCFrw'])
|
|
534
480
|
# replace pHeatPipeNTCFrw = 0.0 by pHeatPipeNTCBck
|
|
535
|
-
pHeatPipeNTCFrw
|
|
481
|
+
par['pHeatPipeNTCFrw'] = par['pHeatPipeNTCFrw'].where (par['pHeatPipeNTCFrw'] > 0.0, par['pHeatPipeNTCBck'])
|
|
536
482
|
# replace pHeatPipeUpInvest = 0.0 by 1.0
|
|
537
|
-
pHeatPipeUpInvest
|
|
483
|
+
par['pHeatPipeUpInvest'] = par['pHeatPipeUpInvest'].where (par['pHeatPipeUpInvest'] > 0.0, 1.0 )
|
|
484
|
+
|
|
485
|
+
#%% storing the parameters in the model
|
|
486
|
+
mTEPES.dFrame = dfs
|
|
487
|
+
mTEPES.dPar = par
|
|
538
488
|
|
|
539
489
|
ReadingDataTime = time.time() - StartTime
|
|
540
490
|
StartTime = time.time()
|
|
541
491
|
print('Reading input data ... ', round(ReadingDataTime), 's')
|
|
542
492
|
|
|
493
|
+
|
|
494
|
+
def DataConfiguration(mTEPES):
|
|
495
|
+
|
|
496
|
+
StartTime = time.time()
|
|
543
497
|
#%% Getting the branches from the electric network data
|
|
544
|
-
sBr = [(ni,nf) for (ni,nf,cc) in dfNetwork.index]
|
|
498
|
+
sBr = [(ni,nf) for (ni,nf,cc) in mTEPES.dFrame['dfNetwork'].index]
|
|
545
499
|
# Dropping duplicate keys
|
|
546
500
|
sBrList = [(ni,nf) for n,(ni,nf) in enumerate(sBr) if (ni,nf) not in sBr[:n]]
|
|
547
501
|
|
|
548
502
|
#%% defining subsets: active load levels (n,n2), thermal units (t), RES units (r), ESS units (es), candidate gen units (gc), candidate ESS units (ec), all the electric lines (la), candidate electric lines (lc), candidate DC electric lines (cd), existing DC electric lines (cd), electric lines with losses (ll), reference node (rf), and reactive generating units (gq)
|
|
549
|
-
mTEPES.p = Set(doc='periods' , initialize=[pp for pp in mTEPES.pp if pPeriodWeight [pp] > 0.0 and sum(pDuration[pp,sc,n] for sc,n in mTEPES.scc*mTEPES.nn)])
|
|
550
|
-
mTEPES.sc = Set(doc='scenarios' , initialize=[scc for scc in mTEPES.scc
|
|
551
|
-
mTEPES.ps = Set(doc='periods/scenarios' , initialize=[(p,sc) for p,sc in mTEPES.p*mTEPES.sc if pScenProb [p,sc] > 0.0 and sum(pDuration[p,sc,n ] for n in mTEPES.nn)])
|
|
552
|
-
mTEPES.st = Set(doc='stages' , initialize=[stt for stt in mTEPES.stt if pStageWeight [stt] > 0.0])
|
|
553
|
-
mTEPES.n = Set(doc='load levels' , initialize=[nn for nn in mTEPES.nn if sum(pDuration [p,sc,nn] for p,sc in mTEPES.ps) > 0])
|
|
554
|
-
mTEPES.n2 = Set(doc='load levels' , initialize=[nn for nn in mTEPES.nn if sum(pDuration [p,sc,nn] for p,sc in mTEPES.ps) > 0])
|
|
555
|
-
mTEPES.g = Set(doc='generating units' , initialize=[gg for gg in mTEPES.gg if (pRatedMaxPowerElec [gg] > 0.0 or pRatedMaxCharge[gg] > 0.0
|
|
556
|
-
mTEPES.t = Set(doc='thermal units' , initialize=[g for g in mTEPES.g if pRatedLinearOperCost[g ] > 0.0])
|
|
557
|
-
mTEPES.re = Set(doc='RES units' , initialize=[g for g in mTEPES.g if pRatedLinearOperCost[g ] == 0.0 and pRatedMaxStorage[g] == 0.0 and pProductionFunctionH2[g ] == 0.0 and pProductionFunctionHeat[g ]
|
|
558
|
-
mTEPES.es = Set(doc='ESS units' , initialize=[g for g in mTEPES.g if (pRatedMaxCharge[g ] > 0.0 or pRatedMaxStorage[g] > 0.0 or pProductionFunctionH2[g ] > 0.0 or pProductionFunctionHeat[g ]
|
|
559
|
-
mTEPES.h = Set(doc='hydro units' , initialize=[g for g in mTEPES.g
|
|
560
|
-
mTEPES.el = Set(doc='electrolyzer units' , initialize=[es for es in mTEPES.es
|
|
561
|
-
mTEPES.hp = Set(doc='heat pump & elec boiler units' , initialize=[es for es in mTEPES.es
|
|
562
|
-
mTEPES.ch = Set(doc='CHP & fuel boiler units' , initialize=[g for g in mTEPES.g if
|
|
563
|
-
mTEPES.bo = Set(doc=' fuel boiler units' , initialize=[ch for ch in mTEPES.ch if pRatedMaxPowerElec [ch] == 0.0 and pRatedMaxPowerHeat[ch] > 0.0 and pProductionFunctionHeat [ch] == 0.0])
|
|
564
|
-
mTEPES.hh = Set(doc=' hydrogen boiler units' , initialize=[bo for bo in mTEPES.bo
|
|
565
|
-
mTEPES.gc = Set(doc='candidate units' , initialize=[g for g in mTEPES.g if pGenInvestCost [g ] > 0.0])
|
|
566
|
-
mTEPES.gd = Set(doc='retirement units' , initialize=[g for g in mTEPES.g if pGenRetireCost [g ] > 0.0])
|
|
567
|
-
mTEPES.ec = Set(doc='candidate ESS units' , initialize=[es for es in mTEPES.es if pGenInvestCost [es] > 0.0])
|
|
568
|
-
mTEPES.bc = Set(doc='candidate boiler units' , initialize=[bo for bo in mTEPES.bo if pGenInvestCost [bo] > 0.0])
|
|
503
|
+
mTEPES.p = Set(doc='periods' , initialize=[pp for pp in mTEPES.pp if mTEPES.dPar['pPeriodWeight'] [pp] > 0.0 and sum(mTEPES.dPar['pDuration'][pp,sc,n] for sc,n in mTEPES.scc*mTEPES.nn)])
|
|
504
|
+
mTEPES.sc = Set(doc='scenarios' , initialize=[scc for scc in mTEPES.scc ])
|
|
505
|
+
mTEPES.ps = Set(doc='periods/scenarios' , initialize=[(p,sc) for p,sc in mTEPES.p*mTEPES.sc if mTEPES.dPar['pScenProb'] [p,sc] > 0.0 and sum(mTEPES.dPar['pDuration'][p,sc,n ] for n in mTEPES.nn)])
|
|
506
|
+
mTEPES.st = Set(doc='stages' , initialize=[stt for stt in mTEPES.stt if mTEPES.dPar['pStageWeight'] [stt] > 0.0])
|
|
507
|
+
mTEPES.n = Set(doc='load levels' , initialize=[nn for nn in mTEPES.nn if sum(mTEPES.dPar['pDuration'] [p,sc,nn] for p,sc in mTEPES.ps) > 0])
|
|
508
|
+
mTEPES.n2 = Set(doc='load levels' , initialize=[nn for nn in mTEPES.nn if sum(mTEPES.dPar['pDuration'] [p,sc,nn] for p,sc in mTEPES.ps) > 0])
|
|
509
|
+
mTEPES.g = Set(doc='generating units' , initialize=[gg for gg in mTEPES.gg if (mTEPES.dPar['pRatedMaxPowerElec'] [gg] > 0.0 or mTEPES.dPar['pRatedMaxCharge'][gg] > 0.0 or mTEPES.dPar['pRatedMaxPowerHeat'] [gg] > 0.0) and mTEPES.dPar['pElecGenPeriodIni'][gg] <= mTEPES.p.last() and mTEPES.dPar['pElecGenPeriodFin'][gg] >= mTEPES.p.first() and mTEPES.dPar['pGenToNode'].reset_index().set_index(['Generator']).isin(mTEPES.nd)['Node'][gg]]) # excludes generators with empty node
|
|
510
|
+
mTEPES.t = Set(doc='thermal units' , initialize=[g for g in mTEPES.g if mTEPES.dPar['pRatedLinearOperCost'][g ] > 0.0])
|
|
511
|
+
mTEPES.re = Set(doc='RES units' , initialize=[g for g in mTEPES.g if mTEPES.dPar['pRatedLinearOperCost'][g ] == 0.0 and mTEPES.dPar['pRatedMaxStorage'][g] == 0.0 and mTEPES.dPar['pProductionFunctionH2'][g ] == 0.0 and mTEPES.dPar['pProductionFunctionHeat'][g ] == 0.0 and mTEPES.dPar['pProductionFunctionHydro'][g ] == 0.0])
|
|
512
|
+
mTEPES.es = Set(doc='ESS units' , initialize=[g for g in mTEPES.g if (mTEPES.dPar['pRatedMaxCharge'][g ] > 0.0 or mTEPES.dPar['pRatedMaxStorage'][g] > 0.0 or mTEPES.dPar['pProductionFunctionH2'][g ] > 0.0 or mTEPES.dPar['pProductionFunctionHeat'][g ] > 0.0) and mTEPES.dPar['pProductionFunctionHydro'][g ] == 0.0])
|
|
513
|
+
mTEPES.h = Set(doc='hydro units' , initialize=[g for g in mTEPES.g if mTEPES.dPar['pProductionFunctionH2'][g ] == 0.0 and mTEPES.dPar['pProductionFunctionHeat'][g ] == 0.0 and mTEPES.dPar['pProductionFunctionHydro'][g ] > 0.0])
|
|
514
|
+
mTEPES.el = Set(doc='electrolyzer units' , initialize=[es for es in mTEPES.es if mTEPES.dPar['pProductionFunctionH2'][es] > 0.0 and mTEPES.dPar['pProductionFunctionHeat'][es] == 0.0 and mTEPES.dPar['pProductionFunctionHydro'][es] == 0.0])
|
|
515
|
+
mTEPES.hp = Set(doc='heat pump & elec boiler units' , initialize=[es for es in mTEPES.es if mTEPES.dPar['pProductionFunctionH2'][es] == 0.0 and mTEPES.dPar['pProductionFunctionHeat'][es] > 0.0 and mTEPES.dPar['pProductionFunctionHydro'][es] == 0.0])
|
|
516
|
+
mTEPES.ch = Set(doc='CHP & fuel boiler units' , initialize=[g for g in mTEPES.g if mTEPES.dPar['pRatedMaxPowerHeat'][g ] > 0.0 and mTEPES.dPar['pProductionFunctionHeat'] [g ] == 0.0])
|
|
517
|
+
mTEPES.bo = Set(doc=' fuel boiler units' , initialize=[ch for ch in mTEPES.ch if mTEPES.dPar['pRatedMaxPowerElec'] [ch] == 0.0 and mTEPES.dPar['pRatedMaxPowerHeat'][ch] > 0.0 and mTEPES.dPar['pProductionFunctionHeat'] [ch] == 0.0])
|
|
518
|
+
mTEPES.hh = Set(doc=' hydrogen boiler units' , initialize=[bo for bo in mTEPES.bo if mTEPES.dPar['pProductionFunctionH2ToHeat'][bo] > 0.0])
|
|
519
|
+
mTEPES.gc = Set(doc='candidate units' , initialize=[g for g in mTEPES.g if mTEPES.dPar['pGenInvestCost'] [g ] > 0.0])
|
|
520
|
+
mTEPES.gd = Set(doc='retirement units' , initialize=[g for g in mTEPES.g if mTEPES.dPar['pGenRetireCost'] [g ] > 0.0])
|
|
521
|
+
mTEPES.ec = Set(doc='candidate ESS units' , initialize=[es for es in mTEPES.es if mTEPES.dPar['pGenInvestCost'] [es] > 0.0])
|
|
522
|
+
mTEPES.bc = Set(doc='candidate boiler units' , initialize=[bo for bo in mTEPES.bo if mTEPES.dPar['pGenInvestCost'] [bo] > 0.0])
|
|
569
523
|
mTEPES.br = Set(doc='all input electric branches', initialize=sBrList )
|
|
570
|
-
mTEPES.ln = Set(doc='all input electric lines' , initialize=dfNetwork.index)
|
|
571
|
-
if len(mTEPES.ln) != len(dfNetwork.index):
|
|
572
|
-
raise ValueError('### Some electric lines are invalid ', len(mTEPES.ln), len(dfNetwork.index))
|
|
573
|
-
mTEPES.la = Set(doc='all real electric lines' , initialize=[ln for ln in mTEPES.ln if pLineX [ln] != 0.0 and pLineNTCFrw[ln] > 0.0 and pLineNTCBck[ln] > 0.0 and pElecNetPeriodIni[ln] <= mTEPES.p.last() and pElecNetPeriodFin[ln] >= mTEPES.p.first()])
|
|
574
|
-
mTEPES.ls = Set(doc='all real switch electric lines' , initialize=[la for la in mTEPES.la if pIndBinLineSwitch [la] ])
|
|
575
|
-
mTEPES.lc = Set(doc='candidate electric lines' , initialize=[la for la in mTEPES.la if pNetFixedCost [la] > 0.0])
|
|
576
|
-
mTEPES.cd = Set(doc='candidate DC electric lines' , initialize=[la for la in mTEPES.la if pNetFixedCost [la] > 0.0 and pLineType[la] == 'DC'])
|
|
577
|
-
mTEPES.ed = Set(doc='existing DC electric lines' , initialize=[la for la in mTEPES.la if pNetFixedCost [la] == 0.0 and pLineType[la] == 'DC'])
|
|
578
|
-
mTEPES.ll = Set(doc='loss electric lines' , initialize=[la for la in mTEPES.la if pLineLossFactor [la] > 0.0 and pIndBinNetLosses > 0 ])
|
|
579
|
-
mTEPES.rf = Set(doc='reference node' , initialize=[pReferenceNode])
|
|
580
|
-
mTEPES.gq = Set(doc='gen reactive units' , initialize=[gg for gg in mTEPES.gg if pRMaxReactivePower [gg] > 0.0 and
|
|
581
|
-
mTEPES.sq = Set(doc='synchr reactive units' , initialize=[gg for gg in mTEPES.gg if pRMaxReactivePower [gg] > 0.0 and pGenToTechnology[gg] == 'SynchronousCondenser' and pElecGenPeriodIni[gg] <= mTEPES.p.last() and pElecGenPeriodFin[gg] >= mTEPES.p.first()])
|
|
524
|
+
mTEPES.ln = Set(doc='all input electric lines' , initialize=mTEPES.dFrame['dfNetwork'].index)
|
|
525
|
+
if len(mTEPES.ln) != len(mTEPES.dFrame['dfNetwork'].index):
|
|
526
|
+
raise ValueError('### Some electric lines are invalid ', len(mTEPES.ln), len(mTEPES.dFrame['dfNetwork'].index))
|
|
527
|
+
mTEPES.la = Set(doc='all real electric lines' , initialize=[ln for ln in mTEPES.ln if mTEPES.dPar['pLineX'] [ln] != 0.0 and mTEPES.dPar['pLineNTCFrw'][ln] > 0.0 and mTEPES.dPar['pLineNTCBck'][ln] > 0.0 and mTEPES.dPar['pElecNetPeriodIni'][ln] <= mTEPES.p.last() and mTEPES.dPar['pElecNetPeriodFin'][ln] >= mTEPES.p.first()])
|
|
528
|
+
mTEPES.ls = Set(doc='all real switch electric lines' , initialize=[la for la in mTEPES.la if mTEPES.dPar['pIndBinLineSwitch'] [la] ])
|
|
529
|
+
mTEPES.lc = Set(doc='candidate electric lines' , initialize=[la for la in mTEPES.la if mTEPES.dPar['pNetFixedCost'] [la] > 0.0])
|
|
530
|
+
mTEPES.cd = Set(doc='candidate DC electric lines' , initialize=[la for la in mTEPES.la if mTEPES.dPar['pNetFixedCost'] [la] > 0.0 and mTEPES.dPar['pLineType'][la] == 'DC'])
|
|
531
|
+
mTEPES.ed = Set(doc='existing DC electric lines' , initialize=[la for la in mTEPES.la if mTEPES.dPar['pNetFixedCost'] [la] == 0.0 and mTEPES.dPar['pLineType'][la] == 'DC'])
|
|
532
|
+
mTEPES.ll = Set(doc='loss electric lines' , initialize=[la for la in mTEPES.la if mTEPES.dPar['pLineLossFactor'] [la] > 0.0 and mTEPES.dPar['pIndBinNetLosses'] > 0 ])
|
|
533
|
+
mTEPES.rf = Set(doc='reference node' , initialize=[mTEPES.dPar['pReferenceNode']])
|
|
534
|
+
mTEPES.gq = Set(doc='gen reactive units' , initialize=[gg for gg in mTEPES.gg if mTEPES.dPar['pRMaxReactivePower'] [gg] > 0.0 and mTEPES.dPar['pElecGenPeriodIni'][gg] <= mTEPES.p.last() and mTEPES.dPar['pElecGenPeriodFin'][gg] >= mTEPES.p.first()])
|
|
535
|
+
mTEPES.sq = Set(doc='synchr reactive units' , initialize=[gg for gg in mTEPES.gg if mTEPES.dPar['pRMaxReactivePower'] [gg] > 0.0 and mTEPES.dPar['pGenToTechnology'][gg] == 'SynchronousCondenser' and mTEPES.dPar['pElecGenPeriodIni'][gg] <= mTEPES.p.last() and mTEPES.dPar['pElecGenPeriodFin'][gg] >= mTEPES.p.first()])
|
|
582
536
|
mTEPES.sqc = Set(doc='synchr reactive candidate')
|
|
583
537
|
mTEPES.shc = Set(doc='shunt candidate')
|
|
584
|
-
if pIndHydroTopology == 1:
|
|
585
|
-
mTEPES.rn = Set(doc='candidate reservoirs' , initialize=[rs for rs in mTEPES.rs
|
|
538
|
+
if mTEPES.dPar['pIndHydroTopology'] == 1:
|
|
539
|
+
mTEPES.rn = Set(doc='candidate reservoirs' , initialize=[rs for rs in mTEPES.rs if mTEPES.dPar['pRsrInvestCost'] [rs] > 0.0 and mTEPES.dPar['pRsrPeriodIni'][rs] <= mTEPES.p.last() and mTEPES.dPar['pRsrPeriodFin'][rs] >= mTEPES.p.first()])
|
|
586
540
|
else:
|
|
587
541
|
mTEPES.rn = Set(doc='candidate reservoirs' , initialize=[])
|
|
588
|
-
if pIndHydrogen == 1:
|
|
589
|
-
mTEPES.pn = Set(doc='all input hydrogen pipes' , initialize=dfNetworkHydrogen.index)
|
|
590
|
-
if len(mTEPES.pn) != len(dfNetworkHydrogen.index):
|
|
591
|
-
raise ValueError('### Some hydrogen pipes are invalid ', len(mTEPES.pn), len(dfNetworkHydrogen.index))
|
|
592
|
-
mTEPES.pa = Set(doc='all real hydrogen pipes' , initialize=[pn for pn in mTEPES.pn
|
|
593
|
-
mTEPES.pc = Set(doc='candidate hydrogen pipes' , initialize=[pa for pa in mTEPES.pa
|
|
542
|
+
if mTEPES.dPar['pIndHydrogen'] == 1:
|
|
543
|
+
mTEPES.pn = Set(doc='all input hydrogen pipes' , initialize=mTEPES.dFrame['dfNetworkHydrogen'].index)
|
|
544
|
+
if len(mTEPES.pn) != len(mTEPES.dFrame['dfNetworkHydrogen'].index):
|
|
545
|
+
raise ValueError('### Some hydrogen pipes are invalid ', len(mTEPES.pn), len(mTEPES.dFrame['dfNetworkHydrogen'].index))
|
|
546
|
+
mTEPES.pa = Set(doc='all real hydrogen pipes' , initialize=[pn for pn in mTEPES.pn if mTEPES.dPar['pH2PipeNTCFrw'] [pn] > 0.0 and mTEPES.dPar['pH2PipeNTCBck'][pn] > 0.0 and mTEPES.dPar['pH2PipePeriodIni'][pn] <= mTEPES.p.last() and mTEPES.dPar['pH2PipePeriodFin'][pn] >= mTEPES.p.first()])
|
|
547
|
+
mTEPES.pc = Set(doc='candidate hydrogen pipes' , initialize=[pa for pa in mTEPES.pa if mTEPES.dPar['pH2PipeFixedCost'] [pa] > 0.0])
|
|
594
548
|
# existing hydrogen pipelines (pe)
|
|
595
549
|
mTEPES.pe = mTEPES.pa - mTEPES.pc
|
|
596
550
|
else:
|
|
@@ -598,12 +552,12 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
598
552
|
mTEPES.pa = Set(doc='all real hydrogen pipes' , initialize=[])
|
|
599
553
|
mTEPES.pc = Set(doc='candidate hydrogen pipes' , initialize=[])
|
|
600
554
|
|
|
601
|
-
if pIndHeat == 1:
|
|
602
|
-
mTEPES.hn = Set(doc='all input heat pipes' , initialize=dfNetworkHeat.index)
|
|
603
|
-
if len(mTEPES.hn) != len(dfNetworkHeat.index):
|
|
604
|
-
raise ValueError('### Some heat pipes are invalid ', len(mTEPES.hn), len(dfNetworkHeat.index))
|
|
605
|
-
mTEPES.ha = Set(doc='all real heat pipes' , initialize=[hn for hn in mTEPES.hn if pHeatPipeNTCFrw [hn] > 0.0 and pHeatPipeNTCBck[hn] > 0.0 and pHeatPipePeriodIni[hn] <= mTEPES.p.last() and pHeatPipePeriodFin[hn] >= mTEPES.p.first()])
|
|
606
|
-
mTEPES.hc = Set(doc='candidate heat pipes' , initialize=[ha for ha in mTEPES.ha if pHeatPipeFixedCost [ha] > 0.0])
|
|
555
|
+
if mTEPES.dPar['pIndHeat'] == 1:
|
|
556
|
+
mTEPES.hn = Set(doc='all input heat pipes' , initialize=mTEPES.dFrame['dfNetworkHeat'].index)
|
|
557
|
+
if len(mTEPES.hn) != len(mTEPES.dFrame['dfNetworkHeat'].index):
|
|
558
|
+
raise ValueError('### Some heat pipes are invalid ', len(mTEPES.hn), len(mTEPES.dFrame['dfNetworkHeat'].index))
|
|
559
|
+
mTEPES.ha = Set(doc='all real heat pipes' , initialize=[hn for hn in mTEPES.hn if mTEPES.dPar['pHeatPipeNTCFrw'] [hn] > 0.0 and mTEPES.dPar['pHeatPipeNTCBck'][hn] > 0.0 and mTEPES.dPar['pHeatPipePeriodIni'][hn] <= mTEPES.p.last() and mTEPES.dPar['pHeatPipePeriodFin'][hn] >= mTEPES.p.first()])
|
|
560
|
+
mTEPES.hc = Set(doc='candidate heat pipes' , initialize=[ha for ha in mTEPES.ha if mTEPES.dPar['pHeatPipeFixedCost'] [ha] > 0.0])
|
|
607
561
|
# existing heat pipes (he)
|
|
608
562
|
mTEPES.he = mTEPES.ha - mTEPES.hc
|
|
609
563
|
else:
|
|
@@ -611,6 +565,16 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
611
565
|
mTEPES.ha = Set(doc='all real heat pipes' , initialize=[])
|
|
612
566
|
mTEPES.hc = Set(doc='candidate heat pipes' , initialize=[])
|
|
613
567
|
|
|
568
|
+
mTEPES.dPar['pIndBinLinePTDF'] = pd.Series(index=mTEPES.la, data=0.0) # indicate if the line has a PTDF or not
|
|
569
|
+
if mTEPES.dPar['pIndVarTTC'] == 1:
|
|
570
|
+
mTEPES.dPar['pVariableNTCFrw'] = mTEPES.dPar['pVariableNTCFrw'].reindex(columns=mTEPES.la, fill_value=0.0) * mTEPES.dFrame['dfNetwork']['SecurityFactor'] # variable NTC forward direction because of the security factor
|
|
571
|
+
mTEPES.dPar['pVariableNTCBck'] = mTEPES.dPar['pVariableNTCBck'].reindex(columns=mTEPES.la, fill_value=0.0) * mTEPES.dFrame['dfNetwork']['SecurityFactor'] # variable NTC backward direction because of the security factor
|
|
572
|
+
if mTEPES.dPar['pIndPTDF'] == 1:
|
|
573
|
+
# get the level_3, level_4, and level_5 from multiindex of pVariablePTDF
|
|
574
|
+
PTDF_columns = mTEPES.dPar['pVariablePTDF'].columns
|
|
575
|
+
PTDF_lines = PTDF_columns.droplevel([3]).drop_duplicates()
|
|
576
|
+
mTEPES.dPar['pIndBinLinePTDF'].loc[:] = mTEPES.dPar['pIndBinLinePTDF'].index.isin(PTDF_lines).astype(float)
|
|
577
|
+
|
|
614
578
|
# non-RES units, they can be committed and also contribute to the operating reserves
|
|
615
579
|
mTEPES.nr = mTEPES.g - mTEPES.re
|
|
616
580
|
# machines able to provide reactive power
|
|
@@ -627,17 +591,14 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
627
591
|
mTEPES.eb = mTEPES.gc | mTEPES.bc
|
|
628
592
|
|
|
629
593
|
#%% inverse index load level to stage
|
|
630
|
-
pStageToLevel = pLevelToStage.reset_index().set_index(['Period','Scenario','Stage'])['LoadLevel']
|
|
594
|
+
mTEPES.dPar['pStageToLevel'] = mTEPES.dPar['pLevelToStage'].reset_index().set_index(['Period','Scenario','Stage'])['LoadLevel']
|
|
631
595
|
#Filter only valid indices
|
|
632
|
-
pStageToLevel = pStageToLevel.loc[
|
|
633
|
-
pStageToLevel.index.isin([(p, s, st) for (p, s) in mTEPES.ps for st in mTEPES.st]) &
|
|
634
|
-
pStageToLevel.isin(mTEPES.n)
|
|
635
|
-
]
|
|
596
|
+
mTEPES.dPar['pStageToLevel'] = mTEPES.dPar['pStageToLevel'].loc[mTEPES.dPar['pStageToLevel'].index.isin([(p,s,st) for (p,s) in mTEPES.ps for st in mTEPES.st]) & mTEPES.dPar['pStageToLevel'].isin(mTEPES.n)]
|
|
636
597
|
#Reorder the elements
|
|
637
|
-
pStageToLevel = [(p,sc,st,n) for (p,sc,st),n in pStageToLevel.items()]
|
|
638
|
-
mTEPES.s2n = Set(initialize=pStageToLevel, doc='Load level to stage')
|
|
598
|
+
mTEPES.dPar['pStageToLevel'] = [(p,sc,st,n) for (p,sc,st),n in mTEPES.dPar['pStageToLevel'].items()]
|
|
599
|
+
mTEPES.s2n = Set(initialize=mTEPES.dPar['pStageToLevel'], doc='Load level to stage')
|
|
639
600
|
# all the stages must have the same duration
|
|
640
|
-
pStageDuration = pd.Series([sum(pDuration[p,sc,n] for p,sc,st2,n in mTEPES.s2n if st2 == st) for st in mTEPES.st], index=mTEPES.st)
|
|
601
|
+
mTEPES.dPar['pStageDuration'] = pd.Series([sum(mTEPES.dPar['pDuration'][p,sc,n] for p,sc,st2,n in mTEPES.s2n if st2 == st) for st in mTEPES.st], index=mTEPES.st)
|
|
641
602
|
# for st in mTEPES.st:
|
|
642
603
|
# if mTEPES.st.ord(st) > 1 and pStageDuration[st] != pStageDuration[mTEPES.st.prev(st)]:
|
|
643
604
|
# assert (0 == 1)
|
|
@@ -645,14 +606,14 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
645
606
|
# delete all the load level belonging to stages with duration equal to zero
|
|
646
607
|
mTEPES.del_component(mTEPES.n )
|
|
647
608
|
mTEPES.del_component(mTEPES.n2)
|
|
648
|
-
mTEPES.n = Set(doc='load levels', initialize=[nn for nn in mTEPES.nn if sum(pDuration[p,sc,nn] for p,sc in mTEPES.ps) > 0])
|
|
649
|
-
mTEPES.n2 = Set(doc='load levels', initialize=[nn for nn in mTEPES.nn if sum(pDuration[p,sc,nn] for p,sc in mTEPES.ps) > 0])
|
|
609
|
+
mTEPES.n = Set(doc='load levels', initialize=[nn for nn in mTEPES.nn if sum(mTEPES.dPar['pDuration'][p,sc,nn] for p,sc in mTEPES.ps) > 0])
|
|
610
|
+
mTEPES.n2 = Set(doc='load levels', initialize=[nn for nn in mTEPES.nn if sum(mTEPES.dPar['pDuration'][p,sc,nn] for p,sc in mTEPES.ps) > 0])
|
|
650
611
|
# instrumental sets
|
|
651
|
-
def CreateInstrumentalSets(mTEPES, pIndHydroTopology, pIndHydrogen, pIndHeat) -> None:
|
|
612
|
+
def CreateInstrumentalSets(mTEPES, pIndHydroTopology, pIndHydrogen, pIndHeat, pIndPTDF) -> None:
|
|
652
613
|
'''
|
|
653
614
|
Create mTEPES instrumental sets.
|
|
654
615
|
|
|
655
|
-
This function takes
|
|
616
|
+
This function takes an mTEPES instance and adds instrumental sets which will be used later.
|
|
656
617
|
|
|
657
618
|
Parameters:
|
|
658
619
|
mTEPES: The instance of mTEPES.
|
|
@@ -660,7 +621,7 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
660
621
|
Returns:
|
|
661
622
|
None: Sets are added directly to the mTEPES object.
|
|
662
623
|
'''
|
|
663
|
-
mTEPES.pg = Set(initialize = [(p, g ) for p, g in mTEPES.p *mTEPES.g if pElecGenPeriodIni[g ] <= p and pElecGenPeriodFin[g ] >= p])
|
|
624
|
+
mTEPES.pg = Set(initialize = [(p, g ) for p, g in mTEPES.p *mTEPES.g if mTEPES.dPar['pElecGenPeriodIni'][g ] <= p and mTEPES.dPar['pElecGenPeriodFin'][g ] >= p])
|
|
664
625
|
mTEPES.pgc = Set(initialize = [(p, gc ) for p, gc in mTEPES.p *mTEPES.gc if (p,gc) in mTEPES.pg])
|
|
665
626
|
mTEPES.pnr = Set(initialize = [(p, nr ) for p, nr in mTEPES.p *mTEPES.nr if (p,nr) in mTEPES.pg])
|
|
666
627
|
mTEPES.pch = Set(initialize = [(p, ch ) for p, ch in mTEPES.p *mTEPES.ch if (p,ch) in mTEPES.pg])
|
|
@@ -678,7 +639,7 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
678
639
|
mTEPES.ph = Set(initialize = [(p, h ) for p, h in mTEPES.p *mTEPES.h if (p,h ) in mTEPES.pg])
|
|
679
640
|
mTEPES.pgd = Set(initialize = [(p, gd ) for p, gd in mTEPES.p *mTEPES.gd if (p,gd) in mTEPES.pg])
|
|
680
641
|
mTEPES.par = Set(initialize = [(p, ar ) for p, ar in mTEPES.p *mTEPES.ar ])
|
|
681
|
-
mTEPES.pla = Set(initialize = [(p, ni,nf,cc) for p, ni,nf,cc in mTEPES.p *mTEPES.la if pElecNetPeriodIni[ni,nf,cc] <= p and pElecNetPeriodFin[ni,nf,cc] >= p])
|
|
642
|
+
mTEPES.pla = Set(initialize = [(p, ni,nf,cc) for p, ni,nf,cc in mTEPES.p *mTEPES.la if mTEPES.dPar['pElecNetPeriodIni'][ni,nf,cc] <= p and mTEPES.dPar['pElecNetPeriodFin'][ni,nf,cc] >= p])
|
|
682
643
|
mTEPES.plc = Set(initialize = [(p, ni,nf,cc) for p, ni,nf,cc in mTEPES.p *mTEPES.lc if (p,ni,nf,cc) in mTEPES.pla])
|
|
683
644
|
mTEPES.pll = Set(initialize = [(p, ni,nf,cc) for p, ni,nf,cc in mTEPES.p *mTEPES.ll if (p,ni,nf,cc) in mTEPES.pla])
|
|
684
645
|
|
|
@@ -703,15 +664,15 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
703
664
|
mTEPES.psnnd = Set(initialize = [(p,sc,n,nd) for p,sc,n,nd in mTEPES.psn*mTEPES.nd ])
|
|
704
665
|
mTEPES.psnar = Set(initialize = [(p,sc,n,ar) for p,sc,n,ar in mTEPES.psn*mTEPES.ar ])
|
|
705
666
|
|
|
706
|
-
mTEPES.psnla = Set(initialize = [(p,sc,n,ni,nf,cc) for p,sc,n,ni,nf,cc in mTEPES.psn*mTEPES.la
|
|
707
|
-
mTEPES.psnle = Set(initialize = [(p,sc,n,ni,nf,cc) for p,sc,n,ni,nf,cc in mTEPES.psn*mTEPES.le
|
|
708
|
-
mTEPES.psnll = Set(initialize = [(p,sc,n,ni,nf,cc) for p,sc,n,ni,nf,cc in mTEPES.psn*mTEPES.ll
|
|
709
|
-
mTEPES.psnls = Set(initialize = [(p,sc,n,ni,nf,cc) for p,sc,n,ni,nf,cc in mTEPES.psn*mTEPES.ls
|
|
667
|
+
mTEPES.psnla = Set(initialize = [(p,sc,n,ni,nf,cc) for p,sc,n,ni,nf,cc in mTEPES.psn*mTEPES.la if (p,ni,nf,cc) in mTEPES.pla ])
|
|
668
|
+
mTEPES.psnle = Set(initialize = [(p,sc,n,ni,nf,cc) for p,sc,n,ni,nf,cc in mTEPES.psn*mTEPES.le if (p,ni,nf,cc) in mTEPES.pla ])
|
|
669
|
+
mTEPES.psnll = Set(initialize = [(p,sc,n,ni,nf,cc) for p,sc,n,ni,nf,cc in mTEPES.psn*mTEPES.ll if (p,ni,nf,cc) in mTEPES.pll ])
|
|
670
|
+
mTEPES.psnls = Set(initialize = [(p,sc,n,ni,nf,cc) for p,sc,n,ni,nf,cc in mTEPES.psn*mTEPES.ls if (p,ni,nf,cc) in mTEPES.pla ])
|
|
710
671
|
|
|
711
|
-
mTEPES.psnehc = Set(initialize = [(p,sc,n,eh) for p,sc,n,eh in mTEPES.psneh if pRatedMaxCharge[eh]>0.0 ])
|
|
672
|
+
mTEPES.psnehc = Set(initialize = [(p,sc,n,eh) for p,sc,n,eh in mTEPES.psneh if mTEPES.dPar['pRatedMaxCharge'][eh] > 0.0 ])
|
|
712
673
|
|
|
713
674
|
if pIndHydroTopology == 1:
|
|
714
|
-
mTEPES.prs = Set(initialize = [(p, rs) for p, rs in mTEPES.p *mTEPES.rs if pRsrPeriodIni[rs] <= p and pRsrPeriodFin[rs] >= p])
|
|
675
|
+
mTEPES.prs = Set(initialize = [(p, rs) for p, rs in mTEPES.p *mTEPES.rs if mTEPES.dPar['pRsrPeriodIni'][rs] <= p and mTEPES.dPar['pRsrPeriodFin'][rs] >= p])
|
|
715
676
|
mTEPES.prc = Set(initialize = [(p, rc) for p, rc in mTEPES.p *mTEPES.rn if (p,rc) in mTEPES.prs])
|
|
716
677
|
mTEPES.psrs = Set(initialize = [(p,sc, rs) for p,sc, rs in mTEPES.ps *mTEPES.rs if (p,rs) in mTEPES.prs])
|
|
717
678
|
mTEPES.psnh = Set(initialize = [(p,sc,n,h ) for p,sc,n,h in mTEPES.psn*mTEPES.h if (p,h ) in mTEPES.ph ])
|
|
@@ -721,7 +682,7 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
721
682
|
mTEPES.prc = []
|
|
722
683
|
|
|
723
684
|
if pIndHydrogen == 1:
|
|
724
|
-
mTEPES.ppa = Set(initialize = [(p, ni,nf,cc) for p, ni,nf,cc in mTEPES.p *mTEPES.pa if pH2PipePeriodIni[ni,nf,cc] <= p and pH2PipePeriodFin[ni,nf,cc] >= p])
|
|
685
|
+
mTEPES.ppa = Set(initialize = [(p, ni,nf,cc) for p, ni,nf,cc in mTEPES.p *mTEPES.pa if mTEPES.dPar['pH2PipePeriodIni'][ni,nf,cc] <= p and mTEPES.dPar['pH2PipePeriodFin'][ni,nf,cc] >= p])
|
|
725
686
|
mTEPES.ppc = Set(initialize = [(p, ni,nf,cc) for p, ni,nf,cc in mTEPES.p *mTEPES.pc if (p,ni,nf,cc) in mTEPES.ppa])
|
|
726
687
|
mTEPES.psnpn = Set(initialize = [(p,sc,n,ni,nf,cc) for p,sc,n,ni,nf,cc in mTEPES.psn*mTEPES.pn if (p,ni,nf,cc) in mTEPES.ppa])
|
|
727
688
|
mTEPES.psnpa = Set(initialize = [(p,sc,n,ni,nf,cc) for p,sc,n,ni,nf,cc in mTEPES.psn*mTEPES.pa if (p,ni,nf,cc) in mTEPES.ppa])
|
|
@@ -730,7 +691,7 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
730
691
|
mTEPES.ppc = Set(initialize = [])
|
|
731
692
|
|
|
732
693
|
if pIndHeat == 1:
|
|
733
|
-
mTEPES.pha = Set(initialize = [(p, ni,nf,cc) for p, ni,nf,cc in mTEPES.p *mTEPES.ha if pHeatPipePeriodIni[ni,nf,cc] <= p and pHeatPipePeriodFin[ni,nf,cc] >= p])
|
|
694
|
+
mTEPES.pha = Set(initialize = [(p, ni,nf,cc) for p, ni,nf,cc in mTEPES.p *mTEPES.ha if mTEPES.dPar['pHeatPipePeriodIni'][ni,nf,cc] <= p and mTEPES.dPar['pHeatPipePeriodFin'][ni,nf,cc] >= p])
|
|
734
695
|
mTEPES.phc = Set(initialize = [(p, ni,nf,cc) for p, ni,nf,cc in mTEPES.p *mTEPES.hc if (p,ni,nf,cc) in mTEPES.pha])
|
|
735
696
|
mTEPES.psnhn = Set(initialize = [(p,sc,n,ni,nf,cc) for p,sc,n,ni,nf,cc in mTEPES.psn*mTEPES.hn if (p,ni,nf,cc) in mTEPES.pha])
|
|
736
697
|
mTEPES.psnha = Set(initialize = [(p,sc,n,ni,nf,cc) for p,sc,n,ni,nf,cc in mTEPES.psn*mTEPES.ha if (p,ni,nf,cc) in mTEPES.pha])
|
|
@@ -738,14 +699,17 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
738
699
|
else:
|
|
739
700
|
mTEPES.phc = Set(initialize = [])
|
|
740
701
|
|
|
702
|
+
if pIndPTDF == 1:
|
|
703
|
+
mTEPES.psnland = Set(initialize = [(p,sc,n,ni,nf,cc,nd) for p,sc,n,ni,nf,cc,nd in mTEPES.psnla*mTEPES.nd if (ni,nf,cc,nd) in mTEPES.dPar['pVariablePTDF'].columns])
|
|
704
|
+
|
|
741
705
|
# assigning a node to an area
|
|
742
706
|
mTEPES.ndar = Set(initialize = [(nd,ar) for (nd,zn,ar) in mTEPES.ndzn*mTEPES.ar if (zn,ar) in mTEPES.znar])
|
|
743
707
|
|
|
744
|
-
# assigning a line to an area. Both nodes are in the same area. Cross-area lines not included
|
|
708
|
+
# assigning a line to an area. Both nodes are in the same area. Cross-area lines are not included
|
|
745
709
|
mTEPES.laar = Set(initialize = [(ni,nf,cc,ar) for ni,nf,cc,ar in mTEPES.la*mTEPES.ar if (ni,ar) in mTEPES.ndar and (nf,ar) in mTEPES.ndar])
|
|
746
710
|
|
|
747
711
|
|
|
748
|
-
CreateInstrumentalSets(mTEPES, pIndHydroTopology, pIndHydrogen, pIndHeat)
|
|
712
|
+
CreateInstrumentalSets(mTEPES, mTEPES.dPar['pIndHydroTopology'], mTEPES.dPar['pIndHydrogen'], mTEPES.dPar['pIndHeat'], mTEPES.dPar['pIndPTDF'])
|
|
749
713
|
|
|
750
714
|
# replacing string values by numerical values
|
|
751
715
|
idxDict = dict()
|
|
@@ -762,58 +726,79 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
762
726
|
idxDict['Y' ] = 1
|
|
763
727
|
idxDict['y' ] = 1
|
|
764
728
|
|
|
765
|
-
pIndBinUnitInvest = pIndBinUnitInvest.map (idxDict)
|
|
766
|
-
pIndBinUnitRetire = pIndBinUnitRetire.map (idxDict)
|
|
767
|
-
pIndBinUnitCommit = pIndBinUnitCommit.map (idxDict)
|
|
768
|
-
pIndBinStorInvest = pIndBinStorInvest.map (idxDict)
|
|
769
|
-
pIndBinLineInvest = pIndBinLineInvest.map (idxDict)
|
|
770
|
-
pIndBinLineSwitch = pIndBinLineSwitch.map (idxDict)
|
|
771
|
-
pIndOperReserve = pIndOperReserve.map (idxDict)
|
|
772
|
-
pIndOutflowIncomp = pIndOutflowIncomp.map (idxDict)
|
|
773
|
-
pMustRun = pMustRun.map (idxDict)
|
|
729
|
+
mTEPES.dPar['pIndBinUnitInvest'] = mTEPES.dPar['pIndBinUnitInvest'].map (idxDict)
|
|
730
|
+
mTEPES.dPar['pIndBinUnitRetire'] = mTEPES.dPar['pIndBinUnitRetire'].map (idxDict)
|
|
731
|
+
mTEPES.dPar['pIndBinUnitCommit'] = mTEPES.dPar['pIndBinUnitCommit'].map (idxDict)
|
|
732
|
+
mTEPES.dPar['pIndBinStorInvest'] = mTEPES.dPar['pIndBinStorInvest'].map (idxDict)
|
|
733
|
+
mTEPES.dPar['pIndBinLineInvest'] = mTEPES.dPar['pIndBinLineInvest'].map (idxDict)
|
|
734
|
+
mTEPES.dPar['pIndBinLineSwitch'] = mTEPES.dPar['pIndBinLineSwitch'].map (idxDict)
|
|
735
|
+
# mTEPES.dPar['pIndOperReserve'] = mTEPES.dPar['pIndOperReserve'].map (idxDict)
|
|
736
|
+
mTEPES.dPar['pIndOutflowIncomp'] = mTEPES.dPar['pIndOutflowIncomp'].map (idxDict)
|
|
737
|
+
mTEPES.dPar['pMustRun'] = mTEPES.dPar['pMustRun'].map (idxDict)
|
|
738
|
+
|
|
739
|
+
# Operating reserves can be provided while generating or while consuming
|
|
740
|
+
# So there is need for two options to decide if the unit is able to provide them
|
|
741
|
+
# Due to backwards compatibility reasons instead of adding a new column to Data_Generation NoOperatingReserve column now accepts two inputs
|
|
742
|
+
# They are separated by "|", if only one input is detected, both parameters are set to whatever the input is
|
|
743
|
+
|
|
744
|
+
def split_and_map(val):
|
|
745
|
+
# Handle new format with double input. Detect if there is a | character
|
|
746
|
+
if isinstance(val, str) and '|' in val:
|
|
747
|
+
gen, cons = val.split('|', 1)
|
|
748
|
+
return pd.Series([idxDict.get(gen.strip(), 0), idxDict.get(cons.strip(), 0)])
|
|
749
|
+
else:
|
|
750
|
+
# If no | character is found, both options are set to the inputted value
|
|
751
|
+
mapped = idxDict.get(val, 0)
|
|
752
|
+
return pd.Series([mapped, mapped])
|
|
753
|
+
|
|
754
|
+
# Split the columns in pIndOperReserve and group them in Generation and Consumption tuples
|
|
755
|
+
mTEPES.dPar['pIndOperReserveGen'], mTEPES.dPar['pIndOperReserveCon'] = zip(*mTEPES.dPar['pIndOperReserve'].map(split_and_map))
|
|
774
756
|
|
|
775
|
-
|
|
776
|
-
|
|
757
|
+
mTEPES.dPar['pIndOperReserveGen'] = pd.Series(mTEPES.dPar['pIndOperReserveGen'], index=mTEPES.dPar['pIndOperReserve'].index)
|
|
758
|
+
mTEPES.dPar['pIndOperReserveCon'] = pd.Series(mTEPES.dPar['pIndOperReserveCon'], index=mTEPES.dPar['pIndOperReserve'].index)
|
|
777
759
|
|
|
778
|
-
if
|
|
779
|
-
|
|
760
|
+
if mTEPES.dPar['pIndHydroTopology'] == 1:
|
|
761
|
+
mTEPES.dPar['pIndBinRsrvInvest'] = mTEPES.dPar['pIndBinRsrvInvest'].map (idxDict)
|
|
780
762
|
|
|
781
|
-
if
|
|
782
|
-
|
|
763
|
+
if mTEPES.dPar['pIndHydrogen'] == 1:
|
|
764
|
+
mTEPES.dPar['pIndBinH2PipeInvest'] = mTEPES.dPar['pIndBinH2PipeInvest'].map (idxDict)
|
|
765
|
+
|
|
766
|
+
if mTEPES.dPar['pIndHeat'] == 1:
|
|
767
|
+
mTEPES.dPar['pIndBinHeatPipeInvest'] = mTEPES.dPar['pIndBinHeatPipeInvest'].map(idxDict)
|
|
783
768
|
|
|
784
769
|
# define AC existing lines non-switchable lines
|
|
785
|
-
mTEPES.lea = Set(doc='AC existing lines and non-switchable lines', initialize=[le for le in mTEPES.le if pIndBinLineSwitch[le] == 0
|
|
770
|
+
mTEPES.lea = Set(doc='AC existing lines and non-switchable lines', initialize=[le for le in mTEPES.le if mTEPES.dPar['pIndBinLineSwitch'][le] == 0 and not mTEPES.dPar['pLineType'][le] == 'DC'])
|
|
786
771
|
# define AC candidate lines and switchable lines
|
|
787
|
-
mTEPES.lca = Set(doc='AC candidate lines and switchable lines', initialize=[la for la in mTEPES.la if (pIndBinLineSwitch[la] == 1 or pNetFixedCost[la] > 0.0) and not pLineType[la] == 'DC'])
|
|
772
|
+
mTEPES.lca = Set(doc='AC candidate lines and switchable lines', initialize=[la for la in mTEPES.la if (mTEPES.dPar['pIndBinLineSwitch'][la] == 1 or mTEPES.dPar['pNetFixedCost'][la] > 0.0) and not mTEPES.dPar['pLineType'][la] == 'DC'])
|
|
788
773
|
|
|
789
774
|
mTEPES.laa = mTEPES.lea | mTEPES.lca
|
|
790
775
|
|
|
791
776
|
# define DC existing lines non-switchable lines
|
|
792
|
-
mTEPES.led = Set(doc='DC existing lines and non-switchable lines', initialize=[le for le in mTEPES.le if pIndBinLineSwitch[le] == 0
|
|
777
|
+
mTEPES.led = Set(doc='DC existing lines and non-switchable lines', initialize=[le for le in mTEPES.le if mTEPES.dPar['pIndBinLineSwitch'][le] == 0 and mTEPES.dPar['pLineType'][le] == 'DC'])
|
|
793
778
|
# define DC candidate lines and switchable lines
|
|
794
|
-
mTEPES.lcd = Set(doc='DC candidate lines and switchable lines', initialize=[la for la in mTEPES.la if (pIndBinLineSwitch[la] == 1 or pNetFixedCost[la] > 0.0) and pLineType[la] == 'DC'])
|
|
779
|
+
mTEPES.lcd = Set(doc='DC candidate lines and switchable lines', initialize=[la for la in mTEPES.la if (mTEPES.dPar['pIndBinLineSwitch'][la] == 1 or mTEPES.dPar['pNetFixedCost'][la] > 0.0) and mTEPES.dPar['pLineType'][la] == 'DC'])
|
|
795
780
|
|
|
796
781
|
mTEPES.lad = mTEPES.led | mTEPES.lcd
|
|
797
782
|
|
|
798
783
|
# line type
|
|
799
|
-
pLineType = pLineType.reset_index().set_index(['InitialNode', 'FinalNode', 'Circuit', 'LineType'])
|
|
784
|
+
mTEPES.dPar['pLineType'] = mTEPES.dPar['pLineType'].reset_index().set_index(['InitialNode', 'FinalNode', 'Circuit', 'LineType'])
|
|
800
785
|
|
|
801
|
-
mTEPES.pLineType = Set(initialize=pLineType.index, doc='line type')
|
|
786
|
+
mTEPES.pLineType = Set(initialize=mTEPES.dPar['pLineType'].index, doc='line type')
|
|
802
787
|
|
|
803
|
-
if
|
|
804
|
-
pDiscountedWeight = pd.Series([
|
|
788
|
+
if mTEPES.dPar['pAnnualDiscountRate'] == 0.0:
|
|
789
|
+
mTEPES.dPar['pDiscountedWeight'] = pd.Series([ mTEPES.dPar['pPeriodWeight'][p] for p in mTEPES.p], index=mTEPES.p)
|
|
805
790
|
else:
|
|
806
|
-
pDiscountedWeight = pd.Series([((1.0+
|
|
791
|
+
mTEPES.dPar['pDiscountedWeight'] = pd.Series([((1.0+mTEPES.dPar['pAnnualDiscountRate'])**mTEPES.dPar['pPeriodWeight'][p]-1.0) / (mTEPES.dPar['pAnnualDiscountRate']*(1.0+mTEPES.dPar['pAnnualDiscountRate'])**(mTEPES.dPar['pPeriodWeight'][p]-1+p-mTEPES.dPar['pEconomicBaseYear'])) for p in mTEPES.p], index=mTEPES.p)
|
|
807
792
|
|
|
808
793
|
mTEPES.pLoadLevelWeight = Param(mTEPES.psn, initialize=0.0, within=NonNegativeReals, doc='Load level weight', mutable=True)
|
|
809
794
|
for p,sc,st,n in mTEPES.s2n:
|
|
810
|
-
mTEPES.pLoadLevelWeight[p,sc,n] = pStageWeight[st]
|
|
795
|
+
mTEPES.pLoadLevelWeight[p,sc,n] = mTEPES.dPar['pStageWeight'][st]
|
|
811
796
|
|
|
812
797
|
#%% inverse index node to generator
|
|
813
|
-
pNodeToGen = pGenToNode.reset_index().set_index('Node').set_axis(['Generator'], axis=1)[['Generator']]
|
|
814
|
-
pNodeToGen = pNodeToGen.loc[pNodeToGen['Generator'].isin(mTEPES.g)].reset_index().set_index(['Node', 'Generator'])
|
|
798
|
+
mTEPES.dPar['pNodeToGen'] = mTEPES.dPar['pGenToNode'].reset_index().set_index('Node').set_axis(['Generator'], axis=1)[['Generator']]
|
|
799
|
+
mTEPES.dPar['pNodeToGen'] = mTEPES.dPar['pNodeToGen'].loc[mTEPES.dPar['pNodeToGen']['Generator'].isin(mTEPES.g)].reset_index().set_index(['Node', 'Generator'])
|
|
815
800
|
|
|
816
|
-
mTEPES.n2g = Set(initialize=pNodeToGen.index, doc='node to generator')
|
|
801
|
+
mTEPES.n2g = Set(initialize=mTEPES.dPar['pNodeToGen'].index, doc='node to generator')
|
|
817
802
|
|
|
818
803
|
mTEPES.z2g = Set(doc='zone to generator', initialize=[(zn,g) for (nd,g,zn ) in mTEPES.n2g*mTEPES.zn if (nd,zn) in mTEPES.ndzn ])
|
|
819
804
|
mTEPES.a2g = Set(doc='area to generator', initialize=[(ar,g) for (nd,g,zn,ar ) in mTEPES.n2g*mTEPES.znar if (nd,zn) in mTEPES.ndzn ])
|
|
@@ -822,10 +807,10 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
822
807
|
# mTEPES.z2g = Set(initialize = [(zn,g) for zn,g in mTEPES.zn*mTEPES.g if (zn,g) in pZone2Gen])
|
|
823
808
|
|
|
824
809
|
#%% inverse index generator to technology
|
|
825
|
-
pTechnologyToGen = pGenToTechnology.reset_index().set_index('Technology').set_axis(['Generator'], axis=1)[['Generator']]
|
|
826
|
-
pTechnologyToGen = pTechnologyToGen.loc[pTechnologyToGen['Generator'].isin(mTEPES.g)].reset_index().set_index(['Technology', 'Generator'])
|
|
810
|
+
mTEPES.dPar['pTechnologyToGen'] = mTEPES.dPar['pGenToTechnology'].reset_index().set_index('Technology').set_axis(['Generator'], axis=1)[['Generator']]
|
|
811
|
+
mTEPES.dPar['pTechnologyToGen'] = mTEPES.dPar['pTechnologyToGen'].loc[mTEPES.dPar['pTechnologyToGen']['Generator'].isin(mTEPES.g)].reset_index().set_index(['Technology', 'Generator'])
|
|
827
812
|
|
|
828
|
-
mTEPES.t2g = Set(initialize=pTechnologyToGen.index, doc='technology to generator')
|
|
813
|
+
mTEPES.t2g = Set(initialize=mTEPES.dPar['pTechnologyToGen'].index, doc='technology to generator')
|
|
829
814
|
|
|
830
815
|
# ESS and RES technologies
|
|
831
816
|
def Create_ESS_RES_Sets(mTEPES) -> None:
|
|
@@ -850,50 +835,81 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
850
835
|
|
|
851
836
|
Create_ESS_RES_Sets(mTEPES)
|
|
852
837
|
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
838
|
+
# Create mutually exclusive groups
|
|
839
|
+
# Store in a group-generator dictionary all the relevant data
|
|
840
|
+
group_dict = {}
|
|
841
|
+
for generator, groups in mTEPES.dPar['pGenToExclusiveGen'].items():
|
|
842
|
+
if groups != 0.0:
|
|
843
|
+
for group in str(groups).split('|'):
|
|
844
|
+
group_dict.setdefault(group, []).append(generator)
|
|
845
|
+
|
|
846
|
+
# These sets store all groups and the generators in them
|
|
847
|
+
mTEPES.ExclusiveGroups = Set(initialize=list(group_dict.keys()))
|
|
848
|
+
mTEPES.GeneratorsInExclusiveGroup = Set(mTEPES.ExclusiveGroups, initialize=group_dict)
|
|
849
|
+
|
|
850
|
+
# Create filtered dictionaries for Yearly and Hourly groups
|
|
851
|
+
group_dict_yearly = {}
|
|
852
|
+
group_dict_hourly = {}
|
|
853
|
+
|
|
854
|
+
for group, generators in group_dict.items():
|
|
855
|
+
if all(gen in mTEPES.gc for gen in generators):
|
|
856
|
+
group_dict_yearly[group] = generators
|
|
857
|
+
else:
|
|
858
|
+
group_dict_hourly[group] = generators
|
|
859
|
+
|
|
860
|
+
# The exclusive groups sets have all groups which are mutually exclusive in that time scope
|
|
861
|
+
# Generators in group sets are sets with the corresponding generators to a given group
|
|
862
|
+
mTEPES.ExclusiveGroupsYearly = Set(initialize=list(group_dict_yearly.keys()))
|
|
863
|
+
mTEPES.GeneratorsInYearlyGroup = Set(mTEPES.ExclusiveGroupsYearly, initialize=group_dict_yearly)
|
|
864
|
+
|
|
865
|
+
mTEPES.ExclusiveGroupsHourly = Set(initialize=list(group_dict_hourly.keys()))
|
|
866
|
+
mTEPES.GeneratorsInHourlyGroup = Set(mTEPES.ExclusiveGroupsHourly, initialize=group_dict_hourly)
|
|
856
867
|
|
|
857
|
-
|
|
868
|
+
# All exclusive generators (sorting to ensure deterministic behavior)
|
|
869
|
+
mTEPES.ExclusiveGenerators = Set(initialize=sorted(sum(group_dict.values(), [])))
|
|
870
|
+
# All yearly exclusive generators (sorting to ensure deterministic behavior)
|
|
871
|
+
mTEPES.ExclusiveGeneratorsYearly = Set(initialize=sorted(sum(group_dict_yearly.values(), [])))
|
|
872
|
+
# All hourly exclusive generators (sorting to ensure deterministic behavior)
|
|
873
|
+
mTEPES.ExclusiveGeneratorsHourly = Set(initialize=sorted(sum(group_dict_hourly.values(), [])))
|
|
858
874
|
|
|
859
875
|
# minimum and maximum variable power, charge, and storage capacity
|
|
860
|
-
pMinPowerElec = pVariableMinPowerElec.replace(0.0, pRatedMinPowerElec)
|
|
861
|
-
pMaxPowerElec = pVariableMaxPowerElec.replace(0.0, pRatedMaxPowerElec)
|
|
862
|
-
pMinCharge = pVariableMinCharge.replace (0.0, pRatedMinCharge )
|
|
863
|
-
pMaxCharge = pVariableMaxCharge.replace (0.0, pRatedMaxCharge )
|
|
864
|
-
pMinStorage = pVariableMinStorage.replace (0.0, pRatedMinStorage )
|
|
865
|
-
pMaxStorage = pVariableMaxStorage.replace (0.0, pRatedMaxStorage )
|
|
866
|
-
if pIndHydroTopology == 1:
|
|
867
|
-
pMinVolume = pVariableMinVolume.replace (0.0, pRatedMinVolume )
|
|
868
|
-
pMaxVolume = pVariableMaxVolume.replace (0.0, pRatedMaxVolume )
|
|
869
|
-
|
|
870
|
-
pMinPowerElec = pMinPowerElec.where(pMinPowerElec > 0.0, 0.0)
|
|
871
|
-
pMaxPowerElec = pMaxPowerElec.where(pMaxPowerElec > 0.0, 0.0)
|
|
872
|
-
pMinCharge = pMinCharge.where (pMinCharge > 0.0, 0.0)
|
|
873
|
-
pMaxCharge = pMaxCharge.where (pMaxCharge > 0.0, 0.0)
|
|
874
|
-
pMinStorage = pMinStorage.where (pMinStorage > 0.0, 0.0)
|
|
875
|
-
pMaxStorage = pMaxStorage.where (pMaxStorage > 0.0, 0.0)
|
|
876
|
-
if pIndHydroTopology == 1:
|
|
877
|
-
pMinVolume = pMinVolume.where (pMinVolume > 0.0, 0.0)
|
|
878
|
-
pMaxVolume = pMaxVolume.where (pMaxVolume > 0.0, 0.0)
|
|
876
|
+
mTEPES.dPar['pMinPowerElec'] = mTEPES.dPar['pVariableMinPowerElec'].replace(0.0, mTEPES.dPar['pRatedMinPowerElec'])
|
|
877
|
+
mTEPES.dPar['pMaxPowerElec'] = mTEPES.dPar['pVariableMaxPowerElec'].replace(0.0, mTEPES.dPar['pRatedMaxPowerElec'])
|
|
878
|
+
mTEPES.dPar['pMinCharge'] = mTEPES.dPar['pVariableMinCharge'].replace (0.0, mTEPES.dPar['pRatedMinCharge'] )
|
|
879
|
+
mTEPES.dPar['pMaxCharge'] = mTEPES.dPar['pVariableMaxCharge'].replace (0.0, mTEPES.dPar['pRatedMaxCharge'] )
|
|
880
|
+
mTEPES.dPar['pMinStorage'] = mTEPES.dPar['pVariableMinStorage'].replace (0.0, mTEPES.dPar['pRatedMinStorage'] )
|
|
881
|
+
mTEPES.dPar['pMaxStorage'] = mTEPES.dPar['pVariableMaxStorage'].replace (0.0, mTEPES.dPar['pRatedMaxStorage'] )
|
|
882
|
+
if mTEPES.dPar['pIndHydroTopology'] == 1:
|
|
883
|
+
mTEPES.dPar['pMinVolume'] = mTEPES.dPar['pVariableMinVolume'].replace (0.0, mTEPES.dPar['pRatedMinVolume'] )
|
|
884
|
+
mTEPES.dPar['pMaxVolume'] = mTEPES.dPar['pVariableMaxVolume'].replace (0.0, mTEPES.dPar['pRatedMaxVolume'] )
|
|
885
|
+
|
|
886
|
+
mTEPES.dPar['pMinPowerElec'] = mTEPES.dPar['pMinPowerElec'].where(mTEPES.dPar['pMinPowerElec'] > 0.0, 0.0)
|
|
887
|
+
mTEPES.dPar['pMaxPowerElec'] = mTEPES.dPar['pMaxPowerElec'].where(mTEPES.dPar['pMaxPowerElec'] > 0.0, 0.0)
|
|
888
|
+
mTEPES.dPar['pMinCharge'] = mTEPES.dPar['pMinCharge'].where (mTEPES.dPar['pMinCharge'] > 0.0, 0.0)
|
|
889
|
+
mTEPES.dPar['pMaxCharge'] = mTEPES.dPar['pMaxCharge'].where (mTEPES.dPar['pMaxCharge'] > 0.0, 0.0)
|
|
890
|
+
mTEPES.dPar['pMinStorage'] = mTEPES.dPar['pMinStorage'].where (mTEPES.dPar['pMinStorage'] > 0.0, 0.0)
|
|
891
|
+
mTEPES.dPar['pMaxStorage'] = mTEPES.dPar['pMaxStorage'].where (mTEPES.dPar['pMaxStorage'] > 0.0, 0.0)
|
|
892
|
+
if mTEPES.dPar['pIndHydroTopology'] == 1:
|
|
893
|
+
mTEPES.dPar['pMinVolume'] = mTEPES.dPar['pMinVolume'].where (mTEPES.dPar['pMinVolume'] > 0.0, 0.0)
|
|
894
|
+
mTEPES.dPar['pMaxVolume'] = mTEPES.dPar['pMaxVolume'].where (mTEPES.dPar['pMaxVolume'] > 0.0, 0.0)
|
|
879
895
|
|
|
880
896
|
# fuel term and constant term variable cost
|
|
881
|
-
pVariableFuelCost = pVariableFuelCost.replace(0.0, dfGeneration['FuelCost'])
|
|
882
|
-
pLinearVarCost = dfGeneration['LinearTerm' ] * 1e-3 * pVariableFuelCost + dfGeneration['OMVariableCost'] * 1e-3
|
|
883
|
-
pConstantVarCost = dfGeneration['ConstantTerm'] * 1e-6 * pVariableFuelCost
|
|
884
|
-
pLinearVarCost = pLinearVarCost.reindex (sorted(pLinearVarCost.columns ), axis=1)
|
|
885
|
-
pConstantVarCost = pConstantVarCost.reindex(sorted(pConstantVarCost.columns), axis=1)
|
|
897
|
+
mTEPES.dPar['pVariableFuelCost'] = mTEPES.dPar ['pVariableFuelCost'].replace(0.0, mTEPES.dFrame['dfGeneration']['FuelCost'])
|
|
898
|
+
mTEPES.dPar['pLinearVarCost'] = mTEPES.dFrame['dfGeneration']['LinearTerm' ] * 1e-3 * mTEPES.dPar['pVariableFuelCost'] + mTEPES.dFrame['dfGeneration']['OMVariableCost'] * 1e-3
|
|
899
|
+
mTEPES.dPar['pConstantVarCost'] = mTEPES.dFrame['dfGeneration']['ConstantTerm'] * 1e-6 * mTEPES.dPar['pVariableFuelCost']
|
|
900
|
+
mTEPES.dPar['pLinearVarCost'] = mTEPES.dPar ['pLinearVarCost'].reindex (sorted(mTEPES.dPar['pLinearVarCost'].columns ), axis=1)
|
|
901
|
+
mTEPES.dPar['pConstantVarCost'] = mTEPES.dPar ['pConstantVarCost'].reindex(sorted(mTEPES.dPar['pConstantVarCost'].columns), axis=1)
|
|
886
902
|
|
|
887
903
|
# variable emission cost [M€/GWh]
|
|
888
|
-
pVariableEmissionCost = pVariableEmissionCost.replace(0.0, pCO2Cost) #[€/tCO2]
|
|
889
|
-
pEmissionVarCost = pEmissionRate * 1e-3 * pVariableEmissionCost #[M€/GWh] = [tCO2/MWh] * 1e-3 * [€/tCO2]
|
|
890
|
-
pEmissionVarCost = pEmissionVarCost.reindex(sorted(pEmissionVarCost.columns), axis=1)
|
|
904
|
+
mTEPES.dPar['pVariableEmissionCost'] = mTEPES.dPar['pVariableEmissionCost'].replace(0.0, mTEPES.dPar['pCO2Cost']) #[€/tCO2]
|
|
905
|
+
mTEPES.dPar['pEmissionVarCost'] = mTEPES.dPar['pEmissionRate'] * 1e-3 * mTEPES.dPar['pVariableEmissionCost'] #[M€/GWh] = [tCO2/MWh] * 1e-3 * [€/tCO2]
|
|
906
|
+
mTEPES.dPar['pEmissionVarCost'] = mTEPES.dPar['pEmissionVarCost'].reindex(sorted(mTEPES.dPar['pEmissionVarCost'].columns), axis=1)
|
|
891
907
|
|
|
892
908
|
# minimum up- and downtime and maximum shift time converted to an integer number of time steps
|
|
893
|
-
pUpTime = round(pUpTime /pTimeStep).astype('int')
|
|
894
|
-
pDwTime = round(pDwTime /pTimeStep).astype('int')
|
|
895
|
-
pStableTime = round(pStableTime/pTimeStep).astype('int')
|
|
896
|
-
pShiftTime = round(pShiftTime /pTimeStep).astype('int')
|
|
909
|
+
mTEPES.dPar['pUpTime'] = round(mTEPES.dPar['pUpTime'] /mTEPES.dPar['pTimeStep']).astype('int')
|
|
910
|
+
mTEPES.dPar['pDwTime'] = round(mTEPES.dPar['pDwTime'] /mTEPES.dPar['pTimeStep']).astype('int')
|
|
911
|
+
mTEPES.dPar['pStableTime'] = round(mTEPES.dPar['pStableTime']/mTEPES.dPar['pTimeStep']).astype('int')
|
|
912
|
+
mTEPES.dPar['pShiftTime'] = round(mTEPES.dPar['pShiftTime'] /mTEPES.dPar['pTimeStep']).astype('int')
|
|
897
913
|
|
|
898
914
|
# %% definition of the time-steps leap to observe the stored energy at an ESS
|
|
899
915
|
idxCycle = dict()
|
|
@@ -901,144 +917,150 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
901
917
|
idxCycle[0.0 ] = 1
|
|
902
918
|
idxCycle['Hourly' ] = 1
|
|
903
919
|
idxCycle['Daily' ] = 1
|
|
904
|
-
idxCycle['Weekly' ] = round( 24/pTimeStep)
|
|
905
|
-
idxCycle['Monthly'] = round( 168/pTimeStep)
|
|
906
|
-
idxCycle['Yearly' ] = round( 672/pTimeStep)
|
|
920
|
+
idxCycle['Weekly' ] = round( 24/mTEPES.dPar['pTimeStep'])
|
|
921
|
+
idxCycle['Monthly'] = round( 168/mTEPES.dPar['pTimeStep'])
|
|
922
|
+
idxCycle['Yearly' ] = round( 672/mTEPES.dPar['pTimeStep'])
|
|
907
923
|
|
|
908
924
|
idxOutflows = dict()
|
|
909
925
|
idxOutflows[0 ] = 1
|
|
910
926
|
idxOutflows[0.0 ] = 1
|
|
911
927
|
idxOutflows['Hourly' ] = 1
|
|
912
|
-
idxOutflows['Daily' ] = round( 24/pTimeStep)
|
|
913
|
-
idxOutflows['Weekly' ] = round( 168/pTimeStep)
|
|
914
|
-
idxOutflows['Monthly'] = round( 672/pTimeStep)
|
|
915
|
-
idxOutflows['Yearly' ] = round(8736/pTimeStep)
|
|
928
|
+
idxOutflows['Daily' ] = round( 24/mTEPES.dPar['pTimeStep'])
|
|
929
|
+
idxOutflows['Weekly' ] = round( 168/mTEPES.dPar['pTimeStep'])
|
|
930
|
+
idxOutflows['Monthly'] = round( 672/mTEPES.dPar['pTimeStep'])
|
|
931
|
+
idxOutflows['Yearly' ] = round(8736/mTEPES.dPar['pTimeStep'])
|
|
916
932
|
|
|
917
933
|
idxEnergy = dict()
|
|
918
934
|
idxEnergy[0 ] = 1
|
|
919
935
|
idxEnergy[0.0 ] = 1
|
|
920
936
|
idxEnergy['Hourly' ] = 1
|
|
921
|
-
idxEnergy['Daily' ] = round( 24/pTimeStep)
|
|
922
|
-
idxEnergy['Weekly' ] = round( 168/pTimeStep)
|
|
923
|
-
idxEnergy['Monthly'] = round( 672/pTimeStep)
|
|
924
|
-
idxEnergy['Yearly' ] = round(8736/pTimeStep)
|
|
937
|
+
idxEnergy['Daily' ] = round( 24/mTEPES.dPar['pTimeStep'])
|
|
938
|
+
idxEnergy['Weekly' ] = round( 168/mTEPES.dPar['pTimeStep'])
|
|
939
|
+
idxEnergy['Monthly'] = round( 672/mTEPES.dPar['pTimeStep'])
|
|
940
|
+
idxEnergy['Yearly' ] = round(8736/mTEPES.dPar['pTimeStep'])
|
|
925
941
|
|
|
926
|
-
pStorageTimeStep = pStorageType.map (idxCycle
|
|
927
|
-
pOutflowsTimeStep = pOutflowsType.map(idxOutflows).where(pEnergyOutflows.sum()
|
|
928
|
-
pEnergyTimeStep = pEnergyType.map (idxEnergy ).where(pVariableMinEnergy.sum() + pVariableMaxEnergy.sum() > 0.0, other = 1).astype('int')
|
|
942
|
+
mTEPES.dPar['pStorageTimeStep'] = mTEPES.dPar['pStorageType'].map (idxCycle ).astype('int')
|
|
943
|
+
mTEPES.dPar['pOutflowsTimeStep'] = mTEPES.dPar['pOutflowsType'].map(idxOutflows).where(mTEPES.dPar['pEnergyOutflows'].sum() > 0.0, other = 1).astype('int')
|
|
944
|
+
mTEPES.dPar['pEnergyTimeStep'] = mTEPES.dPar['pEnergyType'].map (idxEnergy ).where(mTEPES.dPar['pVariableMinEnergy'].sum() + mTEPES.dPar['pVariableMaxEnergy'].sum() > 0.0, other = 1).astype('int')
|
|
929
945
|
|
|
930
|
-
pStorageTimeStep = pd.concat([pStorageTimeStep, pOutflowsTimeStep, pEnergyTimeStep], axis=1).min(axis=1)
|
|
946
|
+
mTEPES.dPar['pStorageTimeStep'] = pd.concat([mTEPES.dPar['pStorageTimeStep'], mTEPES.dPar['pOutflowsTimeStep'], mTEPES.dPar['pEnergyTimeStep']], axis=1).min(axis=1)
|
|
931
947
|
# cycle time step can't exceed the stage duration
|
|
932
|
-
pStorageTimeStep = pStorageTimeStep.where(pStorageTimeStep <= pStageDuration.min(), pStageDuration.min())
|
|
948
|
+
mTEPES.dPar['pStorageTimeStep'] = mTEPES.dPar['pStorageTimeStep'].where(mTEPES.dPar['pStorageTimeStep'] <= mTEPES.dPar['pStageDuration'].min(), mTEPES.dPar['pStageDuration'].min())
|
|
933
949
|
|
|
934
|
-
if pIndHydroTopology == 1:
|
|
950
|
+
if mTEPES.dPar['pIndHydroTopology'] == 1:
|
|
935
951
|
# %% definition of the time-steps leap to observe the stored energy at a reservoir
|
|
936
952
|
idxCycleRsr = dict()
|
|
937
953
|
idxCycleRsr[0 ] = 1
|
|
938
954
|
idxCycleRsr[0.0 ] = 1
|
|
939
955
|
idxCycleRsr['Hourly' ] = 1
|
|
940
956
|
idxCycleRsr['Daily' ] = 1
|
|
941
|
-
idxCycleRsr['Weekly' ] = round( 24/pTimeStep)
|
|
942
|
-
idxCycleRsr['Monthly'] = round( 168/pTimeStep)
|
|
943
|
-
idxCycleRsr['Yearly' ] = round( 672/pTimeStep)
|
|
957
|
+
idxCycleRsr['Weekly' ] = round( 24/mTEPES.dPar['pTimeStep'])
|
|
958
|
+
idxCycleRsr['Monthly'] = round( 168/mTEPES.dPar['pTimeStep'])
|
|
959
|
+
idxCycleRsr['Yearly' ] = round( 672/mTEPES.dPar['pTimeStep'])
|
|
944
960
|
|
|
945
961
|
idxWaterOut = dict()
|
|
946
962
|
idxWaterOut[0 ] = 1
|
|
947
963
|
idxWaterOut[0.0 ] = 1
|
|
948
964
|
idxWaterOut['Hourly' ] = 1
|
|
949
|
-
idxWaterOut['Daily' ] = round( 24/pTimeStep)
|
|
950
|
-
idxWaterOut['Weekly' ] = round( 168/pTimeStep)
|
|
951
|
-
idxWaterOut['Monthly'] = round( 672/pTimeStep)
|
|
952
|
-
idxWaterOut['Yearly' ] = round(8736/pTimeStep)
|
|
965
|
+
idxWaterOut['Daily' ] = round( 24/mTEPES.dPar['pTimeStep'])
|
|
966
|
+
idxWaterOut['Weekly' ] = round( 168/mTEPES.dPar['pTimeStep'])
|
|
967
|
+
idxWaterOut['Monthly'] = round( 672/mTEPES.dPar['pTimeStep'])
|
|
968
|
+
idxWaterOut['Yearly' ] = round(8736/mTEPES.dPar['pTimeStep'])
|
|
953
969
|
|
|
954
|
-
pCycleRsrTimeStep = pReservoirType.map(idxCycleRsr).astype('int')
|
|
955
|
-
pWaterOutTimeStep = pWaterOutfType.map(idxWaterOut).astype('int')
|
|
970
|
+
mTEPES.dPar['pCycleRsrTimeStep'] = mTEPES.dPar['pReservoirType'].map(idxCycleRsr).astype('int')
|
|
971
|
+
mTEPES.dPar['pWaterOutTimeStep'] = mTEPES.dPar['pWaterOutfType'].map(idxWaterOut).astype('int')
|
|
956
972
|
|
|
957
|
-
pReservoirTimeStep = pd.concat([pCycleRsrTimeStep, pWaterOutTimeStep], axis=1).min(axis=1)
|
|
973
|
+
mTEPES.dPar['pReservoirTimeStep'] = pd.concat([mTEPES.dPar['pCycleRsrTimeStep'], mTEPES.dPar['pWaterOutTimeStep']], axis=1).min(axis=1)
|
|
958
974
|
# cycle water step can't exceed the stage duration
|
|
959
|
-
pReservoirTimeStep = pReservoirTimeStep.where(pReservoirTimeStep <= pStageDuration.min(), pStageDuration.min())
|
|
975
|
+
mTEPES.dPar['pReservoirTimeStep'] = mTEPES.dPar['pReservoirTimeStep'].where(mTEPES.dPar['pReservoirTimeStep'] <= mTEPES.dPar['pStageDuration'].min(), mTEPES.dPar['pStageDuration'].min())
|
|
960
976
|
|
|
961
977
|
# initial inventory must be between minimum and maximum
|
|
962
|
-
pInitialInventory = pInitialInventory.where(pInitialInventory > pRatedMinStorage, pRatedMinStorage)
|
|
963
|
-
pInitialInventory = pInitialInventory.where(pInitialInventory < pRatedMaxStorage, pRatedMaxStorage)
|
|
964
|
-
if pIndHydroTopology == 1:
|
|
965
|
-
pInitialVolume = pInitialVolume.where (pInitialVolume > pRatedMinVolume, pRatedMinVolume )
|
|
966
|
-
pInitialVolume = pInitialVolume.where (pInitialVolume < pRatedMaxVolume, pRatedMaxVolume )
|
|
978
|
+
mTEPES.dPar['pInitialInventory'] = mTEPES.dPar['pInitialInventory'].where(mTEPES.dPar['pInitialInventory'] > mTEPES.dPar['pRatedMinStorage'], mTEPES.dPar['pRatedMinStorage'])
|
|
979
|
+
mTEPES.dPar['pInitialInventory'] = mTEPES.dPar['pInitialInventory'].where(mTEPES.dPar['pInitialInventory'] < mTEPES.dPar['pRatedMaxStorage'], mTEPES.dPar['pRatedMaxStorage'])
|
|
980
|
+
if mTEPES.dPar['pIndHydroTopology'] == 1:
|
|
981
|
+
mTEPES.dPar['pInitialVolume'] = mTEPES.dPar['pInitialVolume'].where (mTEPES.dPar['pInitialVolume'] > mTEPES.dPar['pRatedMinVolume'], mTEPES.dPar['pRatedMinVolume'] )
|
|
982
|
+
mTEPES.dPar['pInitialVolume'] = mTEPES.dPar['pInitialVolume'].where (mTEPES.dPar['pInitialVolume'] < mTEPES.dPar['pRatedMaxVolume'], mTEPES.dPar['pRatedMaxVolume'] )
|
|
967
983
|
|
|
968
984
|
# initial inventory of the candidate storage units equal to its maximum capacity if the storage capacity is linked to the investment decision
|
|
969
|
-
pInitialInventory.update(pd.Series([pInitialInventory[ec] if pIndBinStorInvest[ec] == 0 else pRatedMaxStorage[ec] for ec in mTEPES.ec], index=mTEPES.ec, dtype='float64'))
|
|
985
|
+
mTEPES.dPar['pInitialInventory'].update(pd.Series([mTEPES.dPar['pInitialInventory'][ec] if mTEPES.dPar['pIndBinStorInvest'][ec] == 0 else mTEPES.dPar['pRatedMaxStorage'][ec] for ec in mTEPES.ec], index=mTEPES.ec, dtype='float64'))
|
|
970
986
|
|
|
971
987
|
# parameter that allows the initial inventory to change with load level
|
|
972
|
-
pIniInventory = pd.DataFrame([pInitialInventory]*len(mTEPES.psn), index=mTEPES.psn, columns=mTEPES.es)
|
|
973
|
-
if pIndHydroTopology == 1:
|
|
974
|
-
pIniVolume = pd.DataFrame([pInitialVolume ]*len(mTEPES.psn), index=mTEPES.psn, columns=mTEPES.rs)
|
|
988
|
+
mTEPES.dPar['pIniInventory'] = pd.DataFrame([mTEPES.dPar['pInitialInventory']]*len(mTEPES.psn), index=mTEPES.psn, columns=mTEPES.es)
|
|
989
|
+
if mTEPES.dPar['pIndHydroTopology'] == 1:
|
|
990
|
+
mTEPES.dPar['pIniVolume'] = pd.DataFrame([mTEPES.dPar['pInitialVolume'] ]*len(mTEPES.psn), index=mTEPES.psn, columns=mTEPES.rs)
|
|
975
991
|
|
|
976
992
|
# initial inventory must be between minimum and maximum
|
|
977
993
|
for p,sc,n,es in mTEPES.psnes:
|
|
978
|
-
if (p,sc,st,n) in mTEPES.s2n and mTEPES.n.ord(n) == pStorageTimeStep[es]:
|
|
979
|
-
if pIniInventory[es][p,sc,n] < pMinStorage[es][p,sc,n]:
|
|
980
|
-
pIniInventory[es][p,sc,n] = pMinStorage[es][p,sc,n]
|
|
994
|
+
if (p,sc,st,n) in mTEPES.s2n and mTEPES.n.ord(n) == mTEPES.dPar['pStorageTimeStep'][es]:
|
|
995
|
+
if mTEPES.dPar['pIniInventory'][es].loc[p,sc,n] < mTEPES.dPar['pMinStorage'][es].loc[p,sc,n]:
|
|
996
|
+
mTEPES.dPar['pIniInventory'][es].loc[p,sc,n] = mTEPES.dPar['pMinStorage'][es].loc[p,sc,n]
|
|
981
997
|
print('### Initial inventory lower than minimum storage ', p, sc, st, es)
|
|
982
|
-
if pIniInventory[es][p,sc,n] > pMaxStorage[es][p,sc,n]:
|
|
983
|
-
pIniInventory[es][p,sc,n] = pMaxStorage[es][p,sc,n]
|
|
998
|
+
if mTEPES.dPar['pIniInventory'][es].loc[p,sc,n] > mTEPES.dPar['pMaxStorage'][es].loc[p,sc,n]:
|
|
999
|
+
mTEPES.dPar['pIniInventory'][es].loc[p,sc,n] = mTEPES.dPar['pMaxStorage'][es].loc[p,sc,n]
|
|
984
1000
|
print('### Initial inventory greater than maximum storage ', p, sc, st, es)
|
|
985
|
-
if pIndHydroTopology == 1:
|
|
1001
|
+
if mTEPES.dPar['pIndHydroTopology'] == 1:
|
|
986
1002
|
for p,sc,n,rs in mTEPES.psnrs:
|
|
987
|
-
if (p,sc,st,n) in mTEPES.s2n and mTEPES.n.ord(n) == pReservoirTimeStep[rs]:
|
|
988
|
-
if pIniVolume[rs][p,sc,n] < pMinVolume[rs][p,sc,n]:
|
|
989
|
-
pIniVolume[rs][p,sc,n] = pMinVolume[rs][p,sc,n]
|
|
1003
|
+
if (p,sc,st,n) in mTEPES.s2n and mTEPES.n.ord(n) == mTEPES.dPar['pReservoirTimeStep'][rs]:
|
|
1004
|
+
if mTEPES.dPar['pIniVolume'][rs].loc[p,sc,n] < mTEPES.dPar['pMinVolume'][rs].loc[p,sc,n]:
|
|
1005
|
+
mTEPES.dPar['pIniVolume'][rs].loc[p,sc,n] = mTEPES.dPar['pMinVolume'][rs].loc[p,sc,n]
|
|
990
1006
|
print('### Initial volume lower than minimum volume ', p, sc, st, rs)
|
|
991
|
-
if pIniVolume[rs][p,sc,n] > pMaxVolume[rs][p,sc,n]:
|
|
992
|
-
pIniVolume[rs][p,sc,n] = pMaxVolume[rs][p,sc,n]
|
|
1007
|
+
if mTEPES.dPar['pIniVolume'][rs].loc[p,sc,n] > mTEPES.dPar['pMaxVolume'][rs].loc[p,sc,n]:
|
|
1008
|
+
mTEPES.dPar['pIniVolume'][rs].loc[p,sc,n] = mTEPES.dPar['pMaxVolume'][rs].loc[p,sc,n]
|
|
993
1009
|
print('### Initial volume greater than maximum volume ', p, sc, st, rs)
|
|
994
1010
|
|
|
995
1011
|
# drop load levels with duration 0
|
|
996
|
-
pDuration = pDuration.loc [mTEPES.psn ]
|
|
997
|
-
pDemandElec = pDemandElec.loc [mTEPES.psn ]
|
|
998
|
-
pSystemInertia = pSystemInertia.loc [mTEPES.psnar]
|
|
999
|
-
pOperReserveUp = pOperReserveUp.loc [mTEPES.psnar]
|
|
1000
|
-
pOperReserveDw = pOperReserveDw.loc [mTEPES.psnar]
|
|
1001
|
-
pMinPowerElec = pMinPowerElec.loc [mTEPES.psn ]
|
|
1002
|
-
pMaxPowerElec = pMaxPowerElec.loc [mTEPES.psn ]
|
|
1003
|
-
pMinCharge = pMinCharge.loc [mTEPES.psn ]
|
|
1004
|
-
pMaxCharge = pMaxCharge.loc [mTEPES.psn ]
|
|
1005
|
-
pEnergyInflows = pEnergyInflows.loc [mTEPES.psn ]
|
|
1006
|
-
pEnergyOutflows = pEnergyOutflows.loc [mTEPES.psn ]
|
|
1007
|
-
pIniInventory = pIniInventory.loc [mTEPES.psn ]
|
|
1008
|
-
pMinStorage = pMinStorage.loc [mTEPES.psn ]
|
|
1009
|
-
pMaxStorage = pMaxStorage.loc [mTEPES.psn ]
|
|
1010
|
-
pVariableMaxEnergy = pVariableMaxEnergy.loc [mTEPES.psn ]
|
|
1011
|
-
pVariableMinEnergy = pVariableMinEnergy.loc [mTEPES.psn ]
|
|
1012
|
-
pLinearVarCost = pLinearVarCost.loc [mTEPES.psn ]
|
|
1013
|
-
pConstantVarCost = pConstantVarCost.loc [mTEPES.psn ]
|
|
1014
|
-
pEmissionVarCost = pEmissionVarCost.loc [mTEPES.psn ]
|
|
1015
|
-
|
|
1016
|
-
pRatedLinearOperCost = pRatedLinearFuelCost.loc [mTEPES.g ]
|
|
1017
|
-
pRatedLinearVarCost = pRatedLinearFuelCost.loc [mTEPES.g ]
|
|
1012
|
+
mTEPES.dPar['pDuration'] = mTEPES.dPar['pDuration'].loc [mTEPES.psn ]
|
|
1013
|
+
mTEPES.dPar['pDemandElec'] = mTEPES.dPar['pDemandElec'].loc [mTEPES.psn ]
|
|
1014
|
+
mTEPES.dPar['pSystemInertia'] = mTEPES.dPar['pSystemInertia'].loc [mTEPES.psnar]
|
|
1015
|
+
mTEPES.dPar['pOperReserveUp'] = mTEPES.dPar['pOperReserveUp'].loc [mTEPES.psnar]
|
|
1016
|
+
mTEPES.dPar['pOperReserveDw'] = mTEPES.dPar['pOperReserveDw'].loc [mTEPES.psnar]
|
|
1017
|
+
mTEPES.dPar['pMinPowerElec'] = mTEPES.dPar['pMinPowerElec'].loc [mTEPES.psn ]
|
|
1018
|
+
mTEPES.dPar['pMaxPowerElec'] = mTEPES.dPar['pMaxPowerElec'].loc [mTEPES.psn ]
|
|
1019
|
+
mTEPES.dPar['pMinCharge'] = mTEPES.dPar['pMinCharge'].loc [mTEPES.psn ]
|
|
1020
|
+
mTEPES.dPar['pMaxCharge'] = mTEPES.dPar['pMaxCharge'].loc [mTEPES.psn ]
|
|
1021
|
+
mTEPES.dPar['pEnergyInflows'] = mTEPES.dPar['pEnergyInflows'].loc [mTEPES.psn ]
|
|
1022
|
+
mTEPES.dPar['pEnergyOutflows'] = mTEPES.dPar['pEnergyOutflows'].loc [mTEPES.psn ]
|
|
1023
|
+
mTEPES.dPar['pIniInventory'] = mTEPES.dPar['pIniInventory'].loc [mTEPES.psn ]
|
|
1024
|
+
mTEPES.dPar['pMinStorage'] = mTEPES.dPar['pMinStorage'].loc [mTEPES.psn ]
|
|
1025
|
+
mTEPES.dPar['pMaxStorage'] = mTEPES.dPar['pMaxStorage'].loc [mTEPES.psn ]
|
|
1026
|
+
mTEPES.dPar['pVariableMaxEnergy'] = mTEPES.dPar['pVariableMaxEnergy'].loc [mTEPES.psn ]
|
|
1027
|
+
mTEPES.dPar['pVariableMinEnergy'] = mTEPES.dPar['pVariableMinEnergy'].loc [mTEPES.psn ]
|
|
1028
|
+
mTEPES.dPar['pLinearVarCost'] = mTEPES.dPar['pLinearVarCost'].loc [mTEPES.psn ]
|
|
1029
|
+
mTEPES.dPar['pConstantVarCost'] = mTEPES.dPar['pConstantVarCost'].loc [mTEPES.psn ]
|
|
1030
|
+
mTEPES.dPar['pEmissionVarCost'] = mTEPES.dPar['pEmissionVarCost'].loc [mTEPES.psn ]
|
|
1031
|
+
|
|
1032
|
+
mTEPES.dPar['pRatedLinearOperCost'] = mTEPES.dPar['pRatedLinearFuelCost'].loc [mTEPES.g ]
|
|
1033
|
+
mTEPES.dPar['pRatedLinearVarCost'] = mTEPES.dPar['pRatedLinearFuelCost'].loc [mTEPES.g ]
|
|
1018
1034
|
|
|
1019
1035
|
# drop generators not es
|
|
1020
|
-
pEfficiency = pEfficiency.loc [mTEPES.eh ]
|
|
1021
|
-
pStorageTimeStep = pStorageTimeStep.loc [mTEPES.es ]
|
|
1022
|
-
pOutflowsTimeStep = pOutflowsTimeStep.loc [mTEPES.es ]
|
|
1023
|
-
pStorageType = pStorageType.loc [mTEPES.es ]
|
|
1024
|
-
|
|
1025
|
-
if pIndHydroTopology == 1:
|
|
1026
|
-
pHydroInflows = pHydroInflows.loc [mTEPES.psn ]
|
|
1027
|
-
pHydroOutflows = pHydroOutflows.loc [mTEPES.psn ]
|
|
1028
|
-
pIniVolume = pIniVolume.loc [mTEPES.psn ]
|
|
1029
|
-
pMinVolume = pMinVolume.loc [mTEPES.psn ]
|
|
1030
|
-
pMaxVolume = pMaxVolume.loc [mTEPES.psn ]
|
|
1031
|
-
if pIndHydrogen == 1:
|
|
1032
|
-
pDemandH2 = pDemandH2.loc [mTEPES.psn ]
|
|
1033
|
-
pDemandH2Abs = pDemandH2.where (pDemandH2 > 0.0, 0.0)
|
|
1034
|
-
if pIndHeat == 1:
|
|
1035
|
-
pDemandHeat = pDemandHeat.loc [mTEPES.psn ]
|
|
1036
|
-
pDemandHeatAbs = pDemandHeat.where(pDemandHeat > 0.0, 0.0)
|
|
1036
|
+
mTEPES.dPar['pEfficiency'] = mTEPES.dPar['pEfficiency'].loc [mTEPES.eh ]
|
|
1037
|
+
mTEPES.dPar['pStorageTimeStep'] = mTEPES.dPar['pStorageTimeStep'].loc [mTEPES.es ]
|
|
1038
|
+
mTEPES.dPar['pOutflowsTimeStep'] = mTEPES.dPar['pOutflowsTimeStep'].loc [mTEPES.es ]
|
|
1039
|
+
mTEPES.dPar['pStorageType'] = mTEPES.dPar['pStorageType'].loc [mTEPES.es ]
|
|
1040
|
+
|
|
1041
|
+
if mTEPES.dPar['pIndHydroTopology'] == 1:
|
|
1042
|
+
mTEPES.dPar['pHydroInflows'] = mTEPES.dPar['pHydroInflows'].loc [mTEPES.psn ]
|
|
1043
|
+
mTEPES.dPar['pHydroOutflows'] = mTEPES.dPar['pHydroOutflows'].loc [mTEPES.psn ]
|
|
1044
|
+
mTEPES.dPar['pIniVolume'] = mTEPES.dPar['pIniVolume'].loc [mTEPES.psn ]
|
|
1045
|
+
mTEPES.dPar['pMinVolume'] = mTEPES.dPar['pMinVolume'].loc [mTEPES.psn ]
|
|
1046
|
+
mTEPES.dPar['pMaxVolume'] = mTEPES.dPar['pMaxVolume'].loc [mTEPES.psn ]
|
|
1047
|
+
if mTEPES.dPar['pIndHydrogen'] == 1:
|
|
1048
|
+
mTEPES.dPar['pDemandH2'] = mTEPES.dPar['pDemandH2'].loc [mTEPES.psn ]
|
|
1049
|
+
mTEPES.dPar['pDemandH2Abs'] = mTEPES.dPar['pDemandH2'].where (mTEPES.dPar['pDemandH2'] > 0.0, 0.0)
|
|
1050
|
+
if mTEPES.dPar['pIndHeat'] == 1:
|
|
1051
|
+
mTEPES.dPar['pDemandHeat'] = mTEPES.dPar['pDemandHeat'].loc [mTEPES.psn ]
|
|
1052
|
+
mTEPES.dPar['pDemandHeatAbs'] = mTEPES.dPar['pDemandHeat'].where(mTEPES.dPar['pDemandHeat'] > 0.0, 0.0)
|
|
1053
|
+
|
|
1054
|
+
if mTEPES.dPar['pIndVarTTC'] == 1:
|
|
1055
|
+
mTEPES.dPar['pVariableNTCFrw'] = mTEPES.dPar['pVariableNTCFrw'].loc [mTEPES.psn]
|
|
1056
|
+
mTEPES.dPar['pVariableNTCBck'] = mTEPES.dPar['pVariableNTCBck'].loc [mTEPES.psn]
|
|
1057
|
+
if mTEPES.dPar['pIndPTDF'] == 1:
|
|
1058
|
+
mTEPES.dPar['pVariablePTDF'] = mTEPES.dPar['pVariablePTDF'].loc [mTEPES.psn]
|
|
1037
1059
|
|
|
1038
1060
|
# separate positive and negative demands to avoid converting negative values to 0
|
|
1039
|
-
pDemandElecPos = pDemandElec.where(pDemandElec >= 0.0, 0.0)
|
|
1040
|
-
pDemandElecNeg = pDemandElec.where(pDemandElec < 0.0, 0.0)
|
|
1041
|
-
pDemandElecAbs = pDemandElec.where(pDemandElec > 0.0, 0.0)
|
|
1061
|
+
mTEPES.dPar['pDemandElecPos'] = mTEPES.dPar['pDemandElec'].where(mTEPES.dPar['pDemandElec'] >= 0.0, 0.0)
|
|
1062
|
+
mTEPES.dPar['pDemandElecNeg'] = mTEPES.dPar['pDemandElec'].where(mTEPES.dPar['pDemandElec'] < 0.0, 0.0)
|
|
1063
|
+
# mTEPES.dPar['pDemandElecAbs'] = mTEPES.dPar['pDemandElec'].where(mTEPES.dPar['pDemandElec'] > 0.0, 0.0)
|
|
1042
1064
|
|
|
1043
1065
|
# generators to area (g2a) (e2a) (n2a)
|
|
1044
1066
|
g2a = defaultdict(list)
|
|
@@ -1048,6 +1070,11 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
1048
1070
|
for ar,es in mTEPES.ar*mTEPES.es:
|
|
1049
1071
|
if (ar,es) in mTEPES.a2g:
|
|
1050
1072
|
e2a[ar].append(es)
|
|
1073
|
+
r2a = defaultdict(list)
|
|
1074
|
+
for ar,rs in mTEPES.ar*mTEPES.rs:
|
|
1075
|
+
for h in mTEPES.h:
|
|
1076
|
+
if (ar,h) in mTEPES.a2g and sum(1 for h in mTEPES.h if (rs,h) in mTEPES.r2h or (h,rs) in mTEPES.h2r or (rs,h) in mTEPES.r2p or (h,rs) in mTEPES.p2r) and rs not in r2a[ar]:
|
|
1077
|
+
r2a[ar].append(rs)
|
|
1051
1078
|
n2a = defaultdict(list)
|
|
1052
1079
|
for ar,nr in mTEPES.ar*mTEPES.nr:
|
|
1053
1080
|
if (ar,nr) in mTEPES.a2g:
|
|
@@ -1059,225 +1086,244 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
1059
1086
|
d2a[ar].append(nd)
|
|
1060
1087
|
|
|
1061
1088
|
# small values are converted to 0
|
|
1062
|
-
pDemandElecPeak = pd.Series([0.0 for p,ar in mTEPES.par], index=mTEPES.par)
|
|
1063
|
-
pDemandHeatPeak = pd.Series([0.0 for p,ar in mTEPES.par], index=mTEPES.par)
|
|
1089
|
+
mTEPES.dPar['pDemandElecPeak'] = pd.Series([0.0 for p,ar in mTEPES.par], index=mTEPES.par)
|
|
1090
|
+
mTEPES.dPar['pDemandHeatPeak'] = pd.Series([0.0 for p,ar in mTEPES.par], index=mTEPES.par)
|
|
1064
1091
|
for p,ar in mTEPES.par:
|
|
1065
1092
|
# values < 1e-5 times the maximum demand for each area (an area is related to operating reserves procurement, i.e., country) are converted to 0
|
|
1066
|
-
pDemandElecPeak[p,ar] = pDemandElec.loc[p,:,:][[nd for nd in d2a[ar]]].sum(axis=1).max()
|
|
1067
|
-
pEpsilonElec = pDemandElecPeak[p,ar]*1e-5
|
|
1093
|
+
mTEPES.dPar['pDemandElecPeak'][p,ar] = mTEPES.dPar['pDemandElec'].loc[p,:,:][[nd for nd in d2a[ar]]].sum(axis=1).max()
|
|
1094
|
+
mTEPES.dPar['pEpsilonElec'] = mTEPES.dPar['pDemandElecPeak'][p,ar]*1e-5
|
|
1068
1095
|
|
|
1069
1096
|
# these parameters are in GW
|
|
1070
|
-
pDemandElecPos [pDemandElecPos [[nd for nd in d2a[ar]]] < pEpsilonElec] = 0.0
|
|
1071
|
-
pDemandElecNeg [pDemandElecNeg [[nd for nd in d2a[ar]]] > -pEpsilonElec] = 0.0
|
|
1072
|
-
pSystemInertia [pSystemInertia [[ ar ]] < pEpsilonElec] = 0.0
|
|
1073
|
-
pOperReserveUp [pOperReserveUp [[ ar ]] < pEpsilonElec] = 0.0
|
|
1074
|
-
pOperReserveDw [pOperReserveDw [[ ar ]] < pEpsilonElec] = 0.0
|
|
1075
|
-
|
|
1076
|
-
if
|
|
1077
|
-
pMinPowerElec [pMinPowerElec [[g for g in g2a[ar]]] < pEpsilonElec] = 0.0
|
|
1078
|
-
pMaxPowerElec [pMaxPowerElec [[g for g in g2a[ar]]] < pEpsilonElec] = 0.0
|
|
1079
|
-
pMinCharge [pMinCharge [[es for es in e2a[ar]]] < pEpsilonElec] = 0.0
|
|
1080
|
-
pMaxCharge [pMaxCharge [[eh for eh in g2a[ar]]] < pEpsilonElec] = 0.0
|
|
1081
|
-
pEnergyInflows [pEnergyInflows [[es for es in e2a[ar]]] < pEpsilonElec] = 0.0
|
|
1082
|
-
pEnergyOutflows[pEnergyOutflows[[es for es in e2a[ar]]] < pEpsilonElec] = 0.0
|
|
1097
|
+
mTEPES.dPar['pDemandElecPos'] [mTEPES.dPar['pDemandElecPos'] [[nd for nd in d2a[ar]]] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1098
|
+
mTEPES.dPar['pDemandElecNeg'] [mTEPES.dPar['pDemandElecNeg'] [[nd for nd in d2a[ar]]] > -mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1099
|
+
mTEPES.dPar['pSystemInertia'] [mTEPES.dPar['pSystemInertia'] [[ ar ]] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1100
|
+
mTEPES.dPar['pOperReserveUp'] [mTEPES.dPar['pOperReserveUp'] [[ ar ]] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1101
|
+
mTEPES.dPar['pOperReserveDw'] [mTEPES.dPar['pOperReserveDw'] [[ ar ]] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1102
|
+
|
|
1103
|
+
if g2a[ar]:
|
|
1104
|
+
mTEPES.dPar['pMinPowerElec'] [mTEPES.dPar['pMinPowerElec'] [[g for g in g2a[ar]]] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1105
|
+
mTEPES.dPar['pMaxPowerElec'] [mTEPES.dPar['pMaxPowerElec'] [[g for g in g2a[ar]]] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1106
|
+
mTEPES.dPar['pMinCharge'] [mTEPES.dPar['pMinCharge'] [[es for es in e2a[ar]]] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1107
|
+
mTEPES.dPar['pMaxCharge'] [mTEPES.dPar['pMaxCharge'] [[eh for eh in g2a[ar]]] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1108
|
+
mTEPES.dPar['pEnergyInflows'] [mTEPES.dPar['pEnergyInflows'] [[es for es in e2a[ar]]] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1109
|
+
mTEPES.dPar['pEnergyOutflows'][mTEPES.dPar['pEnergyOutflows'][[es for es in e2a[ar]]] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1083
1110
|
# these parameters are in GWh
|
|
1084
|
-
pMinStorage [pMinStorage [[es for es in e2a[ar]]] < pEpsilonElec] = 0.0
|
|
1085
|
-
pMaxStorage [pMaxStorage [[es for es in e2a[ar]]] < pEpsilonElec] = 0.0
|
|
1086
|
-
pIniInventory [pIniInventory [[es for es in e2a[ar]]] < pEpsilonElec] = 0.0
|
|
1111
|
+
mTEPES.dPar['pMinStorage'] [mTEPES.dPar['pMinStorage'] [[es for es in e2a[ar]]] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1112
|
+
mTEPES.dPar['pMaxStorage'] [mTEPES.dPar['pMaxStorage'] [[es for es in e2a[ar]]] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1113
|
+
mTEPES.dPar['pIniInventory'] [mTEPES.dPar['pIniInventory'] [[es for es in e2a[ar]]] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1114
|
+
|
|
1115
|
+
if mTEPES.dPar['pIndHydroTopology'] == 1:
|
|
1116
|
+
mTEPES.dPar['pMinVolume'] [mTEPES.dPar['pMinVolume'] [[rs for rs in r2a[ar]]] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1117
|
+
mTEPES.dPar['pMaxVolume'] [mTEPES.dPar['pMaxVolume'] [[rs for rs in r2a[ar]]] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1118
|
+
mTEPES.dPar['pHydroInflows'] [mTEPES.dPar['pHydroInflows'] [[rs for rs in r2a[ar]]] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1119
|
+
mTEPES.dPar['pHydroOutflows'][mTEPES.dPar['pHydroOutflows'][[rs for rs in r2a[ar]]] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1087
1120
|
|
|
1088
1121
|
# pInitialInventory.update(pd.Series([0.0 for es in e2a[ar] if pInitialInventory[es] < pEpsilonElec], index=[es for es in e2a[ar] if pInitialInventory[es] < pEpsilonElec], dtype='float64'))
|
|
1089
1122
|
|
|
1090
1123
|
# merging positive and negative values of the demand
|
|
1091
|
-
pDemandElec = pDemandElecPos.where(pDemandElecNeg
|
|
1124
|
+
mTEPES.dPar['pDemandElec'] = mTEPES.dPar['pDemandElecPos'].where(mTEPES.dPar['pDemandElecNeg'] == 0.0, mTEPES.dPar['pDemandElecNeg'])
|
|
1092
1125
|
|
|
1093
1126
|
# Increase Maximum to reach minimum
|
|
1094
|
-
# pMaxPowerElec = pMaxPowerElec.where(pMaxPowerElec >= pMinPowerElec, pMinPowerElec)
|
|
1095
|
-
# pMaxCharge = pMaxCharge.where (pMaxCharge >= pMinCharge, pMinCharge )
|
|
1127
|
+
# mTEPES.dPar['pMaxPowerElec'] = mTEPES.dPar['pMaxPowerElec'].where(mTEPES.dPar['pMaxPowerElec'] >= mTEPES.dPar['pMinPowerElec'], mTEPES.dPar['pMinPowerElec'])
|
|
1128
|
+
# mTEPES.dPar['pMaxCharge'] = mTEPES.dPar['pMaxCharge'].where (mTEPES.dPar['pMaxCharge'] >= mTEPES.dPar['pMinCharge'], mTEPES.dPar['pMinCharge'] )
|
|
1096
1129
|
|
|
1097
1130
|
# Decrease Minimum to reach maximum
|
|
1098
|
-
pMinPowerElec = pMinPowerElec.where(pMinPowerElec <= pMaxPowerElec, pMaxPowerElec)
|
|
1099
|
-
pMinCharge = pMinCharge.where (pMinCharge <= pMaxCharge, pMaxCharge )
|
|
1131
|
+
mTEPES.dPar['pMinPowerElec'] = mTEPES.dPar['pMinPowerElec'].where(mTEPES.dPar['pMinPowerElec'] <= mTEPES.dPar['pMaxPowerElec'], mTEPES.dPar['pMaxPowerElec'])
|
|
1132
|
+
mTEPES.dPar['pMinCharge'] = mTEPES.dPar['pMinCharge'].where (mTEPES.dPar['pMinCharge'] <= mTEPES.dPar['pMaxCharge'], mTEPES.dPar['pMaxCharge'] )
|
|
1100
1133
|
|
|
1101
|
-
#
|
|
1102
|
-
pMaxPower2ndBlock = pMaxPowerElec - pMinPowerElec
|
|
1103
|
-
pMaxCharge2ndBlock = pMaxCharge - pMinCharge
|
|
1134
|
+
# calculate 2nd Blocks
|
|
1135
|
+
mTEPES.dPar['pMaxPower2ndBlock'] = mTEPES.dPar['pMaxPowerElec'] - mTEPES.dPar['pMinPowerElec']
|
|
1136
|
+
mTEPES.dPar['pMaxCharge2ndBlock'] = mTEPES.dPar['pMaxCharge'] - mTEPES.dPar['pMinCharge']
|
|
1104
1137
|
|
|
1105
|
-
pMaxCapacity = pMaxPowerElec.where(pMaxPowerElec > pMaxCharge, pMaxCharge)
|
|
1138
|
+
mTEPES.dPar['pMaxCapacity'] = mTEPES.dPar['pMaxPowerElec'].where(mTEPES.dPar['pMaxPowerElec'] > mTEPES.dPar['pMaxCharge'], mTEPES.dPar['pMaxCharge'])
|
|
1106
1139
|
|
|
1107
|
-
if
|
|
1108
|
-
pMaxPower2ndBlock [pMaxPower2ndBlock [[g for g in g2a[ar]]] < pEpsilonElec] = 0.0
|
|
1109
|
-
pMaxCharge2ndBlock[pMaxCharge2ndBlock[[g for g in g2a[ar]]] < pEpsilonElec] = 0.0
|
|
1140
|
+
if g2a[ar]:
|
|
1141
|
+
mTEPES.dPar['pMaxPower2ndBlock'] [mTEPES.dPar['pMaxPower2ndBlock'] [[g for g in g2a[ar]]] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1142
|
+
mTEPES.dPar['pMaxCharge2ndBlock'][mTEPES.dPar['pMaxCharge2ndBlock'][[g for g in g2a[ar]]] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1110
1143
|
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
pLineNTCMax = pLineNTCFrw.where(pLineNTCFrw > pLineNTCBck, pLineNTCBck)
|
|
1144
|
+
mTEPES.dPar['pLineNTCFrw'][mTEPES.dPar['pLineNTCFrw'] < mTEPES.dPar['pEpsilonElec']] = 0
|
|
1145
|
+
mTEPES.dPar['pLineNTCBck'][mTEPES.dPar['pLineNTCBck'] < mTEPES.dPar['pEpsilonElec']] = 0
|
|
1146
|
+
mTEPES.dPar['pLineNTCMax'] = mTEPES.dPar['pLineNTCFrw'].where(mTEPES.dPar['pLineNTCFrw'] > mTEPES.dPar['pLineNTCBck'], mTEPES.dPar['pLineNTCBck'])
|
|
1114
1147
|
|
|
1115
|
-
if pIndHydrogen == 1:
|
|
1116
|
-
pDemandH2[pDemandH2[[nd for nd in d2a[ar]]] < pEpsilonElec] = 0.0
|
|
1117
|
-
|
|
1118
|
-
|
|
1148
|
+
if mTEPES.dPar['pIndHydrogen'] == 1:
|
|
1149
|
+
mTEPES.dPar['pDemandH2'][mTEPES.dPar['pDemandH2'][[nd for nd in d2a[ar]]] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1150
|
+
mTEPES.dPar['pH2PipeNTCFrw'][mTEPES.dPar['pH2PipeNTCFrw'] < mTEPES.dPar['pEpsilonElec']] = 0
|
|
1151
|
+
mTEPES.dPar['pH2PipeNTCBck'][mTEPES.dPar['pH2PipeNTCBck'] < mTEPES.dPar['pEpsilonElec']] = 0
|
|
1119
1152
|
|
|
1120
|
-
if pIndHeat == 1:
|
|
1121
|
-
pDemandHeatPeak[p,ar] = pDemandHeat.loc[p,:,:][[nd for nd in d2a[ar]]].sum(axis=1).max()
|
|
1122
|
-
pEpsilonHeat = pDemandHeatPeak[p,ar]*1e-5
|
|
1123
|
-
pDemandHeat [pDemandHeat [[nd for nd in d2a[ar]]] < pEpsilonHeat] = 0.0
|
|
1124
|
-
|
|
1125
|
-
|
|
1153
|
+
if mTEPES.dPar['pIndHeat'] == 1:
|
|
1154
|
+
mTEPES.dPar['pDemandHeatPeak'][p,ar] = mTEPES.dPar['pDemandHeat'].loc[p,:,:][[nd for nd in d2a[ar]]].sum(axis=1).max()
|
|
1155
|
+
mTEPES.dPar['pEpsilonHeat'] = mTEPES.dPar['pDemandHeatPeak'][p,ar]*1e-5
|
|
1156
|
+
mTEPES.dPar['pDemandHeat'] [mTEPES.dPar['pDemandHeat'] [[nd for nd in d2a[ar]]] < mTEPES.dPar['pEpsilonHeat']] = 0.0
|
|
1157
|
+
mTEPES.dPar['pHeatPipeNTCFrw'][mTEPES.dPar['pHeatPipeNTCFrw'] < mTEPES.dPar['pEpsilonElec']] = 0
|
|
1158
|
+
mTEPES.dPar['pHeatPipeNTCBck'][mTEPES.dPar['pHeatPipeNTCBck'] < mTEPES.dPar['pEpsilonElec']] = 0
|
|
1126
1159
|
|
|
1127
1160
|
# drop generators not g or es or eh or ch
|
|
1128
|
-
pMinPowerElec = pMinPowerElec.loc [:,mTEPES.g ]
|
|
1129
|
-
pMaxPowerElec = pMaxPowerElec.loc [:,mTEPES.g ]
|
|
1130
|
-
pMinCharge = pMinCharge.loc [:,mTEPES.eh]
|
|
1131
|
-
pMaxCharge = pMaxCharge.loc [:,mTEPES.eh]
|
|
1132
|
-
pMaxPower2ndBlock = pMaxPower2ndBlock.loc [:,mTEPES.g ]
|
|
1133
|
-
pMaxCharge2ndBlock = pMaxCharge2ndBlock.loc[:,mTEPES.eh]
|
|
1134
|
-
pMaxCapacity = pMaxCapacity.loc [:,mTEPES.eh]
|
|
1135
|
-
pEnergyInflows = pEnergyInflows.loc [:,mTEPES.es]
|
|
1136
|
-
pEnergyOutflows = pEnergyOutflows.loc [:,mTEPES.es]
|
|
1137
|
-
pIniInventory = pIniInventory.loc [:,mTEPES.es]
|
|
1138
|
-
pMinStorage = pMinStorage.loc [:,mTEPES.es]
|
|
1139
|
-
pMaxStorage = pMaxStorage.loc [:,mTEPES.es]
|
|
1140
|
-
pVariableMaxEnergy = pVariableMaxEnergy.loc[:,mTEPES.g ]
|
|
1141
|
-
pVariableMinEnergy = pVariableMinEnergy.loc[:,mTEPES.g ]
|
|
1142
|
-
pLinearVarCost = pLinearVarCost.loc [:,mTEPES.g ]
|
|
1143
|
-
pConstantVarCost = pConstantVarCost.loc [:,mTEPES.g ]
|
|
1144
|
-
pEmissionVarCost = pEmissionVarCost.loc [:,mTEPES.g ]
|
|
1161
|
+
mTEPES.dPar['pMinPowerElec'] = mTEPES.dPar['pMinPowerElec'].loc [:,mTEPES.g ]
|
|
1162
|
+
mTEPES.dPar['pMaxPowerElec'] = mTEPES.dPar['pMaxPowerElec'].loc [:,mTEPES.g ]
|
|
1163
|
+
mTEPES.dPar['pMinCharge'] = mTEPES.dPar['pMinCharge'].loc [:,mTEPES.eh]
|
|
1164
|
+
mTEPES.dPar['pMaxCharge'] = mTEPES.dPar['pMaxCharge'].loc [:,mTEPES.eh]
|
|
1165
|
+
mTEPES.dPar['pMaxPower2ndBlock'] = mTEPES.dPar['pMaxPower2ndBlock'].loc [:,mTEPES.g ]
|
|
1166
|
+
mTEPES.dPar['pMaxCharge2ndBlock'] = mTEPES.dPar['pMaxCharge2ndBlock'].loc[:,mTEPES.eh]
|
|
1167
|
+
mTEPES.dPar['pMaxCapacity'] = mTEPES.dPar['pMaxCapacity'].loc [:,mTEPES.eh]
|
|
1168
|
+
mTEPES.dPar['pEnergyInflows'] = mTEPES.dPar['pEnergyInflows'].loc [:,mTEPES.es]
|
|
1169
|
+
mTEPES.dPar['pEnergyOutflows'] = mTEPES.dPar['pEnergyOutflows'].loc [:,mTEPES.es]
|
|
1170
|
+
mTEPES.dPar['pIniInventory'] = mTEPES.dPar['pIniInventory'].loc [:,mTEPES.es]
|
|
1171
|
+
mTEPES.dPar['pMinStorage'] = mTEPES.dPar['pMinStorage'].loc [:,mTEPES.es]
|
|
1172
|
+
mTEPES.dPar['pMaxStorage'] = mTEPES.dPar['pMaxStorage'].loc [:,mTEPES.es]
|
|
1173
|
+
mTEPES.dPar['pVariableMaxEnergy'] = mTEPES.dPar['pVariableMaxEnergy'].loc[:,mTEPES.g ]
|
|
1174
|
+
mTEPES.dPar['pVariableMinEnergy'] = mTEPES.dPar['pVariableMinEnergy'].loc[:,mTEPES.g ]
|
|
1175
|
+
mTEPES.dPar['pLinearVarCost'] = mTEPES.dPar['pLinearVarCost'].loc [:,mTEPES.g ]
|
|
1176
|
+
mTEPES.dPar['pConstantVarCost'] = mTEPES.dPar['pConstantVarCost'].loc [:,mTEPES.g ]
|
|
1177
|
+
mTEPES.dPar['pEmissionVarCost'] = mTEPES.dPar['pEmissionVarCost'].loc [:,mTEPES.g ]
|
|
1145
1178
|
|
|
1146
1179
|
# replace < 0.0 by 0.0
|
|
1147
|
-
pEpsilon = 1e-6
|
|
1148
|
-
pMaxPower2ndBlock = pMaxPower2ndBlock.where (pMaxPower2ndBlock > pEpsilon, 0.0)
|
|
1149
|
-
pMaxCharge2ndBlock = pMaxCharge2ndBlock.where(pMaxCharge2ndBlock > pEpsilon, 0.0)
|
|
1180
|
+
mTEPES.dPar['pEpsilon'] = 1e-6
|
|
1181
|
+
mTEPES.dPar['pMaxPower2ndBlock'] = mTEPES.dPar['pMaxPower2ndBlock'].where (mTEPES.dPar['pMaxPower2ndBlock'] > mTEPES.dPar['pEpsilon'], 0.0)
|
|
1182
|
+
mTEPES.dPar['pMaxCharge2ndBlock'] = mTEPES.dPar['pMaxCharge2ndBlock'].where(mTEPES.dPar['pMaxCharge2ndBlock'] > mTEPES.dPar['pEpsilon'], 0.0)
|
|
1150
1183
|
|
|
1151
|
-
# computation of the power
|
|
1184
|
+
# computation of the power-to-heat ratio of the CHP units
|
|
1152
1185
|
# heat ratio of boiler units is fixed to 1.0
|
|
1153
|
-
pPower2HeatRatio = pd.Series([1.0 if ch in mTEPES.bo else (pRatedMaxPowerElec[ch]-pRatedMinPowerElec[ch])/(pRatedMaxPowerHeat[ch]-pRatedMinPowerHeat[ch]) for ch in mTEPES.ch], index=mTEPES.ch)
|
|
1154
|
-
pMinPowerHeat = pd.DataFrame([[pMinPowerElec [ch][p,sc,n]/pPower2HeatRatio[ch] for ch in mTEPES.ch] for p,sc,n in mTEPES.psn], index=mTEPES.psn, columns=mTEPES.ch)
|
|
1155
|
-
pMaxPowerHeat = pd.DataFrame([[pMaxPowerElec [ch][p,sc,n]/pPower2HeatRatio[ch] for ch in mTEPES.ch] for p,sc,n in mTEPES.psn], index=mTEPES.psn, columns=mTEPES.ch)
|
|
1156
|
-
pMinPowerHeat.update(pd.DataFrame([[pRatedMinPowerHeat[bo]
|
|
1157
|
-
pMaxPowerHeat.update(pd.DataFrame([[pRatedMaxPowerHeat[bo]
|
|
1158
|
-
pMaxPowerHeat.update(pd.DataFrame([[pMaxCharge[hp][p,sc,n]/pProductionFunctionHeat[hp] for hp in mTEPES.hp] for p,sc,n in mTEPES.psn], index=mTEPES.psn, columns=mTEPES.hp))
|
|
1186
|
+
mTEPES.dPar['pPower2HeatRatio'] = pd.Series([1.0 if ch in mTEPES.bo else (mTEPES.dPar['pRatedMaxPowerElec'][ch]-mTEPES.dPar['pRatedMinPowerElec'][ch])/(mTEPES.dPar['pRatedMaxPowerHeat'][ch]-mTEPES.dPar['pRatedMinPowerHeat'][ch]) for ch in mTEPES.ch], index=mTEPES.ch)
|
|
1187
|
+
mTEPES.dPar['pMinPowerHeat'] = pd.DataFrame([[mTEPES.dPar['pMinPowerElec'] [ch][p,sc,n]/mTEPES.dPar['pPower2HeatRatio'][ch] for ch in mTEPES.ch] for p,sc,n in mTEPES.psn], index=mTEPES.psn, columns=mTEPES.ch)
|
|
1188
|
+
mTEPES.dPar['pMaxPowerHeat'] = pd.DataFrame([[mTEPES.dPar['pMaxPowerElec'] [ch][p,sc,n]/mTEPES.dPar['pPower2HeatRatio'][ch] for ch in mTEPES.ch] for p,sc,n in mTEPES.psn], index=mTEPES.psn, columns=mTEPES.ch)
|
|
1189
|
+
mTEPES.dPar['pMinPowerHeat'].update(pd.DataFrame([[mTEPES.dPar['pRatedMinPowerHeat'][bo] for bo in mTEPES.bo] for p,sc,n in mTEPES.psn], index=mTEPES.psn, columns=mTEPES.bo))
|
|
1190
|
+
mTEPES.dPar['pMaxPowerHeat'].update(pd.DataFrame([[mTEPES.dPar['pRatedMaxPowerHeat'][bo] for bo in mTEPES.bo] for p,sc,n in mTEPES.psn], index=mTEPES.psn, columns=mTEPES.bo))
|
|
1191
|
+
mTEPES.dPar['pMaxPowerHeat'].update(pd.DataFrame([[mTEPES.dPar['pMaxCharge'][hp][p,sc,n]/mTEPES.dPar['pProductionFunctionHeat'][hp] for hp in mTEPES.hp] for p,sc,n in mTEPES.psn], index=mTEPES.psn, columns=mTEPES.hp))
|
|
1159
1192
|
|
|
1160
1193
|
# drop values not par, p, or ps
|
|
1161
|
-
pReserveMargin = pReserveMargin.loc [mTEPES.par]
|
|
1162
|
-
pEmission = pEmission.loc [mTEPES.par]
|
|
1163
|
-
pRESEnergy = pRESEnergy.loc [mTEPES.par]
|
|
1164
|
-
pDemandElecPeak = pDemandElecPeak.loc[mTEPES.par]
|
|
1165
|
-
pDemandHeatPeak = pDemandHeatPeak.loc[mTEPES.par]
|
|
1166
|
-
pPeriodWeight = pPeriodWeight.loc [mTEPES.p ]
|
|
1167
|
-
pScenProb = pScenProb.loc [mTEPES.ps ]
|
|
1194
|
+
mTEPES.dPar['pReserveMargin'] = mTEPES.dPar['pReserveMargin'].loc [mTEPES.par]
|
|
1195
|
+
mTEPES.dPar['pEmission'] = mTEPES.dPar['pEmission'].loc [mTEPES.par]
|
|
1196
|
+
mTEPES.dPar['pRESEnergy'] = mTEPES.dPar['pRESEnergy'].loc [mTEPES.par]
|
|
1197
|
+
mTEPES.dPar['pDemandElecPeak'] = mTEPES.dPar['pDemandElecPeak'].loc[mTEPES.par]
|
|
1198
|
+
mTEPES.dPar['pDemandHeatPeak'] = mTEPES.dPar['pDemandHeatPeak'].loc[mTEPES.par]
|
|
1199
|
+
mTEPES.dPar['pPeriodWeight'] = mTEPES.dPar['pPeriodWeight'].loc [mTEPES.p ]
|
|
1200
|
+
mTEPES.dPar['pScenProb'] = mTEPES.dPar['pScenProb'].loc [mTEPES.ps ]
|
|
1168
1201
|
|
|
1169
1202
|
# drop generators not gc or gd
|
|
1170
|
-
pGenInvestCost = pGenInvestCost.loc [mTEPES.eb]
|
|
1171
|
-
pGenRetireCost = pGenRetireCost.loc [mTEPES.gd]
|
|
1172
|
-
pIndBinUnitInvest = pIndBinUnitInvest.loc[mTEPES.eb]
|
|
1173
|
-
pIndBinUnitRetire = pIndBinUnitRetire.loc[mTEPES.gd]
|
|
1174
|
-
pGenLoInvest = pGenLoInvest.loc [mTEPES.eb]
|
|
1175
|
-
pGenLoRetire = pGenLoRetire.loc [mTEPES.gd]
|
|
1176
|
-
pGenUpInvest = pGenUpInvest.loc [mTEPES.eb]
|
|
1177
|
-
pGenUpRetire = pGenUpRetire.loc [mTEPES.gd]
|
|
1203
|
+
mTEPES.dPar['pGenInvestCost'] = mTEPES.dPar['pGenInvestCost'].loc [mTEPES.eb]
|
|
1204
|
+
mTEPES.dPar['pGenRetireCost'] = mTEPES.dPar['pGenRetireCost'].loc [mTEPES.gd]
|
|
1205
|
+
mTEPES.dPar['pIndBinUnitInvest'] = mTEPES.dPar['pIndBinUnitInvest'].loc[mTEPES.eb]
|
|
1206
|
+
mTEPES.dPar['pIndBinUnitRetire'] = mTEPES.dPar['pIndBinUnitRetire'].loc[mTEPES.gd]
|
|
1207
|
+
mTEPES.dPar['pGenLoInvest'] = mTEPES.dPar['pGenLoInvest'].loc [mTEPES.eb]
|
|
1208
|
+
mTEPES.dPar['pGenLoRetire'] = mTEPES.dPar['pGenLoRetire'].loc [mTEPES.gd]
|
|
1209
|
+
mTEPES.dPar['pGenUpInvest'] = mTEPES.dPar['pGenUpInvest'].loc [mTEPES.eb]
|
|
1210
|
+
mTEPES.dPar['pGenUpRetire'] = mTEPES.dPar['pGenUpRetire'].loc [mTEPES.gd]
|
|
1178
1211
|
|
|
1179
1212
|
# drop generators not nr or ec
|
|
1180
|
-
pStartUpCost = pStartUpCost.loc [mTEPES.nr]
|
|
1181
|
-
pShutDownCost = pShutDownCost.loc [mTEPES.nr]
|
|
1182
|
-
pIndBinUnitCommit = pIndBinUnitCommit.loc[mTEPES.nr]
|
|
1183
|
-
pIndBinStorInvest = pIndBinStorInvest.loc[mTEPES.ec]
|
|
1213
|
+
mTEPES.dPar['pStartUpCost'] = mTEPES.dPar['pStartUpCost'].loc [mTEPES.nr]
|
|
1214
|
+
mTEPES.dPar['pShutDownCost'] = mTEPES.dPar['pShutDownCost'].loc [mTEPES.nr]
|
|
1215
|
+
mTEPES.dPar['pIndBinUnitCommit'] = mTEPES.dPar['pIndBinUnitCommit'].loc[mTEPES.nr]
|
|
1216
|
+
mTEPES.dPar['pIndBinStorInvest'] = mTEPES.dPar['pIndBinStorInvest'].loc[mTEPES.ec]
|
|
1184
1217
|
|
|
1185
1218
|
# drop lines not la
|
|
1186
|
-
pLineR = pLineR.loc [mTEPES.la]
|
|
1187
|
-
pLineX = pLineX.loc [mTEPES.la]
|
|
1188
|
-
pLineBsh = pLineBsh.loc [mTEPES.la]
|
|
1189
|
-
pLineTAP = pLineTAP.loc [mTEPES.la]
|
|
1190
|
-
pLineLength = pLineLength.loc [mTEPES.la]
|
|
1191
|
-
pElecNetPeriodIni = pElecNetPeriodIni.loc[mTEPES.la]
|
|
1192
|
-
pElecNetPeriodFin = pElecNetPeriodFin.loc[mTEPES.la]
|
|
1193
|
-
pLineVoltage = pLineVoltage.loc [mTEPES.la]
|
|
1194
|
-
pLineNTCFrw = pLineNTCFrw.loc [mTEPES.la]
|
|
1195
|
-
pLineNTCBck = pLineNTCBck.loc [mTEPES.la]
|
|
1196
|
-
pLineNTCMax = pLineNTCMax.loc [mTEPES.la]
|
|
1197
|
-
# pSwOnTime = pSwOnTime.loc [mTEPES.la]
|
|
1198
|
-
# pSwOffTime = pSwOffTime.loc [mTEPES.la]
|
|
1199
|
-
pIndBinLineInvest = pIndBinLineInvest.loc[mTEPES.la]
|
|
1200
|
-
pIndBinLineSwitch = pIndBinLineSwitch.loc[mTEPES.la]
|
|
1201
|
-
pAngMin = pAngMin.loc [mTEPES.la]
|
|
1202
|
-
pAngMax = pAngMax.loc [mTEPES.la]
|
|
1219
|
+
mTEPES.dPar['pLineR'] = mTEPES.dPar['pLineR'].loc [mTEPES.la]
|
|
1220
|
+
mTEPES.dPar['pLineX'] = mTEPES.dPar['pLineX'].loc [mTEPES.la]
|
|
1221
|
+
mTEPES.dPar['pLineBsh'] = mTEPES.dPar['pLineBsh'].loc [mTEPES.la]
|
|
1222
|
+
mTEPES.dPar['pLineTAP'] = mTEPES.dPar['pLineTAP'].loc [mTEPES.la]
|
|
1223
|
+
mTEPES.dPar['pLineLength'] = mTEPES.dPar['pLineLength'].loc [mTEPES.la]
|
|
1224
|
+
mTEPES.dPar['pElecNetPeriodIni'] = mTEPES.dPar['pElecNetPeriodIni'].loc[mTEPES.la]
|
|
1225
|
+
mTEPES.dPar['pElecNetPeriodFin'] = mTEPES.dPar['pElecNetPeriodFin'].loc[mTEPES.la]
|
|
1226
|
+
mTEPES.dPar['pLineVoltage'] = mTEPES.dPar['pLineVoltage'].loc [mTEPES.la]
|
|
1227
|
+
mTEPES.dPar['pLineNTCFrw'] = mTEPES.dPar['pLineNTCFrw'].loc [mTEPES.la]
|
|
1228
|
+
mTEPES.dPar['pLineNTCBck'] = mTEPES.dPar['pLineNTCBck'].loc [mTEPES.la]
|
|
1229
|
+
mTEPES.dPar['pLineNTCMax'] = mTEPES.dPar['pLineNTCMax'].loc [mTEPES.la]
|
|
1230
|
+
# mTEPES.dPar['pSwOnTime'] = mTEPES.dPar['pSwOnTime'].loc [mTEPES.la]
|
|
1231
|
+
# mTEPES.dPar['pSwOffTime'] = mTEPES.dPar['pSwOffTime'].loc [mTEPES.la]
|
|
1232
|
+
mTEPES.dPar['pIndBinLineInvest'] = mTEPES.dPar['pIndBinLineInvest'].loc[mTEPES.la]
|
|
1233
|
+
mTEPES.dPar['pIndBinLineSwitch'] = mTEPES.dPar['pIndBinLineSwitch'].loc[mTEPES.la]
|
|
1234
|
+
mTEPES.dPar['pAngMin'] = mTEPES.dPar['pAngMin'].loc [mTEPES.la]
|
|
1235
|
+
mTEPES.dPar['pAngMax'] = mTEPES.dPar['pAngMax'].loc [mTEPES.la]
|
|
1203
1236
|
|
|
1204
1237
|
# drop lines not lc or ll
|
|
1205
|
-
pNetFixedCost = pNetFixedCost.loc [mTEPES.lc]
|
|
1206
|
-
pNetLoInvest = pNetLoInvest.loc [mTEPES.lc]
|
|
1207
|
-
pNetUpInvest = pNetUpInvest.loc [mTEPES.lc]
|
|
1208
|
-
pLineLossFactor = pLineLossFactor.loc [mTEPES.ll]
|
|
1209
|
-
|
|
1210
|
-
|
|
1238
|
+
mTEPES.dPar['pNetFixedCost'] = mTEPES.dPar['pNetFixedCost'].loc [mTEPES.lc]
|
|
1239
|
+
mTEPES.dPar['pNetLoInvest'] = mTEPES.dPar['pNetLoInvest'].loc [mTEPES.lc]
|
|
1240
|
+
mTEPES.dPar['pNetUpInvest'] = mTEPES.dPar['pNetUpInvest'].loc [mTEPES.lc]
|
|
1241
|
+
mTEPES.dPar['pLineLossFactor'] = mTEPES.dPar['pLineLossFactor'].loc [mTEPES.ll]
|
|
1242
|
+
|
|
1243
|
+
mTEPES.dPar['pMaxNTCFrw'] = pd.DataFrame([[mTEPES.dPar['pLineNTCFrw'][la] for la in mTEPES.la] for p,sc,n in mTEPES.psn], index=mTEPES.psn, columns=mTEPES.la)
|
|
1244
|
+
mTEPES.dPar['pMaxNTCBck'] = pd.DataFrame([[mTEPES.dPar['pLineNTCBck'][la] for la in mTEPES.la] for p,sc,n in mTEPES.psn], index=mTEPES.psn, columns=mTEPES.la)
|
|
1245
|
+
if mTEPES.dPar['pIndVarTTC'] == 1:
|
|
1246
|
+
mTEPES.dPar['pMaxNTCFrw'] = mTEPES.dPar['pVariableNTCFrw'].replace(0.0, mTEPES.dPar['pLineNTCFrw'])
|
|
1247
|
+
mTEPES.dPar['pMaxNTCBck'] = mTEPES.dPar['pVariableNTCBck'].replace(0.0, mTEPES.dPar['pLineNTCBck'])
|
|
1248
|
+
mTEPES.dPar['pMaxNTCFrw'] [mTEPES.dPar['pMaxNTCFrw'] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1249
|
+
mTEPES.dPar['pMaxNTCBck'] [mTEPES.dPar['pMaxNTCBck'] < mTEPES.dPar['pEpsilonElec']] = 0.0
|
|
1250
|
+
mTEPES.dPar['pMaxNTCMax'] = mTEPES.dPar['pMaxNTCFrw'].where(mTEPES.dPar['pMaxNTCFrw'] > mTEPES.dPar['pMaxNTCBck'], mTEPES.dPar['pMaxNTCBck'])
|
|
1251
|
+
|
|
1252
|
+
mTEPES.dPar['pMaxNTCBck'] = mTEPES.dPar['pMaxNTCBck'].loc [:,mTEPES.la]
|
|
1253
|
+
mTEPES.dPar['pMaxNTCFrw'] = mTEPES.dPar['pMaxNTCFrw'].loc [:,mTEPES.la]
|
|
1254
|
+
mTEPES.dPar['pMaxNTCMax'] = mTEPES.dPar['pMaxNTCFrw'].loc [:,mTEPES.la]
|
|
1255
|
+
|
|
1256
|
+
if mTEPES.dPar['pIndHydroTopology'] == 1:
|
|
1211
1257
|
# drop generators not h
|
|
1212
|
-
pProductionFunctionHydro = pProductionFunctionHydro.loc[mTEPES.h ]
|
|
1258
|
+
mTEPES.dPar['pProductionFunctionHydro'] = mTEPES.dPar['pProductionFunctionHydro'].loc[mTEPES.h ]
|
|
1213
1259
|
# drop reservoirs not rn
|
|
1214
|
-
pIndBinRsrvInvest = pIndBinRsrvInvest.loc [mTEPES.rn]
|
|
1215
|
-
pRsrInvestCost = pRsrInvestCost.loc [mTEPES.rn]
|
|
1260
|
+
mTEPES.dPar['pIndBinRsrvInvest'] = mTEPES.dPar['pIndBinRsrvInvest'].loc [mTEPES.rn]
|
|
1261
|
+
mTEPES.dPar['pRsrInvestCost'] = mTEPES.dPar['pRsrInvestCost'].loc [mTEPES.rn]
|
|
1216
1262
|
# maximum outflows depending on the downstream hydropower unit
|
|
1217
|
-
pMaxOutflows = pd.DataFrame([[sum(pMaxPowerElec[h][p,sc,n]/pProductionFunctionHydro[h] for h in mTEPES.h if (rs,h) in mTEPES.r2h) for rs in mTEPES.rs] for p,sc,n in mTEPES.psn], index=mTEPES.psn, columns=mTEPES.rs)
|
|
1263
|
+
mTEPES.dPar['pMaxOutflows'] = pd.DataFrame([[sum(mTEPES.dPar['pMaxPowerElec'][h][p,sc,n]/mTEPES.dPar['pProductionFunctionHydro'][h] for h in mTEPES.h if (rs,h) in mTEPES.r2h) for rs in mTEPES.rs] for p,sc,n in mTEPES.psn], index=mTEPES.psn, columns=mTEPES.rs)
|
|
1218
1264
|
|
|
1219
|
-
if pIndHydrogen == 1:
|
|
1265
|
+
if mTEPES.dPar['pIndHydrogen'] == 1:
|
|
1220
1266
|
# drop generators not el
|
|
1221
|
-
pProductionFunctionH2 = pProductionFunctionH2.loc[mTEPES.el]
|
|
1267
|
+
mTEPES.dPar['pProductionFunctionH2'] = mTEPES.dPar['pProductionFunctionH2'].loc[mTEPES.el]
|
|
1222
1268
|
# drop pipelines not pc
|
|
1223
|
-
pH2PipeFixedCost = pH2PipeFixedCost.loc [mTEPES.pc]
|
|
1224
|
-
pH2PipeLoInvest = pH2PipeLoInvest.loc [mTEPES.pc]
|
|
1225
|
-
pH2PipeUpInvest = pH2PipeUpInvest.loc [mTEPES.pc]
|
|
1269
|
+
mTEPES.dPar['pH2PipeFixedCost'] = mTEPES.dPar['pH2PipeFixedCost'].loc [mTEPES.pc]
|
|
1270
|
+
mTEPES.dPar['pH2PipeLoInvest'] = mTEPES.dPar['pH2PipeLoInvest'].loc [mTEPES.pc]
|
|
1271
|
+
mTEPES.dPar['pH2PipeUpInvest'] = mTEPES.dPar['pH2PipeUpInvest'].loc [mTEPES.pc]
|
|
1226
1272
|
|
|
1227
|
-
if pIndHeat == 1:
|
|
1228
|
-
pReserveMarginHeat = pReserveMarginHeat.loc [mTEPES.par]
|
|
1273
|
+
if mTEPES.dPar['pIndHeat'] == 1:
|
|
1274
|
+
mTEPES.dPar['pReserveMarginHeat'] = mTEPES.dPar['pReserveMarginHeat'].loc [mTEPES.par]
|
|
1229
1275
|
# drop generators not hp
|
|
1230
|
-
pProductionFunctionHeat = pProductionFunctionHeat.loc [mTEPES.hp]
|
|
1276
|
+
mTEPES.dPar['pProductionFunctionHeat'] = mTEPES.dPar['pProductionFunctionHeat'].loc [mTEPES.hp]
|
|
1231
1277
|
# drop generators not hh
|
|
1232
|
-
pProductionFunctionH2ToHeat = pProductionFunctionH2ToHeat.loc[mTEPES.hh]
|
|
1278
|
+
mTEPES.dPar['pProductionFunctionH2ToHeat'] = mTEPES.dPar['pProductionFunctionH2ToHeat'].loc[mTEPES.hh]
|
|
1233
1279
|
# drop heat pipes not hc
|
|
1234
|
-
pHeatPipeFixedCost = pHeatPipeFixedCost.loc [mTEPES.hc]
|
|
1235
|
-
pHeatPipeLoInvest = pHeatPipeLoInvest.loc [mTEPES.hc]
|
|
1236
|
-
pHeatPipeUpInvest = pHeatPipeUpInvest.loc [mTEPES.hc]
|
|
1280
|
+
mTEPES.dPar['pHeatPipeFixedCost'] = mTEPES.dPar['pHeatPipeFixedCost'].loc [mTEPES.hc]
|
|
1281
|
+
mTEPES.dPar['pHeatPipeLoInvest'] = mTEPES.dPar['pHeatPipeLoInvest'].loc [mTEPES.hc]
|
|
1282
|
+
mTEPES.dPar['pHeatPipeUpInvest'] = mTEPES.dPar['pHeatPipeUpInvest'].loc [mTEPES.hc]
|
|
1237
1283
|
|
|
1238
1284
|
# replace very small costs by 0
|
|
1239
|
-
pEpsilon = 1e-5 # this value in EUR/GWh is lower than the O&M variable cost of any technology, independent of the area
|
|
1285
|
+
mTEPES.dPar['pEpsilon'] = 1e-5 # this value in EUR/GWh is lower than the O&M variable cost of any technology, independent of the area
|
|
1240
1286
|
|
|
1241
|
-
pLinearVarCost [pLinearVarCost [[g for g in mTEPES.g]] < pEpsilon] = 0.0
|
|
1242
|
-
pConstantVarCost[pConstantVarCost[[g for g in mTEPES.g]] < pEpsilon] = 0.0
|
|
1243
|
-
pEmissionVarCost[pEmissionVarCost[[g for g in mTEPES.g]] < pEpsilon] = 0.0
|
|
1287
|
+
mTEPES.dPar['pLinearVarCost'] [mTEPES.dPar['pLinearVarCost'] [[g for g in mTEPES.g]] < mTEPES.dPar['pEpsilon']] = 0.0
|
|
1288
|
+
mTEPES.dPar['pConstantVarCost'][mTEPES.dPar['pConstantVarCost'][[g for g in mTEPES.g]] < mTEPES.dPar['pEpsilon']] = 0.0
|
|
1289
|
+
mTEPES.dPar['pEmissionVarCost'][mTEPES.dPar['pEmissionVarCost'][[g for g in mTEPES.g]] < mTEPES.dPar['pEpsilon']] = 0.0
|
|
1244
1290
|
|
|
1245
|
-
pRatedLinearVarCost.update (pd.Series([0.0 for g in mTEPES.g if pRatedLinearVarCost [g ] < pEpsilon], index=[g for g in mTEPES.g if pRatedLinearVarCost [g ] < pEpsilon]))
|
|
1246
|
-
pRatedConstantVarCost.update(pd.Series([0.0 for g in mTEPES.g if pRatedConstantVarCost[g ] < pEpsilon], index=[g for g in mTEPES.g if pRatedConstantVarCost[g ] < pEpsilon]))
|
|
1247
|
-
pLinearOMCost.update (pd.Series([0.0 for g in mTEPES.g if pLinearOMCost [g ] < pEpsilon], index=[g for g in mTEPES.g if pLinearOMCost [g ] < pEpsilon]))
|
|
1248
|
-
pOperReserveCost.update (pd.Series([0.0 for g in mTEPES.g if pOperReserveCost [g ] < pEpsilon], index=[g for g in mTEPES.g if pOperReserveCost [g ] < pEpsilon]))
|
|
1249
|
-
# pEmissionCost.update (pd.Series([0.0 for g in mTEPES.g if abs(pEmissionCost [g ]) < pEpsilon], index=[g for g in mTEPES.g if abs(pEmissionCost [g ]) < pEpsilon]))
|
|
1250
|
-
pStartUpCost.update (pd.Series([0.0 for nr in mTEPES.nr if pStartUpCost [nr] < pEpsilon], index=[nr for nr in mTEPES.nr if pStartUpCost [nr] < pEpsilon]))
|
|
1251
|
-
pShutDownCost.update (pd.Series([0.0 for nr in mTEPES.nr if pShutDownCost [nr] < pEpsilon], index=[nr for nr in mTEPES.nr if pShutDownCost [nr] < pEpsilon]))
|
|
1291
|
+
mTEPES.dPar['pRatedLinearVarCost'].update (pd.Series([0.0 for g in mTEPES.g if mTEPES.dPar['pRatedLinearVarCost'] [g ] < mTEPES.dPar['pEpsilon']], index=[g for g in mTEPES.g if mTEPES.dPar['pRatedLinearVarCost'] [g ] < mTEPES.dPar['pEpsilon']]))
|
|
1292
|
+
mTEPES.dPar['pRatedConstantVarCost'].update(pd.Series([0.0 for g in mTEPES.g if mTEPES.dPar['pRatedConstantVarCost'][g ] < mTEPES.dPar['pEpsilon']], index=[g for g in mTEPES.g if mTEPES.dPar['pRatedConstantVarCost'][g ] < mTEPES.dPar['pEpsilon']]))
|
|
1293
|
+
mTEPES.dPar['pLinearOMCost'].update (pd.Series([0.0 for g in mTEPES.g if mTEPES.dPar['pLinearOMCost'] [g ] < mTEPES.dPar['pEpsilon']], index=[g for g in mTEPES.g if mTEPES.dPar['pLinearOMCost'] [g ] < mTEPES.dPar['pEpsilon']]))
|
|
1294
|
+
mTEPES.dPar['pOperReserveCost'].update (pd.Series([0.0 for g in mTEPES.g if mTEPES.dPar['pOperReserveCost'] [g ] < mTEPES.dPar['pEpsilon']], index=[g for g in mTEPES.g if mTEPES.dPar['pOperReserveCost'] [g ] < mTEPES.dPar['pEpsilon']]))
|
|
1295
|
+
# mTEPES.dPar['pEmissionCost'].update (pd.Series([0.0 for g in mTEPES.g if abs(mTEPES.dPar['pEmissionCost'] [g ]) < mTEPES.dPar['pEpsilon']], index=[g for g in mTEPES.g if abs(mTEPES.dPar['pEmissionCost'] [g ]) < mTEPES.dPar['pEpsilon']]))
|
|
1296
|
+
mTEPES.dPar['pStartUpCost'].update (pd.Series([0.0 for nr in mTEPES.nr if mTEPES.dPar['pStartUpCost'] [nr] < mTEPES.dPar['pEpsilon']], index=[nr for nr in mTEPES.nr if mTEPES.dPar['pStartUpCost'] [nr] < mTEPES.dPar['pEpsilon']]))
|
|
1297
|
+
mTEPES.dPar['pShutDownCost'].update (pd.Series([0.0 for nr in mTEPES.nr if mTEPES.dPar['pShutDownCost'] [nr] < mTEPES.dPar['pEpsilon']], index=[nr for nr in mTEPES.nr if mTEPES.dPar['pShutDownCost'] [nr] < mTEPES.dPar['pEpsilon']]))
|
|
1252
1298
|
|
|
1253
1299
|
# this rated linear variable cost is going to be used to order the generating units
|
|
1254
1300
|
# we include a small term to avoid a stochastic behavior due to equal values
|
|
1255
1301
|
for g in mTEPES.g:
|
|
1256
|
-
pRatedLinearVarCost[g] += 1e-3*pEpsilon*mTEPES.g.ord(g)
|
|
1302
|
+
mTEPES.dPar['pRatedLinearVarCost'][g] += 1e-3*mTEPES.dPar['pEpsilon']*mTEPES.g.ord(g)
|
|
1257
1303
|
|
|
1258
1304
|
# BigM maximum flow to be used in the Kirchhoff's 2nd law disjunctive constraint
|
|
1259
|
-
pBigMFlowBck = pLineNTCBck*0.0
|
|
1260
|
-
pBigMFlowFrw = pLineNTCFrw*0.0
|
|
1305
|
+
mTEPES.dPar['pBigMFlowBck'] = mTEPES.dPar['pLineNTCBck']*0.0
|
|
1306
|
+
mTEPES.dPar['pBigMFlowFrw'] = mTEPES.dPar['pLineNTCFrw']*0.0
|
|
1261
1307
|
for lea in mTEPES.lea:
|
|
1262
|
-
pBigMFlowBck.loc[lea] = pLineNTCBck[lea]
|
|
1263
|
-
pBigMFlowFrw.loc[lea] = pLineNTCFrw[lea]
|
|
1308
|
+
mTEPES.dPar['pBigMFlowBck'].loc[lea] = mTEPES.dPar['pLineNTCBck'][lea]
|
|
1309
|
+
mTEPES.dPar['pBigMFlowFrw'].loc[lea] = mTEPES.dPar['pLineNTCFrw'][lea]
|
|
1264
1310
|
for lca in mTEPES.lca:
|
|
1265
|
-
pBigMFlowBck.loc[lca] = pLineNTCBck[lca]*1.5
|
|
1266
|
-
pBigMFlowFrw.loc[lca] = pLineNTCFrw[lca]*1.5
|
|
1311
|
+
mTEPES.dPar['pBigMFlowBck'].loc[lca] = mTEPES.dPar['pLineNTCBck'][lca]*1.5
|
|
1312
|
+
mTEPES.dPar['pBigMFlowFrw'].loc[lca] = mTEPES.dPar['pLineNTCFrw'][lca]*1.5
|
|
1267
1313
|
for led in mTEPES.led:
|
|
1268
|
-
pBigMFlowBck.loc[led] = pLineNTCBck[led]
|
|
1269
|
-
pBigMFlowFrw.loc[led] = pLineNTCFrw[led]
|
|
1314
|
+
mTEPES.dPar['pBigMFlowBck'].loc[led] = mTEPES.dPar['pLineNTCBck'][led]
|
|
1315
|
+
mTEPES.dPar['pBigMFlowFrw'].loc[led] = mTEPES.dPar['pLineNTCFrw'][led]
|
|
1270
1316
|
for lcd in mTEPES.lcd:
|
|
1271
|
-
pBigMFlowBck.loc[lcd] = pLineNTCBck[lcd]*1.5
|
|
1272
|
-
pBigMFlowFrw.loc[lcd] = pLineNTCFrw[lcd]*1.5
|
|
1317
|
+
mTEPES.dPar['pBigMFlowBck'].loc[lcd] = mTEPES.dPar['pLineNTCBck'][lcd]*1.5
|
|
1318
|
+
mTEPES.dPar['pBigMFlowFrw'].loc[lcd] = mTEPES.dPar['pLineNTCFrw'][lcd]*1.5
|
|
1273
1319
|
|
|
1274
1320
|
# if BigM are 0.0 then converted to 1.0 to avoid division by 0.0
|
|
1275
|
-
pBigMFlowBck = pBigMFlowBck.where(pBigMFlowBck != 0.0, 1.0)
|
|
1276
|
-
pBigMFlowFrw = pBigMFlowFrw.where(pBigMFlowFrw != 0.0, 1.0)
|
|
1321
|
+
mTEPES.dPar['pBigMFlowBck'] = mTEPES.dPar['pBigMFlowBck'].where(mTEPES.dPar['pBigMFlowBck'] != 0.0, 1.0)
|
|
1322
|
+
mTEPES.dPar['pBigMFlowFrw'] = mTEPES.dPar['pBigMFlowFrw'].where(mTEPES.dPar['pBigMFlowFrw'] != 0.0, 1.0)
|
|
1277
1323
|
|
|
1278
1324
|
# maximum voltage angle
|
|
1279
|
-
pMaxTheta = pDemandElec*0.0 + math.pi/2
|
|
1280
|
-
pMaxTheta = pMaxTheta.loc[mTEPES.psn]
|
|
1325
|
+
mTEPES.dPar['pMaxTheta'] = mTEPES.dPar['pDemandElec']*0.0 + math.pi/2
|
|
1326
|
+
mTEPES.dPar['pMaxTheta'] = mTEPES.dPar['pMaxTheta'].loc[mTEPES.psn]
|
|
1281
1327
|
|
|
1282
1328
|
# this option avoids a warning in the following assignments
|
|
1283
1329
|
pd.options.mode.chained_assignment = None
|
|
@@ -1287,186 +1333,201 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
1287
1333
|
df = df[df.index.isin(set)]
|
|
1288
1334
|
return df
|
|
1289
1335
|
|
|
1290
|
-
pMinPowerElec = filter_rows(pMinPowerElec , mTEPES.psng )
|
|
1291
|
-
pMaxPowerElec = filter_rows(pMaxPowerElec , mTEPES.psng )
|
|
1292
|
-
pMinCharge = filter_rows(pMinCharge , mTEPES.psneh)
|
|
1293
|
-
pMaxCharge = filter_rows(pMaxCharge , mTEPES.psneh)
|
|
1294
|
-
pMaxCapacity = filter_rows(pMaxCapacity , mTEPES.psneh)
|
|
1295
|
-
pMaxPower2ndBlock = filter_rows(pMaxPower2ndBlock , mTEPES.psng )
|
|
1296
|
-
pMaxCharge2ndBlock = filter_rows(pMaxCharge2ndBlock, mTEPES.psneh)
|
|
1297
|
-
pEnergyInflows = filter_rows(pEnergyInflows , mTEPES.psnes)
|
|
1298
|
-
pEnergyOutflows = filter_rows(pEnergyOutflows , mTEPES.psnes)
|
|
1299
|
-
pMinStorage = filter_rows(pMinStorage , mTEPES.psnes)
|
|
1300
|
-
pMaxStorage = filter_rows(pMaxStorage , mTEPES.psnes)
|
|
1301
|
-
pVariableMaxEnergy = filter_rows(pVariableMaxEnergy, mTEPES.psng )
|
|
1302
|
-
pVariableMinEnergy = filter_rows(pVariableMinEnergy, mTEPES.psng )
|
|
1303
|
-
pLinearVarCost = filter_rows(pLinearVarCost , mTEPES.psng )
|
|
1304
|
-
pConstantVarCost = filter_rows(pConstantVarCost , mTEPES.psng )
|
|
1305
|
-
pEmissionVarCost = filter_rows(pEmissionVarCost , mTEPES.psng )
|
|
1306
|
-
pIniInventory = filter_rows(pIniInventory , mTEPES.psnes)
|
|
1307
|
-
|
|
1308
|
-
pDemandElec = filter_rows(pDemandElec , mTEPES.psnnd)
|
|
1309
|
-
|
|
1310
|
-
pSystemInertia = filter_rows(pSystemInertia , mTEPES.psnar)
|
|
1311
|
-
pOperReserveUp = filter_rows(pOperReserveUp , mTEPES.psnar)
|
|
1312
|
-
pOperReserveDw = filter_rows(pOperReserveDw , mTEPES.psnar)
|
|
1336
|
+
mTEPES.dPar['pMinPowerElec'] = filter_rows(mTEPES.dPar['pMinPowerElec'] , mTEPES.psng )
|
|
1337
|
+
mTEPES.dPar['pMaxPowerElec'] = filter_rows(mTEPES.dPar['pMaxPowerElec'] , mTEPES.psng )
|
|
1338
|
+
mTEPES.dPar['pMinCharge'] = filter_rows(mTEPES.dPar['pMinCharge'] , mTEPES.psneh)
|
|
1339
|
+
mTEPES.dPar['pMaxCharge'] = filter_rows(mTEPES.dPar['pMaxCharge'] , mTEPES.psneh)
|
|
1340
|
+
mTEPES.dPar['pMaxCapacity'] = filter_rows(mTEPES.dPar['pMaxCapacity'] , mTEPES.psneh)
|
|
1341
|
+
mTEPES.dPar['pMaxPower2ndBlock'] = filter_rows(mTEPES.dPar['pMaxPower2ndBlock'] , mTEPES.psng )
|
|
1342
|
+
mTEPES.dPar['pMaxCharge2ndBlock'] = filter_rows(mTEPES.dPar['pMaxCharge2ndBlock'], mTEPES.psneh)
|
|
1343
|
+
mTEPES.dPar['pEnergyInflows'] = filter_rows(mTEPES.dPar['pEnergyInflows'] , mTEPES.psnes)
|
|
1344
|
+
mTEPES.dPar['pEnergyOutflows'] = filter_rows(mTEPES.dPar['pEnergyOutflows'] , mTEPES.psnes)
|
|
1345
|
+
mTEPES.dPar['pMinStorage'] = filter_rows(mTEPES.dPar['pMinStorage'] , mTEPES.psnes)
|
|
1346
|
+
mTEPES.dPar['pMaxStorage'] = filter_rows(mTEPES.dPar['pMaxStorage'] , mTEPES.psnes)
|
|
1347
|
+
mTEPES.dPar['pVariableMaxEnergy'] = filter_rows(mTEPES.dPar['pVariableMaxEnergy'], mTEPES.psng )
|
|
1348
|
+
mTEPES.dPar['pVariableMinEnergy'] = filter_rows(mTEPES.dPar['pVariableMinEnergy'], mTEPES.psng )
|
|
1349
|
+
mTEPES.dPar['pLinearVarCost'] = filter_rows(mTEPES.dPar['pLinearVarCost'] , mTEPES.psng )
|
|
1350
|
+
mTEPES.dPar['pConstantVarCost'] = filter_rows(mTEPES.dPar['pConstantVarCost'] , mTEPES.psng )
|
|
1351
|
+
mTEPES.dPar['pEmissionVarCost'] = filter_rows(mTEPES.dPar['pEmissionVarCost'] , mTEPES.psng )
|
|
1352
|
+
mTEPES.dPar['pIniInventory'] = filter_rows(mTEPES.dPar['pIniInventory'] , mTEPES.psnes)
|
|
1353
|
+
|
|
1354
|
+
mTEPES.dPar['pDemandElec'] = filter_rows(mTEPES.dPar['pDemandElec'] , mTEPES.psnnd)
|
|
1355
|
+
mTEPES.dPar['pDemandElecPos'] = filter_rows(mTEPES.dPar['pDemandElecPos'] , mTEPES.psnnd)
|
|
1356
|
+
mTEPES.dPar['pSystemInertia'] = filter_rows(mTEPES.dPar['pSystemInertia'] , mTEPES.psnar)
|
|
1357
|
+
mTEPES.dPar['pOperReserveUp'] = filter_rows(mTEPES.dPar['pOperReserveUp'] , mTEPES.psnar)
|
|
1358
|
+
mTEPES.dPar['pOperReserveDw'] = filter_rows(mTEPES.dPar['pOperReserveDw'] , mTEPES.psnar)
|
|
1359
|
+
|
|
1360
|
+
mTEPES.dPar['pMaxNTCBck'] = filter_rows(mTEPES.dPar['pMaxNTCBck'] , mTEPES.psnla)
|
|
1361
|
+
mTEPES.dPar['pMaxNTCFrw'] = filter_rows(mTEPES.dPar['pMaxNTCFrw'] , mTEPES.psnla)
|
|
1362
|
+
mTEPES.dPar['pMaxNTCMax'] = filter_rows(mTEPES.dPar['pMaxNTCMax'] , mTEPES.psnla)
|
|
1363
|
+
|
|
1364
|
+
if mTEPES.dPar['pIndPTDF'] == 1:
|
|
1365
|
+
mTEPES.dPar['pPTDF'] = mTEPES.dPar['pVariablePTDF'].stack(level=list(range(mTEPES.dPar['pVariablePTDF'].columns.nlevels)), future_stack=True)
|
|
1366
|
+
mTEPES.dPar['pPTDF'].index.set_names(['Period', 'Scenario', 'LoadLevel', 'InitialNode', 'FinalNode', 'Circuit', 'Node'], inplace=True)
|
|
1367
|
+
# filter rows to keep the same as mTEPES.psnland
|
|
1368
|
+
mTEPES.dPar['pPTDF'] = mTEPES.dPar['pPTDF'][mTEPES.dPar['pPTDF'].index.isin(mTEPES.psnland)]
|
|
1313
1369
|
|
|
1314
1370
|
# %% parameters
|
|
1315
|
-
mTEPES.pIndBinGenInvest = Param(initialize=pIndBinGenInvest , within=NonNegativeIntegers, doc='Indicator of binary generation investment decisions', mutable=True)
|
|
1316
|
-
mTEPES.pIndBinGenRetire = Param(initialize=
|
|
1317
|
-
mTEPES.pIndBinRsrInvest = Param(initialize=pIndBinRsrInvest , within=NonNegativeIntegers, doc='Indicator of binary reservoir investment decisions', mutable=True)
|
|
1318
|
-
mTEPES.pIndBinNetElecInvest = Param(initialize=
|
|
1319
|
-
mTEPES.pIndBinNetH2Invest = Param(initialize=pIndBinNetH2Invest , within=NonNegativeIntegers, doc='Indicator of binary hydrogen network investment decisions', mutable=True)
|
|
1320
|
-
mTEPES.pIndBinNetHeatInvest = Param(initialize=pIndBinNetHeatInvest, within=NonNegativeIntegers, doc='Indicator of binary heat network investment decisions', mutable=True)
|
|
1321
|
-
mTEPES.pIndBinGenOperat = Param(initialize=pIndBinGenOperat , within=Binary, doc='Indicator of binary generation operation decisions', mutable=True)
|
|
1322
|
-
mTEPES.pIndBinSingleNode = Param(initialize=pIndBinSingleNode , within=Binary, doc='Indicator of single node within a electric network case', mutable=True)
|
|
1323
|
-
mTEPES.pIndBinGenRamps = Param(initialize=pIndBinGenRamps , within=Binary, doc='Indicator of using or not the ramp constraints', mutable=True)
|
|
1324
|
-
mTEPES.pIndBinGenMinTime = Param(initialize=pIndBinGenMinTime , within=Binary, doc='Indicator of using or not the min up/dw time constraints', mutable=True)
|
|
1325
|
-
mTEPES.pIndBinLineCommit = Param(initialize=pIndBinLineCommit , within=Binary, doc='Indicator of binary electric network switching decisions', mutable=True)
|
|
1326
|
-
mTEPES.pIndBinNetLosses = Param(initialize=pIndBinNetLosses , within=Binary, doc='Indicator of binary electric network ohmic losses', mutable=True)
|
|
1327
|
-
mTEPES.pIndHydroTopology = Param(initialize=pIndHydroTopology , within=Binary, doc='Indicator of reservoir and hydropower topology' )
|
|
1328
|
-
mTEPES.pIndHydrogen = Param(initialize=pIndHydrogen , within=Binary, doc='Indicator of hydrogen demand and pipeline network' )
|
|
1329
|
-
mTEPES.pIndHeat = Param(initialize=pIndHeat , within=Binary, doc='Indicator of heat demand and pipe network' )
|
|
1330
|
-
|
|
1331
|
-
mTEPES.
|
|
1332
|
-
|
|
1333
|
-
mTEPES.
|
|
1334
|
-
mTEPES.
|
|
1335
|
-
mTEPES.
|
|
1336
|
-
mTEPES.
|
|
1337
|
-
mTEPES.
|
|
1338
|
-
mTEPES.
|
|
1339
|
-
mTEPES.
|
|
1340
|
-
mTEPES.
|
|
1341
|
-
mTEPES.
|
|
1342
|
-
mTEPES.
|
|
1343
|
-
|
|
1344
|
-
mTEPES.
|
|
1345
|
-
|
|
1346
|
-
mTEPES.
|
|
1347
|
-
mTEPES.
|
|
1348
|
-
mTEPES.
|
|
1349
|
-
mTEPES.
|
|
1350
|
-
mTEPES.
|
|
1351
|
-
mTEPES.
|
|
1352
|
-
mTEPES.
|
|
1353
|
-
mTEPES.
|
|
1354
|
-
mTEPES.
|
|
1355
|
-
mTEPES.
|
|
1356
|
-
mTEPES.
|
|
1357
|
-
mTEPES.
|
|
1358
|
-
mTEPES.
|
|
1359
|
-
mTEPES.
|
|
1360
|
-
mTEPES.
|
|
1361
|
-
mTEPES.
|
|
1362
|
-
mTEPES.
|
|
1363
|
-
mTEPES.
|
|
1364
|
-
mTEPES.
|
|
1365
|
-
mTEPES.
|
|
1366
|
-
mTEPES.
|
|
1367
|
-
mTEPES.
|
|
1368
|
-
mTEPES.
|
|
1369
|
-
mTEPES.
|
|
1370
|
-
mTEPES.
|
|
1371
|
-
mTEPES.
|
|
1372
|
-
mTEPES.
|
|
1373
|
-
mTEPES.
|
|
1374
|
-
mTEPES.
|
|
1375
|
-
mTEPES.
|
|
1376
|
-
mTEPES.
|
|
1377
|
-
mTEPES.
|
|
1378
|
-
mTEPES.
|
|
1379
|
-
mTEPES.
|
|
1380
|
-
mTEPES.
|
|
1381
|
-
mTEPES.
|
|
1382
|
-
mTEPES.
|
|
1383
|
-
mTEPES.
|
|
1384
|
-
mTEPES.
|
|
1385
|
-
mTEPES.
|
|
1386
|
-
mTEPES.
|
|
1387
|
-
mTEPES.
|
|
1388
|
-
mTEPES.
|
|
1389
|
-
mTEPES.
|
|
1390
|
-
mTEPES.
|
|
1391
|
-
mTEPES.
|
|
1392
|
-
mTEPES.
|
|
1393
|
-
mTEPES.
|
|
1394
|
-
mTEPES.
|
|
1395
|
-
mTEPES.
|
|
1396
|
-
mTEPES.
|
|
1397
|
-
mTEPES.
|
|
1398
|
-
mTEPES.
|
|
1399
|
-
mTEPES.
|
|
1400
|
-
mTEPES.
|
|
1401
|
-
mTEPES.
|
|
1402
|
-
mTEPES.
|
|
1403
|
-
mTEPES.
|
|
1404
|
-
mTEPES.
|
|
1405
|
-
mTEPES.
|
|
1406
|
-
mTEPES.
|
|
1407
|
-
mTEPES.
|
|
1408
|
-
mTEPES.
|
|
1409
|
-
mTEPES.
|
|
1410
|
-
mTEPES.
|
|
1411
|
-
mTEPES.
|
|
1412
|
-
mTEPES.
|
|
1413
|
-
mTEPES.
|
|
1414
|
-
mTEPES.
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
if
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
mTEPES.
|
|
1424
|
-
mTEPES.
|
|
1425
|
-
|
|
1426
|
-
mTEPES.
|
|
1427
|
-
mTEPES.
|
|
1428
|
-
mTEPES.
|
|
1429
|
-
mTEPES.
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
mTEPES.
|
|
1441
|
-
mTEPES.
|
|
1442
|
-
mTEPES.
|
|
1443
|
-
mTEPES.
|
|
1444
|
-
|
|
1445
|
-
mTEPES.
|
|
1446
|
-
mTEPES.
|
|
1447
|
-
mTEPES.
|
|
1448
|
-
mTEPES.
|
|
1449
|
-
mTEPES.
|
|
1450
|
-
mTEPES.
|
|
1451
|
-
mTEPES.
|
|
1452
|
-
mTEPES.
|
|
1453
|
-
mTEPES.
|
|
1454
|
-
mTEPES.
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
mTEPES.
|
|
1371
|
+
mTEPES.pIndBinGenInvest = Param(initialize=mTEPES.dPar['pIndBinGenInvest'] , within=NonNegativeIntegers, doc='Indicator of binary generation investment decisions', mutable=True)
|
|
1372
|
+
mTEPES.pIndBinGenRetire = Param(initialize=mTEPES.dPar['pIndBinGenRetirement'], within=NonNegativeIntegers, doc='Indicator of binary generation retirement decisions', mutable=True)
|
|
1373
|
+
mTEPES.pIndBinRsrInvest = Param(initialize=mTEPES.dPar['pIndBinRsrInvest'] , within=NonNegativeIntegers, doc='Indicator of binary reservoir investment decisions', mutable=True)
|
|
1374
|
+
mTEPES.pIndBinNetElecInvest = Param(initialize=mTEPES.dPar['pIndBinNetInvest'] , within=NonNegativeIntegers, doc='Indicator of binary electric network investment decisions', mutable=True)
|
|
1375
|
+
mTEPES.pIndBinNetH2Invest = Param(initialize=mTEPES.dPar['pIndBinNetH2Invest'] , within=NonNegativeIntegers, doc='Indicator of binary hydrogen network investment decisions', mutable=True)
|
|
1376
|
+
mTEPES.pIndBinNetHeatInvest = Param(initialize=mTEPES.dPar['pIndBinNetHeatInvest'], within=NonNegativeIntegers, doc='Indicator of binary heat network investment decisions', mutable=True)
|
|
1377
|
+
mTEPES.pIndBinGenOperat = Param(initialize=mTEPES.dPar['pIndBinGenOperat'] , within=Binary, doc='Indicator of binary generation operation decisions', mutable=True)
|
|
1378
|
+
mTEPES.pIndBinSingleNode = Param(initialize=mTEPES.dPar['pIndBinSingleNode'] , within=Binary, doc='Indicator of single node within a electric network case', mutable=True)
|
|
1379
|
+
mTEPES.pIndBinGenRamps = Param(initialize=mTEPES.dPar['pIndBinGenRamps'] , within=Binary, doc='Indicator of using or not the ramp constraints', mutable=True)
|
|
1380
|
+
mTEPES.pIndBinGenMinTime = Param(initialize=mTEPES.dPar['pIndBinGenMinTime'] , within=Binary, doc='Indicator of using or not the min up/dw time constraints', mutable=True)
|
|
1381
|
+
mTEPES.pIndBinLineCommit = Param(initialize=mTEPES.dPar['pIndBinLineCommit'] , within=Binary, doc='Indicator of binary electric network switching decisions', mutable=True)
|
|
1382
|
+
mTEPES.pIndBinNetLosses = Param(initialize=mTEPES.dPar['pIndBinNetLosses'] , within=Binary, doc='Indicator of binary electric network ohmic losses', mutable=True)
|
|
1383
|
+
mTEPES.pIndHydroTopology = Param(initialize=mTEPES.dPar['pIndHydroTopology'] , within=Binary, doc='Indicator of reservoir and hydropower topology' )
|
|
1384
|
+
mTEPES.pIndHydrogen = Param(initialize=mTEPES.dPar['pIndHydrogen'] , within=Binary, doc='Indicator of hydrogen demand and pipeline network' )
|
|
1385
|
+
mTEPES.pIndHeat = Param(initialize=mTEPES.dPar['pIndHeat'] , within=Binary, doc='Indicator of heat demand and pipe network' )
|
|
1386
|
+
mTEPES.pIndVarTTC = Param(initialize=mTEPES.dPar['pIndVarTTC'] , within=Binary, doc='Indicator of using or not variable TTC' )
|
|
1387
|
+
mTEPES.pIndPTDF = Param(initialize=mTEPES.dPar['pIndPTDF'] , within=Binary, doc='Indicator of using or not the Flow-based method' )
|
|
1388
|
+
|
|
1389
|
+
mTEPES.pENSCost = Param(initialize=mTEPES.dPar['pENSCost'] , within=NonNegativeReals, doc='ENS cost' )
|
|
1390
|
+
mTEPES.pH2NSCost = Param(initialize=mTEPES.dPar['pHNSCost'] , within=NonNegativeReals, doc='HNS cost' )
|
|
1391
|
+
mTEPES.pHeatNSCost = Param(initialize=mTEPES.dPar['pHTNSCost'] , within=NonNegativeReals, doc='HTNS cost' )
|
|
1392
|
+
mTEPES.pCO2Cost = Param(initialize=mTEPES.dPar['pCO2Cost'] , within=NonNegativeReals, doc='CO2 emission cost' )
|
|
1393
|
+
mTEPES.pAnnualDiscRate = Param(initialize=mTEPES.dPar['pAnnualDiscountRate'] , within=UnitInterval, doc='Annual discount rate' )
|
|
1394
|
+
mTEPES.pUpReserveActivation = Param(initialize=mTEPES.dPar['pUpReserveActivation'], within=UnitInterval, doc='Proportion of upward reserve activation' )
|
|
1395
|
+
mTEPES.pDwReserveActivation = Param(initialize=mTEPES.dPar['pDwReserveActivation'], within=UnitInterval, doc='Proportion of downward reserve activation' )
|
|
1396
|
+
mTEPES.pMinRatioDwUp = Param(initialize=mTEPES.dPar['pMinRatioDwUp'] , within=UnitInterval, doc='Minimum ratio downward to upward operating reserves')
|
|
1397
|
+
mTEPES.pMaxRatioDwUp = Param(initialize=mTEPES.dPar['pMaxRatioDwUp'] , within=UnitInterval, doc='Maximum ratio downward to upward operating reserves')
|
|
1398
|
+
mTEPES.pSBase = Param(initialize=mTEPES.dPar['pSBase'] , within=PositiveReals, doc='Base power' )
|
|
1399
|
+
mTEPES.pTimeStep = Param(initialize=mTEPES.dPar['pTimeStep'] , within=PositiveIntegers, doc='Unitary time step' )
|
|
1400
|
+
mTEPES.pEconomicBaseYear = Param(initialize=mTEPES.dPar['pEconomicBaseYear'] , within=PositiveIntegers, doc='Base year' )
|
|
1401
|
+
|
|
1402
|
+
mTEPES.pReserveMargin = Param(mTEPES.par, initialize=mTEPES.dPar['pReserveMargin'].to_dict() , within=NonNegativeReals, doc='Adequacy reserve margin' )
|
|
1403
|
+
mTEPES.pEmission = Param(mTEPES.par, initialize=mTEPES.dPar['pEmission'].to_dict() , within=NonNegativeReals, doc='Maximum CO2 emission' )
|
|
1404
|
+
mTEPES.pRESEnergy = Param(mTEPES.par, initialize=mTEPES.dPar['pRESEnergy'].to_dict() , within=NonNegativeReals, doc='Minimum RES energy' )
|
|
1405
|
+
mTEPES.pDemandElecPeak = Param(mTEPES.par, initialize=mTEPES.dPar['pDemandElecPeak'].to_dict() , within=NonNegativeReals, doc='Peak electric demand' )
|
|
1406
|
+
mTEPES.pDemandElec = Param(mTEPES.psnnd, initialize=mTEPES.dPar['pDemandElec'].to_dict() , within= Reals, doc='Electric demand' )
|
|
1407
|
+
mTEPES.pDemandElecPos = Param(mTEPES.psnnd, initialize=mTEPES.dPar['pDemandElecPos'].to_dict() , within=NonNegativeReals, doc='Electric demand positive' )
|
|
1408
|
+
mTEPES.pPeriodWeight = Param(mTEPES.p, initialize=mTEPES.dPar['pPeriodWeight'].to_dict() , within=NonNegativeReals, doc='Period weight', mutable=True)
|
|
1409
|
+
mTEPES.pDiscountedWeight = Param(mTEPES.p, initialize=mTEPES.dPar['pDiscountedWeight'].to_dict() , within=NonNegativeReals, doc='Discount factor' )
|
|
1410
|
+
mTEPES.pScenProb = Param(mTEPES.psc, initialize=mTEPES.dPar['pScenProb'].to_dict() , within=UnitInterval , doc='Probability', mutable=True)
|
|
1411
|
+
mTEPES.pStageWeight = Param(mTEPES.stt, initialize=mTEPES.dPar['pStageWeight'].to_dict() , within=NonNegativeReals, doc='Stage weight' )
|
|
1412
|
+
mTEPES.pDuration = Param(mTEPES.psn, initialize=mTEPES.dPar['pDuration'].to_dict() , within=NonNegativeIntegers, doc='Duration', mutable=True)
|
|
1413
|
+
mTEPES.pNodeLon = Param(mTEPES.nd, initialize=mTEPES.dPar['pNodeLon'].to_dict() , doc='Longitude' )
|
|
1414
|
+
mTEPES.pNodeLat = Param(mTEPES.nd, initialize=mTEPES.dPar['pNodeLat'].to_dict() , doc='Latitude' )
|
|
1415
|
+
mTEPES.pSystemInertia = Param(mTEPES.psnar, initialize=mTEPES.dPar['pSystemInertia'].to_dict() , within=NonNegativeReals, doc='System inertia' )
|
|
1416
|
+
mTEPES.pOperReserveUp = Param(mTEPES.psnar, initialize=mTEPES.dPar['pOperReserveUp'].to_dict() , within=NonNegativeReals, doc='Upward operating reserve' )
|
|
1417
|
+
mTEPES.pOperReserveDw = Param(mTEPES.psnar, initialize=mTEPES.dPar['pOperReserveDw'].to_dict() , within=NonNegativeReals, doc='Downward operating reserve' )
|
|
1418
|
+
mTEPES.pMinPowerElec = Param(mTEPES.psng , initialize=mTEPES.dPar['pMinPowerElec'].to_dict() , within=NonNegativeReals, doc='Minimum electric power' )
|
|
1419
|
+
mTEPES.pMaxPowerElec = Param(mTEPES.psng , initialize=mTEPES.dPar['pMaxPowerElec'].to_dict() , within=NonNegativeReals, doc='Maximum electric power' )
|
|
1420
|
+
mTEPES.pMinCharge = Param(mTEPES.psneh, initialize=mTEPES.dPar['pMinCharge'].to_dict() , within=NonNegativeReals, doc='Minimum charge' )
|
|
1421
|
+
mTEPES.pMaxCharge = Param(mTEPES.psneh, initialize=mTEPES.dPar['pMaxCharge'].to_dict() , within=NonNegativeReals, doc='Maximum charge' )
|
|
1422
|
+
mTEPES.pMaxCapacity = Param(mTEPES.psneh, initialize=mTEPES.dPar['pMaxCapacity'].to_dict() , within=NonNegativeReals, doc='Maximum capacity' )
|
|
1423
|
+
mTEPES.pMaxPower2ndBlock = Param(mTEPES.psng , initialize=mTEPES.dPar['pMaxPower2ndBlock'].to_dict() , within=NonNegativeReals, doc='Second block power' )
|
|
1424
|
+
mTEPES.pMaxCharge2ndBlock = Param(mTEPES.psneh, initialize=mTEPES.dPar['pMaxCharge2ndBlock'].to_dict() , within=NonNegativeReals, doc='Second block charge' )
|
|
1425
|
+
mTEPES.pEnergyInflows = Param(mTEPES.psnes, initialize=mTEPES.dPar['pEnergyInflows'].to_dict() , within=NonNegativeReals, doc='Energy inflows', mutable=True)
|
|
1426
|
+
mTEPES.pEnergyOutflows = Param(mTEPES.psnes, initialize=mTEPES.dPar['pEnergyOutflows'].to_dict() , within=NonNegativeReals, doc='Energy outflows', mutable=True)
|
|
1427
|
+
mTEPES.pMinStorage = Param(mTEPES.psnes, initialize=mTEPES.dPar['pMinStorage'].to_dict() , within=NonNegativeReals, doc='ESS Minimum storage capacity' )
|
|
1428
|
+
mTEPES.pMaxStorage = Param(mTEPES.psnes, initialize=mTEPES.dPar['pMaxStorage'].to_dict() , within=NonNegativeReals, doc='ESS Maximum storage capacity' )
|
|
1429
|
+
mTEPES.pMinEnergy = Param(mTEPES.psng , initialize=mTEPES.dPar['pVariableMinEnergy'].to_dict() , within=NonNegativeReals, doc='Unit minimum energy demand' )
|
|
1430
|
+
mTEPES.pMaxEnergy = Param(mTEPES.psng , initialize=mTEPES.dPar['pVariableMaxEnergy'].to_dict() , within=NonNegativeReals, doc='Unit maximum energy demand' )
|
|
1431
|
+
mTEPES.pRatedMaxPowerElec = Param(mTEPES.gg, initialize=mTEPES.dPar['pRatedMaxPowerElec'].to_dict() , within=NonNegativeReals, doc='Rated maximum power' )
|
|
1432
|
+
mTEPES.pRatedMaxCharge = Param(mTEPES.gg, initialize=mTEPES.dPar['pRatedMaxCharge'].to_dict() , within=NonNegativeReals, doc='Rated maximum charge' )
|
|
1433
|
+
mTEPES.pMustRun = Param(mTEPES.gg, initialize=mTEPES.dPar['pMustRun'].to_dict() , within=Binary , doc='must-run unit' )
|
|
1434
|
+
mTEPES.pInertia = Param(mTEPES.gg, initialize=mTEPES.dPar['pInertia'].to_dict() , within=NonNegativeReals, doc='unit inertia constant' )
|
|
1435
|
+
mTEPES.pElecGenPeriodIni = Param(mTEPES.gg, initialize=mTEPES.dPar['pElecGenPeriodIni'].to_dict() , within=PositiveIntegers, doc='installation year', )
|
|
1436
|
+
mTEPES.pElecGenPeriodFin = Param(mTEPES.gg, initialize=mTEPES.dPar['pElecGenPeriodFin'].to_dict() , within=PositiveIntegers, doc='retirement year', )
|
|
1437
|
+
mTEPES.pAvailability = Param(mTEPES.gg, initialize=mTEPES.dPar['pAvailability'].to_dict() , within=UnitInterval , doc='unit availability', mutable=True)
|
|
1438
|
+
mTEPES.pEFOR = Param(mTEPES.gg, initialize=mTEPES.dPar['pEFOR'].to_dict() , within=UnitInterval , doc='EFOR' )
|
|
1439
|
+
mTEPES.pRatedLinearVarCost = Param(mTEPES.gg, initialize=mTEPES.dPar['pRatedLinearVarCost'].to_dict() , within=NonNegativeReals, doc='Linear variable cost' )
|
|
1440
|
+
mTEPES.pRatedConstantVarCost = Param(mTEPES.gg, initialize=mTEPES.dPar['pRatedConstantVarCost'].to_dict() , within=NonNegativeReals, doc='Constant variable cost' )
|
|
1441
|
+
mTEPES.pLinearVarCost = Param(mTEPES.psng , initialize=mTEPES.dPar['pLinearVarCost'].to_dict() , within=NonNegativeReals, doc='Linear variable cost' )
|
|
1442
|
+
mTEPES.pConstantVarCost = Param(mTEPES.psng , initialize=mTEPES.dPar['pConstantVarCost'].to_dict() , within=NonNegativeReals, doc='Constant variable cost' )
|
|
1443
|
+
mTEPES.pLinearOMCost = Param(mTEPES.gg, initialize=mTEPES.dPar['pLinearOMCost'].to_dict() , within=NonNegativeReals, doc='Linear O&M cost' )
|
|
1444
|
+
mTEPES.pOperReserveCost = Param(mTEPES.gg, initialize=mTEPES.dPar['pOperReserveCost'].to_dict() , within=NonNegativeReals, doc='Operating reserve cost' )
|
|
1445
|
+
mTEPES.pEmissionVarCost = Param(mTEPES.psng , initialize=mTEPES.dPar['pEmissionVarCost'].to_dict() , within=Reals , doc='CO2 Emission cost' )
|
|
1446
|
+
mTEPES.pEmissionRate = Param(mTEPES.gg, initialize=mTEPES.dPar['pEmissionRate'].to_dict() , within=Reals , doc='CO2 Emission rate' )
|
|
1447
|
+
mTEPES.pStartUpCost = Param(mTEPES.nr, initialize=mTEPES.dPar['pStartUpCost'].to_dict() , within=NonNegativeReals, doc='Startup cost' )
|
|
1448
|
+
mTEPES.pShutDownCost = Param(mTEPES.nr, initialize=mTEPES.dPar['pShutDownCost'].to_dict() , within=NonNegativeReals, doc='Shutdown cost' )
|
|
1449
|
+
mTEPES.pRampUp = Param(mTEPES.gg, initialize=mTEPES.dPar['pRampUp'].to_dict() , within=NonNegativeReals, doc='Ramp up rate' )
|
|
1450
|
+
mTEPES.pRampDw = Param(mTEPES.gg, initialize=mTEPES.dPar['pRampDw'].to_dict() , within=NonNegativeReals, doc='Ramp down rate' )
|
|
1451
|
+
mTEPES.pUpTime = Param(mTEPES.gg, initialize=mTEPES.dPar['pUpTime'].to_dict() , within=NonNegativeIntegers, doc='Up time' )
|
|
1452
|
+
mTEPES.pDwTime = Param(mTEPES.gg, initialize=mTEPES.dPar['pDwTime'].to_dict() , within=NonNegativeIntegers, doc='Down time' )
|
|
1453
|
+
mTEPES.pStableTime = Param(mTEPES.gg, initialize=mTEPES.dPar['pStableTime'].to_dict() , within=NonNegativeIntegers, doc='Stable time' )
|
|
1454
|
+
mTEPES.pShiftTime = Param(mTEPES.gg, initialize=mTEPES.dPar['pShiftTime'].to_dict() , within=NonNegativeIntegers, doc='Shift time' )
|
|
1455
|
+
mTEPES.pGenInvestCost = Param(mTEPES.eb, initialize=mTEPES.dPar['pGenInvestCost'].to_dict() , within=NonNegativeReals, doc='Generation fixed cost' )
|
|
1456
|
+
mTEPES.pGenRetireCost = Param(mTEPES.gd, initialize=mTEPES.dPar['pGenRetireCost'].to_dict() , within=Reals , doc='Generation fixed retire cost' )
|
|
1457
|
+
mTEPES.pIndBinUnitInvest = Param(mTEPES.eb, initialize=mTEPES.dPar['pIndBinUnitInvest'].to_dict() , within=Binary , doc='Binary investment decision' )
|
|
1458
|
+
mTEPES.pIndBinUnitRetire = Param(mTEPES.gd, initialize=mTEPES.dPar['pIndBinUnitRetire'].to_dict() , within=Binary , doc='Binary retirement decision' )
|
|
1459
|
+
mTEPES.pIndBinUnitCommit = Param(mTEPES.nr, initialize=mTEPES.dPar['pIndBinUnitCommit'].to_dict() , within=Binary , doc='Binary commitment decision' )
|
|
1460
|
+
mTEPES.pIndBinStorInvest = Param(mTEPES.ec, initialize=mTEPES.dPar['pIndBinStorInvest'].to_dict() , within=Binary , doc='Storage linked to generation investment' )
|
|
1461
|
+
mTEPES.pIndOperReserveGen = Param(mTEPES.gg, initialize=mTEPES.dPar['pIndOperReserveGen'].to_dict() , within=Binary , doc='Indicator of operating reserve when generating power')
|
|
1462
|
+
mTEPES.pIndOperReserveCon = Param(mTEPES.gg, initialize=mTEPES.dPar['pIndOperReserveCon'].to_dict() , within=Binary , doc='Indicator of operating reserve when consuming power' )
|
|
1463
|
+
mTEPES.pIndOutflowIncomp = Param(mTEPES.gg, initialize=mTEPES.dPar['pIndOutflowIncomp'].to_dict() , within=Binary , doc='Indicator of outflow incompatibility with charging' )
|
|
1464
|
+
mTEPES.pEfficiency = Param(mTEPES.eh, initialize=mTEPES.dPar['pEfficiency'].to_dict() , within=UnitInterval , doc='Round-trip efficiency' )
|
|
1465
|
+
mTEPES.pStorageTimeStep = Param(mTEPES.es, initialize=mTEPES.dPar['pStorageTimeStep'].to_dict() , within=PositiveIntegers, doc='ESS Storage cycle' )
|
|
1466
|
+
mTEPES.pOutflowsTimeStep = Param(mTEPES.es, initialize=mTEPES.dPar['pOutflowsTimeStep'].to_dict() , within=PositiveIntegers, doc='ESS Outflows cycle' )
|
|
1467
|
+
mTEPES.pEnergyTimeStep = Param(mTEPES.gg, initialize=mTEPES.dPar['pEnergyTimeStep'].to_dict() , within=PositiveIntegers, doc='Unit energy cycle' )
|
|
1468
|
+
mTEPES.pIniInventory = Param(mTEPES.psnes, initialize=mTEPES.dPar['pIniInventory'].to_dict() , within=NonNegativeReals, doc='ESS Initial storage', mutable=True)
|
|
1469
|
+
mTEPES.pStorageType = Param(mTEPES.es, initialize=mTEPES.dPar['pStorageType'].to_dict() , within=Any , doc='ESS Storage type' )
|
|
1470
|
+
mTEPES.pGenLoInvest = Param(mTEPES.eb, initialize=mTEPES.dPar['pGenLoInvest'].to_dict() , within=NonNegativeReals, doc='Lower bound of the investment decision', mutable=True)
|
|
1471
|
+
mTEPES.pGenUpInvest = Param(mTEPES.eb, initialize=mTEPES.dPar['pGenUpInvest'].to_dict() , within=NonNegativeReals, doc='Upper bound of the investment decision', mutable=True)
|
|
1472
|
+
mTEPES.pGenLoRetire = Param(mTEPES.gd, initialize=mTEPES.dPar['pGenLoRetire'].to_dict() , within=NonNegativeReals, doc='Lower bound of the retirement decision', mutable=True)
|
|
1473
|
+
mTEPES.pGenUpRetire = Param(mTEPES.gd, initialize=mTEPES.dPar['pGenUpRetire'].to_dict() , within=NonNegativeReals, doc='Upper bound of the retirement decision', mutable=True)
|
|
1474
|
+
|
|
1475
|
+
if mTEPES.dPar['pIndHydrogen'] == 1:
|
|
1476
|
+
mTEPES.pProductionFunctionH2 = Param(mTEPES.el, initialize=mTEPES.dPar['pProductionFunctionH2'].to_dict(), within=NonNegativeReals, doc='Production function of an electrolyzer plant')
|
|
1477
|
+
|
|
1478
|
+
if mTEPES.dPar['pIndHeat'] == 1:
|
|
1479
|
+
mTEPES.dPar['pMinPowerHeat'] = filter_rows(mTEPES.dPar['pMinPowerHeat'], mTEPES.psnch)
|
|
1480
|
+
mTEPES.dPar['pMaxPowerHeat'] = filter_rows(mTEPES.dPar['pMaxPowerHeat'], mTEPES.psnch)
|
|
1481
|
+
|
|
1482
|
+
mTEPES.pReserveMarginHeat = Param(mTEPES.par, initialize=mTEPES.dPar['pReserveMarginHeat'].to_dict() , within=NonNegativeReals, doc='Adequacy reserve margin' )
|
|
1483
|
+
mTEPES.pRatedMaxPowerHeat = Param(mTEPES.gg, initialize=mTEPES.dPar['pRatedMaxPowerHeat'].to_dict() , within=NonNegativeReals, doc='Rated maximum heat' )
|
|
1484
|
+
mTEPES.pMinPowerHeat = Param(mTEPES.psnch, initialize=mTEPES.dPar['pMinPowerHeat'].to_dict() , within=NonNegativeReals, doc='Minimum heat power' )
|
|
1485
|
+
mTEPES.pMaxPowerHeat = Param(mTEPES.psnch, initialize=mTEPES.dPar['pMaxPowerHeat'].to_dict() , within=NonNegativeReals, doc='Maximum heat power' )
|
|
1486
|
+
mTEPES.pPower2HeatRatio = Param(mTEPES.ch, initialize=mTEPES.dPar['pPower2HeatRatio'].to_dict() , within=NonNegativeReals, doc='Power to heat ratio' )
|
|
1487
|
+
mTEPES.pProductionFunctionHeat = Param(mTEPES.hp, initialize=mTEPES.dPar['pProductionFunctionHeat'].to_dict() , within=NonNegativeReals, doc='Production function of an CHP plant' )
|
|
1488
|
+
mTEPES.pProductionFunctionH2ToHeat = Param(mTEPES.hh, initialize=mTEPES.dPar['pProductionFunctionH2ToHeat'].to_dict(), within=NonNegativeReals, doc='Production function of an boiler using H2')
|
|
1489
|
+
|
|
1490
|
+
if mTEPES.dPar['pIndPTDF'] == 1:
|
|
1491
|
+
mTEPES.pPTDF = Param(mTEPES.psnland, initialize=mTEPES.dPar['pPTDF'].to_dict() , within=Reals , doc='Power transfer distribution factor' )
|
|
1492
|
+
|
|
1493
|
+
if mTEPES.dPar['pIndHydroTopology'] == 1:
|
|
1494
|
+
mTEPES.dPar['pHydroInflows'] = filter_rows(mTEPES.dPar['pHydroInflows'] , mTEPES.psnrs)
|
|
1495
|
+
mTEPES.dPar['pHydroOutflows'] = filter_rows(mTEPES.dPar['pHydroOutflows'], mTEPES.psnrs)
|
|
1496
|
+
mTEPES.dPar['pMaxOutflows'] = filter_rows(mTEPES.dPar['pMaxOutflows'] , mTEPES.psnrs)
|
|
1497
|
+
mTEPES.dPar['pMinVolume'] = filter_rows(mTEPES.dPar['pMinVolume'] , mTEPES.psnrs)
|
|
1498
|
+
mTEPES.dPar['pMaxVolume'] = filter_rows(mTEPES.dPar['pMaxVolume'] , mTEPES.psnrs)
|
|
1499
|
+
mTEPES.dPar['pIniVolume'] = filter_rows(mTEPES.dPar['pIniVolume'] , mTEPES.psnrs)
|
|
1500
|
+
|
|
1501
|
+
mTEPES.pProductionFunctionHydro = Param(mTEPES.h , initialize=mTEPES.dPar['pProductionFunctionHydro'].to_dict(), within=NonNegativeReals, doc='Production function of a hydro power plant' )
|
|
1502
|
+
mTEPES.pHydroInflows = Param(mTEPES.psnrs, initialize=mTEPES.dPar['pHydroInflows'].to_dict() , within=NonNegativeReals, doc='Hydro inflows', mutable=True)
|
|
1503
|
+
mTEPES.pHydroOutflows = Param(mTEPES.psnrs, initialize=mTEPES.dPar['pHydroOutflows'].to_dict() , within=NonNegativeReals, doc='Hydro outflows', mutable=True)
|
|
1504
|
+
mTEPES.pMaxOutflows = Param(mTEPES.psnrs, initialize=mTEPES.dPar['pMaxOutflows'].to_dict() , within=NonNegativeReals, doc='Maximum hydro outflows', )
|
|
1505
|
+
mTEPES.pMinVolume = Param(mTEPES.psnrs, initialize=mTEPES.dPar['pMinVolume'].to_dict() , within=NonNegativeReals, doc='Minimum reservoir volume capacity' )
|
|
1506
|
+
mTEPES.pMaxVolume = Param(mTEPES.psnrs, initialize=mTEPES.dPar['pMaxVolume'].to_dict() , within=NonNegativeReals, doc='Maximum reservoir volume capacity' )
|
|
1507
|
+
mTEPES.pIndBinRsrvInvest = Param(mTEPES.rn, initialize=mTEPES.dPar['pIndBinRsrvInvest'].to_dict() , within=Binary , doc='Binary reservoir investment decision' )
|
|
1508
|
+
mTEPES.pRsrInvestCost = Param(mTEPES.rn, initialize=mTEPES.dPar['pRsrInvestCost'].to_dict() , within=NonNegativeReals, doc='Reservoir fixed cost' )
|
|
1509
|
+
mTEPES.pRsrPeriodIni = Param(mTEPES.rs, initialize=mTEPES.dPar['pRsrPeriodIni'].to_dict() , within=PositiveIntegers, doc='Installation year', )
|
|
1510
|
+
mTEPES.pRsrPeriodFin = Param(mTEPES.rs, initialize=mTEPES.dPar['pRsrPeriodFin'].to_dict() , within=PositiveIntegers, doc='Retirement year', )
|
|
1511
|
+
mTEPES.pReservoirTimeStep = Param(mTEPES.rs, initialize=mTEPES.dPar['pReservoirTimeStep'].to_dict() , within=PositiveIntegers, doc='Reservoir volume cycle' )
|
|
1512
|
+
mTEPES.pWaterOutTimeStep = Param(mTEPES.rs, initialize=mTEPES.dPar['pWaterOutTimeStep'].to_dict() , within=PositiveIntegers, doc='Reservoir outflows cycle' )
|
|
1513
|
+
mTEPES.pIniVolume = Param(mTEPES.psnrs, initialize=mTEPES.dPar['pIniVolume'].to_dict() , within=NonNegativeReals, doc='Reservoir initial volume', mutable=True)
|
|
1514
|
+
mTEPES.pInitialVolume = Param(mTEPES.rs, initialize=mTEPES.dPar['pInitialVolume'].to_dict() , within=NonNegativeReals, doc='Reservoir initial volume without load levels')
|
|
1515
|
+
mTEPES.pReservoirType = Param(mTEPES.rs, initialize=mTEPES.dPar['pReservoirType'].to_dict() , within=Any , doc='Reservoir volume type' )
|
|
1516
|
+
|
|
1517
|
+
if mTEPES.dPar['pIndHydrogen'] == 1:
|
|
1518
|
+
mTEPES.dPar['pDemandH2'] = filter_rows(mTEPES.dPar['pDemandH2'] ,mTEPES.psnnd)
|
|
1519
|
+
mTEPES.dPar['pDemandH2Abs'] = filter_rows(mTEPES.dPar['pDemandH2Abs'],mTEPES.psnnd)
|
|
1520
|
+
|
|
1521
|
+
mTEPES.pDemandH2 = Param(mTEPES.psnnd, initialize=mTEPES.dPar['pDemandH2'].to_dict() , within=NonNegativeReals, doc='Hydrogen demand per hour')
|
|
1522
|
+
mTEPES.pDemandH2Abs = Param(mTEPES.psnnd, initialize=mTEPES.dPar['pDemandH2Abs'].to_dict(), within=NonNegativeReals, doc='Hydrogen demand' )
|
|
1523
|
+
|
|
1524
|
+
if mTEPES.dPar['pIndHeat'] == 1:
|
|
1525
|
+
mTEPES.dPar['pDemandHeat'] = filter_rows(mTEPES.dPar['pDemandHeat'] , mTEPES.psnnd)
|
|
1526
|
+
mTEPES.dPar['pDemandHeatAbs'] = filter_rows(mTEPES.dPar['pDemandHeatAbs'] , mTEPES.psnnd)
|
|
1527
|
+
|
|
1528
|
+
mTEPES.pDemandHeatPeak = Param(mTEPES.par, initialize=mTEPES.dPar['pDemandHeatPeak'].to_dict(), within=NonNegativeReals, doc='Peak heat demand' )
|
|
1529
|
+
mTEPES.pDemandHeat = Param(mTEPES.psnnd, initialize=mTEPES.dPar['pDemandHeat'].to_dict() , within=NonNegativeReals, doc='Heat demand per hour' )
|
|
1530
|
+
mTEPES.pDemandHeatAbs = Param(mTEPES.psnnd, initialize=mTEPES.dPar['pDemandHeatAbs'].to_dict(), within=NonNegativeReals, doc='Heat demand' )
|
|
1470
1531
|
|
|
1471
1532
|
mTEPES.pLoadLevelDuration = Param(mTEPES.psn, initialize=0 , within=NonNegativeIntegers, doc='Load level duration', mutable=True)
|
|
1472
1533
|
for p,sc,n in mTEPES.psn:
|
|
@@ -1477,61 +1538,65 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
1477
1538
|
# periods and scenarios are going to be solved together with their weight and probability
|
|
1478
1539
|
mTEPES.pPeriodProb[p,sc] = mTEPES.pPeriodWeight[p] * mTEPES.pScenProb[p,sc]
|
|
1479
1540
|
|
|
1480
|
-
pMaxTheta = filter_rows(pMaxTheta, mTEPES.psnnd)
|
|
1481
|
-
|
|
1482
|
-
mTEPES.pLineLossFactor = Param(mTEPES.ll, initialize=pLineLossFactor.to_dict() , within= Reals, doc='Loss factor' )
|
|
1483
|
-
mTEPES.pLineR = Param(mTEPES.la, initialize=pLineR.to_dict() , within=NonNegativeReals, doc='Resistance' )
|
|
1484
|
-
mTEPES.pLineX = Param(mTEPES.la, initialize=pLineX.to_dict() , within= Reals, doc='Reactance' )
|
|
1485
|
-
mTEPES.pLineBsh = Param(mTEPES.la, initialize=pLineBsh.to_dict() , within=NonNegativeReals, doc='Susceptance', mutable=True)
|
|
1486
|
-
mTEPES.pLineTAP = Param(mTEPES.la, initialize=pLineTAP.to_dict() , within=NonNegativeReals, doc='Tap changer', mutable=True)
|
|
1487
|
-
mTEPES.pLineLength = Param(mTEPES.la, initialize=pLineLength.to_dict() , within=NonNegativeReals, doc='Length', mutable=True)
|
|
1488
|
-
mTEPES.pElecNetPeriodIni = Param(mTEPES.la, initialize=pElecNetPeriodIni.to_dict(), within=PositiveIntegers, doc='Installation period' )
|
|
1489
|
-
mTEPES.pElecNetPeriodFin = Param(mTEPES.la, initialize=pElecNetPeriodFin.to_dict(), within=PositiveIntegers, doc='Retirement period' )
|
|
1490
|
-
mTEPES.pLineVoltage = Param(mTEPES.la, initialize=pLineVoltage.to_dict() , within=NonNegativeReals, doc='Voltage' )
|
|
1491
|
-
mTEPES.pLineNTCFrw = Param(mTEPES.la, initialize=pLineNTCFrw.to_dict() , within=NonNegativeReals, doc='Electric line NTC forward' )
|
|
1492
|
-
mTEPES.pLineNTCBck = Param(mTEPES.la, initialize=pLineNTCBck.to_dict() , within=NonNegativeReals, doc='Electric line NTC backward' )
|
|
1493
|
-
mTEPES.pLineNTCMax = Param(mTEPES.la, initialize=pLineNTCMax.to_dict() , within=NonNegativeReals, doc='Electric line NTC' )
|
|
1494
|
-
mTEPES.pNetFixedCost = Param(mTEPES.lc, initialize=pNetFixedCost.to_dict() , within=NonNegativeReals, doc='Electric line fixed cost' )
|
|
1495
|
-
mTEPES.pIndBinLineInvest = Param(mTEPES.la, initialize=pIndBinLineInvest.to_dict(), within=Binary , doc='Binary electric line investment decision' )
|
|
1496
|
-
mTEPES.pIndBinLineSwitch = Param(mTEPES.la, initialize=pIndBinLineSwitch.to_dict(), within=Binary , doc='Binary electric line switching decision' )
|
|
1497
|
-
# mTEPES.pSwOnTime = Param(mTEPES.la, initialize=pSwitchOnTime.to_dict() , within=NonNegativeIntegers, doc='Minimum switching on time' )
|
|
1498
|
-
# mTEPES.pSwOffTime = Param(mTEPES.la, initialize=pSwitchOffTime.to_dict() , within=NonNegativeIntegers, doc='Minimum switching off time' )
|
|
1499
|
-
mTEPES.pBigMFlowBck = Param(mTEPES.la, initialize=pBigMFlowBck.to_dict() , within=NonNegativeReals, doc='Maximum backward capacity', mutable=True)
|
|
1500
|
-
mTEPES.pBigMFlowFrw = Param(mTEPES.la, initialize=pBigMFlowFrw.to_dict() , within=NonNegativeReals, doc='Maximum forward capacity', mutable=True)
|
|
1501
|
-
mTEPES.pMaxTheta = Param(mTEPES.psnnd, initialize=pMaxTheta.to_dict() , within=NonNegativeReals, doc='Maximum voltage angle', mutable=True)
|
|
1502
|
-
mTEPES.pAngMin = Param(mTEPES.la, initialize=pAngMin.to_dict() , within= Reals, doc='Minimum phase angle difference', mutable=True)
|
|
1503
|
-
mTEPES.pAngMax = Param(mTEPES.la, initialize=pAngMax.to_dict() , within= Reals, doc='Maximum phase angle difference', mutable=True)
|
|
1504
|
-
mTEPES.pNetLoInvest = Param(mTEPES.lc, initialize=pNetLoInvest.to_dict() , within=NonNegativeReals, doc='Lower bound of the electric line investment decision', mutable=True)
|
|
1505
|
-
mTEPES.pNetUpInvest = Param(mTEPES.lc, initialize=pNetUpInvest.to_dict() , within=NonNegativeReals, doc='Upper bound of the electric line investment decision', mutable=True)
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
mTEPES.
|
|
1513
|
-
mTEPES.
|
|
1514
|
-
mTEPES.
|
|
1515
|
-
mTEPES.
|
|
1516
|
-
mTEPES.
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
mTEPES.
|
|
1520
|
-
mTEPES.
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
mTEPES.
|
|
1524
|
-
mTEPES.
|
|
1525
|
-
mTEPES.
|
|
1526
|
-
mTEPES.
|
|
1527
|
-
mTEPES.
|
|
1541
|
+
mTEPES.dPar['pMaxTheta'] = filter_rows(mTEPES.dPar['pMaxTheta'], mTEPES.psnnd)
|
|
1542
|
+
|
|
1543
|
+
mTEPES.pLineLossFactor = Param(mTEPES.ll, initialize=mTEPES.dPar['pLineLossFactor'].to_dict() , within= Reals, doc='Loss factor' )
|
|
1544
|
+
mTEPES.pLineR = Param(mTEPES.la, initialize=mTEPES.dPar['pLineR'].to_dict() , within=NonNegativeReals, doc='Resistance' )
|
|
1545
|
+
mTEPES.pLineX = Param(mTEPES.la, initialize=mTEPES.dPar['pLineX'].to_dict() , within= Reals, doc='Reactance' )
|
|
1546
|
+
mTEPES.pLineBsh = Param(mTEPES.la, initialize=mTEPES.dPar['pLineBsh'].to_dict() , within=NonNegativeReals, doc='Susceptance', mutable=True)
|
|
1547
|
+
mTEPES.pLineTAP = Param(mTEPES.la, initialize=mTEPES.dPar['pLineTAP'].to_dict() , within=NonNegativeReals, doc='Tap changer', mutable=True)
|
|
1548
|
+
mTEPES.pLineLength = Param(mTEPES.la, initialize=mTEPES.dPar['pLineLength'].to_dict() , within=NonNegativeReals, doc='Length', mutable=True)
|
|
1549
|
+
mTEPES.pElecNetPeriodIni = Param(mTEPES.la, initialize=mTEPES.dPar['pElecNetPeriodIni'].to_dict(), within=PositiveIntegers, doc='Installation period' )
|
|
1550
|
+
mTEPES.pElecNetPeriodFin = Param(mTEPES.la, initialize=mTEPES.dPar['pElecNetPeriodFin'].to_dict(), within=PositiveIntegers, doc='Retirement period' )
|
|
1551
|
+
mTEPES.pLineVoltage = Param(mTEPES.la, initialize=mTEPES.dPar['pLineVoltage'].to_dict() , within=NonNegativeReals, doc='Voltage' )
|
|
1552
|
+
mTEPES.pLineNTCFrw = Param(mTEPES.la, initialize=mTEPES.dPar['pLineNTCFrw'].to_dict() , within=NonNegativeReals, doc='Electric line NTC forward' )
|
|
1553
|
+
mTEPES.pLineNTCBck = Param(mTEPES.la, initialize=mTEPES.dPar['pLineNTCBck'].to_dict() , within=NonNegativeReals, doc='Electric line NTC backward' )
|
|
1554
|
+
mTEPES.pLineNTCMax = Param(mTEPES.la, initialize=mTEPES.dPar['pLineNTCMax'].to_dict() , within=NonNegativeReals, doc='Electric line NTC' )
|
|
1555
|
+
mTEPES.pNetFixedCost = Param(mTEPES.lc, initialize=mTEPES.dPar['pNetFixedCost'].to_dict() , within=NonNegativeReals, doc='Electric line fixed cost' )
|
|
1556
|
+
mTEPES.pIndBinLineInvest = Param(mTEPES.la, initialize=mTEPES.dPar['pIndBinLineInvest'].to_dict(), within=Binary , doc='Binary electric line investment decision' )
|
|
1557
|
+
mTEPES.pIndBinLineSwitch = Param(mTEPES.la, initialize=mTEPES.dPar['pIndBinLineSwitch'].to_dict(), within=Binary , doc='Binary electric line switching decision' )
|
|
1558
|
+
# mTEPES.pSwOnTime = Param(mTEPES.la, initialize=mTEPES.dPar['pSwitchOnTime'].to_dict() , within=NonNegativeIntegers, doc='Minimum switching on time' )
|
|
1559
|
+
# mTEPES.pSwOffTime = Param(mTEPES.la, initialize=mTEPES.dPar['pSwitchOffTime'].to_dict() , within=NonNegativeIntegers, doc='Minimum switching off time' )
|
|
1560
|
+
mTEPES.pBigMFlowBck = Param(mTEPES.la, initialize=mTEPES.dPar['pBigMFlowBck'].to_dict() , within=NonNegativeReals, doc='Maximum backward capacity', mutable=True)
|
|
1561
|
+
mTEPES.pBigMFlowFrw = Param(mTEPES.la, initialize=mTEPES.dPar['pBigMFlowFrw'].to_dict() , within=NonNegativeReals, doc='Maximum forward capacity', mutable=True)
|
|
1562
|
+
mTEPES.pMaxTheta = Param(mTEPES.psnnd, initialize=mTEPES.dPar['pMaxTheta'].to_dict() , within=NonNegativeReals, doc='Maximum voltage angle', mutable=True)
|
|
1563
|
+
mTEPES.pAngMin = Param(mTEPES.la, initialize=mTEPES.dPar['pAngMin'].to_dict() , within= Reals, doc='Minimum phase angle difference', mutable=True)
|
|
1564
|
+
mTEPES.pAngMax = Param(mTEPES.la, initialize=mTEPES.dPar['pAngMax'].to_dict() , within= Reals, doc='Maximum phase angle difference', mutable=True)
|
|
1565
|
+
mTEPES.pNetLoInvest = Param(mTEPES.lc, initialize=mTEPES.dPar['pNetLoInvest'].to_dict() , within=NonNegativeReals, doc='Lower bound of the electric line investment decision', mutable=True)
|
|
1566
|
+
mTEPES.pNetUpInvest = Param(mTEPES.lc, initialize=mTEPES.dPar['pNetUpInvest'].to_dict() , within=NonNegativeReals, doc='Upper bound of the electric line investment decision', mutable=True)
|
|
1567
|
+
mTEPES.pIndBinLinePTDF = Param(mTEPES.la, initialize=mTEPES.dPar['pIndBinLinePTDF'].to_dict() , within=Binary , doc='Binary indicator of line with' )
|
|
1568
|
+
mTEPES.pMaxNTCFrw = Param(mTEPES.psnla, initialize=mTEPES.dPar['pMaxNTCFrw'].to_dict() , within= Reals, doc='Maximum NTC forward capacity' )
|
|
1569
|
+
mTEPES.pMaxNTCBck = Param(mTEPES.psnla, initialize=mTEPES.dPar['pMaxNTCBck'].to_dict() , within= Reals, doc='Maximum NTC backward capacity' )
|
|
1570
|
+
mTEPES.pMaxNTCMax = Param(mTEPES.psnla, initialize=mTEPES.dPar['pMaxNTCMax'].to_dict() , within= Reals, doc='Maximum NTC capacity' )
|
|
1571
|
+
|
|
1572
|
+
if mTEPES.dPar['pIndHydrogen'] == 1:
|
|
1573
|
+
mTEPES.pH2PipeLength = Param(mTEPES.pn, initialize=mTEPES.dPar['pH2PipeLength'].to_dict() , within=NonNegativeReals, doc='Hydrogen pipeline length', mutable=True)
|
|
1574
|
+
mTEPES.pH2PipePeriodIni = Param(mTEPES.pn, initialize=mTEPES.dPar['pH2PipePeriodIni'].to_dict() , within=PositiveIntegers, doc='Installation period' )
|
|
1575
|
+
mTEPES.pH2PipePeriodFin = Param(mTEPES.pn, initialize=mTEPES.dPar['pH2PipePeriodFin'].to_dict() , within=PositiveIntegers, doc='Retirement period' )
|
|
1576
|
+
mTEPES.pH2PipeNTCFrw = Param(mTEPES.pn, initialize=mTEPES.dPar['pH2PipeNTCFrw'].to_dict() , within=NonNegativeReals, doc='Hydrogen pipeline NTC forward' )
|
|
1577
|
+
mTEPES.pH2PipeNTCBck = Param(mTEPES.pn, initialize=mTEPES.dPar['pH2PipeNTCBck'].to_dict() , within=NonNegativeReals, doc='Hydrogen pipeline NTC backward' )
|
|
1578
|
+
mTEPES.pH2PipeFixedCost = Param(mTEPES.pc, initialize=mTEPES.dPar['pH2PipeFixedCost'].to_dict() , within=NonNegativeReals, doc='Hydrogen pipeline fixed cost' )
|
|
1579
|
+
mTEPES.pIndBinH2PipeInvest = Param(mTEPES.pn, initialize=mTEPES.dPar['pIndBinH2PipeInvest'].to_dict(), within=Binary , doc='Binary pipeline investment decision' )
|
|
1580
|
+
mTEPES.pH2PipeLoInvest = Param(mTEPES.pc, initialize=mTEPES.dPar['pH2PipeLoInvest'].to_dict() , within=NonNegativeReals, doc='Lower bound of the pipeline investment decision', mutable=True)
|
|
1581
|
+
mTEPES.pH2PipeUpInvest = Param(mTEPES.pc, initialize=mTEPES.dPar['pH2PipeUpInvest'].to_dict() , within=NonNegativeReals, doc='Upper bound of the pipeline investment decision', mutable=True)
|
|
1582
|
+
|
|
1583
|
+
if mTEPES.dPar['pIndHeat'] == 1:
|
|
1584
|
+
mTEPES.pHeatPipeLength = Param(mTEPES.hn, initialize=mTEPES.dPar['pHeatPipeLength'].to_dict() , within=NonNegativeReals, doc='Heat pipe length', mutable=True)
|
|
1585
|
+
mTEPES.pHeatPipePeriodIni = Param(mTEPES.hn, initialize=mTEPES.dPar['pHeatPipePeriodIni'].to_dict() , within=PositiveIntegers, doc='Installation period' )
|
|
1586
|
+
mTEPES.pHeatPipePeriodFin = Param(mTEPES.hn, initialize=mTEPES.dPar['pHeatPipePeriodFin'].to_dict() , within=PositiveIntegers, doc='Retirement period' )
|
|
1587
|
+
mTEPES.pHeatPipeNTCFrw = Param(mTEPES.hn, initialize=mTEPES.dPar['pHeatPipeNTCFrw'].to_dict() , within=NonNegativeReals, doc='Heat pipe NTC forward' )
|
|
1588
|
+
mTEPES.pHeatPipeNTCBck = Param(mTEPES.hn, initialize=mTEPES.dPar['pHeatPipeNTCBck'].to_dict() , within=NonNegativeReals, doc='Heat pipe NTC backward' )
|
|
1589
|
+
mTEPES.pHeatPipeFixedCost = Param(mTEPES.hc, initialize=mTEPES.dPar['pHeatPipeFixedCost'].to_dict() , within=NonNegativeReals, doc='Heat pipe fixed cost' )
|
|
1590
|
+
mTEPES.pIndBinHeatPipeInvest = Param(mTEPES.hn, initialize=mTEPES.dPar['pIndBinHeatPipeInvest'].to_dict(), within=Binary , doc='Binary heat pipe investment decision' )
|
|
1591
|
+
mTEPES.pHeatPipeLoInvest = Param(mTEPES.hc, initialize=mTEPES.dPar['pHeatPipeLoInvest'].to_dict() , within=NonNegativeReals, doc='Lower bound of the heat pipe investment decision', mutable=True)
|
|
1592
|
+
mTEPES.pHeatPipeUpInvest = Param(mTEPES.hc, initialize=mTEPES.dPar['pHeatPipeUpInvest'].to_dict() , within=NonNegativeReals, doc='Upper bound of the heat pipe investment decision', mutable=True)
|
|
1528
1593
|
|
|
1529
1594
|
# load levels multiple of cycles for each ESS/generator
|
|
1530
1595
|
mTEPES.nesc = [(n,es) for n,es in mTEPES.n*mTEPES.es if mTEPES.n.ord(n) % mTEPES.pStorageTimeStep [es] == 0]
|
|
1531
1596
|
mTEPES.necc = [(n,ec) for n,ec in mTEPES.n*mTEPES.ec if mTEPES.n.ord(n) % mTEPES.pStorageTimeStep [ec] == 0]
|
|
1532
1597
|
mTEPES.neso = [(n,es) for n,es in mTEPES.n*mTEPES.es if mTEPES.n.ord(n) % mTEPES.pOutflowsTimeStep[es] == 0]
|
|
1533
1598
|
mTEPES.ngen = [(n,g ) for n,g in mTEPES.n*mTEPES.g if mTEPES.n.ord(n) % mTEPES.pEnergyTimeStep [g ] == 0]
|
|
1534
|
-
if pIndHydroTopology == 1:
|
|
1599
|
+
if mTEPES.dPar['pIndHydroTopology'] == 1:
|
|
1535
1600
|
mTEPES.nhc = [(n,h ) for n,h in mTEPES.n*mTEPES.h if mTEPES.n.ord(n) % sum(mTEPES.pReservoirTimeStep[rs] for rs in mTEPES.rs if (rs,h) in mTEPES.r2h) == 0]
|
|
1536
1601
|
if sum(1 for h,rs in mTEPES.p2r):
|
|
1537
1602
|
mTEPES.np2c = [(n,h ) for n,h in mTEPES.n*mTEPES.h if sum(1 for rs in mTEPES.rs if (h,rs) in mTEPES.p2r) and mTEPES.n.ord(n) % sum(mTEPES.pReservoirTimeStep[rs] for rs in mTEPES.rs if (h,rs) in mTEPES.p2r) == 0]
|
|
@@ -1547,7 +1612,7 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
1547
1612
|
|
|
1548
1613
|
# ESS with outflows
|
|
1549
1614
|
mTEPES.eo = [(p,sc,es) for p,sc,es in mTEPES.pses if sum(mTEPES.pEnergyOutflows[p,sc,n2,es]() for n2 in mTEPES.n2 if (p,sc,n2) in mTEPES.psn)]
|
|
1550
|
-
if pIndHydroTopology == 1:
|
|
1615
|
+
if mTEPES.dPar['pIndHydroTopology'] == 1:
|
|
1551
1616
|
# reservoirs with outflows
|
|
1552
1617
|
mTEPES.ro = [(p,sc,rs) for p,sc,rs in mTEPES.psrs if sum(mTEPES.pHydroOutflows [p,sc,n2,rs]() for n2 in mTEPES.n2 if (p,sc,n2) in mTEPES.psn)]
|
|
1553
1618
|
# generators with min/max energy
|
|
@@ -1564,30 +1629,30 @@ def InputData(DirName, CaseName, mTEPES, pIndLogConsole):
|
|
|
1564
1629
|
if mTEPES.pLineLength[ni,nf,cc]() == 0.0:
|
|
1565
1630
|
mTEPES.pLineLength[ni,nf,cc] = 1.1 * 6371 * 2 * math.asin(math.sqrt(math.pow(math.sin((mTEPES.pNodeLat[nf]-mTEPES.pNodeLat[ni])*math.pi/180/2),2) + math.cos(mTEPES.pNodeLat[ni]*math.pi/180)*math.cos(mTEPES.pNodeLat[nf]*math.pi/180)*math.pow(math.sin((mTEPES.pNodeLon[nf]-mTEPES.pNodeLon[ni])*math.pi/180/2),2)))
|
|
1566
1631
|
|
|
1567
|
-
if pIndHydrogen == 1:
|
|
1632
|
+
if mTEPES.dPar['pIndHydrogen'] == 1:
|
|
1568
1633
|
# if line length = 0 changed to geographical distance with an additional 10%
|
|
1569
1634
|
for ni,nf,cc in mTEPES.pa:
|
|
1570
1635
|
if mTEPES.pH2PipeLength[ni,nf,cc]() == 0.0:
|
|
1571
1636
|
mTEPES.pH2PipeLength[ni,nf,cc] = 1.1 * 6371 * 2 * math.asin(math.sqrt(math.pow(math.sin((mTEPES.pNodeLat[nf]-mTEPES.pNodeLat[ni])*math.pi/180/2),2) + math.cos(mTEPES.pNodeLat[ni]*math.pi/180)*math.cos(mTEPES.pNodeLat[nf]*math.pi/180)*math.pow(math.sin((mTEPES.pNodeLon[nf]-mTEPES.pNodeLon[ni])*math.pi/180/2),2)))
|
|
1572
1637
|
|
|
1573
|
-
if pIndHeat == 1:
|
|
1638
|
+
if mTEPES.dPar['pIndHeat'] == 1:
|
|
1574
1639
|
# if line length = 0 changed to geographical distance with an additional 10%
|
|
1575
1640
|
for ni,nf,cc in mTEPES.pa:
|
|
1576
1641
|
if mTEPES.pHeatPipeLength[ni,nf,cc]() == 0.0:
|
|
1577
1642
|
mTEPES.pHeatPipeLength[ni,nf,cc] = 1.1 * 6371 * 2 * math.asin(math.sqrt(math.pow(math.sin((mTEPES.pNodeLat[nf]-mTEPES.pNodeLat[ni])*math.pi/180/2),2) + math.cos(mTEPES.pNodeLat[ni]*math.pi/180)*math.cos(mTEPES.pNodeLat[nf]*math.pi/180)*math.pow(math.sin((mTEPES.pNodeLon[nf]-mTEPES.pNodeLon[ni])*math.pi/180/2),2)))
|
|
1578
1643
|
|
|
1579
1644
|
# initialize generation output, unit commitment and line switching
|
|
1580
|
-
pInitialOutput = pd.DataFrame([[0.0]*len(mTEPES.g )]*len(mTEPES.psn), index=mTEPES.psn, columns=mTEPES.g )
|
|
1581
|
-
pInitialUC = pd.DataFrame([[0 ]*len(mTEPES.g )]*len(mTEPES.psn), index=mTEPES.psn, columns=mTEPES.g )
|
|
1582
|
-
pInitialSwitch = pd.DataFrame([[0 ]*len(mTEPES.la)]*len(mTEPES.psn), index=mTEPES.psn, columns=mTEPES.la)
|
|
1645
|
+
mTEPES.dPar['pInitialOutput'] = pd.DataFrame([[0.0]*len(mTEPES.g )]*len(mTEPES.psn), index=mTEPES.psn, columns=mTEPES.g )
|
|
1646
|
+
mTEPES.dPar['pInitialUC'] = pd.DataFrame([[0 ]*len(mTEPES.g )]*len(mTEPES.psn), index=mTEPES.psn, columns=mTEPES.g )
|
|
1647
|
+
mTEPES.dPar['pInitialSwitch'] = pd.DataFrame([[0 ]*len(mTEPES.la)]*len(mTEPES.psn), index=mTEPES.psn, columns=mTEPES.la)
|
|
1583
1648
|
|
|
1584
|
-
pInitialOutput = filter_rows(pInitialOutput, mTEPES.psng )
|
|
1585
|
-
pInitialUC = filter_rows(pInitialUC , mTEPES.psng )
|
|
1586
|
-
pInitialSwitch = filter_rows(pInitialSwitch, mTEPES.psnla)
|
|
1649
|
+
mTEPES.dPar['pInitialOutput'] = filter_rows(mTEPES.dPar['pInitialOutput'], mTEPES.psng )
|
|
1650
|
+
mTEPES.dPar['pInitialUC'] = filter_rows(mTEPES.dPar['pInitialUC'] , mTEPES.psng )
|
|
1651
|
+
mTEPES.dPar['pInitialSwitch'] = filter_rows(mTEPES.dPar['pInitialSwitch'], mTEPES.psnla)
|
|
1587
1652
|
|
|
1588
|
-
mTEPES.pInitialOutput = Param(mTEPES.psng , initialize=pInitialOutput.to_dict(), within=NonNegativeReals, doc='unit initial output', mutable=True)
|
|
1589
|
-
mTEPES.pInitialUC = Param(mTEPES.psng , initialize=pInitialUC.to_dict() , within=Binary, doc='unit initial commitment', mutable=True)
|
|
1590
|
-
mTEPES.pInitialSwitch = Param(mTEPES.psnla, initialize=pInitialSwitch.to_dict(), within=Binary, doc='line initial switching', mutable=True)
|
|
1653
|
+
mTEPES.pInitialOutput = Param(mTEPES.psng , initialize=mTEPES.dPar['pInitialOutput'].to_dict(), within=NonNegativeReals, doc='unit initial output', mutable=True)
|
|
1654
|
+
mTEPES.pInitialUC = Param(mTEPES.psng , initialize=mTEPES.dPar['pInitialUC'].to_dict() , within=Binary, doc='unit initial commitment', mutable=True)
|
|
1655
|
+
mTEPES.pInitialSwitch = Param(mTEPES.psnla, initialize=mTEPES.dPar['pInitialSwitch'].to_dict(), within=Binary, doc='line initial switching', mutable=True)
|
|
1591
1656
|
|
|
1592
1657
|
SettingUpDataTime = time.time() - StartTime
|
|
1593
1658
|
print('Setting up input data ... ', round(SettingUpDataTime), 's')
|
|
@@ -1600,7 +1665,7 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
1600
1665
|
'''
|
|
1601
1666
|
Create all mTEPES variables.
|
|
1602
1667
|
|
|
1603
|
-
This function takes
|
|
1668
|
+
This function takes an mTEPES instance with all parameters and sets created and adds variables to it.
|
|
1604
1669
|
|
|
1605
1670
|
Parameters:
|
|
1606
1671
|
mTEPES: The instance of mTEPES.
|
|
@@ -1609,131 +1674,136 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
1609
1674
|
None: Variables are added directly to the mTEPES object.
|
|
1610
1675
|
'''
|
|
1611
1676
|
#%% variables
|
|
1612
|
-
OptModel.vTotalSCost = Var( within=NonNegativeReals,
|
|
1613
|
-
OptModel.vTotalICost = Var( within=NonNegativeReals,
|
|
1614
|
-
OptModel.vTotalFCost = Var(mTEPES.p, within=NonNegativeReals,
|
|
1615
|
-
OptModel.vTotalGCost = Var(mTEPES.psn, within=NonNegativeReals,
|
|
1616
|
-
OptModel.vTotalCCost = Var(mTEPES.psn, within=NonNegativeReals,
|
|
1617
|
-
OptModel.vTotalECost = Var(mTEPES.psn, within=NonNegativeReals,
|
|
1618
|
-
OptModel.vTotalRCost = Var(mTEPES.psn, within=NonNegativeReals,
|
|
1619
|
-
OptModel.vTotalNCost = Var(mTEPES.psn, within=NonNegativeReals,
|
|
1620
|
-
OptModel.vTotalEmissionArea = Var(mTEPES.psnar, within=NonNegativeReals,
|
|
1621
|
-
OptModel.vTotalECostArea = Var(mTEPES.psnar, within=NonNegativeReals,
|
|
1622
|
-
OptModel.vTotalRESEnergyArea = Var(mTEPES.psnar, within=NonNegativeReals,
|
|
1623
|
-
|
|
1624
|
-
OptModel.vTotalOutput = Var(mTEPES.psng , within=NonNegativeReals,
|
|
1625
|
-
OptModel.vOutput2ndBlock = Var(mTEPES.psnnr, within=NonNegativeReals,
|
|
1626
|
-
OptModel.vReserveUp = Var(mTEPES.psnnr, within=NonNegativeReals,
|
|
1627
|
-
OptModel.vReserveDown = Var(mTEPES.psnnr, within=NonNegativeReals,
|
|
1628
|
-
OptModel.vEnergyInflows = Var(mTEPES.psnec, within=NonNegativeReals,
|
|
1629
|
-
OptModel.vEnergyOutflows = Var(mTEPES.psnes, within=NonNegativeReals,
|
|
1630
|
-
OptModel.vESSInventory = Var(mTEPES.psnes, within=NonNegativeReals,
|
|
1631
|
-
OptModel.vESSSpillage = Var(mTEPES.psnes, within=NonNegativeReals,
|
|
1632
|
-
OptModel.vIniInventory = Var(mTEPES.psnec, within=NonNegativeReals,
|
|
1633
|
-
|
|
1634
|
-
OptModel.vESSTotalCharge = Var(mTEPES.psneh, within=NonNegativeReals,
|
|
1635
|
-
OptModel.vCharge2ndBlock = Var(mTEPES.psneh, within=NonNegativeReals,
|
|
1636
|
-
OptModel.vESSReserveUp = Var(mTEPES.psneh, within=NonNegativeReals,
|
|
1637
|
-
OptModel.vESSReserveDown = Var(mTEPES.psneh, within=NonNegativeReals,
|
|
1638
|
-
OptModel.vENS = Var(mTEPES.psnnd, within=NonNegativeReals,
|
|
1677
|
+
OptModel.vTotalSCost = Var( within=NonNegativeReals, doc='total system cost [MEUR]')
|
|
1678
|
+
OptModel.vTotalICost = Var( within=NonNegativeReals, doc='total system investment cost [MEUR]')
|
|
1679
|
+
OptModel.vTotalFCost = Var(mTEPES.p, within=NonNegativeReals, doc='total system fixed cost [MEUR]')
|
|
1680
|
+
OptModel.vTotalGCost = Var(mTEPES.psn, within=NonNegativeReals, doc='total variable generation operation cost [MEUR]')
|
|
1681
|
+
OptModel.vTotalCCost = Var(mTEPES.psn, within=NonNegativeReals, doc='total variable consumption operation cost [MEUR]')
|
|
1682
|
+
OptModel.vTotalECost = Var(mTEPES.psn, within=NonNegativeReals, doc='total system emission cost [MEUR]')
|
|
1683
|
+
OptModel.vTotalRCost = Var(mTEPES.psn, within=NonNegativeReals, doc='total system reliability cost [MEUR]')
|
|
1684
|
+
OptModel.vTotalNCost = Var(mTEPES.psn, within=NonNegativeReals, doc='total network loss penalty operation cost [MEUR]')
|
|
1685
|
+
OptModel.vTotalEmissionArea = Var(mTEPES.psnar, within=NonNegativeReals, doc='total area emission [MtCO2]')
|
|
1686
|
+
OptModel.vTotalECostArea = Var(mTEPES.psnar, within=NonNegativeReals, doc='total area emission cost [MEUR]')
|
|
1687
|
+
OptModel.vTotalRESEnergyArea = Var(mTEPES.psnar, within=NonNegativeReals, doc=' RES energy [GWh]')
|
|
1688
|
+
|
|
1689
|
+
OptModel.vTotalOutput = Var(mTEPES.psng , within=NonNegativeReals, doc='total output of the unit [GW]')
|
|
1690
|
+
OptModel.vOutput2ndBlock = Var(mTEPES.psnnr, within=NonNegativeReals, doc='second block of the unit [GW]')
|
|
1691
|
+
OptModel.vReserveUp = Var(mTEPES.psnnr, within=NonNegativeReals, doc='upward operating reserve [GW]')
|
|
1692
|
+
OptModel.vReserveDown = Var(mTEPES.psnnr, within=NonNegativeReals, doc='downward operating reserve [GW]')
|
|
1693
|
+
OptModel.vEnergyInflows = Var(mTEPES.psnec, within=NonNegativeReals, doc='unscheduled inflows of candidate ESS units [GW]')
|
|
1694
|
+
OptModel.vEnergyOutflows = Var(mTEPES.psnes, within=NonNegativeReals, doc='scheduled outflows of all ESS units [GW]')
|
|
1695
|
+
OptModel.vESSInventory = Var(mTEPES.psnes, within=NonNegativeReals, doc='ESS inventory [GWh]')
|
|
1696
|
+
OptModel.vESSSpillage = Var(mTEPES.psnes, within=NonNegativeReals, doc='ESS spillage [GWh]')
|
|
1697
|
+
OptModel.vIniInventory = Var(mTEPES.psnec, within=NonNegativeReals, doc='initial inventory for ESS candidate [GWh]')
|
|
1698
|
+
|
|
1699
|
+
OptModel.vESSTotalCharge = Var(mTEPES.psneh, within=NonNegativeReals, doc='ESS total charge power [GW]')
|
|
1700
|
+
OptModel.vCharge2ndBlock = Var(mTEPES.psneh, within=NonNegativeReals, doc='ESS charge power [GW]')
|
|
1701
|
+
OptModel.vESSReserveUp = Var(mTEPES.psneh, within=NonNegativeReals, doc='ESS upward operating reserve [GW]')
|
|
1702
|
+
OptModel.vESSReserveDown = Var(mTEPES.psneh, within=NonNegativeReals, doc='ESS downward operating reserve [GW]')
|
|
1703
|
+
OptModel.vENS = Var(mTEPES.psnnd, within=NonNegativeReals, doc='energy not served in node [GW]')
|
|
1639
1704
|
|
|
1640
1705
|
if mTEPES.pIndHydroTopology == 1:
|
|
1641
|
-
OptModel.vHydroInflows = Var(mTEPES.psnrc, within=NonNegativeReals,
|
|
1642
|
-
OptModel.vHydroOutflows = Var(mTEPES.psnrs, within=NonNegativeReals,
|
|
1643
|
-
OptModel.vReservoirVolume = Var(mTEPES.psnrs, within=NonNegativeReals,
|
|
1644
|
-
OptModel.vReservoirSpillage = Var(mTEPES.psnrs, within=NonNegativeReals,
|
|
1706
|
+
OptModel.vHydroInflows = Var(mTEPES.psnrc, within=NonNegativeReals, doc='unscheduled inflows of candidate hydro units [m3/s]')
|
|
1707
|
+
OptModel.vHydroOutflows = Var(mTEPES.psnrs, within=NonNegativeReals, doc='scheduled outflows of all hydro units [m3/s]')
|
|
1708
|
+
OptModel.vReservoirVolume = Var(mTEPES.psnrs, within=NonNegativeReals, doc='Reservoir volume [hm3]')
|
|
1709
|
+
OptModel.vReservoirSpillage = Var(mTEPES.psnrs, within=NonNegativeReals, doc='Reservoir spillage [hm3]')
|
|
1645
1710
|
|
|
1646
1711
|
if mTEPES.pIndHeat == 1:
|
|
1647
|
-
OptModel.vTotalOutputHeat = Var(mTEPES.psng , within=NonNegativeReals,
|
|
1712
|
+
OptModel.vTotalOutputHeat = Var(mTEPES.psng , within=NonNegativeReals, doc='total heat output of the boiler unit [GW]')
|
|
1648
1713
|
[OptModel.vTotalOutputHeat[p,sc,n,ch].setub(mTEPES.pMaxPowerHeat[p,sc,n,ch]) for p,sc,n,ch in mTEPES.psnch]
|
|
1649
1714
|
[OptModel.vTotalOutputHeat[p,sc,n,ch].setlb(mTEPES.pMinPowerHeat[p,sc,n,ch]) for p,sc,n,ch in mTEPES.psnch]
|
|
1650
1715
|
# only boilers are forced to produce at their minimum heat power. CHPs are not forced to produce at their minimum heat power, they are committed or not to produce electricity
|
|
1651
1716
|
|
|
1652
1717
|
if mTEPES.pIndBinGenInvest() != 1:
|
|
1653
|
-
OptModel.vGenerationInvest = Var(mTEPES.peb, within=UnitInterval,
|
|
1654
|
-
OptModel.vGenerationInvPer = Var(mTEPES.peb, within=UnitInterval,
|
|
1718
|
+
OptModel.vGenerationInvest = Var(mTEPES.peb, within=UnitInterval, doc='generation investment decision exists in a year [0,1]')
|
|
1719
|
+
OptModel.vGenerationInvPer = Var(mTEPES.peb, within=UnitInterval, doc='generation investment decision done in a year [0,1]')
|
|
1655
1720
|
else:
|
|
1656
|
-
OptModel.vGenerationInvest = Var(mTEPES.peb, within=Binary,
|
|
1657
|
-
OptModel.vGenerationInvPer = Var(mTEPES.peb, within=Binary,
|
|
1721
|
+
OptModel.vGenerationInvest = Var(mTEPES.peb, within=Binary, doc='generation investment decision exists in a year {0,1}')
|
|
1722
|
+
OptModel.vGenerationInvPer = Var(mTEPES.peb, within=Binary, doc='generation investment decision done in a year {0,1}')
|
|
1658
1723
|
|
|
1659
1724
|
if mTEPES.pIndBinGenRetire() != 1:
|
|
1660
|
-
OptModel.vGenerationRetire = Var(mTEPES.pgd, within=UnitInterval,
|
|
1661
|
-
OptModel.vGenerationRetPer = Var(mTEPES.pgd, within=UnitInterval,
|
|
1725
|
+
OptModel.vGenerationRetire = Var(mTEPES.pgd, within=UnitInterval, doc='generation retirement decision exists in a year [0,1]')
|
|
1726
|
+
OptModel.vGenerationRetPer = Var(mTEPES.pgd, within=UnitInterval, doc='generation retirement decision exists in a year [0,1]')
|
|
1662
1727
|
else:
|
|
1663
|
-
OptModel.vGenerationRetire = Var(mTEPES.pgd, within=Binary,
|
|
1664
|
-
OptModel.vGenerationRetPer = Var(mTEPES.pgd, within=Binary,
|
|
1728
|
+
OptModel.vGenerationRetire = Var(mTEPES.pgd, within=Binary, doc='generation retirement decision exists in a year {0,1}')
|
|
1729
|
+
OptModel.vGenerationRetPer = Var(mTEPES.pgd, within=Binary, doc='generation retirement decision exists in a year {0,1}')
|
|
1665
1730
|
|
|
1666
1731
|
if mTEPES.pIndBinNetElecInvest() != 1:
|
|
1667
|
-
OptModel.vNetworkInvest = Var(mTEPES.plc, within=UnitInterval,
|
|
1668
|
-
OptModel.vNetworkInvPer = Var(mTEPES.plc, within=UnitInterval,
|
|
1732
|
+
OptModel.vNetworkInvest = Var(mTEPES.plc, within=UnitInterval, doc='electric network investment decision exists in a year [0,1]')
|
|
1733
|
+
OptModel.vNetworkInvPer = Var(mTEPES.plc, within=UnitInterval, doc='electric network investment decision exists in a year [0,1]')
|
|
1669
1734
|
else:
|
|
1670
|
-
OptModel.vNetworkInvest = Var(mTEPES.plc, within=Binary,
|
|
1671
|
-
OptModel.vNetworkInvPer = Var(mTEPES.plc, within=Binary,
|
|
1735
|
+
OptModel.vNetworkInvest = Var(mTEPES.plc, within=Binary, doc='electric network investment decision exists in a year {0,1}')
|
|
1736
|
+
OptModel.vNetworkInvPer = Var(mTEPES.plc, within=Binary, doc='electric network investment decision exists in a year {0,1}')
|
|
1672
1737
|
|
|
1673
1738
|
if mTEPES.pIndHydroTopology == 1:
|
|
1674
1739
|
if mTEPES.pIndBinRsrInvest() != 1:
|
|
1675
|
-
OptModel.vReservoirInvest = Var(mTEPES.prc, within=UnitInterval,
|
|
1676
|
-
OptModel.vReservoirInvPer = Var(mTEPES.prc, within=UnitInterval,
|
|
1740
|
+
OptModel.vReservoirInvest = Var(mTEPES.prc, within=UnitInterval, doc='reservoir investment decision exists in a year [0,1]')
|
|
1741
|
+
OptModel.vReservoirInvPer = Var(mTEPES.prc, within=UnitInterval, doc='reservoir investment decision exists in a year [0,1]')
|
|
1677
1742
|
else:
|
|
1678
|
-
OptModel.vReservoirInvest = Var(mTEPES.prc, within=Binary,
|
|
1679
|
-
OptModel.vReservoirInvPer = Var(mTEPES.prc, within=Binary,
|
|
1743
|
+
OptModel.vReservoirInvest = Var(mTEPES.prc, within=Binary, doc='reservoir investment decision exists in a year {0,1}')
|
|
1744
|
+
OptModel.vReservoirInvPer = Var(mTEPES.prc, within=Binary, doc='reservoir investment decision exists in a year {0,1}')
|
|
1680
1745
|
|
|
1681
1746
|
if mTEPES.pIndHydrogen == 1:
|
|
1682
1747
|
if mTEPES.pIndBinNetH2Invest() != 1:
|
|
1683
|
-
OptModel.vH2PipeInvest = Var(mTEPES.ppc, within=UnitInterval,
|
|
1684
|
-
OptModel.vH2PipeInvPer = Var(mTEPES.ppc, within=UnitInterval,
|
|
1748
|
+
OptModel.vH2PipeInvest = Var(mTEPES.ppc, within=UnitInterval, doc='hydrogen network investment decision exists in a year [0,1]')
|
|
1749
|
+
OptModel.vH2PipeInvPer = Var(mTEPES.ppc, within=UnitInterval, doc='hydrogen network investment decision exists in a year [0,1]')
|
|
1685
1750
|
else:
|
|
1686
|
-
OptModel.vH2PipeInvest = Var(mTEPES.ppc, within=Binary,
|
|
1687
|
-
OptModel.vH2PipeInvPer = Var(mTEPES.ppc, within=Binary,
|
|
1751
|
+
OptModel.vH2PipeInvest = Var(mTEPES.ppc, within=Binary, doc='hydrogen network investment decision exists in a year {0,1}')
|
|
1752
|
+
OptModel.vH2PipeInvPer = Var(mTEPES.ppc, within=Binary, doc='hydrogen network investment decision exists in a year {0,1}')
|
|
1688
1753
|
|
|
1689
1754
|
if mTEPES.pIndHeat == 1:
|
|
1690
1755
|
if mTEPES.pIndBinGenInvest() != 1:
|
|
1691
|
-
OptModel.vGenerationInvestHeat = Var(mTEPES.pbc, within=UnitInterval,
|
|
1692
|
-
OptModel.vGenerationInvPerHeat = Var(mTEPES.pbc, within=UnitInterval,
|
|
1756
|
+
OptModel.vGenerationInvestHeat = Var(mTEPES.pbc, within=UnitInterval, doc='generation investment decision exists in a year [0,1]')
|
|
1757
|
+
OptModel.vGenerationInvPerHeat = Var(mTEPES.pbc, within=UnitInterval, doc='generation investment decision done in a year [0,1]')
|
|
1693
1758
|
else:
|
|
1694
|
-
OptModel.vGenerationInvestHeat = Var(mTEPES.pbc, within=Binary,
|
|
1695
|
-
OptModel.vGenerationInvPerHeat = Var(mTEPES.pbc, within=Binary,
|
|
1759
|
+
OptModel.vGenerationInvestHeat = Var(mTEPES.pbc, within=Binary, doc='generation investment decision exists in a year {0,1}')
|
|
1760
|
+
OptModel.vGenerationInvPerHeat = Var(mTEPES.pbc, within=Binary, doc='generation investment decision done in a year {0,1}')
|
|
1696
1761
|
if mTEPES.pIndBinNetHeatInvest() != 1:
|
|
1697
|
-
OptModel.vHeatPipeInvest = Var(mTEPES.phc, within=UnitInterval,
|
|
1698
|
-
OptModel.vHeatPipeInvPer = Var(mTEPES.phc, within=UnitInterval,
|
|
1762
|
+
OptModel.vHeatPipeInvest = Var(mTEPES.phc, within=UnitInterval, doc='heat network investment decision exists in a year [0,1]' )
|
|
1763
|
+
OptModel.vHeatPipeInvPer = Var(mTEPES.phc, within=UnitInterval, doc='heat network investment decision exists in a year [0,1]' )
|
|
1699
1764
|
else:
|
|
1700
|
-
OptModel.vHeatPipeInvest = Var(mTEPES.phc, within=Binary,
|
|
1701
|
-
OptModel.vHeatPipeInvPer = Var(mTEPES.phc, within=Binary,
|
|
1765
|
+
OptModel.vHeatPipeInvest = Var(mTEPES.phc, within=Binary, doc='heat network investment decision exists in a year {0,1}' )
|
|
1766
|
+
OptModel.vHeatPipeInvPer = Var(mTEPES.phc, within=Binary, doc='heat network investment decision exists in a year {0,1}' )
|
|
1702
1767
|
|
|
1703
1768
|
if mTEPES.pIndBinGenOperat() == 0:
|
|
1704
1769
|
OptModel.vCommitment = Var(mTEPES.psnnr, within=UnitInterval, initialize=0.0, doc='commitment of the unit [0,1]')
|
|
1705
1770
|
OptModel.vStartUp = Var(mTEPES.psnnr, within=UnitInterval, initialize=0.0, doc='startup of the unit [0,1]')
|
|
1706
1771
|
OptModel.vShutDown = Var(mTEPES.psnnr, within=UnitInterval, initialize=0.0, doc='shutdown of the unit [0,1]')
|
|
1707
|
-
OptModel.vMaxCommitment = Var(mTEPES.psnr , within=UnitInterval, initialize=0.0, doc='maximum commitment of the unit [0,1]')
|
|
1708
1772
|
OptModel.vStableState = Var(mTEPES.psnnr, within=UnitInterval, initialize=0.0, doc='stable state of the unit [0,1]')
|
|
1709
1773
|
OptModel.vRampUpState = Var(mTEPES.psnnr, within=UnitInterval, initialize=0.0, doc='ramp up state of the unit [0,1]')
|
|
1710
1774
|
OptModel.vRampDwState = Var(mTEPES.psnnr, within=UnitInterval, initialize=0.0, doc='ramp down state of the unit [0,1]')
|
|
1775
|
+
|
|
1776
|
+
OptModel.vMaxCommitmentYearly = Var(mTEPES.psnr ,mTEPES.ExclusiveGroupsYearly, within=UnitInterval, initialize=0.0, doc='maximum commitment of the unit yearly [0,1]')
|
|
1777
|
+
OptModel.vMaxCommitmentHourly = Var(mTEPES.psnnr,mTEPES.ExclusiveGroupsHourly, within=UnitInterval, initialize=0.0, doc='maximum commitment of the unit hourly [0,1]')
|
|
1778
|
+
|
|
1711
1779
|
if mTEPES.pIndHydroTopology == 1:
|
|
1712
|
-
OptModel.vCommitmentCons = Var(mTEPES.psnh, within=UnitInterval,
|
|
1780
|
+
OptModel.vCommitmentCons = Var(mTEPES.psnh, within=UnitInterval, doc='consumption commitment of the unit [0,1]')
|
|
1713
1781
|
|
|
1714
1782
|
else:
|
|
1715
1783
|
OptModel.vCommitment = Var(mTEPES.psnnr, within=Binary, initialize=0 , doc='commitment of the unit {0,1}')
|
|
1716
1784
|
OptModel.vStartUp = Var(mTEPES.psnnr, within=Binary, initialize=0 , doc='startup of the unit {0,1}')
|
|
1717
1785
|
OptModel.vShutDown = Var(mTEPES.psnnr, within=Binary, initialize=0 , doc='shutdown of the unit {0,1}')
|
|
1718
|
-
OptModel.vMaxCommitment = Var(mTEPES.psnr , within=Binary, initialize=0 , doc='maximum commitment of the unit {0,1}')
|
|
1719
1786
|
OptModel.vStableState = Var(mTEPES.psnnr, within=Binary, initialize=0 , doc='stable state of the unit {0,1}')
|
|
1720
1787
|
OptModel.vRampUpState = Var(mTEPES.psnnr, within=Binary, initialize=0 , doc='ramp up state of the unit {0,1}')
|
|
1721
1788
|
OptModel.vRampDwState = Var(mTEPES.psnnr, within=Binary, initialize=0 , doc='ramp down state of the unit {0,1}')
|
|
1789
|
+
|
|
1790
|
+
OptModel.vMaxCommitmentYearly = Var(mTEPES.psnr ,mTEPES.ExclusiveGroupsYearly, within=Binary, initialize=0.0, doc='maximum commitment of the unit yearly [0,1]')
|
|
1791
|
+
OptModel.vMaxCommitmentHourly = Var(mTEPES.psnnr,mTEPES.ExclusiveGroupsHourly, within=Binary, initialize=0.0, doc='maximum commitment of the unit hourly [0,1]')
|
|
1722
1792
|
if mTEPES.pIndHydroTopology == 1:
|
|
1723
|
-
OptModel.vCommitmentCons
|
|
1793
|
+
OptModel.vCommitmentCons = Var(mTEPES.psnh, within=Binary, doc='consumption commitment of the unit {0,1}')
|
|
1724
1794
|
|
|
1725
1795
|
if mTEPES.pIndBinLineCommit() == 0:
|
|
1726
|
-
OptModel.vLineCommit = Var(mTEPES.psnla, within=UnitInterval,
|
|
1796
|
+
OptModel.vLineCommit = Var(mTEPES.psnla, within=UnitInterval, doc='line switching of the electric line [0,1]')
|
|
1727
1797
|
else:
|
|
1728
|
-
OptModel.vLineCommit = Var(mTEPES.psnla, within=Binary,
|
|
1798
|
+
OptModel.vLineCommit = Var(mTEPES.psnla, within=Binary, doc='line switching of the electric line {0,1}')
|
|
1729
1799
|
|
|
1730
1800
|
if sum(mTEPES.pIndBinLineSwitch[:,:,:]):
|
|
1731
1801
|
if mTEPES.pIndBinSingleNode() == 0 and mTEPES.pIndBinLineCommit() == 0:
|
|
1732
|
-
OptModel.vLineOnState = Var(mTEPES.psnla, within=UnitInterval,
|
|
1733
|
-
OptModel.vLineOffState = Var(mTEPES.psnla, within=UnitInterval,
|
|
1802
|
+
OptModel.vLineOnState = Var(mTEPES.psnla, within=UnitInterval, doc='switching on state of the electric line [0,1]')
|
|
1803
|
+
OptModel.vLineOffState = Var(mTEPES.psnla, within=UnitInterval, doc='switching off state of the electric line [0,1]')
|
|
1734
1804
|
else:
|
|
1735
|
-
OptModel.vLineOnState = Var(mTEPES.psnla, within=Binary,
|
|
1736
|
-
OptModel.vLineOffState = Var(mTEPES.psnla, within=Binary,
|
|
1805
|
+
OptModel.vLineOnState = Var(mTEPES.psnla, within=Binary, doc='switching on state of the electric line {0,1}')
|
|
1806
|
+
OptModel.vLineOffState = Var(mTEPES.psnla, within=Binary, doc='switching off state of the electric line {0,1}')
|
|
1737
1807
|
|
|
1738
1808
|
CreateVariables(mTEPES, mTEPES)
|
|
1739
1809
|
# assign lower and upper bounds to variables
|
|
@@ -1741,7 +1811,7 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
1741
1811
|
'''
|
|
1742
1812
|
Set upper/lower bounds.
|
|
1743
1813
|
|
|
1744
|
-
This function takes
|
|
1814
|
+
This function takes an mTEPES instance and adds lower/upper bounds to variables which are limited by a parameter.
|
|
1745
1815
|
|
|
1746
1816
|
Parameters:
|
|
1747
1817
|
mTEPES: The instance of mTEPES
|
|
@@ -1766,7 +1836,7 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
1766
1836
|
[OptModel.vCharge2ndBlock[p,sc,n,eh].setub(mTEPES.pMaxCharge2ndBlock[p,sc,n,eh] ) for p,sc,n,eh in mTEPES.psneh]
|
|
1767
1837
|
[OptModel.vESSReserveUp [p,sc,n,eh].setub(mTEPES.pMaxCharge2ndBlock[p,sc,n,eh] ) for p,sc,n,eh in mTEPES.psneh]
|
|
1768
1838
|
[OptModel.vESSReserveDown[p,sc,n,eh].setub(mTEPES.pMaxCharge2ndBlock[p,sc,n,eh] ) for p,sc,n,eh in mTEPES.psneh]
|
|
1769
|
-
[OptModel.vENS [p,sc,n,nd].setub(mTEPES.
|
|
1839
|
+
[OptModel.vENS [p,sc,n,nd].setub(mTEPES.pDemandElecPos [p,sc,n,nd] ) for p,sc,n,nd in mTEPES.psnnd]
|
|
1770
1840
|
|
|
1771
1841
|
if mTEPES.pIndHydroTopology == 1:
|
|
1772
1842
|
[OptModel.vHydroInflows [p,sc,n,rc].setub(mTEPES.pHydroInflows[p,sc,n,rc]()) for p,sc,n,rc in mTEPES.psnrc]
|
|
@@ -1779,16 +1849,16 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
1779
1849
|
nFixedVariables = 0
|
|
1780
1850
|
def RelaxBinaryInvestmentConditions(mTEPES, OptModel) -> int:
|
|
1781
1851
|
'''
|
|
1782
|
-
Relax binary
|
|
1852
|
+
Relax binary investment variables.
|
|
1783
1853
|
|
|
1784
|
-
This function takes
|
|
1854
|
+
This function takes an mTEPES instance, relaxes binary investment conditions and calculates the number of variables fixed in the process.
|
|
1785
1855
|
|
|
1786
1856
|
Parameters:
|
|
1787
1857
|
mTEPES: The instance of mTEPES.
|
|
1788
1858
|
OptModel:
|
|
1789
1859
|
|
|
1790
1860
|
Returns:
|
|
1791
|
-
int: The
|
|
1861
|
+
int: The number of fixed variables.
|
|
1792
1862
|
'''
|
|
1793
1863
|
|
|
1794
1864
|
nFixedBinaries = 0
|
|
@@ -1850,9 +1920,12 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
1850
1920
|
OptModel.vStartUp [p,sc,n,nr].domain = UnitInterval
|
|
1851
1921
|
OptModel.vShutDown [p,sc,n,nr].domain = UnitInterval
|
|
1852
1922
|
|
|
1853
|
-
for p,sc,
|
|
1854
|
-
if mTEPES.pIndBinUnitCommit[nr] == 0:
|
|
1855
|
-
OptModel.
|
|
1923
|
+
for p,sc,nr, group in mTEPES.psnr * mTEPES.ExclusiveGroups:
|
|
1924
|
+
if mTEPES.pIndBinUnitCommit[nr] == 0 and nr in mTEPES.ExclusiveGeneratorsYearly:
|
|
1925
|
+
OptModel.vMaxCommitmentYearly[p,sc, nr,group].domain = UnitInterval
|
|
1926
|
+
for p,sc,n,nr,group in mTEPES.psnnr * mTEPES.ExclusiveGroups:
|
|
1927
|
+
if mTEPES.pIndBinUnitCommit[nr] == 0 and nr in mTEPES.ExclusiveGeneratorsHourly:
|
|
1928
|
+
OptModel.vMaxCommitmentHourly[p,sc,n,nr,group].domain = UnitInterval
|
|
1856
1929
|
if mTEPES.pIndHydroTopology == 1:
|
|
1857
1930
|
for p,sc,n,h in mTEPES.psnh:
|
|
1858
1931
|
if mTEPES.pIndBinUnitCommit[h] == 0:
|
|
@@ -1861,17 +1934,16 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
1861
1934
|
OptModel.vCommitmentCons[p,sc,n,h].fix(0)
|
|
1862
1935
|
nFixedBinaries += 1
|
|
1863
1936
|
|
|
1864
|
-
|
|
1865
1937
|
return nFixedBinaries
|
|
1866
1938
|
|
|
1867
|
-
#
|
|
1939
|
+
# call the relaxing variables function and add its output to nFixedVariables
|
|
1868
1940
|
nFixedBinaries = RelaxBinaryInvestmentConditions(mTEPES, mTEPES)
|
|
1869
1941
|
nFixedVariables += nFixedBinaries
|
|
1870
1942
|
|
|
1871
1943
|
def CreateFlowVariables(mTEPES,OptModel) -> int:
|
|
1872
1944
|
#TODO use a more descriptive name for nFixedVariables
|
|
1873
1945
|
'''
|
|
1874
|
-
Create electricity, hydrogen and heat
|
|
1946
|
+
Create electricity, hydrogen and heat-flow-related variables.
|
|
1875
1947
|
|
|
1876
1948
|
This function takes a mTEPES instance and adds the variables necessary to model power, hydrogen and heat flows in a network.
|
|
1877
1949
|
|
|
@@ -1880,8 +1952,9 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
1880
1952
|
OptModel:
|
|
1881
1953
|
|
|
1882
1954
|
Returns:
|
|
1883
|
-
int: The
|
|
1955
|
+
int: The number of line commitment variables fixed
|
|
1884
1956
|
'''
|
|
1957
|
+
|
|
1885
1958
|
nFixedVariables = 0
|
|
1886
1959
|
# existing lines are always committed if no switching decision is modeled
|
|
1887
1960
|
[OptModel.vLineCommit[p,sc,n,ni,nf,cc].fix(1) for p,sc,n,ni,nf,cc in mTEPES.psnle if mTEPES.pIndBinLineSwitch[ni,nf,cc] == 0]
|
|
@@ -1897,12 +1970,20 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
1897
1970
|
OptModel.vFlowElec = Var(mTEPES.psnla, within=Reals, doc='electric flow [GW]')
|
|
1898
1971
|
OptModel.vTheta = Var(mTEPES.psnnd, within=Reals, doc='voltage angle [rad]')
|
|
1899
1972
|
|
|
1973
|
+
if mTEPES.pIndVarTTC == 1:
|
|
1974
|
+
# lines with TTC and TTCBck = 0 are disconnected and the flow is fixed to 0
|
|
1975
|
+
[OptModel.vFlowElec[p,sc,n,ni,nf,cc].fix(0.0) for p,sc,n,ni,nf,cc in mTEPES.psnla if mTEPES.pMaxNTCFrw[p,sc,n,ni,nf,cc] == 0.0 and mTEPES.pMaxNTCBck[p,sc,n,ni,nf,cc] == 0.0]
|
|
1976
|
+
nFixedVariables += sum( 1 for p,sc,n,ni,nf,cc in mTEPES.psnla if mTEPES.pMaxNTCFrw[p,sc,n,ni,nf,cc] == 0.0 and mTEPES.pMaxNTCBck[p,sc,n,ni,nf,cc] == 0.0)
|
|
1977
|
+
|
|
1978
|
+
if mTEPES.pIndPTDF == 1:
|
|
1979
|
+
OptModel.vNetPosition = Var(mTEPES.psnnd, within=Reals, doc='net position in node [GW]')
|
|
1980
|
+
|
|
1900
1981
|
[OptModel.vLineLosses[p,sc,n,ni,nf,cc].setub(0.5*mTEPES.pLineLossFactor[ni,nf,cc]*mTEPES.pLineNTCMax[ni,nf,cc]) for p,sc,n,ni,nf,cc in mTEPES.psnll]
|
|
1901
1982
|
if mTEPES.pIndBinSingleNode() == 0:
|
|
1902
|
-
[OptModel.vFlowElec[p,sc,n,ni,nf,cc].setlb(-mTEPES.
|
|
1903
|
-
[OptModel.vFlowElec[p,sc,n,ni,nf,cc].setub( mTEPES.
|
|
1904
|
-
[OptModel.vTheta [p,sc,n,nd ].setlb(-mTEPES.pMaxTheta
|
|
1905
|
-
[OptModel.vTheta [p,sc,n,nd ].setub( mTEPES.pMaxTheta
|
|
1983
|
+
[OptModel.vFlowElec[p,sc,n,ni,nf,cc].setlb(-mTEPES.pMaxNTCBck[p,sc,n,ni,nf,cc] ) for p,sc,n,ni,nf,cc in mTEPES.psnla]
|
|
1984
|
+
[OptModel.vFlowElec[p,sc,n,ni,nf,cc].setub( mTEPES.pMaxNTCFrw[p,sc,n,ni,nf,cc] ) for p,sc,n,ni,nf,cc in mTEPES.psnla]
|
|
1985
|
+
[OptModel.vTheta [p,sc,n,nd ].setlb(-mTEPES.pMaxTheta [p,sc,n,nd ]() ) for p,sc,n,nd in mTEPES.psnnd]
|
|
1986
|
+
[OptModel.vTheta [p,sc,n,nd ].setub( mTEPES.pMaxTheta [p,sc,n,nd ]() ) for p,sc,n,nd in mTEPES.psnnd]
|
|
1906
1987
|
|
|
1907
1988
|
if mTEPES.pIndHydrogen == 1:
|
|
1908
1989
|
OptModel.vFlowH2 = Var(mTEPES.psnpa, within=Reals, doc='pipeline flow [tH2]')
|
|
@@ -1926,14 +2007,14 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
1926
2007
|
'''
|
|
1927
2008
|
Fix commitment variables.
|
|
1928
2009
|
|
|
1929
|
-
This function takes
|
|
2010
|
+
This function takes an mTEPES instance and fixes commitment-related variables for must run units, ESS units and units with no minimum power.
|
|
1930
2011
|
|
|
1931
2012
|
Parameters:
|
|
1932
2013
|
mTEPES: The instance of mTEPES.
|
|
1933
2014
|
OptModel:
|
|
1934
2015
|
|
|
1935
2016
|
Returns:
|
|
1936
|
-
int: The
|
|
2017
|
+
int: The number of commitment variables fixed.
|
|
1937
2018
|
'''
|
|
1938
2019
|
nFixedVariables = 0
|
|
1939
2020
|
|
|
@@ -1945,32 +2026,31 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
1945
2026
|
nFixedVariables += sum( 1 for p,sc,n,g in mTEPES.psng if mTEPES.pMaxPowerElec[p,sc,n,g] == 0.0)
|
|
1946
2027
|
|
|
1947
2028
|
for p,sc,n,nr in mTEPES.psnnr:
|
|
1948
|
-
# must run units or units with no minimum power or ESS existing units are always committed and must produce at least their minimum output
|
|
2029
|
+
# must run units or units with no minimum power, or ESS existing units are always committed and must produce at least their minimum output
|
|
1949
2030
|
# not applicable to mutually exclusive units
|
|
1950
|
-
if len(mTEPES.
|
|
1951
|
-
OptModel.vMaxCommitment [p,sc, nr].fix(1)
|
|
1952
|
-
nFixedVariables += 1/len(mTEPES.n)
|
|
2031
|
+
if len(mTEPES.ExclusiveGroups) == 0:
|
|
1953
2032
|
if (mTEPES.pMustRun[nr] == 1 or (mTEPES.pMinPowerElec[p,sc,n,nr] == 0.0 and mTEPES.pRatedConstantVarCost[nr] == 0.0) or nr in mTEPES.es ) and nr not in mTEPES.ec and nr not in mTEPES.h:
|
|
1954
2033
|
OptModel.vCommitment [p,sc,n,nr].fix(1)
|
|
1955
2034
|
OptModel.vStartUp [p,sc,n,nr].fix(0)
|
|
1956
2035
|
OptModel.vShutDown [p,sc,n,nr].fix(0)
|
|
1957
2036
|
nFixedVariables += 3
|
|
1958
|
-
|
|
2037
|
+
# If there are mutually exclusive groups do not fix variables from ESS in mutually exclusive groups
|
|
2038
|
+
elif len(mTEPES.ExclusiveGroups) > 0 and nr not in mTEPES.ExclusiveGenerators:
|
|
1959
2039
|
if (mTEPES.pMustRun[nr] == 1 or (mTEPES.pMinPowerElec[p,sc,n,nr] == 0.0 and mTEPES.pRatedConstantVarCost[nr] == 0.0) or nr in mTEPES.es) and nr not in mTEPES.ec and nr not in mTEPES.h:
|
|
1960
2040
|
OptModel.vCommitment [p,sc,n,nr].fix(1)
|
|
1961
2041
|
OptModel.vStartUp [p,sc,n,nr].fix(0)
|
|
1962
2042
|
OptModel.vShutDown [p,sc,n,nr].fix(0)
|
|
1963
|
-
|
|
1964
|
-
|
|
2043
|
+
nFixedVariables += 3
|
|
2044
|
+
|
|
1965
2045
|
# if min and max power coincide there are neither second block, nor operating reserve
|
|
1966
|
-
if mTEPES.pMaxPower2ndBlock[p,sc,n,nr] == 0.0:
|
|
1967
|
-
OptModel.vOutput2ndBlock[p,sc,n,nr].fix(0.0)
|
|
1968
|
-
OptModel.vReserveUp
|
|
1969
|
-
OptModel.vReserveDown
|
|
2046
|
+
if mTEPES.pMaxPower2ndBlock [p,sc,n,nr] == 0.0:
|
|
2047
|
+
OptModel.vOutput2ndBlock [p,sc,n,nr].fix(0.0)
|
|
2048
|
+
OptModel.vReserveUp [p,sc,n,nr].fix(0.0)
|
|
2049
|
+
OptModel.vReserveDown [p,sc,n,nr].fix(0.0)
|
|
1970
2050
|
nFixedVariables += 3
|
|
1971
|
-
if mTEPES.
|
|
1972
|
-
OptModel.vReserveUp
|
|
1973
|
-
OptModel.vReserveDown
|
|
2051
|
+
if mTEPES.pIndOperReserveGen[ nr] == 1:
|
|
2052
|
+
OptModel.vReserveUp [p,sc,n,nr].fix(0.0)
|
|
2053
|
+
OptModel.vReserveDown [p,sc,n,nr].fix(0.0)
|
|
1974
2054
|
nFixedVariables += 2
|
|
1975
2055
|
|
|
1976
2056
|
# total energy inflows per storage
|
|
@@ -1996,7 +2076,7 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
1996
2076
|
if mTEPES.pMaxCharge2ndBlock[p,sc,n,es] == 0.0:
|
|
1997
2077
|
OptModel.vCharge2ndBlock [p,sc,n,es].fix(0.0)
|
|
1998
2078
|
nFixedVariables += 1
|
|
1999
|
-
if mTEPES.pMaxCharge2ndBlock[p,sc,n,es] == 0.0 or mTEPES.
|
|
2079
|
+
if mTEPES.pMaxCharge2ndBlock[p,sc,n,es] == 0.0 or mTEPES.pIndOperReserveCon[es] == 1:
|
|
2000
2080
|
OptModel.vESSReserveUp [p,sc,n,es].fix(0.0)
|
|
2001
2081
|
OptModel.vESSReserveDown [p,sc,n,es].fix(0.0)
|
|
2002
2082
|
nFixedVariables += 2
|
|
@@ -2014,7 +2094,7 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
2014
2094
|
if mTEPES.pMaxCharge2ndBlock[p,sc,n,h ] == 0.0:
|
|
2015
2095
|
OptModel.vCharge2ndBlock [p,sc,n,h ].fix(0.0)
|
|
2016
2096
|
nFixedVariables += 1
|
|
2017
|
-
if mTEPES.pMaxCharge2ndBlock[p,sc,n,h ] == 0.0 or mTEPES.
|
|
2097
|
+
if mTEPES.pMaxCharge2ndBlock[p,sc,n,h ] == 0.0 or mTEPES.pIndOperReserveCon[h ] == 1:
|
|
2018
2098
|
OptModel.vESSReserveUp [p,sc,n,h ].fix(0.0)
|
|
2019
2099
|
OptModel.vESSReserveDown [p,sc,n,h ].fix(0.0)
|
|
2020
2100
|
nFixedVariables += 2
|
|
@@ -2022,7 +2102,7 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
2022
2102
|
nFixedGeneratorCommits = FixGeneratorsCommitment(mTEPES,mTEPES)
|
|
2023
2103
|
nFixedVariables += nFixedGeneratorCommits
|
|
2024
2104
|
# thermal, ESS, and RES units ordered by increasing variable operation cost, excluding reactive generating units
|
|
2025
|
-
if
|
|
2105
|
+
if mTEPES.tq:
|
|
2026
2106
|
mTEPES.go = Set(initialize=[g for g in sorted(mTEPES.pRatedLinearVarCost, key=mTEPES.pRatedLinearVarCost.__getitem__) if g not in mTEPES.sq])
|
|
2027
2107
|
else:
|
|
2028
2108
|
if mTEPES.pIndHydroTopology == 1:
|
|
@@ -2042,7 +2122,7 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
2042
2122
|
mTEPES.st = Set(doc='stages', initialize=[stt for stt in mTEPES.stt if st == stt and mTEPES.pStageWeight[stt] and sum(1 for (p,sc,st,nn) in mTEPES.s2n)])
|
|
2043
2123
|
mTEPES.n = Set(doc='load levels', initialize=[nn for nn in mTEPES.nn if (p,sc,st,nn) in mTEPES.s2n ])
|
|
2044
2124
|
|
|
2045
|
-
if
|
|
2125
|
+
if mTEPES.n:
|
|
2046
2126
|
# determine the first load level of each stage
|
|
2047
2127
|
n1 = (p,sc,mTEPES.n.first())
|
|
2048
2128
|
# commit the units of each area and their output at the first load level of each stage
|
|
@@ -2054,7 +2134,7 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
2054
2134
|
mTEPES.pInitialUC [n1,nr] = 1
|
|
2055
2135
|
pSystemOutput += mTEPES.pInitialOutput[n1,nr]()
|
|
2056
2136
|
|
|
2057
|
-
# determine the
|
|
2137
|
+
# determine the initially committed units and their output at the first load level of each period, scenario, and stage
|
|
2058
2138
|
for go in mTEPES.go:
|
|
2059
2139
|
if go in g2a[ar] and (p,go) in mTEPES.pg and pSystemOutput < sum(mTEPES.pDemandElec[n1,nd] for nd in mTEPES.nd if (nd,ar) in mTEPES.ndar) and mTEPES.pMustRun[go] == 0:
|
|
2060
2140
|
if go in mTEPES.re:
|
|
@@ -2064,7 +2144,7 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
2064
2144
|
mTEPES.pInitialUC[n1,go] = 1
|
|
2065
2145
|
pSystemOutput += mTEPES.pInitialOutput[n1,go]()
|
|
2066
2146
|
|
|
2067
|
-
# determine the
|
|
2147
|
+
# determine the initially committed lines
|
|
2068
2148
|
for la in mTEPES.la:
|
|
2069
2149
|
if la in mTEPES.lc:
|
|
2070
2150
|
mTEPES.pInitialSwitch[n1,la] = 0
|
|
@@ -2128,7 +2208,7 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
2128
2208
|
OptModel.vEnergyInflows [p,sc,n,ec].fix (0.0)
|
|
2129
2209
|
nFixedVariables += 1
|
|
2130
2210
|
|
|
2131
|
-
# if no operating reserve is required no variables are needed
|
|
2211
|
+
# if no operating reserve is required, no variables are needed
|
|
2132
2212
|
for p,sc,n,ar,nr in mTEPES.psnar*mTEPES.nr:
|
|
2133
2213
|
if (ar,nr) in mTEPES.a2g and (p,nr) in mTEPES.pnr:
|
|
2134
2214
|
if mTEPES.pOperReserveUp [p,sc,n,ar] == 0.0:
|
|
@@ -2146,7 +2226,7 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
2146
2226
|
OptModel.vESSReserveDown[p,sc,n,es].fix(0.0)
|
|
2147
2227
|
nFixedVariables += 1
|
|
2148
2228
|
|
|
2149
|
-
# if there are no energy outflows no variable is needed
|
|
2229
|
+
# if there are no energy outflows, no variable is needed
|
|
2150
2230
|
for es in mTEPES.es:
|
|
2151
2231
|
if sum(mTEPES.pEnergyOutflows[p,sc,n,es]() for p,sc,n in mTEPES.psn if (p,es) in mTEPES.pes) == 0.0:
|
|
2152
2232
|
for p,sc,n in mTEPES.psn:
|
|
@@ -2154,6 +2234,15 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
2154
2234
|
OptModel.vEnergyOutflows[p,sc,n,es].fix(0.0)
|
|
2155
2235
|
nFixedVariables += 1
|
|
2156
2236
|
|
|
2237
|
+
if mTEPES.pIndHydroTopology == 1:
|
|
2238
|
+
# if there are no hydro outflows, no variable is needed
|
|
2239
|
+
for rs in mTEPES.rs:
|
|
2240
|
+
if sum(mTEPES.pHydroOutflows[p,sc,n,rs]() for p,sc,n in mTEPES.psn if (p,rs) in mTEPES.prs) == 0.0:
|
|
2241
|
+
for p,sc,n in mTEPES.psn:
|
|
2242
|
+
if (p,rs) in mTEPES.prs:
|
|
2243
|
+
OptModel.vHydroOutflows[p,sc,n,rs].fix(0.0)
|
|
2244
|
+
nFixedVariables += 1
|
|
2245
|
+
|
|
2157
2246
|
# fixing the voltage angle of the reference node for each scenario, period, and load level
|
|
2158
2247
|
if mTEPES.pIndBinSingleNode() == 0:
|
|
2159
2248
|
for p,sc,n in mTEPES.psn:
|
|
@@ -2162,7 +2251,7 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
2162
2251
|
|
|
2163
2252
|
# fixing the ENS in nodes with no demand
|
|
2164
2253
|
for p,sc,n,nd in mTEPES.psnnd:
|
|
2165
|
-
if mTEPES.pDemandElec[p,sc,n,nd]
|
|
2254
|
+
if mTEPES.pDemandElec[p,sc,n,nd] <= 0.0:
|
|
2166
2255
|
OptModel.vENS [p,sc,n,nd].fix(0.0)
|
|
2167
2256
|
nFixedVariables += 1
|
|
2168
2257
|
|
|
@@ -2184,14 +2273,14 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
2184
2273
|
'''
|
|
2185
2274
|
Fix installations/retirements forbidden by period.
|
|
2186
2275
|
|
|
2187
|
-
This function takes
|
|
2276
|
+
This function takes an mTEPES instance and fixes all installation and retirement variables to 0 if they are not allowed in the corresponding period.
|
|
2188
2277
|
|
|
2189
2278
|
Parameters:
|
|
2190
2279
|
mTEPES: The instance of mTEPES.
|
|
2191
2280
|
OptModel:
|
|
2192
2281
|
|
|
2193
2282
|
Returns:
|
|
2194
|
-
int: The
|
|
2283
|
+
int: The number of variables fixed.
|
|
2195
2284
|
'''
|
|
2196
2285
|
nFixedVariables = 0
|
|
2197
2286
|
# do not install/retire power plants and lines if not allowed in this period
|
|
@@ -2289,7 +2378,7 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
2289
2378
|
if mTEPES.pIndHydroTopology == 1:
|
|
2290
2379
|
for p,sc,n,rs in mTEPES.psnrs:
|
|
2291
2380
|
if rs not in mTEPES.rn and mTEPES.pRsrPeriodIni[rs] > p:
|
|
2292
|
-
OptModel.
|
|
2381
|
+
OptModel.vHydroOutflows [p,sc,n,rs].fix(0.0)
|
|
2293
2382
|
OptModel.vReservoirVolume [p,sc,n,rs].fix(0.0)
|
|
2294
2383
|
OptModel.vReservoirSpillage [p,sc,n,rs].fix(0.0)
|
|
2295
2384
|
mTEPES.pIniVolume [p,sc,n,rs] = 0.0
|
|
@@ -2311,18 +2400,18 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
2311
2400
|
[OptModel.vLineCommit [p,sc,n,ni,nf,cc].fix(0 ) for p,sc,n,ni,nf,cc in mTEPES.psnla if (ni,nf,cc) not in mTEPES.lc and mTEPES.pElecNetPeriodIni [ni,nf,cc] > p]
|
|
2312
2401
|
[OptModel.vLineOnState [p,sc,n,ni,nf,cc].fix(0 ) for p,sc,n,ni,nf,cc in mTEPES.psnla if (ni,nf,cc) not in mTEPES.lc and mTEPES.pElecNetPeriodIni [ni,nf,cc] > p]
|
|
2313
2402
|
[OptModel.vLineOffState[p,sc,n,ni,nf,cc].fix(0 ) for p,sc,n,ni,nf,cc in mTEPES.psnla if (ni,nf,cc) not in mTEPES.lc and mTEPES.pElecNetPeriodIni [ni,nf,cc] > p]
|
|
2314
|
-
nFixedVariables += sum(
|
|
2403
|
+
nFixedVariables += sum( 4 for p,sc,n,ni,nf,cc in mTEPES.psnla if (ni,nf,cc) not in mTEPES.lc and mTEPES.pElecNetPeriodIni [ni,nf,cc] > p)
|
|
2315
2404
|
|
|
2316
2405
|
[OptModel.vLineLosses [p,sc,n,ni,nf,cc].fix(0.0) for p,sc,n,ni,nf,cc in mTEPES.psnll if (ni,nf,cc) not in mTEPES.lc and mTEPES.pElecNetPeriodIni [ni,nf,cc] > p]
|
|
2317
|
-
nFixedVariables += sum(
|
|
2406
|
+
nFixedVariables += sum( 1 for p,sc,n,ni,nf,cc in mTEPES.psnll if (ni,nf,cc) not in mTEPES.lc and mTEPES.pElecNetPeriodIni [ni,nf,cc] > p)
|
|
2318
2407
|
|
|
2319
2408
|
if mTEPES.pIndHydrogen == 1:
|
|
2320
|
-
[OptModel.vFlowH2 [p,sc,n,ni,nf,cc].fix(0.0) for p,sc,n,ni,nf,cc in mTEPES.psnpa if (ni,nf,cc) not in mTEPES.pc and mTEPES.pH2PipePeriodIni[ni,nf,cc] > p]
|
|
2321
|
-
nFixedVariables += sum(
|
|
2409
|
+
[OptModel.vFlowH2 [p,sc,n,ni,nf,cc].fix(0.0) for p,sc,n,ni,nf,cc in mTEPES.psnpa if (ni,nf,cc) not in mTEPES.pc and mTEPES.pH2PipePeriodIni [ni,nf,cc] > p]
|
|
2410
|
+
nFixedVariables += sum( 4 for p,sc,n,ni,nf,cc in mTEPES.psnpa if (ni,nf,cc) not in mTEPES.pc and mTEPES.pH2PipePeriodIni [ni,nf,cc] > p)
|
|
2322
2411
|
|
|
2323
2412
|
if mTEPES.pIndHeat == 1:
|
|
2324
2413
|
[OptModel.vFlowHeat[p,sc,n,ni,nf,cc].fix(0.0) for p,sc,n,ni,nf,cc in mTEPES.psnha if (ni,nf,cc) not in mTEPES.hc and mTEPES.pHeatPipePeriodIni[ni,nf,cc] > p]
|
|
2325
|
-
nFixedVariables += sum(
|
|
2414
|
+
nFixedVariables += sum( 4 for p,sc,n,ni,nf,cc in mTEPES.psnha if (ni,nf,cc) not in mTEPES.hc and mTEPES.pHeatPipePeriodIni[ni,nf,cc] > p)
|
|
2326
2415
|
|
|
2327
2416
|
# tolerance to consider 0 an investment decision
|
|
2328
2417
|
pEpsilon = 1e-4
|
|
@@ -2330,7 +2419,7 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
2330
2419
|
'''
|
|
2331
2420
|
Set small numbers to 0.
|
|
2332
2421
|
|
|
2333
|
-
This function takes
|
|
2422
|
+
This function takes an mTEPES instance and sets values under a certain threshold to be 0.
|
|
2334
2423
|
|
|
2335
2424
|
Parameters:
|
|
2336
2425
|
mTEPES: The instance of mTEPES.
|
|
@@ -2488,7 +2577,65 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
2488
2577
|
|
|
2489
2578
|
DetectInfeasibilities(mTEPES)
|
|
2490
2579
|
|
|
2491
|
-
mTEPES.nFixedVariables
|
|
2580
|
+
mTEPES.nFixedVariables = Param(initialize=round(nFixedVariables), within=NonNegativeIntegers, doc='Number of fixed variables')
|
|
2581
|
+
|
|
2582
|
+
mTEPES.IndependentPeriods = Param( domain=Boolean, initialize=False, mutable=True)
|
|
2583
|
+
mTEPES.IndependentStages = Param(mTEPES.pp, domain=Boolean, initialize=False, mutable=True)
|
|
2584
|
+
mTEPES.IndependentStages2 = Param( domain=Boolean, initialize=False, mutable=True)
|
|
2585
|
+
mTEPES.Parallel = Param( domain=Boolean, initialize=False, mutable=True)
|
|
2586
|
+
mTEPES.Parallel = True
|
|
2587
|
+
if ( (len(mTEPES.gc) == 0 or mTEPES.pIndBinGenInvest() == 2) # No candidates
|
|
2588
|
+
and (len(mTEPES.gd) == 0 or mTEPES.pIndBinGenRetire() == 2) # No retirements
|
|
2589
|
+
and (len(mTEPES.lc) == 0 or mTEPES.pIndBinNetElecInvest() == 2)): # No line candidates
|
|
2590
|
+
# Periods and scenarios are independent each other
|
|
2591
|
+
ScIndep = True
|
|
2592
|
+
mTEPES.IndependentPeriods = True
|
|
2593
|
+
for p in mTEPES.p:
|
|
2594
|
+
if ( (min([mTEPES.pEmission[p, ar] for ar in mTEPES.ar]) == math.inf or sum(mTEPES.pEmissionRate[nr] for nr in mTEPES.nr) == 0) # No emissions
|
|
2595
|
+
and (max([mTEPES.pRESEnergy[p, ar] for ar in mTEPES.ar]) == 0)): # No minimum RES requirements
|
|
2596
|
+
# Stages are independent from each other
|
|
2597
|
+
StIndep = True
|
|
2598
|
+
mTEPES.IndependentStages[p] = True
|
|
2599
|
+
if all(mTEPES.IndependentStages[p]() for p in mTEPES.pp):
|
|
2600
|
+
mTEPES.IndependentStages2 = True
|
|
2601
|
+
|
|
2602
|
+
mTEPES.Period = Block(mTEPES.p)
|
|
2603
|
+
for p in mTEPES.Period:
|
|
2604
|
+
Period = mTEPES.Period[p]
|
|
2605
|
+
#TODO: Filter in some way that scenarios may not belong to periods
|
|
2606
|
+
# period2scenario = [stt for pp, scc, stt, nn in mTEPES.s2n if scc == sc and pp == p]
|
|
2607
|
+
Period.Scenario = Block(mTEPES.sc)
|
|
2608
|
+
Period.n = Set(doc='load levels', initialize=[nn for pp, scc, stt, nn in mTEPES.s2n if pp == p])
|
|
2609
|
+
for sc in Period.Scenario:
|
|
2610
|
+
Scenario = Period.Scenario[sc]
|
|
2611
|
+
Scenario.Stage = Block(Set(initialize=[stt for pp,scc,stt, nn in mTEPES.s2n if scc == sc and pp == p]))
|
|
2612
|
+
Scenario.n = Set(doc='load levels', initialize=[nn for pp, scc, stt, nn in mTEPES.s2n if scc == sc and pp == p])
|
|
2613
|
+
|
|
2614
|
+
# iterative model formulation for each stage of a year
|
|
2615
|
+
for st in Scenario.Stage:
|
|
2616
|
+
Stage = Scenario.Stage[st]
|
|
2617
|
+
Stage.n = Set(doc='load levels', initialize=[nn for pp, scc, stt, nn in mTEPES.s2n if stt == st and scc == sc and pp == p])
|
|
2618
|
+
Stage.n2 = Set(doc='load levels', initialize=[nn for pp, scc, stt, nn in mTEPES.s2n if stt == st and scc == sc and pp == p])
|
|
2619
|
+
|
|
2620
|
+
# load levels multiple of cycles for each ESS/generator
|
|
2621
|
+
Stage.nesc = [(n, es) for n, es in Stage.n * mTEPES.es if Stage.n.ord(n) % mTEPES.pStorageTimeStep[es] == 0]
|
|
2622
|
+
Stage.necc = [(n, ec) for n, ec in Stage.n * mTEPES.ec if Stage.n.ord(n) % mTEPES.pStorageTimeStep[ec] == 0]
|
|
2623
|
+
Stage.neso = [(n, es) for n, es in Stage.n * mTEPES.es if Stage.n.ord(n) % mTEPES.pOutflowsTimeStep[es] == 0]
|
|
2624
|
+
Stage.ngen = [(n, g ) for n, g in Stage.n * mTEPES.g if Stage.n.ord(n) % mTEPES.pEnergyTimeStep[g] == 0]
|
|
2625
|
+
|
|
2626
|
+
if mTEPES.pIndHydroTopology == 1:
|
|
2627
|
+
Stage.nhc = [(n,h ) for n,h in Stage.n*mTEPES.h if Stage.n.ord(n) % sum(mTEPES.pReservoirTimeStep[rs] for rs in mTEPES.rs if (rs,h) in mTEPES.r2h) == 0]
|
|
2628
|
+
if sum(1 for h,rs in mTEPES.p2r):
|
|
2629
|
+
Stage.np2c = [(n,h ) for n,h in Stage.n*mTEPES.h if sum(1 for rs in mTEPES.rs if (h,rs) in mTEPES.p2r) and Stage.n.ord(n) % sum(mTEPES.pReservoirTimeStep[rs] for rs in mTEPES.rs if (h,rs) in mTEPES.p2r) == 0]
|
|
2630
|
+
else:
|
|
2631
|
+
Stage.np2c = []
|
|
2632
|
+
if sum(1 for rs,h in mTEPES.r2p):
|
|
2633
|
+
Stage.npc = [(n,h ) for n,h in mTEPES.n*mTEPES.h if sum(1 for rs in mTEPES.rs if (rs,h) in mTEPES.r2p) and mTEPES.n.ord(n) % sum(mTEPES.pReservoirTimeStep[rs] for rs in mTEPES.rs if (rs,h) in mTEPES.r2p) == 0]
|
|
2634
|
+
else:
|
|
2635
|
+
Stage.npc = []
|
|
2636
|
+
Stage.nrsc = [(n,rs) for n,rs in Stage.n*mTEPES.rs if mTEPES.n.ord(n) % mTEPES.pReservoirTimeStep[rs] == 0]
|
|
2637
|
+
Stage.nrcc = [(n,rs) for n,rs in Stage.n*mTEPES.rn if mTEPES.n.ord(n) % mTEPES.pReservoirTimeStep[rs] == 0]
|
|
2638
|
+
Stage.nrso = [(n,rs) for n,rs in Stage.n*mTEPES.rs if mTEPES.n.ord(n) % mTEPES.pWaterOutTimeStep [rs] == 0]
|
|
2492
2639
|
|
|
2493
2640
|
SettingUpVariablesTime = time.time() - StartTime
|
|
2494
2641
|
print('Setting up variables ... ', round(SettingUpVariablesTime), 's')
|