openTEPES 4.18.7__py3-none-any.whl → 4.18.9__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.
@@ -1,11 +1,10 @@
1
1
  """
2
- Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - November 19, 2025
2
+ Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - January 22, 2026
3
3
  """
4
4
 
5
5
  import time
6
6
  import datetime
7
7
  import os
8
- # import ast
9
8
  import math
10
9
  import csv
11
10
  import pandas as pd
@@ -15,9 +14,13 @@ import plotly.io as pio
15
14
  import plotly.graph_objs as go
16
15
  from collections import defaultdict
17
16
  from colour import Color
17
+ import duckdb
18
+
19
+ # from line_profiler import profile
18
20
 
19
21
 
20
22
  # Definition of Pie plots
23
+ # @profile
21
24
  def PiePlots(period, scenario, df, Category, Value):
22
25
  df = df.reset_index()
23
26
  df = df.loc[(df['level_0'] == period) & (df['level_1'] == scenario)]
@@ -32,17 +35,18 @@ def PiePlots(period, scenario, df, Category, Value):
32
35
  ComposedCategory = Category+':N'
33
36
  ComposedValue = Value +':Q'
34
37
 
35
- base = alt.Chart(OutputToPlot).encode(theta=alt.Theta(ComposedValue, type="quantitative", stack=True), color=alt.Color(ComposedCategory, scale=alt.Scale(scheme='category20c'), type="nominal", legend=alt.Legend(title=Category))).properties(width=800, height=800)
38
+ base = alt.Chart(OutputToPlot).encode(theta=alt.Theta(ComposedValue, type='quantitative', stack=True), color=alt.Color(ComposedCategory, scale=alt.Scale(scheme='category20c'), type='nominal', legend=alt.Legend(title=Category))).properties(width=800, height=800)
36
39
  pie = base.mark_arc(outerRadius=240)
37
40
  text = base.mark_text(radius=340, size=15).encode(text='Label:N')
38
41
  chart = pie+text
39
- # chart = chart.resolve_scale(theta="independent")
40
- chart = alt.layer(pie, text, data=OutputToPlot).resolve_scale(theta="independent")
42
+ # chart = chart.resolve_scale(theta='independent')
43
+ chart = alt.layer(pie, text, data=OutputToPlot).resolve_scale(theta='independent')
41
44
 
42
45
  return chart
43
46
 
44
47
 
45
48
  # Definition of Area plots
49
+ # @profile
46
50
  def AreaPlots(period, scenario, df, Category, X, Y, OperationType):
47
51
  Results = df.loc[period,scenario,:,:]
48
52
  Results = Results.reset_index().rename(columns={'level_0': X, 'level_1': Category, 0: Y})
@@ -71,6 +75,7 @@ def AreaPlots(period, scenario, df, Category, X, Y, OperationType):
71
75
 
72
76
 
73
77
  # Definition of Line plots
78
+ # @profile
74
79
  def LinePlots(period, scenario, df, Category, X, Y, OperationType):
75
80
  Results = df.loc[period,scenario,:,:].rename_axis(['level_0', 'level_1'], axis=0)
76
81
  Results.columns = [0]
@@ -99,7 +104,165 @@ def LinePlots(period, scenario, df, Category, X, Y, OperationType):
99
104
  return plot
100
105
 
101
106
 
107
+ def _set_df(con, name: str, df: pd.DataFrame):
108
+ """
109
+ Insert a pandas DataFrame into an existing DuckDB table.
110
+
111
+ Parameters
112
+ ----------
113
+ con : duckdb.DuckDBPyConnection
114
+ Open DuckDB connection.
115
+ name : str
116
+ Target table name.
117
+ df : pandas.DataFrame
118
+ DataFrame to insert into the target table.
119
+ """
120
+ con.cursor().execute(f"CREATE OR REPLACE TABLE '{name}' AS SELECT * FROM df;")
121
+
122
+
123
+ def _write_var_to_db(con, var, name):
124
+ """
125
+ Write a Pyomo Var's values and bounds to DuckDB.
126
+
127
+ Parameters
128
+ ----------
129
+ con : duckdb.DuckDBPyConnection
130
+ Open DuckDB connection.
131
+ var : pyomo.core.base.var.Var
132
+ Pyomo variable (indexed or scalar).
133
+ name : str
134
+ Variable/table name to use in the database.
135
+ """
136
+ values = var.extract_values()
137
+ s = pd.Series(values, index=values.keys())
138
+ df = s.to_frame(name=name).reset_index()
139
+ df = pd.concat(
140
+ [
141
+ df,
142
+ pd.DataFrame([dict(upper_bound=var[index].ub, lower_bound=var[index].lb) for index in var]),
143
+ ],
144
+ axis=1,
145
+ )
146
+ _set_df(con, f'v_{name}', df)
147
+
148
+
149
+ def _write_param_to_db(con, param, name):
150
+ """
151
+ Write a Pyomo Param's values to DuckDB.
152
+
153
+ Creates/inserts into a table named `{name}` with:
154
+ - the Param index (via reset_index)
155
+ - a column named `{name}` containing the Param value
156
+
157
+ Parameters
158
+ ----------
159
+ con : duckdb.DuckDBPyConnection
160
+ Open DuckDB connection.
161
+ param : pyomo.core.base.param.Param
162
+ Pyomo parameter (indexed or scalar).
163
+ name : str
164
+ Parameter/table name to use in the database.
165
+ """
166
+ values = param.extract_values()
167
+ s = pd.Series(values, index=values.keys())
168
+ df = s.to_frame(name=name).reset_index()
169
+ _set_df(con, f'p_{name}', df)
170
+
171
+
172
+ def _write_set_to_db(con, set_, name):
173
+ """
174
+ Write a Pyomo Set's elements to DuckDB.
175
+
176
+ Parameters
177
+ ----------
178
+ con : duckdb.DuckDBPyConnection
179
+ Open DuckDB connection.
180
+ set_ : pyomo.core.base.set.Set
181
+ Pyomo set.
182
+ name : str
183
+ Base name used to build the table name `s_{name}`.
184
+ """
185
+ s = pd.Series(set_.sorted_data())
186
+ df = s.to_frame(name=name).reset_index()
187
+ _set_df(con, f's_{name}', df)
188
+
189
+
190
+ def _write_constraint_to_db(con, constraint, name, model):
191
+ """
192
+ Write an indexed Pyomo Constraint's duals and bounds to DuckDB.
193
+
194
+ Parameters
195
+ ----------
196
+ con : duckdb.DuckDBPyConnection
197
+ Open DuckDB connection.
198
+ constraint : pyomo.core.base.constraint.Constraint
199
+ Pyomo constraint component (must be indexed; scalar constraints are skipped).
200
+ name : str
201
+ Constraint name used to build the table name `c_{name}`.
202
+ model : pyomo.core.base.PyomoModel.ConcreteModel
203
+ Model providing `pDuals` (mapping from constraint+index string to dual value).
204
+
205
+ Notes
206
+ -----
207
+ Non-indexed constraints are ignored
208
+ """
209
+ if not constraint.is_indexed():
210
+ return
211
+
212
+ records = []
213
+ for index in constraint:
214
+ key = str(constraint.name) + str(index)
215
+ records.append(
216
+ dict(
217
+ name=str(name),
218
+ index=index,
219
+ dual=model.pDuals.get(key),
220
+ lower_bound=constraint[index].lb,
221
+ upper_bound=constraint[index].ub,
222
+ )
223
+ )
224
+
225
+ df = pd.DataFrame(records)
226
+ _set_df(con, f'c_{name}', df.reset_index())
227
+
228
+
229
+ def write_model_to_db(model, filename):
230
+ """
231
+ Export Pyomo model components to a DuckDB database file.
232
+
233
+ Parameters
234
+ ----------
235
+ model : pyomo.core.base.PyomoModel.ConcreteModel
236
+ filename : str
237
+ """
238
+ with duckdb.connect(filename) as con:
239
+ model_vars = model.component_map(ctype=pyo.Var)
240
+ for k in model_vars.keys():
241
+ var = model_vars[k]
242
+ name = var.getname()
243
+ _write_var_to_db(con, var, name)
244
+
245
+ model_params = model.component_map(ctype=pyo.Param)
246
+ for k in model_params.keys():
247
+ param = model_params[k]
248
+ name = param.getname()
249
+ _write_param_to_db(con, param, name)
250
+
251
+ model_sets = model.component_map(ctype=pyo.Set)
252
+ for k in model_sets.keys():
253
+ s = model_sets[k]
254
+ name = s.getname()
255
+ _write_set_to_db(con, s, name)
256
+
257
+ model_constraints = model.component_map(ctype=pyo.Constraint)
258
+ for k in model_constraints.keys():
259
+ constraint = model_constraints[k]
260
+ name = k
261
+ _write_constraint_to_db(con, constraint, name, model)
262
+
263
+
102
264
  # write parameters, variables, and duals
265
+ # @profile
103
266
  def OutputResultsParVarCon(DirName, CaseName, OptModel, mTEPES):
104
267
  # print('Writing pars, vars, and duals results ... ', end='')
105
268
  # DirName = os.path.dirname(DirName)
@@ -118,40 +281,42 @@ def OutputResultsParVarCon(DirName, CaseName, OptModel, mTEPES):
118
281
  os.makedirs(dump_folder)
119
282
  DateName = str(datetime.datetime.now().strftime('%Y%m%d'))
120
283
 
284
+ write_model_to_db(OptModel, f'{_path}/CaseDumpFolder_{CaseName}_{DateName}/oT_Case_{CaseName}.duckdb')
285
+
121
286
  # Extract and write parameters from the case
122
- with open(f'{_path}/CaseDumpFolder_{CaseName}_{DateName}/oT_Case_{CaseName}_Parameters.csv', 'w', newline='') as csvfile:
123
- writer = csv.writer(csvfile)
124
- writer.writerow(['Name', 'Index', 'Value'])
125
- for par in OptModel.component_objects(pyo.Param):
126
- par_object = getattr(OptModel, str(par))
127
- if par_object.is_indexed():
128
- for index in par_object:
129
- if (isinstance(index, tuple) and par_object.mutable == False) or par_object.mutable == False:
130
- writer.writerow([str(par), index, par_object[index]])
131
- else:
132
- writer.writerow([str(par), index, par_object[index].value])
133
- else:
134
- writer.writerow ([str(par), 'NA', par_object.value])
135
-
136
- # Extract and write variables
137
- with open(f'{_path}/CaseDumpFolder_{CaseName}_{DateName}/oT_Case_{CaseName}_Variables.csv', 'w', newline='') as csvfile:
138
- writer = csv.writer(csvfile)
139
- writer.writerow(['Name', 'Index', 'Value', 'Lower Bound', 'Upper Bound'])
140
- for var in OptModel.component_objects(pyo.Var, active=True):
141
- var_object = getattr(OptModel, str(var))
142
- for index in var_object:
143
- writer.writerow([str(var), index, var_object[index].value, str(var_object[index].lb), str(var_object[index].ub)])
144
-
145
- # Extract and write dual variables
146
- with open(f'{_path}/CaseDumpFolder_{CaseName}_{DateName}/oT_Case_{CaseName}_Constraints.csv', 'w', newline='') as csvfile:
147
- writer = csv.writer(csvfile)
148
- writer.writerow(['Name', 'Index', 'Value', 'Lower Bound', 'Upper Bound'])
149
- for con in OptModel.component_objects(pyo.Constraint, active=True):
150
- con_object = getattr(OptModel, str(con))
151
- if con.is_indexed():
152
- for index in con_object:
153
- writer.writerow([str(con), index, mTEPES.pDuals[str(con_object.name)+str(index)], str(con_object[index].lb), str(con_object[index].ub)])
154
- # writer.writerow([str(con), index, OptModel.dual[con_object[index]], str(con_object[index].lb), str(con_object[index].ub)])
287
+ # with open(f'{_path}/CaseDumpFolder_{CaseName}_{DateName}/oT_Case_{CaseName}_Parameters.csv', 'w', newline='') as csvfile:
288
+ # writer = csv.writer(csvfile)
289
+ # writer.writerow(['Name', 'Index', 'Value'])
290
+ # for par in OptModel.component_objects(pyo.Param):
291
+ # par_object = getattr(OptModel, str(par))
292
+ # if par_object.is_indexed():
293
+ # for index in par_object:
294
+ # if (isinstance(index, tuple) and par_object.mutable == False) or par_object.mutable == False:
295
+ # writer.writerow([str(par), index, par_object[index]])
296
+ # else:
297
+ # writer.writerow([str(par), index, par_object[index].value])
298
+ # else:
299
+ # writer.writerow ([str(par), 'NA', par_object.value])
300
+ #
301
+ # # Extract and write variables
302
+ # with open(f'{_path}/CaseDumpFolder_{CaseName}_{DateName}/oT_Case_{CaseName}_Variables.csv', 'w', newline='') as csvfile:
303
+ # writer = csv.writer(csvfile)
304
+ # writer.writerow(['Name', 'Index', 'Value', 'Lower Bound', 'Upper Bound'])
305
+ # for var in OptModel.component_objects(pyo.Var, active=True):
306
+ # var_object = getattr(OptModel, str(var))
307
+ # for index in var_object:
308
+ # writer.writerow([str(var), index, var_object[index].value, str(var_object[index].lb), str(var_object[index].ub)])
309
+ #
310
+ # # Extract and write dual variables
311
+ # with open(f'{_path}/CaseDumpFolder_{CaseName}_{DateName}/oT_Case_{CaseName}_Constraints.csv', 'w', newline='') as csvfile:
312
+ # writer = csv.writer(csvfile)
313
+ # writer.writerow(['Name', 'Index', 'Value', 'Lower Bound', 'Upper Bound'])
314
+ # for con in OptModel.component_objects(pyo.Constraint, active=True):
315
+ # con_object = getattr(OptModel, str(con))
316
+ # if con.is_indexed():
317
+ # for index in con_object:
318
+ # writer.writerow([str(con), index, mTEPES.pDuals[str(con_object.name)+str(index)], str(con_object[index].lb), str(con_object[index].ub)])
319
+ # # writer.writerow([str(con), index, OptModel.dual[con_object[index]], str(con_object[index].lb), str(con_object[index].ub)])
155
320
 
156
321
  # NameList = ['Parameters', 'Variables', 'Constraints']
157
322
  #
@@ -178,6 +343,7 @@ def OutputResultsParVarCon(DirName, CaseName, OptModel, mTEPES):
178
343
  print('Writing pars, vars, and duals results ... ', round(WritingResultsTime), 's')
179
344
 
180
345
 
346
+ # @profile
181
347
  def InvestmentResults(DirName, CaseName, OptModel, mTEPES, pIndTechnologyOutput, pIndPlotOutput):
182
348
  #%% outputting the investment decisions
183
349
  _path = os.path.join(DirName, CaseName)
@@ -201,26 +367,28 @@ def InvestmentResults(DirName, CaseName, OptModel, mTEPES, pIndTechnologyOutput,
201
367
 
202
368
  # Saving generation investments
203
369
  OutputToFile = pd.Series(data=[OptModel.vGenerationInvest[p,eb]() for p,eb in mTEPES.peb], index=mTEPES.peb)
204
- OutputToFile = OutputToFile.fillna(0).to_frame(name='InvestmentDecision').reset_index().rename(columns={'level_0': 'Period', 'level_1': 'Generating unit'})
370
+ OutputToFile = OutputToFile.fillna(0).to_frame(name='InvestmentDecision').reset_index().rename(columns={'level_0': 'Period', 'level_1': 'Generator'})
205
371
  if pIndTechnologyOutput == 0 or pIndTechnologyOutput == 2:
206
- OutputToFile.pivot_table(index=['Period'], columns=['Generating unit'], values='InvestmentDecision').rename_axis(['Period'], axis=0).to_csv(f'{_path}/oT_Result_GenerationInvestmentPerUnit_{CaseName}.csv', index=True, sep=',')
207
- OutputToFile = OutputToFile.set_index(['Period', 'Generating unit'])
372
+ OutputToFile.pivot_table(index=['Period'], columns=['Generator'], values='InvestmentDecision').rename_axis(['Period'], axis=0).to_csv(f'{_path}/oT_Result_GenerationInvestmentPerUnit_{CaseName}.csv', index=True, sep=',')
373
+ OutputToFile = OutputToFile.set_index(['Period', 'Generator'])
374
+
208
375
  OutputToFile = pd.Series(data=[OptModel.vGenerationInvest[p,eb]()*max(mTEPES.pRatedMaxPowerElec[eb],mTEPES.pRatedMaxCharge[eb]) for p,eb in mTEPES.peb], index=mTEPES.peb)
209
376
  OutputToFile *= 1e3
210
- OutputToFile = OutputToFile.fillna(0).to_frame(name='MW' ).reset_index().rename(columns={'level_0': 'Period', 'level_1': 'Generating unit'})
377
+ OutputToFile = OutputToFile.fillna(0).to_frame(name='MW').reset_index().rename(columns={'level_0': 'Period', 'level_1': 'Generator'})
211
378
  if pIndTechnologyOutput == 0 or pIndTechnologyOutput == 2:
212
- OutputToFile.pivot_table(index=['Period'], columns=['Generating unit'], values='MW' ).rename_axis(['Period'], axis=0).to_csv(f'{_path}/oT_Result_GenerationInvestment_{CaseName}.csv', index=True, sep=',')
213
- OutputToFile = OutputToFile.set_index(['Period', 'Generating unit'])
379
+ OutputToFile.pivot_table(index=['Period'], columns=['Generator'], values='MW').rename_axis(['Period'], axis=0).to_csv(f'{_path}/oT_Result_GenerationInvestment_{CaseName}.csv', index=True, sep=',')
380
+ OutputToFile.pivot_table(index=['Period', 'Generator'], values='MW').rename_axis(['Period', 'Generator'], axis=0).rename(columns={'MW': 'Power [MW]'}, inplace=False).to_csv(f'{_path}/oT_Result_MarketResultsGenerationInvestment_{CaseName}.csv', index=True, sep=',')
381
+ OutputToFile = OutputToFile.set_index(['Period', 'Generator'])
214
382
 
215
383
  if sum(1 for ar in mTEPES.ar if sum(1 for g in g2a[ar])) > 1:
216
384
  if pIndPlotOutput == 1:
217
385
  sPAREB = [(p,ar,eb) for p,ar,eb in mTEPES.par*mTEPES.eb if (p,eb) in mTEPES.peb and eb in g2a[ar]]
218
386
  GenInvestToArea = pd.Series(data=[OutputToFile['MW'][p,eb] for p,ar,eb in sPAREB], index=pd.Index(sPAREB)).to_frame(name='MW')
219
- GenInvestToArea.index.names = ['Period', 'Area', 'Generating unit']
220
- chart = alt.Chart(GenInvestToArea.reset_index()).mark_bar().encode(x='Generating unit:O', y='sum(MW):Q', color='Area:N', column='Period:N').properties(width=600, height=400)
387
+ GenInvestToArea.index.names = ['Period', 'Area', 'Generator']
388
+ chart = alt.Chart(GenInvestToArea.reset_index()).mark_bar().encode(x='Generator:O', y='sum(MW):Q', color='Area:N', column='Period:N').properties(width=600, height=400)
221
389
  chart.save(f'{_path}/oT_Plot_GenerationInvestmentPerArea_{CaseName}.html', embed_options={'renderer':'svg'})
222
- TechInvestToArea = pd.Series(data=[sum(OutputToFile['MW'][p,eb] for eb in mTEPES.eb if (p,eb) in mTEPES.peb and eb in g2a[ar] and eb in g2t[gt]) for p,ar,gt in mTEPES.par*mTEPES.gt], index=mTEPES.par*mTEPES.gt).to_frame(name='MW')
223
- TechInvestToArea.index.names = ['Period', 'Area', 'Technology' ]
390
+ TechInvestToArea = pd.Series(data=[sum(OutputToFile['MW'][p,eb] for eb in mTEPES.eb if (p,eb) in mTEPES.peb and eb in g2t[gt] and eb in g2a[ar]) for p,ar,gt in mTEPES.par*mTEPES.gt], index=mTEPES.par*mTEPES.gt).to_frame(name='MW')
391
+ TechInvestToArea.index.names = ['Period', 'Area', 'Technology']
224
392
  chart = alt.Chart(TechInvestToArea.reset_index()).mark_bar().encode(x='Technology:O', y='sum(MW):Q', color='Area:N', column='Period:N').properties(width=600, height=400)
225
393
  chart.save(f'{_path}/oT_Plot_TechnologyInvestmentPerArea_{CaseName}.html', embed_options={'renderer':'svg'})
226
394
 
@@ -230,11 +398,14 @@ def InvestmentResults(DirName, CaseName, OptModel, mTEPES, pIndTechnologyOutput,
230
398
  OutputResults1 = OutputResults1.to_frame(name='Technology')
231
399
  OutputResults2 = OutputToFile
232
400
  OutputResults = pd.concat([OutputResults1, OutputResults2], axis=1)
233
- OutputResults.index.names = ['Period', 'Generating unit']
401
+ OutputResults.index.names = ['Period', 'Generator']
234
402
  OutputResults = OutputResults.reset_index().groupby(['Period', 'Technology']).sum(numeric_only=True)
235
403
  OutputResults['MW'] = round(OutputResults['MW'], 2)
236
404
  OutputResults.reset_index().pivot_table(index=['Period'], columns=['Technology'], values='MW').rename_axis(['Period'], axis=0).to_csv(f'{_path}/oT_Result_TechnologyInvestment_{CaseName}.csv', index=True, sep=',')
237
405
 
406
+ MarketResultsInv = pd.DataFrame()
407
+ MarketResultsInv = pd.concat([MarketResultsInv, OutputResults], axis=1)
408
+
238
409
  if pIndPlotOutput == 1:
239
410
  chart = alt.Chart(OutputResults.reset_index()).mark_bar().encode(x='Technology:O', y='sum(MW):Q', color='Technology:N', column='Period:N').properties(width=600, height=400)
240
411
  chart.save(f'{_path}/oT_Plot_TechnologyInvestment_{CaseName}.html', embed_options={'renderer':'svg'})
@@ -242,18 +413,30 @@ def InvestmentResults(DirName, CaseName, OptModel, mTEPES, pIndTechnologyOutput,
242
413
  # Saving and plotting generation investment cost
243
414
  OutputResults0 = OutputResults
244
415
  OutputToFile = pd.Series(data=[mTEPES.pDiscountedWeight[p] * mTEPES.pGenInvestCost[eb] * OptModel.vGenerationInvest[p,eb]() for p,eb in mTEPES.peb], index=mTEPES.peb)
245
- OutputToFile = OutputToFile.fillna(0).to_frame(name='MEUR').reset_index().rename(columns={'level_0': 'Period', 'level_1': 'Generating unit'}).set_index(['Period', 'Generating unit'])
416
+ OutputToFile = OutputToFile.fillna(0).to_frame(name='MEUR').reset_index().rename(columns={'level_0': 'Period', 'level_1': 'Generator'}).set_index(['Period', 'Generator'])
246
417
 
247
418
  OutputResults1 = pd.Series(data=[gt for p,eb,gt in mTEPES.peb*mTEPES.gt if eb in g2t[gt]], index=mTEPES.peb)
248
419
  OutputResults1 = OutputResults1.to_frame(name='Technology')
249
420
  OutputResults2 = OutputToFile
250
421
  OutputResults = pd.concat([OutputResults1, OutputResults2], axis=1)
251
- OutputResults.index.names = ['Period', 'Generating unit']
422
+ OutputResults.index.names = ['Period', 'Generator']
252
423
  OutputResults = OutputResults.reset_index().groupby(['Period', 'Technology']).sum(numeric_only=True)
253
424
  OutputResults['MEUR'] = round(OutputResults['MEUR'], 2)
254
425
 
255
426
  OutputResults.reset_index().pivot_table(index=['Period'], columns=['Technology'], values='MEUR').rename_axis(['Period'], axis=0).to_csv(f'{_path}/oT_Result_TechnologyInvestmentCost_{CaseName}.csv', index=True, sep=',')
256
427
 
428
+ MarketResultsInv = pd.concat([MarketResultsInv, OutputResults], axis=1)
429
+
430
+ GenTechInvestCost = pd.Series(data=[sum(mTEPES.pDiscountedWeight[p] * mTEPES.pGenInvestCost[eb] * OptModel.vGenerationInvest[p,eb]() for eb in mTEPES.eb if eb in g2t[gt] and (p,eb) in mTEPES.peb ) for p,gt in mTEPES.p*mTEPES.gt], index=mTEPES.p*mTEPES.gt)
431
+ GenTechInvestCost *= 1e3
432
+ GenTechInjection = pd.Series(data=[sum(mTEPES.pDiscountedWeight[p] * mTEPES.pLoadLevelDuration[p,sc,n]() * OptModel.vTotalOutput[p,sc,n,eb]() for sc,n,eb in mTEPES.sc*mTEPES.n*mTEPES.eb if eb in g2t[gt] and (p,eb) in mTEPES.peb and (p,sc,n) in mTEPES.psn) for p,gt in mTEPES.p*mTEPES.gt], index=mTEPES.p*mTEPES.gt)
433
+ GenTechInjection.name = 'Generation'
434
+ MarketResultsInv = pd.concat([MarketResultsInv, GenTechInjection], axis=1)
435
+ LCOE = GenTechInvestCost.div(GenTechInjection)
436
+ LCOE.name = 'LCOE'
437
+ MarketResultsInv = pd.concat([MarketResultsInv, LCOE], axis=1)
438
+ MarketResultsInv.stack().reset_index().pivot_table(index=['level_0','level_1'], columns='level_2', values=0, aggfunc='sum').rename_axis(['Period', 'Technology'], axis=0).rename(columns={'MW': 'Power [MW]', 'MEUR': 'Cost [MEUR]', 'Generation': 'Generation [GWh]', 'LCOE': 'LCOE [EUR/MWh]'}, inplace=False).to_csv(f'{_path}/oT_Result_MarketResultsTechnologyInvestment_{CaseName}.csv', sep=',')
439
+
257
440
  if pIndPlotOutput == 1:
258
441
  chart = alt.Chart(OutputResults.reset_index()).mark_bar().encode(x='Technology:O', y='sum(MEUR):Q', color='Technology:N', column='Period:N').properties(width=600, height=400)
259
442
  chart.save(f'{_path}/oT_Plot_TechnologyInvestmentCost_{CaseName}.html', embed_options={'renderer':'svg'})
@@ -276,23 +459,23 @@ def InvestmentResults(DirName, CaseName, OptModel, mTEPES, pIndTechnologyOutput,
276
459
 
277
460
  if pIndTechnologyOutput == 0 or pIndTechnologyOutput == 2:
278
461
  # Saving generation retirement
279
- OutputToFile = pd.Series(data=[OptModel.vGenerationRetire[p,gd]() for p,gd in mTEPES.pgd], index=mTEPES.pgd)
280
- OutputToFile = OutputToFile.fillna(0).to_frame(name='RetirementDecision').reset_index().rename(columns={'level_0': 'Period', 'level_1': 'Generating unit'})
281
- OutputToFile.pivot_table(index=['Period'], columns=['Generating unit'], values='RetirementDecision').rename_axis(['Period'], axis=0).to_csv(f'{_path}/oT_Result_GenerationRetirementPerUnit_{CaseName}.csv', index=True, sep=',')
462
+ OutputToFile = pd.Series(data=[OptModel.vGenerationRetire[p,gd]() for p,gd in mTEPES.pgd], index=mTEPES.pgd)
463
+ OutputToFile = OutputToFile.fillna(0).to_frame(name='RetirementDecision').reset_index().rename(columns={'level_0': 'Period', 'level_1': 'Generator'})
464
+ OutputToFile.pivot_table(index=['Period'], columns=['Generator'], values='RetirementDecision').rename_axis(['Period'], axis=0).to_csv(f'{_path}/oT_Result_GenerationRetirementPerUnit_{CaseName}.csv', index=True, sep=',')
282
465
  OutputToFile = pd.Series(data=[OptModel.vGenerationRetire[p,gd]()*max(mTEPES.pRatedMaxPowerElec[gd],mTEPES.pRatedMaxCharge[gd]) for p,gd in mTEPES.pgd], index=mTEPES.pgd)
283
466
  OutputToFile *= 1e3
284
- OutputToFile = OutputToFile.fillna(0).to_frame(name='MW' ).reset_index().rename(columns={'level_0': 'Period', 'level_1': 'Generating unit'})
285
- OutputToFile.pivot_table(index=['Period'], columns=['Generating unit'], values='MW').rename_axis(['Period'], axis=0).to_csv(f'{_path}/oT_Result_GenerationRetirement_{CaseName}.csv', index=True, sep=',')
286
- OutputToFile = OutputToFile.set_index(['Period', 'Generating unit'])
467
+ OutputToFile = OutputToFile.fillna(0).to_frame(name='MW' ).reset_index().rename(columns={'level_0': 'Period', 'level_1': 'Generator'})
468
+ OutputToFile.pivot_table(index=['Period'], columns=['Generator'], values='MW').rename_axis(['Period'], axis=0).to_csv(f'{_path}/oT_Result_GenerationRetirement_{CaseName}.csv', index=True, sep=',')
469
+ OutputToFile = OutputToFile.set_index(['Period', 'Generator'])
287
470
 
288
471
  if sum(1 for ar in mTEPES.ar if sum(1 for g in g2a[ar])) > 1:
289
472
  if pIndPlotOutput == 1:
290
473
  sPARGD = [(p,ar,gd) for p,ar,gd in mTEPES.par*mTEPES.gd if (p,gd) in mTEPES.pgd and gd in g2a[ar]]
291
474
  GenRetireToArea = pd.Series(data=[OutputToFile['MW'][p,gd] for p,ar,gd in sPARGD], index=pd.Index(sPARGD)).to_frame(name='MW')
292
- GenRetireToArea.index.names = ['Period', 'Area', 'Generating unit']
293
- chart = alt.Chart(GenRetireToArea.reset_index()).mark_bar().encode(x='Generating unit:O', y='sum(MW):Q', color='Area:N', column='Period:N').properties(width=600, height=400)
475
+ GenRetireToArea.index.names = ['Period', 'Area', 'Generator']
476
+ chart = alt.Chart(GenRetireToArea.reset_index()).mark_bar().encode(x='Generator:O', y='sum(MW):Q', color='Area:N', column='Period:N').properties(width=600, height=400)
294
477
  chart.save(f'{_path}/oT_Plot_GenerationRetirementPerArea_{CaseName}.html', embed_options={'renderer':'svg'})
295
- TechRetireToArea = pd.Series(data=[sum(OutputToFile['MW'][p,gd] for gd in mTEPES.gd if gd in g2a[ar] and gd in g2t[gt]) for p,ar,gt in mTEPES.par*mTEPES.gt], index=mTEPES.par*mTEPES.gt).to_frame(name='MW')
478
+ TechRetireToArea = pd.Series(data=[sum(OutputToFile['MW'][p,gd] for gd in mTEPES.gd if (p,gd) in mTEPES.pgd and gd in g2t[gt] and gd in g2a[ar]) for p,ar,gt in mTEPES.par*mTEPES.gt], index=mTEPES.par*mTEPES.gt).to_frame(name='MW')
296
479
  TechRetireToArea.index.names = ['Period', 'Area', 'Technology' ]
297
480
  chart = alt.Chart(TechRetireToArea.reset_index()).mark_bar().encode(x='Technology:O', y='sum(MW):Q', color='Area:N', column='Period:N').properties(width=600, height=400)
298
481
  chart.save(f'{_path}/oT_Plot_TechnologyRetirementPerArea_{CaseName}.html', embed_options={'renderer':'svg'})
@@ -303,7 +486,7 @@ def InvestmentResults(DirName, CaseName, OptModel, mTEPES, pIndTechnologyOutput,
303
486
  OutputResults1 = OutputResults1.to_frame(name='Technology')
304
487
  OutputResults2 = OutputToFile
305
488
  OutputResults = pd.concat([OutputResults1, OutputResults2], axis=1)
306
- OutputResults.index.names = ['Period', 'Generating unit']
489
+ OutputResults.index.names = ['Period', 'Generator']
307
490
  OutputResults = OutputResults.reset_index().groupby(['Period', 'Technology']).sum(numeric_only=True)
308
491
  OutputResults['MW'] = round(OutputResults['MW'], 2)
309
492
  OutputResults.reset_index().pivot_table(index=['Period'], columns=['Technology'], values='MW').rename_axis([None], axis=0).to_csv(f'{_path}/oT_Result_TechnologyRetirement_{CaseName}.csv', sep=',', index=False)
@@ -356,6 +539,7 @@ def InvestmentResults(DirName, CaseName, OptModel, mTEPES, pIndTechnologyOutput,
356
539
  print('Writing investment results ... ', round(WritingResultsTime), 's')
357
540
 
358
541
 
542
+ # @profile
359
543
  def GenerationOperationResults(DirName, CaseName, OptModel, mTEPES, pIndTechnologyOutput, pIndAreaOutput, pIndPlotOutput):
360
544
  #%% outputting the generation operation
361
545
  _path = os.path.join(DirName, CaseName)
@@ -405,7 +589,7 @@ def GenerationOperationResults(DirName, CaseName, OptModel, mTEPES, pIndTechnolo
405
589
  OutputToFile = OutputToFile.fillna(0.0)
406
590
  OutputToFile *= 1e3
407
591
  if pIndTechnologyOutput == 0 or pIndTechnologyOutput == 2:
408
- OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_GenerationReserveUp_{CaseName}.csv', sep=',')
592
+ OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_GenerationOperatingReserveUp_{CaseName}.csv', sep=',')
409
593
 
410
594
  if pIndTechnologyOutput == 1 or pIndTechnologyOutput == 2:
411
595
  OutputToFile = pd.Series(data=[sum(OutputToFile[p,sc,n,nr] for nr in n2n[nt] if (p,nr) in mTEPES.pnr) for p,sc,n,nt in mTEPES.psnnt], index=mTEPES.psnnt)
@@ -428,7 +612,7 @@ def GenerationOperationResults(DirName, CaseName, OptModel, mTEPES, pIndTechnolo
428
612
  OutputToFile = OutputToFile.fillna(0.0)
429
613
  OutputToFile *= 1e3
430
614
  if pIndTechnologyOutput == 0 or pIndTechnologyOutput == 2:
431
- OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_GenerationReserveDown_{CaseName}.csv', sep=',')
615
+ OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_GenerationOperatingReserveDown_{CaseName}.csv', sep=',')
432
616
 
433
617
  if pIndTechnologyOutput == 1 or pIndTechnologyOutput == 2:
434
618
  OutputToFile = pd.Series(data=[sum(OutputToFile[p,sc,n,nr] for nr in n2n[nt] if (p,nr) in mTEPES.pnr) for p,sc,n,nt in mTEPES.psnnt], index=mTEPES.psnnt)
@@ -445,6 +629,26 @@ def GenerationOperationResults(DirName, CaseName, OptModel, mTEPES, pIndTechnolo
445
629
  OutputToFile = pd.Series(data=[sum(OutputToFile[p,sc,n,eh] for eh in e2e[et] if (p,eh) in mTEPES.peh and mTEPES.pRatedMaxCharge[eh]) for p,sc,n,et in mTEPES.psnet], index=mTEPES.psnet)
446
630
  OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_TechnologyOperatingReserveDownESS_{CaseName}.csv', sep=',')
447
631
 
632
+ if mTEPES.pIndRampReserves == 1 and sum(mTEPES.pRampReserveUp[:,:,:,:]) and mTEPES.nr:
633
+ OutputToFile = pd.Series(data=[OptModel.vRampReserveUp[p,sc,n,nr]() for p,sc,n,nr in mTEPES.psnnr], index=mTEPES.psnnr)
634
+ OutputToFile = OutputToFile.fillna(0.0)
635
+ OutputToFile *= 1e3
636
+ if pIndTechnologyOutput == 0 or pIndTechnologyOutput == 2:
637
+ OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_GenerationRampReserveUp_{CaseName}.csv', sep=',')
638
+ if pIndTechnologyOutput == 1 or pIndTechnologyOutput == 2:
639
+ OutputToFile = pd.Series(data=[sum(OutputToFile[p,sc,n,nr] for nr in n2n[nt] if (p,nr) in mTEPES.pnr) for p,sc,n,nt in mTEPES.psnnt], index=mTEPES.psnnt)
640
+ OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_TechnologyRampReserveUp_{CaseName}.csv', sep=',')
641
+
642
+ if mTEPES.pIndRampReserves == 1 and sum(mTEPES.pRampReserveDw[:,:,:,:]) and mTEPES.nr:
643
+ OutputToFile = pd.Series(data=[OptModel.vRampReserveDw[p,sc,n,nr]() for p,sc,n,nr in mTEPES.psnnr], index=mTEPES.psnnr)
644
+ OutputToFile = OutputToFile.fillna(0.0)
645
+ OutputToFile *= 1e3
646
+ if pIndTechnologyOutput == 0 or pIndTechnologyOutput == 2:
647
+ OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_GenerationRampReserveDown_{CaseName}.csv', sep=',')
648
+ if pIndTechnologyOutput == 1 or pIndTechnologyOutput == 2:
649
+ OutputToFile = pd.Series(data=[sum(OutputToFile[p,sc,n,nr] for nr in n2n[nt] if (p,nr) in mTEPES.pnr) for p,sc,n,nt in mTEPES.psnnt], index=mTEPES.psnnt)
650
+ OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_TechnologyRampReserveDown_{CaseName}.csv', sep=',')
651
+
448
652
  OutputToFile = pd.Series(data=[OptModel.vTotalOutput[p,sc,n,g]() for p,sc,n,g in mTEPES.psng], index=mTEPES.psng)
449
653
  OutputToFile *= 1e3
450
654
  OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_Generation_{CaseName}.csv', sep=',')
@@ -484,8 +688,8 @@ def GenerationOperationResults(DirName, CaseName, OptModel, mTEPES, pIndTechnolo
484
688
  (OptModel.vTotalOutput[p,sc,n,re].ub - OptModel.vTotalOutput[p,sc,n,re]())*mTEPES.pLoadLevelDuration[p,sc,n]() for p,sc,n,re in mTEPES.psnre], index=mTEPES.psnre)
485
689
  OutputToFile2 = pd.Series(data=[(OptModel.vTotalOutput[p,sc,n,re].ub*OptModel.vGenerationInvest[p,re]() )*mTEPES.pLoadLevelDuration[p,sc,n]() if re in mTEPES.gc else
486
690
  (OptModel.vTotalOutput[p,sc,n,re].ub )*mTEPES.pLoadLevelDuration[p,sc,n]() for p,sc,n,re in mTEPES.psnre], index=mTEPES.psnre)
487
- OutputToFile1 = OutputToFile1.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_3'], values='GWh', aggfunc='sum').rename_axis(['Period', 'Scenario', 'Generating unit'], axis=0).rename_axis([None], axis=1)
488
- OutputToFile2 = OutputToFile2.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_3'], values='GWh', aggfunc='sum').rename_axis(['Period', 'Scenario', 'Generating unit'], axis=0).rename_axis([None], axis=1)
691
+ OutputToFile1 = OutputToFile1.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_3'], values='GWh', aggfunc='sum').rename_axis(['Period', 'Scenario', 'Generator'], axis=0).rename_axis([None], axis=1)
692
+ OutputToFile2 = OutputToFile2.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_3'], values='GWh', aggfunc='sum').rename_axis(['Period', 'Scenario', 'Generator'], axis=0).rename_axis([None], axis=1)
489
693
  if pIndTechnologyOutput == 0 or pIndTechnologyOutput == 2:
490
694
  OutputToFile = OutputToFile1.div(OutputToFile2)*1e2
491
695
  OutputToFile = OutputToFile.fillna(0.0)
@@ -534,10 +738,10 @@ def GenerationOperationResults(DirName, CaseName, OptModel, mTEPES, pIndTechnolo
534
738
  if pIndAreaOutput == 1:
535
739
  for ar in mTEPES.ar:
536
740
  if sum(1 for g in g2a[ar]):
537
- sPSNGT = [(p,sc,n,gt) for p,sc,n,gt in mTEPES.psngt if sum(1 for g in g2a[ar] if (p,g) in mTEPES.pg and g in g2t[gt])]
741
+ sPSNGT = [(p,sc,n,gt) for p,sc,n,gt in mTEPES.psngt if sum(1 for g in g2t[gt] if g in g2a[ar] and (p,g) in mTEPES.pg)]
538
742
  if sPSNGT:
539
743
  if sum(OutputToFile[:,:,:,:]):
540
- OutputResults = pd.Series(data=[sum(OutputToFile[p,sc,n,g] for g in g2a[ar] if (p,g) in mTEPES.pg and g in g2t[gt]) for p,sc,n,gt in sPSNGT], index=pd.Index(sPSNGT))
744
+ OutputResults = pd.Series(data=[sum(OutputToFile[p,sc,n,g] for g in g2t[gt] if g in g2a[ar] and (p,g) in mTEPES.pg) for p,sc,n,gt in sPSNGT], index=pd.Index(sPSNGT))
541
745
  OutputResults.to_frame(name='MtCO2').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MtCO2', aggfunc='sum').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_TechnologyEmission_{CaseName}_{ar}.csv', sep=',')
542
746
 
543
747
  if sum(OutputToFile[:,:,:,:]):
@@ -573,9 +777,9 @@ def GenerationOperationResults(DirName, CaseName, OptModel, mTEPES, pIndTechnolo
573
777
  if pIndAreaOutput == 1:
574
778
  for ar in mTEPES.ar:
575
779
  if sum(1 for g in g2a[ar]):
576
- sPSNGT = [(p,sc,n,gt) for p,sc,n,gt in mTEPES.psngt if sum(1 for g in g2a[ar] if (p,g) in mTEPES.pg and g in g2t[gt])]
780
+ sPSNGT = [(p,sc,n,gt) for p,sc,n,gt in mTEPES.psngt if sum(1 for g in g2t[gt] if g in g2a[ar] and (p,g) in mTEPES.pg)]
577
781
  if sPSNGT:
578
- OutputToFile = pd.Series(data=[sum(OptModel.vTotalOutput[p,sc,n,g]()*mTEPES.pLoadLevelDuration[p,sc,n]() for g in g2a[ar] if (p,g) in mTEPES.pg and g in g2t[gt]) for p,sc,n,gt in sPSNGT], index=pd.Index(sPSNGT))
782
+ OutputToFile = pd.Series(data=[sum(OptModel.vTotalOutput[p,sc,n,g]()*mTEPES.pLoadLevelDuration[p,sc,n]() for g in g2t[gt] if g in g2a[ar] and (p,g) in mTEPES.pg) for p,sc,n,gt in sPSNGT], index=pd.Index(sPSNGT))
579
783
  OutputToFile.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='GWh', aggfunc='sum').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_TechnologyGenerationEnergy_{CaseName}_{ar}.csv', sep=',')
580
784
 
581
785
  if pIndPlotOutput == 1:
@@ -588,6 +792,7 @@ def GenerationOperationResults(DirName, CaseName, OptModel, mTEPES, pIndTechnolo
588
792
  print('Writing generation operation results ... ', round(WritingResultsTime), 's')
589
793
 
590
794
 
795
+ # @profile
591
796
  def GenerationOperationHeatResults(DirName, CaseName, OptModel, mTEPES, pIndTechnologyOutput, pIndAreaOutput, pIndPlotOutput):
592
797
  #%% outputting the generation operation
593
798
  _path = os.path.join(DirName, CaseName)
@@ -650,10 +855,10 @@ def GenerationOperationHeatResults(DirName, CaseName, OptModel, mTEPES, pIndTech
650
855
  if sum(1 for ar in mTEPES.ar if sum(1 for chp in g2a[ar])) > 1:
651
856
  if pIndAreaOutput == 1:
652
857
  for ar in mTEPES.ar:
653
- if sum(1 for chp in g2a[ar] if chp in g2t[gt]):
654
- sPSNGT = [(p,sc,n,gt) for p,sc,n,gt in mTEPES.psngt if sum(1 for chp in g2a[ar] if (p,chp) in mTEPES.pchp and chp in g2t[gt])]
858
+ if sum(1 for chp in g2t[gt] if chp in g2a[ar]):
859
+ sPSNGT = [(p,sc,n,gt) for p,sc,n,gt in mTEPES.psngt if sum(1 for chp in g2t[gt] if chp in g2a[ar] and (p,chp) in mTEPES.pchp)]
655
860
  if sPSNGT:
656
- OutputToFile = pd.Series(data=[sum(OptModel.vTotalOutputHeat[p,sc,n,chp]()*mTEPES.pLoadLevelDuration[p,sc,n]() for chp in g2a[ar] if (p,chp) in mTEPES.pchp and chp in g2t[gt]) for p,sc,n,gt in sPSNGT], index=pd.Index(sPSNGT))
861
+ OutputToFile = pd.Series(data=[sum(OptModel.vTotalOutputHeat[p,sc,n,chp]()*mTEPES.pLoadLevelDuration[p,sc,n]() for chp in g2a[ar] if chp in g2t[gt] and (p,chp) in mTEPES.pchp) for p,sc,n,gt in sPSNGT], index=pd.Index(sPSNGT))
657
862
  OutputToFile.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='GWh', aggfunc='sum').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_TechnologyGenerationEnergyHeat_{CaseName}_{ar}.csv', sep=',')
658
863
 
659
864
  if pIndPlotOutput == 1:
@@ -666,6 +871,7 @@ def GenerationOperationHeatResults(DirName, CaseName, OptModel, mTEPES, pIndTech
666
871
  print('Writing heat operation results ... ', round(WritingResultsTime), 's')
667
872
 
668
873
 
874
+ # @profile
669
875
  def ESSOperationResults(DirName, CaseName, OptModel, mTEPES, pIndTechnologyOutput, pIndAreaOutput, pIndPlotOutput):
670
876
  # %% outputting the ESS operation
671
877
  _path = os.path.join(DirName, CaseName)
@@ -786,8 +992,8 @@ def ESSOperationResults(DirName, CaseName, OptModel, mTEPES, pIndTechnologyOutpu
786
992
  (OptModel.vTotalOutput[p,sc,n,es].ub - OptModel.vTotalOutput[p,sc,n,es]())*mTEPES.pLoadLevelDuration[p,sc,n]() for p,sc,n,es in mTEPES.psnes], index=mTEPES.psnes)
787
993
  OutputToFile2 = pd.Series(data=[(OptModel.vTotalOutput[p,sc,n,es].ub*OptModel.vGenerationInvest[p,es]() )*mTEPES.pLoadLevelDuration[p,sc,n]() if es in mTEPES.ec else
788
994
  (OptModel.vTotalOutput[p,sc,n,es].ub )*mTEPES.pLoadLevelDuration[p,sc,n]() for p,sc,n,es in mTEPES.psnes], index=mTEPES.psnes)
789
- OutputToFile1 = OutputToFile1.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_3'], values='GWh', aggfunc='sum').rename_axis(['Period', 'Scenario', 'Generating unit'], axis=0).rename_axis([None], axis=1)
790
- OutputToFile2 = OutputToFile2.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_3'], values='GWh', aggfunc='sum').rename_axis(['Period', 'Scenario', 'Generating unit'], axis=0).rename_axis([None], axis=1)
995
+ OutputToFile1 = OutputToFile1.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_3'], values='GWh', aggfunc='sum').rename_axis(['Period', 'Scenario', 'Generator'], axis=0).rename_axis([None], axis=1)
996
+ OutputToFile2 = OutputToFile2.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_3'], values='GWh', aggfunc='sum').rename_axis(['Period', 'Scenario', 'Generator'], axis=0).rename_axis([None], axis=1)
791
997
 
792
998
  if pIndTechnologyOutput == 0 or pIndTechnologyOutput == 2:
793
999
  OutputToFile = OutputToFile1.div(OutputToFile2)*1e2
@@ -807,6 +1013,7 @@ def ESSOperationResults(DirName, CaseName, OptModel, mTEPES, pIndTechnologyOutpu
807
1013
  print('Writing ESS operation results ... ', round(WritingResultsTime), 's')
808
1014
 
809
1015
 
1016
+ # @profile
810
1017
  def ReservoirOperationResults(DirName, CaseName, OptModel, mTEPES, pIndTechnologyOutput, pIndPlotOutput):
811
1018
  # %% outputting the reservoir operation
812
1019
  _path = os.path.join(DirName, CaseName)
@@ -814,9 +1021,9 @@ def ReservoirOperationResults(DirName, CaseName, OptModel, mTEPES, pIndTechnolog
814
1021
 
815
1022
  # technology to hydro units (o2h)
816
1023
  o2h = defaultdict(list)
817
- for ht,h in mTEPES.ht*mTEPES.h :
818
- if (ht,h ) in mTEPES.t2g:
819
- o2h[ht].append(h )
1024
+ for ht,h in mTEPES.ht*mTEPES.h:
1025
+ if (ht,h) in mTEPES.t2g:
1026
+ o2h[ht].append(h)
820
1027
 
821
1028
  # tolerance to avoid division by 0
822
1029
  pEpsilon = 1e-6
@@ -848,7 +1055,7 @@ def ReservoirOperationResults(DirName, CaseName, OptModel, mTEPES, pIndTechnolog
848
1055
  if len(OutputToFile) and pIndPlotOutput == 1:
849
1056
  WaterValue = OutputToFile.to_frame(name='WaterValue').reset_index().pivot_table(index=['level_0','level_1','level_3','level_4'], values='WaterValue').rename_axis(['level_0','level_1','level_2','level_3'], axis=0).loc[:,:,:,:]
850
1057
  for p,sc in mTEPES.ps:
851
- chart = LinePlots(p, sc, WaterValue, 'Generating unit', 'LoadLevel', 'EUR/dam3', 'average')
1058
+ chart = LinePlots(p, sc, WaterValue, 'Generator', 'LoadLevel', 'EUR/dam3', 'average')
852
1059
  chart.save(f'{_path}/oT_Plot_MarginalWaterValue_{CaseName}_{p}_{sc}.html', embed_options={'renderer': 'svg'})
853
1060
 
854
1061
  WritingResultsTime = time.time() - StartTime
@@ -856,6 +1063,7 @@ def ReservoirOperationResults(DirName, CaseName, OptModel, mTEPES, pIndTechnolog
856
1063
  print('Writing reservoir operation results ... ', round(WritingResultsTime), 's')
857
1064
 
858
1065
 
1066
+ # @profile
859
1067
  def NetworkH2OperationResults(DirName, CaseName, OptModel, mTEPES):
860
1068
  # %% outputting the hydrogen pipeline network operation
861
1069
  _path = os.path.join(DirName, CaseName)
@@ -881,8 +1089,14 @@ def NetworkH2OperationResults(DirName, CaseName, OptModel, mTEPES):
881
1089
  if (gt,el) in mTEPES.t2g:
882
1090
  e2t[gt].append(el)
883
1091
 
884
- sPSNARND = [(p,sc,n,ar,nd) for p,sc,n,ar,nd in mTEPES.psnar*mTEPES.nd if sum(1 for el in e2n[nd]) + sum(1 for nf,cc in lout[nd]) + sum(1 for ni,cc in lin[nd]) and (nd,ar) in mTEPES.ndar]
885
- sPSNARNDGT = [(p,sc,n,ar,nd,gt) for p,sc,n,ar,nd,gt in sPSNARND*mTEPES.gt if sum(1 for el in e2t[gt] if (p,el) in mTEPES.pg) and (nd,ar) in mTEPES.ndar]
1092
+ # nodes to area (d2a)
1093
+ d2a = defaultdict(list)
1094
+ for ar,nd in mTEPES.ar*mTEPES.nd:
1095
+ if (nd,ar) in mTEPES.ndar:
1096
+ d2a[ar].append(nd)
1097
+
1098
+ sPSNARND = [(p,sc,n,ar,nd) for p,sc,n,ar,nd in mTEPES.psn*mTEPES.ar*mTEPES.nd if nd in d2a[ar] and sum(1 for el in e2n[nd]) + sum(1 for nf,cc in lout[nd]) + sum(1 for ni,cc in lin[nd])]
1099
+ sPSNARNDGT = [(p,sc,n,ar,nd,gt) for p,sc,n,ar,nd,gt in sPSNARND*mTEPES.gt if nd in d2a[ar] and sum(1 for el in e2t[gt] if (p,el) in mTEPES.pg) ]
886
1100
 
887
1101
  OutputResults2 = pd.Series(data=[ sum(OptModel.vESSTotalCharge[p,sc,n,el ]()*mTEPES.pLoadLevelDuration[p,sc,n]()/mTEPES.pProductionFunctionH2[el] for el in mTEPES.el if el in e2n[nd] and el in e2t[gt]) for p,sc,n,ar,nd,gt in sPSNARNDGT], index=pd.Index(sPSNARNDGT)).to_frame(name='Generation' ).reset_index().pivot_table(index=['level_0','level_1','level_2','level_3','level_4'], columns='level_5', values='Generation', aggfunc='sum')
888
1102
  OutputResults3 = pd.Series(data=[ OptModel.vH2NS [p,sc,n,nd ]() for p,sc,n,ar,nd in sPSNARND ], index=pd.Index(sPSNARND )).to_frame(name='HydrogenNotServed')
@@ -1044,6 +1258,7 @@ def NetworkH2OperationResults(DirName, CaseName, OptModel, mTEPES):
1044
1258
  print('Writing hydrogen operation results ... ', round(WritingResultsTime), 's')
1045
1259
 
1046
1260
 
1261
+ # @profile
1047
1262
  def NetworkHeatOperationResults(DirName, CaseName, OptModel, mTEPES):
1048
1263
  # %% outputting the heat pipe network operation
1049
1264
  _path = os.path.join(DirName, CaseName)
@@ -1081,8 +1296,14 @@ def NetworkHeatOperationResults(DirName, CaseName, OptModel, mTEPES):
1081
1296
  if (gt,hp) in mTEPES.t2g:
1082
1297
  h2t[gt].append(hp)
1083
1298
 
1084
- sPSNARND = [(p,sc,n,ar,nd) for p,sc,n,ar,nd in mTEPES.psnar*mTEPES.nd if sum(1 for ch in c2n[nd]) + sum(1 for hp in h2n[nd]) + sum(1 for nf,cc in lout[nd]) + sum(1 for ni,cc in lin[nd]) and (nd,ar) in mTEPES.ndar]
1085
- sPSNARNDGT = [(p,sc,n,ar,nd,gt) for p,sc,n,ar,nd,gt in sPSNARND*mTEPES.gt if sum(1 for ch in c2t[gt] if (p,ch) in mTEPES.pg) + sum(1 for hp in h2t[gt] if (p,hp) in mTEPES.pg) and (nd,ar) in mTEPES.ndar]
1299
+ # nodes to area (d2a)
1300
+ d2a = defaultdict(list)
1301
+ for ar,nd in mTEPES.ar*mTEPES.nd:
1302
+ if (nd,ar) in mTEPES.ndar:
1303
+ d2a[ar].append(nd)
1304
+
1305
+ sPSNARND = [(p,sc,n,ar,nd) for p,sc,n,ar,nd in mTEPES.psn*mTEPES.ar*mTEPES.nd if nd in d2a[ar] and sum(1 for ch in c2n[nd]) + sum(1 for hp in h2n[nd]) + sum(1 for nf,cc in lout[nd]) + sum(1 for ni,cc in lin[nd])]
1306
+ sPSNARNDGT = [(p,sc,n,ar,nd,gt) for p,sc,n,ar,nd,gt in sPSNARND*mTEPES.gt if nd in d2a[ar] and sum(1 for ch in c2t[gt] if (p,ch) in mTEPES.pg) + sum(1 for hp in h2t[gt] if (p,hp) in mTEPES.pg) ]
1086
1307
 
1087
1308
  OutputResults2 = pd.Series(data=[ sum(OptModel.vESSTotalCharge [p,sc,n,hp ]()*mTEPES.pLoadLevelDuration[p,sc,n]()/mTEPES.pProductionFunctionHeat[hp] for hp in mTEPES.hp if hp in h2n[nd] and hp in h2t[gt]) for p,sc,n,ar,nd,gt in sPSNARNDGT], index=pd.Index(sPSNARNDGT)).to_frame(name='GenerationHeatPumps').reset_index().pivot_table(index=['level_0','level_1','level_2','level_3','level_4'], columns='level_5', values='GenerationHeatPumps', aggfunc='sum')
1088
1309
  OutputResults3 = pd.Series(data=[ sum(OptModel.vTotalOutput [p,sc,n,ch ]()*mTEPES.pLoadLevelDuration[p,sc,n]()/mTEPES.pPower2HeatRatio [ch] for ch in mTEPES.ch if ch in c2n[nd] and ch in c2t[gt] and ch not in mTEPES.bo) for p,sc,n,ar,nd,gt in sPSNARNDGT], index=pd.Index(sPSNARNDGT)).to_frame(name='GenerationCHPs' ).reset_index().pivot_table(index=['level_0','level_1','level_2','level_3','level_4'], columns='level_5', values='GenerationCHPs' , aggfunc='sum')
@@ -1272,6 +1493,7 @@ def NetworkHeatOperationResults(DirName, CaseName, OptModel, mTEPES):
1272
1493
  print('Writing heat netwk operation results ... ', round(WritingResultsTime), 's')
1273
1494
 
1274
1495
 
1496
+ # @profile
1275
1497
  def OperationSummaryResults(DirName, CaseName, OptModel, mTEPES):
1276
1498
  #%% outputting the generation operation
1277
1499
  _path = os.path.join(DirName, CaseName)
@@ -1365,71 +1587,69 @@ def OperationSummaryResults(DirName, CaseName, OptModel, mTEPES):
1365
1587
 
1366
1588
  # LCOE per technology
1367
1589
  if mTEPES.gc:
1368
- GenTechInvestCost = pd.Series(data=[sum(mTEPES.pDiscountedWeight[p] * mTEPES.pGenInvestCost[gc] * OptModel.vGenerationInvest[p,gc]() for p, gc in mTEPES.pgc if gc in g2t[gt]) for gt in mTEPES.gt], index=mTEPES.gt)
1369
- GenTechInjection = pd.Series(data=[sum(OptModel.vTotalOutput [p,sc,n,gc]()*mTEPES.pLoadLevelDuration[p,sc,n ]() for p,sc,n,gc in mTEPES.psngc if gc in g2t[gt]) for gt in mTEPES.gt], index=mTEPES.gt)
1590
+ GenTechInvestCost = pd.Series(data=[sum(mTEPES.pDiscountedWeight[p] * mTEPES.pGenInvestCost[gc] * OptModel.vGenerationInvest[p,gc]() for p, gc in mTEPES.pgc if gc in g2t[gt]) for gt in mTEPES.gt], index=mTEPES.gt)
1591
+ GenTechInjection = pd.Series(data=[sum(mTEPES.pDiscountedWeight[p] * mTEPES.pLoadLevelDuration[p,sc,n]() * OptModel.vTotalOutput[p,sc,n,gc]() for p,sc,n,gc in mTEPES.psngc if gc in g2t[gt]) for gt in mTEPES.gt], index=mTEPES.gt)
1370
1592
  GenTechInvestCost *= 1e3
1371
- LCOE = GenTechInvestCost.div(GenTechInjection).to_frame(name='EUR/MWh')
1372
- LCOE.rename_axis(['Technology'], axis=0).to_csv(f'{_path}/oT_Result_TechnologyLCOE_{CaseName}.csv', index=True, sep=',')
1593
+ LCOE = GenTechInvestCost.div(GenTechInjection).to_frame(name='EUR/MWh').rename_axis(['Technology'], axis=0).to_csv(f'{_path}/oT_Result_TechnologyLCOE_{CaseName}.csv', index=True, sep=',')
1373
1594
 
1374
- # LCOE per technology
1595
+ # LCOH per technology
1375
1596
  if mTEPES.gb:
1376
- GenTechInvestCost = pd.Series(data=[sum(mTEPES.pDiscountedWeight[p] * mTEPES.pGenInvestCost[gb] * OptModel.vGenerationInvest[p,gb]() for p, gb in mTEPES.pgb if gb in g2t[gt]) for gt in mTEPES.gt], index=mTEPES.gt)
1377
- GenTechInjection = pd.Series(data=[sum(OptModel.vTotalOutputHeat [p,sc,n,gb]()*mTEPES.pLoadLevelDuration[p,sc,n ]() for p,sc,n,gb in mTEPES.psngb if gb in g2t[gt]) for gt in mTEPES.gt], index=mTEPES.gt)
1597
+ GenTechInvestCost = pd.Series(data=[sum(mTEPES.pDiscountedWeight[p] * mTEPES.pGenInvestCost[gb] * OptModel.vGenerationInvest[p,gb]() for p, gb in mTEPES.pgb if gb in g2t[gt]) for gt in mTEPES.gt], index=mTEPES.gt)
1598
+ GenTechInjection = pd.Series(data=[sum(mTEPES.pDiscountedWeight[p] * mTEPES.pLoadLevelDuration[p,sc,n]() * OptModel.vTotalOutputHeat[p,sc,n,gb]() for p,sc,n,gb in mTEPES.psngb if gb in g2t[gt]) for gt in mTEPES.gt], index=mTEPES.gt)
1378
1599
  GenTechInvestCost *= 1e3
1379
- LCOH = GenTechInvestCost.div(GenTechInjection).to_frame(name='EUR/MWh')
1380
- LCOH.rename_axis(['Technology'], axis=0).to_csv(f'{_path}/oT_Result_TechnologyLCOH_{CaseName}.csv', index=True, sep=',')
1600
+ LCOH = GenTechInvestCost.div(GenTechInjection).to_frame(name='EUR/MWh').rename_axis(['Technology'], axis=0).to_csv(f'{_path}/oT_Result_TechnologyLCOH_{CaseName}.csv', index=True, sep=',')
1381
1601
 
1382
1602
  WritingResultsTime = time.time() - StartTime
1383
1603
  StartTime = time.time()
1384
1604
  print('Writing KPI summary results ... ', round(WritingResultsTime), 's')
1385
-
1386
- StartTime = time.time()
1387
- t2g = pd.DataFrame(mTEPES.t2g).set_index(1)
1388
- n2g = pd.DataFrame(mTEPES.n2g).set_index(1)
1389
- z2g = pd.DataFrame(mTEPES.z2g).set_index(1)
1390
- a2g = pd.DataFrame(mTEPES.a2g).set_index(1)
1391
- r2g = pd.DataFrame(mTEPES.r2g).set_index(1)
1392
- OutputToFile01 = pd.Series(data=[t2g[0][g] for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Technology' )
1393
- OutputToFile02 = pd.Series(data=[n2g[0][g] for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Node' )
1394
- OutputToFile03 = pd.Series(data=[z2g[0][g] for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Zone' )
1395
- OutputToFile04 = pd.Series(data=[a2g[0][g] for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Area' )
1396
- OutputToFile05 = pd.Series(data=[r2g[0][g] for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Region' )
1397
- OutputToFile06 = pd.Series(data=[mTEPES.pLoadLevelDuration[p,sc,n ]() for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='LoadLevelDuration [h]' )
1398
- OutputToFile07 = pd.Series(data=[OptModel.vCommitment [p,sc,n,g]() if g in mTEPES.nr else 0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Commitment {0,1}' )
1399
- OutputToFile08 = pd.Series(data=[OptModel.vStartUp [p,sc,n,g]() if g in mTEPES.nr else 0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='StartUp {0,1}' )
1400
- OutputToFile09 = pd.Series(data=[OptModel.vShutDown [p,sc,n,g]() if g in mTEPES.nr else 0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='ShutDown {0,1}' )
1401
- OutputToFile10 = pd.Series(data=[OptModel.vTotalOutput [p,sc,n,g].ub for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='MaxPower [MW]' )
1402
- OutputToFile11 = pd.Series(data=[OptModel.vTotalOutput [p,sc,n,g].lb for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='MinPower [MW]' )
1403
- OutputToFile12 = pd.Series(data=[OptModel.vTotalOutput [p,sc,n,g]()*mTEPES.pLoadLevelDuration[p,sc,n]() for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='EnergyProduction [GWh]' )
1404
- OutputToFile13 = pd.Series(data=[OptModel.vESSTotalCharge [p,sc,n,g]()*mTEPES.pLoadLevelDuration[p,sc,n]() if g in mTEPES.es else 0.0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='EnergyConsumption [GWh]')
1405
- OutputToFile14 = pd.Series(data=[OptModel.vEnergyOutflows [p,sc,n,g]()*mTEPES.pLoadLevelDuration[p,sc,n]() if g in mTEPES.es else 0.0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Outflows [GWh]' )
1406
- OutputToFile15 = pd.Series(data=[OptModel.vESSInventory [p,sc,n,g]() if g in mTEPES.es else 0.0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Inventory [GWh]' )
1407
- OutputToFile16 = pd.Series(data=[OptModel.vESSSpillage [p,sc,n,g]() if g in mTEPES.es else 0.0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Spillage [GWh]' )
1408
- OutputToFile17 = pd.Series(data=[(OptModel.vTotalOutput [p,sc,n,g].ub-OptModel.vTotalOutput[p,sc,n,g]())*mTEPES.pLoadLevelDuration[p,sc,n]() if g in mTEPES.re else 0.0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Curtailment [GWh]' )
1409
- OutputToFile18 = pd.Series(data=[OptModel.vReserveUp [p,sc,n,g]() if g in mTEPES.nr else 0.0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='ReserveUpGen [MW]' )
1410
- OutputToFile19 = pd.Series(data=[OptModel.vReserveDown [p,sc,n,g]() if g in mTEPES.nr else 0.0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='ReserveDownGen [MW]' )
1411
- OutputToFile20 = pd.Series(data=[OptModel.vESSReserveUp [p,sc,n,g]() if g in mTEPES.es else 0.0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='ReserveUpCons [MW]' )
1412
- OutputToFile21 = pd.Series(data=[OptModel.vESSReserveDown [p,sc,n,g]() if g in mTEPES.es else 0.0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='ReserveDownCons [MW]' )
1413
- OutputToFile22 = pd.Series(data=[OptModel.vTotalOutput [p,sc,n,g]()*mTEPES.pLoadLevelDuration[p,sc,n]()*mTEPES.pEmissionRate[g] if g not in mTEPES.bo
1414
- else OptModel.vTotalOutputHeat [p,sc,n,g]()*mTEPES.pLoadLevelDuration[p,sc,n]()*mTEPES.pEmissionRate[g] for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Emissions [MtCO2]' )
1415
-
1416
- OutputToFile10 *= 1e3
1417
- OutputToFile11 *= 1e3
1418
- OutputToFile18 *= 1e3
1419
- OutputToFile19 *= 1e3
1420
- OutputToFile20 *= 1e3
1421
- OutputToFile21 *= 1e3
1422
- OutputToFile22 *= 1e-3
1423
-
1424
- OutputResults = pd.concat([OutputToFile01, OutputToFile02, OutputToFile03, OutputToFile04, OutputToFile05, OutputToFile06, OutputToFile07, OutputToFile08, OutputToFile09, OutputToFile10,
1425
- OutputToFile11, OutputToFile12, OutputToFile13, OutputToFile14, OutputToFile15, OutputToFile16, OutputToFile17, OutputToFile18, OutputToFile19, OutputToFile20,
1426
- OutputToFile21, OutputToFile22], axis=1)
1427
- # OutputResults.rename_axis(['Period', 'Scenario', 'LoadLevel', 'Generator'], axis=0).to_csv (f'{_path}/oT_Result_SummaryGeneration_{CaseName}.csv', sep=',')
1428
- # OutputResults.rename_axis(['Period', 'Scenario', 'LoadLevel', 'Generator'], axis=0).to_parquet(f'{_path}/oT_Result_SummaryGeneration_{CaseName}.parquet', engine='pyarrow')
1429
-
1430
- WritingResultsTime = time.time() - StartTime
1431
- StartTime = time.time()
1432
- print('Writing generation summary results ... ', round(WritingResultsTime), 's')
1605
+ #
1606
+ # StartTime = time.time()
1607
+ # t2g = pd.DataFrame(mTEPES.t2g).set_index(1)
1608
+ # n2g = pd.DataFrame(mTEPES.n2g).set_index(1)
1609
+ # z2g = pd.DataFrame(mTEPES.z2g).set_index(1)
1610
+ # a2g = pd.DataFrame(mTEPES.a2g).set_index(1)
1611
+ # r2g = pd.DataFrame(mTEPES.r2g).set_index(1)
1612
+ # OutputToFile01 = pd.Series(data=[t2g[0][g] for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Technology' )
1613
+ # OutputToFile02 = pd.Series(data=[n2g[0][g] for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Node' )
1614
+ # OutputToFile03 = pd.Series(data=[z2g[0][g] for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Zone' )
1615
+ # OutputToFile04 = pd.Series(data=[a2g[0][g] for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Area' )
1616
+ # OutputToFile05 = pd.Series(data=[r2g[0][g] for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Region' )
1617
+ # OutputToFile06 = pd.Series(data=[mTEPES.pLoadLevelDuration[p,sc,n ]() for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='LoadLevelDuration [h]' )
1618
+ # OutputToFile07 = pd.Series(data=[OptModel.vCommitment [p,sc,n,g]() if g in mTEPES.nr else 0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Commitment {0,1}' )
1619
+ # OutputToFile08 = pd.Series(data=[OptModel.vStartUp [p,sc,n,g]() if g in mTEPES.nr else 0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='StartUp {0,1}' )
1620
+ # OutputToFile09 = pd.Series(data=[OptModel.vShutDown [p,sc,n,g]() if g in mTEPES.nr else 0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='ShutDown {0,1}' )
1621
+ # OutputToFile10 = pd.Series(data=[OptModel.vTotalOutput [p,sc,n,g].ub for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='MaxPower [MW]' )
1622
+ # OutputToFile11 = pd.Series(data=[OptModel.vTotalOutput [p,sc,n,g].lb for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='MinPower [MW]' )
1623
+ # OutputToFile12 = pd.Series(data=[OptModel.vTotalOutput [p,sc,n,g]()*mTEPES.pLoadLevelDuration[p,sc,n]() for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='EnergyProduction [GWh]' )
1624
+ # OutputToFile13 = pd.Series(data=[OptModel.vESSTotalCharge [p,sc,n,g]()*mTEPES.pLoadLevelDuration[p,sc,n]() if g in mTEPES.es else 0.0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='EnergyConsumption [GWh]')
1625
+ # OutputToFile14 = pd.Series(data=[OptModel.vEnergyOutflows [p,sc,n,g]()*mTEPES.pLoadLevelDuration[p,sc,n]() if g in mTEPES.es else 0.0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Outflows [GWh]' )
1626
+ # OutputToFile15 = pd.Series(data=[OptModel.vESSInventory [p,sc,n,g]() if g in mTEPES.es else 0.0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Inventory [GWh]' )
1627
+ # OutputToFile16 = pd.Series(data=[OptModel.vESSSpillage [p,sc,n,g]() if g in mTEPES.es else 0.0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Spillage [GWh]' )
1628
+ # OutputToFile17 = pd.Series(data=[(OptModel.vTotalOutput [p,sc,n,g].ub-OptModel.vTotalOutput[p,sc,n,g]())*mTEPES.pLoadLevelDuration[p,sc,n]() if g in mTEPES.re else 0.0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Curtailment [GWh]' )
1629
+ # OutputToFile18 = pd.Series(data=[OptModel.vReserveUp [p,sc,n,g]() if g in mTEPES.nr else 0.0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='ReserveUpGen [MW]' )
1630
+ # OutputToFile19 = pd.Series(data=[OptModel.vReserveDown [p,sc,n,g]() if g in mTEPES.nr else 0.0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='ReserveDownGen [MW]' )
1631
+ # OutputToFile20 = pd.Series(data=[OptModel.vESSReserveUp [p,sc,n,g]() if g in mTEPES.es else 0.0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='ReserveUpCons [MW]' )
1632
+ # OutputToFile21 = pd.Series(data=[OptModel.vESSReserveDown [p,sc,n,g]() if g in mTEPES.es else 0.0 for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='ReserveDownCons [MW]' )
1633
+ # OutputToFile22 = pd.Series(data=[OptModel.vTotalOutput [p,sc,n,g]()*mTEPES.pLoadLevelDuration[p,sc,n]()*mTEPES.pEmissionRate[g] if g not in mTEPES.bo
1634
+ # else OptModel.vTotalOutputHeat [p,sc,n,g]()*mTEPES.pLoadLevelDuration[p,sc,n]()*mTEPES.pEmissionRate[g] for p,sc,n,g in mTEPES.psng], index=mTEPES.psng).to_frame(name='Emissions [MtCO2]' )
1635
+ #
1636
+ # OutputToFile10 *= 1e3
1637
+ # OutputToFile11 *= 1e3
1638
+ # OutputToFile18 *= 1e3
1639
+ # OutputToFile19 *= 1e3
1640
+ # OutputToFile20 *= 1e3
1641
+ # OutputToFile21 *= 1e3
1642
+ # OutputToFile22 *= 1e-3
1643
+ #
1644
+ # OutputResults = pd.concat([OutputToFile01, OutputToFile02, OutputToFile03, OutputToFile04, OutputToFile05, OutputToFile06, OutputToFile07, OutputToFile08, OutputToFile09, OutputToFile10,
1645
+ # OutputToFile11, OutputToFile12, OutputToFile13, OutputToFile14, OutputToFile15, OutputToFile16, OutputToFile17, OutputToFile18, OutputToFile19, OutputToFile20,
1646
+ # OutputToFile21, OutputToFile22], axis=1)
1647
+ # # OutputResults.rename_axis(['Period', 'Scenario', 'LoadLevel', 'Generator'], axis=0).to_csv (f'{_path}/oT_Result_SummaryGeneration_{CaseName}.csv', sep=',')
1648
+ # # OutputResults.rename_axis(['Period', 'Scenario', 'LoadLevel', 'Generator'], axis=0).to_parquet(f'{_path}/oT_Result_SummaryGeneration_{CaseName}.parquet', engine='pyarrow')
1649
+ #
1650
+ # WritingResultsTime = time.time() - StartTime
1651
+ # StartTime = time.time()
1652
+ # print('Writing generation summary results ... ', round(WritingResultsTime), 's')
1433
1653
 
1434
1654
  ndzn = pd.DataFrame(mTEPES.ndzn).set_index(0)
1435
1655
  ndar = pd.DataFrame(mTEPES.ndar).set_index(0)
@@ -1455,6 +1675,7 @@ def OperationSummaryResults(DirName, CaseName, OptModel, mTEPES):
1455
1675
  print('Writing elect network summary results ... ', round(WritingResultsTime), 's')
1456
1676
 
1457
1677
 
1678
+ # @profile
1458
1679
  def FlexibilityResults(DirName, CaseName, OptModel, mTEPES):
1459
1680
  # %% outputting the flexibility
1460
1681
  _path = os.path.join(DirName, CaseName)
@@ -1518,6 +1739,7 @@ def FlexibilityResults(DirName, CaseName, OptModel, mTEPES):
1518
1739
  print('Writing flexibility results ... ', round(WritingResultsTime), 's')
1519
1740
 
1520
1741
 
1742
+ # @profile
1521
1743
  def NetworkOperationResults(DirName, CaseName, OptModel, mTEPES):
1522
1744
  # %% outputting the electric network operation
1523
1745
  _path = os.path.join(DirName, CaseName)
@@ -1590,6 +1812,7 @@ def NetworkOperationResults(DirName, CaseName, OptModel, mTEPES):
1590
1812
  print('Writing elect netwk operation results ... ', round(WritingResultsTime), 's')
1591
1813
 
1592
1814
 
1815
+ # @profile
1593
1816
  def MarginalResults(DirName, CaseName, OptModel, mTEPES, pIndPlotOutput):
1594
1817
  # %% outputting marginal results
1595
1818
  _path = os.path.join(DirName, CaseName)
@@ -1637,14 +1860,14 @@ def MarginalResults(DirName, CaseName, OptModel, mTEPES, pIndPlotOutput):
1637
1860
  # tolerance to consider 0 a number
1638
1861
  pEpsilon = 1e-6
1639
1862
 
1640
- #%% outputting the incremental variable cost of each generating unit (neither ESS nor boilers) with power surplus
1863
+ #%% outputting the incremental variable cost of each Generator (neither ESS nor boilers) with power surplus
1641
1864
  sPSNARG = [(p,sc,n,ar,g) for p,sc,n,ar,g in mTEPES.psn*mTEPES.a2g if g not in mTEPES.eh and g not in mTEPES.bo and (p,g) in mTEPES.pg]
1642
1865
  OutputToFile = pd.Series(data=[(mTEPES.pLinearVarCost[p,sc,n,g]+mTEPES.pEmissionVarCost[p,sc,n,g]) if OptModel.vTotalOutput[p,sc,n,g].ub - OptModel.vTotalOutput[p,sc,n,g]() > pEpsilon else math.inf for p,sc,n,ar,g in sPSNARG], index=pd.Index(sPSNARG))
1643
1866
  OutputToFile *= 1e3
1644
1867
 
1645
1868
  OutputToFile = OutputToFile.to_frame(name='EUR/MWh').reset_index().pivot_table(index=['level_0','level_1','level_2','level_3'], columns='level_4', values='EUR/MWh')
1646
1869
  OutputToFile.rename_axis(['Period', 'Scenario', 'LoadLevel', 'Area'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_MarginalIncrementalVariableCost_{CaseName}.csv', sep=',')
1647
- IncrementalGens = pd.Series('N/A', index=mTEPES.psnar).to_frame(name='Generating unit')
1870
+ IncrementalGens = pd.Series('N/A', index=mTEPES.psnar).to_frame(name='Generator')
1648
1871
  for p,sc,n,ar in mTEPES.psnar:
1649
1872
  if all(g not in mTEPES.eh and g not in mTEPES.bo and (p, g) in mTEPES.pg and (ar, g) in mTEPES.a2g for g in mTEPES.g):
1650
1873
  if len(OutputToFile.loc[(p,sc,n,ar)]) > 1:
@@ -1716,7 +1939,7 @@ def MarginalResults(DirName, CaseName, OptModel, mTEPES, pIndPlotOutput):
1716
1939
  if mTEPES.gc:
1717
1940
  sPSSTAR = [(p,sc,st,ar) for p,sc,st,ar in mTEPES.ps*mTEPES.st*mTEPES.ar if mTEPES.pReserveMargin[p,ar] and st == mTEPES.Last_st and sum(1 for g in mTEPES.g if g in g2a[ar]) and (p,sc,n) in mTEPES.psn and sum(mTEPES.pRatedMaxPowerElec[g] * mTEPES.pAvailability[g]() / (1.0-mTEPES.pEFOR[g]) for g in mTEPES.g if g in g2a[ar] and g not in (mTEPES.gc or mTEPES.gd)) <= mTEPES.pDemandElecPeak[p,ar] * mTEPES.pReserveMargin[p,ar]]
1718
1941
  if sPSSTAR:
1719
- OutputResults = pd.Series(data=[mTEPES.pDuals["".join([f"eAdequacyReserveMarginElec_{p}_{sc}_{st}{ar}"])] for p,sc,st,ar in sPSSTAR], index=pd.Index(sPSSTAR))
1942
+ OutputResults = pd.Series(data=[mTEPES.pDuals[''.join([f'eAdequacyReserveMarginElec_{p}_{sc}_{st}{ar}'])] for p,sc,st,ar in sPSSTAR], index=pd.Index(sPSSTAR))
1720
1943
  OutputResults.to_frame(name='RM').reset_index().pivot_table(index=['level_0','level_1'], columns='level_3', values='RM').rename_axis(['Period', 'Scenario'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_MarginalReserveMargin_{CaseName}.csv', sep=',')
1721
1944
 
1722
1945
  if mTEPES.pIndHeat == 1:
@@ -1724,17 +1947,17 @@ def MarginalResults(DirName, CaseName, OptModel, mTEPES, pIndPlotOutput):
1724
1947
  if mTEPES.gc:
1725
1948
  sPSSTAR = [(p,sc,st,ar) for p,sc,st,ar in mTEPES.ps*mTEPES.st*mTEPES.ar if mTEPES.pReserveMarginHeat[p,ar] and st == mTEPES.Last_st and sum(1 for g in mTEPES.g if g in g2a[ar]) and (p,sc,n) in mTEPES.psn and sum(mTEPES.pRatedMaxPowerHeat[g] * mTEPES.pAvailability[g]() / (1.0-mTEPES.pEFOR[g]) for g in mTEPES.g if g in g2a[ar] and g not in (mTEPES.gc or mTEPES.gd)) <= mTEPES.pDemandHeatPeak[p,ar] * mTEPES.pReserveMarginHeat[p,ar]]
1726
1949
  if sPSSTAR:
1727
- OutputResults = pd.Series(data=[mTEPES.pDuals["".join([f"eAdequacyReserveMarginHeat_{p}_{sc}_{st}{ar}"])] for p,sc,st,ar in sPSSTAR], index=pd.Index(sPSSTAR))
1950
+ OutputResults = pd.Series(data=[mTEPES.pDuals[''.join([f'eAdequacyReserveMarginHeat_{p}_{sc}_{st}{ar}'])] for p,sc,st,ar in sPSSTAR], index=pd.Index(sPSSTAR))
1728
1951
  OutputResults.to_frame(name='RM').reset_index().pivot_table(index=['level_0','level_1'], columns='level_3', values='RM').rename_axis(['Period', 'Scenario'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_MarginalReserveMarginHeat_{CaseName}.csv', sep=',')
1729
1952
 
1730
1953
  sPSSTAR = [(p,sc,st,ar) for p,sc,st,ar in mTEPES.ps*mTEPES.st*mTEPES.ar if mTEPES.pEmission[p,ar] < math.inf and st == mTEPES.Last_st and (p,sc,n) in mTEPES.psn and sum(mTEPES.pEmissionVarCost[p,sc,na,g] for na,g in mTEPES.na*mTEPES.g if (ar,g) in mTEPES.a2g and (p,g) in mTEPES.pg)]
1731
1954
  if sPSSTAR:
1732
- OutputResults = pd.Series(data=[mTEPES.pDuals["".join([f"eMaxSystemEmission_{p}_{sc}_{st}{ar}"])] for p,sc,st,ar in sPSSTAR], index=pd.Index(sPSSTAR))
1955
+ OutputResults = pd.Series(data=[mTEPES.pDuals[''.join([f'eMaxSystemEmission_{p}_{sc}_{st}{ar}'])] for p,sc,st,ar in sPSSTAR], index=pd.Index(sPSSTAR))
1733
1956
  OutputResults.to_frame(name='EM').reset_index().pivot_table(index=['level_0','level_1'], columns='level_3', values='EM').rename_axis(['Period', 'Scenario'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_MarginalEmission_{CaseName}.csv', sep=',')
1734
1957
 
1735
1958
  sPSSTAR = [(p,sc,st,ar) for p,sc,st,ar in mTEPES.ps*mTEPES.st*mTEPES.ar if mTEPES.pRESEnergy[p,ar] and st == mTEPES.Last_st and (p,sc,n) in mTEPES.psn]
1736
1959
  if sPSSTAR:
1737
- OutputResults = pd.Series(data=[mTEPES.pDuals["".join([f"eMinSystemRESEnergy_{p}_{sc}_{st}{ar}"])] for p,sc,st,ar in sPSSTAR], index=pd.Index(sPSSTAR))
1960
+ OutputResults = pd.Series(data=[mTEPES.pDuals[''.join([f'eMinSystemRESEnergy_{p}_{sc}_{st}{ar}'])] for p,sc,st,ar in sPSSTAR], index=pd.Index(sPSSTAR))
1738
1961
  OutputResults *= 1e-3*sum(mTEPES.pLoadLevelDuration[p,sc,na]() for na in mTEPES.na)
1739
1962
  OutputResults.to_frame(name='RES').reset_index().pivot_table(index=['level_0','level_1'], columns='level_3', values='RES').rename_axis(['Period', 'Scenario'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_MarginalRESEnergy_{CaseName}.csv', sep=',')
1740
1963
 
@@ -1775,7 +1998,7 @@ def MarginalResults(DirName, CaseName, OptModel, mTEPES, pIndPlotOutput):
1775
1998
  if len(OutputToFile) and pIndPlotOutput == 1:
1776
1999
  WaterValue = OutputToFile.to_frame(name='WaterValue').reset_index().pivot_table(index=['level_0','level_1','level_3','level_4'], values='WaterValue').rename_axis(['level_0','level_1','level_2','level_3'], axis=0).loc[:,:,:,:]
1777
2000
  for p,sc in mTEPES.ps:
1778
- chart = LinePlots(p, sc, WaterValue, 'Generating unit', 'LoadLevel', 'EUR/MWh', 'average')
2001
+ chart = LinePlots(p, sc, WaterValue, 'Generator', 'LoadLevel', 'EUR/MWh', 'average')
1779
2002
  chart.save(f'{_path}/oT_Plot_MarginalEnergyValue_{CaseName}_{p}_{sc}.html', embed_options={'renderer': 'svg'})
1780
2003
 
1781
2004
  # #%% Reduced cost for NetworkInvestment
@@ -1798,6 +2021,7 @@ def MarginalResults(DirName, CaseName, OptModel, mTEPES, pIndPlotOutput):
1798
2021
  print('Writing marginal information results ... ', round(WritingResultsTime), 's')
1799
2022
 
1800
2023
 
2024
+ # @profile
1801
2025
  def ReliabilityResults(DirName, CaseName, OptModel, mTEPES):
1802
2026
  # %% outputting the reliability indexes
1803
2027
  _path = os.path.join(DirName, CaseName)
@@ -1827,7 +2051,7 @@ def ReliabilityResults(DirName, CaseName, OptModel, mTEPES):
1827
2051
  OutputToFile2 = pd.Series(data=[ mTEPES.pDemandElec [p,sc,n,nd] for p,sc,n,nd in mTEPES.psnnd], index=mTEPES.psnnd)
1828
2052
  OutputToFile = OutputToFile2 - OutputToFile1
1829
2053
  OutputToFile *= 1e3
1830
- OutputToFile = OutputToFile.to_frame(name='MW' )
2054
+ OutputToFile = OutputToFile.to_frame(name='MW')
1831
2055
  OutputToFile.reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW', aggfunc='sum').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_NetDemandNetwork_{CaseName}.csv', sep=',')
1832
2056
  OutputToFile.reset_index().pivot_table(index=['level_0','level_1','level_2'], values='MW', aggfunc='sum').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_NetDemand_{CaseName}.csv', sep=',')
1833
2057
 
@@ -1839,7 +2063,7 @@ def ReliabilityResults(DirName, CaseName, OptModel, mTEPES):
1839
2063
  OutputToFile2[p,sc] = pDemandElec.loc [(p,sc)].reset_index().pivot_table(index=['level_0'], values=0, aggfunc='sum')[0].max()
1840
2064
  ReserveMargin1 = OutputToFile1 - OutputToFile2
1841
2065
  ReserveMargin2 = (OutputToFile1 - OutputToFile2)/OutputToFile2
1842
- ReserveMargin1.to_frame(name='MW' ).rename_axis(['Period', 'Scenario'], axis=0).to_csv(f'{_path}/oT_Result_ReserveMargin_{CaseName}.csv', sep=',')
2066
+ ReserveMargin1.to_frame(name='MW' ).rename_axis(['Period', 'Scenario'], axis=0).to_csv(f'{_path}/oT_Result_ReserveMargin_{CaseName}.csv', sep=',')
1843
2067
  ReserveMargin2.to_frame(name='p.u.').rename_axis(['Period', 'Scenario'], axis=0).to_csv(f'{_path}/oT_Result_ReserveMarginPerUnit_{CaseName}.csv', sep=',')
1844
2068
 
1845
2069
  # Determination of the index: Largest Unit
@@ -1853,6 +2077,8 @@ def ReliabilityResults(DirName, CaseName, OptModel, mTEPES):
1853
2077
  WritingResultsTime = time.time() - StartTime
1854
2078
  print('Writing reliability indexes ... ', round(WritingResultsTime), 's')
1855
2079
 
2080
+
2081
+ # @profile
1856
2082
  def CostSummaryResults(DirName, CaseName, OptModel, mTEPES):
1857
2083
  # %% outputting the system costs and revenues
1858
2084
  _path = os.path.join(DirName, CaseName)
@@ -1883,6 +2109,7 @@ def CostSummaryResults(DirName, CaseName, OptModel, mTEPES):
1883
2109
  print('Writing cost summary results ... ', round(WritingResultsTime), 's')
1884
2110
 
1885
2111
 
2112
+ # @profile
1886
2113
  def EconomicResults(DirName, CaseName, OptModel, mTEPES, pIndAreaOutput, pIndPlotOutput):
1887
2114
  # %% outputting the system costs and revenues
1888
2115
  _path = os.path.join(DirName, CaseName)
@@ -1950,9 +2177,9 @@ def EconomicResults(DirName, CaseName, OptModel, mTEPES, pIndAreaOutput, pIndPlo
1950
2177
  if pIndAreaOutput == 1:
1951
2178
  for ar in mTEPES.ar:
1952
2179
  if sum(1 for g in g2a[ar]):
1953
- sPSNGT = [(p,sc,n,gt) for p,sc,n,gt in mTEPES.psngt if sum(1 for g in g2a[ar] if (p,g) in mTEPES.pg and g in g2t[gt])]
2180
+ sPSNGT = [(p,sc,n,gt) for p,sc,n,gt in mTEPES.psngt if sum(1 for g in g2t[gt] if g in g2a[ar] and (p,g) in mTEPES.pg)]
1954
2181
  if sPSNGT:
1955
- OutputToFile = pd.Series(data=[sum(OptModel.vTotalOutput[p,sc,n,g]()*mTEPES.pLoadLevelDuration[p,sc,n]() for g in g2a[ar] if (p,g) in mTEPES.pg and g in g2t[gt]) for p,sc,n,gt in sPSNGT], index=pd.Index(sPSNGT))
2182
+ OutputToFile = pd.Series(data=[sum(OptModel.vTotalOutput[p,sc,n,g]()*mTEPES.pLoadLevelDuration[p,sc,n]() for g in g2t[gt] if g in g2a[ar] and (p,g) in mTEPES.pg) for p,sc,n,gt in sPSNGT], index=pd.Index(sPSNGT))
1956
2183
  OutputToFile.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='GWh', aggfunc='sum').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_TechnologyGenerationEnergy_{CaseName}_{ar}.csv', sep=',')
1957
2184
 
1958
2185
  if pIndPlotOutput == 1:
@@ -1960,10 +2187,10 @@ def EconomicResults(DirName, CaseName, OptModel, mTEPES, pIndAreaOutput, pIndPlo
1960
2187
  chart = PiePlots(p, sc, OutputToFile, 'Technology', '%')
1961
2188
  chart.save(f'{_path}/oT_Plot_TechnologyGenerationEnergy_{CaseName}_{p}_{sc}_{ar}.html', embed_options={'renderer': 'svg'})
1962
2189
 
1963
- sPSNARND = [(p,sc,n,ar,nd) for p,sc,n,ar,nd in mTEPES.psnar*mTEPES.nd if sum(1 for g in g2n[nd]) + sum(1 for nf,cc in lout[nd]) + sum(1 for ni,cc in lin[nd]) and (nd,ar) in mTEPES.ndar]
1964
- sPSNARNDGT = [(p,sc,n,ar,nd,gt) for p,sc,n,ar,nd,gt in sPSNARND*mTEPES.gt if sum(1 for g in g2t[gt] if (p,g ) in mTEPES.pg ) and (nd,ar) in mTEPES.ndar]
1965
- sPSNARNDRT = [(p,sc,n,ar,nd,rt) for p,sc,n,ar,nd,rt in sPSNARND*mTEPES.rt if sum(1 for re in r2r[rt] if (p,re) in mTEPES.pre) and (nd,ar) in mTEPES.ndar]
1966
- sPSNARNDET = [(p,sc,n,ar,nd,et) for p,sc,n,ar,nd,et in sPSNARND*mTEPES.et if sum(1 for eh in e2e[et] if (p,eh) in mTEPES.peh) and (nd,ar) in mTEPES.ndar]
2190
+ sPSNARND = [(p,sc,n,ar,nd) for p,sc,n,ar,nd in mTEPES.psn*mTEPES.ar*mTEPES.nd if nd in d2a[ar] and sum(1 for g in g2n[nd]) + sum(1 for nf,cc in lout[nd]) + sum(1 for ni,cc in lin[nd])]
2191
+ sPSNARNDGT = [(p,sc,n,ar,nd,gt) for p,sc,n,ar,nd,gt in sPSNARND*mTEPES.gt if sum(1 for g in g2t[gt] if (p,g ) in mTEPES.pg )]
2192
+ sPSNARNDRT = [(p,sc,n,ar,nd,rt) for p,sc,n,ar,nd,rt in sPSNARND*mTEPES.rt if sum(1 for re in r2r[rt] if (p,re) in mTEPES.pre)]
2193
+ sPSNARNDET = [(p,sc,n,ar,nd,et) for p,sc,n,ar,nd,et in sPSNARND*mTEPES.et if sum(1 for eh in e2e[et] if (p,eh) in mTEPES.peh)]
1967
2194
 
1968
2195
  if sum(1 for nr in mTEPES.nr if nr not in mTEPES.eh):
1969
2196
  OutputResults01 = pd.Series(data=[ sum(OptModel.vTotalOutput [p,sc,n,nr ]()*mTEPES.pLoadLevelDuration[p,sc,n]() for nr in g2n[nd] if (p,nr) in mTEPES.pnr and nr in g2t[gt] and nr not in mTEPES.eh) for p,sc,n,ar,nd,gt in sPSNARNDGT], index=pd.Index(sPSNARNDGT)).to_frame(name='Generation' ).reset_index().pivot_table(index=['level_0','level_1','level_2','level_3','level_4'], columns='level_5', values='Generation' , aggfunc='sum')
@@ -1997,16 +2224,17 @@ def EconomicResults(DirName, CaseName, OptModel, mTEPES, pIndAreaOutput, pIndPlo
1997
2224
  OutputResults.stack().reset_index().pivot_table(index=['level_0','level_1' ,'level_5'], columns='level_3', values=0, aggfunc='sum').rename_axis(['Period', 'Scenario' , 'Technology' ], axis=0).to_csv(f'{_path}/oT_Result_BalanceEnergyPerArea_{CaseName}.csv', sep=',')
1998
2225
 
1999
2226
  #%% outputting the demand and the LSRMC of electricity
2000
- sPSSTNND = [(p,sc,st,n,ar,nd) for p,sc,st,n,ar,nd in mTEPES.s2n*mTEPES.ar*mTEPES.nd if nd in d2a[ar] and sum(1 for g in g2n[nd]) + sum(1 for nf,cc in lout[nd]) + sum(1 for ni,cc in lin[nd]) and (p,sc,n) in mTEPES.psn]
2227
+ sPSSTNARND = [(p,sc,st,n,ar,nd) for p,sc,st,n,ar,nd in mTEPES.s2n*mTEPES.ar*mTEPES.nd if nd in d2a[ar] and sum(1 for g in g2n[nd]) + sum(1 for nf,cc in lout[nd]) + sum(1 for ni,cc in lin[nd]) and (p,sc,n) in mTEPES.psn]
2001
2228
 
2002
- OutputResults = pd.Series(data=[mTEPES.pDuals["".join([f"eBalanceElec_{p}_{sc}_{st}('{n}', '{nd}')"])]/mTEPES.pPeriodProb[p,sc]()/mTEPES.pLoadLevelDuration[p,sc,n]() for p,sc,st,n,ar,nd in sPSSTNND], index=pd.Index(sPSSTNND))
2229
+ OutputResults = pd.Series(data=[mTEPES.pDuals["".join([f"eBalanceElec_{p}_{sc}_{st}('{n}', '{nd}')"])]/mTEPES.pPeriodProb[p,sc]()/mTEPES.pLoadLevelDuration[p,sc,n]() for p,sc,st,n,ar,nd in sPSSTNARND], index=pd.Index(sPSSTNARND))
2003
2230
  OutputResults *= 1e3
2004
2231
  OutputResults.index = [idx[:2] + idx[3:] for idx in OutputResults.index]
2005
2232
 
2006
2233
  #%% outputting the generator power output
2007
- sPSNARNDNR = [(p,sc,n,ar,nd,nr) for p,sc,n,ar,nd,nr in mTEPES.psnar*mTEPES.nd*mTEPES.nr if nr in g2n[nd] and sum(1 for nf,cc in lout[nd]) + sum(1 for ni,cc in lin[nd]) and (nd,ar) in mTEPES.ndar and (p,nr) in mTEPES.pnr and nr not in mTEPES.eh]
2008
- sPSNARNDRE = [(p,sc,n,ar,nd,re) for p,sc,n,ar,nd,re in mTEPES.psnar*mTEPES.nd*mTEPES.re if re in g2n[nd] and sum(1 for nf,cc in lout[nd]) + sum(1 for ni,cc in lin[nd]) and (nd,ar) in mTEPES.ndar and (p,re) in mTEPES.pre ]
2009
- sPSNARNDEH = [(p,sc,n,ar,nd,eh) for p,sc,n,ar,nd,eh in mTEPES.psnar*mTEPES.nd*mTEPES.eh if eh in g2n[nd] and sum(1 for nf,cc in lout[nd]) + sum(1 for ni,cc in lin[nd]) and (nd,ar) in mTEPES.ndar and (p,eh) in mTEPES.peh ]
2234
+ sPSNARNDG = [(p,sc,n,ar,nd,g ) for p,sc,n,ar,nd,g in sPSNARND*mTEPES.g if g in g2n[nd] and (p,g ) in mTEPES.pg ]
2235
+ sPSNARNDNR = [(p,sc,n,ar,nd,nr) for p,sc,n,ar,nd,nr in sPSNARND*mTEPES.nr if nr in g2n[nd] and (p,nr) in mTEPES.pnr and nr not in mTEPES.eh]
2236
+ sPSNARNDRE = [(p,sc,n,ar,nd,re) for p,sc,n,ar,nd,re in sPSNARND*mTEPES.re if re in g2n[nd] and (p,re) in mTEPES.pre ]
2237
+ sPSNARNDEH = [(p,sc,n,ar,nd,eh) for p,sc,n,ar,nd,eh in sPSNARND*mTEPES.eh if eh in g2n[nd] and (p,eh) in mTEPES.peh ]
2010
2238
 
2011
2239
  if sum(1 for nr in mTEPES.nr if nr not in mTEPES.eh):
2012
2240
  OutputResults01 = pd.Series(data=[ OptModel.vTotalOutput [p,sc,n,nr ]()*mTEPES.pLoadLevelDuration[p,sc,n]() for p,sc,n,ar,nd,nr in sPSNARNDNR], index=pd.Index(sPSNARNDNR)).to_frame(name='Generation' ).reset_index().pivot_table(index=['level_0','level_1','level_2','level_3','level_4'], columns='level_5', values='Generation' , aggfunc='sum')
@@ -2022,32 +2250,38 @@ def EconomicResults(DirName, CaseName, OptModel, mTEPES, pIndAreaOutput, pIndPlo
2022
2250
  OutputResults09 = pd.Series(data=[-sum(OptModel.vLineLosses [p,sc,n,nd,nf,cc]()*mTEPES.pLoadLevelDuration[p,sc,n]() for nf,cc in loutl[nd] if (p,nd,nf,cc) in mTEPES.pla) for p,sc,n,ar,nd in sPSNARND ], index=pd.Index(sPSNARND )).to_frame(name='LineLossesOut' )
2023
2251
  OutputResults10 = pd.Series(data=[-sum(OptModel.vLineLosses [p,sc,n,ni,nd,cc]()*mTEPES.pLoadLevelDuration[p,sc,n]() for ni,cc in linl [nd] if (p,ni,nd,cc) in mTEPES.pla) for p,sc,n,ar,nd in sPSNARND ], index=pd.Index(sPSNARND )).to_frame(name='LineLossesIn' )
2024
2252
 
2025
- MarketResultsDem = pd.DataFrame()
2253
+ MarketResultsDem = pd.DataFrame()
2026
2254
  if mTEPES.eh:
2027
2255
  MarketResultsDem = pd.concat([MarketResultsDem, OutputResults04],axis=1)
2028
-
2029
2256
  MarketResultsDem = pd.concat([MarketResultsDem, OutputResults06],axis=1)
2030
-
2031
2257
  if mTEPES.ll:
2032
2258
  MarketResultsDem = pd.concat([MarketResultsDem, OutputResults09, OutputResults10], axis=1)
2033
2259
 
2260
+ MarketResultsDem *= -1e3
2261
+ MarketResultsDem = pd.concat([MarketResultsDem.sum(axis=1), OutputResults], axis=1)
2262
+ MarketResultsDem.stack().reset_index().pivot_table(index=['level_0','level_1','level_2','level_3','level_4'], columns='level_5', values=0, aggfunc='sum').rename_axis(['Period', 'Scenario', 'LoadLevel', 'Area', 'Node'], axis=0).rename(columns={0: 'Demand [MWh]', 1: 'LSRMC [EUR/MWh]'}, inplace=False).to_csv(f'{_path}/oT_Result_MarketResultsDemand_{CaseName}.csv', sep=',')
2263
+
2034
2264
  MarketResultsGen = pd.DataFrame()
2035
2265
  # Check if there are non-RES generators
2036
2266
  if sum(1 for nr in mTEPES.nr if nr not in mTEPES.eh):
2037
- MarketResultsGen = pd.concat([MarketResultsGen,OutputResults01], axis=1)
2038
-
2267
+ MarketResultsGen = pd.concat([MarketResultsGen, OutputResults01], axis=1)
2039
2268
  if mTEPES.re:
2040
2269
  MarketResultsGen = pd.concat([MarketResultsGen, OutputResults02], axis=1)
2041
-
2042
2270
  if mTEPES.eh:
2043
2271
  MarketResultsGen = pd.concat([MarketResultsGen, OutputResults03], axis=1)
2044
2272
 
2045
- MarketResultsDem *= -1e3
2046
- MarketResultsDem = pd.concat([MarketResultsDem.sum(axis=1), OutputResults], axis=1)
2047
- MarketResultsDem.stack().reset_index().pivot_table(index=['level_0','level_1','level_2','level_3','level_4'], columns='level_5', values=0, aggfunc='sum').rename_axis(['Period', 'Scenario', 'LoadLevel', 'Area', 'Node'], axis=0).rename(columns={0: 'Demand', 1: 'LSRMC'}, inplace=False).to_csv(f'{_path}/oT_Result_MarketResultsDemand_{CaseName}.csv', sep=',')
2273
+ OutputResults11 = pd.Series(data=[(OptModel.vTotalOutput[p,sc,n,g].ub*OptModel.vGenerationInvest[p,g]() - OptModel.vTotalOutput[p,sc,n,g]())*mTEPES.pLoadLevelDuration[p,sc,n]() if g in mTEPES.re and g in mTEPES.gc else
2274
+ (OptModel.vTotalOutput[p,sc,n,g].ub - OptModel.vTotalOutput[p,sc,n,g]())*mTEPES.pLoadLevelDuration[p,sc,n]() if g in mTEPES.re and g not in mTEPES.gc else
2275
+ OptModel.vESSSpillage[p,sc,n,g]() if g in mTEPES.es else 0.0 for p,sc,n,ar,nd,g in sPSNARNDG], index=pd.Index(sPSNARNDG))
2276
+ OutputResults12 = pd.Series(data=[ OptModel.vTotalOutput [p,sc,n,g]()*mTEPES.pLoadLevelDuration[p,sc,n]()*mTEPES.pEmissionRate[g]/1e3 if g not in mTEPES.bo else
2277
+ OptModel.vTotalOutputHeat[p,sc,n,g]()*mTEPES.pLoadLevelDuration[p,sc,n]()*mTEPES.pEmissionRate[g]/1e3 for p,sc,n,ar,nd,g in sPSNARNDG], index=pd.Index(sPSNARNDG))
2278
+
2279
+ OutputResults11.index = [idx[:6] for idx in OutputResults11.index]
2280
+ OutputResults12.index = [idx[:6] for idx in OutputResults12.index]
2048
2281
 
2049
2282
  MarketResultsGen *= 1e3
2050
- MarketResultsGen.stack().reset_index().pivot_table(index=['level_0','level_1','level_2','level_3','level_4','level_5']).rename_axis(['Period', 'Scenario', 'LoadLevel', 'Area', 'Node', 'Generator'], axis=0).rename(columns={0: 'Generation'}, inplace=False).to_csv(f'{_path}/oT_Result_MarketResultsGeneration_{CaseName}.csv', sep=',')
2283
+ MarketResultsGen = pd.concat([MarketResultsGen.stack(), OutputResults11, OutputResults12], axis=1)
2284
+ MarketResultsGen.reset_index().pivot_table(index=['level_0','level_1','level_2','level_3','level_4','level_5']).rename_axis(['Period', 'Scenario', 'LoadLevel', 'Area', 'Node', 'Generator'], axis=0).rename(columns={0: 'Generation [MWh]', 1: 'Curtailment [MWh]', 2: 'Emissions [MtCO2]'}, inplace=False).to_csv(f'{_path}/oT_Result_MarketResultsGeneration_{CaseName}.csv', sep=',')
2051
2285
 
2052
2286
  # df=OutputResults.stack().rename_axis(['Period', 'Scenario', 'LoadLevel', 'Area', 'Node', 'Technology'], axis=0).reset_index()
2053
2287
  # df['AreaFin'] = df['Area']
@@ -2153,14 +2387,25 @@ def EconomicResults(DirName, CaseName, OptModel, mTEPES, pIndAreaOutput, pIndPlo
2153
2387
  OutputResults.loc[(OutputResults['Period'] == p) & (OutputResults['Scenario'] == sc), 'MEUR/year'] = OutputResults.loc[(OutputResults['Period'] == p) & (OutputResults['Scenario'] == sc), 'MEUR'] / mTEPES.pDiscountedWeight[p] / mTEPES.pScenProb[p,sc]()
2154
2388
  OutputResults.to_csv(f'{_path}/oT_Result_CostSummary_{CaseName}_{ar}.csv', sep=',', index=False)
2155
2389
 
2156
- sPSSTNNDG = [(p,sc,st,n,nd,g) for p,sc,st,n,nd,g in mTEPES.s2n*mTEPES.n2g if (p,g) in mTEPES.pg and (p,sc,n) in mTEPES.psn]
2157
- OutputResults = pd.Series(data=[ mTEPES.pDuals["".join([f"eBalanceElec_{p}_{sc}_{st}('{n}', '{nd}')"])]/mTEPES.pPeriodProb[p,sc]()/mTEPES.pLoadLevelDuration[p,sc,n]()*OptModel.vTotalOutput [p,sc,n,g]() for p,sc,st,n,nd,g in sPSSTNNDG], index=pd.Index(sPSSTNNDG))
2390
+ sPSSTNG = [(p,sc,st,n, g) for p,sc,st,n, g in mTEPES.s2n*mTEPES.g if (p,sc,n) in mTEPES.psn and (p,g) in mTEPES.pg]
2391
+ sPSSTNND = [(p,sc,st,n,nd ) for p,sc,st,n,nd in mTEPES.s2n*mTEPES.nd if sum(1 for g in g2n[nd]) + sum(1 for nf,cc in lout[nd]) + sum(1 for ni,cc in lin[nd]) and (p,sc,n) in mTEPES.psn]
2392
+ sPSSTNNDG = [(p,sc,st,n,nd,g) for p,sc,st,n,nd,g in sPSSTNND*mTEPES.g if (nd,g) in mTEPES.n2g and (p,g) in mTEPES.pg]
2393
+ OutputResults = pd.Series(data=[ mTEPES.pDuals["".join([f"eBalanceElec_{p}_{sc}_{st}('{n}', '{nd}')"])]/mTEPES.pPeriodProb[p,sc]()/mTEPES.pLoadLevelDuration[p,sc,n]()*OptModel.vTotalOutput [p,sc,n,g]() for p,sc,st,n,nd,g in sPSSTNNDG if (p,g) in mTEPES.pg], index=pd.Index(sPSSTNNDG))
2394
+ MeanOutput = pd.Series(data=[ OptModel.vTotalOutput [p,sc,n,g]() for p,sc,st,n, g in sPSSTNG if (p,g) in mTEPES.pg], index=pd.Index(sPSSTNG )).groupby(level=4).mean()
2395
+ MeanOutput *= 1e-3
2158
2396
  OutputResults.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_3'], columns='level_5', values='MEUR').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_RevenueEnergyGeneration_{CaseName}.csv', sep=',')
2397
+ OutputResults = pd.Series(data=[ mTEPES.pDuals["".join([f"eBalanceElec_{p}_{sc}_{st}('{n}', '{nd}')"])]/mTEPES.pPeriodProb[p,sc]()/mTEPES.pLoadLevelDuration[p,sc,n]()*OptModel.vTotalOutput [p,sc,n,g]()/MeanOutput[g] for p,sc,st,n,nd,g in sPSSTNNDG], index=pd.Index(sPSSTNNDG))
2398
+ OutputResults.to_frame(name='EUR/MWh').reset_index().pivot_table(index=['level_0','level_1','level_3'], columns='level_5', values='EUR/MWh').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_GenerationCapturedSRMC_{CaseName}.csv', sep=',')
2159
2399
 
2160
2400
  if mTEPES.eh:
2161
- sPSSTNNDES = [(p,sc,st,n,nd,eh) for p,sc,st,n,nd,eh in mTEPES.s2n*mTEPES.n2g if eh in mTEPES.eh if (p,eh) in mTEPES.peh and (p,sc,n) in mTEPES.psn]
2162
- OutputResults = pd.Series(data=[-mTEPES.pDuals["".join([f"eBalanceElec_{p}_{sc}_{st}('{n}', '{nd}')"])]/mTEPES.pPeriodProb[p,sc]()/mTEPES.pLoadLevelDuration[p,sc,n]()*OptModel.vESSTotalCharge[p,sc,n,eh]() for p,sc,st,n,nd,eh in sPSSTNNDES], index=pd.Index(sPSSTNNDES))
2401
+ sPSSTNES = [(p,sc,st,n, eh) for p,sc,st,n, eh in mTEPES.s2n*mTEPES.eh if (p,sc,n) in mTEPES.psn and (p,eh) in mTEPES.peh]
2402
+ sPSSTNNDEH = [(p,sc,st,n,nd,eh) for p,sc,st,n,nd,eh in sPSSTNND*mTEPES.eh if (nd,eh) in mTEPES.n2g and (p,eh) in mTEPES.peh]
2403
+ OutputResults = pd.Series(data=[-mTEPES.pDuals["".join([f"eBalanceElec_{p}_{sc}_{st}('{n}', '{nd}')"])]/mTEPES.pPeriodProb[p,sc]()/mTEPES.pLoadLevelDuration[p,sc,n]()*OptModel.vESSTotalCharge[p,sc,n,eh]() for p,sc,st,n,nd,eh in sPSSTNNDEH if (p,eh) in mTEPES.peh], index=pd.Index(sPSSTNNDEH))
2404
+ MeanOutput = pd.Series(data=[ OptModel.vESSTotalCharge[p,sc,n,eh]() for p,sc,st,n, eh in sPSSTNES if (p,eh) in mTEPES.peh], index=pd.Index(sPSSTNES )).groupby(level=4).mean()
2405
+ MeanOutput *= 1e-3
2163
2406
  OutputResults.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_3'], columns='level_5', values='MEUR').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_RevenueEnergyConsumption_{CaseName}.csv', sep=',')
2407
+ OutputResults = pd.Series(data=[-mTEPES.pDuals["".join([f"eBalanceElec_{p}_{sc}_{st}('{n}', '{nd}')"])]/mTEPES.pPeriodProb[p,sc]()/mTEPES.pLoadLevelDuration[p,sc,n]()*OptModel.vESSTotalCharge[p,sc,n,eh]()/MeanOutput[eh] for p,sc,st,n,nd,eh in sPSSTNNDEH if (p,eh) in mTEPES.peh], index=pd.Index(sPSSTNNDEH))
2408
+ OutputResults.to_frame(name='EUR/MWh').reset_index().pivot_table(index=['level_0','level_1','level_3'], columns='level_5', values='EUR/MWh').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_ConsumptionCapturedSRMC_{CaseName}.csv', sep=',')
2164
2409
 
2165
2410
  if mTEPES.gc:
2166
2411
  GenRev = []
@@ -2168,16 +2413,16 @@ def EconomicResults(DirName, CaseName, OptModel, mTEPES, pIndAreaOutput, pIndPlo
2168
2413
  sPSSTNNDGC1 = [(p,sc,st,n,nd,gc) for p,sc,st,n,nd,gc in mTEPES.s2n*mTEPES.n2g if gc in mTEPES.gc if (p,gc) in mTEPES.pgc and (p,sc,n) in mTEPES.psn]
2169
2414
  OutputToGenRev = pd.Series(data=[mTEPES.pDuals["".join([f"eBalanceElec_{p}_{sc}_{st}('{n}', '{nd}')"])]/mTEPES.pPeriodProb[p,sc]()/mTEPES.pLoadLevelDuration[p,sc,n]()*OptModel.vTotalOutput [p,sc,n,gc]() for p,sc,st,n,nd,gc in sPSSTNNDGC1], index=pd.Index(sPSSTNNDGC1))
2170
2415
  GenRev.append(OutputToGenRev)
2171
- if len([(p,sc,n,nd,gc) for p,sc,n,nd,gc in mTEPES.psn*mTEPES.n2g if gc in mTEPES.gc for ot in mTEPES.ot if (p,gc) in mTEPES.pgc and gc in o2e[ot]]):
2172
- sPSSTNNDGC2 = [(p,sc,st,n,nd,gc) for p,sc,st,n,nd,gc in sPSSTNNDGC1 for ot in mTEPES.ot if (p,gc) in mTEPES.pgc and gc in o2e[ot] and (p,sc,n) in mTEPES.psn]
2416
+ if len([(p,sc,n,nd,gc) for p,sc, n,nd,gc in mTEPES.psn*mTEPES.n2g if gc in mTEPES.gc for ot in mTEPES.ot if (p,sc,n) in mTEPES.psn and (p,gc) in mTEPES.pgc and gc in o2e[ot]]):
2417
+ sPSSTNNDGC2 = [(p,sc,st,n,nd,gc) for p,sc,st,n,nd,gc in sPSSTNNDGC1 for ot in mTEPES.ot if (p,sc,n) in mTEPES.psn and (p,gc) in mTEPES.pgc and gc in o2e[ot]]
2173
2418
  OutputChargeRevESS = pd.Series(data=[mTEPES.pDuals["".join([f"eBalanceElec_{p}_{sc}_{st}('{n}', '{nd}')"])]/mTEPES.pPeriodProb[p,sc]()/mTEPES.pLoadLevelDuration[p,sc,n]()*OptModel.vESSTotalCharge[p,sc,n,gc]() for p,sc,st,n,nd,gc in sPSSTNNDGC2], index=pd.Index(sPSSTNNDGC2))
2174
2419
  ChargeRev.append(OutputChargeRevESS)
2175
- if len([(p,sc,n,nd,gc) for p,sc,n,nd,gc in mTEPES.psn*mTEPES.n2g if gc in mTEPES.gc for rt in mTEPES.rt if (p,gc) in mTEPES.pgc and gc in r2r[rt]]):
2176
- sPSSTNNDGC3 = [(p,sc,st,n,nd,gc) for p,sc,st,n,nd,gc in sPSSTNNDGC1 for rt in mTEPES.rt if (p,gc) in mTEPES.pgc and gc in r2r[rt] and (p,sc,n) in mTEPES.psn]
2420
+ if len([(p,sc,n,nd,gc) for p,sc, n,nd,gc in mTEPES.psn*mTEPES.n2g if gc in mTEPES.gc for rt in mTEPES.rt if (p,sc,n) in mTEPES.psn and (p,gc) in mTEPES.pgc and gc in r2r[rt]]):
2421
+ sPSSTNNDGC3 = [(p,sc,st,n,nd,gc) for p,sc,st,n,nd,gc in sPSSTNNDGC1 for rt in mTEPES.rt if (p,sc,n) in mTEPES.psn and (p,gc) in mTEPES.pgc and gc in r2r[rt]]
2177
2422
  OutputChargeRevRES = pd.Series(data=[mTEPES.pDuals["".join([f"eBalanceElec_{p}_{sc}_{st}('{n}', '{nd}')"])]/mTEPES.pPeriodProb[p,sc]()/mTEPES.pLoadLevelDuration[p,sc,n]() * 0.0 for p,sc,st,n,nd,gc in sPSSTNNDGC3], index=pd.Index(sPSSTNNDGC3))
2178
2423
  ChargeRev.append(OutputChargeRevRES)
2179
- if len([(p,sc,n,nd,gc) for p,sc,n,nd,gc in mTEPES.psn*mTEPES.n2g if gc in mTEPES.gc for ot in mTEPES.ot if (p,gc) in mTEPES.pgc and gc in o2e[ot]]):
2180
- sPSSTNNDGC4 = [(p,sc,st,n,nd,gc) for p,sc,st,n,nd,gc in sPSSTNNDGC1 for ot in mTEPES.ot if (p,gc) in mTEPES.pgc and gc in o2e[ot] and (p,sc,n) in mTEPES.psn]
2424
+ if len([(p,sc,n,nd,gc) for p,sc, n,nd,gc in mTEPES.psn*mTEPES.n2g if gc in mTEPES.gc for ot in mTEPES.ot if (p,sc,n) in mTEPES.psn and (p,gc) in mTEPES.pgc and gc in o2e[ot]]):
2425
+ sPSSTNNDGC4 = [(p,sc,st,n,nd,gc) for p,sc,st,n,nd,gc in sPSSTNNDGC1 for ot in mTEPES.ot if (p,sc,n) in mTEPES.psn and (p,gc) in mTEPES.pgc and gc in o2e[ot]]
2181
2426
  OutputChargeRevThr = pd.Series(data=[mTEPES.pDuals["".join([f"eBalanceElec_{p}_{sc}_{st}('{n}', '{nd}')"])]/mTEPES.pPeriodProb[p,sc]()/mTEPES.pLoadLevelDuration[p,sc,n]() * 0.0 for p,sc,st,n,nd,gc in sPSSTNNDGC4], index=pd.Index(sPSSTNNDGC4))
2182
2427
  ChargeRev.append(OutputChargeRevThr)
2183
2428
  if len(GenRev):
@@ -2199,8 +2444,8 @@ def EconomicResults(DirName, CaseName, OptModel, mTEPES, pIndAreaOutput, pIndPlo
2199
2444
 
2200
2445
  if sum(mTEPES.pReserveMargin[:,:]):
2201
2446
  if mTEPES.gc:
2202
- sPSSTARGC = [(p,sc,st,ar,gc) for p,sc,st,ar,gc in mTEPES.ps*mTEPES.st*mTEPES.ar*mTEPES.gc if gc in g2a[ar] and mTEPES.pReserveMargin[p,ar] and st == mTEPES.Last_st and sum(1 for gc in mTEPES.gc if gc in g2a[ar]) and sum(mTEPES.pRatedMaxPowerElec[g] * mTEPES.pAvailability[g]() / (1.0-mTEPES.pEFOR[g]) for g in mTEPES.g if g in g2a[ar] and g not in (mTEPES.gc or mTEPES.gd)) <= mTEPES.pDemandElecPeak[p,ar] * mTEPES.pReserveMargin[p,ar]]
2203
- OutputToResRev = pd.Series(data=[mTEPES.pDuals["".join([f"eAdequacyReserveMarginElec_{p}_{sc}_{st}{ar}"])]*mTEPES.pRatedMaxPowerElec[gc]*mTEPES.pAvailability[gc]() for p,sc,st,ar,gc in sPSSTARGC], index=pd.Index(sPSSTARGC))
2447
+ sPSSTARGC = [(p,sc,st,ar,gc) for p,sc,st,ar,gc in mTEPES.ps*mTEPES.st*mTEPES.ar*mTEPES.gc if gc in g2a[ar] and (p,gc) in mTEPES.pgc and mTEPES.pReserveMargin[p,ar] and st == mTEPES.Last_st and sum(1 for gc in mTEPES.gc if gc in g2a[ar]) and sum(mTEPES.pRatedMaxPowerElec[g] * mTEPES.pAvailability[g]() / (1.0-mTEPES.pEFOR[g]) for g in mTEPES.g if g in g2a[ar] and g not in (mTEPES.gc or mTEPES.gd)) <= mTEPES.pDemandElecPeak[p,ar] * mTEPES.pReserveMargin[p,ar]]
2448
+ OutputToResRev = pd.Series(data=[mTEPES.pDuals[''.join([f'eAdequacyReserveMarginElec_{p}_{sc}_{st}{ar}'])]*mTEPES.pRatedMaxPowerElec[gc]*mTEPES.pAvailability[gc]() for p,sc,st,ar,gc in sPSSTARGC], index=pd.Index(sPSSTARGC))
2204
2449
  ResRev = pd.Series(data=[0.0 for gc in mTEPES.gc], index=mTEPES.gc, dtype='float64')
2205
2450
  if sPSSTARGC:
2206
2451
  OutputToResRev /= 1e3
@@ -2210,19 +2455,19 @@ def EconomicResults(DirName, CaseName, OptModel, mTEPES, pIndAreaOutput, pIndPlo
2210
2455
  else:
2211
2456
  ResRev = pd.Series(data=[0.0 for gc in mTEPES.gc], index=mTEPES.gc, dtype='float64')
2212
2457
 
2213
- if sum(mTEPES.pOperReserveUp[:,:,:,:]) and sum(1 for ar,nr in mTEPES.ar*mTEPES.nr if nr in g2a[ar] and (mTEPES.pIndOperReserveGen[nr] == 0 or mTEPES.pIndOperReserveCon[nr] == 0) ) + sum(1 for ar,es in mTEPES.ar*mTEPES.es if es in g2a[ar] and (mTEPES.pIndOperReserveGen[nr] == 0 or mTEPES.pIndOperReserveCon[nr] == 0)):
2214
- if len([(p,sc,n,ar,nr) for p,sc,n,ar,nr in mTEPES.psn*mTEPES.ar*mTEPES.nr if nr in g2a[ar] and mTEPES.pOperReserveUp[p,sc,n,ar] and (p,sc,n,nr) in mTEPES.psnnr]):
2215
- sPSSTNARNR = [(p,sc,st,n,ar,nr) for p,sc,st,n,ar,nr in mTEPES.s2n*mTEPES.ar*mTEPES.nr if nr in g2a[ar] and mTEPES.pOperReserveUp[p,sc,n,ar] and (p,sc,n,nr) in mTEPES.psnnr]
2458
+ if sum(mTEPES.pOperReserveUp[:,:,:,:]) and sum(1 for ar,nr in mTEPES.ar*mTEPES.nr if nr in g2a[ar] and (mTEPES.pIndOperReserveGen[nr] == 0 or mTEPES.pIndOperReserveCon[nr] == 0)) + sum(1 for ar,es in mTEPES.ar*mTEPES.es if es in g2a[ar] and (mTEPES.pIndOperReserveGen[nr] == 0 or mTEPES.pIndOperReserveCon[nr] == 0)):
2459
+ if len([(p,sc,n,ar,nr) for p,sc, n,ar,nr in mTEPES.psn*mTEPES.ar*mTEPES.nr if nr in g2a[ar] and mTEPES.pOperReserveUp[p,sc,n,ar] and (p,sc,n,nr) in mTEPES.psnnr and (p,nr) in mTEPES.pnr]):
2460
+ sPSSTNARNR = [(p,sc,st,n,ar,nr) for p,sc,st,n,ar,nr in mTEPES.s2n*mTEPES.ar*mTEPES.nr if nr in g2a[ar] and mTEPES.pOperReserveUp[p,sc,n,ar] and (p,sc,n,nr) in mTEPES.psnnr and (p,nr) in mTEPES.pnr]
2216
2461
  OutputResults = pd.Series(data=[mTEPES.pDuals["".join([f"eOperReserveUp_{p}_{sc}_{st}('{n}', '{ar}')"])]/mTEPES.pPeriodProb[p,sc]()*OptModel.vReserveUp [p,sc,n,nr]() for p,sc,st,n,ar,nr in sPSSTNARNR], index=pd.Index(sPSSTNARNR))
2217
2462
  OutputResults.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_3'], columns='level_5', values='MEUR').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_RevenueOperatingReserveUp_{CaseName}.csv', sep=',')
2218
2463
 
2219
- if len([(p,sc,n,ar,eh) for p,sc,n,ar,eh in mTEPES.psn*mTEPES.ar*mTEPES.eh if eh in g2a[ar] and mTEPES.pOperReserveUp[p,sc,n,ar] and (p,sc,n,eh) in mTEPES.psnehc]):
2220
- sPSSTNARES = [(p,sc,st,n,ar,eh) for p,sc,st,n,ar,eh in mTEPES.s2n*mTEPES.ar*mTEPES.eh if eh in g2a[ar] and mTEPES.pOperReserveUp[p,sc,n,ar] and (p,sc,n,eh) in mTEPES.psnehc]
2464
+ if len([(p,sc,n,ar,eh) for p,sc, n,ar,eh in mTEPES.psn*mTEPES.ar*mTEPES.eh if eh in g2a[ar] and mTEPES.pOperReserveUp[p,sc,n,ar] and (p,sc,n,eh) in mTEPES.psnehc and (p,eh) in mTEPES.peh]):
2465
+ sPSSTNARES = [(p,sc,st,n,ar,eh) for p,sc,st,n,ar,eh in mTEPES.s2n*mTEPES.ar*mTEPES.eh if eh in g2a[ar] and mTEPES.pOperReserveUp[p,sc,n,ar] and (p,sc,n,eh) in mTEPES.psnehc and (p,eh) in mTEPES.peh]
2221
2466
  OutputResults = pd.Series(data=[mTEPES.pDuals["".join([f"eOperReserveUp_{p}_{sc}_{st}('{n}', '{ar}')"])]/mTEPES.pPeriodProb[p,sc]()*OptModel.vESSReserveUp[p,sc,n,eh]() for p,sc,st,n,ar,eh in sPSSTNARES], index=pd.Index(sPSSTNARES))
2222
2467
  OutputResults.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_3'], columns='level_5', values='MEUR').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_RevenueOperatingReserveUpESS_{CaseName}.csv', sep=',')
2223
2468
 
2224
- if len([(p,sc,n,ar,ec) for p,sc,n,ar,ec in mTEPES.psn*mTEPES.ar*mTEPES.gc if ec in g2a[ar] and mTEPES.pOperReserveUp[p,sc,n,ar] and (p,sc,n,ec) in mTEPES.psnec]):
2225
- sPSSTNAREC = [(p,sc,st,n,ar,ec) for p,sc,st,n,ar,ec in mTEPES.s2n*mTEPES.ar*mTEPES.ec if ec in g2a[ar] and mTEPES.pOperReserveUp[p,sc,n,ar] and (p,sc,n,ec) in mTEPES.psnec]
2469
+ if len([(p,sc,n,ar,ec) for p,sc, n,ar,ec in mTEPES.psn*mTEPES.ar*mTEPES.gc if ec in g2a[ar] and mTEPES.pOperReserveUp[p,sc,n,ar] and (p,sc,n,ec) in mTEPES.psnec and (p,ec) in mTEPES.pec]):
2470
+ sPSSTNAREC = [(p,sc,st,n,ar,ec) for p,sc,st,n,ar,ec in mTEPES.s2n*mTEPES.ar*mTEPES.ec if ec in g2a[ar] and mTEPES.pOperReserveUp[p,sc,n,ar] and (p,sc,n,ec) in mTEPES.psnec and (p,ec) in mTEPES.pec]
2226
2471
  OutputResults = pd.Series(data=[mTEPES.pDuals["".join([f"eOperReserveUp_{p}_{sc}_{st}('{n}', '{ar}')"])]/mTEPES.pPeriodProb[p,sc]()*(OptModel.vReserveUp[p,sc,n,ec]()+OptModel.vESSReserveUp[p,sc,n,ec]()) for p,sc,st,n,ar,ec in sPSSTNAREC], index=pd.Index(sPSSTNAREC), dtype='float64')
2227
2472
  if len(OutputResults):
2228
2473
  OutputToUpRev = OutputResults.to_frame('MEUR').reset_index().pivot_table(index=['level_0','level_1','level_3'], columns='level_5', values='MEUR').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).sum(axis=0)
@@ -2238,18 +2483,18 @@ def EconomicResults(DirName, CaseName, OptModel, mTEPES, pIndAreaOutput, pIndPlo
2238
2483
  UpRev = pd.Series(data=[0.0 for gc in mTEPES.gc], index=mTEPES.gc, dtype='float64')
2239
2484
 
2240
2485
  if sum(mTEPES.pOperReserveDw[:,:,:,:]) and sum(1 for ar,nr in mTEPES.ar*mTEPES.nr if nr in g2a[ar] and (mTEPES.pIndOperReserveGen[nr] == 0 or mTEPES.pIndOperReserveGen[nr] == 0 )) + sum(1 for ar,es in mTEPES.ar*mTEPES.es if es in g2a[ar] and (mTEPES.pIndOperReserveGen[es] == 0 or mTEPES.pIndOperReserveCon[es] == 0 )):
2241
- if len([(p,sc,n,ar,nr) for p,sc,n,ar,nr in mTEPES.psn*mTEPES.ar*mTEPES.nr if nr in g2a[ar] and mTEPES.pOperReserveDw[p,sc,n,ar] and (p,sc,n,nr) in mTEPES.psnnr]):
2242
- sPSSTNARNR = [(p,sc,st,n,ar,nr) for p,sc,st,n,ar,nr in mTEPES.s2n*mTEPES.ar*mTEPES.nr if nr in g2a[ar] and mTEPES.pOperReserveDw[p,sc,n,ar] and (p,sc,n,nr) in mTEPES.psnnr]
2486
+ if len([(p,sc,n,ar,nr) for p,sc, n,ar,nr in mTEPES.psn*mTEPES.ar*mTEPES.nr if nr in g2a[ar] and mTEPES.pOperReserveDw[p,sc,n,ar] and (p,sc,n,nr) in mTEPES.psnnr and (p,nr) in mTEPES.pnr]):
2487
+ sPSSTNARNR = [(p,sc,st,n,ar,nr) for p,sc,st,n,ar,nr in mTEPES.s2n*mTEPES.ar*mTEPES.nr if nr in g2a[ar] and mTEPES.pOperReserveDw[p,sc,n,ar] and (p,sc,n,nr) in mTEPES.psnnr and (p,nr) in mTEPES.pnr]
2243
2488
  OutputResults = pd.Series(data=[mTEPES.pDuals["".join([f"eOperReserveDw_{p}_{sc}_{st}('{n}', '{ar}')"])]/mTEPES.pPeriodProb[p,sc]()*OptModel.vReserveDown [p,sc,n,nr]() for p,sc,st,n,ar,nr in sPSSTNARNR], index=pd.Index(sPSSTNARNR))
2244
2489
  OutputResults.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_3'], columns='level_5', values='MEUR').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_RevenueOperatingReserveDw_{CaseName}.csv', sep=',')
2245
2490
 
2246
- if len([(p,sc,n,ar,eh) for p,sc,n,ar,eh in mTEPES.psn*mTEPES.ar*mTEPES.eh if eh in g2a[ar] if mTEPES.pOperReserveDw[p,sc,n,ar] and (p,sc,n,eh) in mTEPES.psnehc]):
2247
- sPSSTNARES = [(p,sc,st,n,ar,eh) for p,sc,st,n,ar,eh in mTEPES.s2n*mTEPES.ar*mTEPES.eh if eh in g2a[ar] and mTEPES.pOperReserveDw[p,sc,n,ar] and (p,sc,n,eh) in mTEPES.psnehc]
2491
+ if len([(p,sc,n,ar,eh) for p,sc, n,ar,eh in mTEPES.psn*mTEPES.ar*mTEPES.eh if eh in g2a[ar] and mTEPES.pOperReserveDw[p,sc,n,ar] and (p,sc,n,eh) in mTEPES.psnehc and (p,eh) in mTEPES.peh]):
2492
+ sPSSTNARES = [(p,sc,st,n,ar,eh) for p,sc,st,n,ar,eh in mTEPES.s2n*mTEPES.ar*mTEPES.eh if eh in g2a[ar] and mTEPES.pOperReserveDw[p,sc,n,ar] and (p,sc,n,eh) in mTEPES.psnehc and (p,eh) in mTEPES.peh]
2248
2493
  OutputResults = pd.Series(data=[mTEPES.pDuals["".join([f"eOperReserveDw_{p}_{sc}_{st}('{n}', '{ar}')"])]/mTEPES.pPeriodProb[p,sc]()*OptModel.vESSReserveDown[p,sc,n,eh]() for p,sc,st,n,ar,eh in sPSSTNARES], index=pd.Index(sPSSTNARES))
2249
2494
  OutputResults.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_3'], columns='level_5', values='MEUR').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_RevenueOperatingReserveDwESS_{CaseName}.csv', sep=',')
2250
2495
 
2251
- if len([(p,sc,n,ar,ec) for p,sc,n,ar,ec in mTEPES.psn*mTEPES.ar*mTEPES.ec if ec in g2a[ar] if mTEPES.pOperReserveDw[p,sc,n,ar] and (p,sc,n,ec) in mTEPES.psnec]):
2252
- sPSSTNAREC = [(p,sc,st,n,ar,ec) for p,sc,st,n,ar,ec in mTEPES.s2n*mTEPES.ar*mTEPES.ec if ec in g2a[ar] and mTEPES.pOperReserveDw[p,sc,n,ar] and (p,sc,n,ec) in mTEPES.psnec]
2496
+ if len([(p,sc,n,ar,ec) for p,sc, n,ar,ec in mTEPES.psn*mTEPES.ar*mTEPES.ec if ec in g2a[ar] and mTEPES.pOperReserveDw[p,sc,n,ar] and (p,sc,n,ec) in mTEPES.psnec and (p,ec) in mTEPES.pec]):
2497
+ sPSSTNAREC = [(p,sc,st,n,ar,ec) for p,sc,st,n,ar,ec in mTEPES.s2n*mTEPES.ar*mTEPES.ec if ec in g2a[ar] and mTEPES.pOperReserveDw[p,sc,n,ar] and (p,sc,n,ec) in mTEPES.psnec and (p,ec) in mTEPES.pec]
2253
2498
  OutputResults = pd.Series(data=[mTEPES.pDuals["".join([f"eOperReserveDw_{p}_{sc}_{st}('{n}', '{ar}')"])]/mTEPES.pPeriodProb[p,sc]()*(OptModel.vReserveDown[p,sc,n,ec]()+OptModel.vESSReserveDown[p,sc,n,ec]()) for p,sc,st,n,ar,ec in sPSSTNAREC], index=pd.Index(sPSSTNAREC), dtype='float64')
2254
2499
  if len(OutputResults):
2255
2500
  OutputToDwRev = OutputResults.to_frame('MEUR').reset_index().pivot_table(index=['level_0','level_1','level_3'], columns='level_5', values='MEUR').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).sum(axis=0)
@@ -2263,6 +2508,60 @@ def EconomicResults(DirName, CaseName, OptModel, mTEPES, pIndAreaOutput, pIndPlo
2263
2508
  else:
2264
2509
  DwRev = pd.Series(data=[0.0 for gc in mTEPES.gc], index=mTEPES.gc, dtype='float64')
2265
2510
 
2511
+ if mTEPES.pIndRampReserves == 1 and sum(mTEPES.pRampReserveUp[:,:,:,:]):
2512
+ if len([(p,sc,n,nr) for p,sc, n,nr in mTEPES.psn*mTEPES.nr if sum(mTEPES.pRampReserveUp[p,sc,n,ar] for ar in mTEPES.ar) and (p,sc,n,nr) in mTEPES.psnnr and (p,nr) in mTEPES.pnr]):
2513
+ sPSSTNNR = [(p,sc,st,n,nr) for p,sc,st,n,nr in mTEPES.s2n*mTEPES.nr if sum(mTEPES.pRampReserveUp[p,sc,n,ar] for ar in mTEPES.ar) and (p,sc,n,nr) in mTEPES.psnnr and (p,nr) in mTEPES.pnr]
2514
+ OutputResults = pd.Series(data=[mTEPES.pDuals["".join([f"eSystemRampUp_{p}_{sc}_{st}{n}"])]/mTEPES.pPeriodProb[p,sc]()*OptModel.vRampReserveUp[p,sc,n,nr]() for p,sc,st,n,nr in sPSSTNNR], index=pd.Index(sPSSTNNR))
2515
+ OutputResults.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_3'], columns='level_4', values='MEUR').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_RevenueRampReserveUp_{CaseName}.csv', sep=',')
2516
+
2517
+ # if len([(p,sc,n,eh) for p,sc, n,eh in mTEPES.psn*mTEPES.eh if sum(mTEPES.pRampReserveUp[p,sc,n,ar] for ar in mTEPES.ar) and (p,sc,n,eh) in mTEPES.psnehc and (p,eh) in mTEPES.peh]):
2518
+ # sPSSTNES = [(p,sc,st,n,eh) for p,sc,st,n,eh in mTEPES.s2n*mTEPES.eh if sum(mTEPES.pRampReserveUp[p,sc,n,ar] for ar in mTEPES.ar) and (p,sc,n,eh) in mTEPES.psnehc and (p,eh) in mTEPES.peh]
2519
+ # OutputResults = pd.Series(data=[mTEPES.pDuals["".join([f"eSystemRampUp_{p}_{sc}_{st}{n}"])]/mTEPES.pPeriodProb[p,sc]()*OptModel.vRampReserveUp[p,sc,n,eh]() for p,sc,st,n,eh in sPSSTNES], index=pd.Index(sPSSTNES))
2520
+ # OutputResults.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_3'], columns='level_4', values='MEUR').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_RevenueRampReserveUpESS_{CaseName}.csv', sep=',')
2521
+
2522
+ if len([(p,sc,n,ec) for p,sc, n,ec in mTEPES.psn*mTEPES.gc if sum(mTEPES.pRampReserveUp[p,sc,n,ar] for ar in mTEPES.ar) and (p,sc,n,ec) in mTEPES.psnec and (p,ec) in mTEPES.pec]):
2523
+ sPSSTNEC = [(p,sc,st,n,ec) for p,sc,st,n,ec in mTEPES.s2n*mTEPES.ec if sum(mTEPES.pRampReserveUp[p,sc,n,ar] for ar in mTEPES.ar) and (p,sc,n,ec) in mTEPES.psnec and (p,ec) in mTEPES.pec]
2524
+ OutputResults = pd.Series(data=[mTEPES.pDuals["".join([f"eSystemRampUp_{p}_{sc}_{st}{n}"])]/mTEPES.pPeriodProb[p,sc]()*OptModel.vRampReserveUp[p,sc,n,ec]() for p,sc,st,n,ec in sPSSTNEC], index=pd.Index(sPSSTNEC), dtype='float64')
2525
+ if len(OutputResults):
2526
+ OutputToUpRev = OutputResults.to_frame('MEUR').reset_index().pivot_table(index=['level_0','level_1','level_3'], columns='level_4', values='MEUR').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).sum(axis=0)
2527
+ else:
2528
+ OutputToUpRev = pd.Series(data=[0.0 for gc in mTEPES.gc], index=mTEPES.gc, dtype='float64')
2529
+ RampUpRev = pd.Series(data=[0.0 for gc in mTEPES.gc], index=mTEPES.gc, dtype='float64')
2530
+
2531
+ for g in OutputToUpRev.index:
2532
+ RampUpRev[g] = OutputToUpRev[g]
2533
+ else:
2534
+ RampUpRev = pd.Series(data=[0.0 for gc in mTEPES.gc], index=mTEPES.gc, dtype='float64')
2535
+ else:
2536
+ RampUpRev = pd.Series(data=[0.0 for gc in mTEPES.gc], index=mTEPES.gc, dtype='float64')
2537
+
2538
+ if mTEPES.pIndRampReserves == 1 and sum(mTEPES.pRampReserveDw[:,:,:,:]):
2539
+ if len([(p,sc,n,nr) for p,sc, n,nr in mTEPES.psn*mTEPES.nr if sum(mTEPES.pRampReserveDw[p,sc,n,ar] for ar in mTEPES.ar) and (p,sc,n,nr) in mTEPES.psnnr and (p,nr) in mTEPES.pnr]):
2540
+ sPSSTNNR = [(p,sc,st,n,nr) for p,sc,st,n,nr in mTEPES.s2n*mTEPES.nr if sum(mTEPES.pRampReserveDw[p,sc,n,ar] for ar in mTEPES.ar) and (p,sc,n,nr) in mTEPES.psnnr and (p,nr) in mTEPES.pnr]
2541
+ OutputResults = pd.Series(data=[mTEPES.pDuals["".join([f"eSystemRampDw_{p}_{sc}_{st}{n}"])]/mTEPES.pPeriodProb[p,sc]()*OptModel.vRampReserveDw[p,sc,n,nr]() for p,sc,st,n,nr in sPSSTNNR], index=pd.Index(sPSSTNNR))
2542
+ OutputResults.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_3'], columns='level_4', values='MEUR').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_RevenueRampReserveDw_{CaseName}.csv', sep=',')
2543
+
2544
+ # if len([(p,sc,n,eh) for p,sc, n,eh in mTEPES.psn*mTEPES.eh if sum(mTEPES.pRampReserveDw[p,sc,n,ar] for ar in mTEPES.ar) and (p,sc,n,eh) in mTEPES.psnehc and (p,eh) in mTEPES.peh]):
2545
+ # sPSSTNES = [(p,sc,st,n,eh) for p,sc,st,n,eh in mTEPES.s2n*mTEPES.eh if sum(mTEPES.pRampReserveDw[p,sc,n,ar] for ar in mTEPES.ar) and (p,sc,n,eh) in mTEPES.psnehc and (p,eh) in mTEPES.peh]
2546
+ # OutputResults = pd.Series(data=[mTEPES.pDuals["".join([f"eSystemRampDw_{p}_{sc}_{st}{n}"])]/mTEPES.pPeriodProb[p,sc]()*OptModel.vRampReserveDw[p,sc,n,eh]() for p,sc,st,n,eh in sPSSTNES], index=pd.Index(sPSSTNES))
2547
+ # OutputResults.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_3'], columns='level_4', values='MEUR').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_RevenueRampReserveDwESS_{CaseName}.csv', sep=',')
2548
+
2549
+ if len([(p,sc,n,ec) for p,sc, n,ec in mTEPES.psn*mTEPES.gc if sum(mTEPES.pRampReserveDw[p,sc,n,ar] for ar in mTEPES.ar) and (p,sc,n,ec) in mTEPES.psnec and (p,ec) in mTEPES.pec]):
2550
+ sPSSTNEC = [(p,sc,st,n,ec) for p,sc,st,n,ec in mTEPES.s2n*mTEPES.ec if sum(mTEPES.pRampReserveDw[p,sc,n,ar] for ar in mTEPES.ar) and (p,sc,n,ec) in mTEPES.psnec and (p,ec) in mTEPES.pec]
2551
+ OutputResults = pd.Series(data=[mTEPES.pDuals["".join([f"eSystemRampDw_{p}_{sc}_{st}{n}"])]/mTEPES.pPeriodProb[p,sc]()*OptModel.vRampReserveUp[p,sc,n,ec]() for p,sc,st,n,ec in sPSSTNEC], index=pd.Index(sPSSTNEC), dtype='float64')
2552
+ if len(OutputResults):
2553
+ OutputToDwRev = OutputResults.to_frame('MEUR').reset_index().pivot_table(index=['level_0','level_1','level_3'], columns='level_4', values='MEUR').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).sum(axis=0)
2554
+ else:
2555
+ OutputToDwRev = pd.Series(data=[0.0 for gc in mTEPES.gc], index=mTEPES.gc, dtype='float64')
2556
+ RampDwRev = pd.Series(data=[0.0 for gc in mTEPES.gc], index=mTEPES.gc, dtype='float64')
2557
+
2558
+ for g in OutputToUpRev.index:
2559
+ RampDwRev[g] = OutputToDwRev[g]
2560
+ else:
2561
+ RampDwRev = pd.Series(data=[0.0 for gc in mTEPES.gc], index=mTEPES.gc, dtype='float64')
2562
+ else:
2563
+ RampDwRev = pd.Series(data=[0.0 for gc in mTEPES.gc], index=mTEPES.gc, dtype='float64')
2564
+
2266
2565
  if mTEPES.gc:
2267
2566
  GenCost = pd.Series(data=[sum(mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelDuration[p,sc,n]() * mTEPES.pLinearVarCost [p,sc,n,gc] * OptModel.vTotalOutput [p,sc,n,gc]() +
2268
2567
  mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelDuration[p,sc,n]() * mTEPES.pConstantVarCost[p,sc,n,gc] * OptModel.vCommitment [p,sc,n,gc]() +
@@ -2282,14 +2581,15 @@ def EconomicResults(DirName, CaseName, OptModel, mTEPES, pIndAreaOutput, pIndPlo
2282
2581
  OpCCost[gc] = 0.0 if gc not in OpCCost.index else OpCCost[gc]
2283
2582
 
2284
2583
  InvCost = pd.Series(data=[sum(mTEPES.pDiscountedWeight[p] * mTEPES.pGenInvestCost[gc] * OptModel.vGenerationInvest[p,gc]() for p in mTEPES.p if (p,gc) in mTEPES.pgc) for gc in mTEPES.gc], index=mTEPES.gc, dtype='float64')
2285
- Balance = pd.Series(data=[GenRev[gc]+ChargeRev[gc]+UpRev[gc]+DwRev[gc]+ResRev[gc]-GenCost[gc]-EmsCost[gc]-OpGCost[gc]-CnsCost[gc]-OpCCost[gc]-InvCost[gc] for gc in mTEPES.gc], index=mTEPES.gc, dtype='float64')
2286
- CostRecovery = pd.concat([GenRev,ChargeRev,UpRev,DwRev,ResRev,-GenCost,-EmsCost,-OpGCost,-CnsCost,-OpCCost,-InvCost,Balance], axis=1, keys=['Revenue generation [MEUR]', 'Revenue consumption [MEUR]', 'Revenue operating reserve up [MEUR]', 'Revenue operating reserve down [MEUR]', 'Revenue reserve margin [MEUR]', 'Cost operation generation [MEUR]', 'Cost emission [MEUR]', 'Cost operating reserves generation [MEUR]', 'Cost operation consumption [MEUR]', 'Cost operating reserves consumption [MEUR]', 'Cost investment [MEUR]', ' Total [MEUR]'])
2584
+ Balance = pd.Series(data=[GenRev[gc]+ChargeRev[gc]+UpRev[gc]+DwRev[gc]+RampUpRev[gc]+RampDwRev[gc]+ResRev[gc]-GenCost[gc]-EmsCost[gc]-OpGCost[gc]-CnsCost[gc]-OpCCost[gc]-InvCost[gc] for gc in mTEPES.gc], index=mTEPES.gc, dtype='float64')
2585
+ CostRecovery = pd.concat([GenRev,ChargeRev,UpRev,DwRev,RampUpRev,RampDwRev,ResRev,-GenCost,-EmsCost,-OpGCost,-CnsCost,-OpCCost,-InvCost,Balance], axis=1, keys=['Revenue generation [MEUR]', 'Revenue consumption [MEUR]', 'Revenue operating reserve up [MEUR]', 'Revenue operating reserve down [MEUR]' 'Revenue ramp reserve up [MEUR]', 'Revenue ramp reserve down [MEUR]', 'Revenue reserve margin [MEUR]', 'Cost operation generation [MEUR]', 'Cost emission [MEUR]', 'Cost operating reserves generation [MEUR]', 'Cost operation consumption [MEUR]', 'Cost operating reserves consumption [MEUR]', 'Cost investment [MEUR]', ' Total [MEUR]'])
2287
2586
  CostRecovery.stack().to_frame(name='MEUR').reset_index().pivot_table(values='MEUR', index=['level_1'], columns=['level_0']).rename_axis([None], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_CostRecovery_{CaseName}.csv', sep=',')
2288
2587
 
2289
2588
  WritingResultsTime = time.time() - StartTime
2290
2589
  print('Writing economic results ... ', round(WritingResultsTime), 's')
2291
2590
 
2292
2591
 
2592
+ # @profile
2293
2593
  def NetworkMapResults(DirName, CaseName, OptModel, mTEPES):
2294
2594
  # %% plotting the network in a map
2295
2595
  _path = os.path.join(DirName, CaseName)