Commit 0b2de1ef authored by jussi ikäheimo's avatar jussi ikäheimo
Browse files

Added boundstart and boundend for superposed nodes. Added self-discharge loss.

parent 1f51eb63
...@@ -77,7 +77,8 @@ Model invest / ...@@ -77,7 +77,8 @@ Model invest /
q_boundCyclic q_boundCyclic
// superpositioned state variables // superpositioned state variables
q_superposBegin q_superposSampleBegin
q_superposBoundEnd
q_superposInter q_superposInter
q_superposStateMax q_superposStateMax
q_superposStateMin q_superposStateMin
......
...@@ -54,6 +54,7 @@ Sets ...@@ -54,6 +54,7 @@ Sets
onlyExistingForecasts "Use only existing forecast values when reading updated forecasts. Note: zero values need to be saved as Eps in the gdx file." onlyExistingForecasts "Use only existing forecast values when reading updated forecasts. Note: zero values need to be saved as Eps in the gdx file."
scenarios "Number of long-term scenarios used" scenarios "Number of long-term scenarios used"
scenarioLength "Length of scenario in time steps for creating stochastic scenarios from time series data" scenarioLength "Length of scenario in time steps for creating stochastic scenarios from time series data"
candidate_periods "Number of candidate periods which are mapped to typical periods"
// Features // Features
t_trajectoryHorizon "Length of the horizon when start-up and shutdown trajectories are considered (in time steps)" t_trajectoryHorizon "Length of the horizon when start-up and shutdown trajectories are considered (in time steps)"
......
...@@ -110,7 +110,8 @@ equations ...@@ -110,7 +110,8 @@ equations
q_boundCyclic(grid, node, s, s, mType) "Cyclic node state bound for the first and the last states of samples" q_boundCyclic(grid, node, s, s, mType) "Cyclic node state bound for the first and the last states of samples"
// superpositioned state variables // superpositioned state variables
q_superposBegin(grid, node, mType, s) q_superposSampleBegin(grid, node, mType, s)
q_superposBoundEnd(grid, node, mType)
q_superposInter(grid, node, mType,z) q_superposInter(grid, node, mType,z)
q_superposStateMax(grid, node, mType, s, f, t) q_superposStateMax(grid, node, mType, s, f, t)
q_superposStateMin(grid, node, mType, s, f, t) q_superposStateMin(grid, node, mType, s, f, t)
......
...@@ -2261,9 +2261,22 @@ q_stateSlack(gn_stateSlack(grid, node), slack, sft(s, f, t)) ...@@ -2261,9 +2261,22 @@ q_stateSlack(gn_stateSlack(grid, node), slack, sft(s, f, t))
* --- Upwards Limit for State Variables --------------------------------------- * --- Upwards Limit for State Variables ---------------------------------------
q_stateUpwardLimit(gn_state(grid, node), msft(m, s, f, t)) q_stateUpwardLimit(gn_state(grid, node), msft(m, s, f, t))
${ sum(gn2gnu(grid, node, grid_, node_output, unit)$(sum(restype, gnuRescapable(restype, 'down', grid_, node_output, unit))), 1) // nodes that have units with endogenous output with possible reserve provision ${ not node_superpos(node)
or sum(gn2gnu(grid_, node_input, grid, node, unit)$(sum(restype, gnuRescapable(restype, 'down', grid_, node_input , unit))), 1) // or nodes that have units with endogenous input with possible reserve provision and
or sum(gnu(grid, node, unit), p_gnu(grid, node, unit, 'upperLimitCapacityRatio')) // or nodes that have units whose invested capacity limits their state {
sum(gn2gnu(grid, node, grid_, node_output, unit)
$(sum(restype, gnuRescapable(restype, 'down', grid_, node_output, unit))),
1
) // nodes that have units with endogenous output with possible reserve provision
or
sum(gn2gnu(grid_, node_input, grid, node, unit)
$(sum(restype, gnuRescapable(restype, 'down', grid_, node_input , unit))),
1) // or nodes that have units with endogenous input with possible reserve provision
or
sum(gnu(grid, node, unit),
p_gnu(grid, node, unit, 'upperLimitCapacityRatio')
) // or nodes that have units whose invested capacity limits their state
}
} .. } ..
// Utilizable headroom in the state variable // Utilizable headroom in the state variable
...@@ -2340,9 +2353,17 @@ q_stateUpwardLimit(gn_state(grid, node), msft(m, s, f, t)) ...@@ -2340,9 +2353,17 @@ q_stateUpwardLimit(gn_state(grid, node), msft(m, s, f, t))
* --- Downwards Limit for State Variables ------------------------------------- * --- Downwards Limit for State Variables -------------------------------------
q_stateDownwardLimit(gn_state(grid, node), msft(m, s, f, t)) q_stateDownwardLimit(gn_state(grid, node), msft(m, s, f, t))
${ sum(gn2gnu(grid, node, grid_, node_output, unit)$(sum(restype, gnuRescapable(restype, 'up', grid_, node_output, unit))), 1) // nodes that have units with endogenous output with possible reserve provision ${ //ordinary nodes with no superpositioning of state
or sum(gn2gnu(grid_, node_input, grid, node, unit) $(sum(restype, gnuRescapable(restype, 'up', grid_, node_input , unit))), 1) // or nodes that have units with endogenous input with possible reserve provision not node_superpos(node)
} .. and
{
// nodes that have units with endogenous output with possible reserve provision
sum(gn2gnu(grid, node, grid_, node_output, unit)$(sum(restype, gnuRescapable(restype, 'up', grid_, node_output, unit))), 1)
or
// or nodes that have units with endogenous input with possible reserve provision
sum(gn2gnu(grid_, node_input, grid, node, unit) $(sum(restype, gnuRescapable(restype, 'up', grid_, node_input , unit))), 1)
}
}..
// Utilizable headroom in the state variable // Utilizable headroom in the state variable
+ [ + [
...@@ -2545,7 +2566,10 @@ q_boundCyclic(gnss_bound(gn_state(grid, node), s_, s), m) ...@@ -2545,7 +2566,10 @@ q_boundCyclic(gnss_bound(gn_state(grid, node), s_, s), m)
*--- Intra-period state for superpositioned states ---------------------------- *--- Intra-period state for superpositioned states ----------------------------
q_superposBegin(gn_state(grid, node_superpos(node)), m, s) * v_state for superpositioned states represents the intra-period state. It
* always starts from zero.
q_superposSampleBegin(gn_state(grid, node_superpos(node)), m, s)
${ ms(m, s) ${ ms(m, s)
}.. }..
...@@ -2559,17 +2583,61 @@ q_superposBegin(gn_state(grid, node_superpos(node)), m, s) ...@@ -2559,17 +2583,61 @@ q_superposBegin(gn_state(grid, node_superpos(node)), m, s)
=E= 0 =E= 0
; ;
q_superposBoundEnd(gn_state(grid, node_superpos(node)), m)
$(p_gn(grid, node, 'boundEnd') )..
// Value of the superposed state of the node at the end of the last candidate
// period
sum(mz(m,z)$(ord(z) eq mSettings('invest', 'candidate_periods') ),
//the inter-period state at the beginning of the last candidate period
v_state_z(grid, node, z)
+
//change of the intra-period state during the representative period
sum(zs(z, s_),
// State of the node at the end of the sample s_
+ sum(mst_end(m, s_, t),
+ sum(sft(s_, f, t),
+ v_state(grid, node, s_, f, t)
) // END sum(ft)
) // END sum(mst_end)
// State of the node at the start of the sample s_
- sum(mst_start(m, s_, t),
sum(sft(s_, f, t),
+ v_state(grid, node, s_, f+df(f,t+dt(t)), t+dt(t))
) // END sum(ft)
) // END sum(mst_start)
) // end sum(zs)
)
=E=
p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'constant')
* p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'multiplier')
;
*--- Inter-period state dynamic equation for superpositioned states ----------- *--- Inter-period state dynamic equation for superpositioned states -----------
q_superposInter(gn_state(grid, node_superpos(node)), mz(m,z)) q_superposInter(gn_state(grid, node_superpos(node)), mz(m,z))
${ ord(z) > 1 ${ ord(z) > 1
}.. }..
// State of the node at the beginning of period z // Inter-period state of the node at the beginning of period z
v_state_z(grid, node, z) v_state_z(grid, node, z)
=E= =E=
// State of the node at the beginning of previous period z-1
v_state_z(grid, node, z-1) v_state_z(grid, node, z-1)
*
//multiplied by the self discharge loss over the period
sum(zs(z-1, s_),
power(1 - mSettings(m, 'stepLengthInHours')
* p_gn(grid, node, 'selfDischargeLoss'),
msEnd(m,s_) - msStart(m,s_) )
)
+ +
//change of the intra-period state during the representative period
sum(zs(z-1, s_), sum(zs(z-1, s_),
// State of the node at the end of the sample s_ // State of the node at the end of the sample s_
+ sum(mst_end(m, s_, t), + sum(mst_end(m, s_, t),
......
...@@ -19,89 +19,89 @@ $offtext ...@@ -19,89 +19,89 @@ $offtext
* --- Variable limits --------------------------------------------------------- * --- Variable limits ---------------------------------------------------------
* ============================================================================= * =============================================================================
* =============================================================================
* --- Node State Boundaries --------------------------------------------------- * --- Node State Boundaries ---------------------------------------------------
* =============================================================================
// When using constant values and to supplement time series with constant values (time series will override when data available) // state limits for normal (not superposed) nodes
// Upper bound loop(node$(not node_superpos(node)),
v_state.up(gn_state(grid, node), sft(s, f, t))${ p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'useConstant')
// When using constant values and to supplement time series with constant values (time series will override when data available)
// Upper bound
v_state.up(gn_state(grid, node), sft(s, f, t))${p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'useConstant')
and not df_central(f,t) and not df_central(f,t)
and not node_superpos(node)
} }
= p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'constant') = p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'constant')
* p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'multiplier') * p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'multiplier')
; ;
// Lower bound // Lower bound
v_state.lo(gn_state(grid, node), sft(s, f, t))${ p_gnBoundaryPropertiesForStates(grid, node, 'downwardLimit', 'useConstant') v_state.lo(gn_state(grid, node), sft(s, f, t))${p_gnBoundaryPropertiesForStates(grid, node, 'downwardLimit', 'useConstant')
and not df_central(f,t) and not df_central(f,t)
and not node_superpos(node)
} }
= p_gnBoundaryPropertiesForStates(grid, node, 'downwardLimit', 'constant') = p_gnBoundaryPropertiesForStates(grid, node, 'downwardLimit', 'constant')
* p_gnBoundaryPropertiesForStates(grid, node, 'downwardLimit', 'multiplier') * p_gnBoundaryPropertiesForStates(grid, node, 'downwardLimit', 'multiplier')
; ;
// Fixed value // Fixed value
v_state.fx(gn_state(grid, node), sft(s, f, t))${ p_gn(grid, node, 'boundAll') v_state.fx(gn_state(grid, node), sft(s, f, t))${p_gn(grid, node, 'boundAll')
and p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'useConstant') and p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'useConstant')
and not df_central(f,t) and not df_central(f,t)
and not node_superpos(node)
} }
= p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'constant') = p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'constant')
* p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'multiplier') * p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'multiplier')
; ;
// BoundEnd to a constant value // BoundEnd to a constant value
v_state.fx(gn_state(grid, node), sft(s, f,t))${ mft_lastSteps(mSolve, f, t) v_state.fx(gn_state(grid, node), sft(s, f,t))${ mft_lastSteps(mSolve, f, t)
and p_gn(grid, node, 'boundEnd') and p_gn(grid, node, 'boundEnd')
and p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'useConstant') and p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'useConstant')
and not node_superpos(node)
} }
= p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'constant') = p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'constant')
* p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'multiplier'); * p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'multiplier');
// When using time series // When using time series
// Upper Bound // Upper Bound
v_state.up(gn_state(grid, node), sft(s, f, t))${ p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'useTimeSeries') v_state.up(gn_state(grid, node), sft(s, f, t))${p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'useTimeSeries')
and not df_central(f,t) and not df_central(f,t)
and not node_superpos(node)
} }
= ts_node_(grid, node, 'upwardLimit', s, f, t) = ts_node_(grid, node, 'upwardLimit', s, f, t)
* p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'multiplier') * p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'multiplier')
; ;
// Lower bound // Lower bound
v_state.lo(gn_state(grid, node), sft(s, f, t))${ p_gnBoundaryPropertiesForStates(grid, node, 'downwardLimit', 'useTimeSeries') v_state.lo(gn_state(grid, node), sft(s, f, t))${p_gnBoundaryPropertiesForStates(grid, node, 'downwardLimit', 'useTimeSeries')
and not df_central(f,t) and not df_central(f,t)
and not node_superpos(node)
} }
= ts_node_(grid, node, 'downwardLimit', s, f, t) = ts_node_(grid, node, 'downwardLimit', s, f, t)
* p_gnBoundaryPropertiesForStates(grid, node, 'downwardLimit', 'multiplier') * p_gnBoundaryPropertiesForStates(grid, node, 'downwardLimit', 'multiplier')
; ;
// Fixed value // Fixed value
v_state.fx(gn_state(grid, node), sft(s, f, t))${ p_gn(grid, node, 'boundAll') v_state.fx(gn_state(grid, node), sft(s, f, t))${p_gn(grid, node, 'boundAll')
and p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'useTimeSeries') and p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'useTimeSeries')
and not df_central(f,t) and not df_central(f,t)
and not node_superpos(node)
} }
= ts_node_(grid, node, 'reference', s, f, t) = ts_node_(grid, node, 'reference', s, f, t)
* p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'multiplier') * p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'multiplier')
; ;
// BoundEnd to a timeseries value // BoundEnd to a timeseries value
v_state.fx(gn_state(grid, node), sft(s, f,t))${ mft_lastSteps(mSolve, f, t) v_state.fx(gn_state(grid, node), sft(s, f,t))${mft_lastSteps(mSolve, f, t)
and p_gn(grid, node, 'boundEnd') and p_gn(grid, node, 'boundEnd')
and p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'useTimeSeries') and p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'useTimeSeries')
and not node_superpos(node)
} }
= ts_node_(grid, node, 'reference', s, f, t) = ts_node_(grid, node, 'reference', s, f, t)
* p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'multiplier'); * p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'multiplier');
// BoundStartToEnd: bound the last interval in the horizon to the value just before the horizon // BoundStartToEnd: bound the last interval in the horizon to the value just before the horizon
v_state.fx(gn_state(grid, node), sft(s, f, t))${ mft_lastSteps(mSolve, f, t) v_state.fx(gn_state(grid, node), sft(s, f, t))${mft_lastSteps(mSolve, f, t)
and p_gn(grid, node, 'boundStartToEnd') and p_gn(grid, node, 'boundStartToEnd')
and not node_superpos(node)
} }
= sum(mf_realization(mSolve, f_), = sum(mf_realization(mSolve, f_),
+ r_state(grid, node, f_, tSolve) + r_state(grid, node, f_, tSolve)
); // END sum(mf_realization) ); // END sum(mf_realization)
loop(mst_start(mSolve, s, t)$(tSolveFirst = mSettings(mSolve, 't_start')),
// Bound also the intervals just before the start of each sample - currently just 'upwardLimit'&'useConstant' and 'downwardLimit'&'useConstant' // Bound also the intervals just before the start of each sample - currently just 'upwardLimit'&'useConstant' and 'downwardLimit'&'useConstant'
loop(mst_start(mSolve, s, t)$(tSolveFirst = mSettings(mSolve, 't_start')),
// Upper bound // Upper bound
v_state.up(gn_state(grid, node), s, f_solve, t+dt(t))${ p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'useConstant') v_state.up(gn_state(grid, node), s, f_solve, t+dt(t))${ p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'useConstant')
and not df_central(f_solve,t) and not df_central(f_solve,t)
...@@ -117,9 +117,22 @@ loop(mst_start(mSolve, s, t)$(tSolveFirst = mSettings(mSolve, 't_start')), ...@@ -117,9 +117,22 @@ loop(mst_start(mSolve, s, t)$(tSolveFirst = mSettings(mSolve, 't_start')),
} }
= p_gnBoundaryPropertiesForStates(grid, node, 'downwardLimit', 'constant') = p_gnBoundaryPropertiesForStates(grid, node, 'downwardLimit', 'constant')
* p_gnBoundaryPropertiesForStates(grid, node, 'downwardLimit', 'multiplier'); * p_gnBoundaryPropertiesForStates(grid, node, 'downwardLimit', 'multiplier');
); // END loop(mst_start) ); // END loop(mst_start)
); //end loop node
// Next deal with bounds for the superposed node states
// note that boundstart is handled further below
loop(node_superpos(node),
//add here the desired bounds for v_state_z
);
* =============================================================================
* --- Spilling of energy from the nodes----------------------------------------
* =============================================================================
// Spilling of energy from the nodes
// Max. & min. spilling, use constant value as base and overwrite with time series if desired // Max. & min. spilling, use constant value as base and overwrite with time series if desired
v_spill.lo(gn(grid, node_spill), sft(s, f, t))${ p_gnBoundaryPropertiesForStates(grid, node_spill, 'minSpill', 'constant') } v_spill.lo(gn(grid, node_spill), sft(s, f, t))${ p_gnBoundaryPropertiesForStates(grid, node_spill, 'minSpill', 'constant') }
= p_gnBoundaryPropertiesForStates(grid, node_spill, 'minSpill', 'constant') = p_gnBoundaryPropertiesForStates(grid, node_spill, 'minSpill', 'constant')
...@@ -469,9 +482,12 @@ v_investTransfer_MIP.up(gn2n_directional(grid, from_node, to_node), t_invest)${ ...@@ -469,9 +482,12 @@ v_investTransfer_MIP.up(gn2n_directional(grid, from_node, to_node), t_invest)${
// Loop over the start intervals // Loop over the start intervals
loop((mft_start(mSolve, f, t), ms_initial(mSolve, s)), loop((mft_start(mSolve, f, t), ms_initial(mSolve, s)),
// If this is the very first solve, set boundStart // If this is the very first solve, set various initial bounds
if(tSolveFirst = mSettings(mSolve, 't_start'), if(tSolveFirst = mSettings(mSolve, 't_start'),
// state limits for normal (not superposed) nodes
loop(node$(not node_superpos(node)),
// Upper bound // Upper bound
v_state.up(gn_state(grid, node), s, f, t)${ p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'useConstant') v_state.up(gn_state(grid, node), s, f, t)${ p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'useConstant')
and not df_central(f,t) and not df_central(f,t)
...@@ -497,6 +513,8 @@ loop((mft_start(mSolve, f, t), ms_initial(mSolve, s)), ...@@ -497,6 +513,8 @@ loop((mft_start(mSolve, f, t), ms_initial(mSolve, s)),
} }
= ts_node(grid, node, 'reference', f, t) // NOTE!!! ts_node_ doesn't contain initial values so using raw data instead. = ts_node(grid, node, 'reference', f, t) // NOTE!!! ts_node_ doesn't contain initial values so using raw data instead.
* p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'multiplier'); * p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'multiplier');
); //end loop of nodes
// Initial online status for units // Initial online status for units
v_online_MIP.fx(unit, s, f, t)${p_unit(unit, 'useInitialOnlineStatus') and uft_onlineMIP(unit, f, t+1)} //sets online status for one time step before the first solve v_online_MIP.fx(unit, s, f, t)${p_unit(unit, 'useInitialOnlineStatus') and uft_onlineMIP(unit, f, t+1)} //sets online status for one time step before the first solve
...@@ -529,6 +547,16 @@ loop((mft_start(mSolve, f, t), ms_initial(mSolve, s)), ...@@ -529,6 +547,16 @@ loop((mft_start(mSolve, f, t), ms_initial(mSolve, s)),
) // END loop(mft_start) ) // END loop(mft_start)
; ;
if(tSolveFirst = mSettings(mSolve, 't_start'),
// state limits for normal (not superposed) nodes
loop(node_superpos(node),
// First solve, state variables (only if boundStart flag is true)
v_state_z.fx(gn_state(grid, node), z)${ p_gn(grid, node, 'boundStart') }
= p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'constant')
* p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'multiplier');
) //END loop node_superpos
); //END if(tSolveFirst)
* ============================================================================= * =============================================================================
* --- Fix previously realized start-ups, shutdowns, and online states --------- * --- Fix previously realized start-ups, shutdowns, and online states ---------
......
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