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.
Files changed (75) hide show
  1. openTEPES/9n_PTDF/oT_Data_Demand_9n_PTDF.csv +8737 -0
  2. openTEPES/9n_PTDF/oT_Data_Duration_9n_PTDF.csv +8737 -0
  3. openTEPES/9n_PTDF/oT_Data_Emission_9n_PTDF.csv +2 -0
  4. openTEPES/9n_PTDF/oT_Data_EnergyInflows_9n_PTDF.csv +8737 -0
  5. openTEPES/9n_PTDF/oT_Data_EnergyOutflows_9n_PTDF.csv +8737 -0
  6. openTEPES/9n_PTDF/oT_Data_Generation_9n_PTDF.csv +17 -0
  7. openTEPES/9n_PTDF/oT_Data_Inertia_9n_PTDF.csv +8737 -0
  8. openTEPES/9n_PTDF/oT_Data_Network_9n_PTDF.csv +14 -0
  9. openTEPES/9n_PTDF/oT_Data_NodeLocation_9n_PTDF.csv +10 -0
  10. openTEPES/9n_PTDF/oT_Data_OperatingReserveDown_9n_PTDF.csv +8737 -0
  11. openTEPES/9n_PTDF/oT_Data_OperatingReserveUp_9n_PTDF.csv +8737 -0
  12. openTEPES/9n_PTDF/oT_Data_Option_9n_PTDF.csv +2 -0
  13. openTEPES/9n_PTDF/oT_Data_Parameter_9n_PTDF.csv +2 -0
  14. openTEPES/9n_PTDF/oT_Data_Period_9n_PTDF.csv +2 -0
  15. openTEPES/9n_PTDF/oT_Data_RESEnergy_9n_PTDF.csv +2 -0
  16. openTEPES/9n_PTDF/oT_Data_ReserveMargin_9n_PTDF.csv +2 -0
  17. openTEPES/9n_PTDF/oT_Data_Scenario_9n_PTDF.csv +2 -0
  18. openTEPES/9n_PTDF/oT_Data_Stage_9n_PTDF.csv +2 -0
  19. openTEPES/9n_PTDF/oT_Data_VariableEmissionCost_9n_PTDF.csv +8737 -0
  20. openTEPES/9n_PTDF/oT_Data_VariableFuelCost_9n_PTDF.csv +8737 -0
  21. openTEPES/9n_PTDF/oT_Data_VariableMaxConsumption_9n_PTDF.csv +8737 -0
  22. openTEPES/9n_PTDF/oT_Data_VariableMaxEnergy_9n_PTDF.csv +8737 -0
  23. openTEPES/9n_PTDF/oT_Data_VariableMaxGeneration_9n_PTDF.csv +8737 -0
  24. openTEPES/9n_PTDF/oT_Data_VariableMaxStorage_9n_PTDF.csv +8737 -0
  25. openTEPES/9n_PTDF/oT_Data_VariableMinConsumption_9n_PTDF.csv +8737 -0
  26. openTEPES/9n_PTDF/oT_Data_VariableMinEnergy_9n_PTDF.csv +8737 -0
  27. openTEPES/9n_PTDF/oT_Data_VariableMinGeneration_9n_PTDF.csv +8737 -0
  28. openTEPES/9n_PTDF/oT_Data_VariableMinStorage_9n_PTDF.csv +8737 -0
  29. openTEPES/9n_PTDF/oT_Data_VariablePTDF_9n_PTDF.csv +8740 -0
  30. openTEPES/9n_PTDF/oT_Data_VariableTTCBck_9n_PTDF.csv +8739 -0
  31. openTEPES/9n_PTDF/oT_Data_VariableTTCFrw_9n_PTDF.csv +8739 -0
  32. openTEPES/9n_PTDF/oT_Dict_AreaToRegion_9n_PTDF.csv +2 -0
  33. openTEPES/9n_PTDF/oT_Dict_Area_9n_PTDF.csv +2 -0
  34. openTEPES/9n_PTDF/oT_Dict_Circuit_9n_PTDF.csv +3 -0
  35. openTEPES/9n_PTDF/oT_Dict_Generation_9n_PTDF.csv +17 -0
  36. openTEPES/9n_PTDF/oT_Dict_Line_9n_PTDF.csv +3 -0
  37. openTEPES/9n_PTDF/oT_Dict_LoadLevel_9n_PTDF.csv +8737 -0
  38. openTEPES/9n_PTDF/oT_Dict_NodeToZone_9n_PTDF.csv +10 -0
  39. openTEPES/9n_PTDF/oT_Dict_Node_9n_PTDF.csv +10 -0
  40. openTEPES/9n_PTDF/oT_Dict_Period_9n_PTDF.csv +2 -0
  41. openTEPES/9n_PTDF/oT_Dict_Region_9n_PTDF.csv +31 -0
  42. openTEPES/9n_PTDF/oT_Dict_Scenario_9n_PTDF.csv +2 -0
  43. openTEPES/9n_PTDF/oT_Dict_Stage_9n_PTDF.csv +2 -0
  44. openTEPES/9n_PTDF/oT_Dict_Storage_9n_PTDF.csv +3 -0
  45. openTEPES/9n_PTDF/oT_Dict_Technology_9n_PTDF.csv +7 -0
  46. openTEPES/9n_PTDF/oT_Dict_ZoneToArea_9n_PTDF.csv +10 -0
  47. openTEPES/9n_PTDF/oT_Dict_Zone_9n_PTDF.csv +10 -0
  48. openTEPES/RTS-GMLC/oT_Data_VariableMinGeneration_RTS-GMLC.csv +1 -1
  49. openTEPES/RTS-GMLC_6y/oT_Data_VariableFuelCost_RTS-GMLC_6y.csv +1 -1
  50. openTEPES/RTS-GMLC_6y/oT_Dict_AreaToRegion_RTS-GMLC_6y.csv +4 -4
  51. openTEPES/RTS-GMLC_6y/oT_Dict_Area_RTS-GMLC_6y.csv +4 -4
  52. openTEPES/RTS-GMLC_6y/oT_Dict_Circuit_RTS-GMLC_6y.csv +5 -5
  53. openTEPES/RTS-GMLC_6y/oT_Dict_Line_RTS-GMLC_6y.csv +3 -3
  54. openTEPES/RTS-GMLC_6y/oT_Dict_NodeToZone_RTS-GMLC_6y.csv +74 -74
  55. openTEPES/RTS-GMLC_6y/oT_Dict_Region_RTS-GMLC_6y.csv +2 -2
  56. openTEPES/RTS-GMLC_6y/oT_Dict_Scenario_RTS-GMLC_6y.csv +2 -2
  57. openTEPES/RTS-GMLC_6y/oT_Dict_Storage_RTS-GMLC_6y.csv +3 -3
  58. openTEPES/RTS-GMLC_6y/oT_Dict_Technology_RTS-GMLC_6y.csv +10 -10
  59. openTEPES/RTS-GMLC_6y/oT_Dict_ZoneToArea_RTS-GMLC_6y.csv +22 -22
  60. openTEPES/RTS-GMLC_6y/oT_Dict_Zone_RTS-GMLC_6y.csv +22 -22
  61. openTEPES/__init__.py +1 -1
  62. openTEPES/openTEPES.py +26 -17
  63. openTEPES/openTEPES_InputData.py +1335 -1188
  64. openTEPES/openTEPES_Main.py +3 -3
  65. openTEPES/openTEPES_ModelFormulation.py +413 -156
  66. openTEPES/openTEPES_OutputResults.py +263 -206
  67. openTEPES/openTEPES_ProblemSolving.py +35 -28
  68. openTEPES/sSEP/oT_Data_DemandHydrogen_sSEP.csv +8736 -8736
  69. openTEPES/sSEP/oT_Data_Generation_sSEP.csv +1 -1
  70. openTEPES/sSEP/oT_Data_HydroOutflows_sSEP.csv +1 -1
  71. {opentepes-4.18.4.dist-info → opentepes-4.18.6.dist-info}/METADATA +65 -46
  72. {opentepes-4.18.4.dist-info → opentepes-4.18.6.dist-info}/RECORD +75 -28
  73. {opentepes-4.18.4.dist-info → opentepes-4.18.6.dist-info}/WHEEL +1 -1
  74. {opentepes-4.18.4.dist-info → opentepes-4.18.6.dist-info}/entry_points.txt +0 -0
  75. {opentepes-4.18.4.dist-info → opentepes-4.18.6.dist-info/licenses}/LICENSE +0 -0
@@ -1,5 +1,5 @@
1
1
  """
2
- Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - April 03, 2025
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
- #%% reading data from CSV
20
- dfOption = pd.read_csv(f'{_path}/oT_Data_Option_' f'{CaseName}.csv', header=0 )
21
- dfParameter = pd.read_csv(f'{_path}/oT_Data_Parameter_' f'{CaseName}.csv', header=0 )
22
- dfPeriod = pd.read_csv(f'{_path}/oT_Data_Period_' f'{CaseName}.csv', header=0, index_col=[0 ])
23
- dfScenario = pd.read_csv(f'{_path}/oT_Data_Scenario_' f'{CaseName}.csv', header=0, index_col=[0,1 ])
24
- dfStage = pd.read_csv(f'{_path}/oT_Data_Stage_' f'{CaseName}.csv', header=0, index_col=[0 ])
25
- dfDuration = pd.read_csv(f'{_path}/oT_Data_Duration_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
26
- dfReserveMargin = pd.read_csv(f'{_path}/oT_Data_ReserveMargin_' f'{CaseName}.csv', header=0, index_col=[0,1 ])
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
- try:
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
- try:
61
- dfDemandHydrogen = pd.read_csv(f'{_path}/oT_Data_DemandHydrogen_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
62
- dfNetworkHydrogen = pd.read_csv(f'{_path}/oT_Data_NetworkHydrogen_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
63
- pIndHydrogen = 1
64
- except:
65
- pIndHydrogen = 0
66
- print('**** No hydrogen energy carrier')
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
- try:
69
- dfDemandHeat = pd.read_csv(f'{_path}/oT_Data_DemandHeat_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
70
- dfReserveMarginHeat = pd.read_csv(f'{_path}/oT_Data_ReserveMarginHeat_' f'{CaseName}.csv', header=0, index_col=[0,1 ])
71
- dfNetworkHeat = pd.read_csv(f'{_path}/oT_Data_NetworkHeat_' f'{CaseName}.csv', header=0, index_col=[0,1,2])
72
- pIndHeat = 1
73
- except:
74
- pIndHeat = 0
75
- print('**** No heat energy carrier')
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
- dfOption.fillna (0 , inplace=True)
79
- dfParameter.fillna (0.0, inplace=True)
80
- dfPeriod.fillna (0.0, inplace=True)
81
- dfScenario.fillna (0.0, inplace=True)
82
- dfStage.fillna (0.0, inplace=True)
83
- dfDuration.fillna (0 , inplace=True)
84
- dfReserveMargin.fillna (0.0, inplace=True)
85
- dfEmission.fillna (math.inf , inplace=True)
86
- dfRESEnergy.fillna (0.0, inplace=True)
87
- dfDemand.fillna (0.0, inplace=True)
88
- dfInertia.fillna (0.0, inplace=True)
89
- dfUpOperatingReserve.fillna (0.0, inplace=True)
90
- dfDwOperatingReserve.fillna (0.0, inplace=True)
91
- dfGeneration.fillna (0.0, inplace=True)
92
- dfVariableMinPower.fillna (0.0, inplace=True)
93
- dfVariableMaxPower.fillna (0.0, inplace=True)
94
- dfVariableMinCharge.fillna (0.0, inplace=True)
95
- dfVariableMaxCharge.fillna (0.0, inplace=True)
96
- dfVariableMinStorage.fillna (0.0, inplace=True)
97
- dfVariableMaxStorage.fillna (0.0, inplace=True)
98
- dfVariableMinEnergy.fillna (0.0, inplace=True)
99
- dfVariableMaxEnergy.fillna (0.0, inplace=True)
100
- dfVariableFuelCost.fillna (0.0, inplace=True)
101
- dfVariableEmissionCost.fillna (0.0, inplace=True)
102
- dfEnergyInflows.fillna (0.0, inplace=True)
103
- dfEnergyOutflows.fillna (0.0, inplace=True)
104
- dfNodeLocation.fillna (0.0, inplace=True)
105
- dfNetwork.fillna (0.0, inplace=True)
106
-
107
- if pIndHydroTopology == 1:
108
- dfReservoir.fillna (0.0, inplace=True)
109
- dfVariableMinVolume.fillna(0.0, inplace=True)
110
- dfVariableMaxVolume.fillna(0.0, inplace=True)
111
- dfHydroInflows.fillna (0.0, inplace=True)
112
- dfHydroOutflows.fillna (0.0, inplace=True)
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
- #%% reading the sets
189
- dictSets = DataPortal()
190
- dictSets.load(filename=f'{_path}/oT_Dict_Period_' f'{CaseName}.csv', set='p' , format='set')
191
- dictSets.load(filename=f'{_path}/oT_Dict_Scenario_' f'{CaseName}.csv', set='sc' , format='set')
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
- #%% parameters
270
- pIndBinGenInvest = dfOption ['IndBinGenInvest' ].iloc[0].astype('int') # Indicator of binary generation expansion decisions, 0 continuous - 1 binary - 2 no investment variables
271
- pIndBinGenRetire = dfOption ['IndBinGenRetirement'].iloc[0].astype('int') # Indicator of binary generation retirement decisions,0 continuous - 1 binary - 2 no retirement variables
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
- if pIndHydroTopology == 1:
365
- pVariableMinVolume = ProcessParameter(pVariableMinVolume, pTimeStep)
366
- pVariableMaxVolume = ProcessParameter(pVariableMaxVolume, pTimeStep)
367
- pHydroInflows = ProcessParameter(pHydroInflows, pTimeStep)
368
- pHydroOutflows = ProcessParameter(pHydroOutflows, pTimeStep)
369
-
370
- if pIndHydrogen == 1:
371
- pDemandH2 = ProcessParameter(pDemandH2, pTimeStep)
372
-
373
- if pIndHeat == 1:
374
- pDemandHeat = ProcessParameter(pDemandHeat, pTimeStep)
375
-
376
- # assign duration 0 to load levels not being considered, active load levels are at the end of every pTimeStep
377
- for n in range(pTimeStep-2,-1,-1):
378
- pDuration.iloc[[range(n,len(mTEPES.pp)*len(mTEPES.scc)*len(mTEPES.nn),pTimeStep)]] = 0
379
-
380
- for psn in pDuration.index:
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' ] # generator location in node
389
- pGenToTechnology = dfGeneration ['Technology' ] # generator association to technology
390
- pGenToExclusiveGen = dfGeneration ['MutuallyExclusive' ] # mutually exclusive generator
391
- pIndBinUnitInvest = dfGeneration ['BinaryInvestment' ] # binary unit investment decision [Yes]
392
- pIndBinUnitRetire = dfGeneration ['BinaryRetirement' ] # binary unit retirement decision [Yes]
393
- pIndBinUnitCommit = dfGeneration ['BinaryCommitment' ] # binary unit commitment decision [Yes]
394
- pIndBinStorInvest = dfGeneration ['StorageInvestment' ] # storage linked to generation investment [Yes]
395
- pIndOperReserve = dfGeneration ['NoOperatingReserve' ] # no contribution to operating reserve [Yes]
396
- pIndOutflowIncomp = dfGeneration ['OutflowsIncompatibility' ] # outflows incompatibility with charging
397
- pMustRun = dfGeneration ['MustRun' ] # must-run unit [Yes]
398
- pInertia = dfGeneration ['Inertia' ] # inertia constant [s]
399
- pElecGenPeriodIni = dfGeneration ['InitialPeriod' ] # initial period [year]
400
- pElecGenPeriodFin = dfGeneration ['FinalPeriod' ] # final period [year]
401
- pAvailability = dfGeneration ['Availability' ] # unit availability for adequacy [p.u.]
402
- pEFOR = dfGeneration ['EFOR' ] # EFOR [p.u.]
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 # O&M term variable cost [MEUR/GWh]
410
- pOperReserveCost = dfGeneration ['OperReserveCost' ] * 1e-3 # operating reserve cost [MEUR/GW]
411
- pStartUpCost = dfGeneration ['StartUpCost' ] # startup cost [MEUR]
412
- pShutDownCost = dfGeneration ['ShutDownCost' ] # shutdown cost [MEUR]
413
- pRampUp = dfGeneration ['RampUp' ] * 1e-3 # ramp up rate [GW/h]
414
- pRampDw = dfGeneration ['RampDown' ] * 1e-3 # ramp down rate [GW/h]
415
- pEmissionCost = dfGeneration ['CO2EmissionRate' ] * 1e-3 * pCO2Cost # CO2 emission cost [MEUR/GWh]
416
- pEmissionRate = dfGeneration ['CO2EmissionRate' ] # CO2 emission rate [tCO2/MWh]
417
- pUpTime = dfGeneration ['UpTime' ] # minimum up time [h]
418
- pDwTime = dfGeneration ['DownTime' ] # minimum down time [h]
419
- pStableTime = dfGeneration ['StableTime' ] # minimum stable time [h]
420
- pShiftTime = dfGeneration ['ShiftTime' ] # maximum shift time for DSM [h]
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 # rated minimum ESS charge [GW]
424
- pRatedMaxCharge = dfGeneration ['MaximumCharge' ] * 1e-3 # rated maximum ESS charge [GW]
425
- pRatedMinStorage = dfGeneration ['MinimumStorage' ] # rated minimum ESS storage [GWh]
426
- pRatedMaxStorage = dfGeneration ['MaximumStorage' ] # rated maximum ESS storage [GWh]
427
- pInitialInventory = dfGeneration ['InitialStorage' ] # initial ESS storage [GWh]
428
- pProductionFunctionHydro = dfGeneration ['ProductionFunctionHydro' ] # production function of a hydropower plant [kWh/m3]
429
- pProductionFunctionH2 = dfGeneration ['ProductionFunctionH2' ] * 1e-3 # production function of an electrolyzer [kWh/gH2]
430
- pProductionFunctionHeat = dfGeneration ['ProductionFunctionHeat' ] # production function of a heat pump [kWh/kWh]
431
- pProductionFunctionH2ToHeat = dfGeneration ['ProductionFunctionH2ToHeat'] * 1e-3 # production function of a boiler using H2 [gH2/kWh]
432
- pEfficiency = dfGeneration ['Efficiency' ] # ESS round-trip efficiency [p.u.]
433
- pStorageType = dfGeneration ['StorageType' ] # ESS storage type
434
- pOutflowsType = dfGeneration ['OutflowsType' ] # ESS outflows type
435
- pEnergyType = dfGeneration ['EnergyType' ] # unit energy type
436
- pRMaxReactivePower = dfGeneration ['MaximumReactivePower' ] * 1e-3 # rated maximum reactive power [Gvar]
437
- pGenLoInvest = dfGeneration ['InvestmentLo' ] # Lower bound of the investment decision [p.u.]
438
- pGenUpInvest = dfGeneration ['InvestmentUp' ] # Upper bound of the investment decision [p.u.]
439
- pGenLoRetire = dfGeneration ['RetirementLo' ] # Lower bound of the retirement decision [p.u.]
440
- pGenUpRetire = dfGeneration ['RetirementUp' ] # Upper bound of the retirement decision [p.u.]
441
-
442
- pRatedLinearOperCost = pRatedLinearFuelCost + pEmissionCost
443
- pRatedLinearVarCost = pRatedLinearFuelCost + pLinearOMCost
444
-
445
- if pIndHydroTopology == 1:
446
- pReservoirType = dfReservoir ['StorageType' ] # reservoir type
447
- pWaterOutfType = dfReservoir ['OutflowsType' ] # water outflow type
448
- pRatedMinVolume = dfReservoir ['MinimumStorage' ] # rated minimum reservoir volume [hm3]
449
- pRatedMaxVolume = dfReservoir ['MaximumStorage' ] # rated maximum reservoir volume [hm3]
450
- pInitialVolume = dfReservoir ['InitialStorage' ] # initial reservoir volume [hm3]
451
- pIndBinRsrvInvest = dfReservoir ['BinaryInvestment' ] # binary reservoir investment decision [Yes]
452
- pRsrInvestCost = dfReservoir ['FixedInvestmentCost' ] * dfReservoir['FixedChargeRate'] # reservoir fixed cost [MEUR]
453
- pRsrPeriodIni = dfReservoir ['InitialPeriod' ] # initial period [year]
454
- pRsrPeriodFin = dfReservoir ['FinalPeriod' ] # final period [year]
455
-
456
- pNodeLat = dfNodeLocation['Latitude' ] # node latitude [º]
457
- pNodeLon = dfNodeLocation['Longitude' ] # node longitude [º]
458
-
459
- pLineType = dfNetwork ['LineType' ] # electric line type
460
- pLineLength = dfNetwork ['Length' ] # electric line length [km]
461
- pLineVoltage = dfNetwork ['Voltage' ] # electric line voltage [kV]
462
- pElecNetPeriodIni = dfNetwork ['InitialPeriod' ] # initial period
463
- pElecNetPeriodFin = dfNetwork ['FinalPeriod' ] # final period
464
- pLineLossFactor = dfNetwork ['LossFactor' ] # electric line loss factor [p.u.]
465
- pLineR = dfNetwork ['Resistance' ] # electric line resistance [p.u.]
466
- pLineX = dfNetwork ['Reactance' ].sort_index() # electric line reactance [p.u.]
467
- pLineBsh = dfNetwork ['Susceptance' ] # electric line susceptance [p.u.]
468
- pLineTAP = dfNetwork ['Tap' ] # tap changer [p.u.]
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' ] # binary electric line switching decision [Yes]
473
- pIndBinLineInvest = dfNetwork ['BinaryInvestment' ] # binary electric line investment decision [Yes]
474
- pSwitchOnTime = dfNetwork ['SwOnTime' ].astype('int') # minimum on time [h]
475
- pSwitchOffTime = dfNetwork ['SwOffTime' ].astype('int') # minimum off time [h]
476
- pAngMin = dfNetwork ['AngMin' ] * math.pi / 180 # Min phase angle difference [rad]
477
- pAngMax = dfNetwork ['AngMax' ] * math.pi / 180 # Max phase angle difference [rad]
478
- pNetLoInvest = dfNetwork ['InvestmentLo' ] # Lower bound of the investment decision [p.u.]
479
- pNetUpInvest = dfNetwork ['InvestmentUp' ] # Upper bound of the investment decision [p.u.]
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' ] # hydrogen line length [km]
503
- pH2PipePeriodIni = dfNetworkHydrogen['InitialPeriod' ] # initial period
504
- pH2PipePeriodFin = dfNetworkHydrogen['FinalPeriod' ] # final period
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' ] # binary hydrogen pipeline investment decision [Yes]
509
- pH2PipeLoInvest = dfNetworkHydrogen['InvestmentLo' ] # Lower bound of the investment decision [p.u.]
510
- pH2PipeUpInvest = dfNetworkHydrogen['InvestmentUp' ] # Upper bound of the investment decision [p.u.]
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 = pH2PipeNTCBck.where (pH2PipeNTCBck > 0.0, pH2PipeNTCFrw)
460
+ par['pH2PipeNTCBck'] = par['pH2PipeNTCBck'].where (par['pH2PipeNTCBck'] > 0.0, par['pH2PipeNTCFrw'])
515
461
  # replace pH2PipeNTCFrw = 0.0 by pH2PipeNTCBck
516
- pH2PipeNTCFrw = pH2PipeNTCFrw.where (pH2PipeNTCFrw > 0.0, pH2PipeNTCBck)
462
+ par['pH2PipeNTCFrw'] = par['pH2PipeNTCFrw'].where (par['pH2PipeNTCFrw'] > 0.0, par['pH2PipeNTCBck'])
517
463
  # replace pH2PipeUpInvest = 0.0 by 1.0
518
- pH2PipeUpInvest = pH2PipeUpInvest.where(pH2PipeUpInvest > 0.0, 1.0 )
519
-
520
- if pIndHeat == 1:
521
- pHeatPipeLength = dfNetworkHeat['Length' ] # heat pipe length [km]
522
- pHeatPipePeriodIni = dfNetworkHeat['InitialPeriod' ] # initial period
523
- pHeatPipePeriodFin = dfNetworkHeat['FinalPeriod' ] # final period
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' ] # binary heat pipe investment decision [Yes]
528
- pHeatPipeLoInvest = dfNetworkHeat['InvestmentLo' ] # Lower bound of the investment decision [p.u.]
529
- pHeatPipeUpInvest = dfNetworkHeat['InvestmentUp' ] # Upper bound of the investment decision [p.u.]
530
-
531
- pHeatPipePeriodFin = pHeatPipePeriodFin.where(pHeatPipePeriodFin != 0.0, 3000 )
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 = pHeatPipeNTCBck.where (pHeatPipeNTCBck > 0.0, pHeatPipeNTCFrw)
479
+ par['pHeatPipeNTCBck'] = par['pHeatPipeNTCBck'].where (par['pHeatPipeNTCBck'] > 0.0, par['pHeatPipeNTCFrw'])
534
480
  # replace pHeatPipeNTCFrw = 0.0 by pHeatPipeNTCBck
535
- pHeatPipeNTCFrw = pHeatPipeNTCFrw.where (pHeatPipeNTCFrw > 0.0, pHeatPipeNTCBck)
481
+ par['pHeatPipeNTCFrw'] = par['pHeatPipeNTCFrw'].where (par['pHeatPipeNTCFrw'] > 0.0, par['pHeatPipeNTCBck'])
536
482
  # replace pHeatPipeUpInvest = 0.0 by 1.0
537
- pHeatPipeUpInvest = pHeatPipeUpInvest.where(pHeatPipeUpInvest > 0.0, 1.0 )
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 or pRatedMaxPowerHeat [gg] > 0.0) and pElecGenPeriodIni[gg] <= mTEPES.p.last() and pElecGenPeriodFin[gg] >= mTEPES.p.first() and pGenToNode.reset_index().set_index(['Generator']).isin(mTEPES.nd)['Node'][gg]]) # excludes generators with empty node
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 ] == 0.0 and pProductionFunctionHydro[g ] == 0.0])
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 ] > 0.0) and pProductionFunctionHydro[g ] == 0.0])
559
- mTEPES.h = Set(doc='hydro units' , initialize=[g for g in mTEPES.g if pProductionFunctionH2[g ] == 0.0 and pProductionFunctionHeat[g ] == 0.0 and pProductionFunctionHydro[g ] > 0.0])
560
- mTEPES.el = Set(doc='electrolyzer units' , initialize=[es for es in mTEPES.es if pProductionFunctionH2[es] > 0.0 and pProductionFunctionHeat[es] == 0.0 and pProductionFunctionHydro[es] == 0.0])
561
- mTEPES.hp = Set(doc='heat pump & elec boiler units' , initialize=[es for es in mTEPES.es if pProductionFunctionH2[es] == 0.0 and pProductionFunctionHeat[es] > 0.0 and pProductionFunctionHydro[es] == 0.0])
562
- mTEPES.ch = Set(doc='CHP & fuel boiler units' , initialize=[g for g in mTEPES.g if pRatedMaxPowerHeat[g ] > 0.0 and pProductionFunctionHeat [g ] == 0.0])
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 if pProductionFunctionH2ToHeat[bo] > 0.0])
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 pElecGenPeriodIni[gg] <= mTEPES.p.last() and pElecGenPeriodFin[gg] >= mTEPES.p.first()])
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 if pRsrInvestCost [rs] > 0.0 and pRsrPeriodIni[rs] <= mTEPES.p.last() and pRsrPeriodFin[rs] >= mTEPES.p.first()])
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 if pH2PipeNTCFrw [pn] > 0.0 and pH2PipeNTCBck[pn] > 0.0 and pH2PipePeriodIni[pn] <= mTEPES.p.last() and pH2PipePeriodFin[pn] >= mTEPES.p.first()])
593
- mTEPES.pc = Set(doc='candidate hydrogen pipes' , initialize=[pa for pa in mTEPES.pa if pH2PipeFixedCost [pa] > 0.0])
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 a mTEPES instance and adds instrumental sets which will be used later.
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 if (p,ni,nf,cc) in mTEPES.pla])
707
- 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])
708
- 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])
709
- 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])
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
- if pIndHydroTopology == 1:
776
- pIndBinRsrvInvest = pIndBinRsrvInvest.map (idxDict)
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 pIndHydrogen == 1:
779
- pIndBinH2PipeInvest = pIndBinH2PipeInvest.map (idxDict)
760
+ if mTEPES.dPar['pIndHydroTopology'] == 1:
761
+ mTEPES.dPar['pIndBinRsrvInvest'] = mTEPES.dPar['pIndBinRsrvInvest'].map (idxDict)
780
762
 
781
- if pIndHeat == 1:
782
- pIndBinHeatPipeInvest = pIndBinHeatPipeInvest.map(idxDict)
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 and not pLineType[le] == 'DC'])
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 and pLineType[le] == 'DC'])
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 pAnnualDiscRate == 0.0:
804
- pDiscountedWeight = pd.Series([ pPeriodWeight[p] for p in mTEPES.p], index=mTEPES.p)
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+pAnnualDiscRate)**pPeriodWeight[p]-1.0) / (pAnnualDiscRate*(1.0+pAnnualDiscRate)**(pPeriodWeight[p]-1+p-pEconomicBaseYear)) for p in mTEPES.p], index=mTEPES.p)
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
- #%% inverse index generator to mutually exclusive generator
854
- pExclusiveGenToGen = pGenToExclusiveGen.reset_index().set_index('MutuallyExclusive').set_axis(['Generator'], axis=1)[['Generator']]
855
- pExclusiveGenToGen = pExclusiveGenToGen.loc[pExclusiveGenToGen['Generator'].isin(mTEPES.g)].reset_index().set_index(['MutuallyExclusive', 'Generator'])
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
- mTEPES.g2g = Set(doc='mutually exclusive generator to generator', initialize=[(gg,g) for gg,g in mTEPES.g*mTEPES.g if (gg,g) in pExclusiveGenToGen])
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 ).astype('int')
927
- pOutflowsTimeStep = pOutflowsType.map(idxOutflows).where(pEnergyOutflows.sum() > 0.0, other = 1).astype('int')
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 len(g2a[ar]):
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 >= 0.0, 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
- #Calculate 2nd Blocks
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 len(g2a[ar]):
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
- pLineNTCFrw.update(pd.Series([0.0 for ni,nf,cc in mTEPES.la if pLineNTCFrw[ni,nf,cc] < pEpsilonElec], index=[(ni,nf,cc) for ni,nf,cc in mTEPES.la if pLineNTCFrw[ni,nf,cc] < pEpsilonElec], dtype='float64'))
1112
- pLineNTCBck.update(pd.Series([0.0 for ni,nf,cc in mTEPES.la if pLineNTCBck[ni,nf,cc] < pEpsilonElec], index=[(ni,nf,cc) for ni,nf,cc in mTEPES.la if pLineNTCBck[ni,nf,cc] < pEpsilonElec], dtype='float64'))
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
- pH2PipeNTCFrw.update(pd.Series([0.0 for ni,nf,cc in mTEPES.pa if pH2PipeNTCFrw[ni,nf,cc] < pEpsilonElec], index=[(ni,nf,cc) for ni,nf,cc in mTEPES.pa if pH2PipeNTCFrw[ni,nf,cc] < pEpsilonElec], dtype='float64'))
1118
- pH2PipeNTCBck.update(pd.Series([0.0 for ni,nf,cc in mTEPES.pa if pH2PipeNTCBck[ni,nf,cc] < pEpsilonElec], index=[(ni,nf,cc) for ni,nf,cc in mTEPES.pa if pH2PipeNTCBck[ni,nf,cc] < pEpsilonElec], dtype='float64'))
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
- pHeatPipeNTCFrw.update(pd.Series([0.0 for ni,nf,cc in mTEPES.ha if pHeatPipeNTCFrw[ni,nf,cc] < pEpsilonHeat], index=[(ni,nf,cc) for ni,nf,cc in mTEPES.ha if pHeatPipeNTCFrw[ni,nf,cc] < pEpsilonHeat], dtype='float64'))
1125
- pHeatPipeNTCBck.update(pd.Series([0.0 for ni,nf,cc in mTEPES.ha if pHeatPipeNTCBck[ni,nf,cc] < pEpsilonHeat], index=[(ni,nf,cc) for ni,nf,cc in mTEPES.ha if pHeatPipeNTCBck[ni,nf,cc] < pEpsilonHeat], dtype='float64'))
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 to heat ratio of the CHP units
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] for bo in mTEPES.bo] for p,sc,n in mTEPES.psn], index=mTEPES.psn, columns=mTEPES.bo))
1157
- pMaxPowerHeat.update(pd.DataFrame([[pRatedMaxPowerHeat[bo] for bo in mTEPES.bo] for p,sc,n in mTEPES.psn], index=mTEPES.psn, columns=mTEPES.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
- if pIndHydroTopology == 1:
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
- pDemandElecAbs = filter_rows(pDemandElecAbs , mTEPES.psnnd)
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=pIndBinGenRetire , within=NonNegativeIntegers, doc='Indicator of binary generation retirement decisions', mutable=True)
1317
- mTEPES.pIndBinRsrInvest = Param(initialize=pIndBinRsrInvest , within=NonNegativeIntegers, doc='Indicator of binary reservoir investment decisions', mutable=True)
1318
- mTEPES.pIndBinNetElecInvest = Param(initialize=pIndBinNetElecInvest, within=NonNegativeIntegers, doc='Indicator of binary electric network investment decisions', mutable=True)
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.pENSCost = Param(initialize=pENSCost , within=NonNegativeReals, doc='ENS cost' )
1332
- mTEPES.pH2NSCost = Param(initialize=pH2NSCost , within=NonNegativeReals, doc='HNS cost' )
1333
- mTEPES.pHeatNSCost = Param(initialize=pHeatNSCost , within=NonNegativeReals, doc='HTNS cost' )
1334
- mTEPES.pCO2Cost = Param(initialize=pCO2Cost , within=NonNegativeReals, doc='CO2 emission cost' )
1335
- mTEPES.pAnnualDiscRate = Param(initialize=pAnnualDiscRate , within=UnitInterval, doc='Annual discount rate' )
1336
- mTEPES.pUpReserveActivation = Param(initialize=pUpReserveActivation, within=UnitInterval, doc='Proportion of upward reserve activation' )
1337
- mTEPES.pDwReserveActivation = Param(initialize=pDwReserveActivation, within=UnitInterval, doc='Proportion of downward reserve activation' )
1338
- mTEPES.pMinRatioDwUp = Param(initialize=pMinRatioDwUp , within=UnitInterval, doc='Minimum ratio downward to upward operating reserves')
1339
- mTEPES.pMaxRatioDwUp = Param(initialize=pMaxRatioDwUp , within=UnitInterval, doc='Maximum ratio downward to upward operating reserves')
1340
- mTEPES.pSBase = Param(initialize=pSBase , within=PositiveReals, doc='Base power' )
1341
- mTEPES.pTimeStep = Param(initialize=pTimeStep , within=PositiveIntegers, doc='Unitary time step' )
1342
- mTEPES.pEconomicBaseYear = Param(initialize=pEconomicBaseYear , within=PositiveIntegers, doc='Base year' )
1343
-
1344
- mTEPES.pReserveMargin = Param(mTEPES.par, initialize=pReserveMargin.to_dict() , within=NonNegativeReals, doc='Adequacy reserve margin' )
1345
- mTEPES.pEmission = Param(mTEPES.par, initialize=pEmission.to_dict() , within=NonNegativeReals, doc='Maximum CO2 emission' )
1346
- mTEPES.pRESEnergy = Param(mTEPES.par, initialize=pRESEnergy.to_dict() , within=NonNegativeReals, doc='Minimum RES energy' )
1347
- mTEPES.pDemandElecPeak = Param(mTEPES.par, initialize=pDemandElecPeak.to_dict() , within=NonNegativeReals, doc='Peak electric demand' )
1348
- mTEPES.pDemandElec = Param(mTEPES.psnnd, initialize=pDemandElec.to_dict() , within= Reals, doc='Electric demand' )
1349
- mTEPES.pDemandElecAbs = Param(mTEPES.psnnd, initialize=pDemandElecAbs.to_dict() , within=NonNegativeReals, doc='Electric demand' )
1350
- mTEPES.pPeriodWeight = Param(mTEPES.p, initialize=pPeriodWeight.to_dict() , within=NonNegativeReals, doc='Period weight', mutable=True)
1351
- mTEPES.pDiscountedWeight = Param(mTEPES.p, initialize=pDiscountedWeight.to_dict() , within=NonNegativeReals, doc='Discount factor' )
1352
- mTEPES.pScenProb = Param(mTEPES.psc, initialize=pScenProb.to_dict() , within=UnitInterval , doc='Probability', mutable=True)
1353
- mTEPES.pStageWeight = Param(mTEPES.stt, initialize=pStageWeight.to_dict() , within=NonNegativeReals, doc='Stage weight' )
1354
- mTEPES.pDuration = Param(mTEPES.psn, initialize=pDuration.to_dict() , within=NonNegativeIntegers, doc='Duration', mutable=True)
1355
- mTEPES.pNodeLon = Param(mTEPES.nd, initialize=pNodeLon.to_dict() , doc='Longitude' )
1356
- mTEPES.pNodeLat = Param(mTEPES.nd, initialize=pNodeLat.to_dict() , doc='Latitude' )
1357
- mTEPES.pSystemInertia = Param(mTEPES.psnar, initialize=pSystemInertia.to_dict() , within=NonNegativeReals, doc='System inertia' )
1358
- mTEPES.pOperReserveUp = Param(mTEPES.psnar, initialize=pOperReserveUp.to_dict() , within=NonNegativeReals, doc='Upward operating reserve' )
1359
- mTEPES.pOperReserveDw = Param(mTEPES.psnar, initialize=pOperReserveDw.to_dict() , within=NonNegativeReals, doc='Downward operating reserve' )
1360
- mTEPES.pMinPowerElec = Param(mTEPES.psng , initialize=pMinPowerElec.to_dict() , within=NonNegativeReals, doc='Minimum electric power' )
1361
- mTEPES.pMaxPowerElec = Param(mTEPES.psng , initialize=pMaxPowerElec.to_dict() , within=NonNegativeReals, doc='Maximum electric power' )
1362
- mTEPES.pMinCharge = Param(mTEPES.psneh, initialize=pMinCharge.to_dict() , within=NonNegativeReals, doc='Minimum charge' )
1363
- mTEPES.pMaxCharge = Param(mTEPES.psneh, initialize=pMaxCharge.to_dict() , within=NonNegativeReals, doc='Maximum charge' )
1364
- mTEPES.pMaxCapacity = Param(mTEPES.psneh, initialize=pMaxCapacity.to_dict() , within=NonNegativeReals, doc='Maximum capacity' )
1365
- mTEPES.pMaxPower2ndBlock = Param(mTEPES.psng , initialize=pMaxPower2ndBlock.to_dict() , within=NonNegativeReals, doc='Second block power' )
1366
- mTEPES.pMaxCharge2ndBlock = Param(mTEPES.psneh, initialize=pMaxCharge2ndBlock.to_dict() , within=NonNegativeReals, doc='Second block charge' )
1367
- mTEPES.pEnergyInflows = Param(mTEPES.psnes, initialize=pEnergyInflows.to_dict() , within=NonNegativeReals, doc='Energy inflows', mutable=True)
1368
- mTEPES.pEnergyOutflows = Param(mTEPES.psnes, initialize=pEnergyOutflows.to_dict() , within=NonNegativeReals, doc='Energy outflows', mutable=True)
1369
- mTEPES.pMinStorage = Param(mTEPES.psnes, initialize=pMinStorage.to_dict() , within=NonNegativeReals, doc='ESS Minimum storage capacity' )
1370
- mTEPES.pMaxStorage = Param(mTEPES.psnes, initialize=pMaxStorage.to_dict() , within=NonNegativeReals, doc='ESS Maximum storage capacity' )
1371
- mTEPES.pMinEnergy = Param(mTEPES.psng , initialize=pVariableMinEnergy.to_dict() , within=NonNegativeReals, doc='Unit minimum energy demand' )
1372
- mTEPES.pMaxEnergy = Param(mTEPES.psng , initialize=pVariableMaxEnergy.to_dict() , within=NonNegativeReals, doc='Unit maximum energy demand' )
1373
- mTEPES.pRatedMaxPowerElec = Param(mTEPES.gg, initialize=pRatedMaxPowerElec.to_dict() , within=NonNegativeReals, doc='Rated maximum power' )
1374
- mTEPES.pRatedMaxCharge = Param(mTEPES.gg, initialize=pRatedMaxCharge.to_dict() , within=NonNegativeReals, doc='Rated maximum charge' )
1375
- mTEPES.pMustRun = Param(mTEPES.gg, initialize=pMustRun.to_dict() , within=Binary , doc='must-run unit' )
1376
- mTEPES.pInertia = Param(mTEPES.gg, initialize=pInertia.to_dict() , within=NonNegativeReals, doc='unit inertia constant' )
1377
- mTEPES.pElecGenPeriodIni = Param(mTEPES.gg, initialize=pElecGenPeriodIni.to_dict() , within=PositiveIntegers, doc='installation year', )
1378
- mTEPES.pElecGenPeriodFin = Param(mTEPES.gg, initialize=pElecGenPeriodFin.to_dict() , within=PositiveIntegers, doc='retirement year', )
1379
- mTEPES.pAvailability = Param(mTEPES.gg, initialize=pAvailability.to_dict() , within=UnitInterval , doc='unit availability', mutable=True)
1380
- mTEPES.pEFOR = Param(mTEPES.gg, initialize=pEFOR.to_dict() , within=UnitInterval , doc='EFOR' )
1381
- mTEPES.pRatedLinearVarCost = Param(mTEPES.gg, initialize=pRatedLinearVarCost.to_dict() , within=NonNegativeReals, doc='Linear variable cost' )
1382
- mTEPES.pRatedConstantVarCost = Param(mTEPES.gg, initialize=pRatedConstantVarCost.to_dict() , within=NonNegativeReals, doc='Constant variable cost' )
1383
- mTEPES.pLinearVarCost = Param(mTEPES.psng , initialize=pLinearVarCost.to_dict() , within=NonNegativeReals, doc='Linear variable cost' )
1384
- mTEPES.pConstantVarCost = Param(mTEPES.psng , initialize=pConstantVarCost.to_dict() , within=NonNegativeReals, doc='Constant variable cost' )
1385
- mTEPES.pLinearOMCost = Param(mTEPES.gg, initialize=pLinearOMCost.to_dict() , within=NonNegativeReals, doc='Linear O&M cost' )
1386
- mTEPES.pOperReserveCost = Param(mTEPES.gg, initialize=pOperReserveCost.to_dict() , within=NonNegativeReals, doc='Operating reserve cost' )
1387
- mTEPES.pEmissionVarCost = Param(mTEPES.psng , initialize=pEmissionVarCost.to_dict() , within=Reals , doc='CO2 Emission cost' )
1388
- mTEPES.pEmissionRate = Param(mTEPES.gg, initialize=pEmissionRate.to_dict() , within=Reals , doc='CO2 Emission rate' )
1389
- mTEPES.pStartUpCost = Param(mTEPES.nr, initialize=pStartUpCost.to_dict() , within=NonNegativeReals, doc='Startup cost' )
1390
- mTEPES.pShutDownCost = Param(mTEPES.nr, initialize=pShutDownCost.to_dict() , within=NonNegativeReals, doc='Shutdown cost' )
1391
- mTEPES.pRampUp = Param(mTEPES.gg, initialize=pRampUp.to_dict() , within=NonNegativeReals, doc='Ramp up rate' )
1392
- mTEPES.pRampDw = Param(mTEPES.gg, initialize=pRampDw.to_dict() , within=NonNegativeReals, doc='Ramp down rate' )
1393
- mTEPES.pUpTime = Param(mTEPES.gg, initialize=pUpTime.to_dict() , within=NonNegativeIntegers, doc='Up time' )
1394
- mTEPES.pDwTime = Param(mTEPES.gg, initialize=pDwTime.to_dict() , within=NonNegativeIntegers, doc='Down time' )
1395
- mTEPES.pStableTime = Param(mTEPES.gg, initialize=pStableTime.to_dict() , within=NonNegativeIntegers, doc='Stable time' )
1396
- mTEPES.pShiftTime = Param(mTEPES.gg, initialize=pShiftTime.to_dict() , within=NonNegativeIntegers, doc='Shift time' )
1397
- mTEPES.pGenInvestCost = Param(mTEPES.eb, initialize=pGenInvestCost.to_dict() , within=NonNegativeReals, doc='Generation fixed cost' )
1398
- mTEPES.pGenRetireCost = Param(mTEPES.gd, initialize=pGenRetireCost.to_dict() , within=Reals , doc='Generation fixed retire cost' )
1399
- mTEPES.pIndBinUnitInvest = Param(mTEPES.eb, initialize=pIndBinUnitInvest.to_dict() , within=Binary , doc='Binary investment decision' )
1400
- mTEPES.pIndBinUnitRetire = Param(mTEPES.gd, initialize=pIndBinUnitRetire.to_dict() , within=Binary , doc='Binary retirement decision' )
1401
- mTEPES.pIndBinUnitCommit = Param(mTEPES.nr, initialize=pIndBinUnitCommit.to_dict() , within=Binary , doc='Binary commitment decision' )
1402
- mTEPES.pIndBinStorInvest = Param(mTEPES.ec, initialize=pIndBinStorInvest.to_dict() , within=Binary , doc='Storage linked to generation investment' )
1403
- mTEPES.pIndOperReserve = Param(mTEPES.gg, initialize=pIndOperReserve.to_dict() , within=Binary , doc='Indicator of operating reserve' )
1404
- mTEPES.pIndOutflowIncomp = Param(mTEPES.gg, initialize=pIndOutflowIncomp.to_dict() , within=Binary , doc='Indicator of outflow incompatibility with charging' )
1405
- mTEPES.pEfficiency = Param(mTEPES.eh, initialize=pEfficiency.to_dict() , within=UnitInterval , doc='Round-trip efficiency' )
1406
- mTEPES.pStorageTimeStep = Param(mTEPES.es, initialize=pStorageTimeStep.to_dict() , within=PositiveIntegers, doc='ESS Storage cycle' )
1407
- mTEPES.pOutflowsTimeStep = Param(mTEPES.es, initialize=pOutflowsTimeStep.to_dict() , within=PositiveIntegers, doc='ESS Outflows cycle' )
1408
- mTEPES.pEnergyTimeStep = Param(mTEPES.gg, initialize=pEnergyTimeStep.to_dict() , within=PositiveIntegers, doc='Unit energy cycle' )
1409
- mTEPES.pIniInventory = Param(mTEPES.psnes, initialize=pIniInventory.to_dict() , within=NonNegativeReals, doc='ESS Initial storage', mutable=True)
1410
- mTEPES.pStorageType = Param(mTEPES.es, initialize=pStorageType.to_dict() , within=Any , doc='ESS Storage type' )
1411
- mTEPES.pGenLoInvest = Param(mTEPES.eb, initialize=pGenLoInvest.to_dict() , within=NonNegativeReals, doc='Lower bound of the investment decision', mutable=True)
1412
- mTEPES.pGenUpInvest = Param(mTEPES.eb, initialize=pGenUpInvest.to_dict() , within=NonNegativeReals, doc='Upper bound of the investment decision', mutable=True)
1413
- mTEPES.pGenLoRetire = Param(mTEPES.gd, initialize=pGenLoRetire.to_dict() , within=NonNegativeReals, doc='Lower bound of the retirement decision', mutable=True)
1414
- mTEPES.pGenUpRetire = Param(mTEPES.gd, initialize=pGenUpRetire.to_dict() , within=NonNegativeReals, doc='Upper bound of the retirement decision', mutable=True)
1415
-
1416
- if pIndHydrogen == 1:
1417
- mTEPES.pProductionFunctionH2 = Param(mTEPES.el, initialize=pProductionFunctionH2.to_dict(), within=NonNegativeReals, doc='Production function of an electrolyzer plant')
1418
-
1419
- if pIndHeat == 1:
1420
- pMinPowerHeat = filter_rows(pMinPowerHeat, mTEPES.psnch)
1421
- pMaxPowerHeat = filter_rows(pMaxPowerHeat, mTEPES.psnch)
1422
-
1423
- mTEPES.pReserveMarginHeat = Param(mTEPES.par, initialize=pReserveMarginHeat.to_dict() , within=NonNegativeReals, doc='Adequacy reserve margin' )
1424
- mTEPES.pRatedMaxPowerHeat = Param(mTEPES.gg, initialize=pRatedMaxPowerHeat.to_dict() , within=NonNegativeReals, doc='Rated maximum heat' )
1425
- mTEPES.pMinPowerHeat = Param(mTEPES.psnch, initialize=pMinPowerHeat.to_dict() , within=NonNegativeReals, doc='Minimum heat power' )
1426
- mTEPES.pMaxPowerHeat = Param(mTEPES.psnch, initialize=pMaxPowerHeat.to_dict() , within=NonNegativeReals, doc='Maximum heat power' )
1427
- mTEPES.pPower2HeatRatio = Param(mTEPES.ch, initialize=pPower2HeatRatio.to_dict() , within=NonNegativeReals, doc='Power to heat ratio' )
1428
- mTEPES.pProductionFunctionHeat = Param(mTEPES.hp, initialize=pProductionFunctionHeat.to_dict() , within=NonNegativeReals, doc='Production function of an CHP plant' )
1429
- mTEPES.pProductionFunctionH2ToHeat = Param(mTEPES.hh, initialize=pProductionFunctionH2ToHeat.to_dict(), within=NonNegativeReals, doc='Production function of an boiler using H2')
1430
-
1431
- if pIndHydroTopology == 1:
1432
-
1433
- pHydroInflows = filter_rows(pHydroInflows , mTEPES.psnrs)
1434
- pHydroOutflows = filter_rows(pHydroOutflows, mTEPES.psnrs)
1435
- pMaxOutflows = filter_rows(pMaxOutflows , mTEPES.psnrs)
1436
- pMinVolume = filter_rows(pMinVolume , mTEPES.psnrs)
1437
- pMaxVolume = filter_rows(pMaxVolume , mTEPES.psnrs)
1438
- pIniVolume = filter_rows(pIniVolume , mTEPES.psnrs)
1439
-
1440
- mTEPES.pProductionFunctionHydro = Param(mTEPES.h , initialize=pProductionFunctionHydro.to_dict(), within=NonNegativeReals, doc='Production function of a hydro power plant' )
1441
- mTEPES.pHydroInflows = Param(mTEPES.psnrs, initialize=pHydroInflows.to_dict() , within=NonNegativeReals, doc='Hydro inflows', mutable=True)
1442
- mTEPES.pHydroOutflows = Param(mTEPES.psnrs, initialize=pHydroOutflows.to_dict() , within=NonNegativeReals, doc='Hydro outflows', mutable=True)
1443
- mTEPES.pMaxOutflows = Param(mTEPES.psnrs, initialize=pMaxOutflows.to_dict() , within=NonNegativeReals, doc='Maximum hydro outflows', )
1444
- mTEPES.pMinVolume = Param(mTEPES.psnrs, initialize=pMinVolume.to_dict() , within=NonNegativeReals, doc='Minimum reservoir volume capacity' )
1445
- mTEPES.pMaxVolume = Param(mTEPES.psnrs, initialize=pMaxVolume.to_dict() , within=NonNegativeReals, doc='Maximum reservoir volume capacity' )
1446
- mTEPES.pIndBinRsrvInvest = Param(mTEPES.rn, initialize=pIndBinRsrvInvest.to_dict() , within=Binary , doc='Binary reservoir investment decision' )
1447
- mTEPES.pRsrInvestCost = Param(mTEPES.rn, initialize=pRsrInvestCost.to_dict() , within=NonNegativeReals, doc='Reservoir fixed cost' )
1448
- mTEPES.pRsrPeriodIni = Param(mTEPES.rs, initialize=pRsrPeriodIni.to_dict() , within=PositiveIntegers, doc='Installation year', )
1449
- mTEPES.pRsrPeriodFin = Param(mTEPES.rs, initialize=pRsrPeriodFin.to_dict() , within=PositiveIntegers, doc='Retirement year', )
1450
- mTEPES.pReservoirTimeStep = Param(mTEPES.rs, initialize=pReservoirTimeStep.to_dict() , within=PositiveIntegers, doc='Reservoir volume cycle' )
1451
- mTEPES.pWaterOutTimeStep = Param(mTEPES.rs, initialize=pWaterOutTimeStep.to_dict() , within=PositiveIntegers, doc='Reservoir outflows cycle' )
1452
- mTEPES.pIniVolume = Param(mTEPES.psnrs, initialize=pIniVolume.to_dict() , within=NonNegativeReals, doc='Reservoir initial volume', mutable=True)
1453
- mTEPES.pInitialVolume = Param(mTEPES.rs, initialize=pInitialVolume.to_dict() , within=NonNegativeReals, doc='Reservoir initial volume without load levels')
1454
- mTEPES.pReservoirType = Param(mTEPES.rs, initialize=pReservoirType.to_dict() , within=Any , doc='Reservoir volume type' )
1455
-
1456
- if pIndHydrogen == 1:
1457
- pDemandH2 = filter_rows(pDemandH2 ,mTEPES.psnnd)
1458
- pDemandH2Abs = filter_rows(pDemandH2Abs,mTEPES.psnnd)
1459
-
1460
- mTEPES.pDemandH2 = Param(mTEPES.psnnd, initialize=pDemandH2.to_dict() , within=NonNegativeReals, doc='Hydrogen demand per hour')
1461
- mTEPES.pDemandH2Abs = Param(mTEPES.psnnd, initialize=pDemandH2Abs.to_dict(), within=NonNegativeReals, doc='Hydrogen demand' )
1462
-
1463
- if pIndHeat == 1:
1464
- pDemandHeat = filter_rows(pDemandHeat , mTEPES.psnnd)
1465
- pDemandHeatAbs = filter_rows(pDemandHeatAbs , mTEPES.psnnd)
1466
-
1467
- mTEPES.pDemandHeatPeak = Param(mTEPES.par, initialize=pDemandHeatPeak.to_dict(), within=NonNegativeReals, doc='Peak heat demand' )
1468
- mTEPES.pDemandHeat = Param(mTEPES.psnnd, initialize=pDemandHeat.to_dict() , within=NonNegativeReals, doc='Heat demand per hour' )
1469
- mTEPES.pDemandHeatAbs = Param(mTEPES.psnnd, initialize=pDemandHeatAbs.to_dict(), within=NonNegativeReals, doc='Heat demand' )
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
- if pIndHydrogen == 1:
1508
- mTEPES.pH2PipeLength = Param(mTEPES.pn, initialize=pH2PipeLength.to_dict() , within=NonNegativeReals, doc='Hydrogen pipeline length', mutable=True)
1509
- mTEPES.pH2PipePeriodIni = Param(mTEPES.pn, initialize=pH2PipePeriodIni.to_dict() , within=PositiveIntegers, doc='Installation period' )
1510
- mTEPES.pH2PipePeriodFin = Param(mTEPES.pn, initialize=pH2PipePeriodFin.to_dict() , within=PositiveIntegers, doc='Retirement period' )
1511
- mTEPES.pH2PipeNTCFrw = Param(mTEPES.pn, initialize=pH2PipeNTCFrw.to_dict() , within=NonNegativeReals, doc='Hydrogen pipeline NTC forward' )
1512
- mTEPES.pH2PipeNTCBck = Param(mTEPES.pn, initialize=pH2PipeNTCBck.to_dict() , within=NonNegativeReals, doc='Hydrogen pipeline NTC backward' )
1513
- mTEPES.pH2PipeFixedCost = Param(mTEPES.pc, initialize=pH2PipeFixedCost.to_dict() , within=NonNegativeReals, doc='Hydrogen pipeline fixed cost' )
1514
- mTEPES.pIndBinH2PipeInvest = Param(mTEPES.pn, initialize=pIndBinH2PipeInvest.to_dict(), within=Binary , doc='Binary pipeline investment decision' )
1515
- mTEPES.pH2PipeLoInvest = Param(mTEPES.pc, initialize=pH2PipeLoInvest.to_dict() , within=NonNegativeReals, doc='Lower bound of the pipeline investment decision', mutable=True)
1516
- mTEPES.pH2PipeUpInvest = Param(mTEPES.pc, initialize=pH2PipeUpInvest.to_dict() , within=NonNegativeReals, doc='Upper bound of the pipeline investment decision', mutable=True)
1517
-
1518
- if pIndHeat == 1:
1519
- mTEPES.pHeatPipeLength = Param(mTEPES.hn, initialize=pHeatPipeLength.to_dict() , within=NonNegativeReals, doc='Heat pipe length', mutable=True)
1520
- mTEPES.pHeatPipePeriodIni = Param(mTEPES.hn, initialize=pHeatPipePeriodIni.to_dict() , within=PositiveIntegers, doc='Installation period' )
1521
- mTEPES.pHeatPipePeriodFin = Param(mTEPES.hn, initialize=pHeatPipePeriodFin.to_dict() , within=PositiveIntegers, doc='Retirement period' )
1522
- mTEPES.pHeatPipeNTCFrw = Param(mTEPES.hn, initialize=pHeatPipeNTCFrw.to_dict() , within=NonNegativeReals, doc='Heat pipe NTC forward' )
1523
- mTEPES.pHeatPipeNTCBck = Param(mTEPES.hn, initialize=pHeatPipeNTCBck.to_dict() , within=NonNegativeReals, doc='Heat pipe NTC backward' )
1524
- mTEPES.pHeatPipeFixedCost = Param(mTEPES.hc, initialize=pHeatPipeFixedCost.to_dict() , within=NonNegativeReals, doc='Heat pipe fixed cost' )
1525
- mTEPES.pIndBinHeatPipeInvest = Param(mTEPES.hn, initialize=pIndBinHeatPipeInvest.to_dict(), within=Binary , doc='Binary heat pipe investment decision' )
1526
- mTEPES.pHeatPipeLoInvest = Param(mTEPES.hc, initialize=pHeatPipeLoInvest.to_dict() , within=NonNegativeReals, doc='Lower bound of the heat pipe investment decision', mutable=True)
1527
- mTEPES.pHeatPipeUpInvest = Param(mTEPES.hc, initialize=pHeatPipeUpInvest.to_dict() , within=NonNegativeReals, doc='Upper bound of the heat pipe investment decision', mutable=True)
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 a mTEPES instance with all parameters and sets created and adds variables to it.
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, doc='total system cost [MEUR]')
1613
- OptModel.vTotalICost = Var( within=NonNegativeReals, doc='total system investment cost [MEUR]')
1614
- OptModel.vTotalFCost = Var(mTEPES.p, within=NonNegativeReals, doc='total system fixed cost [MEUR]')
1615
- OptModel.vTotalGCost = Var(mTEPES.psn, within=NonNegativeReals, doc='total variable generation operation cost [MEUR]')
1616
- OptModel.vTotalCCost = Var(mTEPES.psn, within=NonNegativeReals, doc='total variable consumption operation cost [MEUR]')
1617
- OptModel.vTotalECost = Var(mTEPES.psn, within=NonNegativeReals, doc='total system emission cost [MEUR]')
1618
- OptModel.vTotalRCost = Var(mTEPES.psn, within=NonNegativeReals, doc='total system reliability cost [MEUR]')
1619
- OptModel.vTotalNCost = Var(mTEPES.psn, within=NonNegativeReals, doc='total network loss penalty operation cost [MEUR]')
1620
- OptModel.vTotalEmissionArea = Var(mTEPES.psnar, within=NonNegativeReals, doc='total area emission [MtCO2]')
1621
- OptModel.vTotalECostArea = Var(mTEPES.psnar, within=NonNegativeReals, doc='total area emission cost [MEUR]')
1622
- OptModel.vTotalRESEnergyArea = Var(mTEPES.psnar, within=NonNegativeReals, doc=' RES energy [GWh]')
1623
-
1624
- OptModel.vTotalOutput = Var(mTEPES.psng , within=NonNegativeReals, doc='total output of the unit [GW]')
1625
- OptModel.vOutput2ndBlock = Var(mTEPES.psnnr, within=NonNegativeReals, doc='second block of the unit [GW]')
1626
- OptModel.vReserveUp = Var(mTEPES.psnnr, within=NonNegativeReals, doc='upward operating reserve [GW]')
1627
- OptModel.vReserveDown = Var(mTEPES.psnnr, within=NonNegativeReals, doc='downward operating reserve [GW]')
1628
- OptModel.vEnergyInflows = Var(mTEPES.psnec, within=NonNegativeReals, doc='unscheduled inflows of candidate ESS units [GW]')
1629
- OptModel.vEnergyOutflows = Var(mTEPES.psnes, within=NonNegativeReals, doc='scheduled outflows of all ESS units [GW]')
1630
- OptModel.vESSInventory = Var(mTEPES.psnes, within=NonNegativeReals, doc='ESS inventory [GWh]')
1631
- OptModel.vESSSpillage = Var(mTEPES.psnes, within=NonNegativeReals, doc='ESS spillage [GWh]')
1632
- OptModel.vIniInventory = Var(mTEPES.psnec, within=NonNegativeReals, doc='initial inventory for ESS candidate [GWh]')
1633
-
1634
- OptModel.vESSTotalCharge = Var(mTEPES.psneh, within=NonNegativeReals, doc='ESS total charge power [GW]')
1635
- OptModel.vCharge2ndBlock = Var(mTEPES.psneh, within=NonNegativeReals, doc='ESS charge power [GW]')
1636
- OptModel.vESSReserveUp = Var(mTEPES.psneh, within=NonNegativeReals, doc='ESS upward operating reserve [GW]')
1637
- OptModel.vESSReserveDown = Var(mTEPES.psneh, within=NonNegativeReals, doc='ESS downward operating reserve [GW]')
1638
- OptModel.vENS = Var(mTEPES.psnnd, within=NonNegativeReals, doc='energy not served in node [GW]')
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, doc='unscheduled inflows of candidate hydro units [m3/s]')
1642
- OptModel.vHydroOutflows = Var(mTEPES.psnrs, within=NonNegativeReals, doc='scheduled outflows of all hydro units [m3/s]')
1643
- OptModel.vReservoirVolume = Var(mTEPES.psnrs, within=NonNegativeReals, doc='Reservoir volume [hm3]')
1644
- OptModel.vReservoirSpillage = Var(mTEPES.psnrs, within=NonNegativeReals, doc='Reservoir spillage [hm3]')
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, doc='total heat output of the boiler unit [GW]')
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, doc='generation investment decision exists in a year [0,1]')
1654
- OptModel.vGenerationInvPer = Var(mTEPES.peb, within=UnitInterval, doc='generation investment decision done in a year [0,1]')
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, doc='generation investment decision exists in a year {0,1}')
1657
- OptModel.vGenerationInvPer = Var(mTEPES.peb, within=Binary, doc='generation investment decision done in a year {0,1}')
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, doc='generation retirement decision exists in a year [0,1]')
1661
- OptModel.vGenerationRetPer = Var(mTEPES.pgd, within=UnitInterval, doc='generation retirement decision exists in a year [0,1]')
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, doc='generation retirement decision exists in a year {0,1}')
1664
- OptModel.vGenerationRetPer = Var(mTEPES.pgd, within=Binary, doc='generation retirement decision exists in a year {0,1}')
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, doc='electric network investment decision exists in a year [0,1]')
1668
- OptModel.vNetworkInvPer = Var(mTEPES.plc, within=UnitInterval, doc='electric network investment decision exists in a year [0,1]')
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, doc='electric network investment decision exists in a year {0,1}')
1671
- OptModel.vNetworkInvPer = Var(mTEPES.plc, within=Binary, doc='electric network investment decision exists in a year {0,1}')
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, doc='reservoir investment decision exists in a year [0,1]')
1676
- OptModel.vReservoirInvPer = Var(mTEPES.prc, within=UnitInterval, doc='reservoir investment decision exists in a year [0,1]')
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, doc='reservoir investment decision exists in a year {0,1}')
1679
- OptModel.vReservoirInvPer = Var(mTEPES.prc, within=Binary, doc='reservoir investment decision exists in a year {0,1}')
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, doc='hydrogen network investment decision exists in a year [0,1]')
1684
- OptModel.vH2PipeInvPer = Var(mTEPES.ppc, within=UnitInterval, doc='hydrogen network investment decision exists in a year [0,1]')
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, doc='hydrogen network investment decision exists in a year {0,1}')
1687
- OptModel.vH2PipeInvPer = Var(mTEPES.ppc, within=Binary, doc='hydrogen network investment decision exists in a year {0,1}')
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, doc='generation investment decision exists in a year [0,1]')
1692
- OptModel.vGenerationInvPerHeat = Var(mTEPES.pbc, within=UnitInterval, doc='generation investment decision done in a year [0,1]')
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, doc='generation investment decision exists in a year {0,1}')
1695
- OptModel.vGenerationInvPerHeat = Var(mTEPES.pbc, within=Binary, doc='generation investment decision done in a year {0,1}')
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, doc='heat network investment decision exists in a year [0,1]' )
1698
- OptModel.vHeatPipeInvPer = Var(mTEPES.phc, within=UnitInterval, doc='heat network investment decision exists in a year [0,1]' )
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, doc='heat network investment decision exists in a year {0,1}' )
1701
- OptModel.vHeatPipeInvPer = Var(mTEPES.phc, within=Binary, doc='heat network investment decision exists in a year {0,1}' )
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, initialize=0.0, doc='consumption commitment of the unit [0,1]')
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 = Var(mTEPES.psnh, within=Binary, initialize=0.0, doc='consumption commitment of the unit [0,1]')
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, initialize=0.0, doc='line switching of the electric line [0,1]')
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, initialize=0 , doc='line switching of the electric line {0,1}')
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, initialize=0.0, doc='switching on state of the electric line [0,1]')
1733
- OptModel.vLineOffState = Var(mTEPES.psnla, within=UnitInterval, initialize=0.0, doc='switching off state of the electric line [0,1]')
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, initialize=0 , doc='switching on state of the electric line {0,1}')
1736
- OptModel.vLineOffState = Var(mTEPES.psnla, within=Binary, initialize=0 , doc='switching off state of the electric line {0,1}')
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 a mTEPES instance and adds lower/upper bounds to variables which are limited by a parameter.
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.pDemandElecAbs [p,sc,n,nd] ) for p,sc,n,nd in mTEPES.psnnd]
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 investent variables.
1852
+ Relax binary investment variables.
1783
1853
 
1784
- This function takes a mTEPES instance relaxes binary investment conditions and calculates the amount of variables fixed in the process.
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 amount of fixed variables.
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, nr in mTEPES.psnr:
1854
- if mTEPES.pIndBinUnitCommit[nr] == 0:
1855
- OptModel.vMaxCommitment[p,sc, nr].domain = UnitInterval
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
- #Call the relaxing variables function and add its output to nFixedVariables
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 flow related variables.
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 amount of line commitment variables fixed
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.pLineNTCBck[ni,nf,cc] ) for p,sc,n,ni,nf,cc in mTEPES.psnla]
1903
- [OptModel.vFlowElec[p,sc,n,ni,nf,cc].setub( mTEPES.pLineNTCFrw[ni,nf,cc] ) for p,sc,n,ni,nf,cc in mTEPES.psnla]
1904
- [OptModel.vTheta [p,sc,n,nd ].setlb(-mTEPES.pMaxTheta [p,sc,n,nd]()) for p,sc,n,nd in mTEPES.psnnd]
1905
- [OptModel.vTheta [p,sc,n,nd ].setub( mTEPES.pMaxTheta [p,sc,n,nd]()) for p,sc,n,nd in mTEPES.psnnd]
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 a mTEPES instance and fixes commitment related variables for must run units, ESS units and units with no minimum power.
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 amount of commitment variables fixed.
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.g2g) == 0:
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
- elif len(mTEPES.g2g) > 0 and sum(1 for g in mTEPES.nr if (nr,g) in mTEPES.g2g or (g,nr) in mTEPES.g2g) == 0:
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
- OptModel.vMaxCommitment [p,sc, nr].fix(1)
1964
- nFixedVariables += 3+1/len(mTEPES.n)
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 [p,sc,n,nr].fix(0.0)
1969
- OptModel.vReserveDown [p,sc,n,nr].fix(0.0)
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.pIndOperReserve [ nr] == 1:
1972
- OptModel.vReserveUp [p,sc,n,nr].fix(0.0)
1973
- OptModel.vReserveDown [p,sc,n,nr].fix(0.0)
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.pIndOperReserve[es] == 1:
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.pIndOperReserve[h ] == 1:
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 len(mTEPES.tq):
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 len(mTEPES.n):
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 initial committed units and their output at the first load level of each period, scenario, and stage
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 initial committed lines
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] == 0.0:
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 a mTEPES instance and fixes all installation and retirement variables to 0 if they are not allowed in the corresponding period.
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 amount of variables fixed.
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.vEnergyOutflows [p,sc,n,rs].fix(0.0)
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( 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)
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( 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)
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( 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)
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( 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)
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 a mTEPES instance and sets values under a certain threshold to be 0.
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 = Param(initialize=round(nFixedVariables), within=NonNegativeIntegers, doc='Number of fixed variables')
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')