Skip to content

Commit

Permalink
if there are system emission constraints no stage run can be done
Browse files Browse the repository at this point in the history
  • Loading branch information
arght committed Oct 20, 2023
1 parent 530a052 commit 1bbc678
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 27 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
Change Log
=============

[4.14.5] - 2023-10-20
----------------------
- [FIXED] if there are system emission constraints no stage run can be done

[4.14.4] - 2023-10-15
----------------------
- [FIXED] check that the duration of all the stages is equal
Expand Down
6 changes: 3 additions & 3 deletions doc/rst/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
author = 'Andres Ramos'

# The short X.Y version
version = 'version 4.14.4'
version = 'version 4.14.5'
# The full version, including alpha/beta/rc tags
release = ''

Expand Down Expand Up @@ -84,13 +84,13 @@
#
# html_sidebars = {}
html_theme = 'alabaster'
html_title = 'version 4.14.4'
html_title = 'version 4.14.5'
html_logo = '../img/openTEPES.png'
html_last_updated_fmt = ''
html_show_sphinx = False
html_theme_options = {
'analytics_id': 'UA-515200-2', # Provided by Google in your dashboard
'description': 'version 4.14.4',
'description': 'version 4.14.5',
'page_width': 'auto',
'font_family': 'Georgia'
}
Expand Down
2 changes: 1 addition & 1 deletion openTEPES/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
>>> import openTEPES as oT
>>> oT.routine("9n", "C:\\Users\\UserName\\Documents\\GitHub\\openTEPES", "glpk")
"""
__version__ = "4.14.4"
__version__ = "4.14.5"

from .openTEPES_Main import main
from .openTEPES import *
Expand Down
13 changes: 7 additions & 6 deletions openTEPES/openTEPES.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"""
Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - October 15, 2023
Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - October 20, 2023
"""

import time
import math
import os
import setuptools
import time

import pyomo.environ as pyo
from pyomo.environ import ConcreteModel, Set, Param, Reals
Expand Down Expand Up @@ -37,8 +38,8 @@ def openTEPES_run(DirName, CaseName, SolverName, pIndOutputResults, pIndLogConso
idxDict['y' ] = 1

#%% model declaration
mTEPES = ConcreteModel('Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 4.14.4 - October 15, 2023')
print( 'Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 4.14.4 - October 15, 2023', file=open(_path+'/openTEPES_version_'+CaseName+'.log','a'))
mTEPES = ConcreteModel('Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 4.14.5 - October 20, 2023')
print( 'Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 4.14.5 - October 20, 2023', file=open(_path+'/openTEPES_version_'+CaseName+'.log','a'))

pIndOutputResults = [j for i,j in idxDict.items() if i == pIndOutputResults][0]
pIndLogConsole = [j for i,j in idxDict.items() if i == pIndLogConsole ][0]
Expand Down Expand Up @@ -82,7 +83,7 @@ def openTEPES_run(DirName, CaseName, SolverName, pIndOutputResults, pIndLogConso
NetworkSwitchingModelFormulation (mTEPES, mTEPES, pIndLogConsole, p, sc, st)
NetworkOperationModelFormulation (mTEPES, mTEPES, pIndLogConsole, p, sc, st)

if (len(mTEPES.gc) == 0 or (len(mTEPES.gc) > 0 and mTEPES.pIndBinGenInvest() == 2)) and (len(mTEPES.gd) == 0 or (len(mTEPES.gd) > 0 and mTEPES.pIndBinGenRetire() == 2)) and (len(mTEPES.lc) == 0 or (len(mTEPES.lc) > 0 and mTEPES.pIndBinNetInvest() == 2)):
if (len(mTEPES.gc) == 0 or (len(mTEPES.gc) > 0 and mTEPES.pIndBinGenInvest() == 2)) and (len(mTEPES.gd) == 0 or (len(mTEPES.gd) > 0 and mTEPES.pIndBinGenRetire() == 2)) and (len(mTEPES.lc) == 0 or (len(mTEPES.lc) > 0 and mTEPES.pIndBinNetInvest() == 2)) and (min([mTEPES.pEmission[p,ar] for ar in mTEPES.ar]) == math.inf or sum(mTEPES.pEmissionRate[nr] for nr in mTEPES.nr) == 0):
mTEPES.pPeriodProb[p,sc] = mTEPES.pPeriodWeight[p] = mTEPES.pScenProb[p,sc] = 1.0

if pIndLogConsole == 1:
Expand All @@ -100,7 +101,7 @@ def openTEPES_run(DirName, CaseName, SolverName, pIndOutputResults, pIndLogConso
if c.name.find(str(p)) != -1 and c.name.find(str(sc)) != -1:
c.deactivate()
else:
if mTEPES.p.ord(p)*mTEPES.sc.ord(sc) == len(mTEPES.sc):
if mTEPES.p.ord(p)*mTEPES.sc.ord(sc) == len(mTEPES.ps) and mTEPES.st.last() == mTEPES.stt.last():

if pIndLogConsole == 1:
StartTime = time.time()
Expand Down
10 changes: 5 additions & 5 deletions openTEPES/openTEPES_ModelFormulation.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - October 09, 2023
Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - October 18, 2023
"""

import time
Expand Down Expand Up @@ -140,14 +140,14 @@ def eTotalECost(OptModel,n):

def eTotalECostArea(OptModel,n,ar):
if (st,n) in mTEPES.s2n and sum(mTEPES.pEmissionCost[nr] for nr in mTEPES.nr if (ar,nr) in mTEPES.a2g):
return OptModel.vTotalECostArea[p,sc,n,ar] == sum(mTEPES.pLoadLevelDuration[n] * mTEPES.pEmissionCost[nr] * OptModel.vTotalOutput [p,sc,n,nr] for nr in mTEPES.nr if (ar,nr) in mTEPES.a2g)
return OptModel.vTotalECostArea[p,sc,n,ar] == sum(mTEPES.pLoadLevelDuration[n] * mTEPES.pEmissionCost[nr] * OptModel.vTotalOutput[p,sc,n,nr] for nr in mTEPES.nr if (ar,nr) in mTEPES.a2g)
else:
return Constraint.Skip
setattr(OptModel, 'eTotalECostArea_'+str(p)+'_'+str(sc)+'_'+str(st), Constraint(mTEPES.n, mTEPES.ar, rule=eTotalECostArea, doc='area emission cost [MEUR]'))

def eTotalRCost(OptModel,n):
if (st,n) in mTEPES.s2n:
return OptModel.vTotalRCost[p,sc,n] == sum(mTEPES.pLoadLevelDuration[n] * mTEPES.pENSCost * OptModel.vENS [p,sc,n,nd] for nd in mTEPES.nd) + sum(mTEPES.pHNSCost * OptModel.vHNS[p,sc,n,nd] for nd in mTEPES.nd if sum(1 for el in e2n[nd]) + sum(1 for lout in lout[nd]) + sum(1 for ni,cc in lin[nd]))
return OptModel.vTotalRCost[p,sc,n] == sum(mTEPES.pLoadLevelDuration[n] * mTEPES.pENSCost * OptModel.vENS[p,sc,n,nd] for nd in mTEPES.nd) + sum(mTEPES.pHNSCost * OptModel.vHNS[p,sc,n,nd] for nd in mTEPES.nd if sum(1 for el in e2n[nd]) + sum(1 for lout in lout[nd]) + sum(1 for ni,cc in lin[nd]))
else:
return Constraint.Skip
setattr(OptModel, 'eTotalRCost_'+str(p)+'_'+str(sc)+'_'+str(st), Constraint(mTEPES.n, rule=eTotalRCost, doc='system reliability cost [MEUR]'))
Expand Down Expand Up @@ -235,8 +235,8 @@ def eAdequacyReserveMargin(OptModel,p,ar):
print('eAdequacyReserveMargin... ', len(getattr(OptModel, 'eAdequacyReserveMargin_'+str(p)+'_'+str(sc)+'_'+str(st))), ' rows')

def eMaxSystemEmission(OptModel,p,ar):
if mTEPES.pEmission[p,ar] < math.inf and sum(mTEPES.pEmissionRate[nr] for nr in mTEPES.nr if (ar,nr) in mTEPES.a2g):
return sum(OptModel.vTotalECostArea[p,sc,n,ar]/mTEPES.pCO2Cost for n in mTEPES.n) <= mTEPES.pEmission[p,ar]
if mTEPES.pEmission[p,ar] < math.inf and sum(mTEPES.pEmissionCost[nr] for nr in mTEPES.nr if (ar,nr) in mTEPES.a2g):
return sum(OptModel.vTotalECostArea[p,sc,n,ar]/mTEPES.pCO2Cost for n in mTEPES.nn if (st,n) in mTEPES.s2n) <= mTEPES.pEmission[p,ar]
else:
return Constraint.Skip
setattr(OptModel, 'eMaxSystemEmission_'+str(p)+'_'+str(sc)+'_'+str(st), Constraint(mTEPES.p, mTEPES.ar, rule=eMaxSystemEmission, doc='maximum CO2 emission [tCO2]'))
Expand Down
24 changes: 12 additions & 12 deletions openTEPES/openTEPES_OutputResults.py
Original file line number Diff line number Diff line change
Expand Up @@ -1353,20 +1353,20 @@ def CostSummaryResults(DirName, CaseName, OptModel, mTEPES):
_path = os.path.join(DirName, CaseName)
StartTime = time.time()

SysCost = pd.Series(data=[ OptModel.vTotalSCost() ], index=[' '] ).to_frame(name='Total System Cost').stack()
GenInvCost = pd.Series(data=[mTEPES.pDiscountFactor[p] * sum(mTEPES.pGenInvestCost[gc ] * OptModel.vGenerationInvest[p,gc ]() for gc in mTEPES.gc ) for p in mTEPES.p], index=mTEPES.p).to_frame(name='Generation Investment Cost').stack()
GenRetCost = pd.Series(data=[mTEPES.pDiscountFactor[p] * sum(mTEPES.pGenRetireCost[gd ] * OptModel.vGenerationRetire[p,gd ]() for gd in mTEPES.gd ) for p in mTEPES.p], index=mTEPES.p).to_frame(name='Generation Retirement Cost').stack()
SysCost = pd.Series(data=[ OptModel.vTotalSCost() ], index=[' '] ).to_frame(name='Total System Cost').stack()
GenInvCost = pd.Series(data=[mTEPES.pDiscountFactor[p] * sum(mTEPES.pGenInvestCost[gc ] * OptModel.vGenerationInvest[p,gc ]() for gc in mTEPES.gc ) for p in mTEPES.p], index=mTEPES.p).to_frame(name='Generation Investment Cost').stack()
GenRetCost = pd.Series(data=[mTEPES.pDiscountFactor[p] * sum(mTEPES.pGenRetireCost[gd ] * OptModel.vGenerationRetire[p,gd ]() for gd in mTEPES.gd ) for p in mTEPES.p], index=mTEPES.p).to_frame(name='Generation Retirement Cost').stack()
if mTEPES.pIndHydroTopology == 1:
RsrInvCost = pd.Series(data=[mTEPES.pDiscountFactor[p] * sum(mTEPES.pRsrInvestCost[rc ] * OptModel.vReservoirInvest [p,rc ]() for rc in mTEPES.rn ) for p in mTEPES.p], index=mTEPES.p).to_frame(name='Reservoir Investment Cost').stack()
RsrInvCost = pd.Series(data=[mTEPES.pDiscountFactor[p] * sum(mTEPES.pRsrInvestCost[rc ] * OptModel.vReservoirInvest [p,rc ]() for rc in mTEPES.rn ) for p in mTEPES.p], index=mTEPES.p).to_frame(name='Reservoir Investment Cost').stack()
else:
RsrInvCost = pd.Series(data=[0.0 ], index=mTEPES.p).to_frame(name='Reservoir Investment Cost').stack()
NetInvCost = pd.Series(data=[mTEPES.pDiscountFactor[p] * sum(mTEPES.pNetFixedCost [lc ] * OptModel.vNetworkInvest [p,lc ]() for lc in mTEPES.lc ) for p in mTEPES.p], index=mTEPES.p).to_frame(name='Network Investment Cost').stack()
GenCost = pd.Series(data=[mTEPES.pDiscountFactor[p] * sum(mTEPES.pScenProb [p,sc]() * OptModel.vTotalGCost [p,sc,n]() for sc,n in mTEPES.sc*mTEPES.n if mTEPES.pScenProb[p,sc]()) for p in mTEPES.p], index=mTEPES.p).to_frame(name='Generation Operation Cost').stack()
ConCost = pd.Series(data=[mTEPES.pDiscountFactor[p] * sum(mTEPES.pScenProb [p,sc]() * OptModel.vTotalCCost [p,sc,n]() for sc,n in mTEPES.sc*mTEPES.n if mTEPES.pScenProb[p,sc]()) for p in mTEPES.p], index=mTEPES.p).to_frame(name='Consumption Operation Cost').stack()
EmiCost = pd.Series(data=[mTEPES.pDiscountFactor[p] * sum(mTEPES.pScenProb [p,sc]() * OptModel.vTotalECost [p,sc,n]() for sc,n in mTEPES.sc*mTEPES.n if mTEPES.pScenProb[p,sc]()) for p in mTEPES.p], index=mTEPES.p).to_frame(name='Emission Cost').stack()
RelCost = pd.Series(data=[mTEPES.pDiscountFactor[p] * sum(mTEPES.pScenProb [p,sc]() * OptModel.vTotalRCost [p,sc,n]() for sc,n in mTEPES.sc*mTEPES.n if mTEPES.pScenProb[p,sc]()) for p in mTEPES.p], index=mTEPES.p).to_frame(name='Reliability Cost').stack()
# DemPayment = pd.Series(data=[mTEPES.pDiscountFactor[p] * sum(mTEPES.pScenProb [p,sc]() * mTEPES.pLoadLevelDuration[n]() * mTEPES.pDemand[p,sc,n,nd] * OptModel.LSRMC [p,sc,n,nd] for sc,n,nd in mTEPES.sc*mTEPES.n*mTEPES.nd if mTEPES.pScenProb[p,sc]())/1e3 for p in mTEPES.p], index=mTEPES.p).to_frame(name='Demand Payment' ).stack()
CostSummary = pd.concat([SysCost, GenInvCost, GenRetCost, RsrInvCost, NetInvCost, GenCost, ConCost, EmiCost, RelCost]).reset_index().rename(columns={'level_0': 'Period', 'level_1': 'Costs', 0: 'MEUR'}).to_csv(_path+'/oT_Result_CostSummary_'+CaseName+'.csv', sep=',', index=False)
RsrInvCost = pd.Series(data=[0.0 ], index=mTEPES.p).to_frame(name='Reservoir Investment Cost').stack()
NetInvCost = pd.Series(data=[mTEPES.pDiscountFactor[p] * sum(mTEPES.pNetFixedCost [lc ] * OptModel.vNetworkInvest [p,lc ]() for lc in mTEPES.lc ) for p in mTEPES.p], index=mTEPES.p).to_frame(name='Network Investment Cost').stack()
GenCost = pd.Series(data=[mTEPES.pDiscountFactor[p] * sum(mTEPES.pScenProb [p,sc]() * OptModel.vTotalGCost [p,sc,n]() for sc,n in mTEPES.sc*mTEPES.n if mTEPES.pScenProb[p,sc]()) for p in mTEPES.p], index=mTEPES.p).to_frame(name='Generation Operation Cost').stack()
ConCost = pd.Series(data=[mTEPES.pDiscountFactor[p] * sum(mTEPES.pScenProb [p,sc]() * OptModel.vTotalCCost [p,sc,n]() for sc,n in mTEPES.sc*mTEPES.n if mTEPES.pScenProb[p,sc]()) for p in mTEPES.p], index=mTEPES.p).to_frame(name='Consumption Operation Cost').stack()
EmiCost = pd.Series(data=[mTEPES.pDiscountFactor[p] * sum(mTEPES.pScenProb [p,sc]() * OptModel.vTotalECost [p,sc,n]() for sc,n in mTEPES.sc*mTEPES.n if mTEPES.pScenProb[p,sc]()) for p in mTEPES.p], index=mTEPES.p).to_frame(name='Emission Cost').stack()
RelCost = pd.Series(data=[mTEPES.pDiscountFactor[p] * sum(mTEPES.pScenProb [p,sc]() * OptModel.vTotalRCost [p,sc,n]() for sc,n in mTEPES.sc*mTEPES.n if mTEPES.pScenProb[p,sc]()) for p in mTEPES.p], index=mTEPES.p).to_frame(name='Reliability Cost').stack()
# DemPayment = pd.Series(data=[mTEPES.pDiscountFactor[p] * sum(mTEPES.pScenProb [p,sc]() * mTEPES.pLoadLevelDuration[n]() * mTEPES.pDemand[p,sc,n,nd] * OptModel.LSRMC [p,sc,n,nd] for sc,n,nd in mTEPES.sc*mTEPES.n*mTEPES.nd if mTEPES.pScenProb[p,sc]())/1e3 for p in mTEPES.p], index=mTEPES.p).to_frame(name='Demand Payment' ).stack()
CostSummary = pd.concat([SysCost, GenInvCost, GenRetCost, RsrInvCost, NetInvCost, GenCost, ConCost, EmiCost, RelCost]).reset_index().rename(columns={'level_0': 'Period', 'level_1': 'Costs', 0: 'MEUR'}).to_csv(_path+'/oT_Result_CostSummary_'+CaseName+'.csv', sep=',', index=False)

WritingResultsTime = time.time() - StartTime
print('Writing cost summary results ... ', round(WritingResultsTime), 's')
Expand Down

0 comments on commit 1bbc678

Please sign in to comment.