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,2 +1,2 @@
|
|
|
1
1
|
ENSCost,HNSCost,HTNSCost,CO2Cost,UpReserveActivation,DwReserveActivation,MinRatioDwUp,MaxRatioDwUp,SBase,ReferenceNode,TimeStep,EconomicBaseYear,AnnualDiscountRate
|
|
2
|
-
10000,10000,10000,25,0.25,0.3,0,1,100,Node_4,
|
|
2
|
+
10000,10000,10000,25,0.25,0.3,0,1,100,Node_4,2,2020,0
|
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.
|
|
17
|
+
__version__ = "4.18.11"
|
|
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
|
|
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 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.
|
|
42
|
-
print( 'Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 4.18.
|
|
41
|
+
mTEPES = ConcreteModel('Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 4.18.11 - January 28, 2026')
|
|
42
|
+
print( 'Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 4.18.11 - January 28, 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]
|
openTEPES/openTEPES_InputData.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - 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
|
|
@@ -515,7 +515,7 @@ def DataConfiguration(mTEPES):
|
|
|
515
515
|
|
|
516
516
|
StartTime = time.time()
|
|
517
517
|
#%% Getting the branches from the electric network data
|
|
518
|
-
sBr = [(ni,nf) for
|
|
518
|
+
sBr = [(ni,nf) for ni,nf,cc in mTEPES.dFrame['dfNetwork'].index]
|
|
519
519
|
# Dropping duplicate keys
|
|
520
520
|
sBrList = [(ni,nf) for n,(ni,nf) in enumerate(sBr) if (ni,nf) not in sBr[:n]]
|
|
521
521
|
|
|
@@ -527,7 +527,7 @@ def DataConfiguration(mTEPES):
|
|
|
527
527
|
mTEPES.n = Set(doc='load levels' , initialize=[nn for nn in mTEPES.nn if sum(mTEPES.dPar['pDuration'] [p,sc,nn] for p,sc in mTEPES.ps) > 0])
|
|
528
528
|
mTEPES.n2 = Set(doc='load levels' , initialize=[nn for nn in mTEPES.nn if sum(mTEPES.dPar['pDuration'] [p,sc,nn] for p,sc in mTEPES.ps) > 0])
|
|
529
529
|
mTEPES.g = Set(doc='generating units' , initialize=[gg for gg in mTEPES.gg if (mTEPES.dPar['pRatedMaxPowerElec'] [gg] > 0.0 or mTEPES.dPar['pRatedMaxCharge'][gg] > 0.0 or mTEPES.dPar['pRatedMaxPowerHeat'] [gg] > 0.0) and mTEPES.dPar['pElecGenPeriodIni'][gg] <= mTEPES.p.last() and mTEPES.dPar['pElecGenPeriodFin'][gg] >= mTEPES.p.first() and mTEPES.dPar['pGenToNode'].reset_index().set_index(['Generator']).isin(mTEPES.nd)['Node'][gg]]) # excludes generators with empty node
|
|
530
|
-
mTEPES.
|
|
530
|
+
mTEPES.tr = Set(doc='thermal units' , initialize=[g for g in mTEPES.g if mTEPES.dPar['pRatedLinearOperCost'][g ] > 0.0])
|
|
531
531
|
mTEPES.re = Set(doc='RES units' , initialize=[g for g in mTEPES.g if mTEPES.dPar['pRatedLinearOperCost'][g ] == 0.0 and mTEPES.dPar['pRatedMaxStorage'][g] == 0.0 and mTEPES.dPar['pProductionFunctionH2'][g ] == 0.0 and mTEPES.dPar['pProductionFunctionHeat'][g ] == 0.0 and mTEPES.dPar['pProductionFunctionHydro'][g ] == 0.0])
|
|
532
532
|
mTEPES.es = Set(doc='ESS units' , initialize=[g for g in mTEPES.g if (mTEPES.dPar['pRatedMaxCharge'][g ] > 0.0 or mTEPES.dPar['pRatedMaxStorage'][g] > 0.0 or mTEPES.dPar['pProductionFunctionH2'][g ] > 0.0 or mTEPES.dPar['pProductionFunctionHeat'][g ] > 0.0) and mTEPES.dPar['pProductionFunctionHydro'][g ] == 0.0])
|
|
533
533
|
mTEPES.h = Set(doc='hydro units' , initialize=[g for g in mTEPES.g if mTEPES.dPar['pProductionFunctionH2'][g ] == 0.0 and mTEPES.dPar['pProductionFunctionHeat'][g ] == 0.0 and mTEPES.dPar['pProductionFunctionHydro'][g ] > 0.0])
|
|
@@ -613,7 +613,7 @@ def DataConfiguration(mTEPES):
|
|
|
613
613
|
#%% inverse index load level to stage
|
|
614
614
|
mTEPES.dPar['pStageToLevel'] = mTEPES.dPar['pLevelToStage'].reset_index().set_index(['Period','Scenario','Stage'])['LoadLevel']
|
|
615
615
|
#Filter only valid indices
|
|
616
|
-
mTEPES.dPar['pStageToLevel'] = mTEPES.dPar['pStageToLevel'].loc[mTEPES.dPar['pStageToLevel'].index.isin([(p,s,st) for
|
|
616
|
+
mTEPES.dPar['pStageToLevel'] = mTEPES.dPar['pStageToLevel'].loc[mTEPES.dPar['pStageToLevel'].index.isin([(p,s,st) for p,s in mTEPES.ps for st in mTEPES.st]) & mTEPES.dPar['pStageToLevel'].isin(mTEPES.n)]
|
|
617
617
|
#Reorder the elements
|
|
618
618
|
mTEPES.dPar['pStageToLevel'] = [(p,sc,st,n) for (p,sc,st),n in mTEPES.dPar['pStageToLevel'].items()]
|
|
619
619
|
mTEPES.s2n = Set(initialize=mTEPES.dPar['pStageToLevel'], doc='Load level to stage')
|
|
@@ -642,6 +642,7 @@ def DataConfiguration(mTEPES):
|
|
|
642
642
|
None: Sets are added directly to the mTEPES object.
|
|
643
643
|
'''
|
|
644
644
|
mTEPES.pg = Set(initialize = [(p, g ) for p, g in mTEPES.p *mTEPES.g if mTEPES.dPar['pElecGenPeriodIni'][g ] <= p and mTEPES.dPar['pElecGenPeriodFin'][g ] >= p])
|
|
645
|
+
mTEPES.ptr = Set(initialize = [(p, tr ) for p, tr in mTEPES.p *mTEPES.tr if (p,tr) in mTEPES.pg])
|
|
645
646
|
mTEPES.pgc = Set(initialize = [(p, gc ) for p, gc in mTEPES.p *mTEPES.gc if (p,gc) in mTEPES.pg])
|
|
646
647
|
mTEPES.pnr = Set(initialize = [(p, nr ) for p, nr in mTEPES.p *mTEPES.nr if (p,nr) in mTEPES.pg])
|
|
647
648
|
mTEPES.pch = Set(initialize = [(p, ch ) for p, ch in mTEPES.p *mTEPES.ch if (p,ch) in mTEPES.pg])
|
|
@@ -669,6 +670,7 @@ def DataConfiguration(mTEPES):
|
|
|
669
670
|
mTEPES.pseh = Set(initialize = [(p,sc, eh) for p,sc, eh in mTEPES.ps *mTEPES.eh if (p,eh) in mTEPES.peh ])
|
|
670
671
|
mTEPES.psn = Set(initialize = [(p,sc,n ) for p,sc,n in mTEPES.ps *mTEPES.n if mTEPES.dPar['pDuration'][p,sc,n]])
|
|
671
672
|
mTEPES.psng = Set(initialize = [(p,sc,n,g ) for p,sc,n,g in mTEPES.psn*mTEPES.g if (p,g ) in mTEPES.pg ])
|
|
673
|
+
mTEPES.psntr = Set(initialize = [(p,sc,n,tr) for p,sc,n,tr in mTEPES.psn*mTEPES.tr if (p,tr) in mTEPES.ptr ])
|
|
672
674
|
mTEPES.psngc = Set(initialize = [(p,sc,n,gc) for p,sc,n,gc in mTEPES.psn*mTEPES.gc if (p,gc) in mTEPES.pgc ])
|
|
673
675
|
mTEPES.psngb = Set(initialize = [(p,sc,n,gb) for p,sc,n,gb in mTEPES.psn*mTEPES.gb if (p,gb) in mTEPES.pgc ])
|
|
674
676
|
mTEPES.psnre = Set(initialize = [(p,sc,n,re) for p,sc,n,re in mTEPES.psn*mTEPES.re if (p,re) in mTEPES.pre ])
|
|
@@ -677,6 +679,7 @@ def DataConfiguration(mTEPES):
|
|
|
677
679
|
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
680
|
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
681
|
mTEPES.psnhp = Set(initialize = [(p,sc,n,hp) for p,sc,n,hp in mTEPES.psn*mTEPES.hp if (p,hp) in mTEPES.php ])
|
|
682
|
+
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
683
|
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
684
|
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
685
|
mTEPES.psnec = Set(initialize = [(p,sc,n,ec) for p,sc,n,ec in mTEPES.psn*mTEPES.ec if (p,ec) in mTEPES.pec ])
|
|
@@ -722,7 +725,8 @@ def DataConfiguration(mTEPES):
|
|
|
722
725
|
mTEPES.psnland = Set(initialize = [(p,sc,n,ni,nf,cc,nd) for p,sc,n,ni,nf,cc,nd in mTEPES.psnla*mTEPES.nd if (ni,nf,cc,nd) in mTEPES.dPar['pVariablePTDF'].columns])
|
|
723
726
|
|
|
724
727
|
# assigning a node to an area
|
|
725
|
-
mTEPES.ndar = Set(initialize = [(nd,ar) for
|
|
728
|
+
mTEPES.ndar = Set(initialize = [(nd,ar) for nd,zn,ar in mTEPES.ndzn*mTEPES.ar if (zn,ar) in mTEPES.znar])
|
|
729
|
+
mTEPES.arnd = Set(initialize = [(ar,nd) for nd, ar in mTEPES.ndar])
|
|
726
730
|
|
|
727
731
|
# assigning a line to an area. Both nodes are in the same area. Cross-area lines are not included
|
|
728
732
|
mTEPES.laar = Set(initialize = [(ni,nf,cc,ar) for ni,nf,cc,ar in mTEPES.la*mTEPES.ar if (ni,ar) in mTEPES.ndar and (nf,ar) in mTEPES.ndar])
|
|
@@ -819,9 +823,9 @@ def DataConfiguration(mTEPES):
|
|
|
819
823
|
|
|
820
824
|
mTEPES.n2g = Set(initialize=mTEPES.dPar['pNodeToGen'].index, doc='node to generator')
|
|
821
825
|
|
|
822
|
-
mTEPES.z2g = Set(doc='zone to generator', initialize=[(zn,g) for
|
|
823
|
-
mTEPES.a2g = Set(doc='area to generator', initialize=[(ar,g) for
|
|
824
|
-
mTEPES.r2g = Set(doc='region to generator', initialize=[(rg,g) for
|
|
826
|
+
mTEPES.z2g = Set(doc='zone to generator', initialize=[(zn,g) for nd,g,zn in mTEPES.n2g*mTEPES.zn if (nd,zn) in mTEPES.ndzn ])
|
|
827
|
+
mTEPES.a2g = Set(doc='area to generator', initialize=[(ar,g) for nd,g,zn,ar in mTEPES.n2g*mTEPES.znar if (nd,zn) in mTEPES.ndzn ])
|
|
828
|
+
mTEPES.r2g = Set(doc='region to generator', initialize=[(rg,g) for nd,g,zn,ar,rg in mTEPES.n2g*mTEPES.znar*mTEPES.rg if (nd,zn) in mTEPES.ndzn and [ar,rg] in mTEPES.arrg])
|
|
825
829
|
|
|
826
830
|
# mTEPES.z2g = Set(initialize = [(zn,g) for zn,g in mTEPES.zn*mTEPES.g if (zn,g) in pZone2Gen])
|
|
827
831
|
|
|
@@ -2082,7 +2086,6 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
2082
2086
|
'''
|
|
2083
2087
|
nFixedVariables = 0
|
|
2084
2088
|
|
|
2085
|
-
# fix the must-run existing units and their output
|
|
2086
2089
|
# must-run units must produce at least their minimum output
|
|
2087
2090
|
[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
2091
|
|
|
@@ -2119,8 +2122,12 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
2119
2122
|
OptModel.vReserveUp [p,sc,n,nr].fix(0.0)
|
|
2120
2123
|
OptModel.vReserveDown [p,sc,n,nr].fix(0.0)
|
|
2121
2124
|
nFixedVariables += 3
|
|
2125
|
+
# fix the must-run existing units and their output
|
|
2126
|
+
if mTEPES.pMustRun[nr] == 1 and mTEPES.pMaxPower2ndBlock[p,sc,n,nr] == 0.0 and nr not in mTEPES.gc:
|
|
2127
|
+
OptModel.vTotalOutput[p,sc,n,nr].fix(mTEPES.pMinPowerElec[p,sc,n,nr])
|
|
2128
|
+
nFixedVariables += 1
|
|
2122
2129
|
if mTEPES.pIndRampReserves == 1:
|
|
2123
|
-
if mTEPES.pMaxPower2ndBlock[p,
|
|
2130
|
+
if mTEPES.pMaxPower2ndBlock[p,sc,n,nr] == 0.0 or mTEPES.pRampUp[nr] == 0.0:
|
|
2124
2131
|
OptModel.vRampReserveUp[p,sc,n,nr].fix(0.0)
|
|
2125
2132
|
OptModel.vRampReserveDw[p,sc,n,nr].fix(0.0)
|
|
2126
2133
|
nFixedVariables += 2
|
|
@@ -2197,7 +2204,7 @@ def SettingUpVariables(OptModel, mTEPES):
|
|
|
2197
2204
|
# activate only period, scenario, and load levels to formulate
|
|
2198
2205
|
mTEPES.del_component(mTEPES.st)
|
|
2199
2206
|
mTEPES.del_component(mTEPES.n )
|
|
2200
|
-
mTEPES.st = Set(doc='stages', initialize=[stt for stt in mTEPES.stt if st == stt and mTEPES.pStageWeight[stt] and sum(1 for
|
|
2207
|
+
mTEPES.st = Set(doc='stages', initialize=[stt for stt in mTEPES.stt if st == stt and mTEPES.pStageWeight[stt] and sum(1 for p,sc,st,nn in mTEPES.s2n)])
|
|
2201
2208
|
mTEPES.n = Set(doc='load levels', initialize=[nn for nn in mTEPES.nn if (p,sc,st,nn) in mTEPES.s2n ])
|
|
2202
2209
|
|
|
2203
2210
|
if mTEPES.n:
|
openTEPES/openTEPES_Main.py
CHANGED
|
@@ -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
|
|
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.
|
|
696
|
+
print(GREEN + 'Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 4.18.11 - January 28, 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...')
|