From 2b690a8f1338576bb7012441d91a6f347c6c2ed0 Mon Sep 17 00:00:00 2001 From: Niina Helisto Date: Tue, 19 Oct 2021 14:37:35 +0300 Subject: [PATCH] Updating 'annual' energy constraints From user perspective: - Deleting the p_groupPolicy(group, 'energyMaxVgenSign') parameter. For a minimum energy constraint, the user should now add a positive p_groupPolicy(group, 'energyMin'). - For constraints with p_groupPolicy(group, 'energyShareMax') or p_groupPolicy(group, 'energyShareMin'), the user should now also add the consumption units to be considered in the constraint to gnuGroup. Previously they were automatically considered if they connected to nodes in gnGroup. This was problematic for storage units. From model code perspective: - Rearranging q_energyMax(group), q_energyShareMax(group), and q_energyShareMin(group) constraints to q_energyLimit(group, min_max) and q_energyShareLimit(group, min_max) constraints. Issue #157 --- defModels/building.gms | 5 +- defModels/invest.gms | 5 +- defModels/schedule.gms | 5 +- defOutput/debugSymbols.inc | 4 +- inc/1a_definitions.gms | 10 ++-- inc/2b_eqDeclarations.gms | 5 +- inc/2d_constraints.gms | 105 ++++++++++++++++--------------------- inc/3b_periodicLoop.gms | 5 +- 8 files changed, 61 insertions(+), 83 deletions(-) diff --git a/defModels/building.gms b/defModels/building.gms index 03ad99d9..c0d742cc 100644 --- a/defModels/building.gms +++ b/defModels/building.gms @@ -83,9 +83,8 @@ Model building / * q_capacityMargin * q_constrainedCapMultiUnit * q_emissioncap -* q_energyMax -* q_energyShareMax -* q_energyShareMin +* q_energyLimit +* q_energyShareLimit * q_ReserveShareMax $ifthen exist '%input_dir%/building_additional_constraints.gms' diff --git a/defModels/invest.gms b/defModels/invest.gms index e435920d..2de1a6e7 100644 --- a/defModels/invest.gms +++ b/defModels/invest.gms @@ -91,9 +91,8 @@ Model invest / q_capacityMargin q_constrainedCapMultiUnit q_emissioncap - q_energyMax - q_energyShareMax - q_energyShareMin + q_energyLimit + q_energyShareLimit q_ReserveShareMax $ifthen exist '%input_dir%/invest_additional_constraints.gms' diff --git a/defModels/schedule.gms b/defModels/schedule.gms index c75243f2..305ac6da 100644 --- a/defModels/schedule.gms +++ b/defModels/schedule.gms @@ -83,9 +83,8 @@ Model schedule / q_capacityMargin * q_constrainedCapMultiUnit * q_emissioncap -* q_energyMax -* q_energyShareMax -* q_energyShareMin +* q_energyLimit +* q_energyShareLimit q_ReserveShareMax $ifthen exist '%input_dir%/schedule_additional_constraints.gms' diff --git a/defOutput/debugSymbols.inc b/defOutput/debugSymbols.inc index 5442b8d5..83147bbd 100644 --- a/defOutput/debugSymbols.inc +++ b/defOutput/debugSymbols.inc @@ -157,8 +157,8 @@ v_help_inc q_capacityMargin q_constrainedCapMultiUnit q_emissioncap - q_energyShareMax - q_energyShareMin + q_energyLimit + q_energyShareLimit q_ReserveShareMax * Dummy variables diff --git a/inc/1a_definitions.gms b/inc/1a_definitions.gms index 23f27914..65fe4ee6 100644 --- a/inc/1a_definitions.gms +++ b/inc/1a_definitions.gms @@ -265,7 +265,7 @@ param_gnn "Set of possible data parameters for grid, node, node (nodal interconn variableTransCost "Variable cost applied to transfers (EUR/MW)" availability "Availability of the interconnection (p.u.)" useTimeseriesAvailability "A flag to use time series form input for availability" - useTimeseriesLoss "A flag to use time series form input for transferLoss" + useTimeseriesLoss "A flag to use time series form input for transferLoss" / param_gnu "Set of possible data parameters for grid, node, unit" / @@ -360,10 +360,10 @@ param_policy "Set of possible data parameters for groups or grid, node, regulati emissionTax "Emission tax (EUR/tonne)" emissionCap "Emission limit (tonne)" instantaneousShareMax "Maximum instantaneous share of generation and import from a particular group of units and transfer links" - energyMax "Maximum energy production or consumption from a particular group of units over samples" - energyMaxVgenSign "Sign for v_gen in the maximum energy constraint - use -1 when you need a minimum energy constraint (then also energyMax should be negative)" - energyShareMax "Maximum energy share of generation from a particular group of units" - energyShareMin "Minimum energy share of generation from a particular group of units" + energyMax "Maximum energy production or consumption from particular grid-node-units over particular samples" + energyMin "Minimum energy production or consumption from particular grid-node-units over particular samples" + energyShareMax "Maximum share of energy production from particular grid-node-units over particular samples" + energyShareMin "Minimum share of energy production from particular grid-node-units over particular samples" constrainedCapMultiplier "Multiplier a(i) for unit investments in equation Sum(i, a(i)*v_invest(i)) <= b" constrainedCapTotalMax "Total maximum b for unit investments in equation Sum(i, a(i)*v_invest(i)) <= b" constrainedOnlineMultiplier "Multiplier a(i) for online units in equation Sum(i, a(i)*v_online(i)) <= b" diff --git a/inc/2b_eqDeclarations.gms b/inc/2b_eqDeclarations.gms index c9ae8a82..05a9db43 100644 --- a/inc/2b_eqDeclarations.gms +++ b/inc/2b_eqDeclarations.gms @@ -125,8 +125,7 @@ equations q_capacityMargin(grid, node, s, f, t) "There needs to be enough capacity to cover energy demand plus a margin" q_constrainedCapMultiUnit(group) "Constrained unit number ratios and sums for a group of units" q_emissioncap(group, emission) "Limit for emissions" - q_energyMax(group) "Maximum energy production or consumption from a group of units" - q_energyShareMax(group) "Maximum energy share of generation and import from a group of units" - q_energyShareMin(group) "Minimum energy share of generation and import from a group of units" + q_energyLimit(group, min_max) "Limited energy production or consumption from a group of units" + q_energyShareLimit(group, min_max) "Limited share of energy production from a group of units" q_ReserveShareMax(group, restype, up_down, group, s, f, t) "Maximum reserve share of a group of units" ; diff --git a/inc/2d_constraints.gms b/inc/2d_constraints.gms index 31e1d83e..bdd649ac 100644 --- a/inc/2d_constraints.gms +++ b/inc/2d_constraints.gms @@ -3149,19 +3149,20 @@ q_emissioncap(group, emission) + p_groupPolicyEmission(group, 'emissionCap', emission) ; -*--- Maximum Energy ----------------------------------------------------------- - -q_energyMax(group) - ${ p_groupPolicy(group, 'energyMax') +*--- Limited Energy ----------------------------------------------------------- +* Limited energy production or consumption from particular grid-node-units over +* particular samples. Both production and consumption units to be considered in +* the constraint are defined in gnuGroup. Samples are defined in sGroup. + +q_energyLimit(group, min_max) + ${ (sameas(min_max, 'max') and p_groupPolicy(group, 'energyMax')) + or (sameas(min_max, 'min') and p_groupPolicy(group, 'energyMin')) } .. + [ + sum(msft(m, s, f, t)${sGroup(s, group)}, + p_msft_Probability(m,s,f,t) * p_stepLength(m, f, t) - * [ - + 1${not p_groupPolicy(group, 'energyMaxVgenSign')} - + p_groupPolicy(group, 'energyMaxVgenSign') // Multiply by -1 in order to convert to minimum energy constraint - ] * [ // Production of units in the group + sum(gnu_output(grid, node, unit)${ gnuGroup(grid, node, unit, group) @@ -3177,56 +3178,33 @@ q_energyMax(group) ) // END sum(gnu) ] // END * p_stepLength ) // END sum(msft) - - =L= - - + p_groupPolicy(group, 'energyMax') // Use negative energyMax value if you need a "minimum energy" equation -; - -*--- Maximum Energy Share ----------------------------------------------------- - -q_energyShareMax(group) - ${ p_groupPolicy(group, 'energyShareMax') - } .. - - + sum(msft(m, s, f, t)${sGroup(s, group)}, - + p_msft_Probability(m,s,f,t) - * p_stepLength(m, f, t) - * [ - // Generation of units in the group - + sum(gnu_output(grid, node, unit)${ gnuGroup(grid, node, unit, group) - and p_gnu(grid, node, unit, 'unitSize') - and gnGroup(grid, node, group) - and gnuft(grid, node, unit, f, t) - }, - + v_gen(grid, node, unit, s, f, t) - ) // END sum(gnu) - - // External power inflow/outflow and consumption of units times the maximum share - - p_groupPolicy(group, 'energyShareMax') - * [ - - sum(gnGroup(grid, node, group), - + ts_influx_(grid, node, s, f, t) - ) // END sum(gnGroup) - - sum(gnu_input(grid, node, unit)${ p_gnu(grid, node, unit, 'unitSize') - and gnGroup(grid, node, group) - and gnuft(grid, node, unit, f, t) - }, - + v_gen(grid, node, unit, s, f, t) - ) // END sum(gnu_input) - ] // END * p_groupPolicy - ] // END * p_stepLength - ) // END sum(msft) + - [ + + p_groupPolicy(group, 'energyMax')$sameas(min_max, 'max') + + p_groupPolicy(group, 'energyMin')$sameas(min_max, 'min') + ] + ] // END [sum(msft) - p_groupPolicy] + * [ + // Convert to greater than constraint for 'min' case + + 1$sameas(min_max, 'max') + - 1$sameas(min_max, 'min') + ] // END * [sum(msft) - p_groupPolicy] =L= 0 ; -*--- Minimum Energy Share ----------------------------------------------------- +*--- Limited Energy Share ----------------------------------------------------- +* Limited share of energy production from particular grid-node-units over +* particular samples and based on consumption calculated from influx in +* particular grid-nodes plus consumption of particular grid-node-units. Both +* production and consumption units to be considered in the constraint are +* defined in gnuGroup. Samples are defined in sGroup and influx nodes in +* gnGroup. -q_energyShareMin(group) - ${ p_groupPolicy(group, 'energyShareMin') +q_energyShareLimit(group, min_max) + ${ (sameas(min_max, 'max') and p_groupPolicy(group, 'energyShareMax')) + or (sameas(min_max, 'min') and p_groupPolicy(group, 'energyShareMin')) } .. + sum(msft(m, s, f, t)${sGroup(s, group)}, @@ -3235,30 +3213,35 @@ q_energyShareMin(group) * [ // Generation of units in the group + sum(gnu_output(grid, node, unit)${ gnuGroup(grid, node, unit, group) - and p_gnu(grid, node, unit, 'unitSize') - and gnGroup(grid, node, group) and gnuft(grid, node, unit, f, t) }, - + v_gen(grid, node, unit, s, f, t) + + v_gen(grid, node, unit, s, f, t) // production is taken into account if the grid-node-unit is in gnuGroup ) // END sum(gnu) - // External power inflow/outflow and consumption of units times the maximum share - - p_groupPolicy(group, 'energyShareMin') + // External power inflow/outflow and consumption of units times the share limit + - [ + + p_groupPolicy(group, 'energyShareMax')$sameas(min_max, 'max') + + p_groupPolicy(group, 'energyShareMin')$sameas(min_max, 'min') + ] * [ - sum(gnGroup(grid, node, group), - + ts_influx_(grid, node, s, f, t) + + ts_influx_(grid, node, s, f, t) // influx is taken into account if the node is in gnGroup ) // END sum(gnGroup) - - sum(gnu_input(grid, node, unit)${ p_gnu(grid, node, unit, 'unitSize') - and gnGroup(grid, node, group) + - sum(gnu_input(grid, node, unit)${ gnuGroup(grid, node, unit, group) and gnuft(grid, node, unit, f, t) }, - + v_gen(grid, node, unit, s, f, t) + + v_gen(grid, node, unit, s, f, t) // consumption is taken into account if the grid-node-unit is in gnuGroup ) // END sum(gnu_input) ] // END * p_groupPolicy ] // END * p_stepLength ) // END sum(msft) + * [ + // Convert to greater than constraint for 'min' case + + 1$sameas(min_max, 'max') + - 1$sameas(min_max, 'min') + ] // END * sum(msft) - =G= + =L= 0 ; diff --git a/inc/3b_periodicLoop.gms b/inc/3b_periodicLoop.gms index 8e3abc34..43c70a30 100644 --- a/inc/3b_periodicLoop.gms +++ b/inc/3b_periodicLoop.gms @@ -124,9 +124,8 @@ Option clear = q_constrainedOnlineMultiUnit; Option clear = q_capacityMargin; Option clear = q_constrainedCapMultiUnit; Option clear = q_emissioncap; -Option clear = q_energyMax; -Option clear = q_energyShareMax; -Option clear = q_energyShareMin; +Option clear = q_energyLimit; +Option clear = q_energyShareLimit; Option clear = q_ReserveShareMax; * --- Temporary Time Series --------------------------------------------------- -- GitLab