openTEPES 4.18.9__py3-none-any.whl → 4.18.10__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
openTEPES/__init__.py CHANGED
@@ -14,7 +14,7 @@ Open Generation, Storage, and Transmission Operation and Expansion Planning Mode
14
14
  >>> import openTEPES as oT
15
15
  >>> oT.routine("9n", "C:\\Users\\UserName\\Documents\\GitHub\\openTEPES", "glpk")
16
16
  """
17
- __version__ = "4.18.9"
17
+ __version__ = "4.18.10"
18
18
 
19
19
  from .openTEPES_Main import main
20
20
  from .openTEPES import *
openTEPES/openTEPES.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """
2
- Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - January 22, 2026
2
+ Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - January 25, 2026
3
3
  """
4
4
 
5
5
  # import dill as pickle
@@ -38,8 +38,8 @@ def openTEPES_run(DirName, CaseName, SolverName, pIndOutputResults, pIndLogConso
38
38
  idxDict['y' ] = 1
39
39
 
40
40
  #%% model declaration
41
- mTEPES = ConcreteModel('Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 4.18.9 - January 22, 2026')
42
- print( 'Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 4.18.9 - January 22, 2026', file=open(f'{_path}/openTEPES_version_{CaseName}.log','w'))
41
+ mTEPES = ConcreteModel('Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 4.18.10 - January 25, 2026')
42
+ print( 'Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 4.18.10 - January 25, 2026', file=open(f'{_path}/openTEPES_version_{CaseName}.log','w'))
43
43
 
44
44
  pIndOutputResults = [j for i,j in idxDict.items() if i == pIndOutputResults][0]
45
45
  pIndLogConsole = [j for i,j in idxDict.items() if i == pIndLogConsole ][0]
@@ -677,6 +677,7 @@ def DataConfiguration(mTEPES):
677
677
  mTEPES.psnchp = Set(initialize = [(p,sc,n,chp) for p,sc,n,chp in mTEPES.psn*mTEPES.chp if (p,chp) in mTEPES.pchp])
678
678
  mTEPES.psnbo = Set(initialize = [(p,sc,n,bo) for p,sc,n,bo in mTEPES.psn*mTEPES.bo if (p,bo) in mTEPES.pbo ])
679
679
  mTEPES.psnhp = Set(initialize = [(p,sc,n,hp) for p,sc,n,hp in mTEPES.psn*mTEPES.hp if (p,hp) in mTEPES.php ])
680
+ mTEPES.psneb = Set(initialize = [(p,sc,n,eb) for p,sc,n,eb in mTEPES.psn*mTEPES.eb if (p,eb) in mTEPES.peb ])
680
681
  mTEPES.psnes = Set(initialize = [(p,sc,n,es) for p,sc,n,es in mTEPES.psn*mTEPES.es if (p,es) in mTEPES.pes ])
681
682
  mTEPES.psneh = Set(initialize = [(p,sc,n,eh) for p,sc,n,eh in mTEPES.psn*mTEPES.eh if (p,eh) in mTEPES.peh ])
682
683
  mTEPES.psnec = Set(initialize = [(p,sc,n,ec) for p,sc,n,ec in mTEPES.psn*mTEPES.ec if (p,ec) in mTEPES.pec ])
@@ -2082,7 +2083,6 @@ def SettingUpVariables(OptModel, mTEPES):
2082
2083
  '''
2083
2084
  nFixedVariables = 0
2084
2085
 
2085
- # fix the must-run existing units and their output
2086
2086
  # must-run units must produce at least their minimum output
2087
2087
  [OptModel.vTotalOutput[p,sc,n,g].setlb(mTEPES.pMinPowerElec[p,sc,n,g]) for p,sc,n,g in mTEPES.psng if mTEPES.pMustRun[g] == 1 and g not in mTEPES.gc]
2088
2088
 
@@ -2119,8 +2119,12 @@ def SettingUpVariables(OptModel, mTEPES):
2119
2119
  OptModel.vReserveUp [p,sc,n,nr].fix(0.0)
2120
2120
  OptModel.vReserveDown [p,sc,n,nr].fix(0.0)
2121
2121
  nFixedVariables += 3
2122
+ # fix the must-run existing units and their output
2123
+ if mTEPES.pMustRun[nr] == 1 and mTEPES.pMaxPower2ndBlock[p,sc,n,nr] == 0.0 and nr not in mTEPES.gc:
2124
+ OptModel.vTotalOutput[p,sc,n,nr].fix(mTEPES.pMinPowerElec[p,sc,n,nr])
2125
+ nFixedVariables += 1
2122
2126
  if mTEPES.pIndRampReserves == 1:
2123
- if mTEPES.pMaxPower2ndBlock[p, sc, n, nr] == 0.0 or mTEPES.pRampUp[nr] == 0.0:
2127
+ if mTEPES.pMaxPower2ndBlock[p,sc,n,nr] == 0.0 or mTEPES.pRampUp[nr] == 0.0:
2124
2128
  OptModel.vRampReserveUp[p,sc,n,nr].fix(0.0)
2125
2129
  OptModel.vRampReserveDw[p,sc,n,nr].fix(0.0)
2126
2130
  nFixedVariables += 2
@@ -660,7 +660,7 @@
660
660
  # For more information on this, and how to apply and follow the GNU AGPL, see
661
661
  # <https://www.gnu.org/licenses/>.
662
662
 
663
- # Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - January 22, 2026
663
+ # Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - January 25, 2026
664
664
  # simplicity and transparency in power systems planning
665
665
 
666
666
  # Developed by
@@ -693,7 +693,7 @@ GREEN = "\033[32m"
693
693
  BLUE = "\033[34m"
694
694
  RESET = "\033[0m"
695
695
 
696
- print(GREEN + 'Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 4.18.9 - January 22, 2026' + RESET)
696
+ print(GREEN + 'Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 4.18.10 - January 25, 2026' + RESET)
697
697
  print(BLUE + '#### Academic research license - for non-commercial use only ####' + RESET + '\n')
698
698
 
699
699
  parser = argparse.ArgumentParser(description='Introducing main parameters...')
@@ -1,5 +1,5 @@
1
1
  """
2
- Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - January 15, 2026
2
+ Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - January 23, 2026
3
3
  """
4
4
 
5
5
  import time
@@ -181,7 +181,7 @@ def GenerationOperationModelFormulationObjFunct(OptModel, mTEPES, pIndLogConsole
181
181
  + mTEPES.pLoadLevelDuration[p,sc,n]() * sum(mTEPES.pEmissionRate[bo] * 1e-3 * OptModel.vTotalOutputHeat[p,sc,n,bo] for bo in mTEPES.bo if (ar,bo) in mTEPES.a2g and (p,bo) in mTEPES.pbo)) #1e-3 to change from tCO2/MWh to MtCO2/GWh
182
182
  else:
183
183
  return Constraint.Skip
184
- setattr(OptModel, f'eTotalEmissionArea_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.ar, rule=eTotalEmissionArea, doc='area total emission [MtCO2 eq]'))
184
+ setattr(OptModel, f'eTotalEmissionArea_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.ar, rule=eTotalEmissionArea, doc='area total emission [MtCO2 eq]'))
185
185
 
186
186
  def eTotalECostArea(OptModel,n,ar):
187
187
  if sum(mTEPES.pEmissionVarCost[p,sc,n,g] for g in mTEPES.g if (ar,g) in mTEPES.a2g and (p,g) in mTEPES.pg):
@@ -189,14 +189,14 @@ def GenerationOperationModelFormulationObjFunct(OptModel, mTEPES, pIndLogConsole
189
189
  + sum(mTEPES.pEmissionVarCost[p,sc,n,bo] * OptModel.vTotalOutputHeat[p,sc,n,bo] for bo in mTEPES.bo if (ar,bo) in mTEPES.a2g and (p,bo) in mTEPES.pbo)))
190
190
  else:
191
191
  return Constraint.Skip
192
- setattr(OptModel, f'eTotalECostArea_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.ar, rule=eTotalECostArea, doc='area emission cost [MEUR]'))
192
+ setattr(OptModel, f'eTotalECostArea_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.ar, rule=eTotalECostArea, doc='area emission cost [MEUR]'))
193
193
 
194
194
  def eTotalRESEnergyArea(OptModel,n,ar):
195
195
  if mTEPES.pRESEnergy[p,ar] and st == mTEPES.Last_st:
196
196
  return OptModel.vTotalRESEnergyArea[p,sc,n,ar] == mTEPES.pLoadLevelDuration[p,sc,n]() * sum(OptModel.vTotalOutput[p,sc,n,re] for re in mTEPES.re if (ar,re) in mTEPES.a2g and (p,re) in mTEPES.pre)
197
197
  else:
198
198
  return Constraint.Skip
199
- setattr(OptModel, f'eTotalRESEnergyArea_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.ar, rule=eTotalRESEnergyArea, doc='area RES energy [GWh]'))
199
+ setattr(OptModel, f'eTotalRESEnergyArea_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.ar, rule=eTotalRESEnergyArea, doc='area RES energy [GWh]'))
200
200
 
201
201
  def eTotalNCost(OptModel,n):
202
202
  return OptModel.vTotalNCost[p,sc,n] == mTEPES.pLoadLevelDuration[p,sc,n]() * pEpsilon * sum(OptModel.vLineLosses[p,sc,n,ni,nf,cc] for ni,nf,cc in mTEPES.ll if (p,ni,nf,cc) in mTEPES.pll)
@@ -232,7 +232,7 @@ def GenerationOperationModelFormulationInvestment(OptModel, mTEPES, pIndLogConso
232
232
  return OptModel.vCommitment[p,sc,n,gc] == OptModel.vGenerationInvest[p,gc]
233
233
  else:
234
234
  return Constraint.Skip
235
- setattr(OptModel, f'eInstallGenComm_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.gc, rule=eInstallGenComm, doc='commitment if installed unit [p.u.]'))
235
+ setattr(OptModel, f'eInstallGenComm_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.gc, rule=eInstallGenComm, doc='commitment if installed unit [p.u.]'))
236
236
 
237
237
  if pIndLogConsole == 1:
238
238
  print('eInstallGenComm ... ', len(getattr(OptModel, f'eInstallGenComm_{p}_{sc}_{st}')), ' rows')
@@ -245,7 +245,7 @@ def GenerationOperationModelFormulationInvestment(OptModel, mTEPES, pIndLogConso
245
245
  return Constraint.Skip
246
246
  else:
247
247
  return Constraint.Skip
248
- setattr(OptModel, f'eInstallESSComm_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.ec, rule=eInstallESSComm, doc='commitment if ESS unit [p.u.]'))
248
+ setattr(OptModel, f'eInstallESSComm_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.ec, rule=eInstallESSComm, doc='commitment if ESS unit [p.u.]'))
249
249
 
250
250
  if pIndLogConsole == 1:
251
251
  print('eInstallESSComm ... ', len(getattr(OptModel, f'eInstallESSComm_{p}_{sc}_{st}')), ' rows')
@@ -258,7 +258,7 @@ def GenerationOperationModelFormulationInvestment(OptModel, mTEPES, pIndLogConso
258
258
  return Constraint.Skip
259
259
  else:
260
260
  return Constraint.Skip
261
- setattr(OptModel, f'eInstallGenCap_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.gc, rule=eInstallGenCap, doc='output if installed gen unit [p.u.]'))
261
+ setattr(OptModel, f'eInstallGenCap_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.gc, rule=eInstallGenCap, doc='output if installed gen unit [p.u.]'))
262
262
 
263
263
  if pIndLogConsole == 1:
264
264
  print('eInstallGenCap ... ', len(getattr(OptModel, f'eInstallGenCap_{p}_{sc}_{st}')), ' rows')
@@ -271,7 +271,7 @@ def GenerationOperationModelFormulationInvestment(OptModel, mTEPES, pIndLogConso
271
271
  return Constraint.Skip
272
272
  else:
273
273
  return Constraint.Skip
274
- setattr(OptModel, f'eInstallFHUCap_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.bc, rule=eInstallFHUCap, doc='heat production if installed fuel heating unit [p.u.]'))
274
+ setattr(OptModel, f'eInstallFHUCap_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.bc, rule=eInstallFHUCap, doc='heat production if installed fuel heating unit [p.u.]'))
275
275
 
276
276
  if pIndLogConsole == 1:
277
277
  print('eInstallFHUCap ... ', len(getattr(OptModel, f'eInstallFHUCap_{p}_{sc}_{st}')), ' rows')
@@ -284,7 +284,7 @@ def GenerationOperationModelFormulationInvestment(OptModel, mTEPES, pIndLogConso
284
284
  return Constraint.Skip
285
285
  else:
286
286
  return Constraint.Skip
287
- setattr(OptModel, f'eInstallConESS_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.ec, rule=eInstallConESS, doc='consumption if installed ESS unit [p.u.]'))
287
+ setattr(OptModel, f'eInstallConESS_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.ec, rule=eInstallConESS, doc='consumption if installed ESS unit [p.u.]'))
288
288
 
289
289
  if pIndLogConsole == 1:
290
290
  print('eInstallConESS ... ', len(getattr(OptModel, f'eInstallConESS_{p}_{sc}_{st}')), ' rows')
@@ -297,7 +297,7 @@ def GenerationOperationModelFormulationInvestment(OptModel, mTEPES, pIndLogConso
297
297
  return Constraint.Skip
298
298
  else:
299
299
  return Constraint.Skip
300
- setattr(OptModel, f'eUninstallGenComm_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.gd, rule=eUninstallGenComm, doc='commitment if uninstalled unit [p.u.]'))
300
+ setattr(OptModel, f'eUninstallGenComm_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.gd, rule=eUninstallGenComm, doc='commitment if uninstalled unit [p.u.]'))
301
301
 
302
302
  if pIndLogConsole == 1:
303
303
  print('eUninstallGenComm ... ', len(getattr(OptModel, f'eUninstallGenComm_{p}_{sc}_{st}')), ' rows')
@@ -310,7 +310,7 @@ def GenerationOperationModelFormulationInvestment(OptModel, mTEPES, pIndLogConso
310
310
  return Constraint.Skip
311
311
  else:
312
312
  return Constraint.Skip
313
- setattr(OptModel, f'eUninstallGenCap_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.gd, rule=eUninstallGenCap, doc='output if uninstalled gen unit [p.u.]'))
313
+ setattr(OptModel, f'eUninstallGenCap_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.gd, rule=eUninstallGenCap, doc='output if uninstalled gen unit [p.u.]'))
314
314
 
315
315
  if pIndLogConsole == 1:
316
316
  print('eUninstallGenCap ... ', len(getattr(OptModel, f'eUninstallGenCap_{p}_{sc}_{st}')), ' rows')
@@ -414,7 +414,7 @@ def GenerationOperationModelFormulationDemand(OptModel, mTEPES, pIndLogConsole,
414
414
  return sum(OptModel.vCommitment[p,sc,n,nr] * mTEPES.pInertia[nr] for nr in mTEPES.nr if (ar,nr) in mTEPES.a2g) >= mTEPES.pSystemInertia[p,sc,n,ar]
415
415
  else:
416
416
  return Constraint.Skip
417
- setattr(OptModel, f'eSystemInertia_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.ar, rule=eSystemInertia, doc='system inertia [s]'))
417
+ setattr(OptModel, f'eSystemInertia_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.ar, rule=eSystemInertia, doc='system inertia [s]'))
418
418
 
419
419
  if pIndLogConsole == 1:
420
420
  print('eSystemInertia ... ', len(getattr(OptModel, f'eSystemInertia_{p}_{sc}_{st}')), ' rows')
@@ -429,7 +429,7 @@ def GenerationOperationModelFormulationDemand(OptModel, mTEPES, pIndLogConsole,
429
429
  return Constraint.Skip
430
430
  return sum(OptModel.vReserveUp [p,sc,n,nr] for nr in n2a[ar] if mTEPES.pIndOperReserveGen[nr] == 0 and (p,nr) in mTEPES.pnr) + sum(OptModel.vESSReserveUp [p,sc,n,eh] for eh in e2a[ar] if mTEPES.pIndOperReserveCon[eh] == 0 and (p,eh) in mTEPES.peh) == mTEPES.pOperReserveUp[p,sc,n,ar]
431
431
 
432
- setattr(OptModel, f'eOperReserveUp_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.ar, rule=eOperReserveUp, doc='up operating reserve [GW]'))
432
+ setattr(OptModel, f'eOperReserveUp_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.ar, rule=eOperReserveUp, doc='up operating reserve [GW]'))
433
433
 
434
434
  if pIndLogConsole == 1:
435
435
  print('eOperReserveUp ... ', len(getattr(OptModel, f'eOperReserveUp_{p}_{sc}_{st}')), ' rows')
@@ -444,7 +444,7 @@ def GenerationOperationModelFormulationDemand(OptModel, mTEPES, pIndLogConsole,
444
444
  return Constraint.Skip
445
445
  return sum(OptModel.vReserveDown[p,sc,n,nr] for nr in n2a[ar] if mTEPES.pIndOperReserveGen[nr] == 0 and (p,nr) in mTEPES.pnr) + sum(OptModel.vESSReserveDown[p,sc,n,eh] for eh in e2a[ar] if mTEPES.pIndOperReserveCon[eh] == 0 and (p,eh) in mTEPES.peh) == mTEPES.pOperReserveDw[p,sc,n,ar]
446
446
 
447
- setattr(OptModel, f'eOperReserveDw_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.ar, rule=eOperReserveDw, doc='down operating reserve [GW]'))
447
+ setattr(OptModel, f'eOperReserveDw_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.ar, rule=eOperReserveDw, doc='down operating reserve [GW]'))
448
448
 
449
449
  if pIndLogConsole == 1:
450
450
  print('eOperReserveDw ... ', len(getattr(OptModel, f'eOperReserveDw_{p}_{sc}_{st}')), ' rows')
@@ -462,7 +462,7 @@ def GenerationOperationModelFormulationDemand(OptModel, mTEPES, pIndLogConsole,
462
462
 
463
463
  return OptModel.vReserveDown[p,sc,n,nr] >= OptModel.vReserveUp[p,sc,n,nr] * mTEPES.pMinRatioDwUp
464
464
 
465
- setattr(OptModel, f'eReserveMinRatioDwUp_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.nr, rule=eReserveMinRatioDwUp, doc='minimum ratio down to up operating reserve [GW]'))
465
+ setattr(OptModel, f'eReserveMinRatioDwUp_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.nr, rule=eReserveMinRatioDwUp, doc='minimum ratio down to up operating reserve [GW]'))
466
466
 
467
467
  if pIndLogConsole == 1:
468
468
  print('eReserveMinRatioDwUp ... ', len(getattr(OptModel, f'eReserveMinRatioDwUp_{p}_{sc}_{st}')), ' rows')
@@ -480,7 +480,7 @@ def GenerationOperationModelFormulationDemand(OptModel, mTEPES, pIndLogConsole,
480
480
 
481
481
  return OptModel.vReserveDown[p,sc,n,nr] <= OptModel.vReserveUp[p,sc,n,nr] * mTEPES.pMaxRatioDwUp
482
482
 
483
- setattr(OptModel, f'eReserveMaxRatioDwUp_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.nr, rule=eReserveMaxRatioDwUp, doc='maximum ratio down to up operating reserve [GW]'))
483
+ setattr(OptModel, f'eReserveMaxRatioDwUp_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.nr, rule=eReserveMaxRatioDwUp, doc='maximum ratio down to up operating reserve [GW]'))
484
484
 
485
485
  if pIndLogConsole == 1:
486
486
  print('eReserveMaxRatioDwUp ... ', len(getattr(OptModel, f'eReserveMaxRatioDwUp_{p}_{sc}_{st}')), ' rows')
@@ -497,7 +497,7 @@ def GenerationOperationModelFormulationDemand(OptModel, mTEPES, pIndLogConsole,
497
497
  return Constraint.Skip
498
498
 
499
499
  return OptModel.vESSReserveDown[p,sc,n,eh] >= OptModel.vESSReserveUp[p,sc,n,eh] * mTEPES.pMinRatioDwUp
500
- setattr(OptModel, f'eRsrvMinRatioDwUpESS_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.eh, rule=eRsrvMinRatioDwUpESS, doc='minimum ratio down to up operating reserve [GW]'))
500
+ setattr(OptModel, f'eRsrvMinRatioDwUpESS_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.eh, rule=eRsrvMinRatioDwUpESS, doc='minimum ratio down to up operating reserve [GW]'))
501
501
 
502
502
  if pIndLogConsole == 1:
503
503
  print('eRsrvMinRatioDwUpESS ... ', len(getattr(OptModel, f'eRsrvMinRatioDwUpESS_{p}_{sc}_{st}')), ' rows')
@@ -515,7 +515,7 @@ def GenerationOperationModelFormulationDemand(OptModel, mTEPES, pIndLogConsole,
515
515
 
516
516
  return OptModel.vESSReserveDown[p,sc,n,eh] <= OptModel.vESSReserveUp[p,sc,n,eh] * mTEPES.pMaxRatioDwUp
517
517
 
518
- setattr(OptModel, f'eRsrvMaxRatioDwUpESS_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.eh, rule=eRsrvMaxRatioDwUpESS, doc='maximum ratio down to up operating reserve [GW]'))
518
+ setattr(OptModel, f'eRsrvMaxRatioDwUpESS_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.eh, rule=eRsrvMaxRatioDwUpESS, doc='maximum ratio down to up operating reserve [GW]'))
519
519
 
520
520
  if pIndLogConsole == 1:
521
521
  print('eRsrvMaxRatioDwUpESS ... ', len(getattr(OptModel, f'eRsrvMaxRatioDwUpESS_{p}_{sc}_{st}')), ' rows')
@@ -587,7 +587,7 @@ def GenerationOperationModelFormulationDemand(OptModel, mTEPES, pIndLogConsole,
587
587
  sum(OptModel.vLineLosses[p,sc,n,ni,nd,cc] for ni,cc in linl [nd] if (p,ni,nd,cc) in mTEPES.pll) + sum(OptModel.vFlowElec[p,sc,n,ni,nd,cc] for ni,cc in lin [nd] if (p,ni,nd,cc) in mTEPES.pla)) == mTEPES.pDemandElec[p,sc,n,nd]
588
588
  else:
589
589
  return Constraint.Skip
590
- setattr(OptModel, f'eBalanceElec_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.nd, rule=eBalanceElec, doc='electric load generation balance [GW]'))
590
+ setattr(OptModel, f'eBalanceElec_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.nd, rule=eBalanceElec, doc='electric load generation balance [GW]'))
591
591
 
592
592
  if pIndLogConsole == 1:
593
593
  print('eBalanceElec ... ', len(getattr(OptModel, f'eBalanceElec_{p}_{sc}_{st}')), ' rows')
@@ -694,7 +694,7 @@ def GenerationOperationModelFormulationStorage(OptModel, mTEPES, pIndLogConsole,
694
694
  return mTEPES.pDuration[p,sc,n]()*mTEPES.pEfficiency[eh]*OptModel.vESSTotalCharge[p,sc,n,eh] <= sum(mTEPES.pDuration[p,sc,n2]()*OptModel.vTotalOutput[p,sc,n2,eh] for n2 in list(mTEPES.n2)[mTEPES.n.ord(n):mTEPES.n.ord(n)+mTEPES.pShiftTime[eh]])
695
695
  else:
696
696
  return Constraint.Skip
697
- setattr(OptModel, f'eMaxShiftTime_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.eh, rule=eMaxShiftTime, doc='Maximum shift time [GWh]'))
697
+ setattr(OptModel, f'eMaxShiftTime_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.eh, rule=eMaxShiftTime, doc='Maximum shift time [GWh]'))
698
698
 
699
699
  if pIndLogConsole == 1:
700
700
  print('eMaxShiftTime ... ', len(getattr(OptModel, f'eMaxShiftTime_{p}_{sc}_{st}')), ' rows')
@@ -713,7 +713,7 @@ def GenerationOperationModelFormulationStorage(OptModel, mTEPES, pIndLogConsole,
713
713
  # Hydro case equation
714
714
  else:
715
715
  return (OptModel.vCharge2ndBlock[p,sc,n,eh] + OptModel.vESSReserveDown[p,sc,n,eh]) / mTEPES.pMaxCharge2ndBlock[p,sc,n,eh] <= OptModel.vCommitmentCons[p,sc,n,eh]
716
- setattr(OptModel, f'eMaxCharge_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.eh, rule=eMaxCharge, doc='max charge of an ESS [p.u.]'))
716
+ setattr(OptModel, f'eMaxCharge_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.eh, rule=eMaxCharge, doc='max charge of an ESS [p.u.]'))
717
717
 
718
718
  if pIndLogConsole == 1:
719
719
  print('eMaxCharge ... ', len(getattr(OptModel, f'eMaxCharge_{p}_{sc}_{st}')), ' rows')
@@ -732,7 +732,7 @@ def GenerationOperationModelFormulationStorage(OptModel, mTEPES, pIndLogConsole,
732
732
  if not mTEPES.pMaxCharge2ndBlock[p,sc,n,eh]:
733
733
  return Constraint.Skip
734
734
  return OptModel.vCharge2ndBlock[p,sc,n,eh] - OptModel.vESSReserveUp[p,sc,n,eh] >= 0.0
735
- setattr(OptModel, f'eMinCharge_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.eh, rule=eMinCharge, doc='min charge of an ESS [p.u.]'))
735
+ setattr(OptModel, f'eMinCharge_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.eh, rule=eMinCharge, doc='min charge of an ESS [p.u.]'))
736
736
 
737
737
  if pIndLogConsole == 1:
738
738
  print('eMinCharge ... ', len(getattr(OptModel, f'eMinCharge_{p}_{sc}_{st}')), ' rows')
@@ -742,7 +742,7 @@ def GenerationOperationModelFormulationStorage(OptModel, mTEPES, pIndLogConsole,
742
742
  # return OptModel.vTotalOutput[p,sc,n,eh] / mTEPES.pMaxPowerElec[p,sc,n,eh] + OptModel.vCharge2ndBlock[p,sc,n,eh] / mTEPES.pMaxCharge[p,sc,n,eh] <= 1
743
743
  # else:
744
744
  # return Constraint.Skip
745
- # OptModel.eChargeDischarge = Constraint(mTEPES.n, mTEPES.eh, rule=eChargeDischarge, doc='incompatibility between charge and discharge [p.u.]')
745
+ # OptModel.eChargeDischarge = Constraint(mTEPES.n*mTEPES.eh, rule=eChargeDischarge, doc='incompatibility between charge and discharge [p.u.]')
746
746
 
747
747
  # Generators with consumption capability cannot be consuming and generating simultaneously
748
748
  def eChargeDischarge(OptModel,n,eh):
@@ -760,7 +760,7 @@ def GenerationOperationModelFormulationStorage(OptModel, mTEPES, pIndLogConsole,
760
760
  # Hydro Generator
761
761
  else:
762
762
  return OptModel.vCommitment[p,sc,n,eh] + OptModel.vCommitmentCons[p,sc,n,eh] <= 1.0
763
- setattr(OptModel, f'eChargeDischarge_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.eh, rule=eChargeDischarge, doc='incompatibility between charge and discharge [p.u.]'))
763
+ setattr(OptModel, f'eChargeDischarge_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.eh, rule=eChargeDischarge, doc='incompatibility between charge and discharge [p.u.]'))
764
764
 
765
765
  if pIndLogConsole == 1:
766
766
  print('eChargeDischarge ... ', len(getattr(OptModel, f'eChargeDischarge_{p}_{sc}_{st}')), ' rows')
@@ -787,7 +787,7 @@ def GenerationOperationModelFormulationStorage(OptModel, mTEPES, pIndLogConsole,
787
787
  return OptModel.vESSTotalCharge[p,sc,n,eh] == OptModel.vCharge2ndBlock[p,sc,n,eh] + mTEPES.pDwReserveActivation * OptModel.vESSReserveDown[p,sc,n,eh] - mTEPES.pUpReserveActivation * OptModel.vESSReserveUp[p,sc,n,eh]
788
788
  else:
789
789
  return OptModel.vESSTotalCharge[p,sc,n,eh] / mTEPES.pMinCharge[p,sc,n,eh] == OptModel.vCommitmentCons[p,sc,n,eh] + (OptModel.vCharge2ndBlock[p,sc,n,eh] + mTEPES.pDwReserveActivation * OptModel.vESSReserveDown[p,sc,n,eh] - mTEPES.pUpReserveActivation * OptModel.vESSReserveUp[p,sc,n,eh]) / mTEPES.pMinCharge[p,sc,n,eh]
790
- setattr(OptModel, f'eESSTotalCharge_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.eh, rule=eESSTotalCharge, doc='total charge of an ESS unit [GW]'))
790
+ setattr(OptModel, f'eESSTotalCharge_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.eh, rule=eESSTotalCharge, doc='total charge of an ESS unit [GW]'))
791
791
 
792
792
  if pIndLogConsole == 1:
793
793
  print('eESSTotalCharge ... ', len(getattr(OptModel, f'eESSTotalCharge_{p}_{sc}_{st}')), ' rows')
@@ -800,7 +800,7 @@ def GenerationOperationModelFormulationStorage(OptModel, mTEPES, pIndLogConsole,
800
800
  return Constraint.Skip
801
801
  else:
802
802
  return Constraint.Skip
803
- setattr(OptModel, f'eChargeOutflows_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.eh, rule=eChargeOutflows, doc='incompatibility between charge and outflows use [p.u.]'))
803
+ setattr(OptModel, f'eChargeOutflows_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.eh, rule=eChargeOutflows, doc='incompatibility between charge and outflows use [p.u.]'))
804
804
 
805
805
  if pIndLogConsole == 1:
806
806
  print('eChargeOutflows ... ', len(getattr(OptModel, f'eChargeOutflows_{p}_{sc}_{st}')), ' rows')
@@ -1063,47 +1063,75 @@ def GenerationOperationModelFormulationCommitment(OptModel, mTEPES, pIndLogConso
1063
1063
  a2n[nr].append(ar)
1064
1064
 
1065
1065
  def eMaxOutput2ndBlock(OptModel,n,nr):
1066
- if (p,nr) in mTEPES.pnr and (nr not in mTEPES.es or (nr in mTEPES.es and (mTEPES.pTotalMaxCharge[nr] or mTEPES.pTotalEnergyInflows[nr]))) and sum(mTEPES.pOperReserveUp[p,sc,n,ar] for ar in a2n[nr]):
1067
- if mTEPES.pIndRampReserves == 0 or sum(mTEPES.pRampReserveUp[p,sc,n,ar] for ar in mTEPES.ar) == 0.0:
1068
- if mTEPES.pMaxPower2ndBlock[p,sc,n,nr] and mTEPES.pIndOperReserveGen[nr] != 1 and n != mTEPES.n.last():
1069
- return (OptModel.vOutput2ndBlock[p,sc,n,nr] + OptModel.vReserveUp [p,sc,n,nr] ) / mTEPES.pMaxPower2ndBlock[p,sc,n,nr] <= OptModel.vCommitment[p,sc,n,nr] - OptModel.vStartUp[p,sc,n,nr] - OptModel.vShutDown[p,sc,mTEPES.n.next(n),nr]
1070
- elif mTEPES.pMaxPower2ndBlock[p,sc,n,nr] and mTEPES.pIndOperReserveGen[nr] != 1 and n == mTEPES.n.last():
1071
- return (OptModel.vOutput2ndBlock[p,sc,n,nr] + OptModel.vReserveUp [p,sc,n,nr] ) / mTEPES.pMaxPower2ndBlock[p,sc,n,nr] <= OptModel.vCommitment[p,sc,n,nr] - OptModel.vStartUp[p,sc,n,nr]
1066
+ if mTEPES.pMaxPower2ndBlock[p,sc,n,nr] == 0.0:
1067
+ return Constraint.Skip
1068
+ if (p,nr) in mTEPES.pnr and (nr not in mTEPES.es or (nr in mTEPES.es and (mTEPES.pTotalMaxCharge[nr] or mTEPES.pTotalEnergyInflows[nr]))):
1069
+ if sum(mTEPES.pOperReserveUp[p,sc,n,ar] for ar in a2n[nr]):
1070
+ if mTEPES.pIndRampReserves == 0 or sum(mTEPES.pRampReserveUp[p,sc,n,ar] for ar in mTEPES.ar) == 0.0:
1071
+ if mTEPES.pIndOperReserveGen[nr] != 1 and n != mTEPES.n.last():
1072
+ return (OptModel.vOutput2ndBlock[p,sc,n,nr] + OptModel.vReserveUp [p,sc,n,nr] ) / mTEPES.pMaxPower2ndBlock[p,sc,n,nr] <= OptModel.vCommitment[p,sc,n,nr] - OptModel.vStartUp[p,sc,n,nr] - OptModel.vShutDown[p,sc,mTEPES.n.next(n),nr]
1073
+ elif mTEPES.pIndOperReserveGen[nr] != 1 and n == mTEPES.n.last():
1074
+ return (OptModel.vOutput2ndBlock[p,sc,n,nr] + OptModel.vReserveUp [p,sc,n,nr] ) / mTEPES.pMaxPower2ndBlock[p,sc,n,nr] <= OptModel.vCommitment[p,sc,n,nr] - OptModel.vStartUp[p,sc,n,nr]
1075
+ else:
1076
+ return Constraint.Skip
1077
+ elif mTEPES.pIndRampReserves == 1 and sum(mTEPES.pRampReserveUp[p,sc,n,ar] for ar in mTEPES.ar) > 0.0:
1078
+ if mTEPES.pIndOperReserveGen[nr] != 1 and n != mTEPES.n.last():
1079
+ return (OptModel.vOutput2ndBlock[p,sc,n,nr] + OptModel.vReserveUp [p,sc,n,nr] + OptModel.vRampReserveUp [p,sc,n,nr]) / mTEPES.pMaxPower2ndBlock[p,sc,n,nr] <= OptModel.vCommitment[p,sc,n,nr] - OptModel.vStartUp[p,sc,n,nr] - OptModel.vShutDown[p,sc,mTEPES.n.next(n),nr]
1080
+ elif mTEPES.pIndOperReserveGen[nr] != 1 and n == mTEPES.n.last():
1081
+ return (OptModel.vOutput2ndBlock[p,sc,n,nr] + OptModel.vReserveUp [p,sc,n,nr] + OptModel.vRampReserveUp [p,sc,n,nr]) / mTEPES.pMaxPower2ndBlock[p,sc,n,nr] <= OptModel.vCommitment[p,sc,n,nr] - OptModel.vStartUp[p,sc,n,nr]
1082
+ else:
1083
+ return Constraint.Skip
1072
1084
  else:
1073
1085
  return Constraint.Skip
1074
- elif mTEPES.pIndRampReserves == 1 and sum(mTEPES.pRampReserveUp[p,sc,n,ar] for ar in mTEPES.ar) > 0.0:
1075
- if mTEPES.pMaxPower2ndBlock[p,sc,n,nr] and mTEPES.pIndOperReserveGen[nr] != 1 and n != mTEPES.n.last():
1076
- return (OptModel.vOutput2ndBlock[p,sc,n,nr] + OptModel.vReserveUp [p,sc,n,nr] + OptModel.vRampReserveUp [p,sc,n,nr]) / mTEPES.pMaxPower2ndBlock[p,sc,n,nr] <= OptModel.vCommitment[p,sc,n,nr] - OptModel.vStartUp[p,sc,n,nr] - OptModel.vShutDown[p,sc,mTEPES.n.next(n),nr]
1077
- elif mTEPES.pMaxPower2ndBlock[p,sc,n,nr] and mTEPES.pIndOperReserveGen[nr] != 1 and n == mTEPES.n.last():
1078
- return (OptModel.vOutput2ndBlock[p,sc,n,nr] + OptModel.vReserveUp [p,sc,n,nr] + OptModel.vRampReserveUp [p,sc,n,nr]) / mTEPES.pMaxPower2ndBlock[p,sc,n,nr] <= OptModel.vCommitment[p,sc,n,nr] - OptModel.vStartUp[p,sc,n,nr]
1086
+ if sum(mTEPES.pOperReserveUp[p,sc,n,ar] for ar in a2n[nr]) == 0.0:
1087
+ if mTEPES.pIndRampReserves == 0 or sum(mTEPES.pRampReserveUp[p,sc,n,ar] for ar in mTEPES.ar) == 0.0:
1088
+ if n != mTEPES.n.last():
1089
+ return (OptModel.vOutput2ndBlock[p,sc,n,nr] ) / mTEPES.pMaxPower2ndBlock[p,sc,n,nr] <= OptModel.vCommitment[p,sc,n,nr] - OptModel.vStartUp[p,sc,n,nr] - OptModel.vShutDown[p,sc,mTEPES.n.next(n),nr]
1090
+ elif n == mTEPES.n.last():
1091
+ return (OptModel.vOutput2ndBlock[p,sc,n,nr] ) / mTEPES.pMaxPower2ndBlock[p,sc,n,nr] <= OptModel.vCommitment[p,sc,n,nr] - OptModel.vStartUp[p,sc,n,nr]
1092
+ else:
1093
+ return Constraint.Skip
1094
+ elif mTEPES.pIndRampReserves == 1 and sum(mTEPES.pRampReserveUp[p,sc,n,ar] for ar in mTEPES.ar) > 0.0:
1095
+ if n != mTEPES.n.last():
1096
+ return (OptModel.vOutput2ndBlock[p,sc,n,nr] + OptModel.vRampReserveUp [p,sc,n,nr]) / mTEPES.pMaxPower2ndBlock[p,sc,n,nr] <= OptModel.vCommitment[p,sc,n,nr] - OptModel.vStartUp[p,sc,n,nr] - OptModel.vShutDown[p,sc,mTEPES.n.next(n),nr]
1097
+ elif n == mTEPES.n.last():
1098
+ return (OptModel.vOutput2ndBlock[p,sc,n,nr] + OptModel.vRampReserveUp [p,sc,n,nr]) / mTEPES.pMaxPower2ndBlock[p,sc,n,nr] <= OptModel.vCommitment[p,sc,n,nr] - OptModel.vStartUp[p,sc,n,nr]
1099
+ else:
1100
+ return Constraint.Skip
1079
1101
  else:
1080
1102
  return Constraint.Skip
1081
- else:
1082
- return Constraint.Skip
1083
1103
  else:
1084
1104
  return Constraint.Skip
1085
- setattr(OptModel, f'eMaxOutput2ndBlock_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.nr, rule=eMaxOutput2ndBlock, doc='max output of the second block of a committed unit [p.u.]'))
1105
+ setattr(OptModel, f'eMaxOutput2ndBlock_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.nr, rule=eMaxOutput2ndBlock, doc='max output of the second block of a committed unit [p.u.]'))
1086
1106
 
1087
1107
  if pIndLogConsole == 1:
1088
1108
  print('eMaxOutput2ndBlock ... ', len(getattr(OptModel, f'eMaxOutput2ndBlock_{p}_{sc}_{st}')), ' rows')
1089
1109
 
1090
1110
  def eMinOutput2ndBlock(OptModel,n,nr):
1091
- if (p,nr) in mTEPES.pnr and (nr not in mTEPES.es or (nr in mTEPES.es and (mTEPES.pTotalMaxCharge[nr] or mTEPES.pTotalEnergyInflows[nr]))) and sum(mTEPES.pOperReserveDw[p,sc,n,ar] for ar in a2n[nr]):
1092
- if mTEPES.pMaxPower2ndBlock[p,sc,n,nr] and mTEPES.pIndOperReserveGen[nr] != 1 and (mTEPES.pIndRampReserves == 0 or sum(mTEPES.pRampReserveDw[p,sc,n,ar] for ar in mTEPES.ar) == 0.0):
1093
- return OptModel.vOutput2ndBlock[p,sc,n,nr] - OptModel.vReserveDown[p,sc,n,nr] >= 0.0
1094
- if mTEPES.pMaxPower2ndBlock[p,sc,n,nr] and mTEPES.pIndOperReserveGen[nr] != 1 and mTEPES.pIndRampReserves == 1 and sum(mTEPES.pRampReserveDw[p,sc,n,ar] for ar in mTEPES.ar) > 0.0:
1095
- return OptModel.vOutput2ndBlock[p,sc,n,nr] - OptModel.vReserveDown[p,sc,n,nr] - OptModel.vRampReserveDw[p,sc,n,nr] >= 0.0
1096
- else:
1097
- return Constraint.Skip
1111
+ if mTEPES.pMaxPower2ndBlock[p,sc,n,nr] == 0.0:
1112
+ return Constraint.Skip
1113
+ if (p,nr) in mTEPES.pnr and (nr not in mTEPES.es or (nr in mTEPES.es and (mTEPES.pTotalMaxCharge[nr] or mTEPES.pTotalEnergyInflows[nr]))):
1114
+ if sum(mTEPES.pOperReserveDw[p,sc,n,ar] for ar in a2n[nr]):
1115
+ if mTEPES.pIndOperReserveGen[nr] != 1 and (mTEPES.pIndRampReserves == 0 or sum(mTEPES.pRampReserveDw[p,sc,n,ar] for ar in mTEPES.ar) == 0.0):
1116
+ return OptModel.vOutput2ndBlock[p,sc,n,nr] - OptModel.vReserveDown[p,sc,n,nr] >= 0.0
1117
+ elif mTEPES.pIndOperReserveGen[nr] != 1 and mTEPES.pIndRampReserves == 1 and sum(mTEPES.pRampReserveDw[p,sc,n,ar] for ar in mTEPES.ar) > 0.0:
1118
+ return OptModel.vOutput2ndBlock[p,sc,n,nr] - OptModel.vReserveDown[p,sc,n,nr] - OptModel.vRampReserveDw[p,sc,n,nr] >= 0.0
1119
+ else:
1120
+ return Constraint.Skip
1121
+ if sum(mTEPES.pOperReserveDw[p,sc,n,ar] for ar in a2n[nr]) == 0.0:
1122
+ if mTEPES.pIndRampReserves == 1 and sum(mTEPES.pRampReserveDw[p,sc,n,ar] for ar in mTEPES.ar) > 0.0:
1123
+ return OptModel.vOutput2ndBlock[p,sc,n,nr] - OptModel.vRampReserveDw[p,sc,n,nr] >= 0.0
1124
+ else:
1125
+ return Constraint.Skip
1098
1126
  else:
1099
1127
  return Constraint.Skip
1100
- setattr(OptModel, f'eMinOutput2ndBlock_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.nr, rule=eMinOutput2ndBlock, doc='min output of the second block of a committed unit [p.u.]'))
1128
+ setattr(OptModel, f'eMinOutput2ndBlock_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.nr, rule=eMinOutput2ndBlock, doc='min output of the second block of a committed unit [p.u.]'))
1101
1129
 
1102
1130
  if pIndLogConsole == 1:
1103
1131
  print('eMinOutput2ndBlock ... ', len(getattr(OptModel, f'eMinOutput2ndBlock_{p}_{sc}_{st}')), ' rows')
1104
1132
 
1105
1133
  def eTotalOutput(OptModel,n,nr):
1106
- if (p,nr) in mTEPES.pnr and (nr not in mTEPES.es or (nr in mTEPES.es and (mTEPES.pTotalMaxCharge[nr] or mTEPES.pTotalEnergyInflows[nr]))):
1134
+ if (p,nr) in mTEPES.pnr and (mTEPES.pMustRun[nr] == 0 or mTEPES.pMaxPower2ndBlock[p,sc,n,nr] or nr in mTEPES.gc) and (nr not in mTEPES.es or (nr in mTEPES.es and (mTEPES.pTotalMaxCharge[nr] or mTEPES.pTotalEnergyInflows[nr]))):
1107
1135
  if mTEPES.pMaxPowerElec[p,sc,n,nr]:
1108
1136
  if mTEPES.pMinPowerElec[p,sc,n,nr] == 0.0:
1109
1137
  return OptModel.vTotalOutput[p,sc,n,nr] == OptModel.vOutput2ndBlock[p,sc,n,nr] + mTEPES.pUpReserveActivation * OptModel.vReserveUp[p,sc,n,nr] - mTEPES.pDwReserveActivation * OptModel.vReserveDown[p,sc,n,nr]
@@ -1113,7 +1141,7 @@ def GenerationOperationModelFormulationCommitment(OptModel, mTEPES, pIndLogConso
1113
1141
  return Constraint.Skip
1114
1142
  else:
1115
1143
  return Constraint.Skip
1116
- setattr(OptModel, f'eTotalOutput_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.nr, rule=eTotalOutput, doc='total output of a unit [GW]'))
1144
+ setattr(OptModel, f'eTotalOutput_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.nr, rule=eTotalOutput, doc='total output of a unit [GW]'))
1117
1145
 
1118
1146
  if pIndLogConsole == 1:
1119
1147
  print('eTotalOutput ... ', len(getattr(OptModel, f'eTotalOutput_{p}_{sc}_{st}')), ' rows')
@@ -1129,7 +1157,7 @@ def GenerationOperationModelFormulationCommitment(OptModel, mTEPES, pIndLogConso
1129
1157
  return Constraint.Skip
1130
1158
  else:
1131
1159
  return Constraint.Skip
1132
- setattr(OptModel, f'eUCStrShut_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.nr, rule=eUCStrShut, doc='relation among commitment startup and shutdown [p.u.]'))
1160
+ setattr(OptModel, f'eUCStrShut_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.nr, rule=eUCStrShut, doc='relation among commitment startup and shutdown [p.u.]'))
1133
1161
 
1134
1162
  if pIndLogConsole == 1:
1135
1163
  print('eUCStrShut ... ', len(getattr(OptModel, f'eUCStrShut_{p}_{sc}_{st}')), ' rows')
@@ -1159,7 +1187,7 @@ def GenerationOperationModelFormulationCommitment(OptModel, mTEPES, pIndLogConso
1159
1187
  return Constraint.Skip
1160
1188
  return OptModel.vCommitment[p,sc,n,nr] <= OptModel.vMaxCommitmentYearly[p,sc,nr,group]
1161
1189
 
1162
- setattr(OptModel, f'eMaxCommitmentYearly_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.ExclusiveGroupsYearly, mTEPES.nr, rule=eMaxCommitmentYearly, doc='maximum of all the commitments [p.u.]'))
1190
+ setattr(OptModel, f'eMaxCommitmentYearly_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.ExclusiveGroupsYearly*mTEPES.nr, rule=eMaxCommitmentYearly, doc='maximum of all the commitments [p.u.]'))
1163
1191
 
1164
1192
  if pIndLogConsole == 1:
1165
1193
  print('eMaxCommitmentYearly ... ', len(getattr(OptModel, f'eMaxCommitmentYearly_{p}_{sc}_{st}')), ' rows')
@@ -1178,14 +1206,13 @@ def GenerationOperationModelFormulationCommitment(OptModel, mTEPES, pIndLogConso
1178
1206
  if len(mTEPES.GeneratorsInYearlyGroup[group] & {nr for (p, nr) in mTEPES.pnr}) <= 1:
1179
1207
  return Constraint.Skip
1180
1208
  return OptModel.vTotalOutput[p,sc,n,nr]/mTEPES.pMaxPowerElec[p,sc,n,nr] <= OptModel.vMaxCommitmentYearly[p,sc,nr,group]
1181
-
1182
- setattr(OptModel, f'eMaxCommitGenYearly_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.ExclusiveGroupsYearly,mTEPES.nr, rule=eMaxCommitGenYearly, doc='maximum of all the capacity factors'))
1209
+ setattr(OptModel, f'eMaxCommitGenYearly_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.ExclusiveGroupsYearly*mTEPES.nr, rule=eMaxCommitGenYearly, doc='maximum of all the capacity factors'))
1183
1210
 
1184
1211
  if pIndLogConsole == 1:
1185
1212
  print('eMaxCommitGenYearly ... ', len(getattr(OptModel, f'eMaxCommitGenYearly_{p}_{sc}_{st}')), ' rows')
1186
1213
 
1187
1214
  def eExclusiveGensYearly(OptModel,group):
1188
- # Skip if there are one or less generators in the group
1215
+ # Skip if there are one or fewer generators in the group
1189
1216
  if len(mTEPES.GeneratorsInYearlyGroup[group] & {nr for (p,nr) in mTEPES.pnr}) <= 1:
1190
1217
  return Constraint.Skip
1191
1218
  return sum(OptModel.vMaxCommitmentYearly[p,sc,nr,group] + (OptModel.vCommitmentCons[p,sc,nr] if nr in mTEPES.h else 0) for nr in mTEPES.GeneratorsInYearlyGroup[group] if (p,nr) in mTEPES.pnr ) <= 1
@@ -1209,8 +1236,7 @@ def GenerationOperationModelFormulationCommitment(OptModel, mTEPES, pIndLogConso
1209
1236
  if len(mTEPES.GeneratorsInHourlyGroup[group] & {nr for (p,nr) in mTEPES.pnr}) <= 1:
1210
1237
  return Constraint.Skip
1211
1238
  return OptModel.vCommitment[p,sc,n,nr] <= OptModel.vMaxCommitmentHourly[p,sc,n,nr,group]
1212
-
1213
- setattr(OptModel, f'eMaxCommitmentHourly_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.ExclusiveGroupsHourly, mTEPES.nr, rule=eMaxCommitmentHourly, doc='maximum of all the commitments [p.u.]'))
1239
+ setattr(OptModel, f'eMaxCommitmentHourly_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.ExclusiveGroupsHourly*mTEPES.nr, rule=eMaxCommitmentHourly, doc='maximum of all the commitments [p.u.]'))
1214
1240
 
1215
1241
  if pIndLogConsole == 1:
1216
1242
  print('eMaxCommitmentHourly ... ', len(getattr(OptModel, f'eMaxCommitmentHourly_{p}_{sc}_{st}')), ' rows')
@@ -1230,7 +1256,7 @@ def GenerationOperationModelFormulationCommitment(OptModel, mTEPES, pIndLogConso
1230
1256
  return Constraint.Skip
1231
1257
  return OptModel.vTotalOutput[p,sc,n,nr]/mTEPES.pMaxPowerElec[p,sc,n,nr] <= OptModel.vMaxCommitmentHourly[p,sc,n,nr,group]
1232
1258
 
1233
- setattr(OptModel, f'eMaxCommitGenHourly_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.ExclusiveGroupsHourly,mTEPES.nr, rule=eMaxCommitGenHourly, doc='maximum of all the capacity factors'))
1259
+ setattr(OptModel, f'eMaxCommitGenHourly_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.ExclusiveGroupsHourly*mTEPES.nr, rule=eMaxCommitGenHourly, doc='maximum of all the capacity factors'))
1234
1260
 
1235
1261
  if pIndLogConsole == 1:
1236
1262
  print('eMaxCommitGenHourly ... ', len(getattr(OptModel, f'eMaxCommitGenHourly_{p}_{sc}_{st}')), ' rows')
@@ -1241,8 +1267,7 @@ def GenerationOperationModelFormulationCommitment(OptModel, mTEPES, pIndLogConso
1241
1267
  if len(mTEPES.GeneratorsInHourlyGroup[group] & {gen for (period, gen) in mTEPES.pnr if period == p}) <= 1:
1242
1268
  return Constraint.Skip
1243
1269
  return sum(OptModel.vMaxCommitmentHourly[p,sc,n,nr,group] + (OptModel.vCommitmentCons[p,sc,n,nr] if nr in mTEPES.h else 0) for nr in mTEPES.GeneratorsInHourlyGroup[group] if (p, nr) in mTEPES.pnr ) <= 1
1244
-
1245
- setattr(OptModel, f'eExclusiveGensHourly_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.ExclusiveGroupsHourly, rule=eExclusiveGensHourly, doc='mutually exclusive generators'))
1270
+ setattr(OptModel, f'eExclusiveGensHourly_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.ExclusiveGroupsHourly, rule=eExclusiveGensHourly, doc='mutually exclusive generators'))
1246
1271
 
1247
1272
  if pIndLogConsole == 1:
1248
1273
  print('eExclusiveGensHourly ... ', len(getattr(OptModel, f'eExclusiveGensHourly_{p}_{sc}_{st}')), ' rows')
@@ -1289,7 +1314,7 @@ def GenerationOperationModelFormulationRampMinTime(OptModel, mTEPES, pIndLogCons
1289
1314
  return Constraint.Skip
1290
1315
  else:
1291
1316
  return Constraint.Skip
1292
- setattr(OptModel, f'eRampUp_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.nr, rule=eRampUp, doc='maximum ramp up [p.u.]'))
1317
+ setattr(OptModel, f'eRampUp_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.nr, rule=eRampUp, doc='maximum ramp up [p.u.]'))
1293
1318
 
1294
1319
  if pIndLogConsole == 1:
1295
1320
  print('eRampUp ... ', len(getattr(OptModel, f'eRampUp_{p}_{sc}_{st}')), ' rows')
@@ -1305,7 +1330,7 @@ def GenerationOperationModelFormulationRampMinTime(OptModel, mTEPES, pIndLogCons
1305
1330
  return Constraint.Skip
1306
1331
  else:
1307
1332
  return Constraint.Skip
1308
- setattr(OptModel, f'eRampDw_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.nr, rule=eRampDw, doc='maximum ramp down [p.u.]'))
1333
+ setattr(OptModel, f'eRampDw_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.nr, rule=eRampDw, doc='maximum ramp down [p.u.]'))
1309
1334
 
1310
1335
  if pIndLogConsole == 1:
1311
1336
  print('eRampDw ... ', len(getattr(OptModel, f'eRampDw_{p}_{sc}_{st}')), ' rows')
@@ -1321,7 +1346,7 @@ def GenerationOperationModelFormulationRampMinTime(OptModel, mTEPES, pIndLogCons
1321
1346
  return Constraint.Skip
1322
1347
  else:
1323
1348
  return Constraint.Skip
1324
- setattr(OptModel, f'eRampUpChr_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.eh, rule=eRampUpCharge, doc='maximum ramp up charge [p.u.]'))
1349
+ setattr(OptModel, f'eRampUpChr_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.eh, rule=eRampUpCharge, doc='maximum ramp up charge [p.u.]'))
1325
1350
 
1326
1351
  if pIndLogConsole == 1:
1327
1352
  print('eRampUpChr ... ', len(getattr(OptModel, f'eRampUpChr_{p}_{sc}_{st}')), ' rows')
@@ -1337,7 +1362,7 @@ def GenerationOperationModelFormulationRampMinTime(OptModel, mTEPES, pIndLogCons
1337
1362
  return Constraint.Skip
1338
1363
  else:
1339
1364
  return Constraint.Skip
1340
- setattr(OptModel, f'eRampDwChr_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.eh, rule=eRampDwCharge, doc='maximum ramp down charge [p.u.]'))
1365
+ setattr(OptModel, f'eRampDwChr_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.eh, rule=eRampDwCharge, doc='maximum ramp down charge [p.u.]'))
1341
1366
 
1342
1367
  if pIndLogConsole == 1:
1343
1368
  print('eRampDwChr ... ', len(getattr(OptModel, f'eRampDwChr_{p}_{sc}_{st}')), ' rows')
@@ -1376,7 +1401,7 @@ def GenerationOperationModelFormulationRampMinTime(OptModel, mTEPES, pIndLogCons
1376
1401
  return (- OptModel.vOutput2ndBlock[p,sc,mTEPES.n.prev(n),nr] + OptModel.vOutput2ndBlock[p,sc,n,nr]) / mTEPES.pDuration[p,sc,n]() / mTEPES.pMaxPower2ndBlock[p,sc,n,nr] <= OptModel.vRampUpState[p,sc,n,nr] - pEpsilon * OptModel.vRampDwState[p,sc,n,nr]
1377
1402
  else:
1378
1403
  return Constraint.Skip
1379
- setattr(OptModel, f'eRampUpState_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.nr, rule=eRampUpState, doc='ramp up state [p.u.]'))
1404
+ setattr(OptModel, f'eRampUpState_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.nr, rule=eRampUpState, doc='ramp up state [p.u.]'))
1380
1405
 
1381
1406
  if pIndLogConsole == 1:
1382
1407
  print('eRampUpState ... ', len(getattr(OptModel, f'eRampUpState_{p}_{sc}_{st}')), ' rows')
@@ -1407,7 +1432,7 @@ def GenerationOperationModelFormulationRampMinTime(OptModel, mTEPES, pIndLogCons
1407
1432
  return (OptModel.vOutput2ndBlock[p,sc,mTEPES.n.prev(n),nr] - OptModel.vOutput2ndBlock[p,sc,n,nr]) / mTEPES.pDuration[p,sc,n]() / mTEPES.pMaxPower2ndBlock[p,sc,n,nr] <= OptModel.vRampDwState[p,sc,n,nr] - pEpsilon * OptModel.vRampUpState[p,sc,n,nr]
1408
1433
  else:
1409
1434
  return Constraint.Skip
1410
- setattr(OptModel, f'eRampDwState_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.nr, rule=eRampDwState, doc='maximum ramp down [p.u.]'))
1435
+ setattr(OptModel, f'eRampDwState_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.nr, rule=eRampDwState, doc='maximum ramp down [p.u.]'))
1411
1436
 
1412
1437
  if pIndLogConsole == 1:
1413
1438
  print('eRampDwState ... ', len(getattr(OptModel, f'eRampDwState_{p}_{sc}_{st}')), ' rows')
@@ -1420,7 +1445,7 @@ def GenerationOperationModelFormulationRampMinTime(OptModel, mTEPES, pIndLogCons
1420
1445
  return Constraint.Skip
1421
1446
  else:
1422
1447
  return Constraint.Skip
1423
- setattr(OptModel, f'eMinUpTime_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.t, rule=eMinUpTime , doc='minimum up time [p.u.]'))
1448
+ setattr(OptModel, f'eMinUpTime_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.t, rule=eMinUpTime , doc='minimum up time [p.u.]'))
1424
1449
 
1425
1450
  if pIndLogConsole == 1:
1426
1451
  print('eMinUpTime ... ', len(getattr(OptModel, f'eMinUpTime_{p}_{sc}_{st}')), ' rows')
@@ -1433,7 +1458,7 @@ def GenerationOperationModelFormulationRampMinTime(OptModel, mTEPES, pIndLogCons
1433
1458
  return Constraint.Skip
1434
1459
  else:
1435
1460
  return Constraint.Skip
1436
- setattr(OptModel, f'eMinDownTime_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.t, rule=eMinDownTime, doc='minimum down time [p.u.]'))
1461
+ setattr(OptModel, f'eMinDownTime_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.t, rule=eMinDownTime, doc='minimum down time [p.u.]'))
1437
1462
 
1438
1463
  if pIndLogConsole == 1:
1439
1464
  print('eMinDownTime ... ', len(getattr(OptModel, f'eMinDownTime_{p}_{sc}_{st}')), ' rows')
@@ -1444,7 +1469,7 @@ def GenerationOperationModelFormulationRampMinTime(OptModel, mTEPES, pIndLogCons
1444
1469
  return OptModel.vRampUpState[p,sc,n,nr] + sum(OptModel.vRampDwState[p,sc,n2,nr] for n2 in list(mTEPES.n2)[mTEPES.n.ord(n)-mTEPES.pStableTime[nr]-1:mTEPES.n.ord(n)-1]) <= 1
1445
1470
  else:
1446
1471
  return Constraint.Skip
1447
- setattr(OptModel, f'eMinStableTime_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.nr, rule=eMinStableTime, doc='minimum stable time [p.u.]'))
1472
+ setattr(OptModel, f'eMinStableTime_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.nr, rule=eMinStableTime, doc='minimum stable time [p.u.]'))
1448
1473
  else:
1449
1474
  MinStableTimeLoadLevels = []
1450
1475
  if sum(mTEPES.pStableTime[nr] for nr in mTEPES.nr):
@@ -1480,7 +1505,7 @@ def NetworkSwitchingModelFormulation(OptModel, mTEPES, pIndLogConsole, p, sc, st
1480
1505
  return OptModel.vLineCommit[p,sc,n,ni,nf,cc] == OptModel.vNetworkInvest[p,ni,nf,cc]
1481
1506
  else:
1482
1507
  return Constraint.Skip
1483
- setattr(OptModel, f'eLineStateCand_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.lc, rule=eLineStateCand, doc='logical relation between investment and operation in candidates'))
1508
+ setattr(OptModel, f'eLineStateCand_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.lc, rule=eLineStateCand, doc='logical relation between investment and operation in candidates'))
1484
1509
 
1485
1510
  if pIndLogConsole == 1:
1486
1511
  print('eLineStateCand ... ', len(getattr(OptModel, f'eLineStateCand_{p}_{sc}_{st}')), ' rows')
@@ -1496,7 +1521,7 @@ def NetworkSwitchingModelFormulation(OptModel, mTEPES, pIndLogConsole, p, sc, st
1496
1521
  return Constraint.Skip
1497
1522
  else:
1498
1523
  return Constraint.Skip
1499
- setattr(OptModel, f'eSWOnOff_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.la, rule=eSWOnOff, doc='relation among switching decision activate and deactivate state'))
1524
+ setattr(OptModel, f'eSWOnOff_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.la, rule=eSWOnOff, doc='relation among switching decision activate and deactivate state'))
1500
1525
 
1501
1526
  if pIndLogConsole == 1:
1502
1527
  print('eSWOnOff ... ', len(getattr(OptModel, f'eSWOnOff_{p}_{sc}_{st}')), ' rows')
@@ -1509,7 +1534,7 @@ def NetworkSwitchingModelFormulation(OptModel, mTEPES, pIndLogConsole, p, sc, st
1509
1534
  return Constraint.Skip
1510
1535
  else:
1511
1536
  return Constraint.Skip
1512
- setattr(OptModel, f'eMinSwOnState_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.la, rule=eMinSwOnState, doc='minimum switch on state [h]'))
1537
+ setattr(OptModel, f'eMinSwOnState_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.la, rule=eMinSwOnState, doc='minimum switch on state [h]'))
1513
1538
 
1514
1539
  if pIndLogConsole == 1:
1515
1540
  print('eMinSwOnState ... ', len(getattr(OptModel, f'eMinSwOnState_{p}_{sc}_{st}')), ' rows')
@@ -1522,7 +1547,7 @@ def NetworkSwitchingModelFormulation(OptModel, mTEPES, pIndLogConsole, p, sc, st
1522
1547
  return Constraint.Skip
1523
1548
  else:
1524
1549
  return Constraint.Skip
1525
- setattr(OptModel, f'eMinSwOffState_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.la, rule=eMinSwOffState, doc='minimum switch off state [h]'))
1550
+ setattr(OptModel, f'eMinSwOffState_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.la, rule=eMinSwOffState, doc='minimum switch off state [h]'))
1526
1551
 
1527
1552
  if pIndLogConsole == 1:
1528
1553
  print('eMinSwOffState ... ', len(getattr(OptModel, f'eMinSwOffState_{p}_{sc}_{st}')), ' rows')
@@ -1543,7 +1568,7 @@ def NetworkOperationModelFormulation(OptModel, mTEPES, pIndLogConsole, p, sc, st
1543
1568
  return OptModel.vFlowElec[p,sc,n,ni,nf,cc] / mTEPES.pMaxNTCMax[p,sc,n,ni,nf,cc] >= - OptModel.vLineCommit[p,sc,n,ni,nf,cc]
1544
1569
  else:
1545
1570
  return Constraint.Skip
1546
- setattr(OptModel, f'eNetCapacity1_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.la, rule=eNetCapacity1, doc='maximum flow by existing network capacity [p.u.]'))
1571
+ setattr(OptModel, f'eNetCapacity1_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.la, rule=eNetCapacity1, doc='maximum flow by existing network capacity [p.u.]'))
1547
1572
 
1548
1573
  if pIndLogConsole == 1:
1549
1574
  print('eNetCapacity1 ... ', len(getattr(OptModel, f'eNetCapacity1_{p}_{sc}_{st}')), ' rows')
@@ -1553,7 +1578,7 @@ def NetworkOperationModelFormulation(OptModel, mTEPES, pIndLogConsole, p, sc, st
1553
1578
  return OptModel.vFlowElec[p,sc,n,ni,nf,cc] / mTEPES.pMaxNTCMax[p,sc,n,ni,nf,cc] <= OptModel.vLineCommit[p,sc,n,ni,nf,cc]
1554
1579
  else:
1555
1580
  return Constraint.Skip
1556
- setattr(OptModel, f'eNetCapacity2_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.la, rule=eNetCapacity2, doc='maximum flow by existing network capacity [p.u.]'))
1581
+ setattr(OptModel, f'eNetCapacity2_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.la, rule=eNetCapacity2, doc='maximum flow by existing network capacity [p.u.]'))
1557
1582
 
1558
1583
  if pIndLogConsole == 1:
1559
1584
  print('eNetCapacity2 ... ', len(getattr(OptModel, f'eNetCapacity2_{p}_{sc}_{st}')), ' rows')
@@ -1566,7 +1591,7 @@ def NetworkOperationModelFormulation(OptModel, mTEPES, pIndLogConsole, p, sc, st
1566
1591
  return OptModel.vFlowElec[p,sc,n,ni,nf,cc] / mTEPES.pBigMFlowBck[ni,nf,cc]() - (OptModel.vTheta[p,sc,n,ni] - OptModel.vTheta[p,sc,n,nf]) / mTEPES.pLineX[ni,nf,cc] / mTEPES.pBigMFlowBck[ni,nf,cc]() * mTEPES.pSBase == 0
1567
1592
  else:
1568
1593
  return Constraint.Skip
1569
- setattr(OptModel, f'eKirchhoff2ndLaw1_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.laa, rule=eKirchhoff2ndLaw1, doc='flow for each AC candidate line [rad]'))
1594
+ setattr(OptModel, f'eKirchhoff2ndLaw1_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.laa, rule=eKirchhoff2ndLaw1, doc='flow for each AC candidate line [rad]'))
1570
1595
 
1571
1596
  if pIndLogConsole == 1:
1572
1597
  print('eKirchhoff2ndLaw1 ... ', len(getattr(OptModel, f'eKirchhoff2ndLaw1_{p}_{sc}_{st}')), ' rows')
@@ -1576,7 +1601,7 @@ def NetworkOperationModelFormulation(OptModel, mTEPES, pIndLogConsole, p, sc, st
1576
1601
  return OptModel.vFlowElec[p,sc,n,ni,nf,cc] / mTEPES.pBigMFlowFrw[ni,nf,cc]() - (OptModel.vTheta[p,sc,n,ni] - OptModel.vTheta[p,sc,n,nf]) / mTEPES.pLineX[ni,nf,cc] / mTEPES.pBigMFlowFrw[ni,nf,cc]() * mTEPES.pSBase <= 1 - OptModel.vLineCommit[p,sc,n,ni,nf,cc]
1577
1602
  else:
1578
1603
  return Constraint.Skip
1579
- setattr(OptModel, f'eKirchhoff2ndLaw2_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.lca, rule=eKirchhoff2ndLaw2, doc='flow for each AC candidate line [rad]'))
1604
+ setattr(OptModel, f'eKirchhoff2ndLaw2_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.lca, rule=eKirchhoff2ndLaw2, doc='flow for each AC candidate line [rad]'))
1580
1605
 
1581
1606
  if pIndLogConsole == 1:
1582
1607
  print('eKirchhoff2ndLaw2 ... ', len(getattr(OptModel, f'eKirchhoff2ndLaw2_{p}_{sc}_{st}')), ' rows')
@@ -1586,7 +1611,7 @@ def NetworkOperationModelFormulation(OptModel, mTEPES, pIndLogConsole, p, sc, st
1586
1611
  return OptModel.vLineLosses[p,sc,n,ni,nf,cc] >= - 0.5 * mTEPES.pLineLossFactor[ni,nf,cc] * OptModel.vFlowElec[p,sc,n,ni,nf,cc]
1587
1612
  else:
1588
1613
  return Constraint.Skip
1589
- setattr(OptModel, f'eLineLosses1_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.ll, rule=eLineLosses1, doc='ohmic losses for all the lines [GW]'))
1614
+ setattr(OptModel, f'eLineLosses1_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.ll, rule=eLineLosses1, doc='ohmic losses for all the lines [GW]'))
1590
1615
 
1591
1616
  if pIndLogConsole == 1:
1592
1617
  print('eLineLosses1 ... ', len(getattr(OptModel, f'eLineLosses1_{p}_{sc}_{st}')), ' rows')
@@ -1596,7 +1621,7 @@ def NetworkOperationModelFormulation(OptModel, mTEPES, pIndLogConsole, p, sc, st
1596
1621
  return OptModel.vLineLosses[p,sc,n,ni,nf,cc] >= 0.5 * mTEPES.pLineLossFactor[ni,nf,cc] * OptModel.vFlowElec[p,sc,n,ni,nf,cc]
1597
1622
  else:
1598
1623
  return Constraint.Skip
1599
- setattr(OptModel, f'eLineLosses2_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.ll, rule=eLineLosses2, doc='ohmic losses for all the lines [GW]'))
1624
+ setattr(OptModel, f'eLineLosses2_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.ll, rule=eLineLosses2, doc='ohmic losses for all the lines [GW]'))
1600
1625
 
1601
1626
  if pIndLogConsole == 1:
1602
1627
  print('eLineLosses2 ... ', len(getattr(OptModel, f'eLineLosses2_{p}_{sc}_{st}')), ' rows')
@@ -1616,7 +1641,7 @@ def NetworkOperationModelFormulation(OptModel, mTEPES, pIndLogConsole, p, sc, st
1616
1641
  return (OptModel.vNetPosition[p,sc,n,nd] == sum(OptModel.vTotalOutput[p,sc,n,g] for g in g2n[nd] if (p,g) in mTEPES.pg) - sum(OptModel.vESSTotalCharge[p,sc,n,eh] for eh in e2n[nd] if (p,eh) in mTEPES.peh) + OptModel.vENS[p,sc,n,nd] - mTEPES.pDemandElec[p,sc,n,nd])
1617
1642
  else:
1618
1643
  return Constraint.Skip
1619
- setattr(OptModel, f'eNetPosition_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.nd, rule=eNetPosition, doc='net position [GW]'))
1644
+ setattr(OptModel, f'eNetPosition_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.nd, rule=eNetPosition, doc='net position [GW]'))
1620
1645
 
1621
1646
  def eFlowBasedCalcu1(OptModel,n,ni,nf,cc):
1622
1647
  if mTEPES.pIndBinSingleNode() == 0 and mTEPES.pElecNetPeriodIni[ni,nf,cc] <= p and mTEPES.pElecNetPeriodFin[ni,nf,cc] >= p and mTEPES.pIndPTDF == 1 and mTEPES.pIndBinLinePTDF[ni,nf,cc] == 1:
@@ -1626,7 +1651,7 @@ def NetworkOperationModelFormulation(OptModel, mTEPES, pIndLogConsole, p, sc, st
1626
1651
  return OptModel.vFlowElec[p,sc,n,ni,nf,cc] - sum(mTEPES.pPTDF[p,sc,n,ni,nf,cc,nd] * OptModel.vNetPosition[p,sc,n,nd] for nd in mTEPES.nd if (p,sc,n,ni,nf,cc,nd) in mTEPES.psnland) == 0
1627
1652
  else:
1628
1653
  return Constraint.Skip
1629
- setattr(OptModel, f'eFlowBasedCalcu1_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.la, rule=eFlowBasedCalcu1, doc='flow based calculation [p.u.]'))
1654
+ setattr(OptModel, f'eFlowBasedCalcu1_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.la, rule=eFlowBasedCalcu1, doc='flow based calculation [p.u.]'))
1630
1655
 
1631
1656
  if pIndLogConsole == 1:
1632
1657
  print('eFlowBasedCalcu1 ... ', len(getattr(OptModel, f'eFlowBasedCalcu1_{p}_{sc}_{st}')), ' rows')
@@ -1636,7 +1661,7 @@ def NetworkOperationModelFormulation(OptModel, mTEPES, pIndLogConsole, p, sc, st
1636
1661
  return OptModel.vFlowElec[p,sc,n,ni,nf,cc] - sum(mTEPES.pPTDF[p,sc,n,ni,nf,cc,nd] * OptModel.vNetPosition[p,sc,n,nd] for nd in mTEPES.nd if (p,sc,n,ni,nf,cc,nd) in mTEPES.psnland) <= 1 - OptModel.vLineCommit[p,sc,n,ni,nf,cc]
1637
1662
  else:
1638
1663
  return Constraint.Skip
1639
- setattr(OptModel, f'eFlowBasedCalcu2_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.lca, rule=eFlowBasedCalcu2, doc='flow based calculation [p.u.]'))
1664
+ setattr(OptModel, f'eFlowBasedCalcu2_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.lca, rule=eFlowBasedCalcu2, doc='flow based calculation [p.u.]'))
1640
1665
 
1641
1666
  if pIndLogConsole == 1:
1642
1667
  print('eFlowBasedCalcu2 ... ', len(getattr(OptModel, f'eFlowBasedCalcu2_{p}_{sc}_{st}')), ' rows')
@@ -1646,7 +1671,7 @@ def NetworkOperationModelFormulation(OptModel, mTEPES, pIndLogConsole, p, sc, st
1646
1671
  # return OptModel.vFlowElec[p,sc,n,ni,nf,cc] <= mTEPES.pVariableTTCFrw[p,sc,n,ni,nf,cc]
1647
1672
  # else:
1648
1673
  # return Constraint.Skip
1649
- # setattr(OptModel, f'eSecurityMargingTTCFrw_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.lca, rule=eSecurityMargingTTCFrw, doc='security margin TTC for flow based calculation [p.u.]'))
1674
+ # setattr(OptModel, f'eSecurityMargingTTCFrw_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.lca, rule=eSecurityMargingTTCFrw, doc='security margin TTC for flow based calculation [p.u.]'))
1650
1675
  #
1651
1676
  # if pIndLogConsole == 1:
1652
1677
  # print('eSecurityMargingTTCFrw... ', len(getattr(OptModel, f'eSecurityMargingTTCFrw_{p}_{sc}_{st}')), ' rows')
@@ -1656,7 +1681,7 @@ def NetworkOperationModelFormulation(OptModel, mTEPES, pIndLogConsole, p, sc, st
1656
1681
  # return OptModel.vFlowElec[p,sc,n,ni,nf,cc] >= - mTEPES.pVariableTTCBck[p,sc,n,ni,nf,cc]
1657
1682
  # else:
1658
1683
  # return Constraint.Skip
1659
- # setattr(OptModel, f'eSecurityMargingTTCBck_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.lca, rule=eSecurityMargingTTCBck, doc='security margin TTC for flow based calculation [p.u.]'))
1684
+ # setattr(OptModel, f'eSecurityMargingTTCBck_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.lca, rule=eSecurityMargingTTCBck, doc='security margin TTC for flow based calculation [p.u.]'))
1660
1685
  #
1661
1686
  # if pIndLogConsole == 1:
1662
1687
  # print('eSecurityMargingTTCBck... ', len(getattr(OptModel, f'eSecurityMargingTTCBck_{p}_{sc}_{st}')), ' rows')
@@ -1757,7 +1782,7 @@ def CycleConstraints(OptModel, mTEPES, pIndLogConsole, p, sc, st):
1757
1782
  sum(OptModel.vFlowElec[p,sc,n,ni,nf,cc] * mTEPES.pLineX[ni,nf,cc] / mTEPES.pSBase for nf,ni in list(zip(mTEPES.ncd[cyc], mTEPES.ncd[cyc][1:] + mTEPES.ncd[cyc][:1])) for cc in mTEPES.cc if (ni,nf,cc) in mTEPES.uctc) ) / mTEPES.pBigMTheta[cyc,nii,nff,cc] <= 1 - OptModel.vLineCommit[p,sc,n,nii,nff,cc]
1758
1783
  else:
1759
1784
  return Constraint.Skip
1760
- setattr(OptModel, f'eCycleKirchhoff2ndLawCnd1_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.lcac, rule=eCycleKirchhoff2ndLawCnd1, doc='cycle flow for with some AC candidate lines [rad]'))
1785
+ setattr(OptModel, f'eCycleKirchhoff2ndLawCnd1_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.lcac, rule=eCycleKirchhoff2ndLawCnd1, doc='cycle flow for with some AC candidate lines [rad]'))
1761
1786
 
1762
1787
  if pIndLogConsole == 1:
1763
1788
  print('eCycleKirchhoff2ndLC1 ... ', len(getattr(OptModel, f'eCycleKirchhoff2ndLawCnd1_{p}_{sc}_{st}')), ' rows')
@@ -1768,7 +1793,7 @@ def CycleConstraints(OptModel, mTEPES, pIndLogConsole, p, sc, st):
1768
1793
  sum(OptModel.vFlowElec[p,sc,n,ni,nf,cc] * mTEPES.pLineX[ni,nf,cc] / mTEPES.pSBase for nf,ni in list(zip(mTEPES.ncd[cyc], mTEPES.ncd[cyc][1:] + mTEPES.ncd[cyc][:1])) for cc in mTEPES.cc if (ni,nf,cc) in mTEPES.uctc) ) / mTEPES.pBigMTheta[cyc,nii,nff,cc] >= - 1 + OptModel.vLineCommit[p,sc,n,nii,nff,cc]
1769
1794
  else:
1770
1795
  return Constraint.Skip
1771
- setattr(OptModel, f'eCycleKirchhoff2ndLawCnd2_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.lcac, rule=eCycleKirchhoff2ndLawCnd2, doc='cycle flow for with some AC candidate lines [rad]'))
1796
+ setattr(OptModel, f'eCycleKirchhoff2ndLawCnd2_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.lcac, rule=eCycleKirchhoff2ndLawCnd2, doc='cycle flow for with some AC candidate lines [rad]'))
1772
1797
 
1773
1798
  if pIndLogConsole == 1:
1774
1799
  print('eCycleKirchhoff2ndLC2 ... ', len(getattr(OptModel, f'eCycleKirchhoff2ndLawCnd2_{p}_{sc}_{st}')), ' rows')
@@ -1778,7 +1803,7 @@ def CycleConstraints(OptModel, mTEPES, pIndLogConsole, p, sc, st):
1778
1803
  return (OptModel.vFlowElec[p,sc,n,ni,nf,cc] - OptModel.vFlowElec[p,sc,n,ni,nf,c2] * mTEPES.pLineX[ni,nf,c2] / mTEPES.pLineX[ni,nf,cc]) / max(mTEPES.pMaxNTCBck[p,sc,n,ni,nf,cc],mTEPES.pMaxNTCFrw[p,sc,n,ni,nf,cc]) <= 1 - OptModel.vLineCommit[p,sc,n,ni,nf,c2]
1779
1804
  else:
1780
1805
  return Constraint.Skip
1781
- setattr(OptModel, f'eFlowParallelCandidate1_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.pct, mTEPES.cc, mTEPES.c2, rule=eFlowParallelCandidate1, doc='unitary flow for each AC candidate parallel circuit [p.u.]'))
1806
+ setattr(OptModel, f'eFlowParallelCandidate1_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.pct, mTEPES.cc, mTEPES.c2, rule=eFlowParallelCandidate1, doc='unitary flow for each AC candidate parallel circuit [p.u.]'))
1782
1807
 
1783
1808
  if pIndLogConsole == 1:
1784
1809
  print('eFlowParallelCnddate1 ... ', len(getattr(OptModel, f'eFlowParallelCandidate1_{p}_{sc}_{st}')), ' rows')
@@ -1788,7 +1813,7 @@ def CycleConstraints(OptModel, mTEPES, pIndLogConsole, p, sc, st):
1788
1813
  return (OptModel.vFlowElec[p,sc,n,ni,nf,cc] - OptModel.vFlowElec[p,sc,n,ni,nf,c2] * mTEPES.pLineX[ni,nf,c2] / mTEPES.pLineX[ni,nf,cc]) / max(mTEPES.pMaxNTCBck[p,sc,n,ni,nf,cc],mTEPES.pMaxNTCFrw[p,sc,n,ni,nf,cc]) >= - 1 + OptModel.vLineCommit[p,sc,n,ni,nf,c2]
1789
1814
  else:
1790
1815
  return Constraint.Skip
1791
- setattr(OptModel, f'eFlowParallelCandidate2_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.pct, mTEPES.cc, mTEPES.c2, rule=eFlowParallelCandidate2, doc='unitary flow for each AC candidate parallel circuit [p.u.]'))
1816
+ setattr(OptModel, f'eFlowParallelCandidate2_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.pct, mTEPES.cc, mTEPES.c2, rule=eFlowParallelCandidate2, doc='unitary flow for each AC candidate parallel circuit [p.u.]'))
1792
1817
 
1793
1818
  if pIndLogConsole == 1:
1794
1819
  print('eFlowParallelCnddate2 ... ', len(getattr(OptModel, f'eFlowParallelCandidate2_{p}_{sc}_{st}')), ' rows')
@@ -1829,7 +1854,7 @@ def NetworkH2OperationModelFormulation(OptModel, mTEPES, pIndLogConsole, p, sc,
1829
1854
  sum(OptModel.vFlowH2[p,sc,n,nd,nf,cc] for nf,cc in lout[nd] if (p,nd,nf,cc) in mTEPES.ppa) + sum(OptModel.vFlowH2[p,sc,n,ni,nd,cc] for ni,cc in lin[nd] if (p,ni,nd,cc) in mTEPES.ppa)) == mTEPES.pDemandH2[p,sc,n,nd]*mTEPES.pDuration[p,sc,n]()
1830
1855
  else:
1831
1856
  return Constraint.Skip
1832
- setattr(OptModel, f'eBalanceH2_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.nd, rule=eBalanceH2, doc='H2 load generation balance [tH2]'))
1857
+ setattr(OptModel, f'eBalanceH2_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.nd, rule=eBalanceH2, doc='H2 load generation balance [tH2]'))
1833
1858
 
1834
1859
  if pIndLogConsole == 1:
1835
1860
  print('eBalanceH2 ... ', len(getattr(OptModel, f'eBalanceH2_{p}_{sc}_{st}')), ' rows')
@@ -1865,7 +1890,7 @@ def NetworkHeatOperationModelFormulation(OptModel, mTEPES, pIndLogConsole, p, sc
1865
1890
  return OptModel.vTotalOutputHeat[p,sc,n,chp] == OptModel.vESSTotalCharge[p,sc,n,chp] / mTEPES.pProductionFunctionHeat[chp]
1866
1891
  else:
1867
1892
  return Constraint.Skip
1868
- setattr(OptModel, f'eEnergy2Heat_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.chp, rule=eEnergy2Heat, doc='Energy to heat conversion [GW]'))
1893
+ setattr(OptModel, f'eEnergy2Heat_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.chp, rule=eEnergy2Heat, doc='Energy to heat conversion [GW]'))
1869
1894
 
1870
1895
  if pIndLogConsole == 1:
1871
1896
  print('eEnergy2Heat ... ', len(getattr(OptModel, f'eEnergy2Heat_{p}_{sc}_{st}')), ' rows')
@@ -1876,7 +1901,7 @@ def NetworkHeatOperationModelFormulation(OptModel, mTEPES, pIndLogConsole, p, sc
1876
1901
  sum(OptModel.vFlowHeat[p,sc,n,nd,nf,cc] for nf,cc in lout[nd] if (p,nd,nf,cc) in mTEPES.pha) + sum(OptModel.vFlowHeat[p,sc,n,ni,nd,cc] for ni,cc in lin[nd] if (p,ni,nd,cc) in mTEPES.pha)) == mTEPES.pDemandHeat[p,sc,n,nd]
1877
1902
  else:
1878
1903
  return Constraint.Skip
1879
- setattr(OptModel, f'eBalanceHeat_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.nd, rule=eBalanceHeat, doc='Heat load generation balance [GW]'))
1904
+ setattr(OptModel, f'eBalanceHeat_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.nd, rule=eBalanceHeat, doc='Heat load generation balance [GW]'))
1880
1905
 
1881
1906
  if pIndLogConsole == 1:
1882
1907
  print('eBalanceHeat ... ', len(getattr(OptModel, f'eBalanceHeat_{p}_{sc}_{st}')), ' rows')
@@ -1,5 +1,5 @@
1
1
  """
2
- Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - January 22, 2026
2
+ Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - January 25, 2026
3
3
  """
4
4
 
5
5
  import time
@@ -182,9 +182,18 @@ def _write_set_to_db(con, set_, name):
182
182
  name : str
183
183
  Base name used to build the table name `s_{name}`.
184
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)
185
+ from pyomo.common.sorting import sorted_robust
186
+
187
+ if set_.is_indexed():
188
+ rows = []
189
+ for idx in sorted_robust(set_.keys()):
190
+ for m in set_[idx].sorted_data():
191
+ rows.append((idx, m))
192
+ df = pd.DataFrame(rows, columns=["index", "member"])
193
+ else:
194
+ df = pd.DataFrame({"member": list(set_.sorted_data())})
195
+
196
+ _set_df(con, f"s_{name}", df)
188
197
 
189
198
 
190
199
  def _write_constraint_to_db(con, constraint, name, model):
@@ -427,9 +436,9 @@ def InvestmentResults(DirName, CaseName, OptModel, mTEPES, pIndTechnologyOutput,
427
436
 
428
437
  MarketResultsInv = pd.concat([MarketResultsInv, OutputResults], axis=1)
429
438
 
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)
439
+ 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
440
  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)
441
+ 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,sc,n,eb) in mTEPES.psneb) for p,gt in mTEPES.p*mTEPES.gt], index=mTEPES.p*mTEPES.gt)
433
442
  GenTechInjection.name = 'Generation'
434
443
  MarketResultsInv = pd.concat([MarketResultsInv, GenTechInjection], axis=1)
435
444
  LCOE = GenTechInvestCost.div(GenTechInjection)
@@ -1047,7 +1056,7 @@ def ReservoirOperationResults(DirName, CaseName, OptModel, mTEPES, pIndTechnolog
1047
1056
 
1048
1057
  #%% outputting the water volume values
1049
1058
  OutputResults = []
1050
- sPSSTNES = [(p,sc,st,n,rs) for p,sc,st,n,rs in mTEPES.ps*mTEPES.st*mTEPES.nrsc if (p,rs) in mTEPES.prs and (p,sc,st,n) in mTEPES.s2n and (p,sc,n) in mTEPES.psn]
1059
+ sPSSTNES = [(p,sc,st,n,rs) for p,sc,st,n,rs in mTEPES.s2n*mTEPES.rs if (p,sc,n,rs) in mTEPES.psnrs]
1051
1060
  OutputToFile = pd.Series(data=[abs(mTEPES.pDuals["".join([f"eHydroInventory_{p}_{sc}_{st}('{n}', '{rs}')"])])*1e3 for p,sc,st,n,rs in sPSSTNES], index=pd.Index(sPSSTNES))
1052
1061
  if len(OutputToFile):
1053
1062
  OutputToFile.to_frame(name='WaterValue').reset_index().pivot_table(index=['level_0','level_1','level_3'], columns='level_4', values='WaterValue').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_MarginalWaterValue_{CaseName}.csv', sep=',')
@@ -1545,7 +1554,7 @@ def OperationSummaryResults(DirName, CaseName, OptModel, mTEPES):
1545
1554
  NetInvCostVRESInsCap = 0.0
1546
1555
  # Rate of return for VRE technologies
1547
1556
  # warning division and multiplication
1548
- VRETechRevenue = sum(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 mTEPES.s2n*mTEPES.nd*mTEPES.gc if gc in g2n[nd] and gc in mTEPES.re and (p,gc) in mTEPES.pgc and (p,sc,n) in mTEPES.psn and sum(1 for g in g2n[nd]) + sum(1 for nf,cc in lout[nd]) + sum(1 for ni,cc in lin[nd]))
1557
+ VRETechRevenue = sum(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 mTEPES.s2n*mTEPES.nd*mTEPES.gc if gc in g2n[nd] and gc in mTEPES.re and (p,sc,n,gc) in mTEPES.psngc and sum(1 for g in g2n[nd]) + sum(1 for nf,cc in lout[nd]) + sum(1 for ni,cc in lin[nd]))
1549
1558
  VREInvCostCapacity = sum(mTEPES.pDiscountedWeight[p]*mTEPES.pGenInvestCost[gc]*OptModel.vGenerationInvest[p,gc]() for p,gc in mTEPES.pgc if gc in mTEPES.re)
1550
1559
 
1551
1560
  K1 = pd.Series(data={'Ratio Fossil Fuel Generation/Total Generation [%]' : FossilFuelGeneration / TotalGeneration *1e2}).to_frame(name='Value')
@@ -1869,7 +1878,7 @@ def MarginalResults(DirName, CaseName, OptModel, mTEPES, pIndPlotOutput):
1869
1878
  OutputToFile.rename_axis(['Period', 'Scenario', 'LoadLevel', 'Area'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_MarginalIncrementalVariableCost_{CaseName}.csv', sep=',')
1870
1879
  IncrementalGens = pd.Series('N/A', index=mTEPES.psnar).to_frame(name='Generator')
1871
1880
  for p,sc,n,ar in mTEPES.psnar:
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):
1881
+ 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):
1873
1882
  if len(OutputToFile.loc[(p,sc,n,ar)]) > 1:
1874
1883
  IncrementalGens.loc[p,sc,n,ar] = OutputToFile.loc[[(p,sc,n,ar)]].squeeze().idxmin()
1875
1884
  else:
@@ -1990,7 +1999,7 @@ def MarginalResults(DirName, CaseName, OptModel, mTEPES, pIndPlotOutput):
1990
1999
  #%% outputting the water values
1991
2000
  if mTEPES.es:
1992
2001
  OutputResults = []
1993
- sPSSTNES = [(p,sc,st,n,es) for p,sc,st,n,es in mTEPES.ps*mTEPES.st*mTEPES.nesc if (p,es) in mTEPES.pes and (p,sc,st,n) in mTEPES.s2n and (p,sc,n) in mTEPES.psn and (mTEPES.pTotalMaxCharge[es] or mTEPES.pTotalEnergyInflows[es])]
2002
+ sPSSTNES = [(p,sc,st,n,es) for p,sc,st,n,es in mTEPES.s2n*mTEPES.es if (p,sc,n,es) in mTEPES.psnes and (mTEPES.pTotalMaxCharge[es] or mTEPES.pTotalEnergyInflows[es])]
1994
2003
  OutputToFile = pd.Series(data=[abs(mTEPES.pDuals["".join([f"eESSInventory_{p}_{sc}_{st}('{n}', '{es}')"])])*1e3 for p,sc,st,n,es in sPSSTNES], index=pd.Index(sPSSTNES))
1995
2004
  if len(OutputToFile):
1996
2005
  OutputToFile.to_frame(name='WaterValue').reset_index().pivot_table(index=['level_0','level_1','level_3'], columns='level_4', values='WaterValue').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_MarginalEnergyValue_{CaseName}.csv', sep=',')
@@ -2291,29 +2300,29 @@ def EconomicResults(DirName, CaseName, OptModel, mTEPES, pIndAreaOutput, pIndPlo
2291
2300
  OutputToFile = pd.Series(data=[(mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelDuration[p,sc,n]() * mTEPES.pLinearVarCost [p,sc,n,nr] * OptModel.vTotalOutput[p,sc,n,nr]() +
2292
2301
  mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelDuration[p,sc,n]() * mTEPES.pConstantVarCost[p,sc,n,nr] * OptModel.vCommitment [p,sc,n,nr]() +
2293
2302
  mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelWeight [p,sc,n]() * mTEPES.pStartUpCost [ nr] * OptModel.vStartUp [p,sc,n,nr]() +
2294
- mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelWeight [p,sc,n]() * mTEPES.pShutDownCost [ nr] * OptModel.vShutDown [p,sc,n,nr]()) for p,sc,n,nr in mTEPES.psnnr if (p,nr) in mTEPES.pnr], index=mTEPES.psnnr)
2303
+ mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelWeight [p,sc,n]() * mTEPES.pShutDownCost [ nr] * OptModel.vShutDown [p,sc,n,nr]()) for p,sc,n,nr in mTEPES.psnnr], index=mTEPES.psnnr)
2295
2304
  if mTEPES.psnnr:
2296
2305
  OutputToFile.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MEUR', aggfunc='sum').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_GenerationCostOperation_{CaseName}.csv', sep=',')
2297
2306
 
2298
2307
  if mTEPES.re:
2299
- OutputToFile = pd.Series(data=[mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelDuration[p,sc,n]() * mTEPES.pLinearOMCost [re] * OptModel.vTotalOutput [p,sc,n,re]() for p,sc,n,re in mTEPES.psnre if (p,re) in mTEPES.pre], index=mTEPES.psnre)
2308
+ OutputToFile = pd.Series(data=[mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelDuration[p,sc,n]() * mTEPES.pLinearOMCost [re] * OptModel.vTotalOutput [p,sc,n,re]() for p,sc,n,re in mTEPES.psnre], index=mTEPES.psnre)
2300
2309
  OutputToFile.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MEUR', aggfunc='sum').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_GenerationCostOandM_{CaseName}.csv', sep=',')
2301
2310
 
2302
2311
  if mTEPES.nr:
2303
2312
  if sum(mTEPES.pOperReserveUp[:,:,:,:]) + sum(mTEPES.pOperReserveDw[:,:,:,:]):
2304
2313
  OutputToFile = pd.Series(data=[(mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelWeight[p,sc,n]() * mTEPES.pOperReserveCost[nr] * OptModel.vReserveUp [p,sc,n,nr]() +
2305
- mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelWeight[p,sc,n]() * mTEPES.pOperReserveCost[nr] * OptModel.vReserveDown[p,sc,n,nr]()) for p,sc,n,nr in mTEPES.psnnr if (p,nr) in mTEPES.pnr], index=mTEPES.psnnr)
2314
+ mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelWeight[p,sc,n]() * mTEPES.pOperReserveCost[nr] * OptModel.vReserveDown[p,sc,n,nr]()) for p,sc,n,nr in mTEPES.psnnr], index=mTEPES.psnnr)
2306
2315
  OutputToFile.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MEUR', aggfunc='sum').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_GenerationCostOperatingReserve_{CaseName}.csv', sep=',')
2307
2316
 
2308
2317
  if mTEPES.psnehc:
2309
- OutputToFile = pd.Series(data=[ mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelDuration[p,sc,n]() * mTEPES.pLinearVarCost[p,sc,n,eh] * OptModel.vESSTotalCharge[p,sc,n,eh]() for p,sc,n,eh in mTEPES.psnehc if (p,eh) in mTEPES.peh], index=mTEPES.psnehc)
2318
+ OutputToFile = pd.Series(data=[ mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelDuration[p,sc,n]() * mTEPES.pLinearVarCost[p,sc,n,eh] * OptModel.vESSTotalCharge[p,sc,n,eh]() for p,sc,n,eh in mTEPES.psnehc], index=mTEPES.psnehc)
2310
2319
  OutputToFile.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MEUR', aggfunc='sum').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_ConsumptionCostOperation_{CaseName}.csv', sep=',')
2311
2320
  if sum(mTEPES.pIndOperReserveGen[eh] for eh in mTEPES.eh if mTEPES.pIndOperReserveGen[eh] == 0) + sum(mTEPES.pIndOperReserveCon[eh] for eh in mTEPES.eh if mTEPES.pIndOperReserveCon[eh] == 0):
2312
2321
  OutputToFile = pd.Series(data=[(mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelWeight[p,sc,n]() * mTEPES.pOperReserveCost[eh] * OptModel.vESSReserveUp [p,sc,n,eh]() +
2313
- mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelWeight[p,sc,n]() * mTEPES.pOperReserveCost[eh] * OptModel.vESSReserveDown[p,sc,n,eh]()) for p,sc,n,eh in mTEPES.psnehc if (p,eh) in mTEPES.peh], index=mTEPES.psnehc)
2322
+ mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelWeight[p,sc,n]() * mTEPES.pOperReserveCost[eh] * OptModel.vESSReserveDown[p,sc,n,eh]()) for p,sc,n,eh in mTEPES.psnehc], index=mTEPES.psnehc)
2314
2323
  OutputToFile.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MEUR', aggfunc='sum').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_ConsumptionCostOperatingReserve_{CaseName}.csv', sep=',')
2315
2324
 
2316
- OutputToFile = pd.Series(data=[mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelDuration[p,sc,n]() * mTEPES.pEmissionVarCost[p,sc,n,g] * OptModel.vTotalOutput[p,sc,n,g]() for p,sc,n,g in mTEPES.psng if (p,g) in mTEPES.pg], index=mTEPES.psng)
2325
+ OutputToFile = pd.Series(data=[mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelDuration[p,sc,n]() * mTEPES.pEmissionVarCost[p,sc,n,g] * OptModel.vTotalOutput[p,sc,n,g]() for p,sc,n,g in mTEPES.psng], index=mTEPES.psng)
2317
2326
  OutputToFile.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MEUR', aggfunc='sum').rename_axis(['Period', 'Scenario', 'LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(f'{_path}/oT_Result_GenerationCostEmission_{CaseName}.csv', sep=',')
2318
2327
 
2319
2328
  OutputToFile = pd.Series(data=[mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelDuration[p,sc,n]() * mTEPES.pENSCost() * OptModel.vENS [p,sc,n,nd]() for p,sc,n,nd in mTEPES.psnnd], index=mTEPES.psnnd)
@@ -2338,35 +2347,35 @@ def EconomicResults(DirName, CaseName, OptModel, mTEPES, pIndAreaOutput, pIndPlo
2338
2347
  OutputResults7 = pd.DataFrame(data={'MEUR': [0.0]}, index=pd.Index([(p,sc,'Reliability Cost' ) for p,sc in mTEPES.ps]))
2339
2348
 
2340
2349
  if mTEPES.nr:
2341
- sPSNNR = [(p,sc,n,nr) for p,sc,n,nr in mTEPES.psnnr if nr in n2a[ar] and (p,nr) in mTEPES.pnr]
2350
+ sPSNNR = [(p,sc,n,nr) for p,sc,n,nr in mTEPES.psnnr if nr in n2a[ar]]
2342
2351
  if sPSNNR:
2343
2352
  OutputResults1 = pd.Series(data=[(mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelDuration[p,sc,n]() * mTEPES.pLinearVarCost [p,sc,n,nr] * OptModel.vTotalOutput[p,sc,n,nr]() +
2344
2353
  mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelDuration[p,sc,n]() * mTEPES.pConstantVarCost[p,sc,n,nr] * OptModel.vCommitment [p,sc,n,nr]() +
2345
2354
  mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelWeight [p,sc,n]() * mTEPES.pStartUpCost [ nr] * OptModel.vStartUp [p,sc,n,nr]() +
2346
2355
  mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelWeight [p,sc,n]() * mTEPES.pShutDownCost [ nr] * OptModel.vShutDown [p,sc,n,nr]()) for p,sc,n,nr in sPSNNR], index=pd.Index(sPSNNR))
2347
2356
  OutputResults1 = Transformation1(OutputResults1, 'Operation Cost Generation')
2348
- sPSNNR = [(p,sc,n,nr) for p,sc,n,nr in mTEPES.psnnr if nr in n2a[ar] and (p,nr) in mTEPES.pnr]
2357
+ sPSNNR = [(p,sc,n,nr) for p,sc,n,nr in mTEPES.psnnr if nr in n2a[ar]]
2349
2358
  if sum(mTEPES.pOperReserveUp[:,:,:,:]) + sum(mTEPES.pOperReserveDw[:,:,:,:]):
2350
2359
  OutputResults2 = pd.Series(data=[(mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelWeight [p,sc,n]() * mTEPES.pOperReserveCost[ nr] * OptModel.vReserveUp [p,sc,n,nr]() +
2351
2360
  mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelWeight [p,sc,n]() * mTEPES.pOperReserveCost[ nr] * OptModel.vReserveDown[p,sc,n,nr]()) for p,sc,n,nr in sPSNNR], index=pd.Index(sPSNNR))
2352
2361
  OutputResults2 = Transformation1(OutputResults2, 'Operating Reserve Cost Generation')
2353
2362
 
2354
2363
  if mTEPES.g :
2355
- sPSNG = [(p,sc,n,g ) for p,sc,n,g in mTEPES.psng if g in g2a[ar] and (p,g ) in mTEPES.pg ]
2364
+ sPSNG = [(p,sc,n,g ) for p,sc,n,g in mTEPES.psng if g in g2a[ar]]
2356
2365
  if sPSNG:
2357
2366
  if sum(mTEPES.pEmissionVarCost[:,:,:,:]):
2358
2367
  OutputResults6 = pd.Series(data=[ mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelDuration[p,sc,n]() * mTEPES.pEmissionVarCost[p,sc,n,g ] * OptModel.vTotalOutput[p,sc,n,g ]() for p,sc,n,g in sPSNG], index=pd.Index(sPSNG))
2359
2368
  OutputResults6 = Transformation1(OutputResults6, 'Emission Cost')
2360
2369
 
2361
2370
  if mTEPES.re:
2362
- sPSNRE = [(p,sc,n,re) for p,sc,n,re in mTEPES.psnre if re in g2a[ar] and (p,re) in mTEPES.pre]
2371
+ sPSNRE = [(p,sc,n,re) for p,sc,n,re in mTEPES.psnre if re in g2a[ar]]
2363
2372
  if sPSNRE:
2364
2373
  if sum(mTEPES.pLinearOMCost[:]):
2365
2374
  OutputResults3 = pd.Series(data=[mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelDuration[p,sc,n]() * mTEPES.pLinearOMCost [re] * OptModel.vTotalOutput [p,sc,n,re]() for p,sc,n,re in sPSNRE], index=pd.Index(sPSNRE))
2366
2375
  OutputResults3 = Transformation1(OutputResults3, 'O&M Cost Generation')
2367
2376
 
2368
2377
  if mTEPES.eh:
2369
- sPSNES = [(p,sc,n,eh) for p,sc,n,eh in mTEPES.psnehc if eh in g2a[ar] and (p,eh) in mTEPES.peh]
2378
+ sPSNES = [(p,sc,n,eh) for p,sc,n,eh in mTEPES.psnehc if eh in g2a[ar]]
2370
2379
  if sPSNES:
2371
2380
  if sum(mTEPES.pLinearVarCost [:,:,:,:]):
2372
2381
  OutputResults4 = pd.Series(data=[ mTEPES.pDiscountedWeight[p] * mTEPES.pScenProb[p,sc]() * mTEPES.pLoadLevelDuration[p,sc,n]() * mTEPES.pLinearVarCost [p,sc,n,eh] * OptModel.vESSTotalCharge[p,sc,n,eh]() for p,sc,n,eh in sPSNES], index=pd.Index(sPSNES))
@@ -2387,42 +2396,42 @@ def EconomicResults(DirName, CaseName, OptModel, mTEPES, pIndAreaOutput, pIndPlo
2387
2396
  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]()
2388
2397
  OutputResults.to_csv(f'{_path}/oT_Result_CostSummary_{CaseName}_{ar}.csv', sep=',', index=False)
2389
2398
 
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]
2399
+ sPSSTNG = [(p,sc,st,n, g) for p,sc,st,n, g in mTEPES.s2n*mTEPES.g if (p,sc,n,g) in mTEPES.psng]
2391
2400
  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()
2401
+ sPSSTNNDG = [(p,sc,st,n,nd,g) for p,sc,st,n,nd,g in sPSSTNND*mTEPES.g if (p,sc,n,g) in mTEPES.psng and (nd,g) in mTEPES.n2g]
2402
+ 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))
2403
+ MeanOutput = pd.Series(data=[ OptModel.vTotalOutput [p,sc,n,g]() for p,sc,st,n, g in sPSSTNG ], index=pd.Index(sPSSTNG )).groupby(level=4).mean()
2395
2404
  MeanOutput *= 1e-3
2396
2405
  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
2406
  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
2407
  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=',')
2399
2408
 
2400
2409
  if mTEPES.eh:
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()
2410
+ sPSSTNES = [(p,sc,st,n, eh) for p,sc,st,n, eh in mTEPES.s2n*mTEPES.eh if (p,sc,n,eh) in mTEPES.psneh]
2411
+ sPSSTNNDEH = [(p,sc,st,n,nd,eh) for p,sc,st,n,nd,eh in sPSSTNND*mTEPES.eh if (p,sc,n,eh) in mTEPES.psneh and (nd,eh) in mTEPES.n2g]
2412
+ 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], index=pd.Index(sPSSTNNDEH))
2413
+ MeanOutput = pd.Series(data=[ OptModel.vESSTotalCharge[p,sc,n,eh]() for p,sc,st,n, eh in sPSSTNES ], index=pd.Index(sPSSTNES )).groupby(level=4).mean()
2405
2414
  MeanOutput *= 1e-3
2406
2415
  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))
2416
+ 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], index=pd.Index(sPSSTNNDEH))
2408
2417
  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=',')
2409
2418
 
2410
2419
  if mTEPES.gc:
2411
2420
  GenRev = []
2412
2421
  ChargeRev = []
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]
2422
+ 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,sc,n,gc) in mTEPES.psngc]
2414
2423
  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))
2415
2424
  GenRev.append(OutputToGenRev)
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]]
2425
+ 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,gc) in mTEPES.psngc and gc in o2e[ot]]):
2426
+ 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,gc) in mTEPES.psngc and gc in o2e[ot]]
2418
2427
  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))
2419
2428
  ChargeRev.append(OutputChargeRevESS)
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]]
2429
+ 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,gc) in mTEPES.psngc and gc in r2r[rt]]):
2430
+ 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,gc) in mTEPES.psngc and gc in r2r[rt]]
2422
2431
  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))
2423
2432
  ChargeRev.append(OutputChargeRevRES)
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]]
2433
+ 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,gc) in mTEPES.psngc and gc in o2e[ot]]):
2434
+ 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,gc) in mTEPES.psngc and gc in o2e[ot]]
2426
2435
  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))
2427
2436
  ChargeRev.append(OutputChargeRevThr)
2428
2437
  if len(GenRev):
@@ -2456,18 +2465,18 @@ def EconomicResults(DirName, CaseName, OptModel, mTEPES, pIndAreaOutput, pIndPlo
2456
2465
  ResRev = pd.Series(data=[0.0 for gc in mTEPES.gc], index=mTEPES.gc, dtype='float64')
2457
2466
 
2458
2467
  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]
2468
+ 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]):
2469
+ 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]
2461
2470
  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))
2462
2471
  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=',')
2463
2472
 
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]
2473
+ 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]):
2474
+ 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]
2466
2475
  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))
2467
2476
  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=',')
2468
2477
 
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]
2478
+ 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]):
2479
+ 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]
2471
2480
  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')
2472
2481
  if len(OutputResults):
2473
2482
  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)
@@ -2483,18 +2492,18 @@ def EconomicResults(DirName, CaseName, OptModel, mTEPES, pIndAreaOutput, pIndPlo
2483
2492
  UpRev = pd.Series(data=[0.0 for gc in mTEPES.gc], index=mTEPES.gc, dtype='float64')
2484
2493
 
2485
2494
  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 )):
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]
2495
+ 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]):
2496
+ 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]
2488
2497
  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))
2489
2498
  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=',')
2490
2499
 
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]
2500
+ 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]):
2501
+ 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]
2493
2502
  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))
2494
2503
  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=',')
2495
2504
 
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]
2505
+ 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]):
2506
+ 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]
2498
2507
  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')
2499
2508
  if len(OutputResults):
2500
2509
  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)
@@ -2509,18 +2518,18 @@ def EconomicResults(DirName, CaseName, OptModel, mTEPES, pIndAreaOutput, pIndPlo
2509
2518
  DwRev = pd.Series(data=[0.0 for gc in mTEPES.gc], index=mTEPES.gc, dtype='float64')
2510
2519
 
2511
2520
  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]
2521
+ 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.psnnrr]):
2522
+ 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.psnnrr]
2514
2523
  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
2524
  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
2525
 
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]
2526
+ # 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]):
2527
+ # 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]
2519
2528
  # 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
2529
  # 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
2530
 
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]
2531
+ 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]):
2532
+ 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]
2524
2533
  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
2534
  if len(OutputResults):
2526
2535
  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)
@@ -2536,18 +2545,18 @@ def EconomicResults(DirName, CaseName, OptModel, mTEPES, pIndAreaOutput, pIndPlo
2536
2545
  RampUpRev = pd.Series(data=[0.0 for gc in mTEPES.gc], index=mTEPES.gc, dtype='float64')
2537
2546
 
2538
2547
  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]
2548
+ 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]):
2549
+ 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]
2541
2550
  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
2551
  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
2552
 
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]
2553
+ # 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]):
2554
+ # 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]
2546
2555
  # 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
2556
  # 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
2557
 
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]
2558
+ 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]):
2559
+ 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]
2551
2560
  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
2561
  if len(OutputResults):
2553
2562
  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)
@@ -31,7 +31,7 @@ def ProblemSolving(DirName, CaseName, SolverName, OptModel, mTEPES, pIndLogConso
31
31
  # Solver.options['Seed' ] = 104729
32
32
  # Solver.options['Presolve' ] = 2
33
33
  # Solver.options['RINS' ] = 100
34
- # Solver.options['BarConvTol' ] = 1e-9
34
+ # Solver.options['BarConvTol' ] = 1e-12
35
35
  # Solver.options['BarQCPConvTol' ] = 0.025
36
36
  # Solver.options['IISFile' ] = f'{_path}/openTEPES_gurobi_'+CaseName+'.ilp' # should be uncommented to show results of IIS
37
37
  Solver.options['MIPGap' ] = 0.01
@@ -57,7 +57,7 @@ def ProblemSolving(DirName, CaseName, SolverName, OptModel, mTEPES, pIndLogConso
57
57
  if os.path.exists(FileName):
58
58
  os.remove(FileName)
59
59
  Solver.options['log_file' ] = f'{_path}/openTEPES_highs_{CaseName}_{p}_{sc}_{st}.log'
60
- Solver.options['solver' ] = 'simplex'
60
+ Solver.options['solver' ] = 'hipo'
61
61
  Solver.options['simplex_strategy' ] = 3
62
62
  Solver.options['run_crossover' ] = 'on'
63
63
  Solver.options['mip_rel_gap' ] = 0.01
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openTEPES
3
- Version: 4.18.9
3
+ Version: 4.18.10
4
4
  Summary: Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES)
5
5
  Home-page: https://opentepes.readthedocs.io/en/latest/index.html
6
6
  Author: IIT-EnergySystemModels
@@ -1,11 +1,11 @@
1
- openTEPES/__init__.py,sha256=FozTs8PMPcaz1sPtbHKQYWkBTIQar2I6GWwQGq69oXI,832
1
+ openTEPES/__init__.py,sha256=5L-SpCSyWwUjHcXqOMDHVG25n03wCz2ymKwUn3V1wqI,833
2
2
  openTEPES/openTEPES.mapbox_token,sha256=xsXNkwGp2vzXqQy2zVkyLhhNcNWniK2BMeOFpc5SZHI,93
3
- openTEPES/openTEPES.py,sha256=CnikcchmCP49DjB81RuAtxz8TEK8MSKMhwV1nEeTbMI,27461
4
- openTEPES/openTEPES_InputData.py,sha256=ue_B_yaANq5k4w0vo9CPkESWpXfb5BZjF1xFqRpw3to,245619
5
- openTEPES/openTEPES_Main.py,sha256=glvDODa5hfmSLTXIKamQmt3rlkTFN6d2CMFNMXXuCs0,40782
6
- openTEPES/openTEPES_ModelFormulation.py,sha256=g9nRAbJpZ8r1_aIP-EH6t7mJhoWDB8uj8Q8zZjVnwjM,141751
7
- openTEPES/openTEPES_OutputResults.py,sha256=rIcdKqhVyzaizcZiPtN0uGcst1-SHuFF9gs1Fj-zJjM,242215
8
- openTEPES/openTEPES_ProblemSolving.py,sha256=gORJdW46pSzphOfjIT-vSJ2kgkAEuPWh0exqm7ozx0Q,16766
3
+ openTEPES/openTEPES.py,sha256=K8jUPdByW1wy59Bh0T0_oqZ29Ds8q6cPnCKqH0xTkFc,27463
4
+ openTEPES/openTEPES_InputData.py,sha256=GldpcWf_BUW493LI69vsf5xJ0Oo7VGZI59VaAT9m9KU,246011
5
+ openTEPES/openTEPES_Main.py,sha256=dddDRIF1BAP7414CjznKfcSCvkHXRJYNak1k8JEc65M,40783
6
+ openTEPES/openTEPES_ModelFormulation.py,sha256=Jci1IPJoJOW6psladRbvIJDjdaPSmSMDU_chcp-iCb4,144057
7
+ openTEPES/openTEPES_OutputResults.py,sha256=LDs43z20dA05jdgtqkIBeF2o1_z1n7XagFjybPqWL84,241177
8
+ openTEPES/openTEPES_ProblemSolving.py,sha256=_3CU1dO-VE6g6gWE8hosyfVed-B9UFiMUKt6uDiy4NI,16764
9
9
  openTEPES/openTEPES_gitinfo.py,sha256=6fA1fa-JcyusSc_HcjPiCgnV9zn-fZwdG-kK0a5Fxc8,2004
10
10
  openTEPES/.idea/.name,sha256=jiwfcnJ20wztcvpny4SHcqmAIWK-w5tCqN9TWf0GOkw,11
11
11
  openTEPES/.idea/misc.xml,sha256=m4-3O284ZBS8WZSQD0QWwk8YjuQYz92w6kr7NRFNips,298
@@ -384,8 +384,8 @@ openTEPES/sSEP/oT_Dict_Storage_sSEP.csv,sha256=H2rJXZvoMuT-25sI2GpG8IuiNKD-dxuty
384
384
  openTEPES/sSEP/oT_Dict_Technology_sSEP.csv,sha256=MCTpplzz7_eVPKQfOw35c86ib6CTtW6UK6JrbCJ8wls,170
385
385
  openTEPES/sSEP/oT_Dict_ZoneToArea_sSEP.csv,sha256=AUDCs5Bg6sw9f2pVjGP1o4IJjXFF_VrokOGf_V3QsEI,24
386
386
  openTEPES/sSEP/oT_Dict_Zone_sSEP.csv,sha256=TBud-fvbFbiAsuutxTYe8wWlv_x1P8oyWXILMpYiXJc,13
387
- opentepes-4.18.9.dist-info/entry_points.txt,sha256=gNNPrDaTsRuRJXI1FLNgqMX1CiJ45bEp1dEDH7ZB8Oc,49
388
- opentepes-4.18.9.dist-info/licenses/LICENSE,sha256=4O7bphXVzRuYavtsWzpLGuM3E-fp3HTRna7F4yIfnS4,35184
389
- opentepes-4.18.9.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
390
- opentepes-4.18.9.dist-info/METADATA,sha256=7bDfXPGg6f_5jya58I6bg6evEtMQx8TDoxr-OaSrbTs,19420
391
- opentepes-4.18.9.dist-info/RECORD,,
387
+ opentepes-4.18.10.dist-info/entry_points.txt,sha256=gNNPrDaTsRuRJXI1FLNgqMX1CiJ45bEp1dEDH7ZB8Oc,49
388
+ opentepes-4.18.10.dist-info/licenses/LICENSE,sha256=4O7bphXVzRuYavtsWzpLGuM3E-fp3HTRna7F4yIfnS4,35184
389
+ opentepes-4.18.10.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
390
+ opentepes-4.18.10.dist-info/METADATA,sha256=qCa3FslFhw6oMv4dTbR3oj-e2oI0l5Ha5F9NgDQrj6s,19421
391
+ opentepes-4.18.10.dist-info/RECORD,,