openTEPES 4.18.9__py3-none-any.whl → 4.18.11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openTEPES/9n/oT_Data_Parameter_9n.csv +1 -1
- openTEPES/__init__.py +1 -1
- openTEPES/openTEPES.py +3 -3
- openTEPES/openTEPES_InputData.py +18 -11
- openTEPES/openTEPES_Main.py +2 -2
- openTEPES/openTEPES_ModelFormulation.py +123 -98
- openTEPES/openTEPES_OutputResults.py +118 -105
- {opentepes-4.18.9.dist-info → opentepes-4.18.11.dist-info}/METADATA +1 -1
- {opentepes-4.18.9.dist-info → opentepes-4.18.11.dist-info}/RECORD +12 -12
- {opentepes-4.18.9.dist-info → opentepes-4.18.11.dist-info}/WHEEL +0 -0
- {opentepes-4.18.9.dist-info → opentepes-4.18.11.dist-info}/entry_points.txt +0 -0
- {opentepes-4.18.9.dist-info → opentepes-4.18.11.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - January
|
|
2
|
+
Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - January 28, 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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
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
|
-
|
|
1075
|
-
if mTEPES.
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
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
|
|
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
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
if
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
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
|
|
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
|
|
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
|
|
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')
|
|
@@ -1155,11 +1183,11 @@ def GenerationOperationModelFormulationCommitment(OptModel, mTEPES, pIndLogConso
|
|
|
1155
1183
|
if nr not in mTEPES.GeneratorsInYearlyGroup[group]:
|
|
1156
1184
|
return Constraint.Skip
|
|
1157
1185
|
# Skip if there are one or fewer generators in the group
|
|
1158
|
-
if len(mTEPES.GeneratorsInYearlyGroup[group] & {nr for
|
|
1186
|
+
if len(mTEPES.GeneratorsInYearlyGroup[group] & {nr for p,nr in mTEPES.pnr}) <= 1:
|
|
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
|
|
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')
|
|
@@ -1175,18 +1203,17 @@ def GenerationOperationModelFormulationCommitment(OptModel, mTEPES, pIndLogConso
|
|
|
1175
1203
|
if mTEPES.pMaxPowerElec[p,sc,n,nr] == 0.0:
|
|
1176
1204
|
return Constraint.Skip
|
|
1177
1205
|
# Skip if there are one or less generators in the group
|
|
1178
|
-
if len(mTEPES.GeneratorsInYearlyGroup[group] & {nr for
|
|
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
|
|
1189
|
-
if len(mTEPES.GeneratorsInYearlyGroup[group] & {nr for
|
|
1215
|
+
# Skip if there are one or fewer generators in the group
|
|
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
|
|
1192
1219
|
setattr(OptModel, f'eExclusiveGensYearly_{p}_{sc}_{st}', Constraint(mTEPES.ExclusiveGroupsYearly, rule=eExclusiveGensYearly, doc='mutually exclusive generators'))
|
|
@@ -1206,11 +1233,10 @@ def GenerationOperationModelFormulationCommitment(OptModel, mTEPES, pIndLogConso
|
|
|
1206
1233
|
if nr not in mTEPES.GeneratorsInHourlyGroup[group]:
|
|
1207
1234
|
return Constraint.Skip
|
|
1208
1235
|
# Skip if there are one or fewer generators in the group
|
|
1209
|
-
if len(mTEPES.GeneratorsInHourlyGroup[group] & {nr for
|
|
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')
|
|
@@ -1226,11 +1252,11 @@ def GenerationOperationModelFormulationCommitment(OptModel, mTEPES, pIndLogConso
|
|
|
1226
1252
|
if mTEPES.pMaxPowerElec[p,sc,n,nr] == 0.0:
|
|
1227
1253
|
return Constraint.Skip
|
|
1228
1254
|
# Skip if there are one or less generators in the group
|
|
1229
|
-
if len(mTEPES.GeneratorsInHourlyGroup[group] & {nr for
|
|
1255
|
+
if len(mTEPES.GeneratorsInHourlyGroup[group] & {nr for p,nr in mTEPES.pnr}) <= 1:
|
|
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
|
|
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')
|
|
@@ -1238,11 +1264,10 @@ def GenerationOperationModelFormulationCommitment(OptModel, mTEPES, pIndLogConso
|
|
|
1238
1264
|
def eExclusiveGensHourly(OptModel,n,group):
|
|
1239
1265
|
# Skip if there are one or fewer generators in the group
|
|
1240
1266
|
# This is written in a different way to the rest of the code to avoid variable shadowing due to comprehension
|
|
1241
|
-
if len(mTEPES.GeneratorsInHourlyGroup[group] & {gen for
|
|
1267
|
+
if len(mTEPES.GeneratorsInHourlyGroup[group] & {gen for period,gen in mTEPES.pnr if period == p}) <= 1:
|
|
1242
1268
|
return Constraint.Skip
|
|
1243
|
-
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,
|
|
1244
|
-
|
|
1245
|
-
setattr(OptModel, f'eExclusiveGensHourly_{p}_{sc}_{st}', Constraint(mTEPES.n, mTEPES.ExclusiveGroupsHourly, rule=eExclusiveGensHourly, doc='mutually exclusive generators'))
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
1448
|
+
setattr(OptModel, f'eMinUpTime_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.tr, 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
|
|
1461
|
+
setattr(OptModel, f'eMinDownTime_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.tr, 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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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')
|