Source code for el1xr_opt.Modules.oM_InputData

# Developed by: Erik F. Alvarez

# Erik F. Alvarez
# Electric Power System Unit
# RISE
# erik.alvarez@ri.se

# Importing Libraries
import datetime
import os
import math
import time                                         # count clock time
import numpy             as np
import pandas            as pd
from   itertools         import product
from   pyomo.environ     import Set, Param, Var, Binary, UnitInterval, NonNegativeIntegers, NonNegativeReals, Reals, PositiveReals, RangeSet
from   pyomo.dataportal  import DataPortal
from  .utils.oM_Utils    import log_time, _update_parameters, _psdn_init, _psmd_init, _psmdn_init, _cartesian_4_psd, _cartesian_4_psm, _extend_psdn_filtered, _apply_mask_and_set_zero

[docs] def data_processing(DirName, CaseName, DateModel, model, indlog): # %% Read the input data print('-- Reading the input data') # Defining the path path_to_read = os.path.join(DirName,CaseName) start_time = time.time() if isinstance(DateModel, str): DateModel = datetime.datetime.strptime(DateModel, "%Y-%m-%d %H:%M:%S") set_definitions = { 'pp': ('Period', 'p' ), 'scc': ('Scenario', 'sc'), 'nn': ('LoadLevel', 'n' ), 'st': ('Storage', 'st'), 'gt': ('Technology', 'gt'), 'nd': ('Node', 'nd'), 'ni': ('Node', 'nd'), 'nf': ('Node', 'nd'), 'zn': ('Zone', 'zn'), 'cc': ('Circuit', 'cc'), 'c2': ('Circuit', 'cc'), 'ndzn': ('NodeToZone', 'ndzn'), 'egg': ('ElectricityGeneration', 'eg' ), 'hgg': ('HydrogenGeneration', 'hg' ), 'edd': ('ElectricityDemand', 'ed' ), 'hdd': ('HydrogenDemand', 'hd' ), 'err': ('ElectricityRetail', 'er' ), 'hrr': ('HydrogenRetail', 'hr' ),} dictSets = DataPortal() # Reading dictionaries from CSV and adding elements to the dictSets for set_name, (file_set_name, set_key) in set_definitions.items(): filename = f'oM_Dict_{file_set_name}_{CaseName}.csv' dictSets.load(filename=os.path.join(path_to_read, filename), set=set_key, format='set') # Defining sets in the model for set_name, (file_set_name, set_key) in set_definitions.items(): is_ordered = set_name not in {'egg', 'hgg', 'edd', 'hdd', 'err', 'hrr', 'st', 'gt', 'nd', 'ni', 'nf', 'cc', 'c2', 'ndzn'} setattr(model, set_name, Set(initialize=dictSets[set_key], ordered=is_ordered, doc=f'{file_set_name}')) #%% Reading the input data data_frames = {} files_list = [file.split("_")[2] for file in os.listdir(os.path.join(path_to_read)) if 'oM_Data' in file] for file_set_name in files_list: file_name = f'oM_Data_{file_set_name}_{CaseName}.csv' data_frames[f'df{file_set_name}'] = pd.read_csv(os.path.join(path_to_read, file_name)) unnamed_columns = [col for col in data_frames[f'df{file_set_name}'].columns if 'Unnamed' in col] data_frames[f'df{file_set_name}'].set_index(unnamed_columns, inplace=True) data_frames[f'df{file_set_name}'].index.names = [None] * len(unnamed_columns) # substitute NaN by 0 (only for numeric columns to avoid TypeError on string columns) for df in data_frames.values(): numeric_cols = df.select_dtypes(include='number').columns df[numeric_cols] = df[numeric_cols].fillna(0.0) # Define prefixes and suffixes model.reserves_prefixes = ['FCRD_Up', 'FCRD_Down','FCRN_Up','FCRN_Down'] model.FCRD_prefixes = [i for i in model.reserves_prefixes if "FCRD" in i] model.FCRN_prefixes = [i for i in model.reserves_prefixes if "FCRN" in i] model.gen_frames_suffixes = ['VarMinGeneration', 'VarMaxGeneration', 'VarMinConsumption', 'VarMaxConsumption', 'VarMinStorage', 'VarMaxStorage', 'VarMinInflows', 'VarMaxInflows', 'VarMinOutflows', 'VarMaxOutflows', 'VarMinEnergy', 'VarMaxEnergy', 'VarMinFuelCost', 'VarMaxFuelCost', 'VarMinEmissionCost', 'VarMaxEmissionCost', 'VarPositionConsumption', 'VarPositionGeneration', 'VarFixedAvailability',] model.demand_frames_suffixes = ['VarMaxDemand', 'VarMinDemand'] model.retail_frames_suffixes = ['VarEnergyCost', 'VarEnergyPrice'] # Apply the condition to each specified column for keys, df in data_frames.items(): if [1 for suffix in model.gen_frames_suffixes if suffix in keys]: data_frames[keys] = df.where(df > 0.0, 0.0) # Apply the condition to each specified column for column in model.gen_frames_suffixes: data_frames[f'df{column}'] = data_frames[f'df{column}'].where(data_frames[f'df{column}'] > 0.0) log_time('--- Reading the CSV files:', start_time, ind_log=indlog) start_time = time.time() # Constants factor1 = 1e-0 # Conversion factor factor2 = 1e-3 # Conversion factor model.factor1 = factor1 model.factor2 = factor2 # Option Indicators option_ind = data_frames['dfOption'].columns.to_list() # Extract and cast option indicators parameters_dict = {f'pOpt{indicator}': data_frames['dfOption'][indicator].iloc[0].astype('int') for indicator in option_ind} # Parameter Indicators parameter_ind = data_frames['dfParameter'].columns.to_list() # Extract, process parameter variables and add to parameters_dict for indicator in parameter_ind: if ('Cost' in indicator or 'Target' in indicator or 'Ramp' in indicator) and 'CO2' not in indicator: parameters_dict[f'pPar{indicator}'] = data_frames['dfParameter'][indicator].iloc[0] * factor1 else: parameters_dict[f'pPar{indicator}'] = data_frames['dfParameter'][indicator].iloc[0] parameters_dict['pDuration' ] = data_frames['dfDuration']['Duration'] * parameters_dict['pParTimeStep'] #parameters_dict['pLevelToIDmarket'] = data_frames['dfDuration']['IDMarket'].astype('int') parameters_dict['pPeriodWeight' ] = data_frames['dfPeriod']['Weight'].astype('int') parameters_dict['pScenProb' ] = data_frames['dfScenario']['Probability'].astype('float') # Merging sets gg and hh model.ehd = model.edd | model.hdd # Extract and cast nodal parameters for suffix in model.demand_frames_suffixes: parameters_dict[f'p{suffix}'] = data_frames[f'df{suffix}'].reindex(columns=model.ehd, fill_value=0.0) * factor1 # Merging sets gg and hh model.ehg = model.egg | model.hgg # Extract and cast generation parameters for suffix in model.gen_frames_suffixes: # print(suffix) # parameters_dict[f'p{suffix}'] = data_frames[f'df{suffix}'][model.ehg] * factor1 parameters_dict[f'p{suffix}'] = data_frames[f'df{suffix}'].reindex(columns=model.ehg, fill_value=0.0) * factor1 # Merging sets gg and hh model.ehr = model.err | model.hrr # Extract and cast retail parameters for suffix in model.retail_frames_suffixes: parameters_dict[f'p{suffix}'] = data_frames[f'df{suffix}'].reindex(columns=model.ehr, fill_value=0.0) * factor1 # Extract and cast operating reserve parameters for RM and RT markets for ind in model.reserves_prefixes: parameters_dict[f'pOperatingReservePrice_{ind}' ] = data_frames['dfOperatingReservePrice' ][ind] * factor1 parameters_dict[f'pOperatingReserveRequire_{ind}' ] = data_frames['dfOperatingReserveRequire' ][ind] * factor1 parameters_dict[f'pOperatingReserveActivation_{ind}'] = data_frames['dfOperatingReserveActivation'][ind] # 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 capacity and inflows and outflows for ind in model.gen_frames_suffixes + model.demand_frames_suffixes + model.retail_frames_suffixes: parameters_dict[f'p{ind}'] = parameters_dict[f'p{ind}'].rolling(parameters_dict['pParTimeStep']).mean() parameters_dict[f'p{ind}'].fillna(0.0, inplace=True) for idx in model.reserves_prefixes: parameters_dict[f'pOperatingReservePrice_{idx}' ] = parameters_dict[f'pOperatingReservePrice_{idx}' ].rolling(parameters_dict['pParTimeStep']).mean() parameters_dict[f'pOperatingReservePrice_{idx}' ].fillna(0.0, inplace=True) parameters_dict[f'pOperatingReserveRequire_{idx}' ] = parameters_dict[f'pOperatingReserveRequire_{idx}' ].rolling(parameters_dict['pParTimeStep']).mean() parameters_dict[f'pOperatingReserveRequire_{idx}' ].fillna(0.0, inplace=True) parameters_dict[f'pOperatingReserveActivation_{idx}'] = parameters_dict[f'pOperatingReserveActivation_{idx}'].rolling(parameters_dict['pParTimeStep']).mean() parameters_dict[f'pOperatingReserveActivation_{idx}'].fillna(0.0, inplace=True) if parameters_dict['pParTimeStep'] > 1: # assign duration 0 to load levels not being considered, active load levels are at the end of every pTimeStep for i in range(parameters_dict['pParTimeStep']-2,-1,-1): parameters_dict['pDuration'].iloc[[range(i, len(model.nn), parameters_dict['pParTimeStep'])]] = 0 # generation indicators EleGeneration_ind = data_frames['dfElectricityGeneration'].columns.to_list() HydGeneration_ind = data_frames['dfHydrogenGeneration'].columns.to_list() idx_gen_factoring = ['MaximumPower', 'MinimumPower', 'StandByPower', 'MaximumCharge', 'MinimumCharge', 'OMVariableCost', 'ProductionFunction', 'MaxCompressorConsumption', 'RampUp', 'RampDown', 'CO2EmissionRate', 'MaxOutflowsProd', 'MinOutflowsProd', 'MaxInflowsCons', 'MinInflowsCons', 'OutflowsRampDown', 'OutflowsRampUp'] # demand indicators EleDemand_ind = data_frames['dfElectricityDemand'].columns.to_list() HydDemand_ind = data_frames['dfHydrogenDemand'].columns.to_list() idx_dem_factoring = ['MaximumPower'] # retail indicators EleRetail_ind = data_frames['dfElectricityRetail'].columns.to_list() HydRetail_ind = data_frames['dfHydrogenRetail'].columns.to_list() idx_retail_factoring = ['MaximumEnergyBuy', 'MinimumEnergyBuy', 'MaximumEnergySell', 'MinimumEnergySell'] # Update electricity-related parameters _update_parameters(data_frames, parameters_dict, factor1, EleGeneration_ind, idx_gen_factoring, 'dfElectricityGeneration', 'pEleGen') _update_parameters(data_frames, parameters_dict, factor1, EleDemand_ind, idx_dem_factoring, 'dfElectricityDemand', 'pEleDem') _update_parameters(data_frames, parameters_dict, factor1, EleRetail_ind, idx_retail_factoring, 'dfElectricityRetail', 'pEleRet') # Update hydrogen-related parameters _update_parameters(data_frames, parameters_dict, factor1, HydGeneration_ind, idx_gen_factoring, 'dfHydrogenGeneration', 'pHydGen') _update_parameters(data_frames, parameters_dict, factor1, HydDemand_ind, idx_dem_factoring, 'dfHydrogenDemand', 'pHydDem') _update_parameters(data_frames, parameters_dict, factor1, HydRetail_ind, idx_retail_factoring, 'dfHydrogenRetail', 'pHydRet') for sector in ['Ele', 'Hyd']: parameters_dict[f'p{sector[0:3]}GenLinearVarCost' ] = parameters_dict[f'p{sector[0:3]}GenLinearTerm' ] * model.factor1 * parameters_dict[f'p{sector[0:3]}GenFuelCost'] + parameters_dict[f'p{sector[0:3]}GenOMVariableCost'] * model.factor1 # linear term variable cost [MEUR/GWh] parameters_dict[f'p{sector[0:3]}GenConstantVarCost' ] = parameters_dict[f'p{sector[0:3]}GenConstantTerm' ] * model.factor2 * parameters_dict[f'p{sector[0:3]}GenFuelCost'] # constant term variable cost [MEUR/h] parameters_dict[f'p{sector[0:3]}GenCO2EmissionCost' ] = parameters_dict[f'p{sector[0:3]}GenCO2EmissionRate' ] * model.factor1 * parameters_dict[ 'pParCO2Cost'] # CO2 emission cost [MEUR/GWh] parameters_dict[f'p{sector[0:3]}GenStartUpCost' ] = parameters_dict[f'p{sector[0:3]}GenStartUpCost' ] * model.factor2 # generation startup cost [MEUR] parameters_dict[f'p{sector[0:3]}GenShutDownCost' ] = parameters_dict[f'p{sector[0:3]}GenShutDownCost' ] * model.factor2 # generation shutdown cost [MEUR] parameters_dict[f'p{sector[0:3]}GenInvestCost' ] = parameters_dict[f'p{sector[0:3]}GenFixedInvestmentCost' ] * parameters_dict[f'p{sector[0:3]}GenFixedChargeRate'] # generation fixed cost [MEUR] parameters_dict[f'p{sector[0:3]}GenRetireCost' ] = parameters_dict[f'p{sector[0:3]}GenFixedRetirementCost' ] * parameters_dict[f'p{sector[0:3]}GenFixedChargeRate'] # generation fixed retirement cost [MEUR] # H2 outflows ramp down rate [tonH2] parameters_dict['pNodeLat' ] = data_frames['dfNodeLocation']['Latitude' ] # node latitude [º] parameters_dict['pNodeLon' ] = data_frames['dfNodeLocation']['Longitude' ] # node longitude [º] # electricity network indicators electricity_network_ind = data_frames['dfElectricityNetwork'].columns.to_list() for idx in electricity_network_ind: parameters_dict[f'pEleNet{idx}'] = data_frames['dfElectricityNetwork'][idx] # hydrogen network indicators hydrogen_network_ind = data_frames['dfHydrogenNetwork'].columns.to_list() for idx in hydrogen_network_ind: parameters_dict[f'pHydNet{idx}'] = data_frames['dfHydrogenNetwork'][idx] for net in ['Electricity', 'Hydrogen']: parameters_dict[f'p{net[0:3]}NetTTC' ] = parameters_dict[f'p{net[0:3]}NetTTC' ] * factor1 * parameters_dict[f'p{net[0:3]}NetSecurityFactor' ] parameters_dict[f'p{net[0:3]}NetTTCBck' ] = parameters_dict[f'p{net[0:3]}NetTTCBck' ] * factor1 * parameters_dict[f'p{net[0:3]}NetSecurityFactor' ] parameters_dict[f'p{net[0:3]}NetFixedInvestmentCost'] = parameters_dict[f'p{net[0:3]}NetFixedInvestmentCost'] * parameters_dict[f'p{net[0:3]}NetFixedChargeRate'] if net == 'Electricity': parameters_dict[f'p{net[0:3]}NetReactance'] = parameters_dict[f'p{net[0:3]}NetReactance'].sort_index() parameters_dict[f'p{net[0:3]}NetSwOnTime' ] = parameters_dict[f'p{net[0:3]}NetSwOnTime' ].astype('int') parameters_dict[f'p{net[0:3]}NetSwOffTime'] = parameters_dict[f'p{net[0:3]}NetSwOffTime'].astype('int') for net in ['Electricity', 'Hydrogen']: # replace p{net[0:3]}NetTTCBck = 0.0 by p{net[0:3]}NetTTC parameters_dict[f'p{net[0:3]}NetTTCBck'] = parameters_dict[f'p{net[0:3]}NetTTCBck'].where(parameters_dict[f'p{net[0:3]}NetTTCBck'] > 0.0, other=parameters_dict[f'p{net[0:3]}NetTTC']) # replace p{net[0:3]}NetTTC = 0.0 by p{net[0:3]}NetTTCBck parameters_dict[f'p{net[0:3]}NetTTC' ] = parameters_dict[f'p{net[0:3]}NetTTC' ].where(parameters_dict[f'p{net[0:3]}NetTTC'] > 0.0, other=parameters_dict[f'p{net[0:3]}NetTTCBck']) # replace p{net[0:3]}NetInvestmentUp= 0.0 by 1.0 parameters_dict[f'p{net[0:3]}NetInvestmentUp'] = parameters_dict[f'p{net[0:3]}NetInvestmentUp'].where(parameters_dict[f'p{net[0:3]}NetInvestmentUp'] > 0.0, other=1.0) parameters_dict[f'p{net[0:3]}GenInvestmentUp'] = parameters_dict[f'p{net[0:3]}GenInvestmentUp'].where(parameters_dict[f'p{net[0:3]}GenInvestmentUp'] > 0.0, other=1.0) # minimum up- and downtime converted to an integer number of time steps parameters_dict['pEleNetSwOnTime' ] = round(parameters_dict['pEleNetSwOnTime' ] / parameters_dict['pParTimeStep']).astype('int') log_time('--- Transforming the dataframes:', start_time, ind_log=indlog) start_time = time.time() # replacing string values by numerical values idxDict = dict() idxDict[0 ] = 0 idxDict[0.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 for sector in ['Ele', 'Hyd']: parameters_dict[f'p{sector[0:3]}GenBinaryInvestment' ] = parameters_dict[f'p{sector[0:3]}GenBinaryInvestment' ].map(idxDict) parameters_dict[f'p{sector[0:3]}GenBinaryRetirement' ] = parameters_dict[f'p{sector[0:3]}GenBinaryRetirement' ].map(idxDict) parameters_dict[f'p{sector[0:3]}GenBinaryCommitment' ] = parameters_dict[f'p{sector[0:3]}GenBinaryCommitment' ].map(idxDict) parameters_dict[f'p{sector[0:3]}GenStorageInvestment' ] = parameters_dict[f'p{sector[0:3]}GenStorageInvestment' ].map(idxDict) parameters_dict[f'p{sector[0:3]}GenFixedAvailability' ] = parameters_dict[f'p{sector[0:3]}GenFixedAvailability' ].map(idxDict) parameters_dict[f'p{sector[0:3]}NetBinaryInvestment' ] = parameters_dict[f'p{sector[0:3]}NetBinaryInvestment' ].map(idxDict) parameters_dict['pEleNetSwitching' ] = parameters_dict['pEleNetSwitching' ].map(idxDict) parameters_dict['pHydNetBinaryInvestment' ] = parameters_dict['pHydNetBinaryInvestment' ].map(idxDict) parameters_dict['pEleGenV2G' ] = parameters_dict['pEleGenV2G' ].map(idxDict) parameters_dict['pEleGenNoDayAhead' ] = parameters_dict['pEleGenNoDayAhead' ].map(idxDict) parameters_dict['pEleGenNoFCRD' ] = parameters_dict['pEleGenNoFCRD' ].map(idxDict) parameters_dict['pEleGenNoFCRN' ] = parameters_dict['pEleGenNoFCRN' ].map(idxDict) parameters_dict['pEleGenMaxCommitment' ] = parameters_dict['pEleGenMaxCommitment' ].map(idxDict) parameters_dict['pHydGenStandByStatus' ] = parameters_dict['pHydGenStandByStatus' ].map(idxDict) parameters_dict['pEleGenRES' ] = parameters_dict['pEleGenRES' ].map(idxDict) parameters_dict['pEleGenESS' ] = parameters_dict['pEleGenESS' ].map(idxDict) parameters_dict['pEleGenEV' ] = parameters_dict['pEleGenEV' ].map(idxDict) parameters_dict['pEleDemFlexible' ] = parameters_dict['pEleDemFlexible' ].map(idxDict) parameters_dict['pHydDemFlexible' ] = parameters_dict['pHydDemFlexible' ].map(idxDict) parameters_dict['pEleRetBuy' ] = parameters_dict['pEleRetBuy' ].map(idxDict) parameters_dict['pEleRetSell' ] = parameters_dict['pEleRetSell' ].map(idxDict) parameters_dict['pHydRetBuy' ] = parameters_dict['pHydRetBuy' ].map(idxDict) parameters_dict['pHydRetSell' ] = parameters_dict['pHydRetSell' ].map(idxDict) # %% Getting the branches from the network data sEleBr = [(ni,nf) for (ni,nf,cc) in data_frames['dfElectricityNetwork'].index.to_list()] sHydBr = [(ni,nf) for (ni,nf,cc) in data_frames['dfHydrogenNetwork'].index.to_list()] # Dropping duplicate elements sEleBrList = [(ni,nf) for n, (ni,nf) in enumerate(sEleBr) if (ni,nf) not in sEleBr[:n]] sHydBrList = [(ni,nf) for n, (ni,nf) in enumerate(sHydBr) if (ni,nf) not in sHydBr[:n]] # %% defining subsets: active load levels (n,n2), thermal units (t), RES units (re), ESS units (es), candidate gen units (gc), candidate ESS units (ec), all the electric lines (la), # candidate electric lines (lc), electric lines with losses (ll), reference node (rf) model.p = Set(doc='periods ', initialize=[pp for pp in model.pp if parameters_dict['pPeriodWeight'] [pp] > 0.0 and sum(parameters_dict['pDuration'] [pp,sc,n] for sc,n in model.scc*model.nn) > 0]) model.sc = Set(doc='scenarios ', initialize=[scc for scc in model.scc ]) model.ps = Set(doc='periods/scenarios ', initialize=[(p,sc) for p,sc in model.p * model.sc if parameters_dict['pScenProb'] [p,sc] > 0.0 and sum(parameters_dict['pDuration'] [p ,sc,n] for n in model.nn) > 0]) model.n = Set(doc='load levels ', initialize=[nn for nn in model.nn if sum(parameters_dict['pDuration'] [p,sc,nn] for p,sc in model.ps) > 0]) model.n2 = Set(doc='load levels ', initialize=[nn for nn in model.nn if sum(parameters_dict['pDuration'] [p,sc,nn] for p,sc in model.ps) > 0]) model.eg = Set(doc='electricity generation units ', initialize=[egg for egg in model.egg if (parameters_dict['pEleGenMaximumPower'] [egg] > 0.0 or parameters_dict['pEleGenMaximumCharge'] [egg] > 0 ) and parameters_dict['pEleGenInitialPeriod'] [egg] <= parameters_dict['pParEconomicBaseYear'] and parameters_dict['pEleGenFinalPeriod'][egg] >= parameters_dict['pParEconomicBaseYear']]) model.ed = Set(doc='electricity demand units ', initialize=[edd for edd in model.edd if parameters_dict['pEleDemMaximumPower'] [edd] > 0.0 and parameters_dict['pEleDemInitialPeriod'] [edd] <= parameters_dict['pParEconomicBaseYear'] and parameters_dict['pEleDemFinalPeriod'][edd] >= parameters_dict['pParEconomicBaseYear']]) model.er = Set(doc='electricity retail units ', initialize=[err for err in model.err if (parameters_dict['pEleRetMaximumEnergyBuy'] [err] > 0.0 or parameters_dict['pEleRetMaximumEnergySell'] [err] > 0.0 or parameters_dict['pEleRetMinimumEnergyBuy'] [err] > 0.0 or parameters_dict['pEleRetMinimumEnergySell'][err] > 0.0) and parameters_dict['pEleRetInitialPeriod'] [err] <= parameters_dict['pParEconomicBaseYear'] and parameters_dict['pEleRetFinalPeriod'][err] >= parameters_dict['pParEconomicBaseYear']]) model.egt = Set(doc='electricity thermal units ', initialize=[egt for egt in model.eg if parameters_dict['pEleGenConstantVarCost'] [egt] > 0.0]) model.egr = Set(doc='electricity RES units ', initialize=[egr for egr in model.eg if parameters_dict['pEleGenRES'] [egr] == 1.0]) model.egs = Set(doc='electricity ESS units ', initialize=[egs for egs in model.eg if parameters_dict['pEleGenESS'] [egs] == 1.0 or parameters_dict['pEleGenEV'] [egs] == 1.0]) model.egv = Set(doc='electricity EV units ', initialize=[egv for egv in model.eg if parameters_dict['pEleGenEV' ] [egv] == 1.0]) model.egc = Set(doc='electricity candidate units ', initialize=[egc for egc in model.eg if parameters_dict['pEleGenInvestCost'] [egc] > 0.0]) model.egsc = Set(doc='electricity storage units ', initialize=[egsc for egsc in model.egs if parameters_dict['pEleGenInvestCost'] [egsc] > 0.0]) model.hg = Set(doc='hydrogen generation units ', initialize=[hgg for hgg in model.hgg if (parameters_dict['pHydGenMaximumPower'] [hgg] > 0.0 or parameters_dict['pHydGenMaximumCharge'] [hgg] > 0 ) and parameters_dict['pHydGenInitialPeriod'] [hgg] <= parameters_dict['pParEconomicBaseYear'] and parameters_dict['pHydGenFinalPeriod'][hgg] >= parameters_dict['pParEconomicBaseYear']]) model.hgt = Set(doc='hydrogen scheduled units ', initialize=[hgt for hgt in model.hg if parameters_dict['pHydGenConstantVarCost'] [hgt] > 0.0]) model.hd = Set(doc='hydrogen demand units ', initialize=[hdd for hdd in model.hdd if parameters_dict['pHydDemMaximumPower'] [hdd] == 0.0]) model.hr = Set(doc='hydrogen retail units ', initialize=[hrr for hrr in model.hrr if parameters_dict['pHydRetMaximumEnergyBuy'] [hrr] > 0.0 or parameters_dict['pHydRetMaximumEnergySell'] [hrr] > 0.0 or parameters_dict['pHydRetMinimumEnergyBuy'] [hrr] > 0.0 or parameters_dict['pHydRetMinimumEnergySell'][hrr] > 0.0]) model.hgs = Set(doc='hydrogen storage units ', initialize=[hgs for hgs in model.hg if parameters_dict['pHydGenMaximumStorage'] [hgs] > 0.0 and (parameters_dict['pVarMaxInflows'].sum() [hgs] > 0.0 or parameters_dict['pVarMaxOutflows'].sum() [hgs] > 0.0 or parameters_dict['pHydGenMaximumCharge'][hgs] > 0.0)]) model.hgc = Set(doc='hydrogen candidate units ', initialize=[hgc for hgc in model.hg if parameters_dict['pHydGenInvestCost'] [hgc] > 0.0]) model.hgsc = Set(doc='hydrogen storage units ', initialize=[hgsc for hgsc in model.hgs if parameters_dict['pHydGenInvestCost'] [hgsc] > 0.0]) model.e2h = Set(doc='ele2hyd units ', initialize=[hg for hg in model.hg if parameters_dict['pHydGenProductionFunction'][hg] > 0.0]) model.h2e = Set(doc='hyd2ele units ', initialize=[eg for eg in model.eg if parameters_dict['pEleGenProductionFunction'][eg] > 0.0]) model.ebr = Set(doc='all input branches ', initialize=[(ni,nf) for ni,nf in sEleBrList]) model.eln = Set(doc='all input lines ', initialize=data_frames['dfElectricityNetwork'].index.to_list()) model.ela = Set(doc='all real lines ', initialize=[el for el in model.eln if parameters_dict['pEleNetReactance'][el] != 0.0 and parameters_dict['pEleNetTTC'][el] > 0.0 and parameters_dict['pEleNetTTCBck'][el] > 0.0 and parameters_dict['pEleNetInitialPeriod'][el] <= parameters_dict['pParEconomicBaseYear'] and parameters_dict['pEleNetFinalPeriod'][el] >= parameters_dict['pParEconomicBaseYear']]) model.els = Set(doc='all real switch lines ', initialize=[el for el in model.ela if parameters_dict['pEleNetSwitching'][el]]) model.elc = Set(doc='candidate lines ', initialize=[el for el in model.ela if parameters_dict['pEleNetFixedInvestmentCost'][el] > 0.0]) model.endrf= Set(doc='electricity reference node ', initialize=[nd for nd in model.nd if nd in parameters_dict['pParEleReferenceNode']]) model.hndrf= Set(doc='hydrogen reference node ', initialize=[nd for nd in model.nd if nd in parameters_dict['pParHydReferenceNode']]) model.hbr = Set(doc='all input branches ', initialize=[(ni,nf) for ni,nf in sHydBrList]) model.hpn = Set(doc='all input H2 pipelines ', initialize=data_frames['dfHydrogenNetwork'].index.to_list()) model.hpa = Set(doc='all real H2 pipelines ', initialize=[hp for hp in model.hpn if parameters_dict['pHydNetTTC'][hp] > 0.0 and parameters_dict['pHydNetTTCBck'][hp] > 0.0 and parameters_dict['pHydNetInitialPeriod'][hp] <= parameters_dict['pParEconomicBaseYear'] and parameters_dict['pHydNetFinalPeriod'][hp] >= parameters_dict['pParEconomicBaseYear']]) model.hpc = Set(doc='candidate H2 pipelines ', initialize=[hp for hp in model.hpa if parameters_dict['pHydNetFixedInvestmentCost'][hp] > 0.0]) model.egnr = model.eg - model.egr # non-RES units, they can be committed and also contribute to the operating reserves model.ele = model.ela - model.elc # existing electric lines (le) model.hpe = model.hpa - model.hpc # existing hydrogen pipelines (pe) model.eh = model.egs | model.e2h # set for the electricity consumption model.he = model.hgs | model.h2e # set for the hydrogen consumption model.ehs = model.egs | model.hgs # set for the electricity and hydrogen ESS model.esc = model.egc | model.hgc # set for the candidate ESS and hydrogen units log_time('--- Defining the sets:', start_time, ind_log=indlog) start_time = time.time() # instrumental sets model.psc = [(p, sc ) for p, sc in model.p * model.sc ] model.pn = [(p, n ) for p, n in model.p * model.n ] model.pegs = [(p, egs ) for p, egs in model.p * model.egs ] model.pehs = [(p, ehs ) for p, ehs in model.p * model.ehs ] model.pnegg = [(p, n , g ) for p, n , g in model.pn * model.egg ] model.pneg = [(p, n , g ) for p, n , g in model.pn * model.eg ] model.pnegt = [(p, n , t ) for p, n , t in model.pn * model.egt ] model.pnnd = [(p, n , nd ) for p, n , nd in model.pn * model.nd ] model.pnegr = [(p, n , re ) for p, n , re in model.pn * model.egr ] model.pnegs = [(p, n , es ) for p, n , es in model.pn * model.egs ] model.pnegnr = [(p, n , nr ) for p, n , nr in model.pn * model.egnr] model.pngt = [(p, n , gt ) for p, n , gt in model.pn * model.gt ] model.pnhe = [(p, n , he ) for p, n , he in model.pn * model.he ] model.pneh = [(p, n , eh ) for p, n , eh in model.pn * model.eh ] model.pnesc = [(p, n , esc ) for p, n , esc in model.pn * model.esc ] model.pnhg = [(p, n , h ) for p, n , h in model.pn * model.hg ] model.pnhgs = [(p, n , hs ) for p, n , hs in model.pn * model.hgs ] model.pneln = [(p, n , ni, nf, cc) for p, n , ni, nf, cc in model.pn * model.eln ] model.pnela = [(p, n , ni, nf, cc) for p, n , ni, nf, cc in model.pn * model.ela ] model.pnele = [(p, n , ni, nf, cc) for p, n , ni, nf, cc in model.pn * model.ele ] model.pnels = [(p, n , ni, nf, cc) for p, n , ni, nf, cc in model.pn * model.els ] model.pnhpa = [(p, n , ni, nf, cc) for p, n , ni, nf, cc in model.pn * model.hpa ] model.pnhpc = [(p, n , ni, nf, cc) for p, n , ni, nf, cc in model.pn * model.hpc ] model.pnhpe = [(p, n , ni, nf, cc) for p, n , ni, nf, cc in model.pn * model.hpe ] model.pseg = [(p, sc, g ) for p, sc, g in model.psc * model.eg ] model.psegnr = [(p, sc, nr ) for p, sc, nr in model.psc * model.egnr] model.psegs = [(p, sc, egs ) for p, sc, egs in model.psc * model.egs ] model.pshgs = [(p, sc, hgs ) for p, sc, hgs in model.psc * model.hgs ] model.psehs = [(p, sc, ess ) for p, sc, ess in model.psc * model.ehs ] model.psn = [(p, sc, n ) for p, sc, n in model.psc * model.n ] model.psner = [(p, sc, n, er ) for p, sc, n, er in model.psn * model.er ] model.psned = [(p, sc, n, ed ) for p, sc, n, ed in model.psn * model.ed ] model.psneg = [(p, sc, n, g ) for p, sc, n, g in model.psn * model.eg ] model.psnehg = [(p, sc, n, gh ) for p, sc, n, gh in model.psn * model.ehg ] model.psnegt = [(p, sc, n, t ) for p, sc, n, t in model.psn * model.egt ] model.psnegc = [(p, sc, n, gc ) for p, sc, n, gc in model.psn * model.egc ] model.psnegr = [(p, sc, n, re ) for p, sc, n, re in model.psn * model.egr ] model.psnegnr = [(p, sc, n, nr ) for p, sc, n, nr in model.psn * model.egnr] model.psnegs = [(p, sc, n, es ) for p, sc, n, es in model.psn * model.egs ] model.psnegsc = [(p, sc, n, ec ) for p, sc, n, ec in model.psn * model.egsc] model.psnhg = [(p, sc, n, hz ) for p, sc, n, hz in model.psn * model.hg ] model.psnnd = [(p, sc, n, nd ) for p, sc, n, nd in model.psn * model.nd ] model.psngt = [(p, sc, n, gt ) for p, sc, n, gt in model.psn * model.gt ] model.psneh = [(p, sc, n, eh ) for p, sc, n, eh in model.psn * model.eh ] model.psnhe = [(p, sc, n, he ) for p, sc, n, he in model.psn * model.he ] model.psnehs = [(p, sc, n, es ) for p, sc, n, es in model.psn * model.ehs ] model.psnhr = [(p, sc, n, hr ) for p, sc, n, hr in model.psn * model.hr ] model.psnhd = [(p, sc, n, hd ) for p, sc, n, hd in model.psn * model.hd ] model.psnhg = [(p, sc, n, h ) for p, sc, n, h in model.psn * model.hg ] model.psnhgt = [(p, sc, n, t ) for p, sc, n, t in model.psn * model.hgt ] model.psnhgs = [(p, sc, n, hs ) for p, sc, n, hs in model.psn * model.hgs ] model.psnhgsc = [(p, sc, n, hgsc ) for p, sc, n, hgsc in model.psn * model.hgsc] model.psnesc = [(p, sc, n, es ) for p, sc, n, es in model.psn * model.esc ] model.psne2h = [(p, sc, n, h ) for p, sc, n, h in model.psn * model.e2h ] model.psnh2e = [(p, sc, n, g ) for p, sc, n, g in model.psn * model.h2e ] model.psneln = [(p, sc, n, ni, nf, cc) for p, sc, n, ni, nf, cc in model.psn * model.eln ] model.psnela = [(p, sc, n, ni, nf, cc) for p, sc, n, ni, nf, cc in model.psn * model.ela ] model.psnele = [(p, sc, n, ni, nf, cc) for p, sc, n, ni, nf, cc in model.psn * model.ele ] model.psnels = [(p, sc, n, ni, nf, cc) for p, sc, n, ni, nf, cc in model.psn * model.els ] model.psnhpn = [(p, sc, n, ni, nf, cc) for p, sc, n, ni, nf, cc in model.psn * model.hpn ] model.psnhpa = [(p, sc, n, ni, nf, cc) for p, sc, n, ni, nf, cc in model.psn * model.hpa ] model.psnhpe = [(p, sc, n, ni, nf, cc) for p, sc, n, ni, nf, cc in model.psn * model.hpe ] # define AC existing lines model.elea = Set(initialize=model.ele, ordered=False, doc='AC existing lines and non-switchable lines', filter=lambda model,value: value in model.ele and not parameters_dict['pEleNetType'][value] == 'DC') # define AC candidate lines model.elca = Set(initialize=model.ela, ordered=False, doc='AC candidate lines and switchable lines', filter=lambda model,value: value in model.elc and not parameters_dict['pEleNetType'][value] == 'DC') model.elaa = model.elea | model.elca # define DC existing lines model.eled = Set(initialize=model.ele, ordered=False, doc='DC existing lines and non-switchable lines', filter=lambda model,value: value in model.ele and parameters_dict['pEleNetType'][value] == 'DC') # define DC candidate lines model.elcd = Set(initialize=model.ela, ordered=False, doc='DC candidate lines and switchable lines', filter=lambda model,value: value in model.elc and parameters_dict['pEleNetType'][value] == 'DC') model.elad = model.eled | model.elcd # %% Getting the current year pCurrentYear = datetime.date.today().year if parameters_dict['pParEconomicBaseYear'] == 0: parameters_dict['pParEconomicBaseYear'] = pCurrentYear if parameters_dict['pParAnnualDiscountRate'] == 0.0: parameters_dict['pDiscountFactor'] = pd.Series(data=[ parameters_dict['pPeriodWeight'][p] for p in model.p], index=model.p) else: parameters_dict['pDiscountFactor'] = pd.Series(data=[((1.0+parameters_dict['pParAnnualDiscountRate'])**parameters_dict['pPeriodWeight'][p]-1.0) / (parameters_dict['pParAnnualDiscountRate']*(1.0+parameters_dict['pParAnnualDiscountRate'])**(parameters_dict['pPeriodWeight'][p]-1+p-parameters_dict['pParEconomicBaseYear'])) for p in model.p], index=model.p) # %% inverse index node to electricity/hydrogen unit model.n2eg = Set(initialize=sorted((parameters_dict['pEleGenNode'][eg], eg) for eg in model.eg ), ordered=False, doc='node to generator' ) model.z2eg = Set(initialize=sorted((zn,eg) for (nd,eg,zn) in model.n2eg * model.zn if (nd,zn) in model.ndzn ), ordered=False, doc='zone to generator' ) model.n2hg = Set(initialize=sorted((parameters_dict['pHydGenNode'][hg], hg) for hg in model.hg ), ordered=False, doc='node to generator' ) model.z2hg = Set(initialize=sorted((zn,hg) for (nd,hg,zn) in model.n2hg * model.zn if (nd,zn) in model.ndzn ), ordered=False, doc='zone to generator' ) # inverse index generator to technology model.t2eg = Set(initialize=sorted((parameters_dict['pEleGenTechnology'][eg],eg) for eg in model.eg if parameters_dict['pEleGenTechnology'][eg] in model.gt), ordered=False, doc='technology to generator') model.t2hg = Set(initialize=sorted((parameters_dict['pHydGenTechnology'][hg],hg) for hg in model.hg if parameters_dict['pHydGenTechnology'][hg] in model.gt), ordered=False, doc='technology to generator') # inverse index generator to retailer model.r2eg = Set(initialize=sorted((parameters_dict['pEleGenRetailer'][eg], eg) for eg in model.eg ), ordered=False, doc='retailer to generator' ) model.r2hg = Set(initialize=sorted((parameters_dict['pHydGenRetailer'][hg], hg) for hg in model.hg ), ordered=False, doc='retailer to generator' ) # inverse index node to electricity/hydrogen demand model.n2ed = Set(initialize=sorted((parameters_dict['pEleDemNode'][ed], ed) for ed in model.ed ), ordered=False, doc='node to demand' ) model.z2ed = Set(initialize=sorted((zn,ed) for (nd,ed,zn) in model.n2ed * model.zn if (nd,zn) in model.ndzn ), ordered=False, doc='zone to demand' ) model.n2hd = Set(initialize=sorted((parameters_dict['pHydDemNode'][hd], hd) for hd in model.hd ), ordered=False, doc='node to demand' ) model.z2hd = Set(initialize=sorted((zn,hd) for (nd,hd,zn) in model.n2hd * model.zn if (nd,zn) in model.ndzn ), ordered=False, doc='zone to demand' ) # inverse index demand to retailer model.r2ed = Set(initialize=sorted((parameters_dict['pEleDemRetailer'][ed], ed) for ed in model.ed ), ordered=False, doc='retailer to demand' ) model.r2hd = Set(initialize=sorted((parameters_dict['pHydDemRetailer'][hd], hd) for hd in model.hd ), ordered=False, doc='retailer to demand' ) # inverse index node to electricity/hydrogen retail model.n2er = Set(initialize=sorted((parameters_dict['pEleRetNode'][er], er) for er in model.er ), ordered=False, doc='node to retail' ) model.z2er = Set(initialize=sorted((zn,er) for (nd,er,zn) in model.n2er * model.zn if (nd,zn) in model.ndzn ), ordered=False, doc='zone to retail' ) model.n2hr = Set(initialize=sorted((parameters_dict['pHydRetNode'][hr], hr) for hr in model.hr ), ordered=False, doc='node to retail' ) model.z2hr = Set(initialize=sorted((zn,hr) for (nd,hr,zn) in model.n2hr * model.zn if (nd,zn) in model.ndzn ), ordered=False, doc='zone to retail' ) # ESS and RES technologies model.et = Set(initialize=model.gt, ordered=False, doc='Electricity ESS technologies', filter=lambda model, gt: gt in model.gt and sum(1 for egs in model.egs if (gt, egs) in model.t2eg)) model.ht = Set(initialize=model.gt, ordered=False, doc='Hydrogen ESS technologies', filter=lambda model, gt: gt in model.gt and sum(1 for hgs in model.hgs if (gt, hgs) in model.t2hg)) model.rt = Set(initialize=model.gt, ordered=False, doc='RES technologies' , filter=lambda model, gt: gt in model.gt and sum(1 for egr in model.egr if (gt, egr) in model.t2eg)) model.pset = [(p, sc, et) for p, sc, et in model.ps * model.et] model.psht = [(p, sc, ht) for p, sc, ht in model.ps * model.ht] model.psrt = [(p, sc, rt) for p, sc, rt in model.ps * model.rt] model.psnet = [(p, sc, n, et) for p, sc, n, et in model.psn * model.et] model.psnht = [(p, sc, n, ht) for p, sc, n, ht in model.psn * model.ht] model.psnrt = [(p, sc, n, rt) for p, sc, n, rt in model.psn * model.rt] log_time('--- Defining the instrumental sets:', start_time, ind_log=indlog) start_time = time.time() # --- TEMPORAL REFERENCE FOR THE MODEL --- # Assuming model.n is ordered like ['t0001', 't0002', ..., 'tNNNN'] n_list = list(model.n) # Reference position of DateModel in the year hour_of_day = DateModel.hour day_of_year = DateModel.timetuple().tm_yday hour_of_year = (day_of_year - 1) * 24 + hour_of_day start_dt = DateModel - pd.Timedelta(hours=(hour_of_year)) # Index only by n idx_n = pd.Index(n_list, name='n') pDate = pd.DataFrame(index=idx_n) # Vectorized DateTime for each n (no loops over p, sc) pDate['DateTime'] = start_dt + pd.to_timedelta(np.arange(len(idx_n)), unit='h') # Components pDate['Month'] = pDate['DateTime'].dt.month.astype(int) pDate['Day'] = pDate['DateTime'].dt.dayofyear.astype(int) pDate['Hour'] = pDate['DateTime'].dt.hour.astype(int) pDate['HourOfYear'] = (pDate['Day'] - 1) * 24 + pDate['Hour'] parameters_dict['pDate'] = pDate log_time('--- Creating the temporal reference dataframe:', start_time, ind_log=indlog) start_time = time.time() # --- Fundamental time sets --- # Unique values model.hoy = Set(initialize=sorted(pDate['HourOfYear'].unique())) model.doy = Set(initialize=sorted(pDate['Day'].unique())) model.moy = Set(initialize=sorted(pDate['Month'].unique())) # n -> month/day model.n2m = Set(dimen=2, initialize=[(n, m) for n, m in zip(pDate.index, pDate['Month'])]) model.n2d = Set(dimen=2, initialize=[(n, d) for n, d in zip(pDate.index, pDate['Day'])]) # day -> month (unique pairs) d2m_pairs = list(dict.fromkeys(zip(pDate['Day'], pDate['Month']))) model.d2m = Set(dimen=2, initialize=d2m_pairs) log_time('--- Defining the fundamental time sets:', start_time, ind_log=indlog) start_time = time.time() # --- Composite time sets --- model.psm = Set(dimen=3, initialize=lambda m: product(m.p, m.sc, m.moy)) model.psd = Set(dimen=3, initialize=lambda m: product(m.p, m.sc, m.doy)) # For quick lookup n2d_dict = dict(model.n2d.data()) # n -> d d2m_dict = {d: m for d, m in d2m_pairs} # d -> m model.n2d_dict = n2d_dict model.d2m_dict = d2m_dict model.psdn = Set(dimen=4, initialize=_psdn_init(model, n2d_dict)) model.psmd = Set(dimen=4, initialize=_psmd_init(model, d2m_dict)) model.psmdn = Set(dimen=5, initialize=_psmdn_init(model, n2d_dict, d2m_dict)) # psm × {er, hr, hd} model.psmer = Set(dimen=4, initialize=lambda m: _cartesian_4_psm(m, m.er)) model.psmhr = Set(dimen=4, initialize=lambda m: _cartesian_4_psm(m, m.hr)) model.psmhd = Set(dimen=4, initialize=lambda m: _cartesian_4_psm(m, m.hd)) # psd × {er, ed, hr, hd, egs, hgs} model.psder = Set(dimen=4, initialize=lambda m: _cartesian_4_psd(m, m.er)) model.psded = Set(dimen=4, initialize=lambda m: _cartesian_4_psd(m, m.ed)) model.psdhr = Set(dimen=4, initialize=lambda m: _cartesian_4_psd(m, m.hr)) model.psdhd = Set(dimen=4, initialize=lambda m: _cartesian_4_psd(m, m.hd)) model.psdegs = Set(dimen=4, initialize=lambda m: _cartesian_4_psd(m, m.egs)) model.psdhgs = Set(dimen=4, initialize=lambda m: _cartesian_4_psd(m, m.hgs)) # Now define each: model.psdner = Set(dimen=5, initialize=lambda m: _extend_psdn_filtered(m, 'psner', m.er)) model.psdned = Set(dimen=5, initialize=lambda m: _extend_psdn_filtered(m, 'psned', m.ed)) model.psdnhr = Set(dimen=5, initialize=lambda m: _extend_psdn_filtered(m, 'psnhr', m.hr)) model.psdnhd = Set(dimen=5, initialize=lambda m: _extend_psdn_filtered(m, 'psnhd', m.hd)) model.psdnegs = Set(dimen=5, initialize=lambda m: _extend_psdn_filtered(m, 'psnegs', m.egs)) model.psdnhgs = Set(dimen=5, initialize=lambda m: _extend_psdn_filtered(m, 'psnhgs', m.hgs)) log_time('--- Defining the temporal reference for the model:', start_time, ind_log=indlog) start_time = time.time() # minimum and maximum variable power, charge, and storage capacity dict_sector = {'Ele': model.eg, 'Hyd': model.hg} for sector in ['Ele', 'Hyd']: parameters_dict[f'p{sector}MinPower' ] = parameters_dict['pVarMinGeneration' ][dict_sector[sector]].replace(0.0, parameters_dict[f'p{sector}GenMinimumPower' ]) parameters_dict[f'p{sector}MaxPower' ] = parameters_dict['pVarMaxGeneration' ][dict_sector[sector]].replace(0.0, parameters_dict[f'p{sector}GenMaximumPower' ]) parameters_dict[f'p{sector}MinCharge' ] = parameters_dict['pVarMinConsumption' ][dict_sector[sector]].replace(0.0, parameters_dict[f'p{sector}GenMinimumCharge' ]) parameters_dict[f'p{sector}MaxCharge' ] = parameters_dict['pVarMaxConsumption' ][dict_sector[sector]].replace(0.0, parameters_dict[f'p{sector}GenMaximumCharge' ]) parameters_dict[f'p{sector}MinStorage' ] = parameters_dict['pVarMinStorage' ][dict_sector[sector]].replace(0.0, parameters_dict[f'p{sector}GenMinimumStorage' ]) parameters_dict[f'p{sector}MaxStorage' ] = parameters_dict['pVarMaxStorage' ][dict_sector[sector]].replace(0.0, parameters_dict[f'p{sector}GenMaximumStorage' ]) parameters_dict[f'p{sector}MinInflows' ] = parameters_dict['pVarMinInflows' ][dict_sector[sector]].replace(0.0, parameters_dict[f'p{sector}GenMinInflowsCons' ]) parameters_dict[f'p{sector}MaxInflows' ] = parameters_dict['pVarMaxInflows' ][dict_sector[sector]].replace(0.0, parameters_dict[f'p{sector}GenMaxInflowsCons' ]) parameters_dict[f'p{sector}MinOutflows'] = parameters_dict['pVarMinOutflows' ][dict_sector[sector]].replace(0.0, parameters_dict[f'p{sector}GenMinOutflowsProd']) parameters_dict[f'p{sector}MaxOutflows'] = parameters_dict['pVarMaxOutflows' ][dict_sector[sector]].replace(0.0, parameters_dict[f'p{sector}GenMaxOutflowsProd']) parameters_dict[f'p{sector}MinFuelCost'] = parameters_dict['pVarMinFuelCost' ][dict_sector[sector]].replace(0.0, parameters_dict[f'p{sector}GenLinearVarCost' ]) parameters_dict[f'p{sector}MaxFuelCost'] = parameters_dict['pVarMaxFuelCost' ][dict_sector[sector]].replace(0.0, parameters_dict[f'p{sector}GenLinearVarCost' ]) parameters_dict[f'p{sector}MinCO2Cost' ] = parameters_dict['pVarMinEmissionCost'][dict_sector[sector]].replace(0.0, parameters_dict[f'p{sector}GenCO2EmissionCost']) parameters_dict[f'p{sector}MaxCO2Cost' ] = parameters_dict['pVarMaxEmissionCost'][dict_sector[sector]].replace(0.0, parameters_dict[f'p{sector}GenCO2EmissionCost']) # parameters_dict['pMaxEnergyBuy' ] = parameters_dict['pVarEnergyCost' ].replace(0.0, parameters_dict['pEleRetMaximumEnergyBuy' ]) # parameters_dict['pMinEnergyBuy' ] = parameters_dict['pVarEnergyCost' ].replace(0.0, parameters_dict['pEleRetMinimumEnergyBuy' ]) # parameters_dict['pMaxEnergySell'] = parameters_dict['pVarEnergyPrice'].replace(0.0, parameters_dict['pEleRetMaximumEnergySell']) # parameters_dict['pMinEnergySell'] = parameters_dict['pVarEnergyPrice'].replace(0.0, parameters_dict['pEleRetMinimumEnergySell']) for idx in ['MinPower', 'MaxPower', 'MinCharge', 'MaxCharge', 'MinStorage', 'MaxStorage', 'MinInflows', 'MaxInflows', 'MinOutflows', 'MaxOutflows', 'MinFuelCost', 'MaxFuelCost', 'MinCO2Cost', 'MaxCO2Cost']: for sector in ['Ele', 'Hyd']: parameters_dict[f'p{sector}{idx}'] = parameters_dict[f'p{sector}{idx}'].where(parameters_dict[f'p{sector}{idx}'] > 0.0, other=0.0) # for idx in ['MaxEnergyBuy', 'MinEnergyBuy', 'MaxEnergySell', 'MinEnergySell']: # parameters_dict[f'p{idx}'] = parameters_dict[f'p{idx}'].where(parameters_dict[f'p{idx}'] > 0.0, other=0.0) # parameter that allows the initial inventory to change with load level for sector in ['Ele', 'Hyd']: parameters_dict[f'p{sector}InitialInventory'] = pd.DataFrame([parameters_dict[f'p{sector}GenInitialStorage'] * model.factor1] * len(parameters_dict[f'p{sector}MinStorage'].index), index=parameters_dict[f'p{sector}MinStorage'].index, columns=parameters_dict[f'p{sector}GenInitialStorage'].index) # minimum up- and downtime and maximum shift time converted to an integer number of time steps for idx in ['Up', 'Down']: parameters_dict[f'pEleGen{idx}Time'] = round(parameters_dict[f'pEleGen{idx}Time'] / parameters_dict['pParTimeStep']).astype('int') # %% definition of the time-steps leap to observe the stored energy at an ESS idxCycle = dict() idxCycle[0 ] = 8736 idxCycle[0.0 ] = 8736 idxCycle['Hourly' ] = 1 idxCycle['Daily' ] = 1 idxCycle['Weekly' ] = round(24 / parameters_dict['pParTimeStep']) idxCycle['Monthly'] = round(168 / parameters_dict['pParTimeStep']) idxCycle['Yearly' ] = round(168 / parameters_dict['pParTimeStep']) idxOutflows = dict() idxOutflows[0 ] = 8736 idxOutflows[0.0 ] = 8736 idxOutflows['Hourly' ] = 1 idxOutflows['Daily' ] = round(24 / parameters_dict['pParTimeStep']) idxOutflows['Weekly' ] = round(168 / parameters_dict['pParTimeStep']) idxOutflows['Monthly'] = round(672 / parameters_dict['pParTimeStep']) idxOutflows['Yearly' ] = round(8736 / parameters_dict['pParTimeStep']) for sector in ['Ele', 'Hyd']: parameters_dict[f'p{sector}CycleTimeStep' ] = parameters_dict[f'p{sector}GenStorageType' ].map(idxCycle ).fillna(8736).astype('int') parameters_dict[f'p{sector}OutflowsTimeStep'] = parameters_dict[f'p{sector}GenOutflowsType'].map(idxOutflows).where(parameters_dict['pVarMinOutflows'][dict_sector[sector]].sum() + parameters_dict['pVarMaxOutflows'][dict_sector[sector]].sum() > 0.0, other = 8736).fillna(8736).astype('int') parameters_dict[f'p{sector}CycleTimeStep' ] = pd.concat([parameters_dict[f'p{sector}CycleTimeStep'], parameters_dict[f'p{sector}OutflowsTimeStep']], axis=1).min(axis=1) # mapping the string pParDemandType using the idxCycle dictionary parameters_dict['pParDemandType'] = idxOutflows[parameters_dict['pParDemandType']] # drop levels with duration 0 parameters_dict['pDuration'] = parameters_dict['pDuration'].loc [model.psn ] for sector in ['Ele', 'Hyd']: parameters_dict[f'p{sector}MinPower' ] = parameters_dict[f'p{sector}MinPower' ].loc[model.psn] parameters_dict[f'p{sector}MaxPower' ] = parameters_dict[f'p{sector}MaxPower' ].loc[model.psn] parameters_dict[f'p{sector}MinCharge' ] = parameters_dict[f'p{sector}MinCharge' ].loc[model.psn] parameters_dict[f'p{sector}MaxCharge' ] = parameters_dict[f'p{sector}MaxCharge' ].loc[model.psn] parameters_dict[f'p{sector}MinStorage' ] = parameters_dict[f'p{sector}MinStorage' ].loc[model.psn] parameters_dict[f'p{sector}MaxStorage' ] = parameters_dict[f'p{sector}MaxStorage' ].loc[model.psn] parameters_dict[f'p{sector}MinInflows' ] = parameters_dict[f'p{sector}MinInflows' ].loc[model.psn] parameters_dict[f'p{sector}MaxInflows' ] = parameters_dict[f'p{sector}MaxInflows' ].loc[model.psn] parameters_dict[f'p{sector}MinOutflows' ] = parameters_dict[f'p{sector}MinOutflows' ].loc[model.psn] parameters_dict[f'p{sector}MaxOutflows' ] = parameters_dict[f'p{sector}MaxOutflows' ].loc[model.psn] parameters_dict[f'p{sector}InitialInventory'] = parameters_dict[f'p{sector}InitialInventory'].loc[model.psn] parameters_dict['pVarMaxDemand' ] = parameters_dict['pVarMaxDemand' ].loc[model.psn] parameters_dict['pVarMinDemand' ] = parameters_dict['pVarMinDemand' ].loc[model.psn] parameters_dict['pVarEnergyCost' ] = parameters_dict['pVarEnergyCost' ].loc[model.psn] parameters_dict['pVarEnergyPrice' ] = parameters_dict['pVarEnergyPrice' ].loc[model.psn] parameters_dict['pVarMinInflows' ] = parameters_dict['pVarMinInflows' ].loc[model.psn] parameters_dict['pVarMaxInflows' ] = parameters_dict['pVarMaxInflows' ].loc[model.psn] parameters_dict['pVarMinOutflows' ] = parameters_dict['pVarMinOutflows' ].loc[model.psn] parameters_dict['pVarMaxOutflows' ] = parameters_dict['pVarMaxOutflows' ].loc[model.psn] for idx in model.reserves_prefixes: parameters_dict[f'pOperatingReservePrice_{idx}' ] = parameters_dict[f'pOperatingReservePrice_{idx}' ].loc[model.psn] parameters_dict[f'pOperatingReserveRequire_{idx}' ] = parameters_dict[f'pOperatingReserveRequire_{idx}' ].loc[model.psn] parameters_dict[f'pOperatingReserveActivation_{idx}'] = parameters_dict[f'pOperatingReserveActivation_{idx}'].loc[model.psn] # values < 1e-5 times the maximum system demand are converted to 0 pEleEpsilon = (parameters_dict['pVarMaxDemand'][[ed for ed in model.ed]].sum(axis=1).max()) * 1e-5 pHydEpsilon = (parameters_dict['pVarMaxDemand'][[hd for hd in model.hd]].sum(axis=1).max()) * 1e-5 # these parameters are in GW or tH2 for sector in ['Ele', 'Hyd']: if sector == 'Ele': pEpsilon = pEleEpsilon else: pEpsilon = pHydEpsilon _apply_mask_and_set_zero(parameters_dict, f'p{sector}MinPower' , dict_sector[sector], pEpsilon) _apply_mask_and_set_zero(parameters_dict, f'p{sector}MaxPower' , dict_sector[sector], pEpsilon) _apply_mask_and_set_zero(parameters_dict, f'p{sector}MinCharge' , dict_sector[sector], pEpsilon) _apply_mask_and_set_zero(parameters_dict, f'p{sector}MaxCharge' , dict_sector[sector], pEpsilon) _apply_mask_and_set_zero(parameters_dict, f'p{sector}MinStorage' , dict_sector[sector], pEpsilon) _apply_mask_and_set_zero(parameters_dict, f'p{sector}MaxStorage' , dict_sector[sector], pEpsilon) _apply_mask_and_set_zero(parameters_dict, f'p{sector}MinInflows' , dict_sector[sector], pEpsilon) _apply_mask_and_set_zero(parameters_dict, f'p{sector}MaxInflows' , dict_sector[sector], pEpsilon) _apply_mask_and_set_zero(parameters_dict, f'p{sector}MinOutflows' , dict_sector[sector], pEpsilon) _apply_mask_and_set_zero(parameters_dict, f'p{sector}MaxOutflows' , dict_sector[sector], pEpsilon) _apply_mask_and_set_zero(parameters_dict, f'p{sector}MinFuelCost' , dict_sector[sector], pEpsilon) _apply_mask_and_set_zero(parameters_dict, f'p{sector}MaxFuelCost' , dict_sector[sector], pEpsilon) _apply_mask_and_set_zero(parameters_dict, f'p{sector}MinCO2Cost' , dict_sector[sector], pEpsilon) _apply_mask_and_set_zero(parameters_dict, f'p{sector}MaxCO2Cost' , dict_sector[sector], pEpsilon) _apply_mask_and_set_zero(parameters_dict, f'p{sector}InitialInventory', dict_sector[sector], pEpsilon) _apply_mask_and_set_zero(parameters_dict, 'pVarMaxDemand' , model.ed, pEleEpsilon) _apply_mask_and_set_zero(parameters_dict, 'pVarMinDemand' , model.ed, pEleEpsilon) _apply_mask_and_set_zero(parameters_dict, 'pVarMaxDemand' , model.hd, pHydEpsilon) _apply_mask_and_set_zero(parameters_dict, 'pVarMinDemand' , model.hd, pHydEpsilon) for idx in model.reserves_prefixes: parameters_dict[f'pOperatingReservePrice_{idx}' ][parameters_dict[f'pOperatingReservePrice_{idx}' ] < pEleEpsilon] = 0.0 parameters_dict[f'pOperatingReserveRequire_{idx}' ][parameters_dict[f'pOperatingReserveRequire_{idx}' ] < pEleEpsilon] = 0.0 parameters_dict[f'pOperatingReserveActivation_{idx}'][parameters_dict[f'pOperatingReserveActivation_{idx}'] < pEleEpsilon] = 0.0 for sector in ['Ele', 'Hyd']: if sector == 'Ele': pEpsilon = pEleEpsilon else: pEpsilon = pHydEpsilon parameters_dict[f'p{sector}NetTTC' ].update(pd.Series([0.0 for ni, nf, cc in parameters_dict[f'p{sector}NetTTC'].index if parameters_dict[f'p{sector}NetTTC' ][ni, nf, cc] < pEpsilon], index=[(ni, nf, cc) for ni, nf, cc in parameters_dict[f'p{sector}NetTTC'].index if parameters_dict[f'p{sector}NetTTC' ][ni, nf, cc] < pEpsilon], dtype='float64')) parameters_dict[f'p{sector}NetTTCBck'].update(pd.Series([0.0 for ni, nf, cc in parameters_dict[f'p{sector}NetTTC'].index if parameters_dict[f'p{sector}NetTTCBck'][ni, nf, cc] < pEpsilon], index=[(ni, nf, cc) for ni, nf, cc in parameters_dict[f'p{sector}NetTTC'].index if parameters_dict[f'p{sector}NetTTCBck'][ni, nf, cc] < pEpsilon], dtype='float64')) parameters_dict[f'p{sector}NetTTCMax'] = parameters_dict[f'p{sector}NetTTC'].where(parameters_dict[f'p{sector}NetTTC'] > parameters_dict[f'p{sector}NetTTCBck'], parameters_dict[f'p{sector}NetTTCBck']) parameters_dict[f'p{sector}MaxPower2ndBlock' ] = parameters_dict[f'p{sector}MaxPower' ] - parameters_dict[f'p{sector}MinPower'] parameters_dict[f'p{sector}MaxCharge2ndBlock'] = parameters_dict[f'p{sector}MaxCharge'] - parameters_dict[f'p{sector}MinCharge'] parameters_dict[f'p{sector}MaxCapacity' ] = parameters_dict[f'p{sector}MaxPower' ].where(parameters_dict[f'p{sector}MaxPower'] > parameters_dict[f'p{sector}MaxCharge'], parameters_dict[f'p{sector}MaxCharge']) parameters_dict[f'p{sector}MaxPower2ndBlock' ][parameters_dict[f'p{sector}MaxPower2ndBlock' ] < pEpsilon] = 0.0 parameters_dict[f'p{sector}MaxCharge2ndBlock'][parameters_dict[f'p{sector}MaxCharge2ndBlock'] < pEpsilon] = 0.0 # replace < 0.0 by 0.0 parameters_dict[f'p{sector}MaxPower2ndBlock' ] = parameters_dict[f'p{sector}MaxPower2ndBlock' ].where(parameters_dict[f'p{sector}MaxPower2ndBlock' ] > 0.0, 0.0) parameters_dict[f'p{sector}MaxCharge2ndBlock'] = parameters_dict[f'p{sector}MaxCharge2ndBlock'].where(parameters_dict[f'p{sector}MaxCharge2ndBlock'] > 0.0, 0.0) parameters_dict[f'p{sector}MaxInflows2ndBlock'] = parameters_dict[f'p{sector}MaxInflows' ] - parameters_dict[f'p{sector}MinInflows' ] parameters_dict[f'p{sector}MaxInflows2ndBlock'][parameters_dict[f'p{sector}MaxInflows2ndBlock' ] < pEleEpsilon] = 0.0 parameters_dict[f'p{sector}MaxOutflows2ndBlock'] = parameters_dict[f'p{sector}MaxOutflows'] - parameters_dict[f'p{sector}MinOutflows'] parameters_dict[f'p{sector}MaxOutflows2ndBlock'][parameters_dict[f'p{sector}MaxOutflows2ndBlock'] < pEleEpsilon] = 0.0 # replace < 0.0 by 0.0 parameters_dict[f'p{sector}MaxOutflows2ndBlock'] = parameters_dict[f'p{sector}MaxOutflows2ndBlock'].where(parameters_dict[f'p{sector}MaxOutflows2ndBlock'] > 0.0, 0.0) # drop generators not nr or ec for sector in ['Ele', 'Hyd']: if sector == 'Ele': set_sector = model.egt parameters_dict[f'p{sector}GenStartUpCost' ] = parameters_dict[f'p{sector}GenStartUpCost' ].loc[set_sector] parameters_dict[f'p{sector}GenShutDownCost' ] = parameters_dict[f'p{sector}GenShutDownCost' ].loc[set_sector] parameters_dict[f'p{sector}GenBinaryCommitment' ] = parameters_dict[f'p{sector}GenBinaryCommitment' ].loc[set_sector] parameters_dict[f'p{sector}GenStorageInvestment' ] = parameters_dict[f'p{sector}GenStorageInvestment' ].loc[set_sector] parameters_dict[f'p{sector}GenMaxInflowsCons' ] = parameters_dict[f'p{sector}GenMaxInflowsCons' ].loc[set_sector] parameters_dict[f'p{sector}GenMinInflowsCons' ] = parameters_dict[f'p{sector}GenMinInflowsCons' ].loc[set_sector] parameters_dict[f'p{sector}GenMaxOutflowsProd' ] = parameters_dict[f'p{sector}GenMaxOutflowsProd' ].loc[set_sector] parameters_dict[f'p{sector}GenMinOutflowsProd' ] = parameters_dict[f'p{sector}GenMinOutflowsProd' ].loc[set_sector] # drop lines not lc or ll parameters_dict['pEleNetFixedInvestmentCost'] = parameters_dict['pEleNetFixedInvestmentCost'].loc[model.elc] parameters_dict['pEleNetInvestmentLo' ] = parameters_dict['pEleNetInvestmentLo' ].loc[model.elc] parameters_dict['pEleNetInvestmentUp' ] = parameters_dict['pEleNetInvestmentUp' ].loc[model.elc] # this option avoids a warning in the following assignments pd.options.mode.chained_assignment = None # drop pipelines not pc parameters_dict['pHydNetFixedInvestmentCost'] = parameters_dict['pHydNetFixedInvestmentCost'].loc[model.hpc] parameters_dict['pHydNetInvestmentLo' ] = parameters_dict['pHydNetInvestmentLo' ].loc[model.hpc] parameters_dict['pHydNetInvestmentUp' ] = parameters_dict['pHydNetInvestmentUp' ].loc[model.hpc] # replace very small costs by 0 pEpsilon = 1e-4 # this value in €/GWh is related to the smallest reduced cost parameters_dict['pEleGenLinearTerm' ][parameters_dict['pEleGenLinearTerm' ] < pEpsilon] = 0.0 parameters_dict['pEleGenConstantTerm'][parameters_dict['pEleGenConstantTerm'] < pEpsilon] = 0.0 # parameters_dict['pPeriodProb'] = parameters_dict['pScenProb'].copy() for p,sc in model.ps: # periods and scenarios are going to be solved together with their weight and probability parameters_dict['pPeriodProb'][p,sc] = parameters_dict['pPeriodWeight'][p] * parameters_dict['pScenProb'][p,sc] # load levels multiple of cycles for each ESS/generator model.negs = [(n,egs ) for n,egs in model.n * model.egs if model.n.ord(n) % parameters_dict['pEleCycleTimeStep' ][egs ] == 0] model.negsc = [(n,egsc) for n,egsc in model.n * model.egsc if model.n.ord(n) % parameters_dict['pEleCycleTimeStep' ][egsc] == 0] model.negso = [(n,egs ) for n,egs in model.n * model.egs if model.n.ord(n) % parameters_dict['pEleOutflowsTimeStep'][egs ] == 0] model.nhgs = [(n,hgs ) for n,hgs in model.n * model.hgs if model.n.ord(n) % parameters_dict['pHydCycleTimeStep' ][hgs ] == 0] model.nhgsc = [(n,hgsc) for n,hgsc in model.n * model.hgsc if model.n.ord(n) % parameters_dict['pHydCycleTimeStep' ][hgsc] == 0] model.nhgso = [(n,hgs ) for n,hgs in model.n * model.hgs if model.n.ord(n) % parameters_dict['pHydOutflowsTimeStep'][hgs ] == 0] # # ESS with outflows model.psegsi = [(p,sc,egs) for p,sc,egs in model.psegs if sum(parameters_dict['pVarMaxInflows' ][egs][p,sc,n2] for n2 in model.n2)] model.psegso = [(p,sc,egs) for p,sc,egs in model.psegs if sum(parameters_dict['pVarMaxOutflows'][egs][p,sc,n2] for n2 in model.n2)] model.pshgsi = [(p,sc,hgs) for p,sc,hgs in model.pshgs if sum(parameters_dict['pVarMaxInflows' ][hgs][p,sc,n2] for n2 in model.n2)] model.pshgso = [(p,sc,hgs) for p,sc,hgs in model.pshgs if sum(parameters_dict['pVarMaxOutflows'][hgs][p,sc,n2] for n2 in model.n2)] # if line length = 0 changed to geographical distance with an additional 10% for network in ['Ele', 'Hyd']: if network == 'Ele': snet = model.ela else: snet = model.hpa for ni, nf, cc in snet: if parameters_dict[f'p{network}NetLength'][ni,nf,cc] == 0.0: parameters_dict[f'p{network}NetLength'][ni,nf,cc] = 1.1 * 6371 * 2 * math.asin(math.sqrt(math.pow(math.sin((parameters_dict['pNodeLat'][nf]-parameters_dict['pNodeLat'][ni])*math.pi/180/2),2) + math.cos(parameters_dict['pNodeLat'][ni]*math.pi/180)*math.cos(parameters_dict['pNodeLat'][nf]*math.pi/180)*math.pow(math.sin((parameters_dict['pNodeLon'][nf]-parameters_dict['pNodeLon'][ni])*math.pi/180/2),2))) # thermal and variable units ordered by increasing variable cost model.go = parameters_dict['pEleGenLinearTerm'].sort_values().index # remove the elements in model.go if they are not in model.eg model.go = [go for go in model.go if go in model.eg] # determine the initial committed units and their output parameters_dict['pEleInitialOutput'] = pd.Series([0.0]*len(model.eg), model.ps * model.eg) parameters_dict['pEleInitialUC' ] = pd.Series([0 ]*len(model.eg), model.ps * model.eg) for p,sc in model.ps: parameters_dict['pEleSystemOutput'] = 0.0 for go in model.go: n1 = next(iter(model.n)) if parameters_dict['pEleSystemOutput'] < sum(parameters_dict['pVarMaxDemand'][ed][p,sc,n1] for ed in model.ed): if go in model.egr: parameters_dict['pEleInitialOutput'][p,sc,go] = parameters_dict['pEleMaxPower'][go][p,sc,n1] elif go in model.eg: parameters_dict['pEleInitialOutput'][p,sc,go] = parameters_dict['pEleMinPower'][go][p,sc,n1] parameters_dict['pEleInitialUC' ][p,sc,go] = 1 parameters_dict['pEleSystemOutput' ] += parameters_dict['pEleInitialOutput'][p,sc,go] # calculating if the unit was committed before of the time periods or not if parameters_dict['pEleGenUpTime'][go] - parameters_dict['pEleGenUpTimeZero'][go] > 0: parameters_dict['pEleInitialUC'][p,sc,go] = 1 if parameters_dict['pEleGenDownTime'][go] - parameters_dict['pEleGenDownTimeZero'][go] > 0: parameters_dict['pEleInitialUC'][p,sc,go] = 0 # determine the initial committed hydrogen units and their output parameters_dict['pHydInitialOutput'] = pd.Series([0.0]*len(model.hg), model.ps * model.hg) parameters_dict['pHydInitialUC' ] = pd.Series([0 ]*len(model.hg), model.ps * model.hg) for p,sc in model.ps: parameters_dict['pHydSystemOutput'] = 0.0 for hg in model.hg: n1 = next(iter(model.n)) if parameters_dict['pHydSystemOutput'] < sum(parameters_dict['pVarMaxDemand'][hd][p,sc,n1] for hd in model.hd): if hg in model.hgr: parameters_dict['pHydInitialOutput'][p,sc,hg] = parameters_dict['pHydMaxPower'][hg][p,sc,n1] elif hg in model.hg: parameters_dict['pHydInitialOutput'][p,sc,hg] = parameters_dict['pHydMinPower'][hg][p,sc,n1] parameters_dict['pHydInitialUC' ][p,sc,hg] = 1 parameters_dict['pHydSystemOutput' ] += parameters_dict['pHydInitialOutput'][p,sc,hg] # calculating if the unit was committed before of the time periods or not if parameters_dict['pHydGenUpTime'][hg] - parameters_dict['pHydGenUpTimeZero'][hg] > 0: parameters_dict['pHydInitialUC'][p,sc,hg] = 1 if parameters_dict['pHydGenDownTime'][hg] - parameters_dict['pHydGenDownTimeZero'][hg] > 0: parameters_dict['pHydInitialUC'][p,sc,hg] = 0 # load levels multiple of cycles for each ESS/generator model.negs = [(n,egs ) for n,egs in model.n * model.egs if model.n.ord(n) % parameters_dict['pEleCycleTimeStep' ][egs ] == 0] model.negsc = [(n,egsc) for n,egsc in model.n * model.egsc if model.n.ord(n) % parameters_dict['pEleCycleTimeStep' ][egsc] == 0] model.negso = [(n,egs) for n,egs in model.n * model.egs if model.n.ord(n) % parameters_dict['pEleOutflowsTimeStep'][egs] == 0] for sector in ['Ele', 'Hyd']: # if sector == 'Ele': # retail = model.er # else: # retail = model.hr # small values are converted to 0 pGenerationPeak = parameters_dict[f'p{sector}MaxPower'].sum(axis=1).max() pEpsilon_capacity = pGenerationPeak * 1e-5 pCostPeak = parameters_dict[f'p{sector}GenLinearTerm'].max() pEpsilon_cost = pCostPeak * model.factor1 # pPricePeak = parameters_dict['pVarEnergyPrice'][retail].max() # electricity price # pEpsilon_price = pPricePeak * model.factor1 # values < 1e-5 times the maximum generation are converted to 0 for all elements in parameters_dict for idx in ['MinPower', 'MaxPower', 'MinCharge', 'MaxCharge', 'MinStorage', 'MaxStorage', 'MinInflows', 'MaxInflows', 'MinOutflows', 'MaxOutflows', 'MinFuelCost', 'MaxFuelCost', 'MinCO2Cost', 'MaxCO2Cost']: parameters_dict[f'p{sector}{idx}'] = parameters_dict[f'p{sector}{idx}'].where(parameters_dict[f'p{sector}{idx}'] > pEpsilon_capacity, other=0.0) # for all costs for idx in ['LinearTerm', 'ConstantTerm', 'StartUpCost', 'ShutDownCost', 'LinearVarCost', 'CO2EmissionCost']: parameters_dict[f'p{sector}Gen{idx}'] = parameters_dict[f'p{sector}Gen{idx}'].where(parameters_dict[f'p{sector}Gen{idx}'] > pEpsilon_cost, other=0.0) # # for all pricesi # for idx in ['VarEnergyPrice', 'VarEnergyCost']: # if len(retail): # parameters_dict[f'p{idx}'] = parameters_dict[f'p{idx}'][retail].where(parameters_dict[f'p{idx}'][retail] > pEpsilon_price, other=0.0) # # calculating the availability of the unit # Loop through each sector and set the appropriate sector set for sector in ['Ele', 'Hyd']: set_sector = model.psneg if sector == 'Ele' else model.psnhg # Iterate over each index in the set for idx in set_sector: # Check if the fixed availability for the generator is enabled if parameters_dict[f'p{sector}GenFixedAvailability'][idx[-1]] != 1: parameters_dict['pVarFixedAvailability'].loc[idx[:3], idx[-1]] = 1 df_fixed_availability = parameters_dict['pVarFixedAvailability'].stack().to_frame(name='Value') df_fixed_availability['Type'] = 'FixedAvailability' model.Par = parameters_dict log_time('--- Defining the parameters', start_time, ind_log=indlog) return model
[docs] def create_variables(model, optmodel, indlog): # print('-- Defining the variables') #%% start time StartTime = time.time() # model.Peaks = Set(initialize=[ i for i in range(1,4,1)]) # number of selected peaks hours if model.Par['pParNumberPowerPeaks'] == 0: model.Peaks = RangeSet(1) else: model.Peaks = RangeSet(model.Par['pParNumberPowerPeaks']) # number of selected peaks hours #%% total variables setattr(optmodel, 'vTotalSCost', Var( within= Reals, doc='total system cost [EUR]')) setattr(optmodel, 'vTotalCComponent', Var(model.ps , within= Reals, doc='total system component cost [EUR]')) setattr(optmodel, 'vTotalRComponent', Var(model.ps , within= Reals, doc='total system component revenue [EUR]')) # electricity and hydrogen cost components setattr(optmodel, 'vTotalEleNCost', Var(model.ps , within= Reals, doc='total fixed electricity network cost [EUR]')) setattr(optmodel, 'vTotalEleXCost', Var(model.ps , within= Reals, doc='total tax and surcharges electricity cost [EUR]')) setattr(optmodel, 'vTotalEleMCost', Var(model.psn, within= Reals, doc='total variable electricity market cost [EUR]')) setattr(optmodel, 'vTotalHydMCost', Var(model.psn, within= Reals, doc='total variable hydrogen market cost [EUR]')) setattr(optmodel, 'vTotalEleOCost', Var(model.psn, within= Reals, doc='total electricity oper cost [EUR]')) setattr(optmodel, 'vTotalHydOCost', Var(model.psn, within= Reals, doc='total hydrogen oper cost [EUR]')) setattr(optmodel, 'vTotalEleDCost', Var(model.psd, within= Reals, doc='total electricity degradation cost [EUR]')) setattr(optmodel, 'vTotalHydDCost', Var(model.psd, within= Reals, doc='total hydrogen degradation cost [EUR]')) # electricity and hydrogen revenue components setattr(optmodel, 'vTotalEleXRev', Var(model.ps , within= Reals, doc='total tax electricity revenue [EUR]')) setattr(optmodel, 'vTotalEleMRev', Var(model.psn, within= Reals, doc='total variable electricity market revenue [EUR]')) setattr(optmodel, 'vTotalHydMRev', Var(model.psn, within= Reals, doc='total variable hydrogen market revenue [EUR]')) # electricity network/grid cost such capacity and peak costs setattr(optmodel, 'vTotalElePeakCost', Var(model.ps , within= Reals, doc='total electricity peak cost [EUR]')) # setattr(optmodel, 'vTotalHydPeakCost', Var(model.ps , within= Reals, doc='total hydrogen peak cost [EUR]')) setattr(optmodel, 'vTotalEleNetUseVarCost', Var(model.ps , within= Reals, doc='total electricity network usage cost [EUR]')) setattr(optmodel, 'vTotalEleNetUseFixCost', Var(model.ps , within= Reals, doc='total electricity capacity tariff cost [EUR]')) # electricity market costs setattr(optmodel, 'vTotalEleMrkDACost', Var(model.psn, within= Reals, doc='total electricity day-ahead market cost [EUR]')) setattr(optmodel, 'vTotalEleMrkPPACost', Var(model.psn, within= Reals, doc='total electricity PPA market cost [EUR]')) # electricity market revenues setattr(optmodel, 'vTotalEleMrkDARev', Var(model.psn, within= Reals, doc='total electricity day-ahead market revenue [EUR]')) setattr(optmodel, 'vTotalEleMrkPPARev', Var(model.psn, within= Reals, doc='total electricity PPA market revenue [EUR]')) setattr(optmodel, 'vTotalEleMrkFrqRev', Var(model.psn, within= Reals, doc='total electricity frequency market revenue [EUR]')) # ancillary services revenues setattr(optmodel, 'vTotalEleFCRDUpRev', Var(model.psn, within= Reals, doc='total electricity FCR-D up market revenue [EUR]')) setattr(optmodel, 'vTotalEleFCRDDwRev', Var(model.psn, within= Reals, doc='total electricity FCR-D down market revenue [EUR]')) setattr(optmodel, 'vTotalEleFCRNRev', Var(model.psn, within= Reals, doc='total electricity FCR-N market revenue [EUR]')) # hydrogen market costs and revenues setattr(optmodel, 'vTotalHydMrkPPACost', Var(model.psn, within= Reals, doc='total hydrogen PPA market cost [EUR]')) setattr(optmodel, 'vTotalHydMrkPPARev', Var(model.psn, within= Reals, doc='total hydrogen PPA market revenue [EUR]')) # electricity tax costs and revenues setattr(optmodel, 'vTotalEleEnergyTaxCost', Var(model.ps , within= Reals, doc='total electricity VAT cost [EUR]')) setattr(optmodel, 'vTotalEleISRev', Var(model.ps , within= Reals, doc='total electricity incentives revenue [EUR]')) # electricity and hydrogen generation costs setattr(optmodel, 'vTotalEleGCost', Var(model.psn, within= Reals, doc='total variable electricity prod cost [EUR]')) setattr(optmodel, 'vTotalHydGCost', Var(model.psn, within= Reals, doc='total variable hydrogen prod cost [EUR]')) # electricity and hydrogen emission costs setattr(optmodel, 'vTotalEleECost', Var(model.psn, within= Reals, doc='total electricity emission cost [EUR]')) # electricity and hydrogen consumption costs setattr(optmodel, 'vTotalEleCCost', Var(model.psn, within= Reals, doc='total variable electricity cons cost [EUR]')) setattr(optmodel, 'vTotalHydCCost', Var(model.psn, within= Reals, doc='total variable hydrogen cons cost [EUR]')) # electricity and hydrogen reliability costs setattr(optmodel, 'vTotalEleRCost', Var(model.psn, within= Reals, doc='total system electricity reliability cost [EUR]')) setattr(optmodel, 'vTotalHydRCost', Var(model.psn, within= Reals, doc='total system hydrogen reliability cost [EUR]')) setattr(optmodel, 'vEleDemPeakGlobal', Var(model.psmer, model.Peaks, within=PositiveReals, doc='electricity peak [kW]')) setattr(optmodel, 'vHydDemPeakGlobal', Var(model.psmhr, model.Peaks, within=PositiveReals, doc='hydrogen peak [kgH2]')) setattr(optmodel, 'vEleDemPeakDay', Var(model.psder, within=PositiveReals, doc='electricity daily peak [kW]')) setattr(optmodel, 'vHydDemPeakDay', Var(model.psdhr, within=PositiveReals, doc='hydrogen daily peak [kgH2]')) # Define continuous variables setattr(optmodel, 'vEleBuy', Var(model.psner, within=NonNegativeReals, doc='electricity retail buy [kW]')) setattr(optmodel, 'vEleSell', Var(model.psner, within=NonNegativeReals, doc='electricity retail sell [kW]')) setattr(optmodel, 'vEleDemand', Var(model.psned, within=NonNegativeReals, doc='electricity demand [kW]')) setattr(optmodel, 'vENS', Var(model.psned, within=NonNegativeReals, doc='electricity not served [kW]')) setattr(optmodel, 'vEleTotalOutput', Var(model.psneg, within=NonNegativeReals, doc='total electricity output of the unit [kW]')) setattr(optmodel, 'vEleTotalOutput2ndBlock', Var(model.psnegnr, within=NonNegativeReals, doc='second block of the unit [kW]')) setattr(optmodel, 'vEleTotalCharge', Var(model.psneh, within=NonNegativeReals, doc='ESS total charge power [kW]')) setattr(optmodel, 'vEleTotalCharge2ndBlock', Var(model.psneh, within=NonNegativeReals, doc='ESS charge power [kW]')) setattr(optmodel, 'vEleEnergyInflows', Var(model.psnegs, within=NonNegativeReals, doc='unscheduled inflows of all ESS units [kWh]')) setattr(optmodel, 'vEleEnergyOutflows', Var(model.psnegs, within=NonNegativeReals, doc='scheduled outflows of all ESS units [kWh]')) setattr(optmodel, 'vEleInventory', Var(model.psnegs, within=NonNegativeReals, doc='ESS inventory [kWh]')) setattr(optmodel, 'vEleInventoryMinDay', Var(model.psdegs, within=NonNegativeReals, doc=f'Minimum battery inventory per day [kWh]')) setattr(optmodel, 'vEleInventoryMaxDay', Var(model.psdegs, within=NonNegativeReals, doc=f'Maximum battery inventory per day [kWh]')) setattr(optmodel, 'vEleInventoryDoDDay', Var(model.psdegs, within=NonNegativeReals, doc=f'Battery Depth of Discharge per day [kWh]')) setattr(optmodel, 'vEleInventoryDoDS1Day', Var(model.psdegs, within=NonNegativeReals, doc=f'Battery Depth of Discharge per day S1 [kWh]')) setattr(optmodel, 'vEleInventoryDoDS2Day', Var(model.psdegs, within=NonNegativeReals, doc=f'Battery Depth of Discharge per day S2 [kWh]')) setattr(optmodel, 'vEleInventoryDoDS3Day', Var(model.psdegs, within=NonNegativeReals, doc=f'Battery Depth of Discharge per day S3 [kWh]')) setattr(optmodel, 'vEleSpillage', Var(model.psnegs, within=NonNegativeReals, doc='ESS spillage [kWh]')) setattr(optmodel, 'vEleExport', Var(model.psnnd, within=NonNegativeReals, doc='electricity export in node [kW]')) setattr(optmodel, 'vEleImport', Var(model.psnnd, within=NonNegativeReals, doc='electricity import in node [kW]')) setattr(optmodel, 'vHydBuy', Var(model.psnhr, within=NonNegativeReals, doc='hydrogen buy in node [kgH2]')) setattr(optmodel, 'vHydSell', Var(model.psnhr, within=NonNegativeReals, doc='hydrogen sell in node [kgH2]')) setattr(optmodel, 'vHydDemand', Var(model.psnhd, within=NonNegativeReals, doc='hydrogen demand [kgH2]')) setattr(optmodel, 'vHNS', Var(model.psnhd, within=NonNegativeReals, doc='hydrogen demand [kgH2]')) setattr(optmodel, 'vHydTotalOutput', Var(model.psnhg, within=NonNegativeReals, doc='total hydrogen output of the unit [kgH2]')) setattr(optmodel, 'vHydTotalOutput2ndBlock', Var(model.psnhg, within=NonNegativeReals, doc='second block of the unit [kgH2]')) setattr(optmodel, 'vHydTotalCharge', Var(model.psnhe, within=NonNegativeReals, doc='H2S total charge power [kgH2]')) setattr(optmodel, 'vHydTotalCharge2ndBlock', Var(model.psnhe, within=NonNegativeReals, doc='H2S charge power [kgH2]')) setattr(optmodel, 'vHydEnergyInflows', Var(model.psnhgs, within=NonNegativeReals, doc='unscheduled inflows of all H2S units [kgH2]')) setattr(optmodel, 'vHydEnergyOutflows', Var(model.psnhgs, within=NonNegativeReals, doc='scheduled outflows of all H2S units [kgH2]')) setattr(optmodel, 'vHydInventory', Var(model.psnhgs, within=NonNegativeReals, doc='H2S inventory [kgH2]')) setattr(optmodel, 'vHydSpillage', Var(model.psnhgs, within=NonNegativeReals, doc='H2S spillage [kgH2]')) setattr(optmodel, 'vHydExport', Var(model.psnnd, within=NonNegativeReals, doc='hydrogen export in node [kgH2]')) setattr(optmodel, 'vHydImport', Var(model.psnnd, within=NonNegativeReals, doc='hydrogen import in node [kgH2]')) setattr(optmodel, 'vEleNetFlow', Var(model.psnela, within= Reals, doc='electricity net flow [kW]')) setattr(optmodel, 'vHydNetFlow', Var(model.psnhpa, within= Reals, doc='hydrogen net flow [kgH2]')) setattr(optmodel, 'vEleNetTheta', Var(model.psnnd, within= Reals, doc='electricity net theta [kW]')) setattr(optmodel, 'vEleFreqContReserveDisUpwardBid', Var(model.psneg, within=NonNegativeReals, doc='electricity frequency containment reserve upward bid [kW]')) setattr(optmodel, 'vEleFreqContReserveDisDownwardBid', Var(model.psneg, within=NonNegativeReals, doc='electricity frequency containment reserve downward bid [kW]')) setattr(optmodel, 'vEleFreqContReserveNorBid', Var(model.psneg, within=NonNegativeReals, doc='electricity frequency normal reserve bid [kW]')) # setattr(optmodel, 'vEleFreqContReserveDisUpwardAct', Var(model.psneg, within=NonNegativeReals, doc='electricity frequency containment reserve upward fraction activation [kW]')) # setattr(optmodel, 'vEleFreqContReserveDisDownwardAct', Var(model.psneg, within=NonNegativeReals, doc='electricity frequency containment reserve downward fraction activation [kW]')) setattr(optmodel, 'vEleFreqContReserveDisUpGen', Var(model.psnegt, within=NonNegativeReals, doc='electricity frequency containment reserve upward generation [kW]')) setattr(optmodel, 'vEleFreqContReserveDisDownGen', Var(model.psnegt, within=NonNegativeReals, doc='electricity frequency containment reserve downward generation [kW]')) setattr(optmodel, 'vEleFreqContReserveDisUpCha', Var(model.psnegs, within=NonNegativeReals, doc='electricity frequency containment reserve upward charge [kW]')) setattr(optmodel, 'vEleFreqContReserveDisUpDis', Var(model.psnegs, within=NonNegativeReals, doc='electricity frequency containment reserve upward discharge [kW]')) setattr(optmodel, 'vEleFreqContReserveDisDownCha', Var(model.psnegs, within=NonNegativeReals, doc='electricity frequency containment reserve downward charge [kW]')) setattr(optmodel, 'vEleFreqContReserveDisDownDis', Var(model.psnegs, within=NonNegativeReals, doc='electricity frequency containment reserve downward discharge [kW]')) setattr(optmodel, 'vEleFreqContReserveNorUpGen', Var(model.psnegt, within=NonNegativeReals, doc='electricity frequency normal reserve generation [kW]')) setattr(optmodel, 'vEleFreqContReserveNorDownGen', Var(model.psnegt, within=NonNegativeReals, doc='electricity frequency normal reserve downward generation [kW]')) setattr(optmodel, 'vEleFreqContReserveNorUpCha', Var(model.psnegs, within=NonNegativeReals, doc='electricity frequency normal reserve charge [kW]')) setattr(optmodel, 'vEleFreqContReserveNorUpDis', Var(model.psnegs, within=NonNegativeReals, doc='electricity frequency normal reserve discharge [kW]')) setattr(optmodel, 'vEleFreqContReserveNorDownCha', Var(model.psnegs, within=NonNegativeReals, doc='electricity frequency normal reserve downward charge [kW]')) setattr(optmodel, 'vEleFreqContReserveNorDownDis', Var(model.psnegs, within=NonNegativeReals, doc='electricity frequency normal reserve downward discharge [kW]')) if sum(model.Par['pEleDemFlexible'][idx] for idx in model.ed) > 0: setattr(optmodel, 'vEleDemFlex', Var(model.psned, within= Reals, doc='flexible electricity demand [kW]')) log_time('--- Defining the continuous variables', StartTime, ind_log=indlog) # Define binary variables if model.Par['pOptIndBinGenOperat'] == 0: setattr(optmodel, 'vEleGenCommitment', Var(model.psnegt, within=UnitInterval, initialize=0, doc='generator binary commitment ')) setattr(optmodel, 'vEleGenStartUp', Var(model.psnegt, within=UnitInterval, initialize=0, doc='generator binary start-up ')) setattr(optmodel, 'vEleGenShutDown', Var(model.psnegt, within=UnitInterval, initialize=0, doc='generator binary shut-down ')) # setattr(optmodel, 'vEleStorOperat', Var(model.psnegs, within=UnitInterval, initialize=0, doc='storage binary operation ')) setattr(optmodel, 'vEleStorCharge', Var(model.psnegs, within=UnitInterval, initialize=0, doc='storage binary charge ')) setattr(optmodel, 'vEleStorDischarge', Var(model.psnegs, within=UnitInterval, initialize=0, doc='storage binary discharge ')) setattr(optmodel, 'vElePeakGlobalInd', Var(model.psner, model.Peaks, within=UnitInterval, initialize=0, doc='peak hour indicator ')) setattr(optmodel, 'vElePeakMonthInd', Var(model.psder, model.Peaks, within=UnitInterval, initialize=0, doc='monthly peak hour indicator ')) setattr(optmodel, 'vElePeakDayInd', Var(model.psdner, within=UnitInterval, initialize=0, doc='daily peak hour indicator ')) setattr(optmodel, 'vHydGenCommitment', Var(model.psnhg, within=UnitInterval, initialize=0, doc='generator binary commitment ')) setattr(optmodel, 'vHydGenStartUp', Var(model.psnhg, within=UnitInterval, initialize=0, doc='generator binary start-up ')) setattr(optmodel, 'vHydGenShutDown', Var(model.psnhg, within=UnitInterval, initialize=0, doc='generator binary shut-down ')) setattr(optmodel, 'vHydStorOperat', Var(model.psnhgs, within=UnitInterval, initialize=0, doc='storage binary operation ')) setattr(optmodel, 'vHydStorCharge', Var(model.psnhgs, within=UnitInterval, initialize=0, doc='storage binary charge ')) setattr(optmodel, 'vHydStorDischarge', Var(model.psnhgs, within=UnitInterval, initialize=0, doc='storage binary discharge ')) setattr(optmodel, 'vHydPeakGlobalInd', Var(model.psner, model.Peaks, within=UnitInterval, initialize=0, doc='peak hour indicator ')) setattr(optmodel, 'vHydPeakMonthInd', Var(model.psder, model.Peaks, within=UnitInterval, initialize=0, doc='monthly peak hour indicator ')) setattr(optmodel, 'vHydPeakDayInd', Var(model.psdner, within=UnitInterval, initialize=0, doc='daily peak hour indicator ')) else: setattr(optmodel, 'vEleGenCommitment', Var(model.psnegt, within=Binary, initialize=0, doc='generator binary commitment ')) setattr(optmodel, 'vEleGenStartUp', Var(model.psnegt, within=Binary, initialize=0, doc='generator binary start-up ')) setattr(optmodel, 'vEleGenShutDown', Var(model.psnegt, within=Binary, initialize=0, doc='generator binary shut-down ')) # setattr(optmodel, 'vEleStorOperat', Var(model.psnegs, within=Binary, initialize=0, doc='storage binary operation ')) setattr(optmodel, 'vEleStorCharge', Var(model.psnegs, within=Binary, initialize=0, doc='storage binary charge ')) setattr(optmodel, 'vEleStorDischarge', Var(model.psnegs, within=Binary, initialize=0, doc='storage binary discharge ')) setattr(optmodel, 'vElePeakGlobalInd', Var(model.psner, model.Peaks, within=Binary, initialize=0, doc='peak hour indicator ')) setattr(optmodel, 'vElePeakMonthInd', Var(model.psder, model.Peaks, within=Binary, initialize=0, doc='monthly peak hour indicator ')) setattr(optmodel, 'vElePeakDayInd', Var(model.psdner, within=Binary, initialize=0, doc='daily peak hour indicator ')) setattr(optmodel, 'vHydGenCommitment', Var(model.psnhg, within=Binary, initialize=0, doc='generator binary commitment ')) setattr(optmodel, 'vHydGenStartUp', Var(model.psnhg, within=Binary, initialize=0, doc='generator binary start-up ')) setattr(optmodel, 'vHydGenShutDown', Var(model.psnhg, within=Binary, initialize=0, doc='generator binary shut-down ')) setattr(optmodel, 'vHydStorOperat', Var(model.psnhgs, within=Binary, initialize=0, doc='storage binary operation ')) setattr(optmodel, 'vHydStorCharge', Var(model.psnhgs, within=Binary, initialize=0, doc='storage binary charge ')) setattr(optmodel, 'vHydStorDischarge', Var(model.psnhgs, within=Binary, initialize=0, doc='storage binary discharge ')) setattr(optmodel, 'vHydPeakGlobalInd', Var(model.psner, model.Peaks, within=Binary, initialize=0, doc='peak hour indicator ')) setattr(optmodel, 'vHydPeakMonthInd', Var(model.psder, model.Peaks, within=Binary, initialize=0, doc='monthly peak hour indicator ')) setattr(optmodel, 'vHydPeakDayInd', Var(model.psdner, within=Binary, initialize=0, doc='daily peak hour indicator ')) if model.Par['pOptIndBinNetOperat'] == 0: setattr(optmodel, 'vEleNetCommit', Var(model.psnela, within=UnitInterval, initialize=0, doc='network binary operation ')) setattr(optmodel, 'vHydNetCommit', Var(model.psnela, within=UnitInterval, initialize=0, doc='network binary operation ')) else: setattr(optmodel, 'vEleNetCommit', Var(model.psnela, within=Binary, initialize=0, doc='network binary operation ')) setattr(optmodel, 'vHydNetCommit', Var(model.psnela, within=Binary, initialize=0, doc='network binary operation ')) log_time('--- Defining the binary variables', StartTime, ind_log=indlog) # Precompute the bounds # psn std_upper_bound = 1e4 std_lower_bound = -1e4 zero_upper_bound = 0.0 zero_lower_bound = 0.0 # List of variables to set bounds cost_vars = [optmodel.vTotalEleNCost, optmodel.vTotalEleXCost, optmodel.vTotalEleMCost, optmodel.vTotalHydMCost, optmodel.vTotalEleOCost, optmodel.vTotalHydOCost] zero_cost_vars = [optmodel.vTotalHydDCost, optmodel.vTotalEleMrkPPACost, optmodel.vTotalEleMrkPPARev] rev_vars = [optmodel.vTotalEleXRev, optmodel.vTotalEleMRev, optmodel.vTotalHydMRev] sub_cost_vars = [optmodel.vTotalEleDCost, optmodel.vTotalElePeakCost, optmodel.vTotalEleNetUseVarCost, optmodel.vTotalEleNetUseFixCost, optmodel.vTotalEleMrkDACost, optmodel.vTotalHydMrkPPACost, optmodel.vTotalEleEnergyTaxCost, optmodel.vTotalEleGCost, optmodel.vTotalHydGCost, optmodel.vTotalEleECost, optmodel.vTotalEleCCost, optmodel.vTotalHydCCost, optmodel.vTotalEleRCost, optmodel.vTotalHydRCost] sub_rev_vars = [optmodel.vTotalEleMrkDARev, optmodel.vTotalHydMrkPPARev, optmodel.vTotalEleISRev, optmodel.vTotalEleMrkFrqRev, optmodel.vTotalEleFCRDUpRev, optmodel.vTotalEleFCRDDwRev] # ed_vars = [optmodel.vENS] # Set bounds for each variable # Objective function for var in cost_vars + rev_vars + sub_cost_vars + sub_rev_vars: var.setlb(std_lower_bound) var.setub(std_upper_bound) for var in zero_cost_vars: var.setlb(zero_lower_bound) var.setub(zero_upper_bound) # Electricity for idx in model.psner: optmodel.vEleBuy [idx].setlb(model.Par['pEleRetMinimumEnergyBuy' ][idx[-1]]) optmodel.vEleBuy [idx].setub(model.Par['pEleRetMaximumEnergyBuy' ][idx[-1]]) optmodel.vEleSell[idx].setlb(model.Par['pEleRetMinimumEnergySell'][idx[-1]]) optmodel.vEleSell[idx].setub(model.Par['pEleRetMaximumEnergySell'][idx[-1]]) for idx in model.psned: if model.Par['pEleDemFlexible'][idx[-1]] == 0.0: optmodel.vEleDemand[idx].setlb(model.Par['pVarMaxDemand'][idx[-1]][idx[:3]]) optmodel.vEleDemand[idx].setub(model.Par['pVarMaxDemand'][idx[-1]][idx[:3]]) else: optmodel.vEleDemFlex[idx].setlb(-model.Par['pVarMaxDemand'][idx[-1]][idx[:3]]*model.Par['pEleDemFlexPercent'][idx[-1]]) optmodel.vEleDemFlex[idx].setub(+model.Par['pVarMaxDemand'][idx[-1]][idx[:3]]*model.Par['pEleDemFlexPercent'][idx[-1]]) # optmodel.vEleDemand[idx].setlb(model.Par['pVarMinDemand'][idx[-1]][idx[:3]]) # optmodel.vEleDemand[idx].setub(model.Par['pVarMaxDemand'][idx[-1]][idx[:3]]) optmodel.vENS[idx].setlb(0.0) optmodel.vENS[idx].setub(model.Par['pVarMaxDemand'][idx[-1]][idx[:3]]) for idx in model.psneg: optmodel.vEleTotalOutput[idx].setlb(0.0) optmodel.vEleTotalOutput[idx].setub(model.Par['pEleMaxPower'][idx[-1]][idx[:3]]) if idx[-1] in model.egnr: optmodel.vEleTotalOutput2ndBlock[idx].setlb(0.0) optmodel.vEleTotalOutput2ndBlock[idx].setub(model.Par['pEleMaxPower2ndBlock'][idx[-1]][idx[:3]]) for idx in model.psneh: optmodel.vEleTotalCharge[idx].setlb(0.0) optmodel.vEleTotalCharge2ndBlock[idx].setlb(0.0) if idx[-1] in model.eg: optmodel.vEleTotalCharge[idx].setub(model.Par['pEleMaxCharge'][idx[-1]][idx[:3]]) # optmodel.vEleTotalCharge2ndBlock[idx].setub(model.Par['pEleMaxCharge'][idx[-1]][idx[:3]]) elif idx[-1] in model.hg: optmodel.vEleTotalCharge[idx].setub(model.Par['pHydMaxCharge'][idx[-1]][idx[:3]]) optmodel.vEleTotalCharge2ndBlock[idx].setub(model.Par['pHydMaxCharge2ndBlock'][idx[-1]][idx[:3]]) # for idx in model.psnegs: # if idx[-1] in model.egs: # if model.Par['pEleMinCharge'][idx[-1]][idx[:3]] > 0.0: # optmodel.vEleTotalCharge2ndBlock[idx].setlb(model.Par['pEleMinCharge'][idx[-1]][idx[:3]]) # else: # optmodel.vEleTotalCharge2ndBlock[idx].setlb(0.0) # if model.Par['pEleMinPower'][idx[-1]][idx[:3]] > 0.0: # optmodel.vEleTotalOutput2ndBlock[idx].setlb(model.Par['pEleMinPower'][idx[-1]][idx[:3]]) # else: # optmodel.vEleTotalOutput2ndBlock[idx].setlb(0.0) optmodel.vEleEnergyInflows[idx].setlb(model.Par['pEleMinInflows'][idx[-1]][idx[:3]]) optmodel.vEleEnergyInflows[idx].setub(model.Par['pEleMaxInflows'][idx[-1]][idx[:3]]) optmodel.vEleEnergyOutflows[idx].setlb(model.Par['pEleMinOutflows'][idx[-1]][idx[:3]]) optmodel.vEleEnergyOutflows[idx].setub(model.Par['pEleMaxOutflows'][idx[-1]][idx[:3]]) optmodel.vEleInventory[idx].setlb(model.Par['pEleMinStorage'][idx[-1]][idx[:3]] * model.factor1) optmodel.vEleInventory[idx].setub(model.Par['pEleMaxStorage'][idx[-1]][idx[:3]] * model.factor1) for idx in model.psnela: if model.Par['pOptIndBinSingleNode'] == 0: optmodel.vEleNetFlow[idx].setlb(-model.Par['pEleNetTTCBck' ][idx[-3:]]) optmodel.vEleNetFlow[idx].setub( model.Par['pEleNetTTC' ][idx[-3:]]) else: optmodel.vEleNetFlow[idx].setlb(std_lower_bound) optmodel.vEleNetFlow[idx].setub(std_upper_bound) # Hydrogen for idx in model.psnhr: optmodel.vHydBuy [idx].setlb(model.Par['pHydRetMinimumEnergyBuy' ][idx[-1]]) optmodel.vHydBuy [idx].setub(model.Par['pHydRetMaximumEnergyBuy' ][idx[-1]]) optmodel.vHydSell[idx].setlb(model.Par['pHydRetMinimumEnergySell'][idx[-1]]) optmodel.vHydSell[idx].setub(model.Par['pHydRetMaximumEnergySell'][idx[-1]]) for idx in model.psnhd: if model.Par['pHydDemFlexible'][idx[-1]] == 0.0: optmodel.vHydDemand[idx].setlb(model.Par['pVarMaxDemand'][idx[-1]][idx[:3]]) optmodel.vHydDemand[idx].setub(model.Par['pVarMaxDemand'][idx[-1]][idx[:3]]) else: optmodel.vHydDemand[idx].setlb(model.Par['pVarMinDemand'][idx[-1]][idx[:3]]) optmodel.vHydDemand[idx].setub(model.Par['pVarMaxDemand'][idx[-1]][idx[:3]]) optmodel.vHNS[idx].setlb(0.0) optmodel.vHNS[idx].setub(model.Par['pVarMaxDemand'][idx[-1]][idx[:3]]) for idx in model.psnhg: optmodel.vHydTotalOutput[idx].setlb(0.0) optmodel.vHydTotalOutput[idx].setub(model.Par['pHydMaxPower'][idx[-1]][idx[:3]]) optmodel.vHydTotalOutput2ndBlock[idx].setlb(0.0) optmodel.vHydTotalOutput2ndBlock[idx].setub(model.Par['pHydMaxPower2ndBlock'][idx[-1]][idx[:3]]) for idx in model.psnhe: optmodel.vHydTotalCharge[idx].setlb(0.0) optmodel.vHydTotalCharge2ndBlock[idx].setlb(0.0) if idx in model.hg: optmodel.vHydTotalCharge[idx].setub(model.Par['pHydMaxCharge'][idx[-1]][idx[:3]]) optmodel.vHydTotalCharge2ndBlock[idx].setub(model.Par['pHydMaxCharge2ndBlock'][idx[-1]][idx[:3]]) elif idx in model.eg: optmodel.vHydTotalCharge[idx].setub(model.Par['pEleMaxCharge'][idx[-1]][idx[:3]]) optmodel.vHydTotalCharge2ndBlock[idx].setub(model.Par['pEleMaxCharge2ndBlock'][idx[-1]][idx[:3]]) for idx in model.psnhgs: optmodel.vHydEnergyInflows[idx].setlb(model.Par['pHydMinInflows'][idx[-1]][idx[:3]]) optmodel.vHydEnergyInflows[idx].setub(model.Par['pHydMaxInflows'][idx[-1]][idx[:3]]) optmodel.vHydEnergyOutflows[idx].setlb(model.Par['pHydMinOutflows'][idx[-1]][idx[:3]]) optmodel.vHydEnergyOutflows[idx].setub(model.Par['pHydMaxOutflows'][idx[-1]][idx[:3]]) optmodel.vHydInventory[idx].setlb(model.Par['pHydMinStorage'][idx[-1]][idx[:3]]) optmodel.vHydInventory[idx].setub(model.Par['pHydMaxStorage'][idx[-1]][idx[:3]]) for idx in model.psnhpa: if model.Par['pOptIndBinSingleNode'] == 0: optmodel.vHydNetFlow[idx].setlb(-model.Par['pHydNetTTCBck' ][idx[-3:]]) optmodel.vHydNetFlow[idx].setub( model.Par['pHydNetTTC' ][idx[-3:]]) else: optmodel.vHydNetFlow[idx].setlb(std_lower_bound) optmodel.vHydNetFlow[idx].setub(std_upper_bound) log_time('--- Setting the bounds for the variables', StartTime, ind_log=indlog) EnergyPrefix = {} AssetCand = {} NetCand = {} RetailPrefix = {} for e in model.eg: EnergyPrefix[e] = 'Ele' AssetCand[e] = model.egc for h in model.hg: EnergyPrefix[h] = 'Hyd' AssetCand[h] = model.hgc model.EnergyPrefix = EnergyPrefix model.AssetCand = AssetCand for idx in model.ela: NetCand[idx] = 'Ele' for idx in model.hpa: NetCand[idx] = 'Hyd' model.NetCand = NetCand for idx in model.er: RetailPrefix[idx] = 'Ele' for idx in model.hr: RetailPrefix[idx] = 'Hyd' model.RetailPrefix = RetailPrefix #%% fixing variables nFixedVariables = 0.0 if model.Par['pParNumberPowerPeaks'] == 0: # for idx in model.psmer: # for peak in model.Peaks: # optmodel.__getattribute__('vEleDemPeakGlobal')[idx, peak].fix(0.0) # nFixedVariables += 1.0 # nFixedVariables += 1.0 # for idx in model.psmhr: # for peak in model.Peaks: # optmodel.__getattribute__('vHydDemPeakGlobal')[idx, peak].fix(0.0) # nFixedVariables += 1.0 # nFixedVariables += 1.0 # for idx in model.psder: # optmodel.vEleDemPeakDay[idx].fix(0.0) # nFixedVariables += 1.0 # for idx in model.psdhr: # optmodel.vHydDemPeakDay[idx].fix(0.0) # nFixedVariables += 1.0 # fixing vElePeakGlobalInd, model.psner and model.Peaks for idx in model.psner: for peak in model.Peaks: optmodel.__getattribute__('vElePeakGlobalInd')[idx, peak].fix(0.0) nFixedVariables += 1.0 # fixing vHydPeakGlobalInd, model.psner and model.Peaks for idx in model.psner: for peak in model.Peaks: optmodel.__getattribute__('vHydPeakGlobalInd')[idx, peak].fix(0.0) nFixedVariables += 1.0 # fixing vElePeakMonthInd, model.psder and model.Peaks for idx in model.psder: for peak in model.Peaks: optmodel.__getattribute__('vElePeakMonthInd')[idx, peak].fix(0.0) nFixedVariables += 1.0 # fixing vHydPeakMonthInd, model.psder and model.Peaks for idx in model.psder: for peak in model.Peaks: optmodel.__getattribute__('vHydPeakMonthInd')[idx, peak].fix(0.0) nFixedVariables += 1.0 # fixing vElePeakDayInd, model.psdner for idx in model.psdner: optmodel.__getattribute__('vElePeakDayInd')[idx].fix(0.0) nFixedVariables += 1.0 # fixing vHydPeakDayInd, model.psdner for idx in model.psdner: optmodel.__getattribute__('vHydPeakDayInd')[idx].fix(0.0) nFixedVariables += 1.0 for idx in model.psnegs: egs = idx[-1] # fixing spillage based on the model.Par['pVarFixedAvailability'][egs][p,sc,n] # if model.Par['pVarFixedAvailability'][egs][idx[:3]] == 1: # no storage operation optmodel.__getattribute__('vEleSpillage')[idx].fix(0.0) if model.Par['pEleGenMaximumPower'][egs] <= 1e-5: optmodel.__getattribute__('vEleStorDischarge')[idx].fix(0.0) nFixedVariables += 1.0 nFixedVariables += 1.0 # # fixing storage mode based on the model.Par['pVarFixedAvailability'][egs][p,sc,n] # for idx in model.psnegs: # egs = idx[-1] # if model.Par['pVarFixedAvailability'][egs][idx[:3]] == 0: # charge only # optmodel.__getattribute__('vEleStorCharge')[idx].fix(0.0) # optmodel.__getattribute__('vEleStorDischarge')[idx].fix(0.0) # optmodel.__getattribute__('vElePeakDayInd')[idx[:2]+(model.n2d_dict[idx[2]],idx[2],model.Par['pEleGenRetailer'][egs],)].fix(0.0) # optmodel.__getattribute__('vEleBuy')[idx[:2]+(idx[2],model.Par['pEleGenRetailer'][egs],)].fix(0.0) # optmodel.__getattribute__('vEleSell')[idx[:2] + (idx[2], model.Par['pEleGenRetailer'][egs],)].fix(0.0) # nFixedVariables += 5.0 # fixing storage variables related to depth of discharge scenarios for idx in model.psd: for egs in model.egs: if (model.Par['pEleGenDoDS1'][egs] + model.Par['pEleGenDoDS2'][egs] + model.Par['pEleGenDoDS3'][egs]) == 0: optmodel.__getattribute__(f'vTotalEleDCost')[idx].fix(0.0) nFixedVariables += 1.0 if (idx, egs) in model.psdegs and (model.Par['pEleGenDoDS1'][egs] + model.Par['pEleGenDoDS2'][egs] + model.Par['pEleGenDoDS3'][egs]) == 0: optmodel.__getattribute__(f'vEleInventoryMinDay')[idx+(egs,)].fix(0.0) nFixedVariables += 1.0 optmodel.__getattribute__(f'vEleInventoryMaxDay')[idx+(egs,)].fix(0.0) nFixedVariables += 1.0 optmodel.__getattribute__(f'vEleInventoryDoDDay')[idx+(egs,)].fix(0.0) nFixedVariables += 1.0 if model.Par['pEleGenDoDS1'][egs] == 0: optmodel.__getattribute__(f'vEleInventoryDoDS1Day')[idx+(egs,)].fix(0.0) nFixedVariables += 1.0 if model.Par['pEleGenDoDS2'][egs] == 0: optmodel.__getattribute__(f'vEleInventoryDoDS2Day')[idx+(egs,)].fix(0.0) nFixedVariables += 1.0 if model.Par['pEleGenDoDS3'][egs] == 0: optmodel.__getattribute__(f'vEleInventoryDoDS3Day')[idx+(egs,)].fix(0.0) nFixedVariables += 1.0 # fixing the DemPeakDay and PeakDayInd variables # for idx in model.psmer: # for peak in model.Peaks: # if model.Par['pEleRetTariffType'][idx[-1]] != 'Hourly': # optmodel.__getattribute__(f'v{model.RetailPrefix[idx[-1]]}DemPeakGlobal')[idx, peak].fix(0.0) # nFixedVariables += 1 # for idx in model.psmhr: # for peak in model.Peaks: # if model.Par['pHydRetTariffType'][idx[-1]] != 'Hourly': # optmodel.__getattribute__(f'v{model.RetailPrefix[idx[-1]]}DemPeakGlobal')[idx, peak].fix(0.0) # nFixedVariables += 1 # for idx in model.psder: # if model.Par['pEleRetTariffType'][idx[-1]] != 'Daily': # optmodel.__getattribute__(f'v{model.RetailPrefix[idx[-1]]}DemPeakDay')[idx].fix(0.0) # # # delete the variable from the model to speed up the optimization # # optmodel.del_component(optmodel.vEleDemPeakDay[idx]) # # nFixedVariables += 1 # for idx in model.psdhr: # if model.Par['pHydRetTariffType'][idx[-1]] != 'Daily': # optmodel.__getattribute__(f'v{model.RetailPrefix[idx[-1]]}DemPeakDay')[idx].fix(0.0) # # optmodel.del_component(optmodel.vHydDemPeakDay[idx]) # # nFixedVariables += 1 for idx in model.psner: for peak in model.Peaks: if model.Par['pEleRetTariffType'][idx[-1]] != 'Hourly': optmodel.__getattribute__(f'v{model.RetailPrefix[idx[-1]]}PeakGlobalInd')[idx+(peak,)].fix(0.0) nFixedVariables += 1 for idx in model.psnhr: for peak in model.Peaks: if model.Par['pHydRetTariffType'][idx[-1]] != 'Hourly': optmodel.__getattribute__(f'v{model.RetailPrefix[idx[-1]]}PeakGlobalInd')[idx+(peak,)].fix(0.0) nFixedVariables += 1 for idx in model.psder: for peak in model.Peaks: if model.Par['pEleRetTariffType'][idx[-1]] != 'Daily': optmodel.__getattribute__(f'v{model.RetailPrefix[idx[-1]]}PeakMonthInd')[idx+(peak,)].fix(0.0) nFixedVariables += 1 for idx in model.psdhr: for peak in model.Peaks: if model.Par['pHydRetTariffType'][idx[-1]] != 'Daily': optmodel.__getattribute__(f'v{model.RetailPrefix[idx[-1]]}PeakMonthInd')[idx+(peak,)].fix(0.0) nFixedVariables += 1 for idx in model.psdner: if model.Par['pEleRetTariffType'][idx[-1]] != 'Daily': optmodel.__getattribute__(f'v{model.RetailPrefix[idx[-1]]}PeakDayInd')[idx].fix(0.0) nFixedVariables += 1 for idx in model.psdnhr: if model.Par['pHydRetTariffType'][idx[-1]] != 'Daily': optmodel.__getattribute__(f'v{model.RetailPrefix[idx[-1]]}PeakDayInd')[idx].fix(0.0) nFixedVariables += 1 # assign the minimum power for the RES units for idx in model.psnegr: optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}TotalOutput')[idx].setlb(model.Par['pEleMinPower'][idx[-1]][idx[:(len(idx)-1)]]) # relax binary condition in unit generation, startup and shutdown decisions for idx in model.psnegt: if model.Par[f'p{model.EnergyPrefix[idx[-1]]}GenBinaryCommitment'][idx[-1]] == 0: optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}GenCommitment')[idx].domain = UnitInterval optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}GenStartUp' )[idx].domain = UnitInterval optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}GenShutDown' )[idx].domain = UnitInterval for idx in model.psnhgt: if model.Par[f'p{model.EnergyPrefix[idx[-1]]}GenBinaryCommitment'][idx[-1]] == 0: optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}GenCommitment')[idx].domain = UnitInterval optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}GenStartUp' )[idx].domain = UnitInterval optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}GenShutDown' )[idx].domain = UnitInterval # if min and max power coincide there are second block for idx in model.psnegnr: if model.Par[f'p{model.EnergyPrefix[idx[-1]]}MaxPower2ndBlock'][idx[-1]][idx[:(len(idx)-1)]] == 0.0: optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}TotalOutput2ndBlock')[idx].fix(0.0) nFixedVariables += 1 # if min and max outflows coincide there are neither second block, nor operating reserve for idx in model.psnhgt: if model.Par[f'p{model.EnergyPrefix[idx[-1]]}MaxPower2ndBlock'][idx[-1]][idx[:(len(idx)-1)]] == 0.0: optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}TotalOutput2ndBlock')[idx].fix(0.0) nFixedVariables += 1 # ESS with no charge capacity or not storage capacity can't charge for idx in model.psnehs: if model.Par[f'p{model.EnergyPrefix[idx[-1]]}MaxCharge'][idx[-1]][idx[:(len(idx)-1)]] == 0.0: optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}TotalCharge')[idx].fix(0.0) nFixedVariables += 1 # ESS with no charge capacity and no inflows can't produce if model.Par[f'p{model.EnergyPrefix[idx[-1]]}MaxCharge'][idx[-1]][idx[:(len(idx)-1)]] == 0.0 and sum(model.Par[f'p{model.EnergyPrefix[idx[-1]]}MaxInflows'][idx[-1]][idx[:(len(idx)-2)]+(n2,)] for n2 in model.n2) == 0.0: optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}TotalOutput')[idx].fix(0.0) optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}TotalOutput2ndBlock')[idx].fix(0.0) optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}Spillage')[idx].fix(0.0) nFixedVariables += 3 if model.Par[f'p{model.EnergyPrefix[idx[-1]]}MaxCharge2ndBlock'][idx[-1]][idx[:(len(idx)-1)]] == 0.0: optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}TotalCharge2ndBlock')[idx].fix(0.0) nFixedVariables += 1 if model.Par[f'p{model.EnergyPrefix[idx[-1]]}MaxStorage'][idx[-1]][idx[:(len(idx)-1)]] == 0.0: optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}Inventory')[idx].fix(0.0) nFixedVariables += 1 # fixing the ESS inventory at the last load level of the stage for every period and scenario if between storage limits in the DA market if len(model.n): # if model.Par[f'p{model.EnergyPrefix[idx[-1]]}InitialInventory'][idx[-1]][idx[:(len(idx)-1)]] >= model.Par[f'p{model.EnergyPrefix[idx[-1]]}MinStorage'][idx[-1]][idx[:(len(idx)-2)]+(model.n.last(),)] and model.Par[f'p{model.EnergyPrefix[idx[-1]]}InitialInventory'][idx[-1]][idx[:(len(idx)-1)]] <= model.Par[f'p{model.EnergyPrefix[idx[-1]]}MaxStorage'][idx[-1]][idx[:(len(idx)-2)]+(model.n.last(),)]: # optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}Inventory')[idx[:(len(idx)-2)]+(model.n.last(),)+(idx[-1],)].fix(model.Par[f'p{model.EnergyPrefix[idx[-1]]}InitialInventory'][idx[-1]][idx[:(len(idx)-1)]]) # nFixedVariables += 1 # 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 if model.Par[f'p{model.EnergyPrefix[idx[-1]]}InitialInventory'][idx[-1]][idx[:(len(idx)-1)]] >= model.Par[f'p{model.EnergyPrefix[idx[-1]]}MinStorage'][idx[-1]][idx[:(len(idx)-1)]] and model.Par[f'p{model.EnergyPrefix[idx[-1]]}InitialInventory'][idx[-1]][idx[:(len(idx)-1)]] <= model.Par[f'p{model.EnergyPrefix[idx[-1]]}MaxStorage'][idx[-1]][idx[:(len(idx)-1)]]: # if model.Par[f'p{model.EnergyPrefix[idx[-1]]}GenStorageType'][idx[-1]] == 'Hourly' and model.n.ord(idx[-2]) % int(24/model.Par['pParTimeStep']) == 0: # optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}Inventory')[idx].fix(model.Par[f'p{model.EnergyPrefix[idx[-1]]}InitialInventory'][idx[-1]][idx[:(len(idx)-1)]]) # nFixedVariables += 1 # if model.Par[f'p{model.EnergyPrefix[idx[-1]]}GenStorageType'][idx[-1]] == 'Hourly' and model.n.ord(idx[-2]) % int(168/model.Par['pParTimeStep']) == 0: # optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}Inventory')[idx].fix(model.Par[f'p{model.EnergyPrefix[idx[-1]]}InitialInventory'][idx[-1]][idx[:(len(idx)-1)]]) # nFixedVariables += 1 if model.Par[f'p{model.EnergyPrefix[idx[-1]]}GenStorageType'][idx[-1]] == 'Hourly' and model.n.ord(idx[-2]) % int(744/model.Par['pParTimeStep']) == 0: optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}Inventory')[idx].fix(model.Par[f'p{model.EnergyPrefix[idx[-1]]}InitialInventory'][idx[-1]][idx[:(len(idx)-1)]]) nFixedVariables += 1 if model.Par[f'p{model.EnergyPrefix[idx[-1]]}GenStorageType'][idx[-1]] == 'Weekly' and model.n.ord(idx[-2]) % int(8736/model.Par['pParTimeStep']) == 0: optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}Inventory')[idx].fix(model.Par[f'p{model.EnergyPrefix[idx[-1]]}InitialInventory'][idx[-1]][idx[:(len(idx)-1)]]) nFixedVariables += 1 if model.Par[f'p{model.EnergyPrefix[idx[-1]]}GenStorageType'][idx[-1]] == 'Monthly' and model.n.ord(idx[-2]) % int(8736/model.Par['pParTimeStep']) == 0: optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}Inventory')[idx].fix(model.Par[f'p{model.EnergyPrefix[idx[-1]]}InitialInventory'][idx[-1]][idx[:(len(idx)-1)]]) nFixedVariables += 1 # if pEleGenNoDayAhead == 1, fix the day-ahead market variables to zero for idx in model.psnegnr: if model.Par['pEleGenNoDayAhead'][idx[-1]] == 1: optmodel.vEleTotalCharge2ndBlock[idx].fix(0.0) optmodel.vEleTotalOutput2ndBlock[idx].fix(0.0) # if pEleGenNoFCRD == 1, fix the frequency containment reserve variables to zero for idx in model.psnegnr: if model.Par['pEleGenNoFCRD'][idx[-1]] == 1: optmodel.vEleFreqContReserveDisUpwardBid[idx].fix(0.0) optmodel.vEleFreqContReserveDisDownwardBid[idx].fix(0.0) if idx[-1] in model.egt: optmodel.vEleFreqContReserveDisUpGen[idx].fix(0.0) optmodel.vEleFreqContReserveDisDownGen[idx].fix(0.0) nFixedVariables += 2 if idx[-1] in model.egs: optmodel.vEleFreqContReserveDisUpCha[idx].fix(0.0) optmodel.vEleFreqContReserveDisUpDis[idx].fix(0.0) optmodel.vEleFreqContReserveDisDownCha[idx].fix(0.0) optmodel.vEleFreqContReserveDisDownDis[idx].fix(0.0) nFixedVariables += 4 elif model.Par['pEleGenNoFCRD'][idx[-1]] == 0 and model.Par['pEleGenNoDayAhead'][idx[-1]] == 0 and model.Par['pEleMaxPower'][idx[-1]][idx[:(len(idx) - 1)]] <= 1e-5 and model.Par['pEleGenV2G'][idx[-1]] == 1: optmodel.vEleTotalOutput2ndBlock[idx].fix(0.0) optmodel.vEleFreqContReserveDisDownDis[idx].fix(0.0) nFixedVariables += 2 elif model.Par['pEleGenNoFCRD'][idx[-1]] == 0 and model.Par['pEleGenNoDayAhead'][idx[-1]] == 0 and model.Par['pEleMaxPower'][idx[-1]][idx[:(len(idx) - 1)]] <= 1e-5 and model.Par['pEleGenV2G'][idx[-1]] == 0: optmodel.vEleTotalOutput2ndBlock[idx].fix(0.0) optmodel.vEleFreqContReserveDisUpDis[idx].fix(0.0) optmodel.vEleFreqContReserveDisDownDis[idx].fix(0.0) nFixedVariables += 2 if model.Par['pEleGenNoFCRN'][idx[-1]] == 1: optmodel.vEleFreqContReserveNorBid[idx].fix(0.0) if idx[-1] in model.egt: optmodel.vEleFreqContReserveNorUpGen[idx].fix(0.0) optmodel.vEleFreqContReserveNorDownGen[idx].fix(0.0) nFixedVariables += 2 if idx[-1] in model.egs: optmodel.vEleFreqContReserveNorUpCha[idx].fix(0.0) optmodel.vEleFreqContReserveNorUpDis[idx].fix(0.0) optmodel.vEleFreqContReserveNorDownCha[idx].fix(0.0) optmodel.vEleFreqContReserveNorDownDis[idx].fix(0.0) nFixedVariables += 4 elif model.Par['pEleGenNoFCRN'][idx[-1]] == 0 and model.Par['pEleGenNoDayAhead'][idx[-1]] == 0 and model.Par['pEleMaxPower'][idx[-1]][idx[:(len(idx) - 1)]] <= 1e-5 and model.Par['pEleGenV2G'][idx[-1]] == 1: optmodel.vEleTotalOutput2ndBlock[idx].fix(0.0) optmodel.vEleFreqContReserveNorDownDis[idx].fix(0.0) nFixedVariables += 2 elif model.Par['pEleGenNoFCRN'][idx[-1]] == 0 and model.Par['pEleGenNoDayAhead'][idx[-1]] == 0 and model.Par['pEleMaxPower'][idx[-1]][idx[:(len(idx) - 1)]] <= 1e-5 and model.Par['pEleGenV2G'][idx[-1]] == 0: optmodel.vEleTotalOutput2ndBlock[idx].fix(0.0) optmodel.vEleFreqContReserveNorUpDis[idx].fix(0.0) optmodel.vEleFreqContReserveNorDownDis[idx].fix(0.0) nFixedVariables += 2 # if there are no energy outflows no variable is needed iset = model.psn for ehs in model.ehs: if sum(model.Par[f'p{model.EnergyPrefix[ehs]}MaxOutflows'][ehs][idx] for idx in iset) == 0.0: for idx in iset: optmodel.__getattribute__(f'v{model.EnergyPrefix[ehs]}EnergyOutflows')[idx+(ehs,)].fix(0.0) nFixedVariables += 1 # fixing the voltage angle of the reference node for each scenario, period, and load level if model.Par['pOptIndBinSingleNode'] == 0: for p,sc,n in model.psn: optmodel.__getattribute__('vEleNetTheta')[p,sc,n,model.endrf.first()].fix(0.0) nFixedVariables += 1 # fixing the electricity and hydrogen imports/exports in nodes that are not reference nodes if model.Par['pOptIndBinSingleNode'] == 0: for idx in model.psnnd: if idx[-1] not in model.endrf: optmodel.__getattribute__('vEleImport')[idx].fix(0.0) optmodel.__getattribute__('vEleExport')[idx].fix(0.0) nFixedVariables += 2 if idx[-1] not in model.hndrf: optmodel.__getattribute__('vHydImport')[idx].fix(0.0) optmodel.__getattribute__('vHydExport')[idx].fix(0.0) nFixedVariables += 2 # fixing the ENS in nodes with no electricity and hydrogen demand in market for idx in model.psned: if model.Par['pVarMaxDemand'][idx[-1]][idx[:(len(idx)-1)]] == 0.0: optmodel.__getattribute__('vENS')[idx].fix(0.0) nFixedVariables += 1 for idx in model.psnhd: if model.Par['pVarMaxDemand'][idx[-1]][idx[:(len(idx)-1)]] == 0.0: optmodel.__getattribute__('vHNS')[idx].fix(0.0) nFixedVariables += 1 # remove power plants and lines not installed in this period for idx in model.psneg + model.psnhg: if idx[-1] not in model.AssetCand[idx[-1]] and (model.Par[f'p{model.EnergyPrefix[idx[-1]]}GenInitialPeriod'][idx[-1]] > model.Par['pParEconomicBaseYear'] or model.Par[f'p{model.EnergyPrefix[idx[-1]]}GenFinalPeriod'][idx[-1]] < model.Par['pParEconomicBaseYear']): optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}TotalOutput')[idx].fix(0.0) nFixedVariables += 1 for idx in model.psnegt + model.psnhgt: if idx[-1] not in model.AssetCand[idx[-1]] and (model.Par[f'p{model.EnergyPrefix[idx[-1]]}GenInitialPeriod'][idx[-1]] > model.Par['pParEconomicBaseYear'] or model.Par[f'p{model.EnergyPrefix[idx[-1]]}GenFinalPeriod'][idx[-1]] < model.Par['pParEconomicBaseYear']): optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}TotalOutput2ndBlock')[idx].fix(0.0) optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}GenCommitment')[idx].fix(0.0) optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}GenStartUp')[idx].fix(0.0) optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}GenShutDown')[idx].fix(0.0) nFixedVariables += 4 for idx in model.psnegs + model.psnhgs: if idx[-1] not in model.AssetCand[idx[-1]] and (model.Par[f'p{model.EnergyPrefix[idx[-1]]}GenInitialPeriod'][idx[-1]] > model.Par['pParEconomicBaseYear'] or model.Par[f'p{model.EnergyPrefix[idx[-1]]}GenFinalPeriod'][idx[-1]] < model.Par['pParEconomicBaseYear']): optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}TotalCharge')[idx].fix(0.0) optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}TotalCharge2ndBlock')[idx].fix(0.0) optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}Inventory')[idx].fix(0.0) optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}Spillage')[idx].fix(0.0) nFixedVariables += 4 for idx in model.psnela + model.psnhpa: if model.NetCand[idx[-3:]] == 'Ele': iset = model.elc # electricity lines elif model.NetCand[idx[-3:]] == 'Hyd': iset = model.hpc if idx[-3:] not in iset and (model.Par[f'p{model.NetCand[idx[-3:]]}NetInitialPeriod'][idx[-3:]] > model.Par['pParEconomicBaseYear'] or model.Par[f'p{model.NetCand[idx[-3:]]}NetFinalPeriod'][idx[-3:]] < model.Par['pParEconomicBaseYear']): optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}NetFlow')[idx].fix(0.0) nFixedVariables += 1 # fixing the initial committed electricity units based on the UpTimeZero and DownTimeZero for idx in model.psnegt: if model.Par[f'p{model.EnergyPrefix[idx[-1]]}GenUpTimeZero' ][idx[-1]] > 0 and model.n.ord(n) <= max(0,min(model.n.ord(n),(model.Par[f'p{model.EnergyPrefix[idx[-1]]}GenUpTime' ][idx[-1]]-model.Par[f'p{model.EnergyPrefix[idx[-1]]}GenUpTimeZero' ][idx[-1]]))): optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}GenCommitment')[idx].fix(1) nFixedVariables += 1 if model.Par[f'p{model.EnergyPrefix[idx[-1]]}GenDownTimeZero'][idx[-1]] > 0 and model.n.ord(n) <= max(0,min(model.n.ord(n),(model.Par[f'p{model.EnergyPrefix[idx[-1]]}GenDownTime'][idx[-1]]-model.Par[f'p{model.EnergyPrefix[idx[-1]]}GenDownTimeZero'][idx[-1]]))): optmodel.__getattribute__(f'v{model.EnergyPrefix[idx[-1]]}GenCommitment')[idx].fix(0) nFixedVariables += 1 # # fixing electricity buys in hours when electricity cost is equal o greater than 1000 # for idx in model.psner + model.psnhr: # if model.Par['pVarEnergyCost'][idx[-1]][idx[:(len(idx)-1)]] >= 1000.0: # optmodel.__getattribute__(f'v{model.RetailPrefix[idx[-1]]}Buy')[idx].fix(0.0) # nFixedVariables += 1 # if model.Par['pVarEnergyPrice'][idx[-1]][idx[:(len(idx)-1)]] <= 0: # optmodel.__getattribute__(f'v{model.RetailPrefix[idx[-1]]}Sell')[idx].fix(0.0) # nFixedVariables += 1 log_time('--- Fixing the variables', StartTime, ind_log=indlog) # detecting infeasibility: total min ESS output greater than total inflows, total max ESS charge lower than total outflows for es in model.egs: # if sum(model.Par['pEleMinPower'][es][idx] for idx in model.psn) - sum(model.Par['pEleMaxInflows'][es][idx] for idx in model.psn) > 0.0: # print('### Total minimum output greater than total inflows for Electricity ESS unit ', es) # assert(0==1) if sum(model.Par['pEleMaxCharge'][es][idx] for idx in model.psn) - sum(model.Par['pEleMaxOutflows'][es][idx] for idx in model.psn) < 0.0: print('### Total maximum charge lower than total outflows for Electricity ESS unit ', es) assert(0==1) for es in model.hgs: if sum(model.Par['pHydMinPower'][es][idx] for idx in model.psn) - sum(model.Par['pHydMaxInflows'][es][idx] for idx in model.psn) > 0.0: print('### Total minimum output greater than total inflows for Hydrogen ESS unit ', es) assert(0==1) if sum(model.Par['pHydMaxCharge'][es][idx] for idx in model.psn) - sum(model.Par['pHydMaxOutflows'][es][idx] for idx in model.psn) < 0.0: print('### Total maximum charge lower than total outflows for Hydrogen ESS unit ', es) assert(0==1) # detecting inventory infeasibility for idx in model.psnegs: if model.Par['pEleMaxCharge'][idx[-1]][idx[:(len(idx)-1)]] + model.Par['pEleMaxPower'][idx[-1]][idx[:(len(idx)-1)]] > 0.0: if model.n.ord(idx[-2]) == model.Par['pEleCycleTimeStep'][idx[-1]]: if model.Par['pEleInitialInventory'][idx[-1]][idx[:(len(idx)-1)]] + sum(model.Par['pDuration'][idx[:(len(idx)-2)]+(n2,)] * (model.Par['pEleMaxInflows'][idx[-1]][idx[:(len(idx)-2)]+(n2,)] - model.Par['pEleMinPower'][idx[-1]][idx[:(len(idx)-2)]+(n2,)] + model.Par['pEleGenEfficiency'][idx[-1]] * model.Par['pEleMaxCharge'][idx[-1]][idx[:(len(idx)-2)]+(n2,)]) for n2 in list(model.n2)[model.n.ord(idx[-2]) - model.Par['pEleCycleTimeStep'][idx[-1]]:model.n.ord(idx[-2])]) < model.Par['pEleMinStorage'][idx[-1]][idx[:(len(idx)-1)]]: print('### Inventory equation violation ', idx) assert(0==1) elif model.n.ord(idx[-2]) > model.Par['pEleCycleTimeStep'][idx[-1]]: if model.Par['pEleMaxStorage'][idx[-1]][idx[:(len(idx)-1)]] + sum(model.Par['pDuration'][idx[:(len(idx)-2)]+(n2,)] * (model.Par['pEleMaxInflows'][idx[-1]][idx[:(len(idx)-2)]+(n2,)] - model.Par['pEleMinPower'][idx[-1]][idx[:(len(idx)-2)]+(n2,)] + model.Par['pEleGenEfficiency'][idx[-1]] * model.Par['pEleMaxCharge'][idx[-1]][idx[:(len(idx)-2)]+(n2,)]) for n2 in list(model.n2)[model.n.ord(idx[-2]) - model.Par['pEleCycleTimeStep'][idx[-1]]:model.n.ord(idx[-2])]) < model.Par['pEleMinStorage'][idx[-1]][idx[:(len(idx)-1)]]: print('### Inventory equation violation ', idx) assert(0==1) log_time('--- Checking infeasibility', StartTime, ind_log=indlog) # # Fixing the shut down in the first 8 hours of every day # for idx in model.psnegt: # if model.Par['pEleGenCommitment'][idx[-1]] != 0 and model.n.ord(idx[-2]) % 24 < 10 and idx[-1] in model.hz: # optmodel.__getattribute__(f'vGenShutDown')[idx].fix(0.0) # optmodel.__getattribute__(f'vHydCommitment')[idx].fix(1.0) # nFixedVariables += 2 # identify if MaxStorage is equal to MinStorage for some ESS units for idx in model.psnegs: if model.n.ord(idx[-2]) > 1: prev_idx = idx[:(len(idx) - 2)] + (model.n.prev(idx[-2]),) if abs(model.Par['pEleMaxStorage'][idx[-1]][idx[:(len(idx)-1)]] - model.Par['pEleMinStorage'][idx[-1]][idx[:(len(idx)-1)]]) <= 1e-5 and abs(model.Par['pEleMaxStorage'][idx[-1]][prev_idx] - model.Par['pEleMinStorage'][idx[-1]][prev_idx]) <= 1e-5: # compare the pEleMaxStorage of the current time step with the one of the previous time step if model.Par['pEleMaxStorage'][idx[-1]][prev_idx] > model.Par['pEleMaxStorage'][idx[-1]][idx[:(len(idx)-1)]]: optmodel.__getattribute__(f'vEleEnergyOutflows')[idx].setub(model.Par['pEleMaxStorage'][idx[-1]][prev_idx] - model.Par['pEleMaxStorage'][idx[-1]][idx[:(len(idx)-1)]]) optmodel.__getattribute__(f'vEleEnergyOutflows')[idx].fix(model.Par['pEleMaxStorage'][idx[-1]][prev_idx] - model.Par['pEleMaxStorage'][idx[-1]][idx[:(len(idx)-1)]]) elif model.Par['pEleMaxStorage'][idx[-1]][prev_idx] < model.Par['pEleMaxStorage'][idx[-1]][idx[:(len(idx)-1)]]: optmodel.__getattribute__(f'vEleEnergyInflows')[idx].setub(model.Par['pEleMaxStorage'][idx[-1]][idx[:(len(idx)-1)]] - model.Par['pEleMaxStorage'][idx[-1]][prev_idx]) optmodel.__getattribute__(f'vEleEnergyInflows')[idx].fix(model.Par['pEleMaxStorage'][idx[-1]][idx[:(len(idx)-1)]] - model.Par['pEleMaxStorage'][idx[-1]][prev_idx]) # else: # optmodel.__getattribute__(f'vEleEnergyInflows')[idx].fix(0.0) # optmodel.__getattribute__(f'vEleEnergyOutflows')[idx].fix(0.0) # nFixedVariables += 2 else: if abs(model.Par['pEleMaxStorage'][idx[-1]][idx[:(len(idx)-1)]] - model.Par['pEleMinStorage'][idx[-1]][idx[:(len(idx)-1)]]) <= 1e-5: if model.Par['pEleInitialInventory'][idx[-1]][idx[:(len(idx)-1)]] > model.Par['pEleMaxStorage'][idx[-1]][idx[:(len(idx)-1)]]: optmodel.__getattribute__(f'vEleEnergyOutflows')[idx].setub(model.Par['pEleInitialInventory'][idx[-1]][idx[:(len(idx)-1)]] - model.Par['pEleMaxStorage'][idx[-1]][idx[:(len(idx)-1)]]) optmodel.__getattribute__(f'vEleEnergyOutflows')[idx].fix(model.Par['pEleInitialInventory'][idx[-1]][idx[:(len(idx)-1)]] - model.Par['pEleMaxStorage'][idx[-1]][idx[:(len(idx)-1)]]) elif model.Par['pEleInitialInventory'][idx[-1]][idx[:(len(idx)-1)]] < model.Par['pEleMaxStorage'][idx[-1]][idx[:(len(idx)-1)]]: optmodel.__getattribute__(f'vEleEnergyInflows')[idx].setub(model.Par['pEleMaxStorage'][idx[-1]][idx[:(len(idx)-1)]] - model.Par['pEleInitialInventory'][idx[-1]][idx[:(len(idx)-1)]]) optmodel.__getattribute__(f'vEleEnergyInflows')[idx].fix(model.Par['pEleMaxStorage'][idx[-1]][idx[:(len(idx)-1)]] - model.Par['pEleInitialInventory'][idx[-1]][idx[:(len(idx)-1)]]) # else: # optmodel.__getattribute__(f'vEleEnergyInflows')[idx].fix(0.0) # optmodel.__getattribute__(f'vEleEnergyOutflows')[idx].fix(0.0) # nFixedVariables += 2 model.nFixedVariables = Param(initialize=round(nFixedVariables), within=NonNegativeIntegers, doc='Number of fixed variables') return optmodel