From 12f3938bc203e360cdab6c2ea754af7a2f724c28 Mon Sep 17 00:00:00 2001 From: timmy61109 <38396747+timmy61109@users.noreply.github.com> Date: Sun, 8 Aug 2021 17:48:56 +0800 Subject: [PATCH 1/4] Use autopep8 quick lint --- openTEPES/__init__.py | 10 +- openTEPES/openTEPES.py | 133 +- openTEPES/openTEPES_InputData.py | 2750 +++++++++++++++----- openTEPES/openTEPES_Main.py | 20 +- openTEPES/openTEPES_ModelFormulation.py | 1758 ++++++++++--- openTEPES/openTEPES_OutputResults.py | 3035 ++++++++++++++++++++--- openTEPES/openTEPES_ProblemSolving.py | 151 +- 7 files changed, 6462 insertions(+), 1395 deletions(-) diff --git a/openTEPES/__init__.py b/openTEPES/__init__.py index 5a210a3d..e3170d35 100644 --- a/openTEPES/__init__.py +++ b/openTEPES/__init__.py @@ -16,9 +16,9 @@ """ __version__ = "3.1.2" -from .openTEPES_Main import main -from .openTEPES import * -from .openTEPES_InputData import * +from .openTEPES_Main import main +from .openTEPES import * +from .openTEPES_InputData import * from .openTEPES_ModelFormulation import * -from .openTEPES_OutputResults import * -from .openTEPES_ProblemSolving import * +from .openTEPES_OutputResults import * +from .openTEPES_ProblemSolving import * diff --git a/openTEPES/openTEPES.py b/openTEPES/openTEPES.py index 30599081..4b95144a 100644 --- a/openTEPES/openTEPES.py +++ b/openTEPES/openTEPES.py @@ -8,10 +8,10 @@ from pyomo.environ import ConcreteModel, Set -from .openTEPES_InputData import InputData, SettingUpVariables +from .openTEPES_InputData import InputData, SettingUpVariables from .openTEPES_ModelFormulation import InvestmentModelFormulation, GenerationOperationModelFormulation, NetworkSwitchingModelFormulation, NetworkOperationModelFormulation -from .openTEPES_ProblemSolving import ProblemSolving -from .openTEPES_OutputResults import InvestmentResults, GenerationOperationResults, ESSOperationResults, FlexibilityResults, NetworkOperationResults, MarginalResults, EconomicResults, NetworkMapResults +from .openTEPES_ProblemSolving import ProblemSolving +from .openTEPES_OutputResults import InvestmentResults, GenerationOperationResults, ESSOperationResults, FlexibilityResults, NetworkOperationResults, MarginalResults, EconomicResults, NetworkMapResults def openTEPES_run(DirName, CaseName, SolverName): @@ -19,8 +19,9 @@ def openTEPES_run(DirName, CaseName, SolverName): InitialTime = time.time() _path = os.path.join(DirName, CaseName) - #%% model declaration - mTEPES = ConcreteModel('Open Generation and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 3.1.2 - July 12, 2021') + # %% model declaration + mTEPES = ConcreteModel( + 'Open Generation and Transmission Operation and Expansion Planning Model with RES and ESS (openTEPES) - Version 3.1.2 - July 12, 2021') pIndLogConsole = 1 @@ -34,49 +35,113 @@ def openTEPES_run(DirName, CaseName, SolverName): InvestmentModelFormulation(mTEPES, mTEPES, pIndLogConsole) # iterative model formulation for each stage of a year - for sc,p,st in mTEPES.scc*mTEPES.pp*mTEPES.stt: + for sc, p, st in mTEPES.scc * mTEPES.pp * mTEPES.stt: # activate only scenario, period and load levels to formulate mTEPES.del_component(mTEPES.sc) - mTEPES.del_component(mTEPES.p ) + mTEPES.del_component(mTEPES.p) mTEPES.del_component(mTEPES.st) - mTEPES.del_component(mTEPES.n ) + mTEPES.del_component(mTEPES.n) mTEPES.del_component(mTEPES.n2) - mTEPES.sc = Set(initialize=mTEPES.scc, ordered=True, doc='scenarios', filter=lambda mTEPES,scc: scc in mTEPES.scc and sc == scc and mTEPES.pScenProb [scc]) - mTEPES.p = Set(initialize=mTEPES.pp, ordered=True, doc='periods', filter=lambda mTEPES,pp : pp in p == pp ) - mTEPES.st = Set(initialize=mTEPES.stt, ordered=True, doc='stages', filter=lambda mTEPES,stt: stt in mTEPES.stt and st == stt and mTEPES.pStageWeight[stt] and sum(1 for (st, nn) in mTEPES.s2n)) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn : nn in mTEPES.pDuration and (st,nn) in mTEPES.s2n) - mTEPES.n2 = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn : nn in mTEPES.pDuration and (st,nn) in mTEPES.s2n) + mTEPES.sc = Set( + initialize=mTEPES.scc, + ordered=True, + doc='scenarios', + filter=lambda mTEPES, + scc: scc in mTEPES.scc and sc == scc and mTEPES.pScenProb[scc]) + mTEPES.p = Set( + initialize=mTEPES.pp, + ordered=True, + doc='periods', + filter=lambda mTEPES, + pp: pp in p == pp) + mTEPES.st = Set( + initialize=mTEPES.stt, + ordered=True, + doc='stages', + filter=lambda mTEPES, + stt: stt in mTEPES.stt and st == stt and mTEPES.pStageWeight[stt] and sum( + 1 for ( + st, + nn) in mTEPES.s2n)) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration and ( + st, + nn) in mTEPES.s2n) + mTEPES.n2 = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration and ( + st, + nn) in mTEPES.s2n) # operation model objective function and constraints by stage GenerationOperationModelFormulation(mTEPES, mTEPES, pIndLogConsole, st) - NetworkSwitchingModelFormulation (mTEPES, mTEPES, pIndLogConsole, st) - NetworkOperationModelFormulation (mTEPES, mTEPES, pIndLogConsole, st) - - StartTime = time.time() - mTEPES.write(_path+'/openTEPES_'+CaseName+'.lp', io_options={'symbolic_solver_labels': True}) # create lp-format file + NetworkSwitchingModelFormulation(mTEPES, mTEPES, pIndLogConsole, st) + NetworkOperationModelFormulation(mTEPES, mTEPES, pIndLogConsole, st) + + StartTime = time.time() + mTEPES.write( + _path + + '/openTEPES_' + + CaseName + + '.lp', + io_options={ + 'symbolic_solver_labels': True}) # create lp-format file WritingLPFileTime = time.time() - StartTime - StartTime = time.time() - print('Writing LP file ... ', round(WritingLPFileTime), 's') + StartTime = time.time() + print( + 'Writing LP file ... ', + round(WritingLPFileTime), + 's') ProblemSolving(DirName, CaseName, SolverName, mTEPES, mTEPES) mTEPES.del_component(mTEPES.sc) - mTEPES.del_component(mTEPES.p ) + mTEPES.del_component(mTEPES.p) mTEPES.del_component(mTEPES.st) - mTEPES.del_component(mTEPES.n ) - mTEPES.sc = Set(initialize=mTEPES.scc, ordered=True, doc='scenarios', filter=lambda mTEPES,scc: scc in mTEPES.scc and mTEPES.pScenProb [scc]) - mTEPES.p = Set(initialize=mTEPES.pp, ordered=True, doc='periods', filter=lambda mTEPES,pp : pp in p == pp ) - mTEPES.st = Set(initialize=mTEPES.stt, ordered=True, doc='stages', filter=lambda mTEPES,stt: stt in mTEPES.stt and mTEPES.pStageWeight[stt] and sum(1 for (stt, nn) in mTEPES.s2n)) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn : nn in mTEPES.pDuration ) - - InvestmentResults (DirName, CaseName, mTEPES, mTEPES) + mTEPES.del_component(mTEPES.n) + mTEPES.sc = Set( + initialize=mTEPES.scc, + ordered=True, + doc='scenarios', + filter=lambda mTEPES, + scc: scc in mTEPES.scc and mTEPES.pScenProb[scc]) + mTEPES.p = Set( + initialize=mTEPES.pp, + ordered=True, + doc='periods', + filter=lambda mTEPES, + pp: pp in p == pp) + mTEPES.st = Set( + initialize=mTEPES.stt, + ordered=True, + doc='stages', + filter=lambda mTEPES, + stt: stt in mTEPES.stt and mTEPES.pStageWeight[stt] and sum( + 1 for ( + stt, + nn) in mTEPES.s2n)) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration) + + InvestmentResults(DirName, CaseName, mTEPES, mTEPES) GenerationOperationResults(DirName, CaseName, mTEPES, mTEPES) - ESSOperationResults (DirName, CaseName, mTEPES, mTEPES) - FlexibilityResults (DirName, CaseName, mTEPES, mTEPES) - NetworkOperationResults (DirName, CaseName, mTEPES, mTEPES) - MarginalResults (DirName, CaseName, mTEPES, mTEPES) - EconomicResults (DirName, CaseName, mTEPES, mTEPES) - NetworkMapResults (DirName, CaseName, mTEPES, mTEPES) + ESSOperationResults(DirName, CaseName, mTEPES, mTEPES) + FlexibilityResults(DirName, CaseName, mTEPES, mTEPES) + NetworkOperationResults(DirName, CaseName, mTEPES, mTEPES) + MarginalResults(DirName, CaseName, mTEPES, mTEPES) + EconomicResults(DirName, CaseName, mTEPES, mTEPES) + NetworkMapResults(DirName, CaseName, mTEPES, mTEPES) TotalTime = time.time() - InitialTime print('Total time ... ', round(TotalTime), 's') diff --git a/openTEPES/openTEPES_InputData.py b/openTEPES/openTEPES_InputData.py index 04c84be2..94c3cd88 100644 --- a/openTEPES/openTEPES_InputData.py +++ b/openTEPES/openTEPES_InputData.py @@ -5,8 +5,8 @@ import time import math import os -import pandas as pd -from pyomo.environ import DataPortal, Set, Param, Var, Binary, NonNegativeReals, Reals, UnitInterval, Boolean, Any +import pandas as pd +from pyomo.environ import DataPortal, Set, Param, Var, Binary, NonNegativeReals, Reals, UnitInterval, Boolean, Any def InputData(DirName, CaseName, mTEPES): @@ -15,277 +15,763 @@ def InputData(DirName, CaseName, mTEPES): _path = os.path.join(DirName, CaseName) StartTime = time.time() - #%% reading data from CSV - dfOption = pd.read_csv(_path+'/oT_Data_Option_' +CaseName+'.csv', index_col=[0 ]) - dfParameter = pd.read_csv(_path+'/oT_Data_Parameter_' +CaseName+'.csv', index_col=[0 ]) - dfScenario = pd.read_csv(_path+'/oT_Data_Scenario_' +CaseName+'.csv', index_col=[0 ]) - dfStage = pd.read_csv(_path+'/oT_Data_Stage_' +CaseName+'.csv', index_col=[0 ]) - dfSwitchingStage = pd.read_csv(_path+'/oT_Data_SwitchingStage_' +CaseName+'.csv', index_col=[0,1,2,3]) - dfDuration = pd.read_csv(_path+'/oT_Data_Duration_' +CaseName+'.csv', index_col=[0 ]) - dfReserveMargin = pd.read_csv(_path+'/oT_Data_ReserveMargin_' +CaseName+'.csv', index_col=[0 ]) - dfDemand = pd.read_csv(_path+'/oT_Data_Demand_' +CaseName+'.csv', index_col=[0,1,2 ]) - dfInertia = pd.read_csv(_path+'/oT_Data_Inertia_' +CaseName+'.csv', index_col=[0,1,2 ]) - dfUpOperatingReserve = pd.read_csv(_path+'/oT_Data_OperatingReserveUp_' +CaseName+'.csv', index_col=[0,1,2 ]) - dfDwOperatingReserve = pd.read_csv(_path+'/oT_Data_OperatingReserveDown_' +CaseName+'.csv', index_col=[0,1,2 ]) - dfGeneration = pd.read_csv(_path+'/oT_Data_Generation_' +CaseName+'.csv', index_col=[0 ]) - dfVariableMinPower = pd.read_csv(_path+'/oT_Data_VariableMinGeneration_' +CaseName+'.csv', index_col=[0,1,2 ]) - dfVariableMaxPower = pd.read_csv(_path+'/oT_Data_VariableMaxGeneration_' +CaseName+'.csv', index_col=[0,1,2 ]) - dfVariableMinCharge = pd.read_csv(_path+'/oT_Data_VariableMinConsumption_'+CaseName+'.csv', index_col=[0,1,2 ]) - dfVariableMaxCharge = pd.read_csv(_path+'/oT_Data_VariableMaxConsumption_'+CaseName+'.csv', index_col=[0,1,2 ]) - dfVariableMinStorage = pd.read_csv(_path+'/oT_Data_VariableMinStorage_' +CaseName+'.csv', index_col=[0,1,2 ]) - dfVariableMaxStorage = pd.read_csv(_path+'/oT_Data_VariableMaxStorage_' +CaseName+'.csv', index_col=[0,1,2 ]) - dfEnergyInflows = pd.read_csv(_path+'/oT_Data_EnergyInflows_' +CaseName+'.csv', index_col=[0,1,2 ]) - dfEnergyOutflows = pd.read_csv(_path+'/oT_Data_EnergyOutflows_' +CaseName+'.csv', index_col=[0,1,2 ]) - dfNodeLocation = pd.read_csv(_path+'/oT_Data_NodeLocation_' +CaseName+'.csv', index_col=[0 ]) - dfNetwork = pd.read_csv(_path+'/oT_Data_Network_' +CaseName+'.csv', index_col=[0,1,2 ]) + # %% reading data from CSV + dfOption = pd.read_csv( + _path + + '/oT_Data_Option_' + + CaseName + + '.csv', + index_col=[0]) + dfParameter = pd.read_csv( + _path + + '/oT_Data_Parameter_' + + CaseName + + '.csv', + index_col=[0]) + dfScenario = pd.read_csv( + _path + + '/oT_Data_Scenario_' + + CaseName + + '.csv', + index_col=[0]) + dfStage = pd.read_csv( + _path + + '/oT_Data_Stage_' + + CaseName + + '.csv', + index_col=[0]) + dfSwitchingStage = pd.read_csv( + _path + + '/oT_Data_SwitchingStage_' + + CaseName + + '.csv', + index_col=[ + 0, + 1, + 2, + 3]) + dfDuration = pd.read_csv( + _path + + '/oT_Data_Duration_' + + CaseName + + '.csv', + index_col=[0]) + dfReserveMargin = pd.read_csv( + _path + + '/oT_Data_ReserveMargin_' + + CaseName + + '.csv', + index_col=[0]) + dfDemand = pd.read_csv( + _path + + '/oT_Data_Demand_' + + CaseName + + '.csv', + index_col=[ + 0, + 1, + 2]) + dfInertia = pd.read_csv( + _path + + '/oT_Data_Inertia_' + + CaseName + + '.csv', + index_col=[ + 0, + 1, + 2]) + dfUpOperatingReserve = pd.read_csv( + _path + + '/oT_Data_OperatingReserveUp_' + + CaseName + + '.csv', + index_col=[ + 0, + 1, + 2]) + dfDwOperatingReserve = pd.read_csv( + _path + + '/oT_Data_OperatingReserveDown_' + + CaseName + + '.csv', + index_col=[ + 0, + 1, + 2]) + dfGeneration = pd.read_csv( + _path + + '/oT_Data_Generation_' + + CaseName + + '.csv', + index_col=[0]) + dfVariableMinPower = pd.read_csv( + _path + + '/oT_Data_VariableMinGeneration_' + + CaseName + + '.csv', + index_col=[ + 0, + 1, + 2]) + dfVariableMaxPower = pd.read_csv( + _path + + '/oT_Data_VariableMaxGeneration_' + + CaseName + + '.csv', + index_col=[ + 0, + 1, + 2]) + dfVariableMinCharge = pd.read_csv( + _path + + '/oT_Data_VariableMinConsumption_' + + CaseName + + '.csv', + index_col=[ + 0, + 1, + 2]) + dfVariableMaxCharge = pd.read_csv( + _path + + '/oT_Data_VariableMaxConsumption_' + + CaseName + + '.csv', + index_col=[ + 0, + 1, + 2]) + dfVariableMinStorage = pd.read_csv( + _path + + '/oT_Data_VariableMinStorage_' + + CaseName + + '.csv', + index_col=[ + 0, + 1, + 2]) + dfVariableMaxStorage = pd.read_csv( + _path + + '/oT_Data_VariableMaxStorage_' + + CaseName + + '.csv', + index_col=[ + 0, + 1, + 2]) + dfEnergyInflows = pd.read_csv( + _path + + '/oT_Data_EnergyInflows_' + + CaseName + + '.csv', + index_col=[ + 0, + 1, + 2]) + dfEnergyOutflows = pd.read_csv( + _path + + '/oT_Data_EnergyOutflows_' + + CaseName + + '.csv', + index_col=[ + 0, + 1, + 2]) + dfNodeLocation = pd.read_csv( + _path + + '/oT_Data_NodeLocation_' + + CaseName + + '.csv', + index_col=[0]) + dfNetwork = pd.read_csv( + _path + + '/oT_Data_Network_' + + CaseName + + '.csv', + index_col=[ + 0, + 1, + 2]) # substitute NaN by 0 - dfOption.fillna (0 , inplace=True) - dfParameter.fillna (0.0, inplace=True) - dfScenario.fillna (0.0, inplace=True) - dfStage.fillna (0.0, inplace=True) - dfSwitchingStage.fillna (0.0, inplace=True) - dfDuration.fillna (0 , inplace=True) - dfReserveMargin.fillna (0.0, inplace=True) - dfDemand.fillna (0.0, inplace=True) - dfInertia.fillna (0.0, inplace=True) + dfOption.fillna(0, inplace=True) + dfParameter.fillna(0.0, inplace=True) + dfScenario.fillna(0.0, inplace=True) + dfStage.fillna(0.0, inplace=True) + dfSwitchingStage.fillna(0.0, inplace=True) + dfDuration.fillna(0, inplace=True) + dfReserveMargin.fillna(0.0, inplace=True) + dfDemand.fillna(0.0, inplace=True) + dfInertia.fillna(0.0, inplace=True) dfUpOperatingReserve.fillna(0.0, inplace=True) dfDwOperatingReserve.fillna(0.0, inplace=True) - dfGeneration.fillna (0.0, inplace=True) - dfVariableMinPower.fillna (0.0, inplace=True) - dfVariableMaxPower.fillna (0.0, inplace=True) - dfVariableMinCharge.fillna (0.0, inplace=True) - dfVariableMaxCharge.fillna (0.0, inplace=True) + dfGeneration.fillna(0.0, inplace=True) + dfVariableMinPower.fillna(0.0, inplace=True) + dfVariableMaxPower.fillna(0.0, inplace=True) + dfVariableMinCharge.fillna(0.0, inplace=True) + dfVariableMaxCharge.fillna(0.0, inplace=True) dfVariableMinStorage.fillna(0.0, inplace=True) dfVariableMaxStorage.fillna(0.0, inplace=True) - dfEnergyInflows.fillna (0.0, inplace=True) - dfEnergyOutflows.fillna (0.0, inplace=True) - dfNodeLocation.fillna (0.0, inplace=True) - dfNetwork.fillna (0.0, inplace=True) + dfEnergyInflows.fillna(0.0, inplace=True) + dfEnergyOutflows.fillna(0.0, inplace=True) + dfNodeLocation.fillna(0.0, inplace=True) + dfNetwork.fillna(0.0, inplace=True) # show some statistics of the data - print('Reserve margin \n', dfReserveMargin.describe ()) - print('Demand \n', dfDemand.describe ()) - print('Inertia \n', dfInertia.describe ()) + print('Reserve margin \n', dfReserveMargin.describe()) + print('Demand \n', dfDemand.describe()) + print('Inertia \n', dfInertia.describe()) print('Upward operating reserves \n', dfUpOperatingReserve.describe()) print('Downward operating reserves \n', dfDwOperatingReserve.describe()) - print('Generation \n', dfGeneration.describe ()) - print('Variable minimum generation \n', dfVariableMinPower.describe ()) - print('Variable maximum generation \n', dfVariableMaxPower.describe ()) - print('Variable minimum consumption \n', dfVariableMinCharge.describe ()) - print('Variable maximum consumption \n', dfVariableMaxCharge.describe ()) + print('Generation \n', dfGeneration.describe()) + print('Variable minimum generation \n', dfVariableMinPower.describe()) + print('Variable maximum generation \n', dfVariableMaxPower.describe()) + print('Variable minimum consumption \n', dfVariableMinCharge.describe()) + print('Variable maximum consumption \n', dfVariableMaxCharge.describe()) print('Variable minimum storage \n', dfVariableMinStorage.describe()) print('Variable maximum storage \n', dfVariableMaxStorage.describe()) - print('Energy inflows \n', dfEnergyInflows.describe ()) - print('Energy outflows \n', dfEnergyOutflows.describe ()) - print('Network \n', dfNetwork.describe ()) + print('Energy inflows \n', dfEnergyInflows.describe()) + print('Energy outflows \n', dfEnergyOutflows.describe()) + print('Network \n', dfNetwork.describe()) - #%% reading the sets + # %% reading the sets dictSets = DataPortal() - dictSets.load(filename=_path+'/oT_Dict_Scenario_' +CaseName+'.csv', set='sc' , format='set') - dictSets.load(filename=_path+'/oT_Dict_Period_' +CaseName+'.csv', set='p' , format='set') - dictSets.load(filename=_path+'/oT_Dict_Stage_' +CaseName+'.csv', set='st' , format='set') - dictSets.load(filename=_path+'/oT_Dict_SwitchingStage_'+CaseName+'.csv', set='ss' , format='set') - dictSets.load(filename=_path+'/oT_Dict_LoadLevel_' +CaseName+'.csv', set='n' , format='set') - dictSets.load(filename=_path+'/oT_Dict_Generation_' +CaseName+'.csv', set='g' , format='set') - dictSets.load(filename=_path+'/oT_Dict_Technology_' +CaseName+'.csv', set='gt' , format='set') - dictSets.load(filename=_path+'/oT_Dict_Storage_' +CaseName+'.csv', set='et' , format='set') - dictSets.load(filename=_path+'/oT_Dict_Node_' +CaseName+'.csv', set='nd' , format='set') - dictSets.load(filename=_path+'/oT_Dict_Zone_' +CaseName+'.csv', set='zn' , format='set') - dictSets.load(filename=_path+'/oT_Dict_Area_' +CaseName+'.csv', set='ar' , format='set') - dictSets.load(filename=_path+'/oT_Dict_Region_' +CaseName+'.csv', set='rg' , format='set') - dictSets.load(filename=_path+'/oT_Dict_Circuit_' +CaseName+'.csv', set='cc' , format='set') - dictSets.load(filename=_path+'/oT_Dict_Line_' +CaseName+'.csv', set='lt' , format='set') - - dictSets.load(filename=_path+'/oT_Dict_NodeToZone_' +CaseName+'.csv', set='ndzn', format='set') - dictSets.load(filename=_path+'/oT_Dict_ZoneToArea_' +CaseName+'.csv', set='znar', format='set') - dictSets.load(filename=_path+'/oT_Dict_AreaToRegion_' +CaseName+'.csv', set='arrg', format='set') - - mTEPES.scc = Set(initialize=dictSets['sc'], ordered=True, doc='scenarios' ) - mTEPES.pp = Set(initialize=dictSets['p' ], ordered=True, doc='periods' ) - mTEPES.p = Set(initialize=dictSets['p' ], ordered=True, doc='periods' ) - mTEPES.stt = Set(initialize=dictSets['st'], ordered=True, doc='stages' ) - mTEPES.sws = Set(initialize=dictSets['ss'], ordered=True, doc='switching stages') - mTEPES.nn = Set(initialize=dictSets['n' ], ordered=True, doc='load levels' ) - mTEPES.gg = Set(initialize=dictSets['g' ], ordered=False, doc='units' ) - mTEPES.gt = Set(initialize=dictSets['gt'], ordered=False, doc='technologies' ) - mTEPES.et = Set(initialize=dictSets['et'], ordered=False, doc='ESS types' ) - mTEPES.nd = Set(initialize=dictSets['nd'], ordered=False, doc='nodes' ) - mTEPES.ni = Set(initialize=dictSets['nd'], ordered=False, doc='nodes' ) - mTEPES.nf = Set(initialize=dictSets['nd'], ordered=False, doc='nodes' ) - mTEPES.zn = Set(initialize=dictSets['zn'], ordered=False, doc='zones' ) - mTEPES.ar = Set(initialize=dictSets['ar'], ordered=False, doc='areas' ) - mTEPES.rg = Set(initialize=dictSets['rg'], ordered=False, doc='regions' ) - mTEPES.cc = Set(initialize=dictSets['cc'], ordered=False, doc='circuits' ) - mTEPES.c2 = Set(initialize=dictSets['cc'], ordered=False, doc='circuits' ) - mTEPES.lt = Set(initialize=dictSets['lt'], ordered=False, doc='line types' ) - - mTEPES.ndzn = Set(initialize=dictSets['ndzn'], ordered=False, doc='node to zone' ) - mTEPES.znar = Set(initialize=dictSets['znar'], ordered=False, doc='zone to area' ) - mTEPES.arrg = Set(initialize=dictSets['arrg'], ordered=False, doc='area to region' ) - - #%% parameters - pIndBinGenInvest = dfOption ['IndBinGenInvest' ][0].astype('int') # Indicator of binary generation expansion decisions, 0 continuous - 1 binary - pIndBinNetInvest = dfOption ['IndBinNetInvest' ][0].astype('int') # Indicator of binary network expansion decisions, 0 continuous - 1 binary - pIndBinGenOperat = dfOption ['IndBinGenOperat' ][0].astype('int') # Indicator of binary generation operation decisions, 0 continuous - 1 binary - pIndNetLosses = dfOption ['IndNetLosses' ][0].astype('int') # Indicator of network losses, 0 lossless - 1 ohmic losses - pIndBinLineCommit = dfOption ['IndBinLineCommit' ][0].astype('int') # Indicator of binary switching decisions, 0 continuous - 1 binary - pIndSwitchingStage = dfOption ['IndSwitchingStage' ][0].astype('int') # Indicator to use switching stage decisions, 0 No - 1 Yes - pENSCost = dfParameter['ENSCost' ][0] * 1e-3 # cost of energy not served [MEUR/GWh] - pCO2Cost = dfParameter['CO2Cost' ][0] # cost of CO2 emission [EUR/t CO2] - pUpReserveActivation = dfParameter['UpReserveActivation'][0] # upward reserve activation [p.u.] - pDwReserveActivation = dfParameter['DwReserveActivation'][0] # downward reserve activation [p.u.] - pSBase = dfParameter['SBase' ][0] * 1e-3 # base power [GW] - pReferenceNode = dfParameter['ReferenceNode' ][0] # reference node - pTimeStep = dfParameter['TimeStep' ][0].astype('int') # duration of the unit time step [h] - # pStageDuration = dfParameter['StageDuration' ][0].astype('int') # duration of each stage [h] - - pScenProb = dfScenario ['Probability' ] # probabilities of scenarios [p.u.] - pStageWeight = dfStage ['Weight' ] # weights of stages [p.u.] - pSwitchingStage = dfSwitchingStage['SwitchingStage'] # switching stage - pDuration = dfDuration ['Duration' ] * pTimeStep # duration of load levels [h] - pReserveMargin = dfReserveMargin ['ReserveMargin' ] # adequacy reserve margin [p.u.] - pLevelToStage = dfDuration ['Stage' ] # load levels assignment to stages - pDemand = dfDemand [mTEPES.nd] * 1e-3 # demand [GW] - pSystemInertia = dfInertia [mTEPES.ar] # inertia [s] - pOperReserveUp = dfUpOperatingReserve [mTEPES.ar] * 1e-3 # upward operating reserve [GW] - pOperReserveDw = dfDwOperatingReserve [mTEPES.ar] * 1e-3 # downward operating reserve [GW] - pVariableMinPower = dfVariableMinPower [mTEPES.gg] * 1e-3 # dynamic variable minimum power [GW] - pVariableMaxPower = dfVariableMaxPower [mTEPES.gg] * 1e-3 # dynamic variable maximum power [GW] - pVariableMinCharge = dfVariableMinCharge [mTEPES.gg] * 1e-3 # dynamic variable minimum charge [GW] - pVariableMaxCharge = dfVariableMaxCharge [mTEPES.gg] * 1e-3 # dynamic variable maximum charge [GW] - pVariableMinStorage = dfVariableMinStorage [mTEPES.gg] # dynamic variable minimum storage [GWh] - pVariableMaxStorage = dfVariableMaxStorage [mTEPES.gg] # dynamic variable maximum storage [GWh] - pEnergyInflows = dfEnergyInflows [mTEPES.gg] * 1e-3 # dynamic energy inflows [GW] - pEnergyOutflows = dfEnergyOutflows [mTEPES.gg] * 1e-3 # dynamic energy outflows [GW] - - # compute the demand as the mean over the time step load levels and assign it to active load levels. Idem for operating reserve, variable max power, variable min and max storage and inflows + dictSets.load( + filename=_path + + '/oT_Dict_Scenario_' + + CaseName + + '.csv', + set='sc', + format='set') + dictSets.load( + filename=_path + + '/oT_Dict_Period_' + + CaseName + + '.csv', + set='p', + format='set') + dictSets.load( + filename=_path + + '/oT_Dict_Stage_' + + CaseName + + '.csv', + set='st', + format='set') + dictSets.load( + filename=_path + + '/oT_Dict_SwitchingStage_' + + CaseName + + '.csv', + set='ss', + format='set') + dictSets.load( + filename=_path + + '/oT_Dict_LoadLevel_' + + CaseName + + '.csv', + set='n', + format='set') + dictSets.load( + filename=_path + + '/oT_Dict_Generation_' + + CaseName + + '.csv', + set='g', + format='set') + dictSets.load( + filename=_path + + '/oT_Dict_Technology_' + + CaseName + + '.csv', + set='gt', + format='set') + dictSets.load( + filename=_path + + '/oT_Dict_Storage_' + + CaseName + + '.csv', + set='et', + format='set') + dictSets.load( + filename=_path + + '/oT_Dict_Node_' + + CaseName + + '.csv', + set='nd', + format='set') + dictSets.load( + filename=_path + + '/oT_Dict_Zone_' + + CaseName + + '.csv', + set='zn', + format='set') + dictSets.load( + filename=_path + + '/oT_Dict_Area_' + + CaseName + + '.csv', + set='ar', + format='set') + dictSets.load( + filename=_path + + '/oT_Dict_Region_' + + CaseName + + '.csv', + set='rg', + format='set') + dictSets.load( + filename=_path + + '/oT_Dict_Circuit_' + + CaseName + + '.csv', + set='cc', + format='set') + dictSets.load( + filename=_path + + '/oT_Dict_Line_' + + CaseName + + '.csv', + set='lt', + format='set') + + dictSets.load( + filename=_path + + '/oT_Dict_NodeToZone_' + + CaseName + + '.csv', + set='ndzn', + format='set') + dictSets.load( + filename=_path + + '/oT_Dict_ZoneToArea_' + + CaseName + + '.csv', + set='znar', + format='set') + dictSets.load( + filename=_path + + '/oT_Dict_AreaToRegion_' + + CaseName + + '.csv', + set='arrg', + format='set') + + mTEPES.scc = Set(initialize=dictSets['sc'], ordered=True, doc='scenarios') + mTEPES.pp = Set(initialize=dictSets['p'], ordered=True, doc='periods') + mTEPES.p = Set(initialize=dictSets['p'], ordered=True, doc='periods') + mTEPES.stt = Set(initialize=dictSets['st'], ordered=True, doc='stages') + mTEPES.sws = Set( + initialize=dictSets['ss'], + ordered=True, + doc='switching stages') + mTEPES.nn = Set(initialize=dictSets['n'], ordered=True, doc='load levels') + mTEPES.gg = Set(initialize=dictSets['g'], ordered=False, doc='units') + mTEPES.gt = Set( + initialize=dictSets['gt'], + ordered=False, + doc='technologies') + mTEPES.et = Set(initialize=dictSets['et'], ordered=False, doc='ESS types') + mTEPES.nd = Set(initialize=dictSets['nd'], ordered=False, doc='nodes') + mTEPES.ni = Set(initialize=dictSets['nd'], ordered=False, doc='nodes') + mTEPES.nf = Set(initialize=dictSets['nd'], ordered=False, doc='nodes') + mTEPES.zn = Set(initialize=dictSets['zn'], ordered=False, doc='zones') + mTEPES.ar = Set(initialize=dictSets['ar'], ordered=False, doc='areas') + mTEPES.rg = Set(initialize=dictSets['rg'], ordered=False, doc='regions') + mTEPES.cc = Set(initialize=dictSets['cc'], ordered=False, doc='circuits') + mTEPES.c2 = Set(initialize=dictSets['cc'], ordered=False, doc='circuits') + mTEPES.lt = Set(initialize=dictSets['lt'], ordered=False, doc='line types') + + mTEPES.ndzn = Set( + initialize=dictSets['ndzn'], + ordered=False, + doc='node to zone') + mTEPES.znar = Set( + initialize=dictSets['znar'], + ordered=False, + doc='zone to area') + mTEPES.arrg = Set( + initialize=dictSets['arrg'], + ordered=False, + doc='area to region') + + # %% parameters + # Indicator of binary generation expansion decisions, 0 continuous - 1 + # binary + pIndBinGenInvest = dfOption['IndBinGenInvest'][0].astype('int') + # Indicator of binary network expansion decisions, 0 continuous - 1 + # binary + pIndBinNetInvest = dfOption['IndBinNetInvest'][0].astype('int') + # Indicator of binary generation operation decisions, 0 continuous - 1 + # binary + pIndBinGenOperat = dfOption['IndBinGenOperat'][0].astype('int') + # Indicator of network losses, 0 lossless - 1 + # ohmic losses + pIndNetLosses = dfOption['IndNetLosses'][0].astype('int') + # Indicator of binary switching decisions, 0 continuous - 1 + # binary + pIndBinLineCommit = dfOption['IndBinLineCommit'][0].astype('int') + # Indicator to use switching stage decisions, 0 No - 1 Yes + pIndSwitchingStage = dfOption['IndSwitchingStage'][0].astype('int') + # cost of energy not served [MEUR/GWh] + pENSCost = dfParameter['ENSCost'][0] * 1e-3 + # cost of CO2 emission [EUR/t CO2] + pCO2Cost = dfParameter['CO2Cost'][0] + # upward reserve activation [p.u.] + pUpReserveActivation = dfParameter['UpReserveActivation'][0] + # downward reserve activation [p.u.] + pDwReserveActivation = dfParameter['DwReserveActivation'][0] + # base power [GW] + pSBase = dfParameter['SBase'][0] * 1e-3 + # reference node + pReferenceNode = dfParameter['ReferenceNode'][0] + # duration of the unit time step [h] + pTimeStep = dfParameter['TimeStep'][0].astype('int') + # pStageDuration = dfParameter['StageDuration' + # ][0].astype('int') + # # duration of each stage [h] + + # probabilities of scenarios [p.u.] + pScenProb = dfScenario['Probability'] + # weights of stages [p.u.] + pStageWeight = dfStage['Weight'] + # switching stage + pSwitchingStage = dfSwitchingStage['SwitchingStage'] + # duration of load levels [h] + pDuration = dfDuration['Duration'] * pTimeStep + # adequacy reserve margin [p.u.] + pReserveMargin = dfReserveMargin['ReserveMargin'] + # load levels assignment to stages + pLevelToStage = dfDuration['Stage'] + # demand [GW] + pDemand = dfDemand[mTEPES.nd] * 1e-3 + # inertia [s] + pSystemInertia = dfInertia[mTEPES.ar] + # upward operating reserve [GW] + pOperReserveUp = dfUpOperatingReserve[mTEPES.ar] * 1e-3 + # downward operating reserve [GW] + pOperReserveDw = dfDwOperatingReserve[mTEPES.ar] * 1e-3 + # dynamic variable minimum power [GW] + pVariableMinPower = dfVariableMinPower[mTEPES.gg] * 1e-3 + # dynamic variable maximum power [GW] + pVariableMaxPower = dfVariableMaxPower[mTEPES.gg] * 1e-3 + # dynamic variable minimum charge [GW] + pVariableMinCharge = dfVariableMinCharge[mTEPES.gg] * 1e-3 + # dynamic variable maximum charge [GW] + pVariableMaxCharge = dfVariableMaxCharge[mTEPES.gg] * 1e-3 + # dynamic variable minimum storage [GWh] + pVariableMinStorage = dfVariableMinStorage[mTEPES.gg] + # dynamic variable maximum storage [GWh] + pVariableMaxStorage = dfVariableMaxStorage[mTEPES.gg] + # dynamic energy inflows [GW] + pEnergyInflows = dfEnergyInflows[mTEPES.gg] * 1e-3 + # dynamic energy outflows [GW] + pEnergyOutflows = dfEnergyOutflows[mTEPES.gg] * 1e-3 + + # compute the demand as the mean over the time step load levels and assign + # it to active load levels. Idem for operating reserve, variable max + # power, variable min and max storage and inflows if pTimeStep > 1: - pDemand = pDemand.rolling (pTimeStep).mean() - pSystemInertia = pSystemInertia.rolling (pTimeStep).mean() - pOperReserveUp = pOperReserveUp.rolling (pTimeStep).mean() - pOperReserveDw = pOperReserveDw.rolling (pTimeStep).mean() - pVariableMinPower = pVariableMinPower.rolling (pTimeStep).mean() - pVariableMaxPower = pVariableMaxPower.rolling (pTimeStep).mean() - pVariableMinCharge = pVariableMinCharge.rolling (pTimeStep).mean() - pVariableMaxCharge = pVariableMaxCharge.rolling (pTimeStep).mean() + pDemand = pDemand.rolling(pTimeStep).mean() + pSystemInertia = pSystemInertia.rolling(pTimeStep).mean() + pOperReserveUp = pOperReserveUp.rolling(pTimeStep).mean() + pOperReserveDw = pOperReserveDw.rolling(pTimeStep).mean() + pVariableMinPower = pVariableMinPower.rolling(pTimeStep).mean() + pVariableMaxPower = pVariableMaxPower.rolling(pTimeStep).mean() + pVariableMinCharge = pVariableMinCharge.rolling(pTimeStep).mean() + pVariableMaxCharge = pVariableMaxCharge.rolling(pTimeStep).mean() pVariableMinStorage = pVariableMinStorage.rolling(pTimeStep).mean() pVariableMaxStorage = pVariableMaxStorage.rolling(pTimeStep).mean() - pEnergyInflows = pEnergyInflows.rolling (pTimeStep).mean() - pEnergyOutflows = pEnergyOutflows.rolling (pTimeStep).mean() - - pDemand.fillna (0.0, inplace=True) - pSystemInertia.fillna (0.0, inplace=True) - pOperReserveUp.fillna (0.0, inplace=True) - pOperReserveDw.fillna (0.0, inplace=True) - pVariableMinPower.fillna (0.0, inplace=True) - pVariableMaxPower.fillna (0.0, inplace=True) - pVariableMinCharge.fillna (0.0, inplace=True) - pVariableMaxCharge.fillna (0.0, inplace=True) + pEnergyInflows = pEnergyInflows.rolling(pTimeStep).mean() + pEnergyOutflows = pEnergyOutflows.rolling(pTimeStep).mean() + + pDemand.fillna(0.0, inplace=True) + pSystemInertia.fillna(0.0, inplace=True) + pOperReserveUp.fillna(0.0, inplace=True) + pOperReserveDw.fillna(0.0, inplace=True) + pVariableMinPower.fillna(0.0, inplace=True) + pVariableMaxPower.fillna(0.0, inplace=True) + pVariableMinCharge.fillna(0.0, inplace=True) + pVariableMaxCharge.fillna(0.0, inplace=True) pVariableMinStorage.fillna(0.0, inplace=True) pVariableMaxStorage.fillna(0.0, inplace=True) - pEnergyInflows.fillna (0.0, inplace=True) - pEnergyOutflows.fillna (0.0, inplace=True) + pEnergyInflows.fillna(0.0, inplace=True) + pEnergyOutflows.fillna(0.0, inplace=True) if pTimeStep > 1: - # assign duration 0 to load levels not being considered, active load levels are at the end of every pTimeStep - for i in range(pTimeStep-2,-1,-1): - pDuration[range(i,len(mTEPES.nn),pTimeStep)] = 0 - - #%% generation parameters - pGenToNode = dfGeneration ['Node' ] # generator location in node - pGenToTechnology = dfGeneration ['Technology' ] # generator association to technology - pIndBinUnitInvest = dfGeneration ['BinaryInvestment' ] # binary unit investment decision [Yes] - pIndBinUnitCommit = dfGeneration ['BinaryCommitment' ] # binary unit commitment decision [Yes] - pMustRun = dfGeneration ['MustRun' ] # must-run unit [Yes] - pInertia = dfGeneration ['Inertia' ] # inertia constant [s] - pAvailability = dfGeneration ['Availability' ] # unit availability for adequacy [p.u.] - pEFOR = dfGeneration ['EFOR' ] # EFOR [p.u.] - pRatedMinPower = dfGeneration ['MinimumPower' ] * 1e-3 * (1.0-dfGeneration['EFOR']) # rated minimum power [GW] - pRatedMaxPower = dfGeneration ['MaximumPower' ] * 1e-3 * (1.0-dfGeneration['EFOR']) # rated maximum power [GW] - pLinearFuelCost = dfGeneration ['LinearTerm' ] * 1e-3 * dfGeneration['FuelCost'] # fuel term variable cost [MEUR/GWh] - pLinearOMCost = dfGeneration ['OMVariableCost' ] * 1e-3 # O&M term variable cost [MEUR/GWh] - pConstantVarCost = dfGeneration ['ConstantTerm' ] * 1e-6 * dfGeneration['FuelCost'] # constant term variable cost [MEUR/h] - pStartUpCost = dfGeneration ['StartUpCost' ] # startup cost [MEUR] - pShutDownCost = dfGeneration ['ShutDownCost' ] # shutdown cost [MEUR] - pRampUp = dfGeneration ['RampUp' ] * 1e-3 # ramp up rate [GW/h] - pRampDw = dfGeneration ['RampDown' ] * 1e-3 # ramp down rate [GW/h] - pCO2EmissionCost = dfGeneration ['CO2EmissionRate' ] * 1e-3 * pCO2Cost # emission cost [MEUR/GWh] - pUpTime = dfGeneration ['UpTime' ] # minimum up time [h] - pDwTime = dfGeneration ['DownTime' ] # minimum down time [h] - pGenFixedCost = dfGeneration ['FixedCost' ] * dfGeneration['FixedChargeRate'] # generation fixed cost [MEUR] - pRatedMinCharge = dfGeneration ['MinimumCharge' ] * 1e-3 # rated minimum ESS charge [GW] - pRatedMaxCharge = dfGeneration ['MaximumCharge' ] * 1e-3 # rated maximum ESS charge [GW] - pRatedMinStorage = dfGeneration ['MinimumStorage' ] # rated minimum ESS storage [GWh] - pRatedMaxStorage = dfGeneration ['MaximumStorage' ] # rated maximum ESS storage [GWh] - pInitialInventory = dfGeneration ['InitialStorage' ] # initial ESS storage [GWh] - pEfficiency = dfGeneration ['Efficiency' ] # ESS round-trip efficiency [p.u.] - pStorageType = dfGeneration ['StorageType' ] # ESS storage type - pOutflowsType = dfGeneration ['OutflowsType' ] # ESS outflows type - pRMaxReactivePower = dfGeneration ['MaximumReactivePower'] * 1e-3 # rated maximum reactive power [Gvar] - - pLinearOperCost = pLinearFuelCost + pCO2EmissionCost - pLinearVarCost = pLinearFuelCost + pLinearOMCost - - pNodeLat = dfNodeLocation['Latitude' ] # node latitude [º] - pNodeLon = dfNodeLocation['Longitude' ] # node longitude [º] - - pLineType = dfNetwork ['LineType' ] # line type - pLineLength = dfNetwork ['Length' ] # line length [km] - pLineSwitching = dfNetwork ['Switching' ] # line switching decision [Yes] - pLineVoltage = dfNetwork ['Voltage' ] # line voltage [kV] - pLineLossFactor = dfNetwork ['LossFactor' ] # loss factor [p.u.] - pLineR = dfNetwork ['Resistance' ] # resistance [p.u.] - pLineX = dfNetwork ['Reactance' ].sort_index() # reactance [p.u.] - pLineBsh = dfNetwork ['Susceptance' ] # susceptance [p.u.] - pLineTAP = dfNetwork ['Tap' ] # tap changer [p.u.] - pConverter = dfNetwork ['Converter' ] # converter station [Yes] - pLineNTCFrw = dfNetwork ['TTC' ] * 1e-3 * dfNetwork['SecurityFactor' ] # net transfer capacity in forward direction [GW] - pLineNTCBck = dfNetwork ['TTCBck' ] * 1e-3 * dfNetwork['SecurityFactor' ] # net transfer capacity in backward direction [GW] - pNetFixedCost = dfNetwork ['FixedCost' ] * dfNetwork['FixedChargeRate'] # network fixed cost [MEUR] - pIndBinLineInvest = dfNetwork ['BinaryInvestment' ] # binary line investment decision [Yes] - pSwitchOnTime = dfNetwork ['SwOnTime' ] # minimum on time [h] - pSwitchOffTime = dfNetwork ['SwOffTime' ] # minimum off time [h] - pAngMin = dfNetwork ['AngMin' ] * math.pi / 180 # Min phase angle difference [rad] - pAngMax = dfNetwork ['AngMax' ] * math.pi / 180 # Max phase angle difference [rad] + # assign duration 0 to load levels not being considered, active load + # levels are at the end of every pTimeStep + for i in range(pTimeStep - 2, -1, -1): + pDuration[range(i, len(mTEPES.nn), pTimeStep)] = 0 + + # %% generation parameters + # generator location in node + pGenToNode = dfGeneration['Node'] + # generator association to technology + pGenToTechnology = dfGeneration['Technology'] + # binary unit investment decision [Yes] + pIndBinUnitInvest = dfGeneration['BinaryInvestment'] + # binary unit commitment decision [Yes] + pIndBinUnitCommit = dfGeneration['BinaryCommitment'] + # must-run unit [Yes] + pMustRun = dfGeneration['MustRun'] + # inertia constant [s] + pInertia = dfGeneration['Inertia'] + # unit availability for adequacy [p.u.] + pAvailability = dfGeneration['Availability'] + # EFOR [p.u.] + pEFOR = dfGeneration['EFOR'] + # rated minimum power [GW] + pRatedMinPower = dfGeneration['MinimumPower'] * \ + 1e-3 * (1.0 - dfGeneration['EFOR']) + # rated maximum power [GW] + pRatedMaxPower = dfGeneration['MaximumPower'] * \ + 1e-3 * (1.0 - dfGeneration['EFOR']) + # fuel term variable cost [MEUR/GWh] + pLinearFuelCost = dfGeneration['LinearTerm'] * \ + 1e-3 * dfGeneration['FuelCost'] + # O&M term variable cost [MEUR/GWh] + pLinearOMCost = dfGeneration['OMVariableCost'] * 1e-3 + # constant term variable cost [MEUR/h] + pConstantVarCost = dfGeneration['ConstantTerm'] * \ + 1e-6 * dfGeneration['FuelCost'] + # startup cost [MEUR] + pStartUpCost = dfGeneration['StartUpCost'] + # shutdown cost [MEUR] + pShutDownCost = dfGeneration['ShutDownCost'] + # ramp up rate [GW/h] + pRampUp = dfGeneration['RampUp'] * 1e-3 + # ramp down rate [GW/h] + pRampDw = dfGeneration['RampDown'] * 1e-3 + # emission cost [MEUR/GWh] + pCO2EmissionCost = dfGeneration['CO2EmissionRate'] * 1e-3 * pCO2Cost + # minimum up time [h] + pUpTime = dfGeneration['UpTime'] + # minimum down time [h] + pDwTime = dfGeneration['DownTime'] + # generation fixed cost [MEUR] + pGenFixedCost = dfGeneration['FixedCost'] * dfGeneration['FixedChargeRate'] + # rated minimum ESS charge [GW] + pRatedMinCharge = dfGeneration['MinimumCharge'] * 1e-3 + # rated maximum ESS charge [GW] + pRatedMaxCharge = dfGeneration['MaximumCharge'] * 1e-3 + # rated minimum ESS storage [GWh] + pRatedMinStorage = dfGeneration['MinimumStorage'] + # rated maximum ESS storage [GWh] + pRatedMaxStorage = dfGeneration['MaximumStorage'] + # initial ESS storage [GWh] + pInitialInventory = dfGeneration['InitialStorage'] + # ESS round-trip efficiency [p.u.] + pEfficiency = dfGeneration['Efficiency'] + pStorageType = dfGeneration['StorageType'] # ESS storage type + pOutflowsType = dfGeneration['OutflowsType'] # ESS outflows type + # rated maximum reactive power [Gvar] + pRMaxReactivePower = dfGeneration['MaximumReactivePower'] * 1e-3 + + pLinearOperCost = pLinearFuelCost + pCO2EmissionCost + pLinearVarCost = pLinearFuelCost + pLinearOMCost + + # node latitude [º] + pNodeLat = dfNodeLocation['Latitude'] + # node longitude [º] + pNodeLon = dfNodeLocation['Longitude'] + + # line type + pLineType = dfNetwork['LineType'] + # line length [km] + pLineLength = dfNetwork['Length'] + # line switching decision [Yes] + pLineSwitching = dfNetwork['Switching'] + # line voltage [kV] + pLineVoltage = dfNetwork['Voltage'] + # loss factor [p.u.] + pLineLossFactor = dfNetwork['LossFactor'] + # resistance [p.u.] + pLineR = dfNetwork['Resistance'] + # reactance [p.u.] + pLineX = dfNetwork['Reactance'].sort_index() + # susceptance [p.u.] + pLineBsh = dfNetwork['Susceptance'] + # tap changer [p.u.] + pLineTAP = dfNetwork['Tap'] + # converter station [Yes] + pConverter = dfNetwork['Converter'] + # net transfer capacity in forward direction [GW] + pLineNTCFrw = dfNetwork['TTC'] * 1e-3 * dfNetwork['SecurityFactor'] + # net transfer capacity in backward direction [GW] + pLineNTCBck = dfNetwork['TTCBck'] * 1e-3 * dfNetwork['SecurityFactor'] + # network fixed cost [MEUR] + pNetFixedCost = dfNetwork['FixedCost'] * dfNetwork['FixedChargeRate'] + # binary line investment decision [Yes] + pIndBinLineInvest = dfNetwork['BinaryInvestment'] + # minimum on time [h] + pSwitchOnTime = dfNetwork['SwOnTime'] + # minimum off time [h] + pSwitchOffTime = dfNetwork['SwOffTime'] + # Min phase angle difference [rad] + pAngMin = dfNetwork['AngMin'] * math.pi / 180 + # Max phase angle difference [rad] + pAngMax = dfNetwork['AngMax'] * math.pi / 180 # replace pLineNTCBck = 0.0 by pLineNTCFrw - pLineNTCBck = pLineNTCBck.where(pLineNTCBck > 0.0, other=pLineNTCFrw) + pLineNTCBck = pLineNTCBck.where(pLineNTCBck > 0.0, other=pLineNTCFrw) # replace pLineNTCFrw = 0.0 by pLineNTCBck - pLineNTCFrw = pLineNTCFrw.where(pLineNTCFrw > 0.0, other=pLineNTCBck) + pLineNTCFrw = pLineNTCFrw.where(pLineNTCFrw > 0.0, other=pLineNTCBck) # minimum up and down time converted to an integer number of time steps - pSwitchOnTime = round(pSwitchOnTime /pTimeStep).astype('int') - pSwitchOffTime = round(pSwitchOffTime/pTimeStep).astype('int') + pSwitchOnTime = round(pSwitchOnTime / pTimeStep).astype('int') + pSwitchOffTime = round(pSwitchOffTime / pTimeStep).astype('int') ReadingDataTime = time.time() - StartTime - StartTime = time.time() - print('Reading input data ... ', round(ReadingDataTime), 's') - - #%% defining subsets: active load levels (n,n2), thermal units (t), RES units (r), ESS units (es), candidate gen units (gc), candidate ESS units (ec), all the lines (la), candidate lines (lc), candidate DC lines (cd), existing DC lines (cd), lines with losses (ll), reference node (rf), and reactive generating units (gq) - mTEPES.sc = Set(initialize=mTEPES.scc, ordered=True , doc='scenarios' , filter=lambda mTEPES,scc : scc in mTEPES.scc and pScenProb [scc] > 0.0) - mTEPES.st = Set(initialize=mTEPES.stt, ordered=True , doc='stages' , filter=lambda mTEPES,stt : stt in mTEPES.stt and pStageWeight [stt] > 0.0) - mTEPES.ss = Set(initialize=mTEPES.sws, ordered=True , doc='switching stages' , filter=lambda mTEPES,sws : sws in mTEPES.sws ) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True , doc='load levels' , filter=lambda mTEPES,nn : nn in mTEPES.nn and pDuration [nn] > 0 ) - mTEPES.n2 = Set(initialize=mTEPES.nn, ordered=True , doc='load levels' , filter=lambda mTEPES,nn : nn in mTEPES.nn and pDuration [nn] > 0 ) - mTEPES.g = Set(initialize=mTEPES.gg, ordered=False, doc='generating units', filter=lambda mTEPES,gg : gg in mTEPES.gg and pRatedMaxPower [gg] > 0.0 and pGenToNode.reset_index().set_index(['index']).isin(mTEPES.nd)['Node'][gg]) # excludes generators with empty node - mTEPES.t = Set(initialize=mTEPES.g , ordered=False, doc='thermal units', filter=lambda mTEPES,g : g in mTEPES.g and pLinearOperCost [g ] > 0.0) - mTEPES.r = Set(initialize=mTEPES.g , ordered=False, doc='RES units', filter=lambda mTEPES,g : g in mTEPES.g and pLinearOperCost [g ] == 0.0 and pRatedMaxStorage[g] == 0.0) - mTEPES.es = Set(initialize=mTEPES.g , ordered=False, doc='ESS units', filter=lambda mTEPES,g : g in mTEPES.g and pRatedMaxStorage[g] > 0.0) - mTEPES.gc = Set(initialize=mTEPES.g , ordered=False, doc='candidate units', filter=lambda mTEPES,g : g in mTEPES.g and pGenFixedCost [g ] > 0.0) - mTEPES.ec = Set(initialize=mTEPES.es, ordered=False, doc='candidate ESS units', filter=lambda mTEPES,es : es in mTEPES.es and pGenFixedCost [es] > 0.0) - mTEPES.br = Set(initialize=mTEPES.ni*mTEPES.nf, ordered=False, doc='all branches ', filter=lambda mTEPES,ni,nf : (ni,nf) in pLineType ) - mTEPES.ln = Set(initialize=mTEPES.ni*mTEPES.nf*mTEPES.cc, ordered=False, doc='all input lines', filter=lambda mTEPES,ni,nf,cc: (ni,nf,cc) in pLineType ) - mTEPES.la = Set(initialize=mTEPES.ln, ordered=False, doc='all real lines', filter=lambda mTEPES,*ln : ln in mTEPES.ln and pLineX [ln] > 0.0 and pLineNTCFrw[ln] > 0.0 and pLineNTCBck[ln] > 0.0) - mTEPES.lc = Set(initialize=mTEPES.la, ordered=False, doc='candidate lines', filter=lambda mTEPES,*la : la in mTEPES.la and pNetFixedCost [la] > 0.0) - mTEPES.cd = Set(initialize=mTEPES.la, ordered=False, doc=' DC lines', filter=lambda mTEPES,*la : la in mTEPES.la and pNetFixedCost [la] > 0.0 and pLineType[la] == 'DC') - mTEPES.ed = Set(initialize=mTEPES.la, ordered=False, doc=' DC lines', filter=lambda mTEPES,*la : la in mTEPES.la and pNetFixedCost [la] == 0.0 and pLineType[la] == 'DC') - mTEPES.ll = Set(initialize=mTEPES.la, ordered=False, doc='loss lines', filter=lambda mTEPES,*la : la in mTEPES.la and pLineLossFactor [la] > 0.0 and pIndNetLosses > 0 ) - mTEPES.rf = Set(initialize=mTEPES.nd, ordered=True , doc='reference node' , filter=lambda mTEPES,nd : nd in pReferenceNode ) - mTEPES.gq = Set(initialize=mTEPES.gg, ordered=False, doc='gen reactive units', filter=lambda mTEPES,gg : gg in mTEPES.gg and pRMaxReactivePower[gg] > 0.0) - mTEPES.sq = Set(initialize=mTEPES.gg, ordered=False, doc='syn reactive units', filter=lambda mTEPES,gg : gg in mTEPES.gg and pRMaxReactivePower[gg] > 0.0 and pGenToTechnology[gg] == 'SynchronousCondenser') - - # non-RES units, they can be committed and also contribute to the operating reserves + StartTime = time.time() + print( + 'Reading input data ... ', + round(ReadingDataTime), + 's') + + # %% defining subsets: active load levels (n,n2), thermal units (t), RES units (r), ESS units (es), candidate gen units (gc), candidate ESS units (ec), all the lines (la), candidate lines (lc), candidate DC lines (cd), existing DC lines (cd), lines with losses (ll), reference node (rf), and reactive generating units (gq) + mTEPES.sc = Set( + initialize=mTEPES.scc, + ordered=True, + doc='scenarios', + filter=lambda mTEPES, + scc: scc in mTEPES.scc and pScenProb[scc] > 0.0) + mTEPES.st = Set( + initialize=mTEPES.stt, + ordered=True, + doc='stages', + filter=lambda mTEPES, + stt: stt in mTEPES.stt and pStageWeight[stt] > 0.0) + mTEPES.ss = Set( + initialize=mTEPES.sws, + ordered=True, + doc='switching stages', + filter=lambda mTEPES, + sws: sws in mTEPES.sws) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.nn and pDuration[nn] > 0) + mTEPES.n2 = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.nn and pDuration[nn] > 0) + mTEPES.g = Set( + initialize=mTEPES.gg, + ordered=False, + doc='generating units', + filter=lambda mTEPES, + gg: gg in mTEPES.gg and pRatedMaxPower[gg] > 0.0 and pGenToNode.reset_index().set_index( + ['index']).isin( + mTEPES.nd)['Node'][gg]) # excludes generators with empty node + mTEPES.t = Set( + initialize=mTEPES.g, + ordered=False, + doc='thermal units', + filter=lambda mTEPES, + g: g in mTEPES.g and pLinearOperCost[g] > 0.0) + mTEPES.r = Set( + initialize=mTEPES.g, + ordered=False, + doc='RES units', + filter=lambda mTEPES, + g: g in mTEPES.g and pLinearOperCost[g] == 0.0 and pRatedMaxStorage[g] == 0.0) + mTEPES.es = Set( + initialize=mTEPES.g, + ordered=False, + doc='ESS units', + filter=lambda mTEPES, + g: g in mTEPES.g and pRatedMaxStorage[g] > 0.0) + mTEPES.gc = Set( + initialize=mTEPES.g, + ordered=False, + doc='candidate units', + filter=lambda mTEPES, + g: g in mTEPES.g and pGenFixedCost[g] > 0.0) + mTEPES.ec = Set( + initialize=mTEPES.es, + ordered=False, + doc='candidate ESS units', + filter=lambda mTEPES, + es: es in mTEPES.es and pGenFixedCost[es] > 0.0) + mTEPES.br = Set( + initialize=mTEPES.ni * + mTEPES.nf, + ordered=False, + doc='all branches ', + filter=lambda mTEPES, + ni, + nf: ( + ni, + nf) in pLineType) + mTEPES.ln = Set( + initialize=mTEPES.ni * + mTEPES.nf * + mTEPES.cc, + ordered=False, + doc='all input lines', + filter=lambda mTEPES, + ni, + nf, + cc: ( + ni, + nf, + cc) in pLineType) + mTEPES.la = Set( + initialize=mTEPES.ln, + ordered=False, + doc='all real lines', + filter=lambda mTEPES, + * + ln: ln in mTEPES.ln and pLineX[ln] > 0.0 and pLineNTCFrw[ln] > 0.0 and pLineNTCBck[ln] > 0.0) + mTEPES.lc = Set( + initialize=mTEPES.la, + ordered=False, + doc='candidate lines', + filter=lambda mTEPES, + *la: la in mTEPES.la and pNetFixedCost[la] > 0.0) + mTEPES.cd = Set( + initialize=mTEPES.la, + ordered=False, + doc=' DC lines', + filter=lambda mTEPES, + *la: la in mTEPES.la and pNetFixedCost[la] > 0.0 and pLineType[la] == 'DC') + mTEPES.ed = Set( + initialize=mTEPES.la, + ordered=False, + doc=' DC lines', + filter=lambda mTEPES, + *la: la in mTEPES.la and pNetFixedCost[la] == 0.0 and pLineType[la] == 'DC') + mTEPES.ll = Set( + initialize=mTEPES.la, + ordered=False, + doc='loss lines', + filter=lambda mTEPES, + *la: la in mTEPES.la and pLineLossFactor[la] > 0.0 and pIndNetLosses > 0) + mTEPES.rf = Set( + initialize=mTEPES.nd, + ordered=True, + doc='reference node', + filter=lambda mTEPES, + nd: nd in pReferenceNode) + mTEPES.gq = Set( + initialize=mTEPES.gg, + ordered=False, + doc='gen reactive units', + filter=lambda mTEPES, + gg: gg in mTEPES.gg and pRMaxReactivePower[gg] > 0.0) + mTEPES.sq = Set( + initialize=mTEPES.gg, + ordered=False, + doc='syn reactive units', + filter=lambda mTEPES, + gg: gg in mTEPES.gg and pRMaxReactivePower[gg] > 0.0 and pGenToTechnology[gg] == 'SynchronousCondenser') + + # non-RES units, they can be committed and also contribute to the + # operating reserves mTEPES.nr = mTEPES.g - mTEPES.r # machines able to provide reactive power @@ -299,170 +785,303 @@ def InputData(DirName, CaseName, mTEPES): # mTEPES.lil = Set(initialize=mTEPES.nf*mTEPES.ni*mTEPES.cc, doc='input line', filter=lambda mTEPES,nf,ni,cc: (ni,nf,cc) in mTEPES.ll) # assigning a node to an area - pNode2Area = pd.DataFrame(0, dtype=int, index=pd.MultiIndex.from_tuples(mTEPES.nd*mTEPES.ar, names=('Node', 'Area')), columns=['Y/N']) - for nd,zn,ar in mTEPES.ndzn*mTEPES.ar: - if (zn,ar) in mTEPES.znar: - pNode2Area.loc[nd,ar] = 1 - mTEPES.ndar = Set(initialize=mTEPES.nd*mTEPES.ar, doc='node to area', filter=lambda mTEPES,nd,ar: (nd,ar) in mTEPES.nd*mTEPES.ar and pNode2Area.loc[nd,ar]['Y/N'] == 1) - - # assigning a line to an area. Both nodes are in the same area. Cross-area lines not included - pLine2Area = pd.DataFrame(0, dtype=int, index=pd.MultiIndex.from_tuples(mTEPES.la*mTEPES.ar, names=('InitialNode', 'FinalNode', 'Circuit', 'Area')), columns=['Y/N']) - for ni,nf,cc,ar in mTEPES.la*mTEPES.ar: - if (ni,ar) in mTEPES.ndar: - if (nf,ar) in mTEPES.ndar: - pLine2Area.loc[ni,nf,cc,ar] = 1 - mTEPES.laar = Set(initialize=mTEPES.la*mTEPES.ar, doc='line to area', filter=lambda mTEPES,ni,nf,cc,ar: (ni,nf,cc,ar) in mTEPES.la*mTEPES.ar and pLine2Area.loc[ni,nf,cc,ar]['Y/N'] == 1) + pNode2Area = pd.DataFrame(0, dtype=int, index=pd.MultiIndex.from_tuples( + mTEPES.nd * mTEPES.ar, names=('Node', 'Area')), columns=['Y/N']) + for nd, zn, ar in mTEPES.ndzn * mTEPES.ar: + if (zn, ar) in mTEPES.znar: + pNode2Area.loc[nd, ar] = 1 + mTEPES.ndar = Set(initialize=mTEPES.nd * mTEPES.ar, + doc='node to area', + filter=lambda mTEPES, + nd, + ar: (nd, + ar) in mTEPES.nd * mTEPES.ar and pNode2Area.loc[nd, + ar]['Y/N'] == 1) + + # assigning a line to an area. Both nodes are in the same area. Cross-area + # lines not included + pLine2Area = pd.DataFrame( + 0, + dtype=int, + index=pd.MultiIndex.from_tuples( + mTEPES.la * + mTEPES.ar, + names=( + 'InitialNode', + 'FinalNode', + 'Circuit', + 'Area')), + columns=['Y/N']) + for ni, nf, cc, ar in mTEPES.la * mTEPES.ar: + if (ni, ar) in mTEPES.ndar: + if (nf, ar) in mTEPES.ndar: + pLine2Area.loc[ni, nf, cc, ar] = 1 + mTEPES.laar = Set(initialize=mTEPES.la * mTEPES.ar, + doc='line to area', + filter=lambda mTEPES, + ni, + nf, + cc, + ar: (ni, + nf, + cc, + ar) in mTEPES.la * mTEPES.ar and pLine2Area.loc[ni, + nf, + cc, + ar]['Y/N'] == 1) # replacing string values by numerical values idxDict = dict() - idxDict[0 ] = 0 - idxDict['No' ] = 0 - idxDict['NO' ] = 0 - idxDict['no' ] = 0 - idxDict['N' ] = 0 - idxDict['n' ] = 0 + idxDict[0] = 0 + idxDict['No'] = 0 + idxDict['NO'] = 0 + idxDict['no'] = 0 + idxDict['N'] = 0 + idxDict['n'] = 0 idxDict['Yes'] = 1 idxDict['YES'] = 1 idxDict['yes'] = 1 - idxDict['Y' ] = 1 - idxDict['y' ] = 1 + idxDict['Y'] = 1 + idxDict['y'] = 1 pIndBinUnitInvest = pIndBinUnitInvest.map(idxDict) pIndBinUnitCommit = pIndBinUnitCommit.map(idxDict) pIndBinLineInvest = pIndBinLineInvest.map(idxDict) - pMustRun = pMustRun.map (idxDict) - pLineSwitching = pLineSwitching.map (idxDict) + pMustRun = pMustRun.map(idxDict) + pLineSwitching = pLineSwitching.map(idxDict) # define AC existing lines non-switchable - mTEPES.lea = Set(initialize=mTEPES.le, ordered=False, doc='AC existing lines and non-switchable lines', filter=lambda mTEPES,*le: le in mTEPES.le and pLineSwitching[le] == 0 and not pLineType[le] == 'DC') + mTEPES.lea = Set( + initialize=mTEPES.le, + ordered=False, + doc='AC existing lines and non-switchable lines', + filter=lambda mTEPES, + *le: le in mTEPES.le and pLineSwitching[le] == 0 and not pLineType[le] == 'DC') # define AC candidate lines and switchable lines - mTEPES.lca = Set(initialize=mTEPES.la, ordered=False, doc='AC candidate lines and switchable lines', filter=lambda mTEPES,*la: la in mTEPES.la and (pLineSwitching[la] == 1 or pNetFixedCost[la] > 0.0) and not pLineType[la] == 'DC') + mTEPES.lca = Set( + initialize=mTEPES.la, + ordered=False, + doc='AC candidate lines and switchable lines', + filter=lambda mTEPES, + * + la: la in mTEPES.la and ( + pLineSwitching[la] == 1 or pNetFixedCost[la] > 0.0) and not pLineType[la] == 'DC') mTEPES.laa = mTEPES.lea | mTEPES.lca # line type - pLineType = pLineType.reset_index().set_index(['level_0','level_1','level_2','LineType']) + pLineType = pLineType.reset_index().set_index( + ['level_0', 'level_1', 'level_2', 'LineType']) mTEPES.pLineType = Set(initialize=pLineType.index, doc='line type') - #%% inverse index load level to stage - pStageToLevel = pLevelToStage.reset_index().set_index('Stage').set_axis(['LoadLevel'], axis=1, inplace=False)[['LoadLevel']] - pStageToLevel = pStageToLevel.loc[pStageToLevel['LoadLevel'].isin(mTEPES.n)] - pStage2Level = pStageToLevel.reset_index().set_index(['Stage','LoadLevel']) + # %% inverse index load level to stage + pStageToLevel = pLevelToStage.reset_index().set_index('Stage').set_axis( + ['LoadLevel'], axis=1, inplace=False)[['LoadLevel']] + pStageToLevel = pStageToLevel.loc[pStageToLevel['LoadLevel'].isin( + mTEPES.n)] + pStage2Level = pStageToLevel.reset_index( + ).set_index(['Stage', 'LoadLevel']) mTEPES.s2n = Set(initialize=pStage2Level.index, doc='load level to stage') - mTEPES.pLoadLevelWeight = Param(mTEPES.n, initialize=0.0, within=NonNegativeReals, doc='Load level weight', mutable=True) - for st,n in mTEPES.s2n: + mTEPES.pLoadLevelWeight = Param( + mTEPES.n, + initialize=0.0, + within=NonNegativeReals, + doc='Load level weight', + mutable=True) + for st, n in mTEPES.s2n: mTEPES.pLoadLevelWeight[n] = pStageWeight[st] - #%% inverse index load level to switching stage - pSwStageToLevel = pSwitchingStage.reset_index().set_index('SwitchingStage').set_axis(['LoadLevel', 'InitialNode', 'FinalNode', 'Circuit'], axis=1, inplace=False)[['LoadLevel', 'InitialNode', 'FinalNode', 'Circuit']] - pSwStageToLevel = pSwStageToLevel.loc[pSwStageToLevel['LoadLevel'].isin(mTEPES.n)] - pSwStage2Level = pSwStageToLevel.reset_index().set_index(['SwitchingStage', 'LoadLevel', 'InitialNode', 'FinalNode', 'Circuit']) + # %% inverse index load level to switching stage + pSwStageToLevel = pSwitchingStage.reset_index().set_index('SwitchingStage').set_axis( + ['LoadLevel', 'InitialNode', 'FinalNode', 'Circuit'], axis=1, inplace=False)[['LoadLevel', 'InitialNode', 'FinalNode', 'Circuit']] + pSwStageToLevel = pSwStageToLevel.loc[pSwStageToLevel['LoadLevel'].isin( + mTEPES.n)] + pSwStage2Level = pSwStageToLevel.reset_index().set_index( + ['SwitchingStage', 'LoadLevel', 'InitialNode', 'FinalNode', 'Circuit']) - mTEPES.ss2n = Set(initialize=pSwStage2Level.index, doc='load level to switching stage ') + mTEPES.ss2n = Set(initialize=pSwStage2Level.index, + doc='load level to switching stage ') - #%% inverse index node to generator - pNodeToGen = pGenToNode.reset_index().set_index('Node').set_axis(['Generator'], axis=1, inplace=False)[['Generator']] + # %% inverse index node to generator + pNodeToGen = pGenToNode.reset_index().set_index('Node').set_axis( + ['Generator'], axis=1, inplace=False)[['Generator']] pNodeToGen = pNodeToGen.loc[pNodeToGen['Generator'].isin(mTEPES.g)] - pNode2Gen = pNodeToGen.reset_index().set_index(['Node', 'Generator']) + pNode2Gen = pNodeToGen.reset_index().set_index(['Node', 'Generator']) mTEPES.n2g = Set(initialize=pNode2Gen.index, doc='node to generator') - pZone2Gen = pd.DataFrame(0, dtype=int, index=pd.MultiIndex.from_tuples(mTEPES.zn*mTEPES.g, names=('Zone', 'Generator')), columns=['Y/N']) - pArea2Gen = pd.DataFrame(0, dtype=int, index=pd.MultiIndex.from_tuples(mTEPES.ar*mTEPES.g, names=('Area', 'Generator')), columns=['Y/N']) - pRegion2Gen = pd.DataFrame(0, dtype=int, index=pd.MultiIndex.from_tuples(mTEPES.rg*mTEPES.g, names=('Region', 'Generator')), columns=['Y/N']) + pZone2Gen = pd.DataFrame(0, dtype=int, index=pd.MultiIndex.from_tuples( + mTEPES.zn * mTEPES.g, names=('Zone', 'Generator')), columns=['Y/N']) + pArea2Gen = pd.DataFrame(0, dtype=int, index=pd.MultiIndex.from_tuples( + mTEPES.ar * mTEPES.g, names=('Area', 'Generator')), columns=['Y/N']) + pRegion2Gen = pd.DataFrame(0, dtype=int, index=pd.MultiIndex.from_tuples( + mTEPES.rg * mTEPES.g, names=('Region', 'Generator')), columns=['Y/N']) - for nd,g in mTEPES.n2g: + for nd, g in mTEPES.n2g: for zn in mTEPES.zn: - if (nd,zn) in mTEPES.ndzn: - pZone2Gen.loc[zn,g] = 1 + if (nd, zn) in mTEPES.ndzn: + pZone2Gen.loc[zn, g] = 1 for ar in mTEPES.ar: - if (nd,zn) in mTEPES.ndzn and (zn,ar) in mTEPES.znar: - pArea2Gen.loc[ar,g] = 1 + if (nd, zn) in mTEPES.ndzn and (zn, ar) in mTEPES.znar: + pArea2Gen.loc[ar, g] = 1 for rg in mTEPES.rg: - if (nd,zn) in mTEPES.ndzn and (zn,ar) in mTEPES.znar and (zn,rg) in mTEPES.arrg: - pRegion2Gen.loc[rg,g] = 1 - - mTEPES.z2g = Set(initialize=mTEPES.zn*mTEPES.g, doc='zone to generator', filter=lambda mTEPES,zn,g: (zn,g) in mTEPES.zn*mTEPES.g and pZone2Gen.loc [zn,g]['Y/N'] == 1) - mTEPES.a2g = Set(initialize=mTEPES.ar*mTEPES.g, doc='area to generator', filter=lambda mTEPES,ar,g: (ar,g) in mTEPES.ar*mTEPES.g and pArea2Gen.loc [ar,g]['Y/N'] == 1) - mTEPES.r2g = Set(initialize=mTEPES.rg*mTEPES.g, doc='region to generator', filter=lambda mTEPES,rg,g: (rg,g) in mTEPES.rg*mTEPES.g and pRegion2Gen.loc[rg,g]['Y/N'] == 1) - - #%% inverse index generator to technology - pTechnologyToGen = pGenToTechnology.reset_index().set_index('Technology').set_axis(['Generator'], axis=1, inplace=False)[['Generator']] - pTechnologyToGen = pTechnologyToGen.loc[pTechnologyToGen['Generator'].isin(mTEPES.g)] - pTechnology2Gen = pTechnologyToGen.reset_index().set_index(['Technology', 'Generator']) - - mTEPES.t2g = Set(initialize=pTechnology2Gen.index, doc='technology to generator') + if (nd, + zn) in mTEPES.ndzn and (zn, + ar) in mTEPES.znar and (zn, + rg) in mTEPES.arrg: + pRegion2Gen.loc[rg, g] = 1 + + mTEPES.z2g = Set(initialize=mTEPES.zn * mTEPES.g, + doc='zone to generator', + filter=lambda mTEPES, + zn, + g: (zn, + g) in mTEPES.zn * mTEPES.g and pZone2Gen.loc[zn, + g]['Y/N'] == 1) + mTEPES.a2g = Set(initialize=mTEPES.ar * mTEPES.g, + doc='area to generator', + filter=lambda mTEPES, + ar, + g: (ar, + g) in mTEPES.ar * mTEPES.g and pArea2Gen.loc[ar, + g]['Y/N'] == 1) + mTEPES.r2g = Set(initialize=mTEPES.rg * mTEPES.g, + doc='region to generator', + filter=lambda mTEPES, + rg, + g: (rg, + g) in mTEPES.rg * mTEPES.g and pRegion2Gen.loc[rg, + g]['Y/N'] == 1) + + # %% inverse index generator to technology + pTechnologyToGen = pGenToTechnology.reset_index().set_index( + 'Technology').set_axis(['Generator'], axis=1, inplace=False)[['Generator']] + pTechnologyToGen = pTechnologyToGen.loc[pTechnologyToGen['Generator'].isin( + mTEPES.g)] + pTechnology2Gen = pTechnologyToGen.reset_index( + ).set_index(['Technology', 'Generator']) + + mTEPES.t2g = Set( + initialize=pTechnology2Gen.index, + doc='technology to generator') # minimum and maximum variable power - pVariableMinPower = pVariableMinPower.replace(0.0, float('nan')) - pVariableMaxPower = pVariableMaxPower.replace(0.0, float('nan')) - pMinPower = pd.DataFrame([pRatedMinPower]*len(pVariableMinPower.index), index=pd.MultiIndex.from_tuples(pVariableMinPower.index), columns=pRatedMinPower.index) - pMaxPower = pd.DataFrame([pRatedMaxPower]*len(pVariableMaxPower.index), index=pd.MultiIndex.from_tuples(pVariableMaxPower.index), columns=pRatedMaxPower.index) - pMinPower = pMinPower.reindex (sorted(pMinPower.columns ), axis=1) - pMaxPower = pMaxPower.reindex (sorted(pMaxPower.columns ), axis=1) - pVariableMinPower = pVariableMinPower.reindex(sorted(pVariableMinPower.columns), axis=1) - pVariableMaxPower = pVariableMaxPower.reindex(sorted(pVariableMaxPower.columns), axis=1) - pMinPower = pVariableMinPower.where (pVariableMinPower > pMinPower, other=pMinPower) - pMaxPower = pVariableMaxPower.where (pVariableMaxPower < pMaxPower, other=pMaxPower) + pVariableMinPower = pVariableMinPower.replace(0.0, float('nan')) + pVariableMaxPower = pVariableMaxPower.replace(0.0, float('nan')) + pMinPower = pd.DataFrame( + [pRatedMinPower] * len( + pVariableMinPower.index), + index=pd.MultiIndex.from_tuples( + pVariableMinPower.index), + columns=pRatedMinPower.index) + pMaxPower = pd.DataFrame( + [pRatedMaxPower] * len( + pVariableMaxPower.index), + index=pd.MultiIndex.from_tuples( + pVariableMaxPower.index), + columns=pRatedMaxPower.index) + pMinPower = pMinPower.reindex(sorted(pMinPower.columns), axis=1) + pMaxPower = pMaxPower.reindex(sorted(pMaxPower.columns), axis=1) + pVariableMinPower = pVariableMinPower.reindex( + sorted(pVariableMinPower.columns), axis=1) + pVariableMaxPower = pVariableMaxPower.reindex( + sorted(pVariableMaxPower.columns), axis=1) + pMinPower = pVariableMinPower.where( + pVariableMinPower > pMinPower, other=pMinPower) + pMaxPower = pVariableMaxPower.where( + pVariableMaxPower < pMaxPower, other=pMaxPower) # minimum and maximum variable charge - pVariableMinCharge = pVariableMinCharge.replace(0.0, float('nan')) - pVariableMaxCharge = pVariableMaxCharge.replace(0.0, float('nan')) - pMinCharge = pd.DataFrame([pRatedMinCharge]*len(pVariableMinCharge.index), index=pd.MultiIndex.from_tuples(pVariableMinCharge.index), columns=pRatedMinCharge.index) - pMaxCharge = pd.DataFrame([pRatedMaxCharge]*len(pVariableMaxCharge.index), index=pd.MultiIndex.from_tuples(pVariableMaxCharge.index), columns=pRatedMaxCharge.index) - pMinCharge = pMinCharge.reindex (sorted(pMinCharge.columns ), axis=1) - pMaxCharge = pMaxCharge.reindex (sorted(pMaxCharge.columns ), axis=1) - pVariableMinCharge = pVariableMinCharge.reindex(sorted(pVariableMinCharge.columns), axis=1) - pVariableMaxCharge = pVariableMaxCharge.reindex(sorted(pVariableMaxCharge.columns), axis=1) - pMinCharge = pVariableMinCharge.where (pVariableMinCharge > pMinCharge, other=pMinCharge) - pMaxCharge = pVariableMaxCharge.where (pVariableMaxCharge < pMaxCharge, other=pMaxCharge) + pVariableMinCharge = pVariableMinCharge.replace(0.0, float('nan')) + pVariableMaxCharge = pVariableMaxCharge.replace(0.0, float('nan')) + pMinCharge = pd.DataFrame( + [pRatedMinCharge] * len( + pVariableMinCharge.index), + index=pd.MultiIndex.from_tuples( + pVariableMinCharge.index), + columns=pRatedMinCharge.index) + pMaxCharge = pd.DataFrame( + [pRatedMaxCharge] * len( + pVariableMaxCharge.index), + index=pd.MultiIndex.from_tuples( + pVariableMaxCharge.index), + columns=pRatedMaxCharge.index) + pMinCharge = pMinCharge.reindex(sorted(pMinCharge.columns), axis=1) + pMaxCharge = pMaxCharge.reindex(sorted(pMaxCharge.columns), axis=1) + pVariableMinCharge = pVariableMinCharge.reindex( + sorted(pVariableMinCharge.columns), axis=1) + pVariableMaxCharge = pVariableMaxCharge.reindex( + sorted(pVariableMaxCharge.columns), axis=1) + pMinCharge = pVariableMinCharge.where( + pVariableMinCharge > pMinCharge, other=pMinCharge) + pMaxCharge = pVariableMaxCharge.where( + pVariableMaxCharge < pMaxCharge, other=pMaxCharge) # minimum and maximum variable storage capacity pVariableMinStorage = pVariableMinStorage.replace(0.0, float('nan')) pVariableMaxStorage = pVariableMaxStorage.replace(0.0, float('nan')) - pMinStorage = pd.DataFrame([pRatedMinStorage]*len(pVariableMinStorage.index), index=pd.MultiIndex.from_tuples(pVariableMinStorage.index), columns=pRatedMinStorage.index) - pMaxStorage = pd.DataFrame([pRatedMaxStorage]*len(pVariableMaxStorage.index), index=pd.MultiIndex.from_tuples(pVariableMaxStorage.index), columns=pRatedMaxStorage.index) - pMinStorage = pMinStorage.reindex (sorted(pMinStorage.columns ), axis=1) - pMaxStorage = pMaxStorage.reindex (sorted(pMaxStorage.columns ), axis=1) - pVariableMinStorage = pVariableMinStorage.reindex(sorted(pVariableMinStorage.columns), axis=1) - pVariableMaxStorage = pVariableMaxStorage.reindex(sorted(pVariableMaxStorage.columns), axis=1) - pMinStorage = pVariableMinStorage.where (pVariableMinStorage > pMinStorage, other=pMinStorage) - pMaxStorage = pVariableMaxStorage.where (pVariableMaxStorage < pMaxStorage, other=pMaxStorage) + pMinStorage = pd.DataFrame( + [pRatedMinStorage] * len( + pVariableMinStorage.index), + index=pd.MultiIndex.from_tuples( + pVariableMinStorage.index), + columns=pRatedMinStorage.index) + pMaxStorage = pd.DataFrame( + [pRatedMaxStorage] * len( + pVariableMaxStorage.index), + index=pd.MultiIndex.from_tuples( + pVariableMaxStorage.index), + columns=pRatedMaxStorage.index) + pMinStorage = pMinStorage.reindex(sorted(pMinStorage.columns), axis=1) + pMaxStorage = pMaxStorage.reindex(sorted(pMaxStorage.columns), axis=1) + pVariableMinStorage = pVariableMinStorage.reindex( + sorted(pVariableMinStorage.columns), axis=1) + pVariableMaxStorage = pVariableMaxStorage.reindex( + sorted(pVariableMaxStorage.columns), axis=1) + pMinStorage = pVariableMinStorage.where( + pVariableMinStorage > pMinStorage, other=pMinStorage) + pMaxStorage = pVariableMaxStorage.where( + pVariableMaxStorage < pMaxStorage, other=pMaxStorage) # parameter that allows the initial inventory to change with load level - pIniInventory = pd.DataFrame([pInitialInventory]*len(pVariableMinStorage.index), index=pd.MultiIndex.from_tuples(pVariableMinStorage.index), columns=pInitialInventory.index) + pIniInventory = pd.DataFrame( + [pInitialInventory] * len( + pVariableMinStorage.index), + index=pd.MultiIndex.from_tuples( + pVariableMinStorage.index), + columns=pInitialInventory.index) # initial inventory must be between minimum and maximum # pIniInventory = pMinStorage.where(pMinStorage > pIniInventory, other=pIniInventory) # pIniInventory = pMaxStorage.where(pMaxStorage < pIniInventory, other=pIniInventory) # minimum up and down time converted to an integer number of time steps - pUpTime = round(pUpTime/pTimeStep).astype('int') - pDwTime = round(pDwTime/pTimeStep).astype('int') + pUpTime = round(pUpTime / pTimeStep).astype('int') + pDwTime = round(pDwTime / pTimeStep).astype('int') - #%% definition of the time-steps leap to observe the stored energy at ESS - pCycleTimeStep = (pUpTime*0).astype('int') - pOutflowsTimeStep = (pUpTime*0).astype('int') + # %% definition of the time-steps leap to observe the stored energy at ESS + pCycleTimeStep = (pUpTime * 0).astype('int') + pOutflowsTimeStep = (pUpTime * 0).astype('int') for es in mTEPES.es: - if pStorageType [es] == 'Daily' : - pCycleTimeStep[es] = 1 - if pStorageType [es] == 'Weekly' : - pCycleTimeStep[es] = int( 24/pTimeStep) - if pStorageType [es] == 'Monthly': - pCycleTimeStep[es] = int(168/pTimeStep) - - if pOutflowsType [es] == 'Hourly' : - pOutflowsTimeStep[es] = 1 - if pOutflowsType [es] == 'Daily' : - pOutflowsTimeStep[es] = 24/pTimeStep - if pOutflowsType [es] == 'Weekly' : - pOutflowsTimeStep[es] = 168/pTimeStep - if pOutflowsType [es] == 'Monthly': - pOutflowsTimeStep[es] = 672/pTimeStep - if pOutflowsType [es] == 'Yearly' : - pOutflowsTimeStep[es] = 8736/pTimeStep + if pStorageType[es] == 'Daily': + pCycleTimeStep[es] = 1 + if pStorageType[es] == 'Weekly': + pCycleTimeStep[es] = int(24 / pTimeStep) + if pStorageType[es] == 'Monthly': + pCycleTimeStep[es] = int(168 / pTimeStep) + + if pOutflowsType[es] == 'Hourly': + pOutflowsTimeStep[es] = 1 + if pOutflowsType[es] == 'Daily': + pOutflowsTimeStep[es] = 24 / pTimeStep + if pOutflowsType[es] == 'Weekly': + pOutflowsTimeStep[es] = 168 / pTimeStep + if pOutflowsType[es] == 'Monthly': + pOutflowsTimeStep[es] = 672 / pTimeStep + if pOutflowsType[es] == 'Yearly': + pOutflowsTimeStep[es] = 8736 / pTimeStep pCycleTimeStep[es] = min(pCycleTimeStep[es], pOutflowsTimeStep[es]) @@ -470,411 +1089,1248 @@ def InputData(DirName, CaseName, mTEPES): # pStageDuration = max(pStageDuration, pCycleTimeStep.max(), pOutflowsTimeStep.max()) # drop load levels with duration 0 - pDuration = pDuration.loc [ mTEPES.n ] - pDemand = pDemand.loc [mTEPES.sc*mTEPES.p*mTEPES.n ] - pSystemInertia = pSystemInertia.loc [mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.ar] - pOperReserveUp = pOperReserveUp.loc [mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.ar] - pOperReserveDw = pOperReserveDw.loc [mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.ar] - pMinPower = pMinPower.loc [mTEPES.sc*mTEPES.p*mTEPES.n ] - pMaxPower = pMaxPower.loc [mTEPES.sc*mTEPES.p*mTEPES.n ] - pMinCharge = pMinCharge.loc [mTEPES.sc*mTEPES.p*mTEPES.n ] - pMaxCharge = pMaxCharge.loc [mTEPES.sc*mTEPES.p*mTEPES.n ] - pEnergyInflows = pEnergyInflows.loc [mTEPES.sc*mTEPES.p*mTEPES.n ] - pEnergyOutflows = pEnergyOutflows.loc [mTEPES.sc*mTEPES.p*mTEPES.n ] - pMinStorage = pMinStorage.loc [mTEPES.sc*mTEPES.p*mTEPES.n ] - pMaxStorage = pMaxStorage.loc [mTEPES.sc*mTEPES.p*mTEPES.n ] - pIniInventory = pIniInventory.loc [mTEPES.sc*mTEPES.p*mTEPES.n ] + pDuration = pDuration.loc[mTEPES.n] + pDemand = pDemand.loc[mTEPES.sc * mTEPES.p * mTEPES.n] + pSystemInertia = pSystemInertia.loc[mTEPES.sc * + mTEPES.p * mTEPES.n * mTEPES.ar] + pOperReserveUp = pOperReserveUp.loc[mTEPES.sc * + mTEPES.p * mTEPES.n * mTEPES.ar] + pOperReserveDw = pOperReserveDw.loc[mTEPES.sc * + mTEPES.p * mTEPES.n * mTEPES.ar] + pMinPower = pMinPower.loc[mTEPES.sc * mTEPES.p * mTEPES.n] + pMaxPower = pMaxPower.loc[mTEPES.sc * mTEPES.p * mTEPES.n] + pMinCharge = pMinCharge.loc[mTEPES.sc * mTEPES.p * mTEPES.n] + pMaxCharge = pMaxCharge.loc[mTEPES.sc * mTEPES.p * mTEPES.n] + pEnergyInflows = pEnergyInflows.loc[mTEPES.sc * mTEPES.p * mTEPES.n] + pEnergyOutflows = pEnergyOutflows.loc[mTEPES.sc * mTEPES.p * mTEPES.n] + pMinStorage = pMinStorage.loc[mTEPES.sc * mTEPES.p * mTEPES.n] + pMaxStorage = pMaxStorage.loc[mTEPES.sc * mTEPES.p * mTEPES.n] + pIniInventory = pIniInventory.loc[mTEPES.sc * mTEPES.p * mTEPES.n] # small values are converted to 0 pPeakDemand = pd.Series(data=[0.0 for ar in mTEPES.ar], index=mTEPES.ar) for a2 in mTEPES.ar: - # 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 - pPeakDemand[a2] = pDemand [[nd for nd,a2 in mTEPES.ndar]].sum(axis=1).max() - pEpsilon = pPeakDemand[a2]*2.5e-5 + # 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 + pPeakDemand[a2] = pDemand[[nd for nd, + a2 in mTEPES.ndar]].sum(axis=1).max() + pEpsilon = pPeakDemand[a2] * 2.5e-5 # values < 1e-5 times the maximum system demand are converted to 0 # pEpsilon = pDemand.sum(axis=1).max()*1e-5 # these parameters are in GW - pDemand [pDemand [[nd for nd,a2 in mTEPES.ndar]] < pEpsilon] = 0.0 - pSystemInertia [pSystemInertia [[ a2]] < pEpsilon] = 0.0 - pOperReserveUp [pOperReserveUp [[ a2]] < pEpsilon] = 0.0 - pOperReserveDw [pOperReserveDw [[ a2]] < pEpsilon] = 0.0 - pMinPower [pMinPower [[g for a2,g in mTEPES.a2g ]] < pEpsilon] = 0.0 - pMaxPower [pMaxPower [[g for a2,g in mTEPES.a2g ]] < pEpsilon] = 0.0 - pMinCharge [pMinCharge [[es for a2,es in mTEPES.a2g ]] < pEpsilon] = 0.0 - pMaxCharge [pMaxCharge [[es for a2,es in mTEPES.a2g ]] < pEpsilon] = 0.0 - pEnergyInflows [pEnergyInflows [[es for a2,es in mTEPES.a2g ]] < pEpsilon/pTimeStep] = 0.0 - pEnergyOutflows[pEnergyOutflows[[es for a2,es in mTEPES.a2g ]] < pEpsilon/pTimeStep] = 0.0 + pDemand[pDemand[[nd for nd, a2 in mTEPES.ndar]] < pEpsilon] = 0.0 + pSystemInertia[pSystemInertia[[a2]] < pEpsilon] = 0.0 + pOperReserveUp[pOperReserveUp[[a2]] < pEpsilon] = 0.0 + pOperReserveDw[pOperReserveDw[[a2]] < pEpsilon] = 0.0 + pMinPower[pMinPower[[g for a2, g in mTEPES.a2g]] < pEpsilon] = 0.0 + pMaxPower[pMaxPower[[g for a2, g in mTEPES.a2g]] < pEpsilon] = 0.0 + pMinCharge[pMinCharge[[es for a2, es in mTEPES.a2g]] < pEpsilon] = 0.0 + pMaxCharge[pMaxCharge[[es for a2, es in mTEPES.a2g]] < pEpsilon] = 0.0 + pEnergyInflows[pEnergyInflows[[es for a2, es in mTEPES.a2g]] + < pEpsilon / pTimeStep] = 0.0 + pEnergyOutflows[pEnergyOutflows[[es for a2, + es in mTEPES.a2g]] < pEpsilon / pTimeStep] = 0.0 # these parameters are in GWh - pMinStorage [pMinStorage [[es for a2,es in mTEPES.a2g ]] < pEpsilon] = 0.0 - pMaxStorage [pMaxStorage [[es for a2,es in mTEPES.a2g ]] < pEpsilon] = 0.0 - pIniInventory [pIniInventory [[es for a2,es in mTEPES.a2g ]] < pEpsilon] = 0.0 + pMinStorage[pMinStorage[[es for a2, es in mTEPES.a2g]] < pEpsilon] = 0.0 + pMaxStorage[pMaxStorage[[es for a2, es in mTEPES.a2g]] < pEpsilon] = 0.0 + pIniInventory[pIniInventory[[es for a2, + es in mTEPES.a2g]] < pEpsilon] = 0.0 # these parameters are in GW - for ni,nf,cc,a2 in mTEPES.laar: - if pLineNTCFrw[ni,nf,cc] < pEpsilon: - pLineNTCFrw[ni,nf,cc] = 0.0 - if pLineNTCBck[ni,nf,cc] < pEpsilon: - pLineNTCBck[ni,nf,cc] = 0.0 - for a2,es in mTEPES.a2g: - if pInitialInventory[es] < pEpsilon and es in mTEPES.es: + for ni, nf, cc, a2 in mTEPES.laar: + if pLineNTCFrw[ni, nf, cc] < pEpsilon: + pLineNTCFrw[ni, nf, cc] = 0.0 + if pLineNTCBck[ni, nf, cc] < pEpsilon: + pLineNTCBck[ni, nf, cc] = 0.0 + for a2, es in mTEPES.a2g: + if pInitialInventory[es] < pEpsilon and es in mTEPES.es: pInitialInventory[es] = 0.0 - pMaxPower2ndBlock = pMaxPower - pMinPower + pMaxPower2ndBlock = pMaxPower - pMinPower pMaxCharge2ndBlock = pMaxCharge - pMinCharge - pMaxPower2ndBlock [pMaxPower2ndBlock [[es for a2, es in mTEPES.a2g]] < pEpsilon] = 0.0 - pMaxCharge2ndBlock[pMaxCharge2ndBlock[[es for a2, es in mTEPES.a2g]] < pEpsilon] = 0.0 + pMaxPower2ndBlock[pMaxPower2ndBlock[[ + es for a2, es in mTEPES.a2g]] < pEpsilon] = 0.0 + pMaxCharge2ndBlock[pMaxCharge2ndBlock[[ + es for a2, es in mTEPES.a2g]] < pEpsilon] = 0.0 # replace < 0.0 by 0.0 - pMaxPower2ndBlock = pMaxPower2ndBlock.where (pMaxPower2ndBlock > 0.0, other=0.0) - pMaxCharge2ndBlock = pMaxCharge2ndBlock.where(pMaxCharge2ndBlock > 0.0, other=0.0) - - # BigM maximum flow to be used in the Kirchhoff's 2nd law disjunctive constraint - pBigMFlowBck = pLineNTCBck*0.0 - pBigMFlowFrw = pLineNTCFrw*0.0 + pMaxPower2ndBlock = pMaxPower2ndBlock.where( + pMaxPower2ndBlock > 0.0, other=0.0) + pMaxCharge2ndBlock = pMaxCharge2ndBlock.where( + pMaxCharge2ndBlock > 0.0, other=0.0) + + # BigM maximum flow to be used in the Kirchhoff's 2nd law disjunctive + # constraint + pBigMFlowBck = pLineNTCBck * 0.0 + pBigMFlowFrw = pLineNTCFrw * 0.0 for lea in mTEPES.lea: pBigMFlowBck.loc[lea] = pLineNTCBck[lea] pBigMFlowFrw.loc[lea] = pLineNTCFrw[lea] for lca in mTEPES.lca: - pBigMFlowBck.loc[lca] = pLineNTCBck[lca]*1.5 - pBigMFlowFrw.loc[lca] = pLineNTCFrw[lca]*1.5 + pBigMFlowBck.loc[lca] = pLineNTCBck[lca] * 1.5 + pBigMFlowFrw.loc[lca] = pLineNTCFrw[lca] * 1.5 # maximum voltage angle - pMaxTheta = pDemand*0.0 + math.pi/2 - pMaxTheta = pMaxTheta.loc[mTEPES.sc*mTEPES.p*mTEPES.n] + pMaxTheta = pDemand * 0.0 + math.pi / 2 + pMaxTheta = pMaxTheta.loc[mTEPES.sc * mTEPES.p * mTEPES.n] # this option avoids a warning in the following assignments pd.options.mode.chained_assignment = None # %% parameters - mTEPES.pIndBinGenInvest = Param(initialize=pIndBinGenInvest , within=Boolean, doc='Indicator of binary generation investment decisions', mutable=True) - mTEPES.pIndBinGenOperat = Param(initialize=pIndBinGenOperat , within=Boolean, doc='Indicator of binary generation operation decisions', mutable=True) - mTEPES.pIndBinNetInvest = Param(initialize=pIndBinNetInvest , within=Boolean, doc='Indicator of binary network investment decisions', mutable=True) - mTEPES.pIndBinLineCommit = Param(initialize=pIndBinLineCommit , within=Boolean, doc='Indicator of binary network switching decisions', mutable=True) - mTEPES.pIndSwitchingStage = Param(initialize=pIndSwitchingStage , within=Boolean, doc='Indicator to use switching stages', mutable=True) - mTEPES.pIndNetLosses = Param(initialize=pIndNetLosses , within=Boolean, doc='Indicator of binary network ohmic losses', mutable=True) - - mTEPES.pENSCost = Param(initialize=pENSCost , within=NonNegativeReals) - mTEPES.pCO2Cost = Param(initialize=pCO2Cost , within=NonNegativeReals) - mTEPES.pUpReserveActivation = Param(initialize=pUpReserveActivation , within=NonNegativeReals) - mTEPES.pDwReserveActivation = Param(initialize=pDwReserveActivation , within=NonNegativeReals) - mTEPES.pSBase = Param(initialize=pSBase , within=NonNegativeReals) - mTEPES.pTimeStep = Param(initialize=pTimeStep , within=NonNegativeReals) + mTEPES.pIndBinGenInvest = Param( + initialize=pIndBinGenInvest, + within=Boolean, + doc='Indicator of binary generation investment decisions', + mutable=True) + mTEPES.pIndBinGenOperat = Param( + initialize=pIndBinGenOperat, + within=Boolean, + doc='Indicator of binary generation operation decisions', + mutable=True) + mTEPES.pIndBinNetInvest = Param( + initialize=pIndBinNetInvest, + within=Boolean, + doc='Indicator of binary network investment decisions', + mutable=True) + mTEPES.pIndBinLineCommit = Param( + initialize=pIndBinLineCommit, + within=Boolean, + doc='Indicator of binary network switching decisions', + mutable=True) + mTEPES.pIndSwitchingStage = Param( + initialize=pIndSwitchingStage, + within=Boolean, + doc='Indicator to use switching stages', + mutable=True) + mTEPES.pIndNetLosses = Param( + initialize=pIndNetLosses, + within=Boolean, + doc='Indicator of binary network ohmic losses', + mutable=True) + + mTEPES.pENSCost = Param(initialize=pENSCost, within=NonNegativeReals) + mTEPES.pCO2Cost = Param(initialize=pCO2Cost, within=NonNegativeReals) + mTEPES.pUpReserveActivation = Param( + initialize=pUpReserveActivation, + within=NonNegativeReals) + mTEPES.pDwReserveActivation = Param( + initialize=pDwReserveActivation, + within=NonNegativeReals) + mTEPES.pSBase = Param(initialize=pSBase, within=NonNegativeReals) + mTEPES.pTimeStep = Param(initialize=pTimeStep, within=NonNegativeReals) # mTEPES.pStageDuration = Param(initialize=pStageDuration , within=NonNegativeReals) - mTEPES.pReserveMargin = Param( mTEPES.ar, initialize=pReserveMargin.to_dict() , within=NonNegativeReals, doc='Adequacy reserve margin' ) - mTEPES.pPeakDemand = Param( mTEPES.ar, initialize=pPeakDemand.to_dict() , within=NonNegativeReals, doc='Peak demand' ) - mTEPES.pDemand = Param(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.nd, initialize=pDemand.stack().to_dict() , within=NonNegativeReals, doc='Demand' ) - mTEPES.pScenProb = Param(mTEPES.scc, initialize=pScenProb.to_dict() , within=NonNegativeReals, doc='Probability' ) - mTEPES.pStageWeight = Param(mTEPES.stt, initialize=pStageWeight.to_dict() , within=NonNegativeReals, doc='Stage weight' ) - mTEPES.pDuration = Param( mTEPES.n, initialize=pDuration.to_dict() , within=NonNegativeReals, doc='Duration' ) - mTEPES.pNodeLon = Param( mTEPES.nd, initialize=pNodeLon.to_dict() , doc='Longitude' ) - mTEPES.pNodeLat = Param( mTEPES.nd, initialize=pNodeLat.to_dict() , doc='Latitude' ) - mTEPES.pSystemInertia = Param(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.ar, initialize=pSystemInertia.stack().to_dict() , within=NonNegativeReals, doc='System inertia' ) - mTEPES.pOperReserveUp = Param(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.ar, initialize=pOperReserveUp.stack().to_dict() , within=NonNegativeReals, doc='Upward operating reserve' ) - mTEPES.pOperReserveDw = Param(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.ar, initialize=pOperReserveDw.stack().to_dict() , within=NonNegativeReals, doc='Downward operating reserve' ) - mTEPES.pMinPower = Param(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.gg, initialize=pMinPower.stack().to_dict() , within=NonNegativeReals, doc='Minimum power' ) - mTEPES.pMaxPower = Param(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.gg, initialize=pMaxPower.stack().to_dict() , within=NonNegativeReals, doc='Maximum power' ) - mTEPES.pMinCharge = Param(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.gg, initialize=pMinCharge.stack().to_dict() , within=NonNegativeReals, doc='Minimum charge' ) - mTEPES.pMaxCharge = Param(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.gg, initialize=pMaxCharge.stack().to_dict() , within=NonNegativeReals, doc='Maximum charge' ) - mTEPES.pMaxPower2ndBlock = Param(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.gg, initialize=pMaxPower2ndBlock.stack().to_dict() , within=NonNegativeReals, doc='Second block power' ) - mTEPES.pMaxCharge2ndBlock = Param(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.gg, initialize=pMaxCharge2ndBlock.stack().to_dict(), within=NonNegativeReals, doc='Second block charge' ) - mTEPES.pEnergyInflows = Param(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.gg, initialize=pEnergyInflows.stack().to_dict() , within=NonNegativeReals, doc='Energy inflows' ) - mTEPES.pEnergyOutflows = Param(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.gg, initialize=pEnergyOutflows.stack().to_dict() , within=NonNegativeReals, doc='Energy outflows' ) - mTEPES.pMinStorage = Param(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.gg, initialize=pMinStorage.stack().to_dict() , within=NonNegativeReals, doc='ESS Minimum stoarage capacity') - mTEPES.pMaxStorage = Param(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.gg, initialize=pMaxStorage.stack().to_dict() , within=NonNegativeReals, doc='ESS Maximum stoarage capacity') - mTEPES.pRatedMaxPower = Param( mTEPES.gg, initialize=pRatedMaxPower.to_dict() , within=NonNegativeReals, doc='Rated maximum power' ) - mTEPES.pMustRun = Param( mTEPES.gg, initialize=pMustRun.to_dict() , within=Boolean , doc='must-run unit' ) - mTEPES.pInertia = Param( mTEPES.gg, initialize=pInertia.to_dict() , within=NonNegativeReals, doc='unit inertia constant' ) - mTEPES.pAvailability = Param( mTEPES.gg, initialize=pAvailability.to_dict() , within=NonNegativeReals, doc='unit availability', mutable=True) - mTEPES.pEFOR = Param( mTEPES.gg, initialize=pEFOR.to_dict() , within=NonNegativeReals, doc='EFOR' ) - mTEPES.pLinearOperCost = Param( mTEPES.gg, initialize=pLinearOperCost.to_dict() , within=NonNegativeReals, doc='Linear variable cost' ) - mTEPES.pLinearVarCost = Param( mTEPES.gg, initialize=pLinearVarCost.to_dict() , within=NonNegativeReals, doc='Linear variable cost' ) - mTEPES.pLinearOMCost = Param( mTEPES.gg, initialize=pLinearOMCost.to_dict() , within=NonNegativeReals, doc='Linear O&M cost' ) - mTEPES.pConstantVarCost = Param( mTEPES.gg, initialize=pConstantVarCost.to_dict() , within=NonNegativeReals, doc='Constant variable cost' ) - mTEPES.pCO2EmissionCost = Param( mTEPES.gg, initialize=pCO2EmissionCost.to_dict() , within=NonNegativeReals, doc='CO2 Emission cost' ) - mTEPES.pStartUpCost = Param( mTEPES.gg, initialize=pStartUpCost.to_dict() , within=NonNegativeReals, doc='Startup cost' ) - mTEPES.pShutDownCost = Param( mTEPES.gg, initialize=pShutDownCost.to_dict() , within=NonNegativeReals, doc='Shutdown cost' ) - mTEPES.pRampUp = Param( mTEPES.gg, initialize=pRampUp.to_dict() , within=NonNegativeReals, doc='Ramp up rate' ) - mTEPES.pRampDw = Param( mTEPES.gg, initialize=pRampDw.to_dict() , within=NonNegativeReals, doc='Ramp down rate' ) - mTEPES.pUpTime = Param( mTEPES.gg, initialize=pUpTime.to_dict() , within=NonNegativeReals, doc='Up time' ) - mTEPES.pDwTime = Param( mTEPES.gg, initialize=pDwTime.to_dict() , within=NonNegativeReals, doc='Down time' ) - mTEPES.pRatedMaxCharge = Param( mTEPES.gg, initialize=pRatedMaxCharge.to_dict() , within=NonNegativeReals, doc='Rated maximum charge' ) - mTEPES.pGenFixedCost = Param( mTEPES.gg, initialize=pGenFixedCost.to_dict() , within=NonNegativeReals, doc='Generation fixed cost' ) - mTEPES.pIndBinUnitInvest = Param( mTEPES.gg, initialize=pIndBinUnitInvest.to_dict() , within=Boolean , doc='Binary investment decision' ) - mTEPES.pIndBinUnitCommit = Param( mTEPES.gg, initialize=pIndBinUnitCommit.to_dict() , within=Boolean , doc='Binary commitment decision' ) - mTEPES.pEfficiency = Param( mTEPES.gg, initialize=pEfficiency.to_dict() , within=NonNegativeReals, doc='Round-trip efficiency' ) - mTEPES.pCycleTimeStep = Param( mTEPES.gg, initialize=pCycleTimeStep.to_dict() , within=NonNegativeReals, doc='ESS Storage cycle' ) - mTEPES.pOutflowsTimeStep = Param( mTEPES.gg, initialize=pOutflowsTimeStep.to_dict() , within=NonNegativeReals, doc='ESS Outflows cycle' ) - mTEPES.pIniInventory = Param(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.gg, initialize=pIniInventory.stack().to_dict() , within=NonNegativeReals, doc='ESS Initial storage', mutable=True) - mTEPES.pInitialInventory = Param( mTEPES.gg, initialize=pInitialInventory.to_dict() , within=NonNegativeReals, doc='ESS Initial storage without loadlevels' ) - mTEPES.pStorageType = Param( mTEPES.gg, initialize=pStorageType.to_dict() , within=Any , doc='ESS Storage type' ) - - mTEPES.pLineLossFactor = Param( mTEPES.ln, initialize=pLineLossFactor.to_dict() , within=NonNegativeReals, doc='Loss factor' ) - mTEPES.pLineR = Param( mTEPES.ln, initialize=pLineR.to_dict() , within=NonNegativeReals, doc='Resistance' ) - mTEPES.pLineX = Param( mTEPES.ln, initialize=pLineX.to_dict() , within=NonNegativeReals, doc='Reactance' ) - mTEPES.pLineBsh = Param( mTEPES.ln, initialize=pLineBsh.to_dict() , within=NonNegativeReals, doc='Susceptance', mutable=True) - mTEPES.pLineTAP = Param( mTEPES.ln, initialize=pLineTAP.to_dict() , within=NonNegativeReals, doc='Tap changer', mutable=True) - mTEPES.pConverter = Param( mTEPES.ln, initialize=pConverter.to_dict() , within=NonNegativeReals, doc='Converter' ) - mTEPES.pLineLength = Param( mTEPES.ln, initialize=pLineLength.to_dict() , within=NonNegativeReals, doc='Length', mutable=True) - mTEPES.pLineVoltage = Param( mTEPES.ln, initialize=pLineVoltage.to_dict() , within=NonNegativeReals, doc='Voltage' ) - mTEPES.pLineNTCFrw = Param( mTEPES.ln, initialize=pLineNTCFrw.to_dict() , within=NonNegativeReals, doc='NTC forward' ) - mTEPES.pLineNTCBck = Param( mTEPES.ln, initialize=pLineNTCBck.to_dict() , within=NonNegativeReals, doc='NTC backward' ) - mTEPES.pNetFixedCost = Param( mTEPES.ln, initialize=pNetFixedCost.to_dict() , within=NonNegativeReals, doc='Network fixed cost' ) - mTEPES.pIndBinLineInvest = Param( mTEPES.ln, initialize=pIndBinLineInvest.to_dict() , within=Boolean , doc='Binary investment decision' ) - mTEPES.pSwOnTime = Param( mTEPES.ln, initialize=pSwitchOnTime.to_dict() , within=NonNegativeReals, doc='Minimum switching on time' ) - mTEPES.pSwOffTime = Param( mTEPES.ln, initialize=pSwitchOffTime.to_dict() , within=NonNegativeReals, doc='Minimum switching off time' ) - mTEPES.pLineSwitching = Param( mTEPES.ln, initialize=pLineSwitching.to_dict() , within=Boolean , doc='Switching decision' ) - mTEPES.pBigMFlowBck = Param( mTEPES.ln, initialize=pBigMFlowBck.to_dict() , within=NonNegativeReals, doc='Maximum backward capacity', mutable=True) - mTEPES.pBigMFlowFrw = Param( mTEPES.ln, initialize=pBigMFlowFrw.to_dict() , within=NonNegativeReals, doc='Maximum forward capacity', mutable=True) - mTEPES.pMaxTheta = Param(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.nd, initialize=pMaxTheta.stack().to_dict() , within=NonNegativeReals, doc='Maximum voltage angle', mutable=True) - mTEPES.pAngMin = Param( mTEPES.ln, initialize=pAngMin.to_dict() , within=Reals, doc='Minimum phase angle diff', mutable=True) - mTEPES.pAngMax = Param( mTEPES.ln, initialize=pAngMax.to_dict() , within=Reals, doc='Maximum phase angle diff', mutable=True) + mTEPES.pReserveMargin = Param( + mTEPES.ar, + initialize=pReserveMargin.to_dict(), + within=NonNegativeReals, + doc='Adequacy reserve margin') + mTEPES.pPeakDemand = Param( + mTEPES.ar, + initialize=pPeakDemand.to_dict(), + within=NonNegativeReals, + doc='Peak demand') + mTEPES.pDemand = Param( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.nd, + initialize=pDemand.stack().to_dict(), + within=NonNegativeReals, + doc='Demand') + mTEPES.pScenProb = Param( + mTEPES.scc, + initialize=pScenProb.to_dict(), + within=NonNegativeReals, + doc='Probability') + mTEPES.pStageWeight = Param( + mTEPES.stt, + initialize=pStageWeight.to_dict(), + within=NonNegativeReals, + doc='Stage weight') + mTEPES.pDuration = Param( + mTEPES.n, + initialize=pDuration.to_dict(), + within=NonNegativeReals, + doc='Duration') + mTEPES.pNodeLon = Param( + mTEPES.nd, + initialize=pNodeLon.to_dict(), + doc='Longitude') + mTEPES.pNodeLat = Param( + mTEPES.nd, + initialize=pNodeLat.to_dict(), + doc='Latitude') + mTEPES.pSystemInertia = Param( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.ar, + initialize=pSystemInertia.stack().to_dict(), + within=NonNegativeReals, + doc='System inertia') + mTEPES.pOperReserveUp = Param( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.ar, + initialize=pOperReserveUp.stack().to_dict(), + within=NonNegativeReals, + doc='Upward operating reserve') + mTEPES.pOperReserveDw = Param( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.ar, + initialize=pOperReserveDw.stack().to_dict(), + within=NonNegativeReals, + doc='Downward operating reserve') + mTEPES.pMinPower = Param( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.gg, + initialize=pMinPower.stack().to_dict(), + within=NonNegativeReals, + doc='Minimum power') + mTEPES.pMaxPower = Param( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.gg, + initialize=pMaxPower.stack().to_dict(), + within=NonNegativeReals, + doc='Maximum power') + mTEPES.pMinCharge = Param( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.gg, + initialize=pMinCharge.stack().to_dict(), + within=NonNegativeReals, + doc='Minimum charge') + mTEPES.pMaxCharge = Param( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.gg, + initialize=pMaxCharge.stack().to_dict(), + within=NonNegativeReals, + doc='Maximum charge') + mTEPES.pMaxPower2ndBlock = Param( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.gg, + initialize=pMaxPower2ndBlock.stack().to_dict(), + within=NonNegativeReals, + doc='Second block power') + mTEPES.pMaxCharge2ndBlock = Param( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.gg, + initialize=pMaxCharge2ndBlock.stack().to_dict(), + within=NonNegativeReals, + doc='Second block charge') + mTEPES.pEnergyInflows = Param( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.gg, + initialize=pEnergyInflows.stack().to_dict(), + within=NonNegativeReals, + doc='Energy inflows') + mTEPES.pEnergyOutflows = Param( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.gg, + initialize=pEnergyOutflows.stack().to_dict(), + within=NonNegativeReals, + doc='Energy outflows') + mTEPES.pMinStorage = Param( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.gg, + initialize=pMinStorage.stack().to_dict(), + within=NonNegativeReals, + doc='ESS Minimum stoarage capacity') + mTEPES.pMaxStorage = Param( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.gg, + initialize=pMaxStorage.stack().to_dict(), + within=NonNegativeReals, + doc='ESS Maximum stoarage capacity') + mTEPES.pRatedMaxPower = Param( + mTEPES.gg, + initialize=pRatedMaxPower.to_dict(), + within=NonNegativeReals, + doc='Rated maximum power') + mTEPES.pMustRun = Param( + mTEPES.gg, + initialize=pMustRun.to_dict(), + within=Boolean, + doc='must-run unit') + mTEPES.pInertia = Param( + mTEPES.gg, + initialize=pInertia.to_dict(), + within=NonNegativeReals, + doc='unit inertia constant') + mTEPES.pAvailability = Param( + mTEPES.gg, + initialize=pAvailability.to_dict(), + within=NonNegativeReals, + doc='unit availability', + mutable=True) + mTEPES.pEFOR = Param( + mTEPES.gg, + initialize=pEFOR.to_dict(), + within=NonNegativeReals, + doc='EFOR') + mTEPES.pLinearOperCost = Param( + mTEPES.gg, + initialize=pLinearOperCost.to_dict(), + within=NonNegativeReals, + doc='Linear variable cost') + mTEPES.pLinearVarCost = Param( + mTEPES.gg, + initialize=pLinearVarCost.to_dict(), + within=NonNegativeReals, + doc='Linear variable cost') + mTEPES.pLinearOMCost = Param( + mTEPES.gg, + initialize=pLinearOMCost.to_dict(), + within=NonNegativeReals, + doc='Linear O&M cost') + mTEPES.pConstantVarCost = Param( + mTEPES.gg, + initialize=pConstantVarCost.to_dict(), + within=NonNegativeReals, + doc='Constant variable cost') + mTEPES.pCO2EmissionCost = Param( + mTEPES.gg, + initialize=pCO2EmissionCost.to_dict(), + within=NonNegativeReals, + doc='CO2 Emission cost') + mTEPES.pStartUpCost = Param( + mTEPES.gg, + initialize=pStartUpCost.to_dict(), + within=NonNegativeReals, + doc='Startup cost') + mTEPES.pShutDownCost = Param( + mTEPES.gg, + initialize=pShutDownCost.to_dict(), + within=NonNegativeReals, + doc='Shutdown cost') + mTEPES.pRampUp = Param( + mTEPES.gg, + initialize=pRampUp.to_dict(), + within=NonNegativeReals, + doc='Ramp up rate') + mTEPES.pRampDw = Param( + mTEPES.gg, + initialize=pRampDw.to_dict(), + within=NonNegativeReals, + doc='Ramp down rate') + mTEPES.pUpTime = Param( + mTEPES.gg, + initialize=pUpTime.to_dict(), + within=NonNegativeReals, + doc='Up time') + mTEPES.pDwTime = Param( + mTEPES.gg, + initialize=pDwTime.to_dict(), + within=NonNegativeReals, + doc='Down time') + mTEPES.pRatedMaxCharge = Param( + mTEPES.gg, + initialize=pRatedMaxCharge.to_dict(), + within=NonNegativeReals, + doc='Rated maximum charge') + mTEPES.pGenFixedCost = Param( + mTEPES.gg, + initialize=pGenFixedCost.to_dict(), + within=NonNegativeReals, + doc='Generation fixed cost') + mTEPES.pIndBinUnitInvest = Param( + mTEPES.gg, + initialize=pIndBinUnitInvest.to_dict(), + within=Boolean, + doc='Binary investment decision') + mTEPES.pIndBinUnitCommit = Param( + mTEPES.gg, + initialize=pIndBinUnitCommit.to_dict(), + within=Boolean, + doc='Binary commitment decision') + mTEPES.pEfficiency = Param( + mTEPES.gg, + initialize=pEfficiency.to_dict(), + within=NonNegativeReals, + doc='Round-trip efficiency') + mTEPES.pCycleTimeStep = Param( + mTEPES.gg, + initialize=pCycleTimeStep.to_dict(), + within=NonNegativeReals, + doc='ESS Storage cycle') + mTEPES.pOutflowsTimeStep = Param( + mTEPES.gg, + initialize=pOutflowsTimeStep.to_dict(), + within=NonNegativeReals, + doc='ESS Outflows cycle') + mTEPES.pIniInventory = Param( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.gg, + initialize=pIniInventory.stack().to_dict(), + within=NonNegativeReals, + doc='ESS Initial storage', + mutable=True) + mTEPES.pInitialInventory = Param( + mTEPES.gg, + initialize=pInitialInventory.to_dict(), + within=NonNegativeReals, + doc='ESS Initial storage without loadlevels') + mTEPES.pStorageType = Param( + mTEPES.gg, + initialize=pStorageType.to_dict(), + within=Any, + doc='ESS Storage type') + + mTEPES.pLineLossFactor = Param( + mTEPES.ln, + initialize=pLineLossFactor.to_dict(), + within=NonNegativeReals, + doc='Loss factor') + mTEPES.pLineR = Param( + mTEPES.ln, + initialize=pLineR.to_dict(), + within=NonNegativeReals, + doc='Resistance') + mTEPES.pLineX = Param( + mTEPES.ln, + initialize=pLineX.to_dict(), + within=NonNegativeReals, + doc='Reactance') + mTEPES.pLineBsh = Param( + mTEPES.ln, + initialize=pLineBsh.to_dict(), + within=NonNegativeReals, + doc='Susceptance', + mutable=True) + mTEPES.pLineTAP = Param( + mTEPES.ln, + initialize=pLineTAP.to_dict(), + within=NonNegativeReals, + doc='Tap changer', + mutable=True) + mTEPES.pConverter = Param( + mTEPES.ln, + initialize=pConverter.to_dict(), + within=NonNegativeReals, + doc='Converter') + mTEPES.pLineLength = Param( + mTEPES.ln, + initialize=pLineLength.to_dict(), + within=NonNegativeReals, + doc='Length', + mutable=True) + mTEPES.pLineVoltage = Param( + mTEPES.ln, + initialize=pLineVoltage.to_dict(), + within=NonNegativeReals, + doc='Voltage') + mTEPES.pLineNTCFrw = Param( + mTEPES.ln, + initialize=pLineNTCFrw.to_dict(), + within=NonNegativeReals, + doc='NTC forward') + mTEPES.pLineNTCBck = Param( + mTEPES.ln, + initialize=pLineNTCBck.to_dict(), + within=NonNegativeReals, + doc='NTC backward') + mTEPES.pNetFixedCost = Param( + mTEPES.ln, + initialize=pNetFixedCost.to_dict(), + within=NonNegativeReals, + doc='Network fixed cost') + mTEPES.pIndBinLineInvest = Param( + mTEPES.ln, + initialize=pIndBinLineInvest.to_dict(), + within=Boolean, + doc='Binary investment decision') + mTEPES.pSwOnTime = Param( + mTEPES.ln, + initialize=pSwitchOnTime.to_dict(), + within=NonNegativeReals, + doc='Minimum switching on time') + mTEPES.pSwOffTime = Param( + mTEPES.ln, + initialize=pSwitchOffTime.to_dict(), + within=NonNegativeReals, + doc='Minimum switching off time') + mTEPES.pLineSwitching = Param( + mTEPES.ln, + initialize=pLineSwitching.to_dict(), + within=Boolean, + doc='Switching decision') + mTEPES.pBigMFlowBck = Param( + mTEPES.ln, + initialize=pBigMFlowBck.to_dict(), + within=NonNegativeReals, + doc='Maximum backward capacity', + mutable=True) + mTEPES.pBigMFlowFrw = Param( + mTEPES.ln, + initialize=pBigMFlowFrw.to_dict(), + within=NonNegativeReals, + doc='Maximum forward capacity', + mutable=True) + mTEPES.pMaxTheta = Param( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.nd, + initialize=pMaxTheta.stack().to_dict(), + within=NonNegativeReals, + doc='Maximum voltage angle', + mutable=True) + mTEPES.pAngMin = Param( + mTEPES.ln, + initialize=pAngMin.to_dict(), + within=Reals, + doc='Minimum phase angle diff', + mutable=True) + mTEPES.pAngMax = Param( + mTEPES.ln, + initialize=pAngMax.to_dict(), + within=Reals, + doc='Maximum phase angle diff', + mutable=True) # if unit availability = 0 changed to 1 for g in mTEPES.g: - if mTEPES.pAvailability[g]() == 0.0: - mTEPES.pAvailability[g] = 1.0 + if mTEPES.pAvailability[g]() == 0.0: + mTEPES.pAvailability[g] = 1.0 # if line length = 0 changed to geographical distance - for ni,nf,cc in mTEPES.la: - if mTEPES.pLineLength[ni,nf,cc]() == 0.0: - mTEPES.pLineLength[ni,nf,cc] = 1.1 * 6371 * 2 * math.asin(math.sqrt(math.pow(math.sin((mTEPES.pNodeLat[nf]-mTEPES.pNodeLat[ni])*math.pi/180/2),2) + math.cos(mTEPES.pNodeLat[ni]*math.pi/180)*math.cos(mTEPES.pNodeLat[nf]*math.pi/180)*math.pow(math.sin((mTEPES.pNodeLon[nf]-mTEPES.pNodeLon[ni])*math.pi/180/2),2))) + for ni, nf, cc in mTEPES.la: + if mTEPES.pLineLength[ni, nf, cc]() == 0.0: + mTEPES.pLineLength[ni, nf, cc] = 1.1 * 6371 * 2 * math.asin(math.sqrt(math.pow(math.sin((mTEPES.pNodeLat[nf] - mTEPES.pNodeLat[ni]) * math.pi / 180 / 2), 2) + math.cos( + mTEPES.pNodeLat[ni] * math.pi / 180) * math.cos(mTEPES.pNodeLat[nf] * math.pi / 180) * math.pow(math.sin((mTEPES.pNodeLon[nf] - mTEPES.pNodeLon[ni]) * math.pi / 180 / 2), 2))) # initialize generation output, unit commitment and line switching - pInitialOutput = pd.DataFrame([[0.0]*len(mTEPES.gg)]*len(mTEPES.sc*mTEPES.p*mTEPES.n), index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n), columns=list(mTEPES.gg)) - pInitialUC = pd.DataFrame([[0 ]*len(mTEPES.gg)]*len(mTEPES.sc*mTEPES.p*mTEPES.n), index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n), columns=list(mTEPES.gg)) - pInitialSwitch = pd.DataFrame([[0 ]*len(mTEPES.ln)]*len(mTEPES.sc*mTEPES.p*mTEPES.n), index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n), columns=list(mTEPES.ln)) - - mTEPES.pInitialOutput = Param(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.gg, initialize=pInitialOutput.stack().to_dict() , within=NonNegativeReals, doc='unit initial output', mutable=True) - mTEPES.pInitialUC = Param(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.gg, initialize=pInitialUC.stack().to_dict() , within=Boolean, doc='unit initial commitment', mutable=True) - mTEPES.pInitialSwitch = Param(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.ln, initialize=pInitialSwitch.stack().to_dict() , within=Boolean, doc='line initial switching', mutable=True) + pInitialOutput = pd.DataFrame([[0.0] * + len(mTEPES.gg)] * + len(mTEPES.sc * + mTEPES.p * + mTEPES.n), index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n), columns=list(mTEPES.gg)) + pInitialUC = pd.DataFrame([[0] * + len(mTEPES.gg)] * + len(mTEPES.sc * + mTEPES.p * + mTEPES.n), index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n), columns=list(mTEPES.gg)) + pInitialSwitch = pd.DataFrame([[0] * + len(mTEPES.ln)] * + len(mTEPES.sc * + mTEPES.p * + mTEPES.n), index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n), columns=list(mTEPES.ln)) + + mTEPES.pInitialOutput = Param( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.gg, + initialize=pInitialOutput.stack().to_dict(), + within=NonNegativeReals, + doc='unit initial output', + mutable=True) + mTEPES.pInitialUC = Param( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.gg, + initialize=pInitialUC.stack().to_dict(), + within=Boolean, + doc='unit initial commitment', + mutable=True) + mTEPES.pInitialSwitch = Param( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.ln, + initialize=pInitialSwitch.stack().to_dict(), + within=Boolean, + doc='line initial switching', + mutable=True) SettingUpDataTime = time.time() - StartTime - print('Setting up input data ... ', round(SettingUpDataTime), 's') + print( + 'Setting up input data ... ', + round(SettingUpDataTime), + 's') def SettingUpVariables(OptModel, mTEPES): StartTime = time.time() - #%% variables - OptModel.vTotalFCost = Var( within=NonNegativeReals, doc='total system fixed cost [MEUR]') - OptModel.vTotalGCost = Var(mTEPES.sc, mTEPES.p, mTEPES.n, within=NonNegativeReals, doc='total variable generation operation cost [MEUR]') - OptModel.vTotalCCost = Var(mTEPES.sc, mTEPES.p, mTEPES.n, within=NonNegativeReals, doc='total variable consumption operation cost [MEUR]') - OptModel.vTotalECost = Var(mTEPES.sc, mTEPES.p, mTEPES.n, within=NonNegativeReals, doc='total system emission cost [MEUR]') - OptModel.vTotalRCost = Var(mTEPES.sc, mTEPES.p, mTEPES.n, within=NonNegativeReals, doc='total system reliability cost [MEUR]') - OptModel.vTotalOutput = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.g , within=NonNegativeReals, bounds=lambda OptModel,sc,p,n,g : (0.0,mTEPES.pMaxPower [sc,p,n,g ]), doc='total output of the unit [GW]') - OptModel.vOutput2ndBlock = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.nr, within=NonNegativeReals, bounds=lambda OptModel,sc,p,n,nr: (0.0,mTEPES.pMaxPower2ndBlock [sc,p,n,nr]), doc='second block of the unit [GW]') - OptModel.vReserveUp = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.nr, within=NonNegativeReals, bounds=lambda OptModel,sc,p,n,nr: (0.0,mTEPES.pMaxPower2ndBlock [sc,p,n,nr]), doc='upward operating reserve [GW]') - OptModel.vReserveDown = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.nr, within=NonNegativeReals, bounds=lambda OptModel,sc,p,n,nr: (0.0,mTEPES.pMaxPower2ndBlock [sc,p,n,nr]), doc='downward operating reserve [GW]') - OptModel.vEnergyOutflows = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.g , within=NonNegativeReals, bounds=lambda OptModel,sc,p,n,g : (0.0,mTEPES.pMaxPower [sc,p,n,g ]), doc='total outflows of the ESS unit [GW]') - OptModel.vESSInventory = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.es, within=NonNegativeReals, bounds=lambda OptModel,sc,p,n,es: (mTEPES.pMinStorage[sc,p,n,es],mTEPES.pMaxStorage[sc,p,n,es]), doc='ESS inventory [GWh]') - OptModel.vESSSpillage = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.es, within=NonNegativeReals, doc='ESS spillage [GWh]') - OptModel.vESSTotalCharge = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.es, within=NonNegativeReals, bounds=lambda OptModel,sc,p,n,es: (0.0,mTEPES.pMaxCharge [sc,p,n,es]), doc='ESS total charge power [GW]') - OptModel.vCharge2ndBlock = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.es, within=NonNegativeReals, bounds=lambda OptModel,sc,p,n,es: (0.0,mTEPES.pMaxCharge2ndBlock[sc,p,n,es]), doc='ESS charge power [GW]') - OptModel.vESSReserveUp = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.es, within=NonNegativeReals, bounds=lambda OptModel,sc,p,n,es: (0.0,mTEPES.pMaxCharge2ndBlock[sc,p,n,es]), doc='ESS upward operating reserve [GW]') - OptModel.vESSReserveDown = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.es, within=NonNegativeReals, bounds=lambda OptModel,sc,p,n,es: (0.0,mTEPES.pMaxCharge2ndBlock[sc,p,n,es]), doc='ESS downward operating reserve [GW]') - OptModel.vENS = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.nd, within=NonNegativeReals, bounds=lambda OptModel,sc,p,n,nd: (0.0,mTEPES.pDemand [sc,p,n,nd]), doc='energy not served in node [GW]') + # %% variables + OptModel.vTotalFCost = Var( + within=NonNegativeReals, + doc='total system fixed cost [MEUR]') + OptModel.vTotalGCost = Var( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + within=NonNegativeReals, + doc='total variable generation operation cost [MEUR]') + OptModel.vTotalCCost = Var( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + within=NonNegativeReals, + doc='total variable consumption operation cost [MEUR]') + OptModel.vTotalECost = Var( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + within=NonNegativeReals, + doc='total system emission cost [MEUR]') + OptModel.vTotalRCost = Var( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + within=NonNegativeReals, + doc='total system reliability cost [MEUR]') + OptModel.vTotalOutput = Var(mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.g, + within=NonNegativeReals, + bounds=lambda OptModel, + sc, + p, + n, + g: (0.0, + mTEPES.pMaxPower[sc, + p, + n, + g]), + doc='total output of the unit [GW]') + OptModel.vOutput2ndBlock = Var(mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.nr, + within=NonNegativeReals, + bounds=lambda OptModel, + sc, + p, + n, + nr: (0.0, + mTEPES.pMaxPower2ndBlock[sc, + p, + n, + nr]), + doc='second block of the unit [GW]') + OptModel.vReserveUp = Var(mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.nr, + within=NonNegativeReals, + bounds=lambda OptModel, + sc, + p, + n, + nr: (0.0, + mTEPES.pMaxPower2ndBlock[sc, + p, + n, + nr]), + doc='upward operating reserve [GW]') + OptModel.vReserveDown = Var(mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.nr, + within=NonNegativeReals, + bounds=lambda OptModel, + sc, + p, + n, + nr: (0.0, + mTEPES.pMaxPower2ndBlock[sc, + p, + n, + nr]), + doc='downward operating reserve [GW]') + OptModel.vEnergyOutflows = Var(mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.g, + within=NonNegativeReals, + bounds=lambda OptModel, + sc, + p, + n, + g: (0.0, + mTEPES.pMaxPower[sc, + p, + n, + g]), + doc='total outflows of the ESS unit [GW]') + OptModel.vESSInventory = Var(mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.es, + within=NonNegativeReals, + bounds=lambda OptModel, + sc, + p, + n, + es: (mTEPES.pMinStorage[sc, + p, + n, + es], + mTEPES.pMaxStorage[sc, + p, + n, + es]), + doc='ESS inventory [GWh]') + OptModel.vESSSpillage = Var( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.es, + within=NonNegativeReals, + doc='ESS spillage [GWh]') + OptModel.vESSTotalCharge = Var(mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.es, + within=NonNegativeReals, + bounds=lambda OptModel, + sc, + p, + n, + es: (0.0, + mTEPES.pMaxCharge[sc, + p, + n, + es]), + doc='ESS total charge power [GW]') + OptModel.vCharge2ndBlock = Var(mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.es, + within=NonNegativeReals, + bounds=lambda OptModel, + sc, + p, + n, + es: (0.0, + mTEPES.pMaxCharge2ndBlock[sc, + p, + n, + es]), + doc='ESS charge power [GW]') + OptModel.vESSReserveUp = Var(mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.es, + within=NonNegativeReals, + bounds=lambda OptModel, + sc, + p, + n, + es: (0.0, + mTEPES.pMaxCharge2ndBlock[sc, + p, + n, + es]), + doc='ESS upward operating reserve [GW]') + OptModel.vESSReserveDown = Var(mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.es, + within=NonNegativeReals, + bounds=lambda OptModel, + sc, + p, + n, + es: (0.0, + mTEPES.pMaxCharge2ndBlock[sc, + p, + n, + es]), + doc='ESS downward operating reserve [GW]') + OptModel.vENS = Var(mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.nd, + within=NonNegativeReals, + bounds=lambda OptModel, + sc, + p, + n, + nd: (0.0, + mTEPES.pDemand[sc, + p, + n, + nd]), + doc='energy not served in node [GW]') if mTEPES.pIndBinGenInvest() == 0: - OptModel.vGenerationInvest = Var( mTEPES.gc, within=UnitInterval, doc='generation investment decision exists in a year [0,1]') + OptModel.vGenerationInvest = Var( + mTEPES.gc, + within=UnitInterval, + doc='generation investment decision exists in a year [0,1]') else: - OptModel.vGenerationInvest = Var( mTEPES.gc, within=Binary, doc='generation investment decision exists in a year {0,1}') + OptModel.vGenerationInvest = Var( + mTEPES.gc, + within=Binary, + doc='generation investment decision exists in a year {0,1}') if mTEPES.pIndBinNetInvest() == 0: - OptModel.vNetworkInvest = Var( mTEPES.lc, within=UnitInterval, doc='network investment decision exists in a year [0,1]') + OptModel.vNetworkInvest = Var( + mTEPES.lc, + within=UnitInterval, + doc='network investment decision exists in a year [0,1]') else: - OptModel.vNetworkInvest = Var( mTEPES.lc, within=Binary, doc='network investment decision exists in a year {0,1}') + OptModel.vNetworkInvest = Var( + mTEPES.lc, + within=Binary, + doc='network investment decision exists in a year {0,1}') if mTEPES.pIndBinGenOperat() == 0: - OptModel.vCommitment = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.nr, within=UnitInterval, initialize=0.0, doc='commitment of the unit [0,1]') - OptModel.vStartUp = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.nr, within=UnitInterval, initialize=0.0, doc='startup of the unit [0,1]') - OptModel.vShutDown = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.nr, within=UnitInterval, initialize=0.0, doc='shutdown of the unit [0,1]') + OptModel.vCommitment = Var( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.nr, + within=UnitInterval, + initialize=0.0, + doc='commitment of the unit [0,1]') + OptModel.vStartUp = Var( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.nr, + within=UnitInterval, + initialize=0.0, + doc='startup of the unit [0,1]') + OptModel.vShutDown = Var( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.nr, + within=UnitInterval, + initialize=0.0, + doc='shutdown of the unit [0,1]') else: - OptModel.vCommitment = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.nr, within=Binary, initialize=0 , doc='commitment of the unit {0,1}') - OptModel.vStartUp = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.nr, within=Binary, initialize=0 , doc='startup of the unit {0,1}') - OptModel.vShutDown = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.nr, within=Binary, initialize=0 , doc='shutdown of the unit {0,1}') + OptModel.vCommitment = Var( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.nr, + within=Binary, + initialize=0, + doc='commitment of the unit {0,1}') + OptModel.vStartUp = Var( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.nr, + within=Binary, + initialize=0, + doc='startup of the unit {0,1}') + OptModel.vShutDown = Var( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.nr, + within=Binary, + initialize=0, + doc='shutdown of the unit {0,1}') if mTEPES.pIndBinLineCommit() == 0: - OptModel.vLineCommit = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.la, within=UnitInterval, initialize=0.0, doc='line switching of the line [0,1]') - OptModel.vLineOnState = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.la, within=UnitInterval, initialize=0.0, doc='switching on state of the line [0,1]') - OptModel.vLineOffState = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.la, within=UnitInterval, initialize=0.0, doc='switching off state of the line [0,1]') + OptModel.vLineCommit = Var( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.la, + within=UnitInterval, + initialize=0.0, + doc='line switching of the line [0,1]') + OptModel.vLineOnState = Var( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.la, + within=UnitInterval, + initialize=0.0, + doc='switching on state of the line [0,1]') + OptModel.vLineOffState = Var( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.la, + within=UnitInterval, + initialize=0.0, + doc='switching off state of the line [0,1]') if mTEPES.pIndSwitchingStage() == 1: - OptModel.vSwitchingStage = Var(mTEPES.sc, mTEPES.p, mTEPES.ss, mTEPES.la, within=UnitInterval, initialize=0.0, doc='line switching of the line per stage [0,1]') + OptModel.vSwitchingStage = Var( + mTEPES.sc, + mTEPES.p, + mTEPES.ss, + mTEPES.la, + within=UnitInterval, + initialize=0.0, + doc='line switching of the line per stage [0,1]') else: - OptModel.vLineCommit = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.la, within=Binary, initialize=0 , doc='line switching of the line {0,1}') - OptModel.vLineOnState = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.la, within=Binary, initialize=0 , doc='switching on state of the line {0,1}') - OptModel.vLineOffState = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.la, within=Binary, initialize=0 , doc='switching off state of the line {0,1}') + OptModel.vLineCommit = Var( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.la, + within=Binary, + initialize=0, + doc='line switching of the line {0,1}') + OptModel.vLineOnState = Var( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.la, + within=Binary, + initialize=0, + doc='switching on state of the line {0,1}') + OptModel.vLineOffState = Var( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.la, + within=Binary, + initialize=0, + doc='switching off state of the line {0,1}') if mTEPES.pIndSwitchingStage() == 1: - OptModel.vSwitchingStage = Var(mTEPES.sc, mTEPES.p, mTEPES.ss, mTEPES.la, within=Binary, initialize=0 , doc='line switching of the line per stage {0,1}') + OptModel.vSwitchingStage = Var( + mTEPES.sc, + mTEPES.p, + mTEPES.ss, + mTEPES.la, + within=Binary, + initialize=0, + doc='line switching of the line per stage {0,1}') # relax binary condition in generation and network investment decisions for gc in mTEPES.gc: - if mTEPES.pIndBinGenInvest() != 0 and mTEPES.pIndBinUnitInvest[gc] == 0: + if mTEPES.pIndBinGenInvest( + ) != 0 and mTEPES.pIndBinUnitInvest[gc] == 0: OptModel.vGenerationInvest[gc].domain = UnitInterval for ec in mTEPES.ec: - if mTEPES.pIndBinGenInvest() != 0 and mTEPES.pIndBinUnitInvest[ec] == 0: + if mTEPES.pIndBinGenInvest( + ) != 0 and mTEPES.pIndBinUnitInvest[ec] == 0: OptModel.vGenerationInvest[ec].domain = UnitInterval for lc in mTEPES.lc: - if mTEPES.pIndBinNetInvest() != 0 and mTEPES.pIndBinLineInvest[lc] == 0: - OptModel.vNetworkInvest [lc].domain = UnitInterval + if mTEPES.pIndBinNetInvest( + ) != 0 and mTEPES.pIndBinLineInvest[lc] == 0: + OptModel.vNetworkInvest[lc].domain = UnitInterval # relax binary condition in unit generation, startup and shutdown decisions - for sc,p,n,nr in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nr: + for sc, p, n, nr in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.nr: if mTEPES.pIndBinUnitCommit[nr] == 0: - OptModel.vCommitment[sc,p,n,nr].domain = UnitInterval - OptModel.vStartUp [sc,p,n,nr].domain = UnitInterval - OptModel.vShutDown [sc,p,n,nr].domain = UnitInterval + OptModel.vCommitment[sc, p, n, nr].domain = UnitInterval + OptModel.vStartUp[sc, p, n, nr].domain = UnitInterval + OptModel.vShutDown[sc, p, n, nr].domain = UnitInterval # existing lines are always committed if no decision is modeled - for sc,p,n,ni,nf,cc in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.le: - if mTEPES.pLineSwitching[ni,nf,cc] == 0: - OptModel.vLineCommit [sc,p,n ,ni,nf,cc].fix(1) - OptModel.vLineOnState [sc,p,n ,ni,nf,cc].fix(0) - OptModel.vLineOffState [sc,p,n ,ni,nf,cc].fix(0) + for sc, p, n, ni, nf, cc in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.le: + if mTEPES.pLineSwitching[ni, nf, cc] == 0: + OptModel.vLineCommit[sc, p, n, ni, nf, cc].fix(1) + OptModel.vLineOnState[sc, p, n, ni, nf, cc].fix(0) + OptModel.vLineOffState[sc, p, n, ni, nf, cc].fix(0) if mTEPES.pIndSwitchingStage() == 1: - for sc,p,ss,ni,nf,cc in mTEPES.sc*mTEPES.p*mTEPES.ss*mTEPES.le: - if mTEPES.pLineSwitching[ni,nf,cc] == 0: - OptModel.vSwitchingStage[sc,p,ss,ni,nf,cc].fix(1) - - OptModel.vLineLosses = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.ll, within=NonNegativeReals, bounds=lambda OptModel,sc,p,n,*ll: (0.0,0.5*mTEPES.pLineLossFactor[ll]*max(mTEPES.pLineNTCBck[ll],mTEPES.pLineNTCFrw[ll])), doc='half line losses [GW]') - OptModel.vFlow = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.la, within=Reals, bounds=lambda OptModel,sc,p,n,*la: (-mTEPES.pLineNTCBck[la],mTEPES.pLineNTCFrw[la]), doc='flow [GW]') - OptModel.vTheta = Var(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.nd, within=Reals, bounds=lambda OptModel,sc,p,n, nd: (-mTEPES.pMaxTheta[sc,p,n,nd],mTEPES.pMaxTheta[sc,p,n,nd]), doc='voltage angle [rad]') + for sc, p, ss, ni, nf, cc in mTEPES.sc * \ + mTEPES.p * mTEPES.ss * mTEPES.le: + if mTEPES.pLineSwitching[ni, nf, cc] == 0: + OptModel.vSwitchingStage[sc, p, ss, ni, nf, cc].fix(1) + + OptModel.vLineLosses = Var( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.ll, + within=NonNegativeReals, + bounds=lambda OptModel, + sc, + p, + n, + * + ll: ( + 0.0, + 0.5 * + mTEPES.pLineLossFactor[ll] * + max( + mTEPES.pLineNTCBck[ll], + mTEPES.pLineNTCFrw[ll])), + doc='half line losses [GW]') + OptModel.vFlow = Var(mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.la, + within=Reals, + bounds=lambda OptModel, + sc, + p, + n, + *la: (-mTEPES.pLineNTCBck[la], + mTEPES.pLineNTCFrw[la]), + doc='flow [GW]') + OptModel.vTheta = Var(mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.nd, + within=Reals, + bounds=lambda OptModel, + sc, + p, + n, + nd: (-mTEPES.pMaxTheta[sc, + p, + n, + nd], + mTEPES.pMaxTheta[sc, + p, + n, + nd]), + doc='voltage angle [rad]') # fix the must-run units and their output - for sc,p,n,g in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.g : + for sc, p, n, g in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.g: # must run units must produce at least their minimum output if mTEPES.pMustRun[g] == 1: - OptModel.vTotalOutput[sc,p,n,g].setlb(mTEPES.pMinPower[sc,p,n,g]) + OptModel.vTotalOutput[sc, p, n, g].setlb( + mTEPES.pMinPower[sc, p, n, g]) # if no max power, no total output - if mTEPES.pMaxPower[sc,p,n,g] == 0.0: - OptModel.vTotalOutput[sc,p,n,g].fix(0.0) - #for sc,p,n,r in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.r : + if mTEPES.pMaxPower[sc, p, n, g] == 0.0: + OptModel.vTotalOutput[sc, p, n, g].fix(0.0) + # for sc,p,n,r in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.r : # if mTEPES.pMinPower[sc,p,n,r] == mTEPES.pMaxPower[sc,p,n,r] and mTEPES.pLinearOMCost[r] == 0.0: # OptModel.vTotalOutput[sc,p,n,r].fix(mTEPES.pMaxPower[sc,p,n,r]) - for sc,p,n,nr in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nr: - # must run units or units with no minimum power or ESS units are always committed and must produce at least their minimum output - if mTEPES.pMustRun[nr] == 1 or (mTEPES.pMinPower[sc,p,n,nr] == 0.0 and mTEPES.pConstantVarCost[nr] == 0.0) or nr in mTEPES.es: - OptModel.vCommitment [sc,p,n,nr].fix(1) - OptModel.vStartUp [sc,p,n,nr].fix(0) - OptModel.vShutDown [sc,p,n,nr].fix(0) - # if min and max power coincide there are neither second block, nor operating reserve - if mTEPES.pMaxPower2ndBlock[sc,p,n,nr] == 0.0: - OptModel.vOutput2ndBlock[sc,p,n,nr].fix(0.0) - OptModel.vReserveUp [sc,p,n,nr].fix(0.0) - OptModel.vReserveDown [sc,p,n,nr].fix(0.0) - - for sc,p,n,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es: + for sc, p, n, nr in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.nr: + # must run units or units with no minimum power or ESS units are always + # committed and must produce at least their minimum output + if mTEPES.pMustRun[nr] == 1 or ( + mTEPES.pMinPower[sc, p, n, nr] == 0.0 and mTEPES.pConstantVarCost[nr] == 0.0) or nr in mTEPES.es: + OptModel.vCommitment[sc, p, n, nr].fix(1) + OptModel.vStartUp[sc, p, n, nr].fix(0) + OptModel.vShutDown[sc, p, n, nr].fix(0) + # if min and max power coincide there are neither second block, nor + # operating reserve + if mTEPES.pMaxPower2ndBlock[sc, p, n, nr] == 0.0: + OptModel.vOutput2ndBlock[sc, p, n, nr].fix(0.0) + OptModel.vReserveUp[sc, p, n, nr].fix(0.0) + OptModel.vReserveDown[sc, p, n, nr].fix(0.0) + + for sc, p, n, es in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.es: # ESS with no charge capacity or not storage capacity can't charge - if mTEPES.pMaxCharge[sc,p,n,es] == 0.0: - OptModel.vESSTotalCharge[sc,p,n,es].fix(0.0) - if mTEPES.pMaxCharge2ndBlock[sc,p,n,es] == 0.0: - OptModel.vCharge2ndBlock[sc,p,n,es].fix(0.0) - OptModel.vESSReserveUp [sc,p,n,es].fix(0.0) - OptModel.vESSReserveDown[sc,p,n,es].fix(0.0) - if mTEPES.pMaxStorage[sc,p,n,es] == 0.0: - OptModel.vESSInventory [sc,p,n,es].fix(0.0) - - # thermal and RES units ordered by increasing variable operation cost, excluding reactive generating units + if mTEPES.pMaxCharge[sc, p, n, es] == 0.0: + OptModel.vESSTotalCharge[sc, p, n, es].fix(0.0) + if mTEPES.pMaxCharge2ndBlock[sc, p, n, es] == 0.0: + OptModel.vCharge2ndBlock[sc, p, n, es].fix(0.0) + OptModel.vESSReserveUp[sc, p, n, es].fix(0.0) + OptModel.vESSReserveDown[sc, p, n, es].fix(0.0) + if mTEPES.pMaxStorage[sc, p, n, es] == 0.0: + OptModel.vESSInventory[sc, p, n, es].fix(0.0) + + # thermal and RES units ordered by increasing variable operation cost, + # excluding reactive generating units if len(mTEPES.tq): - mTEPES.go = [k for k in sorted(mTEPES.pLinearVarCost, key=mTEPES.pLinearVarCost.__getitem__) if k not in mTEPES.gq] + mTEPES.go = [ + k for k in sorted( + mTEPES.pLinearVarCost, + key=mTEPES.pLinearVarCost.__getitem__) if k not in mTEPES.gq] else: - mTEPES.go = [k for k in sorted(mTEPES.pLinearVarCost, key=mTEPES.pLinearVarCost.__getitem__)] + mTEPES.go = [ + k for k in sorted( + mTEPES.pLinearVarCost, + key=mTEPES.pLinearVarCost.__getitem__)] - for sc,p,st in mTEPES.scc*mTEPES.pp*mTEPES.stt: + for sc, p, st in mTEPES.scc * mTEPES.pp * mTEPES.stt: # activate only scenario, period and load levels to formulate mTEPES.del_component(mTEPES.sc) - mTEPES.del_component(mTEPES.p ) + mTEPES.del_component(mTEPES.p) mTEPES.del_component(mTEPES.st) - mTEPES.del_component(mTEPES.n ) - mTEPES.sc = Set(initialize=mTEPES.scc, ordered=True, doc='scenarios', filter=lambda mTEPES,scc: scc in mTEPES.scc and sc == scc and mTEPES.pScenProb [scc]) - mTEPES.st = Set(initialize=mTEPES.stt, ordered=True, doc='stages', filter=lambda mTEPES,stt: stt in mTEPES.stt and st == stt and mTEPES.pStageWeight[stt] and sum(1 for (st,nn) in mTEPES.s2n)) - mTEPES.p = Set(initialize=mTEPES.pp , ordered=True, doc='periods', filter=lambda mTEPES,pp : pp in p == pp ) - mTEPES.n = Set(initialize=mTEPES.nn , ordered=True, doc='load levels', filter=lambda mTEPES,nn : nn in mTEPES.pDuration and (st,nn) in mTEPES.s2n ) + mTEPES.del_component(mTEPES.n) + mTEPES.sc = Set( + initialize=mTEPES.scc, + ordered=True, + doc='scenarios', + filter=lambda mTEPES, + scc: scc in mTEPES.scc and sc == scc and mTEPES.pScenProb[scc]) + mTEPES.st = Set( + initialize=mTEPES.stt, + ordered=True, + doc='stages', + filter=lambda mTEPES, + stt: stt in mTEPES.stt and st == stt and mTEPES.pStageWeight[stt] and sum( + 1 for ( + st, + nn) in mTEPES.s2n)) + mTEPES.p = Set( + initialize=mTEPES.pp, + ordered=True, + doc='periods', + filter=lambda mTEPES, + pp: pp in p == pp) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration and ( + st, + nn) in mTEPES.s2n) if len(mTEPES.n): # determine the first load level of each stage n1 = next(iter(mTEPES.sc * mTEPES.p * mTEPES.n)) - # commit the units and their output at the first load level of each stage + # commit the units and their output at the first load level of each + # stage pSystemOutput = 0.0 for nr in mTEPES.nr: - if pSystemOutput < sum(mTEPES.pDemand[n1,nd] for nd in mTEPES.nd) and mTEPES.pMustRun[nr] == 1: - mTEPES.pInitialOutput[n1,nr] = mTEPES.pMaxPower[n1,nr] - mTEPES.pInitialUC [n1,nr] = 1 - pSystemOutput += mTEPES.pInitialOutput[n1,nr]() - - # determine the initial committed units and their output at the first load level of each stage + if pSystemOutput < sum( + mTEPES.pDemand[n1, nd] for nd in mTEPES.nd) and mTEPES.pMustRun[nr] == 1: + mTEPES.pInitialOutput[n1, nr] = mTEPES.pMaxPower[n1, nr] + mTEPES.pInitialUC[n1, nr] = 1 + pSystemOutput += mTEPES.pInitialOutput[n1, nr]() + + # determine the initial committed units and their output at the + # first load level of each stage for go in mTEPES.go: - if pSystemOutput < sum(mTEPES.pDemand[n1,nd] for nd in mTEPES.nd) and mTEPES.pMustRun[go] != 1: + if pSystemOutput < sum( + mTEPES.pDemand[n1, nd] for nd in mTEPES.nd) and mTEPES.pMustRun[go] != 1: if go in mTEPES.r: - mTEPES.pInitialOutput[n1,go] = mTEPES.pMaxPower[n1,go] + mTEPES.pInitialOutput[n1, + go] = mTEPES.pMaxPower[n1, go] else: - mTEPES.pInitialOutput[n1,go] = mTEPES.pMinPower[n1,go] - mTEPES.pInitialUC[n1,go] = 1 - pSystemOutput = pSystemOutput + mTEPES.pInitialOutput[n1,go]() + mTEPES.pInitialOutput[n1, + go] = mTEPES.pMinPower[n1, go] + mTEPES.pInitialUC[n1, go] = 1 + pSystemOutput = pSystemOutput + \ + mTEPES.pInitialOutput[n1, go]() # determine the initial committed lines for la in mTEPES.la: if la in mTEPES.lc: - mTEPES.pInitialSwitch[n1,la] = 0 + mTEPES.pInitialSwitch[n1, la] = 0 else: - mTEPES.pInitialSwitch[n1,la] = 1 + mTEPES.pInitialSwitch[n1, la] = 1 # fixing the ESS inventory at the last load level - for sc,p,es in mTEPES.sc*mTEPES.p*mTEPES.es: - OptModel.vESSInventory[sc,p,mTEPES.n.last(),es].fix(mTEPES.pInitialInventory[es]) + for sc, p, es in mTEPES.sc * mTEPES.p * mTEPES.es: + OptModel.vESSInventory[sc, p, mTEPES.n.last(), es].fix( + mTEPES.pInitialInventory[es]) # activate all the scenarios, periods and load levels again mTEPES.del_component(mTEPES.sc) - mTEPES.del_component(mTEPES.p ) + mTEPES.del_component(mTEPES.p) mTEPES.del_component(mTEPES.st) - mTEPES.del_component(mTEPES.n ) - mTEPES.sc = Set(initialize=mTEPES.scc, ordered=True, doc='scenarios', filter=lambda mTEPES,scc: scc in mTEPES.scc and mTEPES.pScenProb [scc]) - mTEPES.p = Set(initialize=mTEPES.pp, ordered=True, doc='periods', filter=lambda mTEPES,pp : pp in p == pp ) - mTEPES.st = Set(initialize=mTEPES.stt, ordered=True, doc='stages', filter=lambda mTEPES,stt: stt in mTEPES.stt and mTEPES.pStageWeight[stt] and sum(1 for (stt,nn) in mTEPES.s2n)) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn : nn in mTEPES.pDuration ) - - # fixing the ESS inventory at the end of the following pCycleTimeStep (daily, weekly, monthly), i.e., for daily ESS is fixed at the end of the week, for weekly/monthly ESS is fixed at the end of the year - for sc,p,n,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es: - if mTEPES.pStorageType[es] == 'Daily' and mTEPES.n.ord(n) % int( 168/mTEPES.pTimeStep()) == 0: - OptModel.vESSInventory[sc,p,n,es].fix(mTEPES.pInitialInventory[es]) - if mTEPES.pStorageType[es] == 'Weekly' and mTEPES.n.ord(n) % int(8736/mTEPES.pTimeStep()) == 0: - OptModel.vESSInventory[sc,p,n,es].fix(mTEPES.pInitialInventory[es]) - if mTEPES.pStorageType[es] == 'Monthly' and mTEPES.n.ord(n) % int(8736/mTEPES.pTimeStep()) == 0: - OptModel.vESSInventory[sc,p,n,es].fix(mTEPES.pInitialInventory[es]) + mTEPES.del_component(mTEPES.n) + mTEPES.sc = Set( + initialize=mTEPES.scc, + ordered=True, + doc='scenarios', + filter=lambda mTEPES, + scc: scc in mTEPES.scc and mTEPES.pScenProb[scc]) + mTEPES.p = Set( + initialize=mTEPES.pp, + ordered=True, + doc='periods', + filter=lambda mTEPES, + pp: pp in p == pp) + mTEPES.st = Set( + initialize=mTEPES.stt, + ordered=True, + doc='stages', + filter=lambda mTEPES, + stt: stt in mTEPES.stt and mTEPES.pStageWeight[stt] and sum( + 1 for ( + stt, + nn) in mTEPES.s2n)) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration) + + # fixing the ESS inventory at the end of the following pCycleTimeStep + # (daily, weekly, monthly), i.e., for daily ESS is fixed at the end of the + # week, for weekly/monthly ESS is fixed at the end of the year + for sc, p, n, es in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.es: + if mTEPES.pStorageType[es] == 'Daily' and mTEPES.n.ord( + n) % int(168 / mTEPES.pTimeStep()) == 0: + OptModel.vESSInventory[sc, p, n, es].fix( + mTEPES.pInitialInventory[es]) + if mTEPES.pStorageType[es] == 'Weekly' and mTEPES.n.ord( + n) % int(8736 / mTEPES.pTimeStep()) == 0: + OptModel.vESSInventory[sc, p, n, es].fix( + mTEPES.pInitialInventory[es]) + if mTEPES.pStorageType[es] == 'Monthly' and mTEPES.n.ord( + n) % int(8736 / mTEPES.pTimeStep()) == 0: + OptModel.vESSInventory[sc, p, n, es].fix( + mTEPES.pInitialInventory[es]) # if no operating reserve is required no variables are needed - for sc,p,n,ar,nr in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.ar*mTEPES.nr: - if (ar,nr) in mTEPES.a2g: - if mTEPES.pOperReserveUp [sc,p,n,ar] == 0.0: - OptModel.vReserveUp [sc,p,n,nr].fix(0.0) - if mTEPES.pOperReserveDw [sc,p,n,ar] == 0.0: - OptModel.vReserveDown [sc,p,n,nr].fix(0.0) - for sc,p,n,ar,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.ar*mTEPES.es: - if (ar,es) in mTEPES.a2g: - if mTEPES.pOperReserveUp [sc,p,n,ar] == 0.0: - OptModel.vESSReserveUp [sc,p,n,es].fix(0.0) - if mTEPES.pOperReserveDw [sc,p,n,ar] == 0.0: - OptModel.vESSReserveDown[sc,p,n,es].fix(0.0) + for sc, p, n, ar, nr in mTEPES.sc * \ + mTEPES.p * mTEPES.n * mTEPES.ar * mTEPES.nr: + if (ar, nr) in mTEPES.a2g: + if mTEPES.pOperReserveUp[sc, p, n, ar] == 0.0: + OptModel.vReserveUp[sc, p, n, nr].fix(0.0) + if mTEPES.pOperReserveDw[sc, p, n, ar] == 0.0: + OptModel.vReserveDown[sc, p, n, nr].fix(0.0) + for sc, p, n, ar, es in mTEPES.sc * \ + mTEPES.p * mTEPES.n * mTEPES.ar * mTEPES.es: + if (ar, es) in mTEPES.a2g: + if mTEPES.pOperReserveUp[sc, p, n, ar] == 0.0: + OptModel.vESSReserveUp[sc, p, n, es].fix(0.0) + if mTEPES.pOperReserveDw[sc, p, n, ar] == 0.0: + OptModel.vESSReserveDown[sc, p, n, es].fix(0.0) # if there are no energy outflows no variable is needed for es in mTEPES.es: - if sum(mTEPES.pEnergyOutflows[sc,p,n,es] for sc,p,n in mTEPES.sc*mTEPES.p*mTEPES.n) == 0: - for sc,p,n in mTEPES.sc*mTEPES.p*mTEPES.n: - OptModel.vEnergyOutflows[sc,p,n,es].fix(0.0) + if sum(mTEPES.pEnergyOutflows[sc, p, n, es] + for sc, p, n in mTEPES.sc * mTEPES.p * mTEPES.n) == 0: + for sc, p, n in mTEPES.sc * mTEPES.p * mTEPES.n: + OptModel.vEnergyOutflows[sc, p, n, es].fix(0.0) - # fixing the voltage angle of the reference node for each scenario, period, and load level - for sc,p,n in mTEPES.sc*mTEPES.p*mTEPES.n: - OptModel.vTheta[sc,p,n,mTEPES.rf.first()].fix(0.0) + # fixing the voltage angle of the reference node for each scenario, + # period, and load level + for sc, p, n in mTEPES.sc * mTEPES.p * mTEPES.n: + OptModel.vTheta[sc, p, n, mTEPES.rf.first()].fix(0.0) # fixing the ENS in nodes with no demand - for sc,p,n,nd in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nd: - if mTEPES.pDemand[sc,p,n,nd] == 0.0: - OptModel.vENS [sc,p,n,nd].fix(0.0) + for sc, p, n, nd in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.nd: + if mTEPES.pDemand[sc, p, n, nd] == 0.0: + OptModel.vENS[sc, p, n, nd].fix(0.0) SettingUpVariablesTime = time.time() - StartTime - print('Setting up variables ... ', round(SettingUpVariablesTime), 's') + print('Setting up variables ... ', + round(SettingUpVariablesTime), 's') diff --git a/openTEPES/openTEPES_Main.py b/openTEPES/openTEPES_Main.py index 77dbe3f4..16f395ca 100644 --- a/openTEPES/openTEPES_Main.py +++ b/openTEPES/openTEPES_Main.py @@ -81,31 +81,34 @@ # Sara.Lumbreras@comillas.edu # https://pascua.iit.comillas.edu/aramos/Ramos_CV.htm -# with the very valuable collaboration from David Dominguez (david.dominguez@comillas.edu) and Alejandro Rodriguez (argallego@comillas.edu), our local Python gurus +# with the very valuable collaboration from David Dominguez +# (david.dominguez@comillas.edu) and Alejandro Rodriguez +# (argallego@comillas.edu), our local Python gurus -#%% libraries +# %% libraries import argparse import os # import pkg_resources from .openTEPES import openTEPES_run parser = argparse.ArgumentParser(description='Introducing main parameters...') -parser.add_argument('--case', type=str, default=None) -parser.add_argument('--dir', type=str, default=None) +parser.add_argument('--case', type=str, default=None) +parser.add_argument('--dir', type=str, default=None) parser.add_argument('--solver', type=str, default=None) -DIR = os.path.dirname(__file__) -CASE = '9n' +DIR = os.path.dirname(__file__) +CASE = '9n' SOLVER = 'glpk' + def main(): args = parser.parse_args() if args.dir is None: - args.dir = input('Input Dir Name (Default {}): '.format(DIR)) + args.dir = input('Input Dir Name (Default {}): '.format(DIR)) if args.dir == '': args.dir = DIR if args.case is None: - args.case = input('Input Case Name (Default {}): '.format(CASE)) + args.case = input('Input Case Name (Default {}): '.format(CASE)) if args.case == '': args.case = CASE if args.solver is None: @@ -121,5 +124,6 @@ def main(): openTEPES_run(args.dir, args.case, args.solver) sys.exit('End of the run ...') + if __name__ == '__main__': main() diff --git a/openTEPES/openTEPES_ModelFormulation.py b/openTEPES/openTEPES_ModelFormulation.py index 17076d1e..d873b63c 100644 --- a/openTEPES/openTEPES_ModelFormulation.py +++ b/openTEPES/openTEPES_ModelFormulation.py @@ -3,8 +3,8 @@ """ import time -from collections import defaultdict -from pyomo.environ import Set, Constraint, Objective, Block, minimize +from collections import defaultdict +from pyomo.environ import Set, Constraint, Objective, Block, minimize def InvestmentModelFormulation(OptModel, mTEPES, pIndLogConsole): @@ -13,16 +13,36 @@ def InvestmentModelFormulation(OptModel, mTEPES, pIndLogConsole): StartTime = time.time() def eTotalTCost(OptModel): - return OptModel.vTotalFCost + sum(mTEPES.pScenProb[sc] * (OptModel.vTotalGCost[sc,p,n] + OptModel.vTotalCCost[sc,p,n] + OptModel.vTotalECost[sc,p,n] + OptModel.vTotalRCost[sc,p,n]) for sc,p,n in mTEPES.sc*mTEPES.p*mTEPES.n) - OptModel.eTotalTCost = Objective(rule=eTotalTCost, sense=minimize, doc='total system cost [MEUR]') + return OptModel.vTotalFCost + sum(mTEPES.pScenProb[sc] * (OptModel.vTotalGCost[sc, + p, + n] + OptModel.vTotalCCost[sc, + p, + n] + OptModel.vTotalECost[sc, + p, + n] + OptModel.vTotalRCost[sc, + p, + n]) for sc, + p, + n in mTEPES.sc * mTEPES.p * mTEPES.n) + OptModel.eTotalTCost = Objective( + rule=eTotalTCost, + sense=minimize, + doc='total system cost [MEUR]') def eTotalFCost(OptModel): - return OptModel.vTotalFCost == sum(mTEPES.pGenFixedCost[gc] * OptModel.vGenerationInvest[gc] for gc in mTEPES.gc) + sum(mTEPES.pNetFixedCost[lc] * OptModel.vNetworkInvest[lc] for lc in mTEPES.lc) - OptModel.eTotalFCost = Constraint(rule=eTotalFCost, doc='system fixed cost [MEUR]') + return OptModel.vTotalFCost == sum( + mTEPES.pGenFixedCost[gc] * OptModel.vGenerationInvest[gc] for gc in mTEPES.gc) + sum( + mTEPES.pNetFixedCost[lc] * OptModel.vNetworkInvest[lc] for lc in mTEPES.lc) + OptModel.eTotalFCost = Constraint( + rule=eTotalFCost, + doc='system fixed cost [MEUR]') GeneratingOFTime = time.time() - StartTime if pIndLogConsole == 1: - print('Generating investment o.f. ... ', round(GeneratingOFTime), 's') + print( + 'Generating investment o.f. ... ', + round(GeneratingOFTime), + 's') def GenerationOperationModelFormulation(OptModel, mTEPES, pIndLogConsole, st): @@ -30,213 +50,587 @@ def GenerationOperationModelFormulation(OptModel, mTEPES, pIndLogConsole, st): StartTime = time.time() - def eTotalGCost(OptModel,sc,p,n): - return OptModel.vTotalGCost[sc,p,n] == (sum(mTEPES.pLinearVarCost [nr] * mTEPES.pLoadLevelWeight[n] * mTEPES.pDuration[n] * OptModel.vTotalOutput[sc,p,n,nr] + - mTEPES.pConstantVarCost[nr] * mTEPES.pLoadLevelWeight[n] * mTEPES.pDuration[n] * OptModel.vCommitment [sc,p,n,nr] + - mTEPES.pStartUpCost [nr] * mTEPES.pLoadLevelWeight[n] * OptModel.vStartUp [sc,p,n,nr] + - mTEPES.pShutDownCost [nr] * mTEPES.pLoadLevelWeight[n] * OptModel.vShutDown [sc,p,n,nr] for nr in mTEPES.nr) + - sum(mTEPES.pLinearOMCost [ r] * mTEPES.pLoadLevelWeight[n] * mTEPES.pDuration[n] * OptModel.vTotalOutput[sc,p,n, r] for r in mTEPES.r ) ) - setattr(OptModel, 'eTotalGCost_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, rule=eTotalGCost, doc='system variable generation operation cost [MEUR]')) - - def eTotalCCost(OptModel,sc,p,n): - if sum(mTEPES.pLinearVarCost [es] for es in mTEPES.es): - return OptModel.vTotalCCost[sc,p,n] == sum(mTEPES.pLinearVarCost [es] * mTEPES.pLoadLevelWeight[n] * mTEPES.pDuration[n] * OptModel.vESSTotalCharge[sc,p,n,es] for es in mTEPES.es) + def eTotalGCost(OptModel, sc, p, n): + return OptModel.vTotalGCost[sc, p, n] == (sum(mTEPES.pLinearVarCost[nr] * + mTEPES.pLoadLevelWeight[n] * + mTEPES.pDuration[n] * + OptModel.vTotalOutput[sc, p, n, nr] + + mTEPES.pConstantVarCost[nr] * + mTEPES.pLoadLevelWeight[n] * + mTEPES.pDuration[n] * + OptModel.vCommitment[sc, p, n, nr] + + mTEPES.pStartUpCost[nr] * + mTEPES.pLoadLevelWeight[n] * + OptModel.vStartUp[sc, p, n, nr] + + mTEPES.pShutDownCost[nr] * + mTEPES.pLoadLevelWeight[n] * + OptModel.vShutDown[sc, p, n, nr] for nr in mTEPES.nr) + + sum(mTEPES.pLinearOMCost[r] * + mTEPES.pLoadLevelWeight[n] * + mTEPES.pDuration[n] * + OptModel.vTotalOutput[sc, p, n, r] for r in mTEPES.r)) + setattr( + OptModel, + 'eTotalGCost_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + rule=eTotalGCost, + doc='system variable generation operation cost [MEUR]')) + + def eTotalCCost(OptModel, sc, p, n): + if sum(mTEPES.pLinearVarCost[es] for es in mTEPES.es): + return OptModel.vTotalCCost[sc, p, n] == sum(mTEPES.pLinearVarCost[es] * + mTEPES.pLoadLevelWeight[n] * + mTEPES.pDuration[n] * + OptModel.vESSTotalCharge[sc, p, n, es] for es in mTEPES.es) else: return Constraint.Skip - setattr(OptModel, 'eTotalCCost_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, rule=eTotalCCost, doc='system variable consumption operation cost [MEUR]')) - - def eTotalECost(OptModel,sc,p,n): + setattr( + OptModel, + 'eTotalCCost_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + rule=eTotalCCost, + doc='system variable consumption operation cost [MEUR]')) + + def eTotalECost(OptModel, sc, p, n): if sum(mTEPES.pCO2EmissionCost[nr] for nr in mTEPES.nr): - return OptModel.vTotalECost[sc,p,n] == sum(mTEPES.pCO2EmissionCost[nr] * mTEPES.pLoadLevelWeight[n] * mTEPES.pDuration[n] * OptModel.vTotalOutput [sc,p,n,nr] for nr in mTEPES.nr) + return OptModel.vTotalECost[sc, p, n] == sum(mTEPES.pCO2EmissionCost[nr] * + mTEPES.pLoadLevelWeight[n] * + mTEPES.pDuration[n] * + OptModel.vTotalOutput[sc, p, n, nr] for nr in mTEPES.nr) else: return Constraint.Skip - setattr(OptModel, 'eTotalECost_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, rule=eTotalECost, doc='system emission cost [MEUR]')) - - def eTotalRCost(OptModel,sc,p,n): - return OptModel.vTotalRCost[sc,p,n] == sum(mTEPES.pENSCost * mTEPES.pLoadLevelWeight[n] * mTEPES.pDuration[n] * OptModel.vENS [sc,p,n,nd] for nd in mTEPES.nd) - setattr(OptModel, 'eTotalRCost_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, rule=eTotalRCost, doc='system reliability cost [MEUR]')) + setattr( + OptModel, + 'eTotalECost_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + rule=eTotalECost, + doc='system emission cost [MEUR]')) + + def eTotalRCost(OptModel, sc, p, n): + return OptModel.vTotalRCost[sc, p, n] == sum(mTEPES.pENSCost * + mTEPES.pLoadLevelWeight[n] * + mTEPES.pDuration[n] * + OptModel.vENS[sc, p, n, nd] for nd in mTEPES.nd) + setattr( + OptModel, + 'eTotalRCost_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + rule=eTotalRCost, + doc='system reliability cost [MEUR]')) GeneratingOFTime = time.time() - StartTime - StartTime = time.time() + StartTime = time.time() if pIndLogConsole == 1: - print('Generating operation o.f. ... ', round(GeneratingOFTime), 's') + print( + 'Generating operation o.f. ... ', + round(GeneratingOFTime), + 's') StartTime = time.time() - #%% constraints + # %% constraints - def eInstalGenComm(OptModel,sc,p,n,gc): - if gc in mTEPES.nr and gc not in mTEPES.es and mTEPES.pMustRun[gc] == 0 and (mTEPES.pMinPower[sc,p,n,gc] > 0.0 or mTEPES.pConstantVarCost[gc] > 0.0): - return OptModel.vCommitment[sc,p,n,gc] <= OptModel.vGenerationInvest[gc] + def eInstalGenComm(OptModel, sc, p, n, gc): + if gc in mTEPES.nr and gc not in mTEPES.es and mTEPES.pMustRun[gc] == 0 and ( + mTEPES.pMinPower[sc, p, n, gc] > 0.0 or mTEPES.pConstantVarCost[gc] > 0.0): + return OptModel.vCommitment[sc, p, n, + gc] <= OptModel.vGenerationInvest[gc] else: return Constraint.Skip - setattr(OptModel, 'eInstalGenComm_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.gc, rule=eInstalGenComm, doc='commitment if installed unit [p.u.]')) + setattr( + OptModel, + 'eInstalGenComm_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.gc, + rule=eInstalGenComm, + doc='commitment if installed unit [p.u.]')) if pIndLogConsole == 1: - print('eInstalGenComm ... ', len(getattr(OptModel, 'eInstalGenComm_'+st)), ' rows') - - def eInstalGenCap(OptModel,sc,p,n,gc): - if mTEPES.pMaxPower[sc,p,n,gc]: - return OptModel.vTotalOutput[sc,p,n,gc] / mTEPES.pMaxPower[sc,p,n,gc] <= OptModel.vGenerationInvest[gc] + print('eInstalGenComm ... ', len( + getattr(OptModel, 'eInstalGenComm_' + st)), ' rows') + + def eInstalGenCap(OptModel, sc, p, n, gc): + if mTEPES.pMaxPower[sc, p, n, gc]: + return OptModel.vTotalOutput[sc, + p, + n, + gc] / mTEPES.pMaxPower[sc, + p, + n, + gc] <= OptModel.vGenerationInvest[gc] else: - return OptModel.vTotalOutput[sc,p,n,gc] <= 0.0 - setattr(OptModel, 'eInstalGenCap_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.gc, rule=eInstalGenCap, doc='output if installed gen unit [p.u.]')) + return OptModel.vTotalOutput[sc, p, n, gc] <= 0.0 + setattr( + OptModel, + 'eInstalGenCap_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.gc, + rule=eInstalGenCap, + doc='output if installed gen unit [p.u.]')) if pIndLogConsole == 1: - print('eInstalGenCap ... ', len(getattr(OptModel, 'eInstalGenCap_'+st)), ' rows') - - def eInstalConESS(OptModel,sc,p,n,ec): - return OptModel.vESSTotalCharge [sc,p,n,ec] / mTEPES.pMaxCharge[sc,p,n,ec] <= OptModel.vGenerationInvest[ec] - setattr(OptModel, 'eInstalConESS_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.ec, rule=eInstalConESS, doc='consumption if installed ESS unit [p.u.]')) + print('eInstalGenCap ... ', len( + getattr(OptModel, 'eInstalGenCap_' + st)), ' rows') + + def eInstalConESS(OptModel, sc, p, n, ec): + return OptModel.vESSTotalCharge[sc, + p, + n, + ec] / mTEPES.pMaxCharge[sc, + p, + n, + ec] <= OptModel.vGenerationInvest[ec] + setattr( + OptModel, + 'eInstalConESS_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.ec, + rule=eInstalConESS, + doc='consumption if installed ESS unit [p.u.]')) if pIndLogConsole == 1: - print('eInstalConESS ... ', len(getattr(OptModel, 'eInstalConESS_'+st)), ' rows') - - def eAdequacyReserveMargin(OptModel,ar): - if mTEPES.pReserveMargin[ar] and sum(1 for g in mTEPES.g if (ar,g) in mTEPES.a2g): - return ((sum( mTEPES.pRatedMaxPower[g ] * mTEPES.pAvailability[g ] / (1.0-mTEPES.pEFOR[g ]) for g in mTEPES.g if (ar,g ) in mTEPES.a2g and g not in mTEPES.gc) + - sum(OptModel.vGenerationInvest[gc] * mTEPES.pRatedMaxPower[gc] * mTEPES.pAvailability[gc] / (1.0-mTEPES.pEFOR[gc]) for gc in mTEPES.gc if (ar,gc) in mTEPES.a2g ) ) >= mTEPES.pPeakDemand[ar] * mTEPES.pReserveMargin[ar]) + print('eInstalConESS ... ', len( + getattr(OptModel, 'eInstalConESS_' + st)), ' rows') + + def eAdequacyReserveMargin(OptModel, ar): + if mTEPES.pReserveMargin[ar] and sum( + 1 for g in mTEPES.g if (ar, g) in mTEPES.a2g): + return ((sum(mTEPES.pRatedMaxPower[g] * + mTEPES.pAvailability[g] / + (1.0 - + mTEPES.pEFOR[g]) for g in mTEPES.g if (ar, g) in mTEPES.a2g and g not in mTEPES.gc) + + sum(OptModel.vGenerationInvest[gc] * + mTEPES.pRatedMaxPower[gc] * + mTEPES.pAvailability[gc] / + (1.0 - + mTEPES.pEFOR[gc]) for gc in mTEPES.gc if (ar, gc) in mTEPES.a2g)) >= mTEPES.pPeakDemand[ar] * + mTEPES.pReserveMargin[ar]) else: return Constraint.Skip - setattr(OptModel, 'eAdequacyReserveMargin_'+st, Constraint(mTEPES.ar, rule=eAdequacyReserveMargin, doc='system adequacy reserve margin [p.u.]')) + setattr( + OptModel, + 'eAdequacyReserveMargin_' + st, + Constraint( + mTEPES.ar, + rule=eAdequacyReserveMargin, + doc='system adequacy reserve margin [p.u.]')) if pIndLogConsole == 1: - print('eAdequacyReserveMargin... ', len(getattr(OptModel, 'eAdequacyReserveMargin_'+st)), ' rows') - - def eSystemInertia(OptModel,sc,p,n,ar): - if mTEPES.pSystemInertia[sc,p,n,ar] and sum(1 for nr in mTEPES.nr if (ar,nr) in mTEPES.a2g) + sum(1 for es in mTEPES.es if (ar,es) in mTEPES.a2g): - return sum(OptModel.vCommitment[sc,p,n,nr] * mTEPES.pInertia[nr] for nr in mTEPES.nr if (ar,nr) in mTEPES.a2g) >= mTEPES.pSystemInertia[sc,p,n,ar] + print( + 'eAdequacyReserveMargin... ', len( + getattr( + OptModel, 'eAdequacyReserveMargin_' + st)), ' rows') + + def eSystemInertia(OptModel, sc, p, n, ar): + if mTEPES.pSystemInertia[sc, p, n, ar] and sum(1 for nr in mTEPES.nr if ( + ar, nr) in mTEPES.a2g) + sum(1 for es in mTEPES.es if (ar, es) in mTEPES.a2g): + return sum(OptModel.vCommitment[sc, p, n, nr] * mTEPES.pInertia[nr] + for nr in mTEPES.nr if (ar, nr) in mTEPES.a2g) >= mTEPES.pSystemInertia[sc, p, n, ar] else: return Constraint.Skip - setattr(OptModel, 'eSystemInertia_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.ar, rule=eSystemInertia, doc='system inertia [s]')) + setattr( + OptModel, + 'eSystemInertia_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.ar, + rule=eSystemInertia, + doc='system inertia [s]')) if pIndLogConsole == 1: - print('eSystemInertia ... ', len(getattr(OptModel, 'eSystemInertia_'+st)), ' rows') - - #%% - def eOperReserveUp(OptModel,sc,p,n,ar): - if mTEPES.pOperReserveUp[sc,p,n,ar] and sum(1 for nr in mTEPES.nr if (ar,nr) in mTEPES.a2g) + sum(1 for es in mTEPES.es if (ar,es) in mTEPES.a2g): - return sum(OptModel.vReserveUp [sc,p,n,nr] for nr in mTEPES.nr if (ar,nr) in mTEPES.a2g) + sum(OptModel.vESSReserveUp [sc,p,n,es] for es in mTEPES.es if (ar,es) in mTEPES.a2g) == mTEPES.pOperReserveUp[sc,p,n,ar] + print('eSystemInertia ... ', len( + getattr(OptModel, 'eSystemInertia_' + st)), ' rows') + + # %% + def eOperReserveUp(OptModel, sc, p, n, ar): + if mTEPES.pOperReserveUp[sc, p, n, ar] and sum(1 for nr in mTEPES.nr if ( + ar, nr) in mTEPES.a2g) + sum(1 for es in mTEPES.es if (ar, es) in mTEPES.a2g): + return sum(OptModel.vReserveUp[sc, + p, + n, + nr] for nr in mTEPES.nr if (ar, + nr) in mTEPES.a2g) + sum(OptModel.vESSReserveUp[sc, + p, + n, + es] for es in mTEPES.es if (ar, + es) in mTEPES.a2g) == mTEPES.pOperReserveUp[sc, + p, + n, + ar] else: return Constraint.Skip - setattr(OptModel, 'eOperReserveUp_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.ar, rule=eOperReserveUp, doc='up operating reserve [GW]')) + setattr( + OptModel, + 'eOperReserveUp_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.ar, + rule=eOperReserveUp, + doc='up operating reserve [GW]')) if pIndLogConsole == 1: - print('eOperReserveUp ... ', len(getattr(OptModel, 'eOperReserveUp_'+st)), ' rows') - - def eOperReserveDw(OptModel,sc,p,n,ar): - if mTEPES.pOperReserveDw[sc,p,n,ar] and sum(1 for nr in mTEPES.nr if (ar,nr) in mTEPES.a2g) + sum(1 for es in mTEPES.es if (ar,es) in mTEPES.a2g): - return sum(OptModel.vReserveDown[sc,p,n,nr] for nr in mTEPES.nr if (ar,nr) in mTEPES.a2g) + sum(OptModel.vESSReserveDown[sc,p,n,es] for es in mTEPES.es if (ar,es) in mTEPES.a2g) == mTEPES.pOperReserveDw[sc,p,n,ar] + print('eOperReserveUp ... ', len( + getattr(OptModel, 'eOperReserveUp_' + st)), ' rows') + + def eOperReserveDw(OptModel, sc, p, n, ar): + if mTEPES.pOperReserveDw[sc, p, n, ar] and sum(1 for nr in mTEPES.nr if ( + ar, nr) in mTEPES.a2g) + sum(1 for es in mTEPES.es if (ar, es) in mTEPES.a2g): + return sum(OptModel.vReserveDown[sc, + p, + n, + nr] for nr in mTEPES.nr if (ar, + nr) in mTEPES.a2g) + sum(OptModel.vESSReserveDown[sc, + p, + n, + es] for es in mTEPES.es if (ar, + es) in mTEPES.a2g) == mTEPES.pOperReserveDw[sc, + p, + n, + ar] else: return Constraint.Skip - setattr(OptModel, 'eOperReserveDw_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.ar, rule=eOperReserveDw, doc='down operating reserve [GW]')) + setattr( + OptModel, + 'eOperReserveDw_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.ar, + rule=eOperReserveDw, + doc='down operating reserve [GW]')) if pIndLogConsole == 1: - print('eOperReserveDw ... ', len(getattr(OptModel, 'eOperReserveDw_'+st)), ' rows') - - #%% - def eReserveUpIfEnergy(OptModel,sc,p,n,es): - if sum(mTEPES.pOperReserveUp[sc,p,n,ar] for ar in mTEPES.ar if (ar,es) in mTEPES.a2g) and mTEPES.pMaxPower2ndBlock[sc,p,n,es]: - return OptModel.vReserveUp [sc,p,n,es] <= OptModel.vESSInventory[sc,p,n,es] / mTEPES.pDuration[n] + print('eOperReserveDw ... ', len( + getattr(OptModel, 'eOperReserveDw_' + st)), ' rows') + + # %% + def eReserveUpIfEnergy(OptModel, sc, p, n, es): + if sum(mTEPES.pOperReserveUp[sc, p, n, ar] for ar in mTEPES.ar if ( + ar, es) in mTEPES.a2g) and mTEPES.pMaxPower2ndBlock[sc, p, n, es]: + return OptModel.vReserveUp[sc, + p, + n, + es] <= OptModel.vESSInventory[sc, + p, + n, + es] / mTEPES.pDuration[n] else: return Constraint.Skip - setattr(OptModel, 'eReserveUpIfEnergy_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.es, rule=eReserveUpIfEnergy, doc='up operating reserve if energy available [GW]')) + setattr( + OptModel, + 'eReserveUpIfEnergy_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.es, + rule=eReserveUpIfEnergy, + doc='up operating reserve if energy available [GW]')) if pIndLogConsole == 1: - print('eReserveUpIfEnergy ... ', len(getattr(OptModel, 'eReserveUpIfEnergy_'+st)), ' rows') - - def eReserveDwIfEnergy(OptModel,sc,p,n,es): - if sum(mTEPES.pOperReserveDw[sc,p,n,ar] for ar in mTEPES.ar if (ar,es) in mTEPES.a2g) and mTEPES.pMaxPower2ndBlock[sc,p,n,es]: - return OptModel.vReserveDown[sc,p,n,es] <= (mTEPES.pMaxStorage[sc,p,n,es] - OptModel.vESSInventory[sc,p,n,es]) / mTEPES.pDuration[n] + print( + 'eReserveUpIfEnergy ... ', len( + getattr( + OptModel, 'eReserveUpIfEnergy_' + st)), ' rows') + + def eReserveDwIfEnergy(OptModel, sc, p, n, es): + if sum(mTEPES.pOperReserveDw[sc, p, n, ar] for ar in mTEPES.ar if ( + ar, es) in mTEPES.a2g) and mTEPES.pMaxPower2ndBlock[sc, p, n, es]: + return OptModel.vReserveDown[sc, + p, + n, + es] <= (mTEPES.pMaxStorage[sc, + p, + n, + es] - OptModel.vESSInventory[sc, + p, + n, + es]) / mTEPES.pDuration[n] else: return Constraint.Skip - setattr(OptModel, 'eReserveDwIfEnergy_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.es, rule=eReserveDwIfEnergy, doc='down operating reserve if energy available [GW]')) + setattr( + OptModel, + 'eReserveDwIfEnergy_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.es, + rule=eReserveDwIfEnergy, + doc='down operating reserve if energy available [GW]')) if pIndLogConsole == 1: - print('eReserveDwIfEnergy ... ', len(getattr(OptModel, 'eReserveDwIfEnergy_'+st)), ' rows') - - def eESSReserveUpIfEnergy(OptModel,sc,p,n,es): - if sum(mTEPES.pOperReserveUp[sc,p,n,ar] for ar in mTEPES.ar if (ar,es) in mTEPES.a2g) and mTEPES.pMaxCharge2ndBlock[sc,p,n,es]: - return OptModel.vESSReserveUp [sc,p,n,es] <= (mTEPES.pMaxStorage[sc,p,n,es] - OptModel.vESSInventory[sc,p,n,es]) / mTEPES.pDuration[n] + print( + 'eReserveDwIfEnergy ... ', len( + getattr( + OptModel, 'eReserveDwIfEnergy_' + st)), ' rows') + + def eESSReserveUpIfEnergy(OptModel, sc, p, n, es): + if sum(mTEPES.pOperReserveUp[sc, p, n, ar] for ar in mTEPES.ar if ( + ar, es) in mTEPES.a2g) and mTEPES.pMaxCharge2ndBlock[sc, p, n, es]: + return OptModel.vESSReserveUp[sc, + p, + n, + es] <= (mTEPES.pMaxStorage[sc, + p, + n, + es] - OptModel.vESSInventory[sc, + p, + n, + es]) / mTEPES.pDuration[n] else: return Constraint.Skip - setattr(OptModel, 'eESSReserveUpIfEnergy_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.es, rule=eESSReserveUpIfEnergy, doc='up operating reserve if energy available [GW]')) + setattr( + OptModel, + 'eESSReserveUpIfEnergy_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.es, + rule=eESSReserveUpIfEnergy, + doc='up operating reserve if energy available [GW]')) if pIndLogConsole == 1: - print('eESSReserveUpIfEnergy ... ', len(getattr(OptModel, 'eESSReserveUpIfEnergy_'+st)), ' rows') - - def eESSReserveDwIfEnergy(OptModel,sc,p,n,es): - if sum(mTEPES.pOperReserveDw[sc,p,n,ar] for ar in mTEPES.ar if (ar,es) in mTEPES.a2g) and mTEPES.pMaxCharge2ndBlock[sc,p,n,es]: - return OptModel.vESSReserveDown[sc,p,n,es] <= OptModel.vESSInventory[sc,p,n,es] / mTEPES.pDuration[n] + print( + 'eESSReserveUpIfEnergy ... ', len( + getattr( + OptModel, 'eESSReserveUpIfEnergy_' + st)), ' rows') + + def eESSReserveDwIfEnergy(OptModel, sc, p, n, es): + if sum(mTEPES.pOperReserveDw[sc, p, n, ar] for ar in mTEPES.ar if ( + ar, es) in mTEPES.a2g) and mTEPES.pMaxCharge2ndBlock[sc, p, n, es]: + return OptModel.vESSReserveDown[sc, + p, + n, + es] <= OptModel.vESSInventory[sc, + p, + n, + es] / mTEPES.pDuration[n] else: return Constraint.Skip - setattr(OptModel, 'eESSReserveDwIfEnergy_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.es, rule=eESSReserveDwIfEnergy, doc='down operating reserve if energy available [GW]')) + setattr( + OptModel, + 'eESSReserveDwIfEnergy_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.es, + rule=eESSReserveDwIfEnergy, + doc='down operating reserve if energy available [GW]')) if pIndLogConsole == 1: - print('eESSReserveDwIfEnergy ... ', len(getattr(OptModel, 'eESSReserveDwIfEnergy_'+st)), ' rows') + print( + 'eESSReserveDwIfEnergy ... ', len( + getattr( + OptModel, 'eESSReserveDwIfEnergy_' + st)), ' rows') # incoming and outgoing lines (lin) (lout) - lin = defaultdict(list) - linl = defaultdict(list) - lout = defaultdict(list) + lin = defaultdict(list) + linl = defaultdict(list) + lout = defaultdict(list) loutl = defaultdict(list) - for ni,nf,cc in mTEPES.la: - lin [nf].append((ni,cc)) - lout [ni].append((nf,cc)) - for ni,nf,cc in mTEPES.ll: - linl [nf].append((ni,cc)) - loutl[ni].append((nf,cc)) - - #%% - def eBalance(OptModel,sc,p,n,nd): - if sum(1 for g in mTEPES.g if (nd,g) in mTEPES.n2g) + sum(1 for lout in lout[nd]) + sum(1 for ni,cc in lin[nd]): - return (sum(OptModel.vTotalOutput[sc,p,n,g] for g in mTEPES.g if (nd,g) in mTEPES.n2g) - sum(OptModel.vESSTotalCharge[sc,p,n,es] for es in mTEPES.es if (nd,es) in mTEPES.n2g) + OptModel.vENS[sc,p,n,nd] == mTEPES.pDemand[sc,p,n,nd] + - sum(OptModel.vLineLosses[sc,p,n,nd,lout ] for lout in loutl[nd]) + sum(OptModel.vFlow[sc,p,n,nd,lout ] for lout in lout[nd]) + - sum(OptModel.vLineLosses[sc,p,n,ni,nd,cc] for ni,cc in linl [nd]) - sum(OptModel.vFlow[sc,p,n,ni,nd,cc] for ni,cc in lin [nd])) + for ni, nf, cc in mTEPES.la: + lin[nf].append((ni, cc)) + lout[ni].append((nf, cc)) + for ni, nf, cc in mTEPES.ll: + linl[nf].append((ni, cc)) + loutl[ni].append((nf, cc)) + + # %% + def eBalance(OptModel, sc, p, n, nd): + if sum(1 for g in mTEPES.g if (nd, g) in mTEPES.n2g) + \ + sum(1 for lout in lout[nd]) + sum(1 for ni, cc in lin[nd]): + return (sum(OptModel.vTotalOutput[sc, p, n, g] for g in mTEPES.g if (nd, g) in mTEPES.n2g) - + sum(OptModel.vESSTotalCharge[sc, p, n, es] for es in mTEPES.es if (nd, es) in mTEPES.n2g) + + OptModel.vENS[sc, p, n, nd] == mTEPES.pDemand[sc, p, n, nd] + + sum(OptModel.vLineLosses[sc, p, n, nd, lout] for lout in loutl[nd]) + + sum(OptModel.vFlow[sc, p, n, nd, lout] for lout in lout[nd]) + + sum(OptModel.vLineLosses[sc, p, n, ni, nd, cc] for ni, cc in linl[nd]) - + sum(OptModel.vFlow[sc, p, n, ni, nd, cc] for ni, cc in lin[nd])) else: return Constraint.Skip - setattr(OptModel, 'eBalance_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.nd, rule=eBalance, doc='load generation balance [GW]')) + setattr( + OptModel, + 'eBalance_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.nd, + rule=eBalance, + doc='load generation balance [GW]')) if pIndLogConsole == 1: - print('eBalance ... ', len(getattr(OptModel, 'eBalance_'+st)), ' rows') - - def eESSInventory(OptModel,sc,p,n,es): - if mTEPES.n.ord(n) == mTEPES.pCycleTimeStep[es]: - return mTEPES.pIniInventory[sc,p,n,es] + sum(mTEPES.pDuration[n2]*(mTEPES.pEnergyInflows[sc,p,n2,es] - OptModel.vEnergyOutflows[sc,p,n2,es] - OptModel.vTotalOutput[sc,p,n2,es] + mTEPES.pEfficiency[es]*OptModel.vESSTotalCharge[sc,p,n2,es]) for n2 in list(mTEPES.n2)[mTEPES.n.ord(n)-mTEPES.pCycleTimeStep[es]:mTEPES.n.ord(n)]) == OptModel.vESSInventory[sc,p,n,es] + OptModel.vESSSpillage[sc,p,n,es] - elif mTEPES.n.ord(n) > mTEPES.pCycleTimeStep[es] and mTEPES.n.ord(n) % mTEPES.pCycleTimeStep[es] == 0: - return OptModel.vESSInventory[sc,p,mTEPES.n.prev(n,mTEPES.pCycleTimeStep[es]),es] + sum(mTEPES.pDuration[n2]*(mTEPES.pEnergyInflows[sc,p,n2,es] - OptModel.vEnergyOutflows[sc,p,n2,es] - OptModel.vTotalOutput[sc,p,n2,es] + mTEPES.pEfficiency[es]*OptModel.vESSTotalCharge[sc,p,n2,es]) for n2 in list(mTEPES.n2)[mTEPES.n.ord(n)-mTEPES.pCycleTimeStep[es]:mTEPES.n.ord(n)]) == OptModel.vESSInventory[sc,p,n,es] + OptModel.vESSSpillage[sc,p,n,es] + print('eBalance ... ', len( + getattr(OptModel, 'eBalance_' + st)), ' rows') + + def eESSInventory(OptModel, sc, p, n, es): + if mTEPES.n.ord(n) == mTEPES.pCycleTimeStep[es]: + return mTEPES.pIniInventory[sc, + p, + n, + es] + sum(mTEPES.pDuration[n2] * (mTEPES.pEnergyInflows[sc, + p, + n2, + es] - OptModel.vEnergyOutflows[sc, + p, + n2, + es] - OptModel.vTotalOutput[sc, + p, + n2, + es] + mTEPES.pEfficiency[es] * OptModel.vESSTotalCharge[sc, + p, + n2, + es]) for n2 in list(mTEPES.n2)[mTEPES.n.ord(n) - mTEPES.pCycleTimeStep[es]:mTEPES.n.ord(n)]) == OptModel.vESSInventory[sc, + p, + n, + es] + OptModel.vESSSpillage[sc, + p, + n, + es] + elif mTEPES.n.ord(n) > mTEPES.pCycleTimeStep[es] and mTEPES.n.ord(n) % mTEPES.pCycleTimeStep[es] == 0: + return OptModel.vESSInventory[sc, + p, + mTEPES.n.prev(n, + mTEPES.pCycleTimeStep[es]), + es] + sum(mTEPES.pDuration[n2] * (mTEPES.pEnergyInflows[sc, + p, + n2, + es] - OptModel.vEnergyOutflows[sc, + p, + n2, + es] - OptModel.vTotalOutput[sc, + p, + n2, + es] + mTEPES.pEfficiency[es] * OptModel.vESSTotalCharge[sc, + p, + n2, + es]) for n2 in list(mTEPES.n2)[mTEPES.n.ord(n) - mTEPES.pCycleTimeStep[es]:mTEPES.n.ord(n)]) == OptModel.vESSInventory[sc, + p, + n, + es] + OptModel.vESSSpillage[sc, + p, + n, + es] else: return Constraint.Skip - setattr(OptModel, 'eESSInventory_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.es, rule=eESSInventory, doc='ESS inventory balance [GWh]')) + setattr( + OptModel, + 'eESSInventory_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.es, + rule=eESSInventory, + doc='ESS inventory balance [GWh]')) if pIndLogConsole == 1: - print('eESSInventory ... ', len(getattr(OptModel, 'eESSInventory_'+st)), ' rows') + print('eESSInventory ... ', len( + getattr(OptModel, 'eESSInventory_' + st)), ' rows') GeneratingRBITime = time.time() - StartTime - StartTime = time.time() + StartTime = time.time() if pIndLogConsole == 1: - print('Generating reserves/balance/inventory ... ', round(GeneratingRBITime), 's') - - #%% - def eMaxCharge(OptModel,sc,p,n,es): - if sum(mTEPES.pOperReserveDw[sc,p,n,ar] for ar in mTEPES.ar if (ar,es) in mTEPES.a2g) and mTEPES.pMaxCharge[sc,p,n,es]: - return (OptModel.vCharge2ndBlock[sc,p,n,es] + mTEPES.pUpReserveActivation * OptModel.vESSReserveDown[sc,p,n,es] + OptModel.vESSReserveDown[sc,p,n,es]) / mTEPES.pMaxCharge[sc,p,n,es] <= 1.0 + print( + 'Generating reserves/balance/inventory ... ', + round(GeneratingRBITime), + 's') + + # %% + def eMaxCharge(OptModel, sc, p, n, es): + if sum(mTEPES.pOperReserveDw[sc, p, n, ar] for ar in mTEPES.ar if ( + ar, es) in mTEPES.a2g) and mTEPES.pMaxCharge[sc, p, n, es]: + return (OptModel.vCharge2ndBlock[sc, + p, + n, + es] + mTEPES.pUpReserveActivation * OptModel.vESSReserveDown[sc, + p, + n, + es] + OptModel.vESSReserveDown[sc, + p, + n, + es]) / mTEPES.pMaxCharge[sc, + p, + n, + es] <= 1.0 else: return Constraint.Skip - setattr(OptModel, 'eMaxCharge_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.es, rule=eMaxCharge, doc='max charge of an ESS [p.u.]')) + setattr( + OptModel, + 'eMaxCharge_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.es, + rule=eMaxCharge, + doc='max charge of an ESS [p.u.]')) if pIndLogConsole == 1: - print('eMaxCharge ... ', len(getattr(OptModel, 'eMaxCharge_'+st)), ' rows') - - def eMinCharge(OptModel,sc,p,n,es): - if sum(mTEPES.pOperReserveUp[sc,p,n,ar] for ar in mTEPES.ar if (ar,es) in mTEPES.a2g) and mTEPES.pMaxCharge[sc,p,n,es]: - return (OptModel.vCharge2ndBlock[sc,p,n,es] - mTEPES.pDwReserveActivation * OptModel.vESSReserveUp [sc,p,n,es] - OptModel.vESSReserveUp [sc,p,n,es]) / mTEPES.pMaxCharge[sc,p,n,es] >= 0.0 + print('eMaxCharge ... ', len( + getattr(OptModel, 'eMaxCharge_' + st)), ' rows') + + def eMinCharge(OptModel, sc, p, n, es): + if sum(mTEPES.pOperReserveUp[sc, p, n, ar] for ar in mTEPES.ar if ( + ar, es) in mTEPES.a2g) and mTEPES.pMaxCharge[sc, p, n, es]: + return (OptModel.vCharge2ndBlock[sc, + p, + n, + es] - mTEPES.pDwReserveActivation * OptModel.vESSReserveUp[sc, + p, + n, + es] - OptModel.vESSReserveUp[sc, + p, + n, + es]) / mTEPES.pMaxCharge[sc, + p, + n, + es] >= 0.0 else: return Constraint.Skip - setattr(OptModel, 'eMinCharge_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.es, rule=eMinCharge, doc='min charge of an ESS [p.u.]')) + setattr( + OptModel, + 'eMinCharge_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.es, + rule=eMinCharge, + doc='min charge of an ESS [p.u.]')) if pIndLogConsole == 1: - print('eMinCharge ... ', len(getattr(OptModel, 'eMinCharge_'+st)), ' rows') + print('eMinCharge ... ', len( + getattr(OptModel, 'eMinCharge_' + st)), ' rows') # def eChargeDischarge(OptModel,sc,p,n,es): # if mTEPES.pMaxCharge[sc,p,n,es]: @@ -245,306 +639,1044 @@ def eMinCharge(OptModel,sc,p,n,es): # return Constraint.Skip # OptModel.eChargeDischarge = Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.es, rule=eChargeDischarge, doc='incompatibility between charge and discharge [p.u.]') - def eChargeDischarge(OptModel,sc,p,n,es): - if mTEPES.pMaxCharge[sc,p,n,es]: - if sum(mTEPES.pOperReserveDw[sc,p,n,ar] for ar in mTEPES.ar if (ar,es) in mTEPES.a2g): - return ((OptModel.vOutput2ndBlock[sc,p,n,es] + mTEPES.pUpReserveActivation * OptModel.vReserveUp [sc,p,n,es] + OptModel.vReserveUp [sc,p,n,es]) / mTEPES.pMaxPower2ndBlock [sc,p,n,es] + - (OptModel.vCharge2ndBlock[sc,p,n,es] + mTEPES.pUpReserveActivation * OptModel.vESSReserveDown[sc,p,n,es] + OptModel.vESSReserveDown[sc,p,n,es]) / mTEPES.pMaxCharge2ndBlock[sc,p,n,es] <= 1.0) + def eChargeDischarge(OptModel, sc, p, n, es): + if mTEPES.pMaxCharge[sc, p, n, es]: + if sum(mTEPES.pOperReserveDw[sc, p, n, ar] + for ar in mTEPES.ar if (ar, es) in mTEPES.a2g): + return ((OptModel.vOutput2ndBlock[sc, p, n, es] + + mTEPES.pUpReserveActivation * + OptModel.vReserveUp[sc, p, n, es] + + OptModel.vReserveUp[sc, p, n, es]) / + mTEPES.pMaxPower2ndBlock[sc, p, n, es] + + (OptModel.vCharge2ndBlock[sc, p, n, es] + + mTEPES.pUpReserveActivation * + OptModel.vESSReserveDown[sc, p, n, es] + + OptModel.vESSReserveDown[sc, p, n, es]) / + mTEPES.pMaxCharge2ndBlock[sc, p, n, es] <= 1.0) else: - return ((OptModel.vOutput2ndBlock[sc,p,n,es] ) / mTEPES.pMaxPower2ndBlock [sc,p,n,es] + - (OptModel.vCharge2ndBlock[sc,p,n,es] ) / mTEPES.pMaxCharge2ndBlock[sc,p,n,es] <= 1.0) + return ((OptModel.vOutput2ndBlock[sc, p, n, es]) / + mTEPES.pMaxPower2ndBlock[sc, p, n, es] + + (OptModel.vCharge2ndBlock[sc, p, n, es]) / + mTEPES.pMaxCharge2ndBlock[sc, p, n, es] <= 1.0) else: return Constraint.Skip - setattr(OptModel, 'eChargeDischarge_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.es, rule=eChargeDischarge, doc='incompatibility between charge and discharge [p.u.]')) + setattr( + OptModel, + 'eChargeDischarge_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.es, + rule=eChargeDischarge, + doc='incompatibility between charge and discharge [p.u.]')) if pIndLogConsole == 1: - print('eChargeDischarge ... ', len(getattr(OptModel, 'eChargeDischarge_'+st)), ' rows') - - def eESSTotalCharge(OptModel,sc,p,n,es): - if mTEPES.pMaxCharge[sc,p,n,es] and mTEPES.pMaxCharge2ndBlock[sc,p,n,es] and mTEPES.pMinCharge[sc,p,n,es] == 0.0: - return OptModel.vESSTotalCharge[sc,p,n,es] == OptModel.vCharge2ndBlock[sc,p,n,es] + mTEPES.pUpReserveActivation * OptModel.vESSReserveDown[sc,p,n,es] - mTEPES.pDwReserveActivation * OptModel.vESSReserveUp[sc,p,n,es] - elif mTEPES.pMaxCharge[sc,p,n,es] and mTEPES.pMaxCharge2ndBlock[sc,p,n,es]: - return OptModel.vESSTotalCharge[sc,p,n,es] / mTEPES.pMinCharge[sc,p,n,es] == 1 + (OptModel.vCharge2ndBlock[sc,p,n,es] + mTEPES.pUpReserveActivation * OptModel.vESSReserveDown[sc,p,n,es] - mTEPES.pDwReserveActivation * OptModel.vESSReserveUp[sc,p,n,es]) / mTEPES.pMinCharge[sc,p,n,es] + print( + 'eChargeDischarge ... ', len( + getattr( + OptModel, 'eChargeDischarge_' + st)), ' rows') + + def eESSTotalCharge(OptModel, sc, p, n, es): + if mTEPES.pMaxCharge[sc, + p, + n, + es] and mTEPES.pMaxCharge2ndBlock[sc, + p, + n, + es] and mTEPES.pMinCharge[sc, + p, + n, + es] == 0.0: + return OptModel.vESSTotalCharge[sc, + p, + n, + es] == OptModel.vCharge2ndBlock[sc, + p, + n, + es] + mTEPES.pUpReserveActivation * OptModel.vESSReserveDown[sc, + p, + n, + es] - mTEPES.pDwReserveActivation * OptModel.vESSReserveUp[sc, + p, + n, + es] + elif mTEPES.pMaxCharge[sc, p, n, es] and mTEPES.pMaxCharge2ndBlock[sc, p, n, es]: + return OptModel.vESSTotalCharge[sc, + p, + n, + es] / mTEPES.pMinCharge[sc, + p, + n, + es] == 1 + (OptModel.vCharge2ndBlock[sc, + p, + n, + es] + mTEPES.pUpReserveActivation * OptModel.vESSReserveDown[sc, + p, + n, + es] - mTEPES.pDwReserveActivation * OptModel.vESSReserveUp[sc, + p, + n, + es]) / mTEPES.pMinCharge[sc, + p, + n, + es] else: return Constraint.Skip - setattr(OptModel, 'eESSTotalCharge_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.es, rule=eESSTotalCharge, doc='total charge of an ESS unit [GW]')) + setattr( + OptModel, + 'eESSTotalCharge_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.es, + rule=eESSTotalCharge, + doc='total charge of an ESS unit [GW]')) if pIndLogConsole == 1: - print('eESSTotalCharge ... ', len(getattr(OptModel, 'eESSTotalCharge_'+st)), ' rows') - - def eEnergyOutflows(OptModel,sc,p,n,es): - if mTEPES.n.ord(n) % mTEPES.pOutflowsTimeStep[es] == 0 and sum(mTEPES.pEnergyOutflows[sc,p,n2,es] for n2 in mTEPES.n2): - return sum(OptModel.vEnergyOutflows[sc,p,n2,es] for n2 in list(mTEPES.n2)[mTEPES.n.ord(n) - int(mTEPES.pOutflowsTimeStep[es]/mTEPES.pCycleTimeStep[es]):mTEPES.n.ord(n)]) == sum(mTEPES.pEnergyOutflows[sc,p,n2,es] for n2 in list(mTEPES.n2)[mTEPES.n.ord(n) - mTEPES.pOutflowsTimeStep[es]:mTEPES.n.ord(n)]) + print('eESSTotalCharge ... ', len( + getattr(OptModel, 'eESSTotalCharge_' + st)), ' rows') + + def eEnergyOutflows(OptModel, sc, p, n, es): + if mTEPES.n.ord(n) % mTEPES.pOutflowsTimeStep[es] == 0 and sum( + mTEPES.pEnergyOutflows[sc, p, n2, es] for n2 in mTEPES.n2): + return sum(OptModel.vEnergyOutflows[sc, p, n2, es] for n2 in list(mTEPES.n2)[mTEPES.n.ord(n) - int(mTEPES.pOutflowsTimeStep[es] / mTEPES.pCycleTimeStep[es]):mTEPES.n.ord( + n)]) == sum(mTEPES.pEnergyOutflows[sc, p, n2, es] for n2 in list(mTEPES.n2)[mTEPES.n.ord(n) - mTEPES.pOutflowsTimeStep[es]:mTEPES.n.ord(n)]) else: return Constraint.Skip - setattr(OptModel, 'eEnergyOutflows_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.es, rule=eEnergyOutflows, doc='energy outflows of an ESS unit [GW]')) + setattr( + OptModel, + 'eEnergyOutflows_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.es, + rule=eEnergyOutflows, + doc='energy outflows of an ESS unit [GW]')) if pIndLogConsole == 1: - print('eEnergyOutflows ... ', len(getattr(OptModel, 'eEnergyOutflows_'+st)), ' rows') - - #%% - def eMaxOutput2ndBlock(OptModel,sc,p,n,nr): - if sum(mTEPES.pOperReserveUp[sc,p,n,ar] for ar in mTEPES.ar if (ar,nr) in mTEPES.a2g) and mTEPES.pMaxPower2ndBlock[sc,p,n,nr]: - return (OptModel.vOutput2ndBlock[sc,p,n,nr] + mTEPES.pUpReserveActivation * OptModel.vReserveUp [sc,p,n,nr] + OptModel.vReserveUp [sc,p,n,nr]) / mTEPES.pMaxPower2ndBlock[sc,p,n,nr] <= OptModel.vCommitment[sc,p,n,nr] + print('eEnergyOutflows ... ', len( + getattr(OptModel, 'eEnergyOutflows_' + st)), ' rows') + + # %% + def eMaxOutput2ndBlock(OptModel, sc, p, n, nr): + if sum(mTEPES.pOperReserveUp[sc, p, n, ar] for ar in mTEPES.ar if ( + ar, nr) in mTEPES.a2g) and mTEPES.pMaxPower2ndBlock[sc, p, n, nr]: + return (OptModel.vOutput2ndBlock[sc, + p, + n, + nr] + mTEPES.pUpReserveActivation * OptModel.vReserveUp[sc, + p, + n, + nr] + OptModel.vReserveUp[sc, + p, + n, + nr]) / mTEPES.pMaxPower2ndBlock[sc, + p, + n, + nr] <= OptModel.vCommitment[sc, + p, + n, + nr] else: return Constraint.Skip - setattr(OptModel, 'eMaxOutput2ndBlock_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.nr, rule=eMaxOutput2ndBlock, doc='max output of the second block of a committed unit [p.u.]')) + setattr( + OptModel, + 'eMaxOutput2ndBlock_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.nr, + rule=eMaxOutput2ndBlock, + doc='max output of the second block of a committed unit [p.u.]')) if pIndLogConsole == 1: - print('eMaxOutput2ndBlock ... ', len(getattr(OptModel, 'eMaxOutput2ndBlock_'+st)), ' rows') - - def eMinOutput2ndBlock(OptModel,sc,p,n,nr): - if sum(mTEPES.pOperReserveDw[sc,p,n,ar] for ar in mTEPES.ar if (ar,nr) in mTEPES.a2g) and mTEPES.pMaxPower2ndBlock[sc,p,n,nr]: - return (OptModel.vOutput2ndBlock[sc,p,n,nr] - mTEPES.pDwReserveActivation * OptModel.vReserveDown[sc,p,n,nr] - OptModel.vReserveDown[sc,p,n,nr]) / mTEPES.pMaxPower2ndBlock[sc,p,n,nr] >= 0.0 + print( + 'eMaxOutput2ndBlock ... ', len( + getattr( + OptModel, 'eMaxOutput2ndBlock_' + st)), ' rows') + + def eMinOutput2ndBlock(OptModel, sc, p, n, nr): + if sum(mTEPES.pOperReserveDw[sc, p, n, ar] for ar in mTEPES.ar if ( + ar, nr) in mTEPES.a2g) and mTEPES.pMaxPower2ndBlock[sc, p, n, nr]: + return (OptModel.vOutput2ndBlock[sc, + p, + n, + nr] - mTEPES.pDwReserveActivation * OptModel.vReserveDown[sc, + p, + n, + nr] - OptModel.vReserveDown[sc, + p, + n, + nr]) / mTEPES.pMaxPower2ndBlock[sc, + p, + n, + nr] >= 0.0 else: return Constraint.Skip - setattr(OptModel, 'eMinOutput2ndBlock_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.nr, rule=eMinOutput2ndBlock, doc='min output of the second block of a committed unit [p.u.]')) + setattr( + OptModel, + 'eMinOutput2ndBlock_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.nr, + rule=eMinOutput2ndBlock, + doc='min output of the second block of a committed unit [p.u.]')) if pIndLogConsole == 1: - print('eMinOutput2ndBlock ... ', len(getattr(OptModel, 'eMinOutput2ndBlock_'+st)), ' rows') - - def eTotalOutput(OptModel,sc,p,n,nr): - if mTEPES.pMaxPower[sc,p,n,nr] and mTEPES.pMinPower[sc,p,n,nr] == 0.0: - return OptModel.vTotalOutput[sc,p,n,nr] == OptModel.vOutput2ndBlock[sc,p,n,nr] + mTEPES.pUpReserveActivation * OptModel.vReserveUp[sc,p,n,nr] - mTEPES.pDwReserveActivation * OptModel.vReserveDown[sc,p,n,nr] - elif mTEPES.pMaxPower[sc,p,n,nr]: - return OptModel.vTotalOutput[sc,p,n,nr] / mTEPES.pMinPower[sc,p,n,nr] == OptModel.vCommitment[sc,p,n,nr] + (OptModel.vOutput2ndBlock[sc,p,n,nr] + mTEPES.pUpReserveActivation * OptModel.vReserveUp[sc,p,n,nr] - mTEPES.pDwReserveActivation * OptModel.vReserveDown[sc,p,n,nr]) / mTEPES.pMinPower[sc,p,n,nr] + print( + 'eMinOutput2ndBlock ... ', len( + getattr( + OptModel, 'eMinOutput2ndBlock_' + st)), ' rows') + + def eTotalOutput(OptModel, sc, p, n, nr): + if mTEPES.pMaxPower[sc, + p, + n, + nr] and mTEPES.pMinPower[sc, + p, + n, + nr] == 0.0: + return OptModel.vTotalOutput[sc, + p, + n, + nr] == OptModel.vOutput2ndBlock[sc, + p, + n, + nr] + mTEPES.pUpReserveActivation * OptModel.vReserveUp[sc, + p, + n, + nr] - mTEPES.pDwReserveActivation * OptModel.vReserveDown[sc, + p, + n, + nr] + elif mTEPES.pMaxPower[sc, p, n, nr]: + return OptModel.vTotalOutput[sc, + p, + n, + nr] / mTEPES.pMinPower[sc, + p, + n, + nr] == OptModel.vCommitment[sc, + p, + n, + nr] + (OptModel.vOutput2ndBlock[sc, + p, + n, + nr] + mTEPES.pUpReserveActivation * OptModel.vReserveUp[sc, + p, + n, + nr] - mTEPES.pDwReserveActivation * OptModel.vReserveDown[sc, + p, + n, + nr]) / mTEPES.pMinPower[sc, + p, + n, + nr] else: return Constraint.Skip - setattr(OptModel, 'eTotalOutput_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.nr, rule=eTotalOutput, doc='total output of a unit [GW]')) + setattr( + OptModel, + 'eTotalOutput_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.nr, + rule=eTotalOutput, + doc='total output of a unit [GW]')) if pIndLogConsole == 1: - print('eTotalOutput ... ', len(getattr(OptModel, 'eTotalOutput_'+st)), ' rows') - - def eUCStrShut(OptModel,sc,p,n,nr): - if mTEPES.pMustRun[nr] == 0 and (mTEPES.pMinPower[sc,p,n,nr] or mTEPES.pConstantVarCost[nr]) and nr not in mTEPES.es and n == mTEPES.n.first(): - return OptModel.vCommitment[sc,p,n,nr] - mTEPES.pInitialUC[sc,p,n,nr] == OptModel.vStartUp[sc,p,n,nr] - OptModel.vShutDown[sc,p,n,nr] - elif mTEPES.pMustRun[nr] == 0 and (mTEPES.pMinPower[sc,p,n,nr] or mTEPES.pConstantVarCost[nr]) and nr not in mTEPES.es: - return OptModel.vCommitment[sc,p,n,nr] - OptModel.vCommitment[sc,p,mTEPES.n.prev(n),nr] == OptModel.vStartUp[sc,p,n,nr] - OptModel.vShutDown[sc,p,n,nr] + print('eTotalOutput ... ', len( + getattr(OptModel, 'eTotalOutput_' + st)), ' rows') + + def eUCStrShut(OptModel, sc, p, n, nr): + if mTEPES.pMustRun[nr] == 0 and ( + mTEPES.pMinPower[sc, p, n, nr] or mTEPES.pConstantVarCost[nr]) and nr not in mTEPES.es and n == mTEPES.n.first(): + return OptModel.vCommitment[sc, + p, + n, + nr] - mTEPES.pInitialUC[sc, + p, + n, + nr] == OptModel.vStartUp[sc, + p, + n, + nr] - OptModel.vShutDown[sc, + p, + n, + nr] + elif mTEPES.pMustRun[nr] == 0 and (mTEPES.pMinPower[sc, p, n, nr] or mTEPES.pConstantVarCost[nr]) and nr not in mTEPES.es: + return OptModel.vCommitment[sc, + p, + n, + nr] - OptModel.vCommitment[sc, + p, + mTEPES.n.prev(n), + nr] == OptModel.vStartUp[sc, + p, + n, + nr] - OptModel.vShutDown[sc, + p, + n, + nr] else: return Constraint.Skip - setattr(OptModel, 'eUCStrShut_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.nr, rule=eUCStrShut, doc='relation among commitment startup and shutdown')) + setattr( + OptModel, + 'eUCStrShut_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.nr, + rule=eUCStrShut, + doc='relation among commitment startup and shutdown')) if pIndLogConsole == 1: - print('eUCStrShut ... ', len(getattr(OptModel, 'eUCStrShut_'+st)), ' rows') + print('eUCStrShut ... ', len( + getattr(OptModel, 'eUCStrShut_' + st)), ' rows') GeneratingGenConsTime = time.time() - StartTime - StartTime = time.time() + StartTime = time.time() if pIndLogConsole == 1: - print('Generating generation constraints ... ', round(GeneratingGenConsTime), 's') - - #%% - def eRampUp(OptModel,sc,p,n,nr): - if mTEPES.pRampUp[nr] and mTEPES.pRampUp[nr] < mTEPES.pMaxPower2ndBlock[sc,p,n,nr] and n == mTEPES.n.first(): - return (- max(mTEPES.pInitialOutput[sc,p,n,nr]() - mTEPES.pMinPower[sc,p,n,nr],0.0) + OptModel.vOutput2ndBlock[sc,p,n,nr] + mTEPES.pUpReserveActivation * OptModel.vReserveUp [sc,p,n,nr] + OptModel.vReserveUp [sc,p,n,nr]) / mTEPES.pDuration[n] / mTEPES.pRampUp[nr] <= OptModel.vCommitment[sc,p,n,nr] - OptModel.vStartUp[sc,p,n,nr] - elif mTEPES.pRampUp[nr] and mTEPES.pRampUp[nr] < mTEPES.pMaxPower2ndBlock[sc,p,n,nr]: - return (- OptModel.vOutput2ndBlock[sc,p,mTEPES.n.prev(n),nr] - mTEPES.pUpReserveActivation * OptModel.vReserveUp [sc,p,mTEPES.n.prev(n),nr] + OptModel.vOutput2ndBlock[sc,p,n,nr] + mTEPES.pUpReserveActivation * OptModel.vReserveUp [sc,p,n,nr] + OptModel.vReserveUp [sc,p,n,nr]) / mTEPES.pDuration[n] / mTEPES.pRampUp[nr] <= OptModel.vCommitment[sc,p,n,nr] - OptModel.vStartUp[sc,p,n,nr] + print('Generating generation constraints ... ', + round(GeneratingGenConsTime), 's') + + # %% + def eRampUp(OptModel, sc, p, n, nr): + if mTEPES.pRampUp[nr] and mTEPES.pRampUp[nr] < mTEPES.pMaxPower2ndBlock[sc, + p, n, nr] and n == mTEPES.n.first(): + return (- max(mTEPES.pInitialOutput[sc, + p, + n, + nr]() - mTEPES.pMinPower[sc, + p, + n, + nr], + 0.0) + OptModel.vOutput2ndBlock[sc, + p, + n, + nr] + mTEPES.pUpReserveActivation * OptModel.vReserveUp[sc, + p, + n, + nr] + OptModel.vReserveUp[sc, + p, + n, + nr]) / mTEPES.pDuration[n] / mTEPES.pRampUp[nr] <= OptModel.vCommitment[sc, + p, + n, + nr] - OptModel.vStartUp[sc, + p, + n, + nr] + elif mTEPES.pRampUp[nr] and mTEPES.pRampUp[nr] < mTEPES.pMaxPower2ndBlock[sc, p, n, nr]: + return (- OptModel.vOutput2ndBlock[sc, + p, + mTEPES.n.prev(n), + nr] - mTEPES.pUpReserveActivation * OptModel.vReserveUp[sc, + p, + mTEPES.n.prev(n), + nr] + OptModel.vOutput2ndBlock[sc, + p, + n, + nr] + mTEPES.pUpReserveActivation * OptModel.vReserveUp[sc, + p, + n, + nr] + OptModel.vReserveUp[sc, + p, + n, + nr]) / mTEPES.pDuration[n] / mTEPES.pRampUp[nr] <= OptModel.vCommitment[sc, + p, + n, + nr] - OptModel.vStartUp[sc, + p, + n, + nr] else: return Constraint.Skip - setattr(OptModel, 'eRampUp_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.nr, rule=eRampUp, doc='maximum ramp up [p.u.]')) + setattr( + OptModel, + 'eRampUp_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.nr, + rule=eRampUp, + doc='maximum ramp up [p.u.]')) if pIndLogConsole == 1: - print('eRampUp ... ', len(getattr(OptModel, 'eRampUp_'+st)), ' rows') - - def eRampDw(OptModel,sc,p,n,nr): - if mTEPES.pRampDw[nr] and mTEPES.pRampDw[nr] < mTEPES.pMaxPower2ndBlock[sc,p,n,nr] and n == mTEPES.n.first(): - return (- max(mTEPES.pInitialOutput[sc,p,n,nr]() - mTEPES.pMinPower[sc,p,n,nr],0.0) + OptModel.vOutput2ndBlock[sc,p,n,nr] - mTEPES.pDwReserveActivation * OptModel.vReserveDown[sc,p,n,nr] - OptModel.vReserveDown[sc,p,n,nr]) / mTEPES.pDuration[n] / mTEPES.pRampDw[nr] >= - mTEPES.pInitialUC[sc,p,n,nr] + OptModel.vShutDown[sc,p,n,nr] - elif mTEPES.pRampDw[nr] and mTEPES.pRampDw[nr] < mTEPES.pMaxPower2ndBlock[sc,p,n,nr]: - return (- OptModel.vOutput2ndBlock[sc,p,mTEPES.n.prev(n),nr] + mTEPES.pDwReserveActivation * OptModel.vReserveDown[sc,p,mTEPES.n.prev(n),nr] + OptModel.vOutput2ndBlock[sc,p,n,nr] - mTEPES.pDwReserveActivation * OptModel.vReserveDown[sc,p,n,nr] - OptModel.vReserveDown[sc,p,n,nr]) / mTEPES.pDuration[n] / mTEPES.pRampDw[nr] >= - OptModel.vCommitment[sc,p,mTEPES.n.prev(n),nr] + OptModel.vShutDown[sc,p,n,nr] + print('eRampUp ... ', len( + getattr(OptModel, 'eRampUp_' + st)), ' rows') + + def eRampDw(OptModel, sc, p, n, nr): + if mTEPES.pRampDw[nr] and mTEPES.pRampDw[nr] < mTEPES.pMaxPower2ndBlock[sc, + p, n, nr] and n == mTEPES.n.first(): + return (- max(mTEPES.pInitialOutput[sc, + p, + n, + nr]() - mTEPES.pMinPower[sc, + p, + n, + nr], + 0.0) + OptModel.vOutput2ndBlock[sc, + p, + n, + nr] - mTEPES.pDwReserveActivation * OptModel.vReserveDown[sc, + p, + n, + nr] - OptModel.vReserveDown[sc, + p, + n, + nr]) / mTEPES.pDuration[n] / mTEPES.pRampDw[nr] >= - mTEPES.pInitialUC[sc, + p, + n, + nr] + OptModel.vShutDown[sc, + p, + n, + nr] + elif mTEPES.pRampDw[nr] and mTEPES.pRampDw[nr] < mTEPES.pMaxPower2ndBlock[sc, p, n, nr]: + return (- OptModel.vOutput2ndBlock[sc, + p, + mTEPES.n.prev(n), + nr] + mTEPES.pDwReserveActivation * OptModel.vReserveDown[sc, + p, + mTEPES.n.prev(n), + nr] + OptModel.vOutput2ndBlock[sc, + p, + n, + nr] - mTEPES.pDwReserveActivation * OptModel.vReserveDown[sc, + p, + n, + nr] - OptModel.vReserveDown[sc, + p, + n, + nr]) / mTEPES.pDuration[n] / mTEPES.pRampDw[nr] >= - OptModel.vCommitment[sc, + p, + mTEPES.n.prev(n), + nr] + OptModel.vShutDown[sc, + p, + n, + nr] else: return Constraint.Skip - setattr(OptModel,'eRampDw_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.nr, rule=eRampDw, doc='maximum ramp down [p.u.]')) + setattr( + OptModel, + 'eRampDw_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.nr, + rule=eRampDw, + doc='maximum ramp down [p.u.]')) if pIndLogConsole == 1: - print('eRampDw ... ', len(getattr(OptModel, 'eRampDw_'+st)), ' rows') - - def eRampUpCharge(OptModel,sc,p,n,es): - if mTEPES.pRampUp[es] and mTEPES.pMaxCharge2ndBlock[sc,p,n,es] and n == mTEPES.n.first(): - return ( + OptModel.vCharge2ndBlock[sc,p,n,es] - mTEPES.pDwReserveActivation * OptModel.vESSReserveUp [sc,p,n,es] - OptModel.vESSReserveUp [sc,p,n,es]) / mTEPES.pDuration[n] / mTEPES.pRampUp[es] >= - 1.0 - elif mTEPES.pRampUp[es] and mTEPES.pMaxCharge2ndBlock[sc,p,n,es]: - return (- OptModel.vCharge2ndBlock[sc,p,mTEPES.n.prev(n),es] + mTEPES.pDwReserveActivation * OptModel.vESSReserveUp [sc,p,mTEPES.n.prev(n),es] + OptModel.vCharge2ndBlock[sc,p,n,es] - mTEPES.pDwReserveActivation * OptModel.vESSReserveUp [sc,p,n,es] - OptModel.vESSReserveUp [sc,p,n,es]) / mTEPES.pDuration[n] / mTEPES.pRampUp[es] >= - 1.0 + print('eRampDw ... ', len( + getattr(OptModel, 'eRampDw_' + st)), ' rows') + + def eRampUpCharge(OptModel, sc, p, n, es): + if mTEPES.pRampUp[es] and mTEPES.pMaxCharge2ndBlock[sc, + p, n, es] and n == mTEPES.n.first(): + return (+ OptModel.vCharge2ndBlock[sc, + p, + n, + es] - mTEPES.pDwReserveActivation * OptModel.vESSReserveUp[sc, + p, + n, + es] - OptModel.vESSReserveUp[sc, + p, + n, + es]) / mTEPES.pDuration[n] / mTEPES.pRampUp[es] >= - 1.0 + elif mTEPES.pRampUp[es] and mTEPES.pMaxCharge2ndBlock[sc, p, n, es]: + return (- OptModel.vCharge2ndBlock[sc, + p, + mTEPES.n.prev(n), + es] + mTEPES.pDwReserveActivation * OptModel.vESSReserveUp[sc, + p, + mTEPES.n.prev(n), + es] + OptModel.vCharge2ndBlock[sc, + p, + n, + es] - mTEPES.pDwReserveActivation * OptModel.vESSReserveUp[sc, + p, + n, + es] - OptModel.vESSReserveUp[sc, + p, + n, + es]) / mTEPES.pDuration[n] / mTEPES.pRampUp[es] >= - 1.0 else: return Constraint.Skip - setattr(OptModel, 'eRampUpChr_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.es, rule=eRampUpCharge, doc='maximum ramp up charge [p.u.]')) + setattr( + OptModel, + 'eRampUpChr_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.es, + rule=eRampUpCharge, + doc='maximum ramp up charge [p.u.]')) if pIndLogConsole == 1: - print('eRampUpChr ... ', len(getattr(OptModel, 'eRampUpChr_'+st)), ' rows') - - def eRampDwCharge(OptModel,sc,p,n,es): - if mTEPES.pRampDw[es] and mTEPES.pMaxCharge[sc,p,n,es] and n == mTEPES.n.first(): - return ( + OptModel.vCharge2ndBlock[sc,p,n,es] + mTEPES.pUpReserveActivation * OptModel.vESSReserveDown[sc,p,n,es] + OptModel.vESSReserveDown[sc,p,n,es]) / mTEPES.pDuration[n] / mTEPES.pRampDw[es] <= 1.0 - elif mTEPES.pRampDw[es] and mTEPES.pMaxCharge[sc,p,n,es]: - return (- OptModel.vCharge2ndBlock[sc,p,mTEPES.n.prev(n),es] - mTEPES.pUpReserveActivation * OptModel.vESSReserveDown[sc,p,mTEPES.n.prev(n),es] + OptModel.vCharge2ndBlock[sc,p,n,es] + mTEPES.pUpReserveActivation * OptModel.vESSReserveDown[sc,p,n,es] + OptModel.vESSReserveDown[sc,p,n,es]) / mTEPES.pDuration[n] / mTEPES.pRampDw[es] <= 1.0 + print('eRampUpChr ... ', len( + getattr(OptModel, 'eRampUpChr_' + st)), ' rows') + + def eRampDwCharge(OptModel, sc, p, n, es): + if mTEPES.pRampDw[es] and mTEPES.pMaxCharge[sc, + p, n, es] and n == mTEPES.n.first(): + return (+ OptModel.vCharge2ndBlock[sc, + p, + n, + es] + mTEPES.pUpReserveActivation * OptModel.vESSReserveDown[sc, + p, + n, + es] + OptModel.vESSReserveDown[sc, + p, + n, + es]) / mTEPES.pDuration[n] / mTEPES.pRampDw[es] <= 1.0 + elif mTEPES.pRampDw[es] and mTEPES.pMaxCharge[sc, p, n, es]: + return (- OptModel.vCharge2ndBlock[sc, + p, + mTEPES.n.prev(n), + es] - mTEPES.pUpReserveActivation * OptModel.vESSReserveDown[sc, + p, + mTEPES.n.prev(n), + es] + OptModel.vCharge2ndBlock[sc, + p, + n, + es] + mTEPES.pUpReserveActivation * OptModel.vESSReserveDown[sc, + p, + n, + es] + OptModel.vESSReserveDown[sc, + p, + n, + es]) / mTEPES.pDuration[n] / mTEPES.pRampDw[es] <= 1.0 else: return Constraint.Skip - setattr(OptModel, 'eRampDwChr_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.es, rule=eRampDwCharge, doc='maximum ramp down charge [p.u.]')) + setattr( + OptModel, + 'eRampDwChr_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.es, + rule=eRampDwCharge, + doc='maximum ramp down charge [p.u.]')) if pIndLogConsole == 1: - print('eRampDwChr ... ', len(getattr(OptModel, 'eRampDwChr_'+st)), ' rows') + print('eRampDwChr ... ', len( + getattr(OptModel, 'eRampDwChr_' + st)), ' rows') GeneratingRampsTime = time.time() - StartTime - StartTime = time.time() + StartTime = time.time() if pIndLogConsole == 1: - print('Generating ramps up/down ... ', round(GeneratingRampsTime), 's') - - #%% - def eMinUpTime(OptModel,sc,p,n,t): - if mTEPES.pMustRun[t] == 0 and (mTEPES.pMinPower[sc,p,n,t] or mTEPES.pConstantVarCost[t]) and t not in mTEPES.es and mTEPES.pUpTime[t] > 1 and mTEPES.n.ord(n) >= mTEPES.pUpTime[t]: - return sum(OptModel.vStartUp [sc,p,n2,t] for n2 in list(mTEPES.n2)[mTEPES.n.ord(n)-mTEPES.pUpTime[t]:mTEPES.n.ord(n)]) <= OptModel.vCommitment[sc,p,n,t] + print('Generating ramps up/down ... ', + round(GeneratingRampsTime), 's') + + # %% + def eMinUpTime(OptModel, sc, p, n, t): + if mTEPES.pMustRun[t] == 0 and (mTEPES.pMinPower[sc, p, n, t] or mTEPES.pConstantVarCost[t] + ) and t not in mTEPES.es and mTEPES.pUpTime[t] > 1 and mTEPES.n.ord(n) >= mTEPES.pUpTime[t]: + return sum(OptModel.vStartUp[sc, p, n2, t] for n2 in list(mTEPES.n2)[mTEPES.n.ord( + n) - mTEPES.pUpTime[t]:mTEPES.n.ord(n)]) <= OptModel.vCommitment[sc, p, n, t] else: return Constraint.Skip - setattr(OptModel, 'eMinUpTime_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.t, rule=eMinUpTime , doc='minimum up time [h]')) + setattr( + OptModel, + 'eMinUpTime_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.t, + rule=eMinUpTime, + doc='minimum up time [h]')) if pIndLogConsole == 1: - print('eMinUpTime ... ', len(getattr(OptModel, 'eMinUpTime_'+st)), ' rows') - - def eMinDownTime(OptModel,sc,p,n,t): - if mTEPES.pMustRun[t] == 0 and (mTEPES.pMinPower[sc,p,n,t] or mTEPES.pConstantVarCost[t]) and t not in mTEPES.es and mTEPES.pDwTime[t] > 1 and mTEPES.n.ord(n) >= mTEPES.pDwTime[t]: - return sum(OptModel.vShutDown[sc,p,n2,t] for n2 in list(mTEPES.n2)[mTEPES.n.ord(n)-mTEPES.pDwTime[t]:mTEPES.n.ord(n)]) <= 1 - OptModel.vCommitment[sc,p,n,t] + print('eMinUpTime ... ', len( + getattr(OptModel, 'eMinUpTime_' + st)), ' rows') + + def eMinDownTime(OptModel, sc, p, n, t): + if mTEPES.pMustRun[t] == 0 and (mTEPES.pMinPower[sc, p, n, t] or mTEPES.pConstantVarCost[t] + ) and t not in mTEPES.es and mTEPES.pDwTime[t] > 1 and mTEPES.n.ord(n) >= mTEPES.pDwTime[t]: + return sum(OptModel.vShutDown[sc, p, n2, t] for n2 in list(mTEPES.n2)[mTEPES.n.ord( + n) - mTEPES.pDwTime[t]:mTEPES.n.ord(n)]) <= 1 - OptModel.vCommitment[sc, p, n, t] else: return Constraint.Skip - setattr(OptModel, 'eMinDownTime_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.t, rule=eMinDownTime, doc='minimum down time [h]')) + setattr( + OptModel, + 'eMinDownTime_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.t, + rule=eMinDownTime, + doc='minimum down time [h]')) if pIndLogConsole == 1: - print('eMinDownTime ... ', len(getattr(OptModel, 'eMinDownTime_'+st)), ' rows') + print('eMinDownTime ... ', len( + getattr(OptModel, 'eMinDownTime_' + st)), ' rows') GeneratingMinUDTime = time.time() - StartTime if pIndLogConsole == 1: - print('Generating minimum up/down time ... ', round(GeneratingMinUDTime), 's') + print('Generating minimum up/down time ... ', + round(GeneratingMinUDTime), 's') def NetworkSwitchingModelFormulation(OptModel, mTEPES, pIndLogConsole, st): print('Network switching model formulation ****') StartTime = time.time() - #%% - def eLineStateCand(OptModel,sc,p,n,ni,nf,cc): - if mTEPES.pLineSwitching[ni,nf,cc] == 1: - return OptModel.vLineCommit[sc,p,n,ni,nf,cc] <= OptModel.vNetworkInvest[ni,nf,cc] + # %% + + def eLineStateCand(OptModel, sc, p, n, ni, nf, cc): + if mTEPES.pLineSwitching[ni, nf, cc] == 1: + return OptModel.vLineCommit[sc, p, n, ni, nf, + cc] <= OptModel.vNetworkInvest[ni, nf, cc] else: - return OptModel.vLineCommit[sc,p,n,ni,nf,cc] == OptModel.vNetworkInvest[ni,nf,cc] - setattr(OptModel, 'eLineStateCand_' + str(st), Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.lc, rule=eLineStateCand, doc='logical relation between investment and operation in candidates')) + return OptModel.vLineCommit[sc, p, n, ni, nf, + cc] == OptModel.vNetworkInvest[ni, nf, cc] + setattr( + OptModel, + 'eLineStateCand_' + + str(st), + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.lc, + rule=eLineStateCand, + doc='logical relation between investment and operation in candidates')) if pIndLogConsole == 1: - print('eLineStateCand ... ', len(getattr(OptModel, 'eLineStateCand_' + str(st))), ' rows') - - def eLineSwtStageToLevel(OptModel,sc,p,ss,n,ni,nf,cc): - if mTEPES.pLineSwitching[ni,nf,cc] == 1 and mTEPES.pIndSwitchingStage() == 1: - return OptModel.vLineCommit[sc,p,n,ni,nf,cc] == OptModel.vSwitchingStage[sc,p,ss,ni,nf,cc] + print( + 'eLineStateCand ... ', len( + getattr( + OptModel, 'eLineStateCand_' + str(st))), ' rows') + + def eLineSwtStageToLevel(OptModel, sc, p, ss, n, ni, nf, cc): + if mTEPES.pLineSwitching[ni, nf, + cc] == 1 and mTEPES.pIndSwitchingStage() == 1: + return OptModel.vLineCommit[sc, + p, + n, + ni, + nf, + cc] == OptModel.vSwitchingStage[sc, + p, + ss, + ni, + nf, + cc] else: return Constraint.Skip - setattr(OptModel, 'eLineSwtStageToLevel_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.ss2n, rule=eLineSwtStageToLevel, doc='constraints between line commitment per load level and per stage')) + setattr( + OptModel, + 'eLineSwtStageToLevel_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.ss2n, + rule=eLineSwtStageToLevel, + doc='constraints between line commitment per load level and per stage')) if pIndLogConsole == 1: - print('eLineSwtStageToLevel ... ', len(getattr(OptModel, 'eLineSwtStageToLevel_'+st)), ' rows') - - def eSWOnOff(OptModel,sc,p,n,ni,nf,cc): - if mTEPES.pLineSwitching[ni,nf,cc] == 1 and (mTEPES.pSwOnTime[ni,nf,cc] > 1 or mTEPES.pSwOffTime[ni,nf,cc] > 1) and n == mTEPES.n.first(): - return OptModel.vLineCommit[sc,p,n,ni,nf,cc] - mTEPES.pInitialSwitch[sc,p,n,ni,nf,cc] == OptModel.vLineOnState[sc,p,n,ni,nf,cc] - OptModel.vLineOffState[sc,p,n,ni,nf,cc] - elif mTEPES.pLineSwitching[ni,nf,cc] == 1 and (mTEPES.pSwOnTime[ni,nf,cc] > 1 or mTEPES.pSwOffTime[ni,nf,cc] > 1): - return OptModel.vLineCommit[sc,p,n,ni,nf,cc] - OptModel.vLineCommit[sc,p,mTEPES.n.prev(n),ni,nf,cc] == OptModel.vLineOnState[sc,p,n,ni,nf,cc] - OptModel.vLineOffState[sc,p,n,ni,nf,cc] + print( + 'eLineSwtStageToLevel ... ', len( + getattr( + OptModel, 'eLineSwtStageToLevel_' + st)), ' rows') + + def eSWOnOff(OptModel, sc, p, n, ni, nf, cc): + if mTEPES.pLineSwitching[ni, + nf, + cc] == 1 and (mTEPES.pSwOnTime[ni, + nf, + cc] > 1 or mTEPES.pSwOffTime[ni, + nf, + cc] > 1) and n == mTEPES.n.first(): + return OptModel.vLineCommit[sc, + p, + n, + ni, + nf, + cc] - mTEPES.pInitialSwitch[sc, + p, + n, + ni, + nf, + cc] == OptModel.vLineOnState[sc, + p, + n, + ni, + nf, + cc] - OptModel.vLineOffState[sc, + p, + n, + ni, + nf, + cc] + elif mTEPES.pLineSwitching[ni, nf, cc] == 1 and (mTEPES.pSwOnTime[ni, nf, cc] > 1 or mTEPES.pSwOffTime[ni, nf, cc] > 1): + return OptModel.vLineCommit[sc, + p, + n, + ni, + nf, + cc] - OptModel.vLineCommit[sc, + p, + mTEPES.n.prev(n), + ni, + nf, + cc] == OptModel.vLineOnState[sc, + p, + n, + ni, + nf, + cc] - OptModel.vLineOffState[sc, + p, + n, + ni, + nf, + cc] else: return Constraint.Skip - setattr(OptModel, 'eSWOnOff_' + str(st), Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.la, rule=eSWOnOff, doc='relation among switching decision activate and deactivate state')) + setattr( + OptModel, + 'eSWOnOff_' + + str(st), + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.la, + rule=eSWOnOff, + doc='relation among switching decision activate and deactivate state')) if pIndLogConsole == 1: - print('eSWOnOff ... ', len(getattr(OptModel, 'eSWOnOff_'+st)), ' rows') + print('eSWOnOff ... ', len( + getattr(OptModel, 'eSWOnOff_' + st)), ' rows') SwitchingLogicalRelation = time.time() - StartTime - StartTime = time.time() + StartTime = time.time() if pIndLogConsole == 1: - print('Switching logical relation ... ', round(SwitchingLogicalRelation), 's') - - def eMinSwOnState(OptModel,sc,p,n,ni,nf,cc): - if mTEPES.pLineSwitching[ni,nf,cc] == 1 and mTEPES.pSwOnTime [ni,nf,cc] > 1 and mTEPES.n.ord(n) >= mTEPES.pSwOnTime [ni,nf,cc]: - return sum(OptModel.vLineOnState [sc,p,n2,ni,nf,cc] for n2 in list(mTEPES.n2)[mTEPES.n.ord(n)-mTEPES.pSwOnTime [ni,nf,cc]:mTEPES.n.ord(n)]) <= OptModel.vLineCommit[sc,p,n,ni,nf,cc] + print('Switching logical relation ... ', + round(SwitchingLogicalRelation), 's') + + def eMinSwOnState(OptModel, sc, p, n, ni, nf, cc): + if mTEPES.pLineSwitching[ni, + nf, + cc] == 1 and mTEPES.pSwOnTime[ni, + nf, + cc] > 1 and mTEPES.n.ord(n) >= mTEPES.pSwOnTime[ni, + nf, + cc]: + return sum(OptModel.vLineOnState[sc, p, n2, ni, nf, cc] for n2 in list(mTEPES.n2)[mTEPES.n.ord( + n) - mTEPES.pSwOnTime[ni, nf, cc]:mTEPES.n.ord(n)]) <= OptModel.vLineCommit[sc, p, n, ni, nf, cc] else: return Constraint.Skip - setattr(OptModel, 'eMinSwOnState_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.la, rule=eMinSwOnState, doc='minimum switch on state [h]')) + setattr( + OptModel, + 'eMinSwOnState_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.la, + rule=eMinSwOnState, + doc='minimum switch on state [h]')) if pIndLogConsole == 1: - print('eMinSwOnState ... ', len(getattr(OptModel, 'eMinSwOnState_'+st)), ' rows') - - def eMinSwOffState(OptModel,sc,p,n,ni,nf,cc): - if mTEPES.pLineSwitching[ni,nf,cc] == 1 and mTEPES.pSwOffTime[ni,nf,cc] > 1 and mTEPES.n.ord(n) >= mTEPES.pSwOffTime[ni,nf,cc]: - return sum(OptModel.vLineOffState[sc,p,n2,ni,nf,cc] for n2 in list(mTEPES.n2)[mTEPES.n.ord(n)-mTEPES.pSwOffTime[ni,nf,cc]:mTEPES.n.ord(n)]) <= 1 - OptModel.vLineCommit[sc,p,n,ni,nf,cc] + print('eMinSwOnState ... ', len( + getattr(OptModel, 'eMinSwOnState_' + st)), ' rows') + + def eMinSwOffState(OptModel, sc, p, n, ni, nf, cc): + if mTEPES.pLineSwitching[ni, + nf, + cc] == 1 and mTEPES.pSwOffTime[ni, + nf, + cc] > 1 and mTEPES.n.ord(n) >= mTEPES.pSwOffTime[ni, + nf, + cc]: + return sum(OptModel.vLineOffState[sc, p, n2, ni, nf, cc] for n2 in list(mTEPES.n2)[mTEPES.n.ord( + n) - mTEPES.pSwOffTime[ni, nf, cc]:mTEPES.n.ord(n)]) <= 1 - OptModel.vLineCommit[sc, p, n, ni, nf, cc] else: return Constraint.Skip - setattr(OptModel, 'eMinSwOffState_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.la, rule=eMinSwOffState, doc='minimum switch off state [h]')) + setattr( + OptModel, + 'eMinSwOffState_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.la, + rule=eMinSwOffState, + doc='minimum switch off state [h]')) if pIndLogConsole == 1: - print('eMinSwOffState ... ', len(getattr(OptModel, 'eMinSwOffState_'+st)), ' rows') + print('eMinSwOffState ... ', len( + getattr(OptModel, 'eMinSwOffState_' + st)), ' rows') SwitchingMinStateTime = time.time() - StartTime if pIndLogConsole == 1: - print('Switching minimum on/off state ... ', round(SwitchingMinStateTime), 's') + print('Switching minimum on/off state ... ', + round(SwitchingMinStateTime), 's') def NetworkOperationModelFormulation(OptModel, mTEPES, pIndLogConsole, st): print('Network operation model formulation ****') StartTime = time.time() - #%% - def eExistNetCap1(OptModel,sc,p,n,ni,nf,cc): - if (ni,nf,cc) in mTEPES.lc or mTEPES.pLineSwitching[ni,nf,cc] == 1: - return OptModel.vFlow[sc,p,n,ni,nf,cc] / max(mTEPES.pLineNTCBck[ni,nf,cc],mTEPES.pLineNTCFrw[ni,nf,cc]) >= - OptModel.vLineCommit[sc,p,n,ni,nf,cc] + # %% + + def eExistNetCap1(OptModel, sc, p, n, ni, nf, cc): + if (ni, nf, cc) in mTEPES.lc or mTEPES.pLineSwitching[ni, nf, cc] == 1: + return OptModel.vFlow[sc, + p, + n, + ni, + nf, + cc] / max(mTEPES.pLineNTCBck[ni, + nf, + cc], + mTEPES.pLineNTCFrw[ni, + nf, + cc]) >= - OptModel.vLineCommit[sc, + p, + n, + ni, + nf, + cc] else: return Constraint.Skip - setattr(OptModel, 'eExistNetCap1_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.la, rule=eExistNetCap1, doc='maximum flow by existing network capacity [p.u.]')) + setattr( + OptModel, + 'eExistNetCap1_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.la, + rule=eExistNetCap1, + doc='maximum flow by existing network capacity [p.u.]')) if pIndLogConsole == 1: - print('eExistNetCap1 ... ', len(getattr(OptModel, 'eExistNetCap1_'+st)), ' rows') - - def eExistNetCap2(OptModel,sc,p,n,ni,nf,cc): - if (ni,nf,cc) in mTEPES.lc or mTEPES.pLineSwitching[ni,nf,cc] == 1: - return OptModel.vFlow[sc,p,n,ni,nf,cc] / max(mTEPES.pLineNTCBck[ni,nf,cc],mTEPES.pLineNTCFrw[ni,nf,cc]) <= OptModel.vLineCommit[sc,p,n,ni,nf,cc] + print('eExistNetCap1 ... ', len( + getattr(OptModel, 'eExistNetCap1_' + st)), ' rows') + + def eExistNetCap2(OptModel, sc, p, n, ni, nf, cc): + if (ni, nf, cc) in mTEPES.lc or mTEPES.pLineSwitching[ni, nf, cc] == 1: + return OptModel.vFlow[sc, + p, + n, + ni, + nf, + cc] / max(mTEPES.pLineNTCBck[ni, + nf, + cc], + mTEPES.pLineNTCFrw[ni, + nf, + cc]) <= OptModel.vLineCommit[sc, + p, + n, + ni, + nf, + cc] else: return Constraint.Skip - setattr(OptModel, 'eExistNetCap2_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.la, rule=eExistNetCap2, doc='maximum flow by existing network capacity [p.u.]')) + setattr( + OptModel, + 'eExistNetCap2_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.la, + rule=eExistNetCap2, + doc='maximum flow by existing network capacity [p.u.]')) if pIndLogConsole == 1: - print('eExistNetCap2 ... ', len(getattr(OptModel, 'eExistNetCap2_'+st)), ' rows') - - #%% - def eKirchhoff2ndLaw1(OptModel,sc,p,n,ni,nf,cc): - if (ni,nf,cc) in mTEPES.lca: - return OptModel.vFlow[sc,p,n,ni,nf,cc] / mTEPES.pBigMFlowBck[ni,nf,cc] - (OptModel.vTheta[sc,p,n,ni] - OptModel.vTheta[sc,p,n,nf]) / mTEPES.pLineX[ni,nf,cc] / mTEPES.pBigMFlowBck[ni,nf,cc] * mTEPES.pSBase >= - 1 + OptModel.vLineCommit[sc,p,n,ni,nf,cc] + print('eExistNetCap2 ... ', len( + getattr(OptModel, 'eExistNetCap2_' + st)), ' rows') + + # %% + def eKirchhoff2ndLaw1(OptModel, sc, p, n, ni, nf, cc): + if (ni, nf, cc) in mTEPES.lca: + return OptModel.vFlow[sc, + p, + n, + ni, + nf, + cc] / mTEPES.pBigMFlowBck[ni, + nf, + cc] - (OptModel.vTheta[sc, + p, + n, + ni] - OptModel.vTheta[sc, + p, + n, + nf]) / mTEPES.pLineX[ni, + nf, + cc] / mTEPES.pBigMFlowBck[ni, + nf, + cc] * mTEPES.pSBase >= - 1 + OptModel.vLineCommit[sc, + p, + n, + ni, + nf, + cc] else: - return OptModel.vFlow[sc,p,n,ni,nf,cc] / mTEPES.pBigMFlowBck[ni,nf,cc] - (OptModel.vTheta[sc,p,n,ni] - OptModel.vTheta[sc,p,n,nf]) / mTEPES.pLineX[ni,nf,cc] / mTEPES.pBigMFlowBck[ni,nf,cc] * mTEPES.pSBase == 0 - setattr(OptModel, 'eKirchhoff2ndLaw1_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.laa, rule=eKirchhoff2ndLaw1, doc='flow for each AC candidate line [rad]')) + return OptModel.vFlow[sc, + p, + n, + ni, + nf, + cc] / mTEPES.pBigMFlowBck[ni, + nf, + cc] - (OptModel.vTheta[sc, + p, + n, + ni] - OptModel.vTheta[sc, + p, + n, + nf]) / mTEPES.pLineX[ni, + nf, + cc] / mTEPES.pBigMFlowBck[ni, + nf, + cc] * mTEPES.pSBase == 0 + setattr( + OptModel, + 'eKirchhoff2ndLaw1_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.laa, + rule=eKirchhoff2ndLaw1, + doc='flow for each AC candidate line [rad]')) if pIndLogConsole == 1: - print('eKirchhoff2ndLaw1 ... ', len(getattr(OptModel, 'eKirchhoff2ndLaw1_'+st)), ' rows') - - def eKirchhoff2ndLaw2(OptModel,sc,p,n,ni,nf,cc): - if (ni,nf,cc) in mTEPES.lca: - return OptModel.vFlow[sc,p,n,ni,nf,cc] / mTEPES.pBigMFlowFrw[ni,nf,cc] - (OptModel.vTheta[sc,p,n,ni] - OptModel.vTheta[sc,p,n,nf]) / mTEPES.pLineX[ni,nf,cc] / mTEPES.pBigMFlowFrw[ni,nf,cc] * mTEPES.pSBase <= 1 - OptModel.vLineCommit[sc,p,n,ni,nf,cc] + print( + 'eKirchhoff2ndLaw1 ... ', len( + getattr( + OptModel, 'eKirchhoff2ndLaw1_' + st)), ' rows') + + def eKirchhoff2ndLaw2(OptModel, sc, p, n, ni, nf, cc): + if (ni, nf, cc) in mTEPES.lca: + return OptModel.vFlow[sc, + p, + n, + ni, + nf, + cc] / mTEPES.pBigMFlowFrw[ni, + nf, + cc] - (OptModel.vTheta[sc, + p, + n, + ni] - OptModel.vTheta[sc, + p, + n, + nf]) / mTEPES.pLineX[ni, + nf, + cc] / mTEPES.pBigMFlowFrw[ni, + nf, + cc] * mTEPES.pSBase <= 1 - OptModel.vLineCommit[sc, + p, + n, + ni, + nf, + cc] else: return Constraint.Skip - setattr(OptModel, 'eKirchhoff2ndLaw2_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.laa, rule=eKirchhoff2ndLaw2, doc='flow for each AC candidate line [rad]')) + setattr( + OptModel, + 'eKirchhoff2ndLaw2_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.laa, + rule=eKirchhoff2ndLaw2, + doc='flow for each AC candidate line [rad]')) if pIndLogConsole == 1: - print('eKirchhoff2ndLaw2 ... ', len(getattr(OptModel, 'eKirchhoff2ndLaw2_'+st)), ' rows') + print( + 'eKirchhoff2ndLaw2 ... ', len( + getattr( + OptModel, 'eKirchhoff2ndLaw2_' + st)), ' rows') - def eLineLosses1(OptModel,sc,p,n,ni,nf,cc): + def eLineLosses1(OptModel, sc, p, n, ni, nf, cc): if mTEPES.pIndNetLosses() and len(mTEPES.ll): - return OptModel.vLineLosses[sc,p,n,ni,nf,cc] >= - 0.5 * mTEPES.pLineLossFactor[ni,nf,cc] * OptModel.vFlow[sc,p,n,ni,nf,cc] + return OptModel.vLineLosses[sc, + p, + n, + ni, + nf, + cc] >= - 0.5 * mTEPES.pLineLossFactor[ni, + nf, + cc] * OptModel.vFlow[sc, + p, + n, + ni, + nf, + cc] else: return Constraint.Skip - setattr(OptModel, 'eLineLosses1_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.ll, rule=eLineLosses1, doc='ohmic losses for all the lines [GW]')) + setattr( + OptModel, + 'eLineLosses1_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.ll, + rule=eLineLosses1, + doc='ohmic losses for all the lines [GW]')) if pIndLogConsole == 1: - print('eLineLosses1 ... ', len(getattr(OptModel, 'eLineLosses1_'+st)), ' rows') + print('eLineLosses1 ... ', len( + getattr(OptModel, 'eLineLosses1_' + st)), ' rows') - def eLineLosses2(OptModel,sc,p,n,ni,nf,cc): + def eLineLosses2(OptModel, sc, p, n, ni, nf, cc): if mTEPES.pIndNetLosses() and len(mTEPES.ll): - return OptModel.vLineLosses[sc,p,n,ni,nf,cc] >= 0.5 * mTEPES.pLineLossFactor[ni,nf,cc] * OptModel.vFlow[sc,p,n,ni,nf,cc] + return OptModel.vLineLosses[sc, + p, + n, + ni, + nf, + cc] >= 0.5 * mTEPES.pLineLossFactor[ni, + nf, + cc] * OptModel.vFlow[sc, + p, + n, + ni, + nf, + cc] else: return Constraint.Skip - setattr(OptModel, 'eLineLosses2_'+st, Constraint(mTEPES.sc, mTEPES.p, mTEPES.n, mTEPES.ll, rule=eLineLosses2, doc='ohmic losses for all the lines [GW]')) + setattr( + OptModel, + 'eLineLosses2_' + st, + Constraint( + mTEPES.sc, + mTEPES.p, + mTEPES.n, + mTEPES.ll, + rule=eLineLosses2, + doc='ohmic losses for all the lines [GW]')) if pIndLogConsole == 1: - print('eLineLosses2 ... ', len(getattr(OptModel, 'eLineLosses2_'+st)), ' rows') + print('eLineLosses2 ... ', len( + getattr(OptModel, 'eLineLosses2_' + st)), ' rows') GeneratingNetConsTime = time.time() - StartTime if pIndLogConsole == 1: - print('Generating network constraints ... ', round(GeneratingNetConsTime), 's') + print('Generating network constraints ... ', + round(GeneratingNetConsTime), 's') diff --git a/openTEPES/openTEPES_OutputResults.py b/openTEPES/openTEPES_OutputResults.py index 4c117dc8..92791515 100644 --- a/openTEPES/openTEPES_OutputResults.py +++ b/openTEPES/openTEPES_OutputResults.py @@ -5,140 +5,756 @@ import time import os import pandas as pd -from collections import defaultdict +from collections import defaultdict import matplotlib.pyplot as plt import pyomo.environ as pyo -from pyomo.environ import Set +from pyomo.environ import Set def InvestmentResults(DirName, CaseName, OptModel, mTEPES): - #%% outputting the investment decisions + # %% outputting the investment decisions _path = os.path.join(DirName, CaseName) StartTime = time.time() if len(mTEPES.gc): - OutputToFile = pd.DataFrame.from_dict(OptModel.vGenerationInvest.extract_values(), orient='index', columns=[str(OptModel.vGenerationInvest)]) + OutputToFile = pd.DataFrame.from_dict(OptModel.vGenerationInvest.extract_values( + ), orient='index', columns=[str(OptModel.vGenerationInvest)]) OutputToFile.index.names = ['Generator'] OutputToFile = OutputToFile.reset_index() - OutputToFile.rename(columns={'vGenerationInvest': 'Investment Decision'}).to_csv(_path+'/oT_Result_GenerationInvestment_'+CaseName+'.csv', index=False, sep=',') + OutputToFile.rename( + columns={ + 'vGenerationInvest': 'Investment Decision'}).to_csv( + _path + + '/oT_Result_GenerationInvestment_' + + CaseName + + '.csv', + index=False, + sep=',') if len(mTEPES.lc): - OutputToFile = pd.DataFrame.from_dict(OptModel.vNetworkInvest.extract_values(), orient='index', columns=[str(OptModel.vNetworkInvest)]) + OutputToFile = pd.DataFrame.from_dict(OptModel.vNetworkInvest.extract_values( + ), orient='index', columns=[str(OptModel.vNetworkInvest)]) OutputToFile.index = pd.MultiIndex.from_tuples(OutputToFile.index) - OutputToFile.index.names = ['InitialNode','FinalNode','Circuit'] + OutputToFile.index.names = ['InitialNode', 'FinalNode', 'Circuit'] OutputToFile = OutputToFile.reset_index() - OutputToFile.rename(columns={'vNetworkInvest': 'Investment Decision'}).to_csv(_path + '/oT_Result_NetworkInvestment_' + CaseName + '.csv', index=False, sep=',') - + OutputToFile.rename( + columns={ + 'vNetworkInvest': 'Investment Decision'}).to_csv( + _path + + '/oT_Result_NetworkInvestment_' + + CaseName + + '.csv', + index=False, + sep=',') WritingResultsTime = time.time() - StartTime - StartTime = time.time() - print('Writing investment results ... ', round(WritingResultsTime), 's') + StartTime = time.time() + print('Writing investment results ... ', + round(WritingResultsTime), 's') def GenerationOperationResults(DirName, CaseName, OptModel, mTEPES): - #%% outputting the generation operation + # %% outputting the generation operation _path = os.path.join(DirName, CaseName) StartTime = time.time() - OutputToFile = pd.Series(data=[OptModel.vCommitment[sc,p,n,nr]() for sc,p,n,nr in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nr], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nr)) - OutputToFile.to_frame(name='p.u.').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='p.u.').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_GenerationCommitment_'+CaseName+'.csv', sep=',') - OutputToFile = pd.Series(data=[OptModel.vStartUp [sc,p,n,nr]() for sc,p,n,nr in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nr], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nr)) - OutputToFile.to_frame(name='p.u.').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='p.u.').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_GenerationStartUp_' +CaseName+'.csv', sep=',') - OutputToFile = pd.Series(data=[OptModel.vShutDown [sc,p,n,nr]() for sc,p,n,nr in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nr], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nr)) - OutputToFile.to_frame(name='p.u.').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='p.u.').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_GenerationShutDown_' +CaseName+'.csv', sep=',') - - if sum(mTEPES.pOperReserveUp[sc,p,n,ar] for sc,p,n,ar in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.ar): - OutputToFile = pd.Series(data=[OptModel.vReserveUp [sc,p,n,nr]() for sc,p,n,nr in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nr], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nr)) + OutputToFile = pd.Series(data=[OptModel.vCommitment[sc, + p, + n, + nr]() for sc, + p, + n, + nr in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.nr], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.nr)) + OutputToFile.to_frame( + name='p.u.').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='p.u.').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_GenerationCommitment_' + + CaseName + + '.csv', + sep=',') + OutputToFile = pd.Series(data=[OptModel.vStartUp[sc, + p, + n, + nr]() for sc, + p, + n, + nr in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.nr], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.nr)) + OutputToFile.to_frame( + name='p.u.').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='p.u.').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_GenerationStartUp_' + + CaseName + + '.csv', + sep=',') + OutputToFile = pd.Series(data=[OptModel.vShutDown[sc, + p, + n, + nr]() for sc, + p, + n, + nr in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.nr], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.nr)) + OutputToFile.to_frame( + name='p.u.').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='p.u.').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_GenerationShutDown_' + + CaseName + + '.csv', + sep=',') + + if sum(mTEPES.pOperReserveUp[sc, p, n, ar] for sc, p, n, + ar in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.ar): + OutputToFile = pd.Series(data=[OptModel.vReserveUp[sc, + p, + n, + nr]() for sc, + p, + n, + nr in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.nr], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.nr)) OutputToFile *= 1e3 OutputToFile = OutputToFile.fillna(0.0) - OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_GenerationReserveUp_'+CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[sum(OutputToFile[sc,p,n,nr] for nr in mTEPES.nr if (gt,nr) in mTEPES.t2g) for sc,p,n,gt in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt)) - OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_TechnologyReserveUp_'+CaseName+'.csv', sep=',') + OutputToFile.to_frame( + name='MW').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MW').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_GenerationReserveUp_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[sum(OutputToFile[sc, + p, + n, + nr] for nr in mTEPES.nr if (gt, + nr) in mTEPES.t2g) for sc, + p, + n, + gt in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt)) + OutputToFile.to_frame( + name='MW').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MW').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_TechnologyReserveUp_' + + CaseName + + '.csv', + sep=',') if len(mTEPES.es): - OutputToFile = pd.Series(data=[OptModel.vESSReserveUp [sc,p,n,es]() for sc,p,n,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es)) + OutputToFile = pd.Series(data=[OptModel.vESSReserveUp[sc, + p, + n, + es]() for sc, + p, + n, + es in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.es], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.es)) OutputToFile *= 1e3 OutputToFile = OutputToFile.fillna(0.0) - OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_ESSGenerationReserveUp_'+CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[sum(OutputToFile[sc,p,n,es] for es in mTEPES.es if (gt,es) in mTEPES.t2g) for sc,p,n,gt in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt)) - OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_ESSTechnologyReserveUp_'+CaseName+'.csv', sep=',') - - if sum(mTEPES.pOperReserveDw[sc,p,n,ar] for sc,p,n,ar in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.ar): - OutputToFile = pd.Series(data=[OptModel.vReserveDown [sc,p,n,nr]() for sc,p,n,nr in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nr], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nr)) + OutputToFile.to_frame( + name='MW').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MW').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_ESSGenerationReserveUp_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[sum(OutputToFile[sc, + p, + n, + es] for es in mTEPES.es if (gt, + es) in mTEPES.t2g) for sc, + p, + n, + gt in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt)) + OutputToFile.to_frame( + name='MW').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MW').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_ESSTechnologyReserveUp_' + + CaseName + + '.csv', + sep=',') + + if sum(mTEPES.pOperReserveDw[sc, p, n, ar] for sc, p, n, + ar in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.ar): + OutputToFile = pd.Series(data=[OptModel.vReserveDown[sc, + p, + n, + nr]() for sc, + p, + n, + nr in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.nr], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.nr)) OutputToFile *= 1e3 OutputToFile = OutputToFile.fillna(0.0) - OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_GenerationReserveDown_'+CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[sum(OutputToFile[sc,p,n,nr] for nr in mTEPES.nr if (gt,nr) in mTEPES.t2g) for sc,p,n,gt in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt)) - OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_TechnologyReserveDown_'+CaseName+'.csv', sep=',') + OutputToFile.to_frame( + name='MW').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MW').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_GenerationReserveDown_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[sum(OutputToFile[sc, + p, + n, + nr] for nr in mTEPES.nr if (gt, + nr) in mTEPES.t2g) for sc, + p, + n, + gt in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt)) + OutputToFile.to_frame( + name='MW').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MW').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_TechnologyReserveDown_' + + CaseName + + '.csv', + sep=',') if len(mTEPES.es): - OutputToFile = pd.Series(data=[OptModel.vESSReserveDown[sc,p,n,es]() for sc,p,n,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es)) + OutputToFile = pd.Series(data=[OptModel.vESSReserveDown[sc, + p, + n, + es]() for sc, + p, + n, + es in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.es], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.es)) OutputToFile *= 1e3 OutputToFile = OutputToFile.fillna(0.0) - OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_ESSGenerationReserveDown_'+CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[sum(OutputToFile[sc,p,n,es] for es in mTEPES.es if (gt,es) in mTEPES.t2g) for sc,p,n,gt in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt)) - OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_ESSTechnologyReserveDown_'+CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[OptModel.vTotalOutput[sc,p,n,g]()*1e3 for sc,p,n,g in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.g ], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.g )) - OutputToFile.to_frame(name='MW ').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW ').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_GenerationOutput_' +CaseName+'.csv', sep=',') + OutputToFile.to_frame( + name='MW').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MW').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_ESSGenerationReserveDown_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[sum(OutputToFile[sc, + p, + n, + es] for es in mTEPES.es if (gt, + es) in mTEPES.t2g) for sc, + p, + n, + gt in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt)) + OutputToFile.to_frame( + name='MW').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MW').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_ESSTechnologyReserveDown_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[OptModel.vTotalOutput[sc, p, n, g]() * + 1e3 for sc, p, n, g in mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.g], index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.g)) + OutputToFile.to_frame( + name='MW ').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MW ').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_GenerationOutput_' + + CaseName + + '.csv', + sep=',') if len(mTEPES.r): - OutputToFile = pd.Series(data=[(mTEPES.pMaxPower[sc,p,n,r]-OptModel.vTotalOutput[sc,p,n,r]())*1e3 for sc,p,n,r in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.r], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.r)) - OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW' ).rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_RESCurtailment_' +CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[(mTEPES.pMaxPower[sc,p,n,r]-OptModel.vTotalOutput[sc,p,n,r]())*mTEPES.pDuration[n]*mTEPES.pLoadLevelWeight[n]() for sc,p,n,r in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.r], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.r)) - OutputToFile.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='GWh').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_RESCurtailmentEnergy_' +CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[sum(OutputToFile[sc,p,n,r] for r in mTEPES.r if (gt,r) in mTEPES.t2g) for sc,p,n,gt in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt)) - OutputToFile.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='GWh').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_RESTechnologyCurtailment_'+CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[OptModel.vTotalOutput[sc,p,n,g ]()*mTEPES.pDuration[n]*mTEPES.pLoadLevelWeight[n]() for sc,p,n,g in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.g ], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.g )) - OutputToFile.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='GWh').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_GenerationEnergy_' +CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[OptModel.vTotalOutput[sc,p,n,nr]()*mTEPES.pDuration[n]*mTEPES.pLoadLevelWeight[n]()*mTEPES.pCO2EmissionCost[nr]*1e-3/mTEPES.pCO2Cost() for sc,p,n,nr in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nr], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nr)) - OutputToFile.to_frame(name='tCO2').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='tCO2').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_GenerationEmission_'+CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[sum(OptModel.vTotalOutput[sc,p,n,g]() for g in mTEPES.g if (gt,g) in mTEPES.t2g)*1e3 for sc,p,n,gt in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt)) - OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_TechnologyOutput_'+CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[OptModel.vTotalOutput[sc,p,n,g]()*mTEPES.pDuration[n]*mTEPES.pLoadLevelWeight[n]() for sc,p,n,g in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.g ], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.g )) - OutputToFile = pd.Series(data=[sum(OutputToFile[sc,p,n,g] for g in mTEPES.g if (gt,g) in mTEPES.t2g) for sc,p,n,gt in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt)) - OutputToFile.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='GWh').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_TechnologyEnergy_'+CaseName+'.csv', sep=',') + OutputToFile = pd.Series(data=[(mTEPES.pMaxPower[sc, p, n, r] - + OptModel.vTotalOutput[sc, p, n, r]()) * + 1e3 for sc, p, n, r in mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.r], index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.r)) + OutputToFile.to_frame( + name='MW').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MW').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_RESCurtailment_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[(mTEPES.pMaxPower[sc, p, n, r] - + OptModel.vTotalOutput[sc, p, n, r]()) * + mTEPES.pDuration[n] * + mTEPES.pLoadLevelWeight[n]() for sc, p, n, r in mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.r], index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.r)) + OutputToFile.to_frame( + name='GWh').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='GWh').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_RESCurtailmentEnergy_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[sum(OutputToFile[sc, + p, + n, + r] for r in mTEPES.r if (gt, + r) in mTEPES.t2g) for sc, + p, + n, + gt in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt)) + OutputToFile.to_frame( + name='GWh').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='GWh').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_RESTechnologyCurtailment_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[OptModel.vTotalOutput[sc, p, n, g]() * + mTEPES.pDuration[n] * + mTEPES.pLoadLevelWeight[n]() for sc, p, n, g in mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.g], index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.g)) + OutputToFile.to_frame( + name='GWh').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='GWh').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_GenerationEnergy_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[OptModel.vTotalOutput[sc, p, n, nr]() * + mTEPES.pDuration[n] * + mTEPES.pLoadLevelWeight[n]() * + mTEPES.pCO2EmissionCost[nr] * + 1e-3 / + mTEPES.pCO2Cost() for sc, p, n, nr in mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.nr], index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.nr)) + OutputToFile.to_frame( + name='tCO2').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='tCO2').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_GenerationEmission_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[sum(OptModel.vTotalOutput[sc, + p, + n, + g]() for g in mTEPES.g if (gt, + g) in mTEPES.t2g) * 1e3 for sc, + p, + n, + gt in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt)) + OutputToFile.to_frame( + name='MW').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MW').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_TechnologyOutput_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[OptModel.vTotalOutput[sc, p, n, g]() * + mTEPES.pDuration[n] * + mTEPES.pLoadLevelWeight[n]() for sc, p, n, g in mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.g], index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.g)) + OutputToFile = pd.Series(data=[sum(OutputToFile[sc, + p, + n, + g] for g in mTEPES.g if (gt, + g) in mTEPES.t2g) for sc, + p, + n, + gt in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt)) + OutputToFile.to_frame( + name='GWh').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='GWh').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_TechnologyEnergy_' + + CaseName + + '.csv', + sep=',') TechnologyEnergy = OutputToFile.to_frame(name='') - TechnologyEnergy[''] = (TechnologyEnergy[''] / TechnologyEnergy[''].sum()) * 100 + TechnologyEnergy[''] = (TechnologyEnergy[''] / + TechnologyEnergy[''].sum()) * 100 TechnologyEnergy.reset_index(level=3, inplace=True) - TechnologyEnergy.groupby(['level_3']).sum().plot(kind='pie', subplots=True, shadow=False, startangle=-40, figsize=(15, 10), autopct='%1.1f%%', pctdistance=0.85, title='Energy Generation', legend=False) + TechnologyEnergy.groupby( + ['level_3']).sum().plot( + kind='pie', + subplots=True, + shadow=False, + startangle=-40, + figsize=( + 15, + 10), + autopct='%1.1f%%', + pctdistance=0.85, + title='Energy Generation', + legend=False) # plt.legend(loc='center left', bbox_to_anchor=(1, 0, 0.5, 1)) centre_circle = plt.Circle((0, 0), 0.60, fc='white') fg = plt.gcf() fg.gca().add_artist(centre_circle) # plt.show() - plt.savefig(_path+'/oT_Plot_TechnologyEnergy_'+CaseName+'.png', bbox_inches=None, dpi=600) + plt.savefig( + _path + + '/oT_Plot_TechnologyEnergy_' + + CaseName + + '.png', + bbox_inches=None, + dpi=600) for ar in mTEPES.ar: if len(mTEPES.ar) > 1: - OutputToFile = pd.Series(data=[OptModel.vTotalOutput[sc,p,n,g]()*mTEPES.pDuration[n]*mTEPES.pLoadLevelWeight[n]() for sc,p,n,g in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.g ], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.g )) - OutputToFile = pd.Series(data=[sum(OutputToFile[sc,p,n,g] for g in mTEPES.g if (ar,g) in mTEPES.a2g and (gt,g) in mTEPES.t2g) for sc,p,n,gt in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt)) - OutputToFile.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='GWh').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_TechnologyEnergy_'+ar+'_'+CaseName+'.csv', sep=',') + OutputToFile = pd.Series(data=[OptModel.vTotalOutput[sc, p, n, g]() * + mTEPES.pDuration[n] * + mTEPES.pLoadLevelWeight[n]() for sc, p, n, g in mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.g], index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.g)) + OutputToFile = pd.Series(data=[sum(OutputToFile[sc, + p, + n, + g] for g in mTEPES.g if (ar, + g) in mTEPES.a2g and (gt, + g) in mTEPES.t2g) for sc, + p, + n, + gt in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt)) + OutputToFile.to_frame( + name='GWh').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='GWh').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_TechnologyEnergy_' + + ar + + '_' + + CaseName + + '.csv', + sep=',') TechnologyEnergy = OutputToFile.to_frame(name='') - TechnologyEnergy[''] = (TechnologyEnergy[''] / TechnologyEnergy[''].sum()) * 100 + TechnologyEnergy[''] = ( + TechnologyEnergy[''] / TechnologyEnergy[''].sum()) * 100 TechnologyEnergy.reset_index(level=3, inplace=True) - TechnologyEnergy.groupby(['level_3']).sum().plot(kind='pie', subplots=True, shadow=False, startangle=-40, figsize=(15, 10), autopct='%1.1f%%', pctdistance=0.85, title='Energy Generation in '+ar, legend=False) + TechnologyEnergy.groupby( + ['level_3']).sum().plot( + kind='pie', + subplots=True, + shadow=False, + startangle=-40, + figsize=( + 15, + 10), + autopct='%1.1f%%', + pctdistance=0.85, + title='Energy Generation in ' + ar, + legend=False) # plt.legend(loc='center left', bbox_to_anchor=(1, 0, 0.5, 1)) centre_circle = plt.Circle((0, 0), 0.60, fc='white') fg = plt.gcf() fg.gca().add_artist(centre_circle) # plt.show() - plt.savefig(_path+'/oT_Plot_TechnologyEnergy_'+ar+'_'+CaseName+'.png', bbox_inches=None, dpi=600) + plt.savefig( + _path + + '/oT_Plot_TechnologyEnergy_' + + ar + + '_' + + CaseName + + '.png', + bbox_inches=None, + dpi=600) WritingResultsTime = time.time() - StartTime - StartTime = time.time() - print('Writing generation operation results ... ', round(WritingResultsTime), 's') + StartTime = time.time() + print('Writing generation operation results ... ', + round(WritingResultsTime), 's') def ESSOperationResults(DirName, CaseName, OptModel, mTEPES): @@ -147,94 +763,483 @@ def ESSOperationResults(DirName, CaseName, OptModel, mTEPES): StartTime = time.time() if len(mTEPES.es): - OutputToFile = pd.Series(data=[OptModel.vEnergyOutflows [sc,p,n,es]()*1e3 for sc,p,n,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es)) - OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_GenerationOutflows_' +CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[sum(OutputToFile[sc,p,n,es] for es in mTEPES.es if (gt,es) in mTEPES.t2g) for sc,p,n,gt in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt)) - OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_TechnologyOutflows_'+CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[-OptModel.vESSTotalCharge [sc,p,n,es]()*1e3 for sc,p,n,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es)) - OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_ESSChargeOutput_' +CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[sum(OutputToFile[sc,p,n,es] for es in mTEPES.es if (gt,es) in mTEPES.t2g) for sc,p,n,gt in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt)) - OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_ESSTechnologyOutput_'+CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[OptModel.vEnergyOutflows [sc,p,n,es]()*mTEPES.pDuration[n]*mTEPES.pLoadLevelWeight[n]() for sc,p,n,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es)) - OutputToFile.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='GWh').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_GenerationOutflowsEnergy_'+CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[sum(OutputToFile[sc,p,n,es] for es in mTEPES.es if (gt,es) in mTEPES.t2g) for sc,p,n,gt in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt)) - OutputToFile.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='GWh').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_TechnologyOutflowsEnergy_'+CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[-OptModel.vESSTotalCharge [sc,p,n,es]()*mTEPES.pDuration[n]*mTEPES.pLoadLevelWeight[n]() for sc,p,n,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es)) - OutputToFile.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='GWh').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_ESSChargeEnergy_' +CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[sum(OutputToFile[sc,p,n,es] for es in mTEPES.es if (gt,es) in mTEPES.t2g) for sc,p,n,gt in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt)) - OutputToFile.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='GWh').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_ESSTechnologyEnergy_'+CaseName+'.csv', sep=',') + OutputToFile = pd.Series(data=[OptModel.vEnergyOutflows[sc, p, n, es]() * + 1e3 for sc, p, n, es in mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.es], index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.es)) + OutputToFile.to_frame( + name='MW').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MW').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_GenerationOutflows_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[sum(OutputToFile[sc, + p, + n, + es] for es in mTEPES.es if (gt, + es) in mTEPES.t2g) for sc, + p, + n, + gt in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt)) + OutputToFile.to_frame( + name='MW').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MW').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_TechnologyOutflows_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[-OptModel.vESSTotalCharge[sc, + p, + n, + es]() * 1e3 for sc, + p, + n, + es in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.es], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.es)) + OutputToFile.to_frame( + name='MW').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MW').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_ESSChargeOutput_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[sum(OutputToFile[sc, + p, + n, + es] for es in mTEPES.es if (gt, + es) in mTEPES.t2g) for sc, + p, + n, + gt in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt)) + OutputToFile.to_frame( + name='MW').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MW').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_ESSTechnologyOutput_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[OptModel.vEnergyOutflows[sc, p, n, es]() * + mTEPES.pDuration[n] * + mTEPES.pLoadLevelWeight[n]() for sc, p, n, es in mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.es], index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.es)) + OutputToFile.to_frame( + name='GWh').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='GWh').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_GenerationOutflowsEnergy_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[sum(OutputToFile[sc, + p, + n, + es] for es in mTEPES.es if (gt, + es) in mTEPES.t2g) for sc, + p, + n, + gt in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt)) + OutputToFile.to_frame( + name='GWh').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='GWh').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_TechnologyOutflowsEnergy_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[-OptModel.vESSTotalCharge[sc, + p, + n, + es]() * mTEPES.pDuration[n] * mTEPES.pLoadLevelWeight[n]() for sc, + p, + n, + es in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.es], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.es)) + OutputToFile.to_frame( + name='GWh').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='GWh').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_ESSChargeEnergy_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[sum(OutputToFile[sc, + p, + n, + es] for es in mTEPES.es if (gt, + es) in mTEPES.t2g) for sc, + p, + n, + gt in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt)) + OutputToFile.to_frame( + name='GWh').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='GWh').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_ESSTechnologyEnergy_' + + CaseName + + '.csv', + sep=',') OutputToFile *= -1 ESSTechnologyEnergy = OutputToFile.to_frame(name='') - ESSTechnologyEnergy[''] = (ESSTechnologyEnergy[''] / ESSTechnologyEnergy[''].sum()) * 100 + ESSTechnologyEnergy[''] = ( + ESSTechnologyEnergy[''] / ESSTechnologyEnergy[''].sum()) * 100 ESSTechnologyEnergy.reset_index(level=3, inplace=True) - ESSTechnologyEnergy.groupby(['level_3']).sum().plot(kind='pie', subplots=True, shadow=False, startangle=90, figsize=(15, 10), autopct='%1.1f%%', title='ESS Energy Consumption', legend=False) + ESSTechnologyEnergy.groupby( + ['level_3']).sum().plot( + kind='pie', + subplots=True, + shadow=False, + startangle=90, + figsize=( + 15, + 10), + autopct='%1.1f%%', + title='ESS Energy Consumption', + legend=False) # plt.legend(title='Energy Consumption', loc='center left', bbox_to_anchor=(1, 0, 0.5, 1)) centre_circle = plt.Circle((0, 0), 0.60, fc='white') fg = plt.gcf() fg.gca().add_artist(centre_circle) # plt.show() - plt.savefig(_path+'/oT_Plot_ESSTechnologyEnergy_'+CaseName+'.png', bbox_inches=None, dpi=600) + plt.savefig( + _path + + '/oT_Plot_ESSTechnologyEnergy_' + + CaseName + + '.png', + bbox_inches=None, + dpi=600) for ar in mTEPES.ar: if len(mTEPES.ar) > 1: - OutputToFile = pd.Series(data=[-OptModel.vESSTotalCharge [sc,p,n,es]()*mTEPES.pDuration[n]*mTEPES.pLoadLevelWeight[n]() for sc,p,n,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es)) - OutputToFile = pd.Series(data=[sum(OutputToFile[sc,p,n,es] for es in mTEPES.es if (ar,es) in mTEPES.a2g and (gt,es) in mTEPES.t2g) for sc,p,n,gt in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt)) - OutputToFile.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='GWh').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_ESSTechnologyEnergy_'+ar+'_'+CaseName+'.csv', sep=',') + OutputToFile = pd.Series(data=[-OptModel.vESSTotalCharge[sc, + p, + n, + es]() * mTEPES.pDuration[n] * mTEPES.pLoadLevelWeight[n]() for sc, + p, + n, + es in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.es], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.es)) + OutputToFile = pd.Series(data=[sum(OutputToFile[sc, + p, + n, + es] for es in mTEPES.es if (ar, + es) in mTEPES.a2g and (gt, + es) in mTEPES.t2g) for sc, + p, + n, + gt in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt)) + OutputToFile.to_frame( + name='GWh').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='GWh').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_ESSTechnologyEnergy_' + + ar + + '_' + + CaseName + + '.csv', + sep=',') OutputToFile *= -1 ESSTechnologyEnergy = OutputToFile.to_frame(name='') - ESSTechnologyEnergy[''] = (ESSTechnologyEnergy[''] / ESSTechnologyEnergy[''].sum()) * 100 + ESSTechnologyEnergy[''] = ( + ESSTechnologyEnergy[''] / ESSTechnologyEnergy[''].sum()) * 100 ESSTechnologyEnergy.reset_index(level=3, inplace=True) - ESSTechnologyEnergy.groupby(['level_3']).sum().plot(kind='pie', subplots=True, shadow=False, startangle=90, figsize=(15, 10), autopct='%1.1f%%', title='ESS Energy Consumption in '+ar, legend=False) + ESSTechnologyEnergy.groupby( + ['level_3']).sum().plot( + kind='pie', + subplots=True, + shadow=False, + startangle=90, + figsize=( + 15, + 10), + autopct='%1.1f%%', + title='ESS Energy Consumption in ' + + ar, + legend=False) # plt.legend(title='Energy Consumption', loc='center left', bbox_to_anchor=(1, 0, 0.5, 1)) centre_circle = plt.Circle((0, 0), 0.60, fc='white') fg = plt.gcf() fg.gca().add_artist(centre_circle) # plt.show() - plt.savefig(_path+'/oT_Plot_ESSTechnologyEnergy_'+ar+'_'+CaseName+'.png', bbox_inches=None, dpi=600) - - OutputToFile = pd.Series(data=[OptModel.vESSInventory[sc,p,n,es]() for sc,p,n,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es)) + plt.savefig( + _path + + '/oT_Plot_ESSTechnologyEnergy_' + + ar + + '_' + + CaseName + + '.png', + bbox_inches=None, + dpi=600) + + OutputToFile = pd.Series(data=[OptModel.vESSInventory[sc, + p, + n, + es]() for sc, + p, + n, + es in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.es], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.es)) OutputToFile = OutputToFile.fillna(0.0) - OutputToFile.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='GWh', dropna=False).rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_ESSInventory_'+CaseName+'.csv', sep=',') + OutputToFile.to_frame( + name='GWh').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='GWh', + dropna=False).rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_ESSInventory_' + + CaseName + + '.csv', + sep=',') # OutputToFile = pd.Series(data=[OptModel.vESSInventory[sc,p,n,es]()/mTEPES.pMaxStorage[sc,p,n,es] for sc,p,n,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es if mTEPES.pMaxStorage[sc,p,n,es] and mTEPES.n.ord(n) % mTEPES.pCycleTimeStep[es] == 0], index=pd.MultiIndex.from_tuples(list(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es)[mTEPES.pMaxStorage[sc,p,n,es] and mTEPES.n.ord(n) % mTEPES.pCycleTimeStep[es] == 0])) # OutputToFile = OutputToFile.fillna(0.0) # OutputToFile.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='GWh', dropna=False).rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_ESSInventoryUtilization_'+CaseName+'.csv', sep=',') - OutputToFile = pd.Series(data=[OptModel.vESSSpillage [sc,p,n,es]() for sc,p,n,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es)) + OutputToFile = pd.Series(data=[OptModel.vESSSpillage[sc, + p, + n, + es]() for sc, + p, + n, + es in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.es], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.es)) OutputToFile = OutputToFile.fillna(0.0) - OutputToFile.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='GWh', dropna=False).rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_ESSSpillage_'+CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[-OptModel.vESSTotalCharge[sc,p,n,es]()*1e3 for sc,p,n,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es)) - OutputToFile = pd.Series(data=[sum(OutputToFile[sc,p,n,es] for es in mTEPES.es if (gt,es) in mTEPES.t2g) for sc,p,n,gt in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt)) - OutputToFile.to_frame(name='MW' ).reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW' ).rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_TechnologyCharge_'+CaseName+'.csv', sep=',') - - TechnologyCharge = OutputToFile.loc[:,:,:,:] - - for sc,p in mTEPES.sc*mTEPES.p: + OutputToFile.to_frame( + name='GWh').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='GWh', + dropna=False).rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_ESSSpillage_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[-OptModel.vESSTotalCharge[sc, + p, + n, + es]() * 1e3 for sc, + p, + n, + es in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.es], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.es)) + OutputToFile = pd.Series(data=[sum(OutputToFile[sc, + p, + n, + es] for es in mTEPES.es if (gt, + es) in mTEPES.t2g) for sc, + p, + n, + gt in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt)) + OutputToFile.to_frame( + name='MW').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MW').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_TechnologyCharge_' + + CaseName + + '.csv', + sep=',') + + TechnologyCharge = OutputToFile.loc[:, :, :, :] + + for sc, p in mTEPES.sc * mTEPES.p: fig, fg = plt.subplots() - fg.stackplot(range(len(mTEPES.n)), TechnologyCharge.loc[sc,p,:,:].values.reshape(len(mTEPES.n),len(mTEPES.gt)).transpose().tolist(), labels=mTEPES.gt) + fg.stackplot(range(len(mTEPES.n)), TechnologyCharge.loc[sc, p, :, :].values.reshape( + len(mTEPES.n), len(mTEPES.gt)).transpose().tolist(), labels=mTEPES.gt) # fg.stackplot(range(len(mTEPES.n)), -TechnologyCharge.loc[sc,p,:,:].values.reshape(len(mTEPES.n),len(mTEPES.gt)).transpose().tolist(), labels=list(mTEPES.gt)) # fg.plot (range(len(mTEPES.n)), pDemand.sum(axis=1)*1e3, label='Demand', linewidth=0.2, color='k') fg.set(xlabel='Time Steps', ylabel='MW') - plt.title(sc+' '+p) + plt.title(sc + ' ' + p) fg.tick_params(axis='x', rotation=90) fg.legend() plt.tight_layout() # plt.show() - plt.savefig(_path+'/oT_Plot_TechnologyCharge_'+sc+'_'+p+'_'+CaseName+'.png', bbox_inches=None, dpi=600) + plt.savefig( + _path + + '/oT_Plot_TechnologyCharge_' + + sc + + '_' + + p + + '_' + + CaseName + + '.png', + bbox_inches=None, + dpi=600) WritingResultsTime = time.time() - StartTime StartTime = time.time() - print('Writing ESS operation results ... ', round(WritingResultsTime), 's') + print('Writing ESS operation results ... ', + round(WritingResultsTime), 's') def FlexibilityResults(DirName, CaseName, OptModel, mTEPES): @@ -242,35 +1247,214 @@ def FlexibilityResults(DirName, CaseName, OptModel, mTEPES): _path = os.path.join(DirName, CaseName) StartTime = time.time() - OutputToFile = pd.Series(data=[sum(OptModel.vTotalOutput[sc,p,n,g]() for g in mTEPES.g if (gt,g) in mTEPES.t2g)*1e3 for sc,p,n,gt in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt)) - TechnologyOutput = OutputToFile.loc[:,:,:,:] - MeanTechnologyOutput = OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).mean() - NetTechnologyOutput = pd.Series([0.0]*len(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt), index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt)) - for sc,p,n,gt in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt: - NetTechnologyOutput[sc,p,n,gt] = TechnologyOutput[sc,p,n,gt] - MeanTechnologyOutput[gt] - NetTechnologyOutput.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_FlexibilityTechnology_'+CaseName+'.csv', sep=',') + OutputToFile = pd.Series(data=[sum(OptModel.vTotalOutput[sc, + p, + n, + g]() for g in mTEPES.g if (gt, + g) in mTEPES.t2g) * 1e3 for sc, + p, + n, + gt in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt)) + TechnologyOutput = OutputToFile.loc[:, :, :, :] + MeanTechnologyOutput = OutputToFile.to_frame( + name='MW').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MW').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).mean() + NetTechnologyOutput = pd.Series( + [0.0] * + len( + mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.gt), + index=pd.MultiIndex.from_tuples( + mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.gt)) + for sc, p, n, gt in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.gt: + NetTechnologyOutput[sc, + p, + n, + gt] = TechnologyOutput[sc, + p, + n, + gt] - MeanTechnologyOutput[gt] + NetTechnologyOutput.to_frame( + name='MW').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MW').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_FlexibilityTechnology_' + + CaseName + + '.csv', + sep=',') if len(mTEPES.es): - ESSTechnologies = [(sc,p,n,gt) for sc,p,n,gt in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.gt if sum(1 for es in mTEPES.es if (gt,es) in mTEPES.t2g)] - OutputToFile = pd.Series(data=[sum(OptModel.vTotalOutput[sc,p,n,es]() for es in mTEPES.es if (gt,es) in mTEPES.t2g)*1e3 for sc,p,n,gt in ESSTechnologies], index=pd.MultiIndex.from_tuples(ESSTechnologies)) - ESSTechnologyOutput = -OutputToFile.loc[:,:,:,:] - MeanESSTechnologyOutput = -OutputToFile.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).mean() - NetESSTechnologyOutput = pd.Series([0.0] * len(ESSTechnologies), index=pd.MultiIndex.from_tuples(ESSTechnologies)) - for sc,p,n,gt in ESSTechnologies: - NetESSTechnologyOutput[sc,p,n,gt] = MeanESSTechnologyOutput[gt] - ESSTechnologyOutput[sc,p,n,gt] - NetESSTechnologyOutput.to_frame(name='MW').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_FlexibilityESSTechnology_'+CaseName+'.csv', sep=',') - - MeanDemand = pd.Series(data=[sum(mTEPES.pDemand[sc,p,n,nd] for nd in mTEPES.nd)*1e3 for sc,p,n in mTEPES.sc*mTEPES.p*mTEPES.n], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n)).mean() - OutputToFile = pd.Series(data=[sum(mTEPES.pDemand[sc,p,n,nd] for nd in mTEPES.nd)*1e3 - MeanDemand for sc,p,n in mTEPES.sc*mTEPES.p*mTEPES.n], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n)) - OutputToFile.to_frame(name='Demand').reset_index().pivot_table(index=['level_0','level_1','level_2']).rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_FlexibilityDemand_' +CaseName+'.csv', sep=',') - - MeanENS = pd.Series(data=[sum(OptModel.vENS[sc,p,n,nd]() for nd in mTEPES.nd)*1e3 for sc,p,n in mTEPES.sc*mTEPES.p*mTEPES.n], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n)).mean() - OutputToFile = pd.Series(data=[sum(OptModel.vENS[sc,p,n,nd]()*1e3 for nd in mTEPES.nd) - MeanENS for sc,p,n in mTEPES.sc*mTEPES.p*mTEPES.n], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n)) - OutputToFile.to_frame(name='PNS').reset_index().pivot_table(index=['level_0','level_1','level_2']).rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_FlexibilityPNS_' +CaseName+'.csv', sep=',') + ESSTechnologies = [ + (sc, + p, + n, + gt) for sc, + p, + n, + gt in mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.gt if sum( + 1 for es in mTEPES.es if ( + gt, + es) in mTEPES.t2g)] + OutputToFile = pd.Series(data=[sum(OptModel.vTotalOutput[sc, + p, + n, + es]() for es in mTEPES.es if (gt, + es) in mTEPES.t2g) * 1e3 for sc, + p, + n, + gt in ESSTechnologies], + index=pd.MultiIndex.from_tuples(ESSTechnologies)) + ESSTechnologyOutput = -OutputToFile.loc[:, :, :, :] + MeanESSTechnologyOutput = -OutputToFile.to_frame( + name='MW').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MW').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).mean() + NetESSTechnologyOutput = pd.Series( + [0.0] * len(ESSTechnologies), + index=pd.MultiIndex.from_tuples(ESSTechnologies)) + for sc, p, n, gt in ESSTechnologies: + NetESSTechnologyOutput[sc, + p, + n, + gt] = MeanESSTechnologyOutput[gt] - ESSTechnologyOutput[sc, + p, + n, + gt] + NetESSTechnologyOutput.to_frame( + name='MW').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MW').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_FlexibilityESSTechnology_' + + CaseName + + '.csv', + sep=',') + + MeanDemand = pd.Series(data=[sum(mTEPES.pDemand[sc, + p, + n, + nd] for nd in mTEPES.nd) * 1e3 for sc, + p, + n in mTEPES.sc * mTEPES.p * mTEPES.n], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n)).mean() + OutputToFile = pd.Series(data=[sum(mTEPES.pDemand[sc, + p, + n, + nd] for nd in mTEPES.nd) * 1e3 - MeanDemand for sc, + p, + n in mTEPES.sc * mTEPES.p * mTEPES.n], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n)) + OutputToFile.to_frame( + name='Demand').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2']).rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_FlexibilityDemand_' + + CaseName + + '.csv', + sep=',') + + MeanENS = pd.Series(data=[sum(OptModel.vENS[sc, + p, + n, + nd]() for nd in mTEPES.nd) * 1e3 for sc, + p, + n in mTEPES.sc * mTEPES.p * mTEPES.n], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n)).mean() + OutputToFile = pd.Series(data=[sum(OptModel.vENS[sc, p, n, nd]() * + 1e3 for nd in mTEPES.nd) - + MeanENS for sc, p, n in mTEPES.sc * + mTEPES.p * + mTEPES.n], index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n)) + OutputToFile.to_frame( + name='PNS').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2']).rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_FlexibilityPNS_' + + CaseName + + '.csv', + sep=',') WritingResultsTime = time.time() - StartTime StartTime = time.time() - print('Writing flexibility results ... ', round(WritingResultsTime), 's') + print('Writing flexibility results ... ', + round(WritingResultsTime), 's') def NetworkOperationResults(DirName, CaseName, OptModel, mTEPES): @@ -278,86 +1462,366 @@ def NetworkOperationResults(DirName, CaseName, OptModel, mTEPES): _path = os.path.join(DirName, CaseName) StartTime = time.time() - OutputToFile = pd.Series(data=[OptModel.vLineCommit [sc,p,n,ni,nf,cc]() for sc,p,n,ni,nf,cc in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.la], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.la)) - OutputToFile.index.names = ['Scenario','Period','LoadLevel','InitialNode','FinalNode','Circuit'] - OutputToFile = pd.pivot_table(OutputToFile.to_frame(name='p.u.'), values='p.u.', index=['Scenario','Period','LoadLevel'], columns=['InitialNode','FinalNode','Circuit'], fill_value=0.0) + OutputToFile = pd.Series(data=[OptModel.vLineCommit[sc, + p, + n, + ni, + nf, + cc]() for sc, + p, + n, + ni, + nf, + cc in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.la], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.la)) + OutputToFile.index.names = [ + 'Scenario', + 'Period', + 'LoadLevel', + 'InitialNode', + 'FinalNode', + 'Circuit'] + OutputToFile = pd.pivot_table( + OutputToFile.to_frame( + name='p.u.'), values='p.u.', index=[ + 'Scenario', 'Period', 'LoadLevel'], columns=[ + 'InitialNode', 'FinalNode', 'Circuit'], fill_value=0.0) OutputToFile.index.names = [None] * len(OutputToFile.index.names) - OutputToFile.to_csv(_path+'/oT_Result_NetworkCommitment_'+CaseName+'.csv', sep=',') - OutputToFile = pd.Series(data=[OptModel.vLineOnState [sc,p,n,ni,nf,cc]() for sc,p,n,ni,nf,cc in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.la], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.la)) - OutputToFile.index.names = ['Scenario','Period','LoadLevel','InitialNode','FinalNode','Circuit'] - OutputToFile = pd.pivot_table(OutputToFile.to_frame(name='p.u.'), values='p.u.', index=['Scenario','Period','LoadLevel'], columns=['InitialNode','FinalNode','Circuit'], fill_value=0.0) + OutputToFile.to_csv( + _path + + '/oT_Result_NetworkCommitment_' + + CaseName + + '.csv', + sep=',') + OutputToFile = pd.Series(data=[OptModel.vLineOnState[sc, + p, + n, + ni, + nf, + cc]() for sc, + p, + n, + ni, + nf, + cc in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.la], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.la)) + OutputToFile.index.names = [ + 'Scenario', + 'Period', + 'LoadLevel', + 'InitialNode', + 'FinalNode', + 'Circuit'] + OutputToFile = pd.pivot_table( + OutputToFile.to_frame( + name='p.u.'), values='p.u.', index=[ + 'Scenario', 'Period', 'LoadLevel'], columns=[ + 'InitialNode', 'FinalNode', 'Circuit'], fill_value=0.0) OutputToFile.index.names = [None] * len(OutputToFile.index.names) - OutputToFile.to_csv(_path+'/oT_Result_NetworkSwitchOn_' +CaseName+'.csv', sep=',') - OutputToFile = pd.Series(data=[OptModel.vLineOffState[sc,p,n,ni,nf,cc]() for sc,p,n,ni,nf,cc in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.la], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.la)) - OutputToFile.index.names = ['Scenario','Period','LoadLevel','InitialNode','FinalNode','Circuit'] - OutputToFile = pd.pivot_table(OutputToFile.to_frame(name='p.u.'), values='p.u.', index=['Scenario','Period','LoadLevel'], columns=['InitialNode','FinalNode','Circuit'], fill_value=0.0) + OutputToFile.to_csv( + _path + + '/oT_Result_NetworkSwitchOn_' + + CaseName + + '.csv', + sep=',') + OutputToFile = pd.Series(data=[OptModel.vLineOffState[sc, + p, + n, + ni, + nf, + cc]() for sc, + p, + n, + ni, + nf, + cc in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.la], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.la)) + OutputToFile.index.names = [ + 'Scenario', + 'Period', + 'LoadLevel', + 'InitialNode', + 'FinalNode', + 'Circuit'] + OutputToFile = pd.pivot_table( + OutputToFile.to_frame( + name='p.u.'), values='p.u.', index=[ + 'Scenario', 'Period', 'LoadLevel'], columns=[ + 'InitialNode', 'FinalNode', 'Circuit'], fill_value=0.0) OutputToFile.index.names = [None] * len(OutputToFile.index.names) - OutputToFile.to_csv(_path+'/oT_Result_NetworkSwitchOff_' +CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[OptModel.vFlow[sc,p,n,ni,nf,cc]()*1e3 for sc,p,n,ni,nf,cc in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.la], index= pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.la)) - OutputToFile.index.names = ['Scenario','Period','LoadLevel','InitialNode','FinalNode','Circuit'] - OutputToFile = pd.pivot_table(OutputToFile.to_frame(name='MW'), values='MW', index=['Scenario','Period','LoadLevel'], columns=['InitialNode','FinalNode','Circuit'], fill_value=0.0) + OutputToFile.to_csv( + _path + + '/oT_Result_NetworkSwitchOff_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[OptModel.vFlow[sc, p, n, ni, nf, cc]() * + 1e3 for sc, p, n, ni, nf, cc in mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.la], index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.la)) + OutputToFile.index.names = [ + 'Scenario', + 'Period', + 'LoadLevel', + 'InitialNode', + 'FinalNode', + 'Circuit'] + OutputToFile = pd.pivot_table( + OutputToFile.to_frame( + name='MW'), values='MW', index=[ + 'Scenario', 'Period', 'LoadLevel'], columns=[ + 'InitialNode', 'FinalNode', 'Circuit'], fill_value=0.0) OutputToFile.index.names = [None] * len(OutputToFile.index.names) - OutputToFile.to_csv(_path+'/oT_Result_NetworkFlow_'+CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[abs(OptModel.vFlow[sc,p,n,ni,nf,cc]()/max(mTEPES.pLineNTCBck[ni,nf,cc],mTEPES.pLineNTCFrw[ni,nf,cc])) for sc,p,n,ni,nf,cc in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.la], index= pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.la)) - OutputToFile.index.names = ['Scenario','Period','LoadLevel','InitialNode','FinalNode','Circuit'] - OutputToFile = pd.pivot_table(OutputToFile.to_frame(name='pu'), values='pu', index=['Scenario','Period','LoadLevel'], columns=['InitialNode','FinalNode','Circuit'], fill_value=0.0) + OutputToFile.to_csv( + _path + + '/oT_Result_NetworkFlow_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[abs(OptModel.vFlow[sc, + p, + n, + ni, + nf, + cc]() / max(mTEPES.pLineNTCBck[ni, + nf, + cc], + mTEPES.pLineNTCFrw[ni, + nf, + cc])) for sc, + p, + n, + ni, + nf, + cc in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.la], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.la)) + OutputToFile.index.names = [ + 'Scenario', + 'Period', + 'LoadLevel', + 'InitialNode', + 'FinalNode', + 'Circuit'] + OutputToFile = pd.pivot_table( + OutputToFile.to_frame( + name='pu'), values='pu', index=[ + 'Scenario', 'Period', 'LoadLevel'], columns=[ + 'InitialNode', 'FinalNode', 'Circuit'], fill_value=0.0) OutputToFile.index.names = [None] * len(OutputToFile.index.names) - OutputToFile.to_csv(_path+'/oT_Result_NetworkUtilization_'+CaseName+'.csv', sep=',') + OutputToFile.to_csv( + _path + + '/oT_Result_NetworkUtilization_' + + CaseName + + '.csv', + sep=',') if mTEPES.pIndNetLosses(): - OutputToFile = pd.Series(data=[OptModel.vLineLosses[sc,p,n,ni,nf,cc]() for sc,p,n,ni,nf,cc in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.ll], index= pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.ll)) - OutputToFile.index.names = ['Scenario','Period','LoadLevel','InitialNode','FinalNode','Circuit'] - OutputToFile = pd.pivot_table(OutputToFile.to_frame(name='pu'), values='pu', index=['Scenario','Period','LoadLevel'], columns=['InitialNode','FinalNode','Circuit'], fill_value=0.0) + OutputToFile = pd.Series(data=[OptModel.vLineLosses[sc, + p, + n, + ni, + nf, + cc]() for sc, + p, + n, + ni, + nf, + cc in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.ll], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.ll)) + OutputToFile.index.names = [ + 'Scenario', + 'Period', + 'LoadLevel', + 'InitialNode', + 'FinalNode', + 'Circuit'] + OutputToFile = pd.pivot_table( + OutputToFile.to_frame( + name='pu'), values='pu', index=[ + 'Scenario', 'Period', 'LoadLevel'], columns=[ + 'InitialNode', 'FinalNode', 'Circuit'], fill_value=0.0) OutputToFile.index.names = [None] * len(OutputToFile.index.names) - OutputToFile.to_csv(_path+'/oT_Result_NetworkLosses_'+CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[OptModel.vTheta[sc,p,n,nd]() for sc,p,n,nd in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nd], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nd)) - OutputToFile.to_frame(name='rad').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='rad').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_NetworkAngle_'+CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[OptModel.vENS[sc,p,n,nd]()*1e3 for sc,p,n,nd in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nd], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nd)) - OutputToFile.to_frame(name='MW' ).reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MW' ).rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_NetworkPNS_'+CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[OptModel.vENS[sc,p,n,nd]()*mTEPES.pDuration[n]*mTEPES.pLoadLevelWeight[n]() for sc,p,n,nd in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nd], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nd)) - OutputToFile.to_frame(name='GWh').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='GWh').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_NetworkENS_'+CaseName+'.csv', sep=',') + OutputToFile.to_csv( + _path + + '/oT_Result_NetworkLosses_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[OptModel.vTheta[sc, + p, + n, + nd]() for sc, + p, + n, + nd in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.nd], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.nd)) + OutputToFile.to_frame( + name='rad').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='rad').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_NetworkAngle_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[OptModel.vENS[sc, p, n, nd]() * + 1e3 for sc, p, n, nd in mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.nd], index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.nd)) + OutputToFile.to_frame( + name='MW').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MW').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_NetworkPNS_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[OptModel.vENS[sc, p, n, nd]() * + mTEPES.pDuration[n] * + mTEPES.pLoadLevelWeight[n]() for sc, p, n, nd in mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.nd], index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.nd)) + OutputToFile.to_frame( + name='GWh').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='GWh').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_NetworkENS_' + + CaseName + + '.csv', + sep=',') WritingResultsTime = time.time() - StartTime StartTime = time.time() - print('Writing network operation results ... ', round(WritingResultsTime), 's') + print('Writing network operation results ... ', + round(WritingResultsTime), 's') def MarginalResults(DirName, CaseName, OptModel, mTEPES): - #%% outputting the up operating reserve marginal + # %% outputting the up operating reserve marginal _path = os.path.join(DirName, CaseName) StartTime = time.time() # incoming and outgoing lines (lin) (lout) - lin = defaultdict(list) + lin = defaultdict(list) lout = defaultdict(list) - for ni,nf,cc in mTEPES.la: - lin [nf].append((ni,cc)) - lout[ni].append((nf,cc)) + for ni, nf, cc in mTEPES.la: + lin[nf].append((ni, cc)) + lout[ni].append((nf, cc)) - #%% outputting the LSRMC + # %% outputting the LSRMC AppendData = [] for st in mTEPES.st: mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration and (st,nn) in mTEPES.s2n) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration and ( + st, + nn) in mTEPES.s2n) if len(mTEPES.n): - OutputToFile = pd.Series(data=[OptModel.dual[getattr(OptModel, 'eBalance_'+st)[sc,p,n,nd]]*1e3/mTEPES.pScenProb[sc]/mTEPES.pDuration[n] for sc,p,n,nd in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nd if sum(1 for g in mTEPES.g if (nd,g) in mTEPES.n2g) + sum(1 for lout in lout[nd]) + sum(1 for ni,cc in lin[nd])], index=pd.MultiIndex.from_tuples(getattr(OptModel, 'eBalance_'+st))) + OutputToFile = pd.Series(data=[OptModel.dual[getattr(OptModel, 'eBalance_' + + st)[sc, p, n, nd]] * + 1e3 / + mTEPES.pScenProb[sc] / + mTEPES.pDuration[n] for sc, p, n, nd in mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.nd if sum(1 for g in mTEPES.g if (nd, g) in mTEPES.n2g) + + sum(1 for lout in lout[nd]) + + sum(1 for ni, cc in lin[nd])], index=pd.MultiIndex.from_tuples(getattr(OptModel, 'eBalance_' + + st))) AppendData.append(OutputToFile) mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration) AppendData = pd.concat(AppendData) - AppendData.to_frame(name='LSRMC').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='LSRMC').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_LSRMC_'+CaseName+'.csv', sep=',') - - LSRMC = OutputToFile.loc[:,:] + AppendData.to_frame( + name='LSRMC').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='LSRMC').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_LSRMC_' + + CaseName + + '.csv', + sep=',') + + LSRMC = OutputToFile.loc[:, :] fig, fg = plt.subplots() for nd in mTEPES.nd: - if sum(1 for g in mTEPES.g if (nd,g) in mTEPES.n2g) + sum(1 for lout in lout[nd]) + sum(1 for ni,cc in lin[nd]): - fg.plot(range(len(LSRMC[:,:,:,nd])), LSRMC[:,:,:,nd], label=nd) + if sum(1 for g in mTEPES.g if (nd, g) in mTEPES.n2g) + \ + sum(1 for lout in lout[nd]) + sum(1 for ni, cc in lin[nd]): + fg.plot(range(len(LSRMC[:, :, :, nd])), + LSRMC[:, :, :, nd], label=nd) fg.set(xlabel='Time Steps', ylabel='EUR/MWh') fg.set_ybound(lower=0, upper=100) plt.title('LSRMC') @@ -365,27 +1829,81 @@ def MarginalResults(DirName, CaseName, OptModel, mTEPES): fg.legend() plt.tight_layout() # plt.show() - plt.savefig(_path+'/oT_Plot_LSRMC_'+CaseName+'.png', bbox_inches=None, dpi=600) - - if sum(mTEPES.pOperReserveUp[sc,p,n,ar] for sc,p,n,ar in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.ar): + plt.savefig( + _path + + '/oT_Plot_LSRMC_' + + CaseName + + '.png', + bbox_inches=None, + dpi=600) + + if sum(mTEPES.pOperReserveUp[sc, p, n, ar] for sc, p, n, + ar in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.ar): AppendData = [] for st in mTEPES.st: mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration and (st,nn) in mTEPES.s2n) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration and ( + st, + nn) in mTEPES.s2n) if len(mTEPES.n): - OutputToFile = pd.Series(data=[OptModel.dual[getattr(OptModel, 'eOperReserveUp_'+st)[sc,p,n,ar]]*1e3/mTEPES.pScenProb[sc]/mTEPES.pDuration[n]/mTEPES.pLoadLevelWeight[n]() for sc,p,n,ar in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.ar if mTEPES.pOperReserveUp[sc,p,n,ar] and sum(1 for nr in mTEPES.nr if (ar,nr) in mTEPES.a2g) + sum(1 for es in mTEPES.es if (ar,es) in mTEPES.a2g)], index=pd.MultiIndex.from_tuples(getattr(OptModel, 'eOperReserveUp_'+st))) + OutputToFile = pd.Series(data=[OptModel.dual[getattr(OptModel, + 'eOperReserveUp_' + st)[sc, + p, + n, + ar]] * 1e3 / mTEPES.pScenProb[sc] / mTEPES.pDuration[n] / mTEPES.pLoadLevelWeight[n]() for sc, + p, + n, + ar in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.ar if mTEPES.pOperReserveUp[sc, + p, + n, + ar] and sum(1 for nr in mTEPES.nr if (ar, + nr) in mTEPES.a2g) + sum(1 for es in mTEPES.es if (ar, + es) in mTEPES.a2g)], + index=pd.MultiIndex.from_tuples(getattr(OptModel, + 'eOperReserveUp_' + st))) AppendData.append(OutputToFile) mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration) AppendData = pd.concat(AppendData) - AppendData.to_frame(name='UORM').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='UORM').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_MarginalOperatingReserveUp_'+CaseName+'.csv', sep=',') - - MarginalUpOperatingReserve = OutputToFile.loc[:,:] + AppendData.to_frame( + name='UORM').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='UORM').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_MarginalOperatingReserveUp_' + + CaseName + + '.csv', + sep=',') + + MarginalUpOperatingReserve = OutputToFile.loc[:, :] fig, fg = plt.subplots() for ar in mTEPES.ar: - if sum(mTEPES.pOperReserveUp[sc,p,n,ar] for sc,p,n in mTEPES.sc*mTEPES.p*mTEPES.n): - fg.plot(range(len(MarginalUpOperatingReserve[:,:,:,ar])), MarginalUpOperatingReserve[:,:,:,ar], label=ar) + if sum(mTEPES.pOperReserveUp[sc, p, n, ar] + for sc, p, n in mTEPES.sc * mTEPES.p * mTEPES.n): + fg.plot(range(len( + MarginalUpOperatingReserve[:, :, :, ar])), MarginalUpOperatingReserve[:, :, :, ar], label=ar) fg.set(xlabel='Time Steps', ylabel='EUR/MW') fg.set_ybound(lower=0, upper=100) plt.title('Upward Operating Reserve Marginal') @@ -393,28 +1911,82 @@ def MarginalResults(DirName, CaseName, OptModel, mTEPES): fg.legend() plt.tight_layout() # plt.show() - plt.savefig(_path+'/oT_Plot_MarginalOperatingReserveUpward_'+CaseName+'.png', bbox_inches=None, dpi=600) - - #%% outputting the down operating reserve marginal - if sum(mTEPES.pOperReserveDw[sc,p,n,ar] for sc,p,n,ar in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.ar): + plt.savefig( + _path + + '/oT_Plot_MarginalOperatingReserveUpward_' + + CaseName + + '.png', + bbox_inches=None, + dpi=600) + + # %% outputting the down operating reserve marginal + if sum(mTEPES.pOperReserveDw[sc, p, n, ar] for sc, p, n, + ar in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.ar): AppendData = [] for st in mTEPES.st: mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration and (st,nn) in mTEPES.s2n) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration and ( + st, + nn) in mTEPES.s2n) if len(mTEPES.n): - OutputToFile = pd.Series(data=[OptModel.dual[getattr(OptModel, 'eOperReserveDw_'+st)[sc,p,n,ar]]*1e3/mTEPES.pScenProb[sc]/mTEPES.pDuration[n]/mTEPES.pLoadLevelWeight[n]() for sc,p,n,ar in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.ar if mTEPES.pOperReserveDw[sc,p,n,ar] and sum(1 for nr in mTEPES.nr if (ar,nr) in mTEPES.a2g) + sum(1 for es in mTEPES.es if (ar,es) in mTEPES.a2g)], index=pd.MultiIndex.from_tuples(getattr(OptModel, 'eOperReserveDw_'+st))) + OutputToFile = pd.Series(data=[OptModel.dual[getattr(OptModel, + 'eOperReserveDw_' + st)[sc, + p, + n, + ar]] * 1e3 / mTEPES.pScenProb[sc] / mTEPES.pDuration[n] / mTEPES.pLoadLevelWeight[n]() for sc, + p, + n, + ar in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.ar if mTEPES.pOperReserveDw[sc, + p, + n, + ar] and sum(1 for nr in mTEPES.nr if (ar, + nr) in mTEPES.a2g) + sum(1 for es in mTEPES.es if (ar, + es) in mTEPES.a2g)], + index=pd.MultiIndex.from_tuples(getattr(OptModel, + 'eOperReserveDw_' + st))) AppendData.append(OutputToFile) mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration) AppendData = pd.concat(AppendData) - AppendData.to_frame(name='DORM').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='DORM').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_MarginalOperatingReserveDown_'+CaseName+'.csv', sep=',') - - MarginalDwOperatingReserve = OutputToFile.loc[:,:] + AppendData.to_frame( + name='DORM').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='DORM').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_MarginalOperatingReserveDown_' + + CaseName + + '.csv', + sep=',') + + MarginalDwOperatingReserve = OutputToFile.loc[:, :] fig, fg = plt.subplots() for ar in mTEPES.ar: - if sum(mTEPES.pOperReserveDw[sc,p,n,ar] for sc,p,n in mTEPES.sc*mTEPES.p*mTEPES.n): - fg.plot(range(len(MarginalDwOperatingReserve[:,:,:,ar])), MarginalDwOperatingReserve[:,:,:,ar], label=ar) + if sum(mTEPES.pOperReserveDw[sc, p, n, ar] + for sc, p, n in mTEPES.sc * mTEPES.p * mTEPES.n): + fg.plot(range(len( + MarginalDwOperatingReserve[:, :, :, ar])), MarginalDwOperatingReserve[:, :, :, ar], label=ar) fg.set(xlabel='Time Steps', ylabel='EUR/MW') fg.set_ybound(lower=0, upper=100) plt.title('Downward Operating Reserve Marginal') @@ -422,27 +1994,91 @@ def MarginalResults(DirName, CaseName, OptModel, mTEPES): fg.legend() plt.tight_layout() # plt.show() - plt.savefig(_path+'/oT_Plot_MarginalOperatingReserveDownward_'+CaseName+'.png', bbox_inches=None, dpi=600) - - #%% outputting the water values + plt.savefig( + _path + + '/oT_Plot_MarginalOperatingReserveDownward_' + + CaseName + + '.png', + bbox_inches=None, + dpi=600) + + # %% outputting the water values if len(mTEPES.es): AppendData = [] for st in mTEPES.st: mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration and (st,nn) in mTEPES.s2n) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration and ( + st, + nn) in mTEPES.s2n) if len(mTEPES.n): - OutputToFile = pd.Series(data=[OptModel.dual[getattr(OptModel, 'eESSInventory_'+st)[sc,p,n,es]]*1e3/mTEPES.pScenProb[sc]/mTEPES.pDuration[n]/mTEPES.pLoadLevelWeight[n]() for sc,p,n,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es if mTEPES.n.ord(n) % mTEPES.pCycleTimeStep[es] == 0], index=pd.MultiIndex.from_tuples(getattr(OptModel, 'eESSInventory_'+st))) + OutputToFile = pd.Series( + data=[ + OptModel.dual[ + getattr( + OptModel, + 'eESSInventory_' + + st)[ + sc, + p, + n, + es]] * + 1e3 / + mTEPES.pScenProb[sc] / + mTEPES.pDuration[n] / + mTEPES.pLoadLevelWeight[n]() for sc, + p, + n, + es in mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.es if mTEPES.n.ord(n) % + mTEPES.pCycleTimeStep[es] == 0], + index=pd.MultiIndex.from_tuples( + getattr( + OptModel, + 'eESSInventory_' + + st))) AppendData.append(OutputToFile) mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration) AppendData = pd.concat(AppendData) - AppendData.to_frame(name='WaterValue').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='WaterValue').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_WaterValue_'+CaseName+'.csv', sep=',') - - WaterValue = OutputToFile.loc[:,:] + AppendData.to_frame( + name='WaterValue').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='WaterValue').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_WaterValue_' + + CaseName + + '.csv', + sep=',') + + WaterValue = OutputToFile.loc[:, :] fig, fg = plt.subplots() for es in mTEPES.es: - fg.plot(range(len(WaterValue[:,:,:,es])), WaterValue[:,:,:,es], label=es) + fg.plot(range(len(WaterValue[:, :, :, es])), + WaterValue[:, :, :, es], label=es) fg.set(xlabel='Time Steps', ylabel='EUR/MWh') fg.set_ybound(lower=0, upper=100) plt.title('Water Value') @@ -450,36 +2086,99 @@ def MarginalResults(DirName, CaseName, OptModel, mTEPES): fg.legend() plt.tight_layout() # plt.show() - plt.savefig(_path+'/oT_Plot_WaterValue_'+CaseName+'.png', bbox_inches=None, dpi=600) - - #%% Reduced cost for NetworkInvestment - ReducedCostActivation = mTEPES.pIndBinGenInvest()*len(mTEPES.gc) + mTEPES.pIndBinNetInvest()*len(mTEPES.lc) + mTEPES.pIndBinGenOperat()*len(mTEPES.nr) + mTEPES.pIndBinLineCommit()*len(mTEPES.la) + plt.savefig( + _path + + '/oT_Plot_WaterValue_' + + CaseName + + '.png', + bbox_inches=None, + dpi=600) + + # %% Reduced cost for NetworkInvestment + ReducedCostActivation = mTEPES.pIndBinGenInvest() * len(mTEPES.gc) + mTEPES.pIndBinNetInvest() * \ + len(mTEPES.lc) + mTEPES.pIndBinGenOperat() * len(mTEPES.nr) + mTEPES.pIndBinLineCommit() * len(mTEPES.la) if len(mTEPES.lc) and not ReducedCostActivation: - OutputToFile = pd.Series(data=[OptModel.rc[OptModel.vNetworkInvest[ni,nf,cc]] for ni,nf,cc in mTEPES.lc], index=pd.MultiIndex.from_tuples(getattr(OptModel, 'vNetworkInvest'))) + OutputToFile = pd.Series(data=[OptModel.rc[OptModel.vNetworkInvest[ni, nf, cc]] for ni, nf, + cc in mTEPES.lc], index=pd.MultiIndex.from_tuples(getattr(OptModel, 'vNetworkInvest'))) OutputToFile.index.names = ['InitialNode', 'FinalNode', 'Circuit'] - OutputToFile.to_frame(name='p.u.').to_csv(_path + '/oT_Result_NetworkInvestment_ReducedCost_'+CaseName+'.csv', sep=',') + OutputToFile.to_frame( + name='p.u.').to_csv( + _path + + '/oT_Result_NetworkInvestment_ReducedCost_' + + CaseName + + '.csv', + sep=',') # %% Reduced cost for NetworkCommitment - mTEPES.las = Set(initialize=mTEPES.ni*mTEPES.nf*mTEPES.cc, ordered=False, doc='all real lines with switching decision', filter=lambda mTEPES,ni,nf,cc: (ni,nf,cc) in mTEPES.pLineX and mTEPES.pLineSwitching[ni,nf,cc]) + mTEPES.las = Set(initialize=mTEPES.ni * mTEPES.nf * mTEPES.cc, + ordered=False, + doc='all real lines with switching decision', + filter=lambda mTEPES, + ni, + nf, + cc: (ni, + nf, + cc) in mTEPES.pLineX and mTEPES.pLineSwitching[ni, + nf, + cc]) if len(mTEPES.las) and not ReducedCostActivation: AppendData = [] for st in mTEPES.st: mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration and (st,nn) in mTEPES.s2n) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration and ( + st, + nn) in mTEPES.s2n) if len(mTEPES.n): - OutputToFile = pd.Series(data=[OptModel.rc[OptModel.vLineCommit[sc,p,n,ni,nf,cc]] for sc,p,n,ni,nf,cc in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.las], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.las)) + OutputToFile = pd.Series(data=[OptModel.rc[OptModel.vLineCommit[sc, + p, + n, + ni, + nf, + cc]] for sc, + p, + n, + ni, + nf, + cc in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.las], + index=pd.MultiIndex.from_tuples(mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.las)) AppendData.append(OutputToFile) mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration) AppendData = pd.concat(AppendData) - AppendData.index.names = ['Scenario','Period','LoadLevel','InitialNode','FinalNode','Circuit'] - AppendData = pd.pivot_table(AppendData.to_frame(name='p.u.'), values='p.u.', index=['Scenario','Period','LoadLevel'], columns=['InitialNode','FinalNode','Circuit'], fill_value=0.0) + AppendData.index.names = [ + 'Scenario', + 'Period', + 'LoadLevel', + 'InitialNode', + 'FinalNode', + 'Circuit'] + AppendData = pd.pivot_table( + AppendData.to_frame( + name='p.u.'), values='p.u.', index=[ + 'Scenario', 'Period', 'LoadLevel'], columns=[ + 'InitialNode', 'FinalNode', 'Circuit'], fill_value=0.0) AppendData.index.names = [None] * len(AppendData.index.names) - AppendData.to_csv(_path+'/oT_Result_NetworkCommitment_ReducedCost_' +CaseName+'.csv', sep=',') + AppendData.to_csv( + _path + + '/oT_Result_NetworkCommitment_ReducedCost_' + + CaseName + + '.csv', + sep=',') WritingResultsTime = time.time() - StartTime StartTime = time.time() - print('Writing marginal information results ... ', round(WritingResultsTime), 's') + print('Writing marginal information results ... ', + round(WritingResultsTime), 's') def EconomicResults(DirName, CaseName, OptModel, mTEPES): @@ -487,116 +2186,597 @@ def EconomicResults(DirName, CaseName, OptModel, mTEPES): _path = os.path.join(DirName, CaseName) StartTime = time.time() - OutputToFile = pd.Series(data=[(mTEPES.pScenProb[sc] * mTEPES.pLoadLevelWeight[n]() * mTEPES.pDuration[n] * mTEPES.pLinearVarCost [nr] * OptModel.vTotalOutput[sc,p,n,nr]() + - mTEPES.pScenProb[sc] * mTEPES.pLoadLevelWeight[n]() * mTEPES.pDuration[n] * mTEPES.pConstantVarCost[nr] * OptModel.vCommitment [sc,p,n,nr]() + - mTEPES.pScenProb[sc] * mTEPES.pLoadLevelWeight[n]() * mTEPES.pStartUpCost [nr] * OptModel.vStartUp [sc,p,n,nr]() + - mTEPES.pScenProb[sc] * mTEPES.pLoadLevelWeight[n]() * mTEPES.pShutDownCost [nr] * OptModel.vShutDown [sc,p,n,nr]()) for sc,p,n,nr in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nr], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nr)) - OutputToFile.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MEUR').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_GenerationOperationCost_' +CaseName+'.csv', sep=',') + OutputToFile = pd.Series(data=[(mTEPES.pScenProb[sc] * + mTEPES.pLoadLevelWeight[n]() * + mTEPES.pDuration[n] * + mTEPES.pLinearVarCost[nr] * + OptModel.vTotalOutput[sc, p, n, nr]() + + mTEPES.pScenProb[sc] * + mTEPES.pLoadLevelWeight[n]() * + mTEPES.pDuration[n] * + mTEPES.pConstantVarCost[nr] * + OptModel.vCommitment[sc, p, n, nr]() + + mTEPES.pScenProb[sc] * + mTEPES.pLoadLevelWeight[n]() * + mTEPES.pStartUpCost[nr] * + OptModel.vStartUp[sc, p, n, nr]() + + mTEPES.pScenProb[sc] * + mTEPES.pLoadLevelWeight[n]() * + mTEPES.pShutDownCost[nr] * + OptModel.vShutDown[sc, p, n, nr]()) for sc, p, n, nr in mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.nr], index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.nr)) + OutputToFile.to_frame( + name='MEUR').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MEUR').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_GenerationOperationCost_' + + CaseName + + '.csv', + sep=',') if len(mTEPES.r): - OutputToFile = pd.Series(data=[mTEPES.pScenProb[sc] * mTEPES.pDuration[n] * mTEPES.pLoadLevelWeight[n]() * mTEPES.pLinearOMCost [ r] * OptModel.vTotalOutput [sc,p,n, r]() for sc,p,n, r in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.r ], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.r )) - OutputToFile.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MEUR').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_GenerationOandMCost_' +CaseName+'.csv', sep=',') + OutputToFile = pd.Series(data=[mTEPES.pScenProb[sc] * + mTEPES.pDuration[n] * + mTEPES.pLoadLevelWeight[n]() * + mTEPES.pLinearOMCost[r] * + OptModel.vTotalOutput[sc, p, n, r]() for sc, p, n, r in mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.r], index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.r)) + OutputToFile.to_frame( + name='MEUR').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MEUR').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_GenerationOandMCost_' + + CaseName + + '.csv', + sep=',') if len(mTEPES.es): - OutputToFile = pd.Series(data=[mTEPES.pScenProb[sc] * mTEPES.pDuration[n] * mTEPES.pLoadLevelWeight[n]() * mTEPES.pLinearVarCost[es] * OptModel.vESSTotalCharge[sc,p,n,es]() for sc,p,n,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.es)) - OutputToFile.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MEUR').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_ChargeOperationCost_'+CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[mTEPES.pScenProb[sc] * mTEPES.pDuration[n] * mTEPES.pLoadLevelWeight[n]() * mTEPES.pCO2EmissionCost[nr] * OptModel.vTotalOutput[sc,p,n,nr]() for sc,p,n,nr in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nr], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nr)) - OutputToFile.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MEUR').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_GenerationEmissionCost_'+CaseName+'.csv', sep=',') - - OutputToFile = pd.Series(data=[mTEPES.pScenProb[sc] * mTEPES.pDuration[n] * mTEPES.pLoadLevelWeight[n]() * mTEPES.pENSCost() * OptModel.vENS [sc,p,n,nd]() for sc,p,n,nd in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nd], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nd)) - OutputToFile.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_3', values='MEUR').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_ReliabilityCost_'+CaseName+'.csv', sep=',') + OutputToFile = pd.Series(data=[mTEPES.pScenProb[sc] * + mTEPES.pDuration[n] * + mTEPES.pLoadLevelWeight[n]() * + mTEPES.pLinearVarCost[es] * + OptModel.vESSTotalCharge[sc, p, n, es]() for sc, p, n, es in mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.es], index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.es)) + OutputToFile.to_frame( + name='MEUR').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MEUR').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_ChargeOperationCost_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[mTEPES.pScenProb[sc] * + mTEPES.pDuration[n] * + mTEPES.pLoadLevelWeight[n]() * + mTEPES.pCO2EmissionCost[nr] * + OptModel.vTotalOutput[sc, p, n, nr]() for sc, p, n, nr in mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.nr], index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.nr)) + OutputToFile.to_frame( + name='MEUR').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MEUR').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_GenerationEmissionCost_' + + CaseName + + '.csv', + sep=',') + + OutputToFile = pd.Series(data=[mTEPES.pScenProb[sc] * + mTEPES.pDuration[n] * + mTEPES.pLoadLevelWeight[n]() * + mTEPES.pENSCost() * + OptModel.vENS[sc, p, n, nd]() for sc, p, n, nd in mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.nd], index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.nd)) + OutputToFile.to_frame( + name='MEUR').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_3', + values='MEUR').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_ReliabilityCost_' + + CaseName + + '.csv', + sep=',') AppendData = [] for st in mTEPES.st: mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration and (st,nn) in mTEPES.s2n) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration and ( + st, + nn) in mTEPES.s2n) if len(mTEPES.n): - OutputToFile = pd.Series(data=[OptModel.dual[getattr(OptModel, 'eBalance_'+st)[sc,p,n,nd]]/mTEPES.pScenProb[sc] * OptModel.vTotalOutput[sc,p,n,g]() for sc,p,n,nd,g in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.n2g], index=pd.MultiIndex.from_tuples(mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.n2g)) + OutputToFile = pd.Series(data=[OptModel.dual[getattr(OptModel, 'eBalance_' + + st)[sc, p, n, nd]] / + mTEPES.pScenProb[sc] * + OptModel.vTotalOutput[sc, p, n, g]() for sc, p, n, nd, g in mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.n2g], index=pd.MultiIndex.from_tuples(mTEPES.sc * + mTEPES.p * + mTEPES.n * + mTEPES.n2g)) AppendData.append(OutputToFile) mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration) AppendData = pd.concat(AppendData) - AppendData.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_4', values='MEUR').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_GenerationEnergyRevenue_'+CaseName+'.csv', sep=',') + AppendData.to_frame( + name='MEUR').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_4', + values='MEUR').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_GenerationEnergyRevenue_' + + CaseName + + '.csv', + sep=',') if len(mTEPES.es): AppendData = [] for st in mTEPES.st: mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration and (st,nn) in mTEPES.s2n) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration and ( + st, + nn) in mTEPES.s2n) if len(mTEPES.n): - OutputToFile = pd.Series(data=[OptModel.dual[getattr(OptModel, 'eBalance_'+st)[sc,p,n,nd]]/mTEPES.pScenProb[sc] * OptModel.vESSTotalCharge[sc,p,n,es]() for sc,p,n,nd,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.n2g if es in mTEPES.es], index=pd.MultiIndex.from_tuples([(sc,p,n,nd,es) for sc,p,n,nd,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.n2g if es in mTEPES.es])) + OutputToFile = pd.Series(data=[OptModel.dual[getattr(OptModel, + 'eBalance_' + st)[sc, + p, + n, + nd]] / mTEPES.pScenProb[sc] * OptModel.vESSTotalCharge[sc, + p, + n, + es]() for sc, + p, + n, + nd, + es in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.n2g if es in mTEPES.es], + index=pd.MultiIndex.from_tuples([(sc, + p, + n, + nd, + es) for sc, + p, + n, + nd, + es in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.n2g if es in mTEPES.es])) AppendData.append(OutputToFile) mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration) AppendData = pd.concat(AppendData) - AppendData.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_4', values='MEUR').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_ChargeEnergyRevenue_'+CaseName+'.csv', sep=',') - - if sum(mTEPES.pOperReserveUp[sc,p,n,ar] for sc,p,n,ar in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.ar): - if len([(sc,p,n,ar,nr) for sc,p,n,ar,nr in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.a2g if mTEPES.pOperReserveUp[sc,p,n,ar] and nr in mTEPES.nr]): + AppendData.to_frame( + name='MEUR').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_4', + values='MEUR').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_ChargeEnergyRevenue_' + + CaseName + + '.csv', + sep=',') + + if sum(mTEPES.pOperReserveUp[sc, p, n, ar] for sc, p, n, + ar in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.ar): + if len([(sc, p, n, ar, nr) for sc, p, n, ar, nr in mTEPES.sc * mTEPES.p * \ + mTEPES.n * mTEPES.a2g if mTEPES.pOperReserveUp[sc, p, n, ar] and nr in mTEPES.nr]): AppendData = [] for st in mTEPES.st: mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration and (st,nn) in mTEPES.s2n) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration and ( + st, + nn) in mTEPES.s2n) if len(mTEPES.n): - OutputToFile = pd.Series(data=[OptModel.dual[getattr(OptModel, 'eOperReserveUp_'+st)[sc,p,n,ar]]*1e3/mTEPES.pScenProb[sc]*OptModel.vReserveUp [sc,p,n,nr]() for sc,p,n,ar,nr in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.a2g if mTEPES.pOperReserveUp[sc,p,n,ar] and nr in mTEPES.nr], index=pd.MultiIndex.from_tuples([(sc,p,n,ar,nr) for sc,p,n,ar,nr in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.a2g if mTEPES.pOperReserveUp[sc,p,n,ar] and nr in mTEPES.nr])) + OutputToFile = pd.Series(data=[OptModel.dual[getattr(OptModel, + 'eOperReserveUp_' + st)[sc, + p, + n, + ar]] * 1e3 / mTEPES.pScenProb[sc] * OptModel.vReserveUp[sc, + p, + n, + nr]() for sc, + p, + n, + ar, + nr in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.a2g if mTEPES.pOperReserveUp[sc, + p, + n, + ar] and nr in mTEPES.nr], + index=pd.MultiIndex.from_tuples([(sc, + p, + n, + ar, + nr) for sc, + p, + n, + ar, + nr in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.a2g if mTEPES.pOperReserveUp[sc, + p, + n, + ar] and nr in mTEPES.nr])) AppendData.append(OutputToFile) mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration) AppendData = pd.concat(AppendData) - AppendData.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_4', values='MEUR').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_OperatingReserveUpRevenue_'+CaseName+'.csv', sep=',') - if len([(sc,p,n,ar,es) for sc,p,n,ar,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.a2g if mTEPES.pOperReserveUp[sc,p,n,ar] and es in mTEPES.es]): + AppendData.to_frame( + name='MEUR').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_4', + values='MEUR').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_OperatingReserveUpRevenue_' + + CaseName + + '.csv', + sep=',') + if len([(sc, p, n, ar, es) for sc, p, n, ar, es in mTEPES.sc * mTEPES.p * \ + mTEPES.n * mTEPES.a2g if mTEPES.pOperReserveUp[sc, p, n, ar] and es in mTEPES.es]): AppendData = [] for st in mTEPES.st: mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration and (st,nn) in mTEPES.s2n) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration and ( + st, + nn) in mTEPES.s2n) if len(mTEPES.n): - OutputToFile = pd.Series(data=[OptModel.dual[getattr(OptModel, 'eOperReserveUp_'+st)[sc,p,n,ar]]*1e3/mTEPES.pScenProb[sc]*OptModel.vESSReserveUp[sc,p,n,es]() for sc,p,n,ar,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.a2g if mTEPES.pOperReserveUp[sc,p,n,ar] and es in mTEPES.es], index=pd.MultiIndex.from_tuples([(sc,p,n,ar,es) for sc,p,n,ar,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.a2g if mTEPES.pOperReserveUp[sc,p,n,ar] and es in mTEPES.es])) + OutputToFile = pd.Series(data=[OptModel.dual[getattr(OptModel, + 'eOperReserveUp_' + st)[sc, + p, + n, + ar]] * 1e3 / mTEPES.pScenProb[sc] * OptModel.vESSReserveUp[sc, + p, + n, + es]() for sc, + p, + n, + ar, + es in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.a2g if mTEPES.pOperReserveUp[sc, + p, + n, + ar] and es in mTEPES.es], + index=pd.MultiIndex.from_tuples([(sc, + p, + n, + ar, + es) for sc, + p, + n, + ar, + es in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.a2g if mTEPES.pOperReserveUp[sc, + p, + n, + ar] and es in mTEPES.es])) AppendData.append(OutputToFile) mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration) AppendData = pd.concat(AppendData) - AppendData.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_4', values='MEUR').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_ESSOperatingReserveUpRevenue_'+CaseName+'.csv', sep=',') - - if sum(mTEPES.pOperReserveDw[sc,p,n,ar] for sc,p,n,ar in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.ar): - if len([(sc,p,n,ar,nr) for sc,p,n,ar,nr in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.a2g if mTEPES.pOperReserveUp[sc,p,n,ar] and nr in mTEPES.nr]): + AppendData.to_frame( + name='MEUR').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_4', + values='MEUR').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_ESSOperatingReserveUpRevenue_' + + CaseName + + '.csv', + sep=',') + + if sum(mTEPES.pOperReserveDw[sc, p, n, ar] for sc, p, n, + ar in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.ar): + if len([(sc, p, n, ar, nr) for sc, p, n, ar, nr in mTEPES.sc * mTEPES.p * \ + mTEPES.n * mTEPES.a2g if mTEPES.pOperReserveUp[sc, p, n, ar] and nr in mTEPES.nr]): AppendData = [] for st in mTEPES.st: mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration and (st,nn) in mTEPES.s2n) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration and ( + st, + nn) in mTEPES.s2n) if len(mTEPES.n): - OutputToFile = pd.Series(data=[OptModel.dual[getattr(OptModel, 'eOperReserveDw_'+st)[sc,p,n,ar]]*1e3/mTEPES.pScenProb[sc]*OptModel.vReserveDown [sc,p,n,nr]() for sc,p,n,ar,nr in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.a2g if mTEPES.pOperReserveDw[sc,p,n,ar] and nr in mTEPES.nr], index=pd.MultiIndex.from_tuples([(sc,p,n,ar,nr) for sc,p,n,ar,nr in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.a2g if mTEPES.pOperReserveDw[sc,p,n,ar] and nr in mTEPES.nr])) + OutputToFile = pd.Series(data=[OptModel.dual[getattr(OptModel, + 'eOperReserveDw_' + st)[sc, + p, + n, + ar]] * 1e3 / mTEPES.pScenProb[sc] * OptModel.vReserveDown[sc, + p, + n, + nr]() for sc, + p, + n, + ar, + nr in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.a2g if mTEPES.pOperReserveDw[sc, + p, + n, + ar] and nr in mTEPES.nr], + index=pd.MultiIndex.from_tuples([(sc, + p, + n, + ar, + nr) for sc, + p, + n, + ar, + nr in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.a2g if mTEPES.pOperReserveDw[sc, + p, + n, + ar] and nr in mTEPES.nr])) AppendData.append(OutputToFile) mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration) AppendData = pd.concat(AppendData) - AppendData.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_4', values='MEUR').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_OperatingReserveDwRevenue_'+CaseName+'.csv', sep=',') - if len([(sc,p,n,ar,es) for sc,p,n,ar,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.a2g if mTEPES.pOperReserveUp[sc,p,n,ar] and es in mTEPES.es]): + AppendData.to_frame( + name='MEUR').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_4', + values='MEUR').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_OperatingReserveDwRevenue_' + + CaseName + + '.csv', + sep=',') + if len([(sc, p, n, ar, es) for sc, p, n, ar, es in mTEPES.sc * mTEPES.p * \ + mTEPES.n * mTEPES.a2g if mTEPES.pOperReserveUp[sc, p, n, ar] and es in mTEPES.es]): AppendData = [] for st in mTEPES.st: mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration and (st,nn) in mTEPES.s2n) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration and ( + st, + nn) in mTEPES.s2n) if len(mTEPES.n): - OutputToFile = pd.Series(data=[OptModel.dual[getattr(OptModel, 'eOperReserveDw_'+st)[sc,p,n,ar]]*1e3/mTEPES.pScenProb[sc]*OptModel.vESSReserveDown[sc,p,n,es]() for sc,p,n,ar,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.a2g if mTEPES.pOperReserveDw[sc,p,n,ar] and es in mTEPES.es], index=pd.MultiIndex.from_tuples([(sc,p,n,ar,es) for sc,p,n,ar,es in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.a2g if mTEPES.pOperReserveDw[sc,p,n,ar] and es in mTEPES.es])) + OutputToFile = pd.Series(data=[OptModel.dual[getattr(OptModel, + 'eOperReserveDw_' + st)[sc, + p, + n, + ar]] * 1e3 / mTEPES.pScenProb[sc] * OptModel.vESSReserveDown[sc, + p, + n, + es]() for sc, + p, + n, + ar, + es in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.a2g if mTEPES.pOperReserveDw[sc, + p, + n, + ar] and es in mTEPES.es], + index=pd.MultiIndex.from_tuples([(sc, + p, + n, + ar, + es) for sc, + p, + n, + ar, + es in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.a2g if mTEPES.pOperReserveDw[sc, + p, + n, + ar] and es in mTEPES.es])) AppendData.append(OutputToFile) mTEPES.del_component(mTEPES.n) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn: nn in mTEPES.pDuration) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration) AppendData = pd.concat(AppendData) - AppendData.to_frame(name='MEUR').reset_index().pivot_table(index=['level_0','level_1','level_2'], columns='level_4', values='MEUR').rename_axis(['Scenario','Period','LoadLevel'], axis=0).rename_axis([None], axis=1).to_csv(_path+'/oT_Result_ESSOperatingReserveDwRevenue_'+CaseName+'.csv', sep=',') + AppendData.to_frame( + name='MEUR').reset_index().pivot_table( + index=[ + 'level_0', + 'level_1', + 'level_2'], + columns='level_4', + values='MEUR').rename_axis( + [ + 'Scenario', + 'Period', + 'LoadLevel'], + axis=0).rename_axis( + [None], + axis=1).to_csv( + _path + + '/oT_Result_ESSOperatingReserveDwRevenue_' + + CaseName + + '.csv', + sep=',') WritingResultsTime = time.time() - StartTime - StartTime = time.time() - print('Writing economic results ... ', round(WritingResultsTime), 's') + StartTime = time.time() + print('Writing economic results ... ', + round(WritingResultsTime), 's') def NetworkMapResults(DirName, CaseName, OptModel, mTEPES): - #%% plotting the network in a map + # %% plotting the network in a map _path = os.path.join(DirName, CaseName) StartTime = time.time() - import cartopy.crs as ccrs + import cartopy.crs as ccrs import cartopy.io.img_tiles as cimgt - import cartopy.feature as cfeature + import cartopy.feature as cfeature from matplotlib.transforms import offset_copy # Create a Stamen terrain background instance. @@ -608,11 +2788,14 @@ def NetworkMapResults(DirName, CaseName, OptModel, mTEPES): ax = fig.add_subplot(1, 1, 1, projection=stamen_terrain.crs) # Limit the extent of the map to a small longitude/latitude range. - ax.set_extent((min(mTEPES.pNodeLon.values()) - 2, max(mTEPES.pNodeLon.values()) + 2, - min(mTEPES.pNodeLat.values()) - 2, max(mTEPES.pNodeLat.values()) + 2), crs=ccrs.Geodetic()) - - ax.add_feature(cfeature.BORDERS, linewidth=1 ) - ax.add_feature(cfeature.STATES, linewidth=0.1) + ax.set_extent((min(mTEPES.pNodeLon.values()) - + 2, max(mTEPES.pNodeLon.values()) + + 2, min(mTEPES.pNodeLat.values()) - + 2, max(mTEPES.pNodeLat.values()) + + 2), crs=ccrs.Geodetic()) + + ax.add_feature(cfeature.BORDERS, linewidth=1) + ax.add_feature(cfeature.STATES, linewidth=0.1) # Add the Stamen data at zoom level 8. ax.add_image(stamen_terrain, 8) @@ -627,43 +2810,210 @@ def NetworkMapResults(DirName, CaseName, OptModel, mTEPES): for nd in mTEPES.nd: # plt.annotate(nd, [mTEPES.pNodeLon[nd], mTEPES.pNodeLat[nd]]) # Add text 25 pixels to the left of each node. - ax.text(mTEPES.pNodeLon[nd], mTEPES.pNodeLat[nd], nd, fontsize=8, verticalalignment='center', horizontalalignment='right', transform=text_transform, bbox=dict(facecolor='sandybrown', alpha=0.5, boxstyle='round')) - - #%% colors of the lines according to the ENTSO-E color code + ax.text( + mTEPES.pNodeLon[nd], + mTEPES.pNodeLat[nd], + nd, + fontsize=8, + verticalalignment='center', + horizontalalignment='right', + transform=text_transform, + bbox=dict( + facecolor='sandybrown', + alpha=0.5, + boxstyle='round')) + + # %% colors of the lines according to the ENTSO-E color code # existing lines - for ni,nf,cc in mTEPES.le: - if (ni,nf,cc) in mTEPES.lea: - if mTEPES.pLineVoltage[ni,nf,cc] > 700 and mTEPES.pLineVoltage[ni,nf,cc] <= 900: - ax.plot([mTEPES.pNodeLon[ni], mTEPES.pNodeLon[nf]], [mTEPES.pNodeLat[ni], mTEPES.pNodeLat[nf]], color='blue' , linewidth=2 , marker='o', linestyle='solid', transform=ccrs.PlateCarree()) - if mTEPES.pLineVoltage[ni,nf,cc] > 500 and mTEPES.pLineVoltage[ni,nf,cc] <= 700: - ax.plot([mTEPES.pNodeLon[ni], mTEPES.pNodeLon[nf]], [mTEPES.pNodeLat[ni], mTEPES.pNodeLat[nf]], color='#ff8000', linewidth=2 , marker='o', linestyle='solid', transform=ccrs.PlateCarree()) - if mTEPES.pLineVoltage[ni,nf,cc] > 350 and mTEPES.pLineVoltage[ni,nf,cc] <= 500: - ax.plot([mTEPES.pNodeLon[ni], mTEPES.pNodeLon[nf]], [mTEPES.pNodeLat[ni], mTEPES.pNodeLat[nf]], color='red' , linewidth=1 , marker='o', linestyle='solid', transform=ccrs.PlateCarree()) - if mTEPES.pLineVoltage[ni,nf,cc] > 290 and mTEPES.pLineVoltage[ni,nf,cc] <= 350: - ax.plot([mTEPES.pNodeLon[ni], mTEPES.pNodeLon[nf]], [mTEPES.pNodeLat[ni], mTEPES.pNodeLat[nf]], color='green' , linewidth=0.4, marker='o', linestyle='solid', transform=ccrs.PlateCarree()) - if mTEPES.pLineVoltage[ni,nf,cc] > 200 and mTEPES.pLineVoltage[ni,nf,cc] <= 290: - ax.plot([mTEPES.pNodeLon[ni], mTEPES.pNodeLon[nf]], [mTEPES.pNodeLat[ni], mTEPES.pNodeLat[nf]], color='green' , linewidth=0.4, marker='o', linestyle='solid', transform=ccrs.PlateCarree()) - if mTEPES.pLineVoltage[ni,nf,cc] <= 200: - ax.plot([mTEPES.pNodeLon[ni], mTEPES.pNodeLon[nf]], [mTEPES.pNodeLat[ni], mTEPES.pNodeLat[nf]], color='#ff6300', linewidth=0.4, marker='o', linestyle='solid', transform=ccrs.PlateCarree()) + for ni, nf, cc in mTEPES.le: + if (ni, nf, cc) in mTEPES.lea: + if mTEPES.pLineVoltage[ni, + nf, + cc] > 700 and mTEPES.pLineVoltage[ni, + nf, + cc] <= 900: + ax.plot([mTEPES.pNodeLon[ni], + mTEPES.pNodeLon[nf]], + [mTEPES.pNodeLat[ni], + mTEPES.pNodeLat[nf]], + color='blue', + linewidth=2, + marker='o', + linestyle='solid', + transform=ccrs.PlateCarree()) + if mTEPES.pLineVoltage[ni, + nf, + cc] > 500 and mTEPES.pLineVoltage[ni, + nf, + cc] <= 700: + ax.plot([mTEPES.pNodeLon[ni], + mTEPES.pNodeLon[nf]], + [mTEPES.pNodeLat[ni], + mTEPES.pNodeLat[nf]], + color='#ff8000', + linewidth=2, + marker='o', + linestyle='solid', + transform=ccrs.PlateCarree()) + if mTEPES.pLineVoltage[ni, + nf, + cc] > 350 and mTEPES.pLineVoltage[ni, + nf, + cc] <= 500: + ax.plot([mTEPES.pNodeLon[ni], + mTEPES.pNodeLon[nf]], + [mTEPES.pNodeLat[ni], + mTEPES.pNodeLat[nf]], + color='red', + linewidth=1, + marker='o', + linestyle='solid', + transform=ccrs.PlateCarree()) + if mTEPES.pLineVoltage[ni, + nf, + cc] > 290 and mTEPES.pLineVoltage[ni, + nf, + cc] <= 350: + ax.plot([mTEPES.pNodeLon[ni], + mTEPES.pNodeLon[nf]], + [mTEPES.pNodeLat[ni], + mTEPES.pNodeLat[nf]], + color='green', + linewidth=0.4, + marker='o', + linestyle='solid', + transform=ccrs.PlateCarree()) + if mTEPES.pLineVoltage[ni, + nf, + cc] > 200 and mTEPES.pLineVoltage[ni, + nf, + cc] <= 290: + ax.plot([mTEPES.pNodeLon[ni], + mTEPES.pNodeLon[nf]], + [mTEPES.pNodeLat[ni], + mTEPES.pNodeLat[nf]], + color='green', + linewidth=0.4, + marker='o', + linestyle='solid', + transform=ccrs.PlateCarree()) + if mTEPES.pLineVoltage[ni, nf, cc] <= 200: + ax.plot([mTEPES.pNodeLon[ni], + mTEPES.pNodeLon[nf]], + [mTEPES.pNodeLat[ni], + mTEPES.pNodeLat[nf]], + color='#ff6300', + linewidth=0.4, + marker='o', + linestyle='solid', + transform=ccrs.PlateCarree()) else: - ax.plot ([mTEPES.pNodeLon[ni], mTEPES.pNodeLon[nf]], [mTEPES.pNodeLat[ni], mTEPES.pNodeLat[nf]], color='magenta', linewidth=1 , marker='o', linestyle='solid', transform=ccrs.PlateCarree()) + ax.plot([mTEPES.pNodeLon[ni], + mTEPES.pNodeLon[nf]], + [mTEPES.pNodeLat[ni], + mTEPES.pNodeLat[nf]], + color='magenta', + linewidth=1, + marker='o', + linestyle='solid', + transform=ccrs.PlateCarree()) # candidate lines - for ni,nf,cc in mTEPES.lc: - if (ni,nf,cc) in mTEPES.lca and OptModel.vNetworkInvest[ni,nf,cc]() > 0: - if mTEPES.pLineVoltage[ni,nf,cc] > 700 and mTEPES.pLineVoltage[ni,nf,cc] <= 900: - ax.plot([mTEPES.pNodeLon[ni], mTEPES.pNodeLon[nf]], [mTEPES.pNodeLat[ni], mTEPES.pNodeLat[nf]], color='blue' , linewidth=2 , marker='o', linestyle='dashed', transform=ccrs.PlateCarree()) - if mTEPES.pLineVoltage[ni,nf,cc] > 500 and mTEPES.pLineVoltage[ni,nf,cc] <= 700: - ax.plot([mTEPES.pNodeLon[ni], mTEPES.pNodeLon[nf]], [mTEPES.pNodeLat[ni], mTEPES.pNodeLat[nf]], color='#ff8000', linewidth=2 , marker='o', linestyle='dashed', transform=ccrs.PlateCarree()) - if mTEPES.pLineVoltage[ni,nf,cc] > 350 and mTEPES.pLineVoltage[ni,nf,cc] <= 500: - ax.plot([mTEPES.pNodeLon[ni], mTEPES.pNodeLon[nf]], [mTEPES.pNodeLat[ni], mTEPES.pNodeLat[nf]], color='red' , linewidth=1 , marker='o', linestyle='dashed', transform=ccrs.PlateCarree()) - if mTEPES.pLineVoltage[ni,nf,cc] > 290 and mTEPES.pLineVoltage[ni,nf,cc] <= 350: - ax.plot([mTEPES.pNodeLon[ni], mTEPES.pNodeLon[nf]], [mTEPES.pNodeLat[ni], mTEPES.pNodeLat[nf]], color='green' , linewidth=0.4, marker='o', linestyle='dashed', transform=ccrs.PlateCarree()) - if mTEPES.pLineVoltage[ni,nf,cc] > 200 and mTEPES.pLineVoltage[ni,nf,cc] <= 290: - ax.plot([mTEPES.pNodeLon[ni], mTEPES.pNodeLon[nf]], [mTEPES.pNodeLat[ni], mTEPES.pNodeLat[nf]], color='green' , linewidth=0.4, marker='o', linestyle='dashed', transform=ccrs.PlateCarree()) - if mTEPES.pLineVoltage[ni,nf,cc] <= 200: - ax.plot([mTEPES.pNodeLon[ni], mTEPES.pNodeLon[nf]], [mTEPES.pNodeLat[ni], mTEPES.pNodeLat[nf]], color='#ff6300', linewidth=0.4, marker='o', linestyle='dashed', transform=ccrs.PlateCarree()) + for ni, nf, cc in mTEPES.lc: + if (ni, + nf, + cc) in mTEPES.lca and OptModel.vNetworkInvest[ni, + nf, + cc]() > 0: + if mTEPES.pLineVoltage[ni, + nf, + cc] > 700 and mTEPES.pLineVoltage[ni, + nf, + cc] <= 900: + ax.plot([mTEPES.pNodeLon[ni], + mTEPES.pNodeLon[nf]], + [mTEPES.pNodeLat[ni], + mTEPES.pNodeLat[nf]], + color='blue', + linewidth=2, + marker='o', + linestyle='dashed', + transform=ccrs.PlateCarree()) + if mTEPES.pLineVoltage[ni, + nf, + cc] > 500 and mTEPES.pLineVoltage[ni, + nf, + cc] <= 700: + ax.plot([mTEPES.pNodeLon[ni], + mTEPES.pNodeLon[nf]], + [mTEPES.pNodeLat[ni], + mTEPES.pNodeLat[nf]], + color='#ff8000', + linewidth=2, + marker='o', + linestyle='dashed', + transform=ccrs.PlateCarree()) + if mTEPES.pLineVoltage[ni, + nf, + cc] > 350 and mTEPES.pLineVoltage[ni, + nf, + cc] <= 500: + ax.plot([mTEPES.pNodeLon[ni], + mTEPES.pNodeLon[nf]], + [mTEPES.pNodeLat[ni], + mTEPES.pNodeLat[nf]], + color='red', + linewidth=1, + marker='o', + linestyle='dashed', + transform=ccrs.PlateCarree()) + if mTEPES.pLineVoltage[ni, + nf, + cc] > 290 and mTEPES.pLineVoltage[ni, + nf, + cc] <= 350: + ax.plot([mTEPES.pNodeLon[ni], + mTEPES.pNodeLon[nf]], + [mTEPES.pNodeLat[ni], + mTEPES.pNodeLat[nf]], + color='green', + linewidth=0.4, + marker='o', + linestyle='dashed', + transform=ccrs.PlateCarree()) + if mTEPES.pLineVoltage[ni, + nf, + cc] > 200 and mTEPES.pLineVoltage[ni, + nf, + cc] <= 290: + ax.plot([mTEPES.pNodeLon[ni], + mTEPES.pNodeLon[nf]], + [mTEPES.pNodeLat[ni], + mTEPES.pNodeLat[nf]], + color='green', + linewidth=0.4, + marker='o', + linestyle='dashed', + transform=ccrs.PlateCarree()) + if mTEPES.pLineVoltage[ni, nf, cc] <= 200: + ax.plot([mTEPES.pNodeLon[ni], + mTEPES.pNodeLon[nf]], + [mTEPES.pNodeLat[ni], + mTEPES.pNodeLat[nf]], + color='#ff6300', + linewidth=0.4, + marker='o', + linestyle='dashed', + transform=ccrs.PlateCarree()) else: - ax.plot ([mTEPES.pNodeLon[ni], mTEPES.pNodeLon[nf]], [mTEPES.pNodeLat[ni], mTEPES.pNodeLat[nf]], color='magenta', linewidth=1 , marker='o', linestyle='dashed', transform=ccrs.PlateCarree()) + ax.plot([mTEPES.pNodeLon[ni], + mTEPES.pNodeLon[nf]], + [mTEPES.pNodeLat[ni], + mTEPES.pNodeLat[nf]], + color='magenta', + linewidth=1, + marker='o', + linestyle='dashed', + transform=ccrs.PlateCarree()) # # line NTC # for ni,nf,cc in mTEPES.la: @@ -673,7 +3023,14 @@ def NetworkMapResults(DirName, CaseName, OptModel, mTEPES): # # Place a legend to the right of this smaller subplot. # plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0.) # plt.show() - plt.savefig(_path+'/oT_Plot_MapNetwork_'+CaseName+'.png', bbox_inches=None, dpi=1200) + plt.savefig( + _path + + '/oT_Plot_MapNetwork_' + + CaseName + + '.png', + bbox_inches=None, + dpi=1200) PlottingNetMapsTime = time.time() - StartTime - print('Plotting network maps ... ', round(PlottingNetMapsTime), 's') + print('Plotting network maps ... ', + round(PlottingNetMapsTime), 's') diff --git a/openTEPES/openTEPES_ProblemSolving.py b/openTEPES/openTEPES_ProblemSolving.py index b680cf0f..5b4263a3 100644 --- a/openTEPES/openTEPES_ProblemSolving.py +++ b/openTEPES/openTEPES_ProblemSolving.py @@ -5,78 +5,131 @@ import time import os import psutil -from pyomo.opt import SolverFactory -from pyomo.environ import Suffix, Set +from pyomo.opt import SolverFactory +from pyomo.environ import Suffix, Set + def ProblemSolving(DirName, CaseName, SolverName, OptModel, mTEPES): print('Problem solving ****') _path = os.path.join(DirName, CaseName) StartTime = time.time() - #%% activating all scenarios, periods, and load levels + # %% activating all scenarios, periods, and load levels mTEPES.del_component(mTEPES.sc) - mTEPES.del_component(mTEPES.p ) + mTEPES.del_component(mTEPES.p) mTEPES.del_component(mTEPES.st) - mTEPES.del_component(mTEPES.n ) - mTEPES.sc = Set(initialize=mTEPES.scc, ordered=True, doc='scenarios', filter=lambda mTEPES,scc: scc in mTEPES.scc and mTEPES.pScenProb [scc]) - mTEPES.p = Set(initialize=mTEPES.pp, ordered=True, doc='periods', filter=lambda mTEPES,pp : pp ) - mTEPES.st = Set(initialize=mTEPES.stt, ordered=True, doc='stages', filter=lambda mTEPES,stt: stt in mTEPES.stt and mTEPES.pStageWeight[stt] and sum(1 for (stt, nn) in mTEPES.s2n)) - mTEPES.n = Set(initialize=mTEPES.nn, ordered=True, doc='load levels', filter=lambda mTEPES,nn : nn in mTEPES.pDuration ) + mTEPES.del_component(mTEPES.n) + mTEPES.sc = Set( + initialize=mTEPES.scc, + ordered=True, + doc='scenarios', + filter=lambda mTEPES, + scc: scc in mTEPES.scc and mTEPES.pScenProb[scc]) + mTEPES.p = Set( + initialize=mTEPES.pp, + ordered=True, + doc='periods', + filter=lambda mTEPES, + pp: pp) + mTEPES.st = Set( + initialize=mTEPES.stt, + ordered=True, + doc='stages', + filter=lambda mTEPES, + stt: stt in mTEPES.stt and mTEPES.pStageWeight[stt] and sum( + 1 for ( + stt, + nn) in mTEPES.s2n)) + mTEPES.n = Set( + initialize=mTEPES.nn, + ordered=True, + doc='load levels', + filter=lambda mTEPES, + nn: nn in mTEPES.pDuration) - #%% solving the problem - Solver = SolverFactory(SolverName, solver_io='mps') # select solver + # %% solving the problem + # select solver + Solver = SolverFactory(SolverName, solver_io='mps') if SolverName == 'gurobi': - Solver.options['LogFile' ] = _path+'/openTEPES_'+CaseName+'.log' - # Solver.options['IISFile' ] = _path+'/openTEPES_'+CaseName+'.ilp' # should be uncommented to show results of IIS - Solver.options['Method' ] = 2 # barrier method - Solver.options['Presolve' ] = 2 - Solver.options['Crossover' ] = 0 - Solver.options['RINS' ] = 100 + Solver.options['LogFile'] = _path + '/openTEPES_' + CaseName + '.log' + # Solver.options['IISFile' ] = _path+'/openTEPES_'+CaseName+'.ilp' + # # should be uncommented to show results of IIS + # barrier method + Solver.options['Method'] = 2 + Solver.options['Presolve'] = 2 + Solver.options['Crossover'] = 0 + Solver.options['RINS'] = 100 # Solver.options['BarConvTol' ] = 1e-9 # Solver.options['BarQCPConvTol' ] = 0.025 - Solver.options['MIPGap' ] = 0.01 - Solver.options['Threads' ] = int((psutil.cpu_count(logical=True) + psutil.cpu_count(logical=False))/2) - Solver.options['TimeLimit' ] = 7200 + Solver.options['MIPGap'] = 0.01 + Solver.options['Threads'] = int( + (psutil.cpu_count( + logical=True) + + psutil.cpu_count( + logical=False)) / + 2) + Solver.options['TimeLimit'] = 7200 Solver.options['IterationLimit'] = 7200000 - if mTEPES.pIndBinGenInvest()*len(mTEPES.gc) + mTEPES.pIndBinNetInvest()*len(mTEPES.lc) + mTEPES.pIndBinGenOperat()*len(mTEPES.nr) + mTEPES.pIndBinLineCommit()*len(mTEPES.la) == 0: - Solver.options['relax_integrality'] = 1 + if mTEPES.pIndBinGenInvest() * len(mTEPES.gc) + mTEPES.pIndBinNetInvest() * len(mTEPES.lc) + \ + mTEPES.pIndBinGenOperat() * len(mTEPES.nr) + mTEPES.pIndBinLineCommit() * len(mTEPES.la) == 0: + Solver.options['relax_integrality'] = 1 if SolverName == 'gurobi': - Solver.options['Crossover' ] = -1 + Solver.options['Crossover'] = -1 OptModel.dual = Suffix(direction=Suffix.IMPORT) - OptModel.rc = Suffix(direction=Suffix.IMPORT) - SolverResults = Solver.solve(OptModel, tee=True, report_timing=True) # tee=True displays the log of the solver + OptModel.rc = Suffix(direction=Suffix.IMPORT) + # tee=True displays the log of the solver + SolverResults = Solver.solve(OptModel, tee=True, report_timing=True) assert str(SolverResults.solver.termination_condition) == 'optimal' - SolverResults.write() # summary of the solver results + # summary of the solver results + SolverResults.write() - #%% fix values of binary variables to get dual variables and solve it again + # %% fix values of binary variables to get dual variables and solve it again # investment decision values are rounded to the nearest integer - if mTEPES.pIndBinGenInvest()*len(mTEPES.gc) + mTEPES.pIndBinNetInvest()*len(mTEPES.lc) + mTEPES.pIndBinGenOperat()*len(mTEPES.nr) + mTEPES.pIndBinLineCommit()*len(mTEPES.la): - if mTEPES.pIndBinGenInvest()*len(mTEPES.gc): + if mTEPES.pIndBinGenInvest() * len(mTEPES.gc) + mTEPES.pIndBinNetInvest() * len(mTEPES.lc) + \ + mTEPES.pIndBinGenOperat() * len(mTEPES.nr) + mTEPES.pIndBinLineCommit() * len(mTEPES.la): + if mTEPES.pIndBinGenInvest() * len(mTEPES.gc): for gc in mTEPES.gc: - OptModel.vGenerationInvest[gc].fix(round(OptModel.vGenerationInvest[gc]())) - if mTEPES.pIndBinNetInvest()*len(mTEPES.lc): + OptModel.vGenerationInvest[gc].fix( + round(OptModel.vGenerationInvest[gc]())) + if mTEPES.pIndBinNetInvest() * len(mTEPES.lc): for lc in mTEPES.lc: - OptModel.vNetworkInvest [lc].fix(round(OptModel.vNetworkInvest[lc]())) - if mTEPES.pIndBinGenOperat()*len(mTEPES.nr): - for sc,p,n,nr in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.nr: - OptModel.vCommitment[sc,p,n,nr].fix(round(OptModel.vCommitment[sc,p,n,nr]())) - OptModel.vStartUp [sc,p,n,nr].fix(round(OptModel.vStartUp [sc,p,n,nr]())) - OptModel.vShutDown [sc,p,n,nr].fix(round(OptModel.vShutDown [sc,p,n,nr]())) - if mTEPES.pIndBinLineCommit()*len(mTEPES.la): - for sc,p,n,ni,nf,cc in mTEPES.sc*mTEPES.p*mTEPES.n*mTEPES.la: - if mTEPES.pLineSwitching[ni,nf,cc] == 1: - OptModel.vLineCommit [sc,p,n,ni,nf,cc].fix(round(OptModel.vLineCommit [sc,p,n,ni,nf,cc]())) - OptModel.vLineOnState [sc,p,n,ni,nf,cc].fix(round(OptModel.vLineOnState [sc,p,n,ni,nf,cc]())) - OptModel.vLineOffState[sc,p,n,ni,nf,cc].fix(round(OptModel.vLineOffState[sc,p,n,ni,nf,cc]())) - Solver.options['relax_integrality'] = 1 # introduced to show results of the dual variables + OptModel.vNetworkInvest[lc].fix( + round(OptModel.vNetworkInvest[lc]())) + if mTEPES.pIndBinGenOperat() * len(mTEPES.nr): + for sc, p, n, nr in mTEPES.sc * mTEPES.p * mTEPES.n * mTEPES.nr: + OptModel.vCommitment[sc, p, n, nr].fix( + round(OptModel.vCommitment[sc, p, n, nr]())) + OptModel.vStartUp[sc, p, n, nr].fix( + round(OptModel.vStartUp[sc, p, n, nr]())) + OptModel.vShutDown[sc, p, n, nr].fix( + round(OptModel.vShutDown[sc, p, n, nr]())) + if mTEPES.pIndBinLineCommit() * len(mTEPES.la): + for sc, p, n, ni, nf, cc in mTEPES.sc * \ + mTEPES.p * mTEPES.n * mTEPES.la: + if mTEPES.pLineSwitching[ni, nf, cc] == 1: + OptModel.vLineCommit[sc, p, n, ni, nf, cc].fix( + round(OptModel.vLineCommit[sc, p, n, ni, nf, cc]())) + OptModel.vLineOnState[sc, p, n, ni, nf, cc].fix( + round(OptModel.vLineOnState[sc, p, n, ni, nf, cc]())) + OptModel.vLineOffState[sc, p, n, ni, nf, cc].fix( + round(OptModel.vLineOffState[sc, p, n, ni, nf, cc]())) + # introduced to show results of the dual variables + Solver.options['relax_integrality'] = 1 if SolverName == 'gurobi': - Solver.options['Crossover' ] = -1 + Solver.options['Crossover'] = -1 OptModel.dual = Suffix(direction=Suffix.IMPORT) - OptModel.rc = Suffix(direction=Suffix.IMPORT) - SolverResults = Solver.solve(OptModel, tee=True, report_timing=True, warmstart=True) # tee=True displays the log of the solver - SolverResults.write() # summary of the solver results + OptModel.rc = Suffix(direction=Suffix.IMPORT) + SolverResults = Solver.solve( + OptModel, + tee=True, + report_timing=True, + warmstart=True) # tee=True displays the log of the solver + # summary of the solver results + SolverResults.write() SolvingTime = time.time() - StartTime print('Solution time ... ', round(SolvingTime), 's') - print('Total system cost [MEUR] ', OptModel.eTotalTCost.expr()) + print( + 'Total system cost [MEUR] ', + OptModel.eTotalTCost.expr()) From 478e0193dd73ef8ff73ebcf57a23b36c660e1144 Mon Sep 17 00:00:00 2001 From: timmy61109 <38396747+timmy61109@users.noreply.github.com> Date: Sun, 8 Aug 2021 17:51:01 +0800 Subject: [PATCH 2/4] Update doc to docs --- {doc => docs}/img/Escudo.png | Bin {doc => docs}/img/logoIIT.gif | Bin {doc => docs}/img/oT_Map_Network_MAF2030.png | Bin {doc => docs}/img/oT_Map_Network_sSEP.png | Bin {doc => docs}/img/oT_Plot_MapNetwork_9n.png | Bin .../img/oT_Plot_TechnologyEnergy_ES_MAF2030.png | Bin .../img/oT_Plot_TechnologyOutput_sc01_y2030_9n.png | Bin {doc => docs}/img/open-entrance_logo.png | Bin {doc => docs}/img/openTEPES.png | Bin {doc => docs}/rst/ContactUs.rst | 0 {doc => docs}/rst/Download.rst | 0 {doc => docs}/rst/InputData.rst | 0 {doc => docs}/rst/Introduction.rst | 0 {doc => docs}/rst/MathematicalFormulation.rst | 0 {doc => docs}/rst/OutputResults.rst | 0 {doc => docs}/rst/Papers.rst | 0 {doc => docs}/rst/Projects.rst | 0 {doc => docs}/rst/conf.py | 0 {doc => docs}/rst/index.rst | 0 {doc => docs}/rst/openTEPES.png | Bin 20 files changed, 0 insertions(+), 0 deletions(-) rename {doc => docs}/img/Escudo.png (100%) rename {doc => docs}/img/logoIIT.gif (100%) rename {doc => docs}/img/oT_Map_Network_MAF2030.png (100%) rename {doc => docs}/img/oT_Map_Network_sSEP.png (100%) rename {doc => docs}/img/oT_Plot_MapNetwork_9n.png (100%) rename {doc => docs}/img/oT_Plot_TechnologyEnergy_ES_MAF2030.png (100%) rename {doc => docs}/img/oT_Plot_TechnologyOutput_sc01_y2030_9n.png (100%) rename {doc => docs}/img/open-entrance_logo.png (100%) rename {doc => docs}/img/openTEPES.png (100%) rename {doc => docs}/rst/ContactUs.rst (100%) rename {doc => docs}/rst/Download.rst (100%) rename {doc => docs}/rst/InputData.rst (100%) rename {doc => docs}/rst/Introduction.rst (100%) rename {doc => docs}/rst/MathematicalFormulation.rst (100%) rename {doc => docs}/rst/OutputResults.rst (100%) rename {doc => docs}/rst/Papers.rst (100%) rename {doc => docs}/rst/Projects.rst (100%) rename {doc => docs}/rst/conf.py (100%) rename {doc => docs}/rst/index.rst (100%) rename {doc => docs}/rst/openTEPES.png (100%) diff --git a/doc/img/Escudo.png b/docs/img/Escudo.png similarity index 100% rename from doc/img/Escudo.png rename to docs/img/Escudo.png diff --git a/doc/img/logoIIT.gif b/docs/img/logoIIT.gif similarity index 100% rename from doc/img/logoIIT.gif rename to docs/img/logoIIT.gif diff --git a/doc/img/oT_Map_Network_MAF2030.png b/docs/img/oT_Map_Network_MAF2030.png similarity index 100% rename from doc/img/oT_Map_Network_MAF2030.png rename to docs/img/oT_Map_Network_MAF2030.png diff --git a/doc/img/oT_Map_Network_sSEP.png b/docs/img/oT_Map_Network_sSEP.png similarity index 100% rename from doc/img/oT_Map_Network_sSEP.png rename to docs/img/oT_Map_Network_sSEP.png diff --git a/doc/img/oT_Plot_MapNetwork_9n.png b/docs/img/oT_Plot_MapNetwork_9n.png similarity index 100% rename from doc/img/oT_Plot_MapNetwork_9n.png rename to docs/img/oT_Plot_MapNetwork_9n.png diff --git a/doc/img/oT_Plot_TechnologyEnergy_ES_MAF2030.png b/docs/img/oT_Plot_TechnologyEnergy_ES_MAF2030.png similarity index 100% rename from doc/img/oT_Plot_TechnologyEnergy_ES_MAF2030.png rename to docs/img/oT_Plot_TechnologyEnergy_ES_MAF2030.png diff --git a/doc/img/oT_Plot_TechnologyOutput_sc01_y2030_9n.png b/docs/img/oT_Plot_TechnologyOutput_sc01_y2030_9n.png similarity index 100% rename from doc/img/oT_Plot_TechnologyOutput_sc01_y2030_9n.png rename to docs/img/oT_Plot_TechnologyOutput_sc01_y2030_9n.png diff --git a/doc/img/open-entrance_logo.png b/docs/img/open-entrance_logo.png similarity index 100% rename from doc/img/open-entrance_logo.png rename to docs/img/open-entrance_logo.png diff --git a/doc/img/openTEPES.png b/docs/img/openTEPES.png similarity index 100% rename from doc/img/openTEPES.png rename to docs/img/openTEPES.png diff --git a/doc/rst/ContactUs.rst b/docs/rst/ContactUs.rst similarity index 100% rename from doc/rst/ContactUs.rst rename to docs/rst/ContactUs.rst diff --git a/doc/rst/Download.rst b/docs/rst/Download.rst similarity index 100% rename from doc/rst/Download.rst rename to docs/rst/Download.rst diff --git a/doc/rst/InputData.rst b/docs/rst/InputData.rst similarity index 100% rename from doc/rst/InputData.rst rename to docs/rst/InputData.rst diff --git a/doc/rst/Introduction.rst b/docs/rst/Introduction.rst similarity index 100% rename from doc/rst/Introduction.rst rename to docs/rst/Introduction.rst diff --git a/doc/rst/MathematicalFormulation.rst b/docs/rst/MathematicalFormulation.rst similarity index 100% rename from doc/rst/MathematicalFormulation.rst rename to docs/rst/MathematicalFormulation.rst diff --git a/doc/rst/OutputResults.rst b/docs/rst/OutputResults.rst similarity index 100% rename from doc/rst/OutputResults.rst rename to docs/rst/OutputResults.rst diff --git a/doc/rst/Papers.rst b/docs/rst/Papers.rst similarity index 100% rename from doc/rst/Papers.rst rename to docs/rst/Papers.rst diff --git a/doc/rst/Projects.rst b/docs/rst/Projects.rst similarity index 100% rename from doc/rst/Projects.rst rename to docs/rst/Projects.rst diff --git a/doc/rst/conf.py b/docs/rst/conf.py similarity index 100% rename from doc/rst/conf.py rename to docs/rst/conf.py diff --git a/doc/rst/index.rst b/docs/rst/index.rst similarity index 100% rename from doc/rst/index.rst rename to docs/rst/index.rst diff --git a/doc/rst/openTEPES.png b/docs/rst/openTEPES.png similarity index 100% rename from doc/rst/openTEPES.png rename to docs/rst/openTEPES.png From abec17b186e1335a9b98945a9b4083267b52dc95 Mon Sep 17 00:00:00 2001 From: timmy61109 <38396747+timmy61109@users.noreply.github.com> Date: Sun, 8 Aug 2021 18:48:26 +0800 Subject: [PATCH 3/4] Add setup.cfg --- setup.cfg | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 setup.cfg diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 00000000..5e088939 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,21 @@ +[flake8] +extend-ignore = +exclude = + .git, + __pycache__, + docs/conf.py, + old, + build, + dist, + build-pypy, + .tox, + .eggs, + venv + +[mypy] +ignore_missing_imports = True + +[pydocstyle] + +[pylint] +disable = R0205 From 04e7cb3cfd4cc64d6467889fcb6dfccfe4e3a404 Mon Sep 17 00:00:00 2001 From: timmy61109 <38396747+timmy61109@users.noreply.github.com> Date: Sun, 8 Aug 2021 18:49:37 +0800 Subject: [PATCH 4/4] Delete annotation --- tests/test_run.py | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/tests/test_run.py b/tests/test_run.py index c0a59c97..d503f518 100644 --- a/tests/test_run.py +++ b/tests/test_run.py @@ -1,27 +1,13 @@ -# import argparse import os -# from openTEPES.openTEPES import openTEPES_run -# import openTEPES.openTEPES as oT import openTEPES.openTEPES as oT -# import openTEPES + CWD = os.getcwd() TEST_PATH = CWD + '/openTEPES' os.chdir(TEST_PATH) CASE = "9n" -# parser = argparse.ArgumentParser(description='Introducing main parameters.') -# parser.add_argument('--case', type=str, default=None) -# parser.add_argument('--dir', type=str, default=None) -# parser.add_argument('--solver', type=str, default=None) -# DIR = os.path.dirname(openTEPES.__file__) DIR = TEST_PATH SOLVER = "gurobi" oT.openTEPES_run(DIR, CASE, SOLVER) -# def test_openTEPES(): -# assert mTEPES == oT.openTEPES_run(DIR, CASE, SOLVER) - - -# if __name__ == "__main__": -# test_openTEPES(DIR, CASE, SOLVER) \ No newline at end of file