Commit 47373711 authored by Niina Helistö's avatar Niina Helistö
Browse files

LP and MIP version for investment options implemented

parent 1540b964
......@@ -179,8 +179,11 @@ param_gnn "Set of possible data parameters for grid, node, node (nodal interconn
diffCoeff "Coefficients for energy diffusion between nodes"
boundStateOffset "Offset parameter for relatively bound node states"
boundStateMaxDiff "Maximum difference of node state pairs"
transferCapInvLimit "Capacity limit for investments"
transferCapInvLimit "Capacity limit for investments (MW)"
investMIP "Choice of making integer investment instead of continous investment (MW versus number of links)"
unitSize "Size of one link for integer investments (MW)"
invCost "Investment cost (€/MW)"
annuity "Investment annuity"
/
param_gnu "Set of possible data parameters for grid, node, unit" /
......@@ -195,6 +198,10 @@ param_gnu "Set of possible data parameters for grid, node, unit" /
maxGenCap "Maximum output capacity investment (MW)"
maxConsCap "Maximum loading capacity investment (MW)"
upperLimitCapacityRatio "Ratio of the upper limit of the node state and the unit capacity investment"
investMIP "Choice of making integer investment instead of continous investment (MW versus number of units)"
unitSize "Size of one unit for integer investments (MW)"
invCosts "Investment costs (€/MW)"
annuity "Investment annuity"
/
param_unit "Set of possible data parameters for units" /
......@@ -222,7 +229,6 @@ param_unit "Set of possible data parameters for units" /
level1 * level9 "Level of simplification in the part-load efficiency representation"
useTimeseries "Uses time series form input for unit parameters whenever possible"
section "Possibility to define a no load fuel use for units with zero minimum output"
invCosts "Investment costs (€/MW)"
/
param_fuel "Parameters for fuels" /
......
......@@ -23,6 +23,8 @@ Free variables
;
Integer variables
v_online(unit, f, t) "Number of units online for units with unit commitment restrictions"
v_investTransfer_MIP(grid, node, node) "Number of invested transfer links"
v_invest_MIP(grid, node, unit) "Number of invested generation units"
;
SOS2 variables
v_sos2(unit, f, t, effSelector) "Intermediate lambda variable for SOS2 based piece-wise linear efficiency curve"
......@@ -36,8 +38,8 @@ Positive variables
v_transfer(grid, node, node, f, t) "Average electricity transmission level from node to node during time period/slice (MW)"
v_resTransfer(restype, up_down, node, node, f, t) "Electricity transmission capacity from node to node reserved for providing reserves (MW)"
v_reserve(restype, up_down, node, unit, f, t) "Unit capacity reserved for providing reserve of specific type (MW)"
v_gnn(grid, node, node) "Invested transfer capacity (MW)"
v_gnu(grid, node, unit) "Invested energy generation capacity (MW)"
v_investTransfer_LP(grid, node, node) "Invested transfer capacity (MW)"
v_invest_LP(grid, node, unit) "Invested energy generation capacity (MW)"
;
* --- Feasibility control -----------------------------------------------------
......
......@@ -157,11 +157,19 @@ q_obj ..
)
)
)
// Unit investment costs
+ sum(gnu(grid, node, unit),
v_gnu(grid, node, unit) * p_unit(unit, 'invCosts')
+ v_invest_LP(grid, node, unit) * p_gnu(grid, node, unit, 'invCosts')
* p_gnu(grid, node, unit, 'annuity')
+ v_invest_MIP(grid, node, unit) * p_gnu(grid, node, unit, 'unitSize')
* p_gnu(grid, node, unit, 'invCosts') * p_gnu(grid, node, unit, 'annuity')
)
// Transfer link investment costs
+ sum(gn2n(grid, from_node, to_node),
v_gnn(grid, from_node, to_node) * p_gnn(grid, from_node, to_node, 'invCost')
+ v_investTransfer_LP(grid, from_node, to_node) * p_gnn(grid, from_node, to_node, 'invCost')
* p_gnn(grid, from_node, to_node, 'annuity')
+ v_investTransfer_MIP(grid, from_node, to_node) * p_gnn(grid, from_node, to_node, 'unitSize')
* p_gnn(grid, from_node, to_node, 'invCost') * p_gnn(grid, from_node, to_node, 'annuity')
)
;
......@@ -259,7 +267,8 @@ q_resTransfer(gn2n(grid, from_node, to_node), ft(f, t))${ sum(restypeDirection(r
)
=L=
+ p_gnn(grid, from_node, to_node, 'transferCap')
+ v_gnn(grid, from_node, to_node)
+ v_investTransfer_LP(grid, from_node, to_node)
+ v_investTransfer_MIP(grid, from_node, to_node) * p_gnn(grid, from_node, to_node, 'unitSize')
;
* -----------------------------------------------------------------------------
q_maxDownward(m, gnuft(grid, node, unit, f, t))${ [ ord(t) < tSolveFirst + mSettings(m, 't_reserveLength') // Unit is either providing
......@@ -287,11 +296,13 @@ q_maxDownward(m, gnuft(grid, node, unit, f, t))${ [ ord(t) < tSolveFirst + m
+ (p_effGroupUnit(effGroup, unit, 'lb')${not ts_effGroupUnit(effGroup, unit, 'lb', f, t)} + ts_effGroupUnit(effGroup, unit, 'lb', f, t))
)
+ v_gen.lo(grid, node, unit, f, t)$p_gnu(grid, node, unit, 'maxCons') // notice: v_gen.lo for consuming units is negative
- v_gnu(grid, node, unit)$p_gnu(grid, node, unit, 'maxConsCap') // notice: v_gnu also for consuming units is positive
- v_invest_LP(grid, node, unit)$p_gnu(grid, node, unit, 'maxConsCap') // notice: v_invest_LP also for consuming units is positive
- v_invest_MIP(grid, node, unit)$p_gnu(grid, node, unit, 'maxConsCap') // notice: v_invest_MIP also for consuming units is positive
* p_gnu(grid, node, unit, 'unitSize')
- v_online(unit, f+cf(f,t), t)${uft_online(unit, f, t) and p_gnu(grid, node, unit, 'maxCons')} // Online variables should only be generated for units with restrictions
/ p_unit(unit, 'unitCount')
* p_gnu(grid, node, unit, 'maxGen')
* Check what needs to be done for investment options and check why there is maxGen in the row above
* Check what needs to be done for investment options and check why there is maxGen in the row above: minimum load, ...
;
* -----------------------------------------------------------------------------
q_maxUpward(m, gnuft(grid, node, unit, f, t))${ [ ord(t) < tSolveFirst + mSettings(m, 't_reserveLength') // Unit is either providing
......@@ -319,16 +330,20 @@ q_maxUpward(m, gnuft(grid, node, unit, f, t))${ [ ord(t) < tSolveFirst + mSe
+ (p_effGroupUnit(effGroup, unit, 'lb')${not ts_effGroupUnit(effGroup, unit, 'lb', f, t)} + ts_effGroupUnit(effGroup, unit, 'lb', f, t))
)
+ v_gen.up(grid, node, unit, f, t)${not uft_online(unit, f, t) and p_gnu(grid, node, unit, 'maxGen')} // Generation units are restricted by their (online) capacity
+ (v_gnu(grid, node, unit) * p_unit(unit, 'availability'))${not unit_flow(unit) and p_gnu(grid, node, unit, 'maxGenCap')}
+ v_invest_LP(grid, node, unit)${not unit_flow(unit) and p_gnu(grid, node, unit, 'maxGenCap')}
* p_unit(unit, 'availability')
+ v_invest_MIP(grid, node, unit)${not unit_flow(unit) and p_gnu(grid, node, unit, 'maxGenCap')}
* p_gnu(grid, node, unit, 'unitSize')
* p_unit(unit, 'availability')
+ sum(flow$(flowUnit(flow, unit) and nu(node, unit) and unit_flow(unit) and p_gnu(grid, node, unit, 'maxGenCap')),
ts_cf_(flow, node, f, t) *
v_gnu(grid, node, unit) *
{v_invest_LP(grid, node, unit) + v_invest_MIP(grid, node, unit) * p_gnu(grid, node, unit, 'unitSize')} *
p_unit(unit, 'availability')
)
+ v_online(unit, f+cf(f,t), t)${uft_online(unit, f, t) and p_gnu(grid, node, unit, 'maxGen')} // Consuming units are restricted by their min. load (consuming is negative)
/ p_unit(unit, 'unitCount')
* p_gnu(grid, node, unit, 'maxGen')
* Check what needs to be done for investment options
* Check what needs to be done for investment options: online capacity restrictions for MIP, ...
;
* -----------------------------------------------------------------------------
q_startup(unit, ft_dynamic(f, t))${ uft_online(unit, f, t)
......@@ -462,7 +477,8 @@ q_stateUpwardLimit(gn_state(grid, node), m, ft_dynamic(f, t))$( sum(gn2gnu(gr
( // Utilizable headroom in the state variable
+ p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'useConstant') * p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'constant')
+ p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'useTimeSeries') * ts_nodeState(grid, node, 'upwardLimit', f, t)
+ sum{gnu(grid, node, unit), v_gnu(grid, node, unit) * p_gnu(grid, node, unit, 'upperLimitCapacityRatio')}
+ sum{gnu(grid, node, unit), v_invest_LP(grid, node, unit) * p_gnu(grid, node, unit, 'upperLimitCapacityRatio')}
+ sum{gnu(grid, node, unit), v_invest_MIP(grid, node, unit) * p_gnu(grid, node, unit, 'unitSize') * p_gnu(grid, node, unit, 'upperLimitCapacityRatio')}
- v_state(grid, node, f, t)
)
* ( // Accounting for the energyStoredPerUnitOfState ...
......@@ -604,16 +620,22 @@ q_bidirectionalTransfer(gn2n_bidirectional(grid, node, node_), ft(f, t))${p_gnn(
;
*-----------------------------------------------------------------------------
q_fixedGenCap(grid, node, unit, grid_, node_, unit_)${p_gnugnu(grid, node, unit, grid_, node_, unit_, 'capacityRatio')} ..
+ v_gnu(grid, node, unit)
+ v_invest_LP(grid, node, unit)
+ v_invest_MIP(grid, node, unit)
=E=
+ v_gnu(grid_, node_, unit_)
* p_gnugnu(grid, node, unit, grid_, node_, unit_, 'capacityRatio')
+ (
+ v_invest_LP(grid_, node_, unit_)
+ v_invest_MIP(grid_, node_, unit_)
)
* p_gnugnu(grid, node, unit, grid_, node_, unit_, 'capacityRatio')
;
*-----------------------------------------------------------------------------
q_symmetricTransferCap(gn2n(grid, from_node, to_node)) ..
+ v_gnn(grid, from_node, to_node)
+ v_investTransfer_LP(grid, from_node, to_node)
+ v_investTransfer_MIP(grid, from_node, to_node)
=E=
+ v_gnn(grid, to_node, from_node)
+ v_investTransfer_LP(grid, to_node, from_node)
+ v_investTransfer_MIP(grid, to_node, from_node)
;
......@@ -104,10 +104,34 @@ v_reserve.up(nuRescapable(restype, 'down', node, unit_elec), f+cf_nReserves(node
};
// Max capacity investment
v_gnu.up(gnu(grid, node, unit))$(p_gnu(grid, node, unit, 'maxGenCap') > 0) = p_gnu(grid, node, unit, 'maxGenCap');
v_gnu.up(gnu(grid, node, unit))$(p_gnu(grid, node, unit, 'maxConsCap') > 0) = p_gnu(grid, node, unit, 'maxConsCap');
v_gnu.fx(gnu(grid, node, unit))${not p_gnu(grid, node, unit, 'maxGenCap') and not p_gnu(grid, node, unit, 'maxConsCap')} = 0;
v_gnn.up(gn2n(grid, from_node, to_node)) = p_gnn(grid, from_node, to_node, 'transferCapInvLimit');
v_invest_LP.up(gnu(grid, node, unit))${ p_gnu(grid, node, unit, 'maxGenCap') > 0
and not p_gnu(grid, node, unit, 'investMIP')
} = p_gnu(grid, node, unit, 'maxGenCap');
v_invest_LP.up(gnu(grid, node, unit))${ p_gnu(grid, node, unit, 'maxConsCap') > 0
and not p_gnu(grid, node, unit, 'investMIP')
} = p_gnu(grid, node, unit, 'maxConsCap');
v_invest_LP.fx(gnu(grid, node, unit))${ [not p_gnu(grid, node, unit, 'maxGenCap')
and not p_gnu(grid, node, unit, 'maxConsCap')
] or p_gnu(grid, node, unit, 'investMIP')
} = 0;
v_invest_MIP.up(gnu(grid, node, unit))${ p_gnu(grid, node, unit, 'maxGenCap') > 0
and p_gnu(grid, node, unit, 'investMIP')
} = p_gnu(grid, node, unit, 'maxGenCap') / p_gnu(grid, node, unit, 'unitSize');
v_invest_MIP.up(gnu(grid, node, unit))${ p_gnu(grid, node, unit, 'maxConsCap') > 0
and p_gnu(grid, node, unit, 'investMIP')
} = p_gnu(grid, node, unit, 'maxConsCap') / p_gnu(grid, node, unit, 'unitSize');
v_invest_MIP.fx(gnu(grid, node, unit))${ [not p_gnu(grid, node, unit, 'maxGenCap')
and not p_gnu(grid, node, unit, 'maxConsCap')
] or not p_gnu(grid, node, unit, 'investMIP')
} = 0;
v_investTransfer_LP.up(gn2n(grid, from_node, to_node))${not p_gnn(grid, from_node, to_node, 'investMIP')
} = p_gnn(grid, from_node, to_node, 'transferCapInvLimit');
v_investTransfer_LP.fx(gn2n(grid, from_node, to_node))${p_gnn(grid, from_node, to_node, 'investMIP')
} = 0;
v_investTransfer_MIP.up(gn2n(grid, from_node, to_node))${p_gnn(grid, from_node, to_node, 'investMIP')
} = p_gnn(grid, from_node, to_node, 'transferCapInvLimit') / p_gnn(grid, from_node, to_node, 'unitSize');
v_investTransfer_MIP.fx(gn2n(grid, from_node, to_node))${not p_gnn(grid, from_node, to_node, 'investMIP')
} = 0;
// Fix reserves between t_jump and gate_closure based on previous allocations
loop(restypeDirectionNode(restypeDirection(restype, up_down), node),
* if ([not mod(tSolveFirst-1, p_nReserves(node, restype, 'update_frequency')) and not tSolveFirst = mSettings(mSolve, 't_start')],
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment