Skip to content

Commit c0ca5fa

Browse files
committed
increase tolerances from 1e-5 to 2e-5
1 parent 2f48cae commit c0ca5fa

7 files changed

Lines changed: 24 additions & 20 deletions

File tree

CHANGELOG.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
Change Log
22
=============
33

4+
[4.18.17RC] - 2026-04-11
5+
-------------------------
6+
- [CHANGED] change from 1e-5 to 2e-5 tolerances to avoid extreme values in the optimization problem and to improve the robustness of the model
7+
48
[4.18.16] - 2026-04-10
59
-------------------------
610
- [CHANGED] add H2 network utilization in output results

doc/rst/conf.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
author = 'Andres Ramos'
1313

1414
# The short X.Y version
15-
version = 'version 4.18.16'
15+
version = 'version 4.18.17RC'
1616
# The full version, including alpha/beta/rc tags
1717
release = ''
1818

@@ -84,13 +84,13 @@
8484
#
8585
# html_sidebars = {}
8686
html_theme = 'alabaster'
87-
html_title = 'version 4.18.16'
87+
html_title = 'version 4.18.17RC'
8888
html_logo = '../img/openTEPES.png'
8989
html_last_updated_fmt = ''
9090
html_show_sphinx = False
9191
html_theme_options = {
9292
'analytics_id': 'UA-515200-2', # Provided by Google in your dashboard
93-
'description': 'version 4.18.16',
93+
'description': 'version 4.18.17RC',
9494
'body_max_width' : 'none',
9595
'page_width': 'auto',
9696
'font_family': 'Georgia'

openTEPES/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
>>> import openTEPES as oT
1515
>>> oT.routine("9n", "C:\\Users\\UserName\\Documents\\GitHub\\openTEPES", "glpk")
1616
"""
17-
__version__ = "4.18.16"
17+
__version__ = "4.18.17RC"
1818

1919
from .openTEPES_Main import main
2020
from .openTEPES import *

openTEPES/openTEPES.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ def openTEPES_run(DirName, CaseName, SolverName, pIndOutputResults, pIndLogConso
3939
idxDict['y' ] = 1
4040

4141
#%% model declaration
42-
mTEPES = ConcreteModel('Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 4.18.16 - April 10, 2026')
43-
print( 'Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 4.18.16 - April 10, 2026', file=open(f'{_path}/openTEPES_version_{CaseName}.log','w'))
42+
mTEPES = ConcreteModel('Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 4.18.17RC - April 10, 2026')
43+
print( 'Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 4.18.17RC - April 10, 2026', file=open(f'{_path}/openTEPES_version_{CaseName}.log','w'))
4444

4545
pIndOutputResults = [j for i,j in idxDict.items() if i == pIndOutputResults][0]
4646
pIndLogConsole = [j for i,j in idxDict.items() if i == pIndLogConsole ][0]

openTEPES/openTEPES_InputData.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - March 17, 2026
2+
Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - April 11, 2026
33
"""
44

55
import time
@@ -931,7 +931,7 @@ def Create_ESS_RES_Sets(mTEPES) -> None:
931931

932932
# variable emission cost [M€/GWh]
933933
mTEPES.dPar['pVariableEmissionCost'] = mTEPES.dPar['pVariableEmissionCost'].replace(0.0, mTEPES.dPar['pCO2Cost']) #[€/tCO2]
934-
mTEPES.dPar['pEmissionVarCost'] = mTEPES.dPar['pEmissionRate'] * 1e-3 * mTEPES.dPar['pVariableEmissionCost'] #[M€/GWh] = [tCO2/MWh] * 1e-3 * [€/tCO2]
934+
mTEPES.dPar['pEmissionVarCost'] = mTEPES.dPar['pEmissionRate'] * 1e-3 * mTEPES.dPar['pVariableEmissionCost'] # [M€/GWh] = [tCO2/MWh] * 1e-3 * [€/tCO2]
935935
mTEPES.dPar['pEmissionVarCost'] = mTEPES.dPar['pEmissionVarCost'].reindex(sorted(mTEPES.dPar['pEmissionVarCost'].columns), axis=1)
936936

937937
# minimum up- and downtime and maximum shift time converted to an integer number of time steps
@@ -1122,9 +1122,9 @@ def Create_ESS_RES_Sets(mTEPES) -> None:
11221122
mTEPES.dPar['pDemandElecPeak'] = pd.Series([0.0 for p,ar in mTEPES.par], index=mTEPES.par)
11231123
mTEPES.dPar['pDemandHeatPeak'] = pd.Series([0.0 for p,ar in mTEPES.par], index=mTEPES.par)
11241124
for p,ar in mTEPES.par:
1125-
# values < 1e-5 times the maximum demand for each area (an area is related to operating reserves procurement, i.e., country) are converted to 0
1125+
# values < 2e-5 times the maximum demand for each area (an area is related to operating reserves procurement, i.e., country) are converted to 0
11261126
mTEPES.dPar['pDemandElecPeak'][p,ar] = mTEPES.dPar['pDemandElec'].loc[p,:,:][[nd for nd in d2a[ar]]].sum(axis=1).max()
1127-
mTEPES.dPar['pEpsilonElec'] = mTEPES.dPar['pDemandElecPeak'][p,ar]*1e-5
1127+
mTEPES.dPar['pEpsilonElec'] = mTEPES.dPar['pDemandElecPeak'][p,ar]*2e-5
11281128

11291129
# these parameters are in GW
11301130
mTEPES.dPar['pDemandElecPos'] [mTEPES.dPar['pDemandElecPos'] [[nd for nd in d2a[ar]]] < mTEPES.dPar['pEpsilonElec']] = 0.0
@@ -1186,7 +1186,7 @@ def Create_ESS_RES_Sets(mTEPES) -> None:
11861186

11871187
if mTEPES.dPar['pIndHeat']:
11881188
mTEPES.dPar['pDemandHeatPeak'][p,ar] = mTEPES.dPar['pDemandHeat'].loc[p,:,:][[nd for nd in d2a[ar]]].sum(axis=1).max()
1189-
mTEPES.dPar['pEpsilonHeat'] = mTEPES.dPar['pDemandHeatPeak'][p,ar]*1e-5
1189+
mTEPES.dPar['pEpsilonHeat'] = mTEPES.dPar['pDemandHeatPeak'][p,ar]*2e-5
11901190
mTEPES.dPar['pDemandHeat'] [mTEPES.dPar['pDemandHeat'] [[nd for nd in d2a[ar]]] < mTEPES.dPar['pEpsilonHeat']] = 0.0
11911191
mTEPES.dPar['pHeatPipeNTCFrw'][mTEPES.dPar['pHeatPipeNTCFrw'] < mTEPES.dPar['pEpsilonElec']] = 0
11921192
mTEPES.dPar['pHeatPipeNTCBck'][mTEPES.dPar['pHeatPipeNTCBck'] < mTEPES.dPar['pEpsilonElec']] = 0
@@ -1211,7 +1211,7 @@ def Create_ESS_RES_Sets(mTEPES) -> None:
12111211
mTEPES.dPar['pEmissionVarCost'] = mTEPES.dPar['pEmissionVarCost'].loc [:,mTEPES.g ]
12121212

12131213
# replace < 0.0 by 0.0
1214-
mTEPES.dPar['pEpsilon'] = 1e-6
1214+
mTEPES.dPar['pEpsilon'] = 1e-6 # measure of how close two values are
12151215
mTEPES.dPar['pMaxPower2ndBlock'] = mTEPES.dPar['pMaxPower2ndBlock'].where (mTEPES.dPar['pMaxPower2ndBlock'] > mTEPES.dPar['pEpsilon'], 0.0)
12161216
mTEPES.dPar['pMaxCharge2ndBlock'] = mTEPES.dPar['pMaxCharge2ndBlock'].where(mTEPES.dPar['pMaxCharge2ndBlock'] > mTEPES.dPar['pEpsilon'], 0.0)
12171217

@@ -1316,7 +1316,7 @@ def Create_ESS_RES_Sets(mTEPES) -> None:
13161316
mTEPES.dPar['pHeatPipeUpInvest'] = mTEPES.dPar['pHeatPipeUpInvest'].loc [mTEPES.hc]
13171317

13181318
# replace very small costs by 0
1319-
mTEPES.dPar['pEpsilon'] = 1e-5 # this value in EUR/GWh is lower than the O&M variable cost of any technology, independent of the area
1319+
mTEPES.dPar['pEpsilon'] = 2e-5 # this value in EUR/GWh is lower than the O&M variable cost of any technology, independent of the area
13201320

13211321
mTEPES.dPar['pLinearVarCost'] [mTEPES.dPar['pLinearVarCost'] [[g for g in mTEPES.g]] < mTEPES.dPar['pEpsilon']] = 0.0
13221322
mTEPES.dPar['pConstantVarCost'][mTEPES.dPar['pConstantVarCost'][[g for g in mTEPES.g]] < mTEPES.dPar['pEpsilon']] = 0.0

openTEPES/openTEPES_Main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,7 @@
660660
# For more information on this, and how to apply and follow the GNU AGPL, see
661661
# <https://www.gnu.org/licenses/>.
662662

663-
# Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - April 10, 2026
663+
# Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - April 11, 2026
664664
# simplicity and transparency in power systems planning
665665

666666
# Developed by
@@ -693,7 +693,7 @@
693693
BLUE = "\033[34m"
694694
RESET = "\033[0m"
695695

696-
print(GREEN + 'Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 4.18.16 - April 10, 2026' + RESET)
696+
print(GREEN + 'Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 4.18.17RC - April 11, 2026' + RESET)
697697
print(BLUE + '#### Academic research license - for non-commercial use only ####' + RESET + '\n')
698698

699699
parser = argparse.ArgumentParser(description='Introducing main parameters...')

openTEPES/openTEPES_ModelFormulation.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - April 05, 2026
2+
Open Generation, Storage, and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - April 11, 2026
33
"""
44

55
import time
@@ -169,8 +169,8 @@ def eTotalGCost(OptModel,n):
169169
mTEPES.pLoadLevelDuration[p,sc,n]() * sum(mTEPES.pLinearOMCost [ re] * OptModel.vTotalOutput [p,sc,n,re] for re in mTEPES.re if (p,re) in mTEPES.pre) )
170170
setattr(OptModel, f'eTotalGCost_{p}_{sc}_{st}', Constraint(mTEPES.n, rule=eTotalGCost, doc='system variable generation operation cost [MEUR]'))
171171

172-
# the small tolerance pEpsilon=1e-5 is added to avoid pumping/charging with curtailment/spillage
173-
pEpsilon = 1e-5
172+
# the small tolerance pEpsilon=2e-5 is added to avoid pumping/charging with curtailment/spillage
173+
pEpsilon = 2e-5
174174
def eTotalCCost(OptModel,n):
175175
return OptModel.vTotalCCost [p,sc,n] == mTEPES.pLoadLevelDuration[p,sc,n]() * sum((mTEPES.pLinearVarCost[p,sc,n,eh]+pEpsilon) * OptModel.vESSTotalCharge[p,sc,n,eh] for eh in mTEPES.eh if (p,eh) in mTEPES.peh and eh not in mTEPES.el)
176176
setattr(OptModel, f'eTotalCCost_{p}_{sc}_{st}', Constraint(mTEPES.n, rule=eTotalCCost, doc='system variable consumption operation cost [MEUR]'))
@@ -184,8 +184,8 @@ def eTotalECost(OptModel,n):
184184
def eTotalEmissionArea(OptModel,n,ar):
185185
if mTEPES.pEmission[p,ar] == math.inf or sum(mTEPES.pEmissionRate[g] for g in mTEPES.g if g in g2a[ar] and (p,g) in mTEPES.pg) == 0.0:
186186
return Constraint.Skip
187-
return OptModel.vTotalEmissionArea[p,sc,n,ar] == (mTEPES.pLoadLevelDuration[p,sc,n]() * 1e-3 * (sum(mTEPES.pEmissionRate[nr] * OptModel.vTotalOutput [p,sc,n,nr] for nr in mTEPES.nr if nr in g2a[ar] and (p,nr) in mTEPES.pnr) #1e-3 to change from tCO2/MWh to MtCO2/GWh
188-
+ sum(mTEPES.pEmissionRate[bo] * OptModel.vTotalOutputHeat[p,sc,n,bo] for bo in mTEPES.bo if bo in g2a[ar] and (p,bo) in mTEPES.pbo))) #1e-3 to change from tCO2/MWh to MtCO2/GWh
187+
return OptModel.vTotalEmissionArea[p,sc,n,ar] == (mTEPES.pLoadLevelDuration[p,sc,n]() * 1e-3 * (sum(mTEPES.pEmissionRate[nr] * OptModel.vTotalOutput [p,sc,n,nr] for nr in mTEPES.nr if nr in g2a[ar] and (p,nr) in mTEPES.pnr) # 1e-3 to change from tCO2/MWh to MtCO2/GWh
188+
+ sum(mTEPES.pEmissionRate[bo] * OptModel.vTotalOutputHeat[p,sc,n,bo] for bo in mTEPES.bo if bo in g2a[ar] and (p,bo) in mTEPES.pbo))) # 1e-3 to change from tCO2/MWh to MtCO2/GWh
189189
setattr(OptModel, f'eTotalEmissionArea_{p}_{sc}_{st}', Constraint(mTEPES.n*mTEPES.ar, rule=eTotalEmissionArea, doc='area total emission [MtCO2 eq]'))
190190

191191
def eTotalECostArea(OptModel,n,ar):

0 commit comments

Comments
 (0)