Commit 74a39217 authored by Erkka Rinne's avatar Erkka Rinne
Browse files

New parameter `df_scenario` for forecast displacement in long-term scenarios

Long-term scenarios should use realized (`f00`) data but time structure in the scenario period uses central forecast (`f02`).
parent 2875e0f6
......@@ -118,6 +118,7 @@ Parameters
df(f, t) "Displacement needed to reach the realized forecast on the current time step"
df_central(f, t) "Displacement needed to reach the central forecast - this is needed when the forecast tree gets reduced in dynamic equations"
df_reserves(node, restype, f, t) "Forecast index displacement needed to reach the realized forecast when committing reserves"
df_scenario(f, t) "Forecast index displacement needed to get realized scenario data for long-term scenarios"
// Sample displacement arrays
ds(s, t) "Displacement needed to reach the sample of previous time step"
......
......@@ -394,6 +394,13 @@ dt(t)${sum(ms(mSolve, s)$(not s_stochastic(s)), mst_start(mSolve, s, t))} = -1;
// NOTE! This set cannot be reset without references to previously solved time steps in the stochastic tree becoming ill-defined!
df(f_solve(f), t_active(t))${ ord(t) <= tSolveFirst + mSettings(mSolve, 't_jump') }
= sum(mf_realization(mSolve, f_), ord(f_) - ord(f));
// If using scenarios, central forecast will be using realized data
if(mSettings('schedule', 'scenarios'),
loop(ms_initial(mSolve, s),
df_scenario(f_solve(f), t_active(t))${ord(t) > msEnd(mSolve, s)}
= sum(mf_realization(mSolve, f_), ord(f_) - ord(f));
);
);
// Forecast displacement between central and forecasted intervals at the end of forecast horizon
Option clear = df_central; // This can be reset.
......
......@@ -314,20 +314,21 @@ $ontext
= ts_effGroupUnit(effSelector, unit, param_eff, f_solve, t+dt_circular(t));
$offtext
ts_cf_(flowNode(flow, node), f, t, s)$sft(s, f, t)
= ts_cf(flow, node, f_solve, t + (dt_scenarioOffset(flow, node, 'ts_cf', s)
+ dt_circular(t)$(not gn_scenarios(flow, node, 'ts_cf'))));
= ts_cf(flow, node, f + df_scenario(f, t), t + (dt_scenarioOffset(flow, node, 'ts_cf', s)
+ dt_circular(t)$(not gn_scenarios(flow, node, 'ts_cf'))));
ts_influx_(gn(grid, node), f, t, s)$sft(s, f, t)
= ts_influx(grid, node, f, t + (dt_scenarioOffset(grid, node, 'ts_influx', s)
= ts_influx(grid, node, f + df_scenario(f, t), t + (dt_scenarioOffset(grid, node, 'ts_influx', s)
+ dt_circular(t)$(not gn_scenarios(grid, node, 'ts_influx'))));
// Reserve demand relevant only up until reserve_length
ts_reserveDemand_(restypeDirectionNode(restype, up_down, node), f_solve, t)
ts_reserveDemand_(restypeDirectionNode(restype, up_down, node), f, t)
${ord(t) <= tSolveFirst + p_nReserves(node, restype, 'reserve_length')}
= ts_reserveDemand(restype, up_down, node, f_solve, t+dt_circular(t));
ts_node_(gn_state(grid, node), param_gnBoundaryTypes, f_solve, t, s)
= ts_reserveDemand(restype, up_down, node, f + df_scenario(f,t),
t+dt_circular(t));
ts_node_(gn_state(grid, node), param_gnBoundaryTypes, f, t, s)
$p_gnBoundaryPropertiesForStates(grid, node, param_gnBoundaryTypes, 'useTimeseries')
= ts_node(grid, node, param_gnBoundaryTypes, f_solve, t + (dt_scenarioOffset(grid, node, param_gnBoundaryTypes, s)
+ dt_circular(t)$(not gn_scenarios(grid, node, 'ts_node'))));
= ts_node(grid, node, param_gnBoundaryTypes, f + df_scenario(f, t),
t + (dt_scenarioOffset(grid, node, param_gnBoundaryTypes, s)
+ dt_circular(t)$(not gn_scenarios(grid, node, 'ts_node'))));
// Fuel price time series
ts_fuelPrice_(fuel, t)
= ts_fuelPrice(fuel, t+dt_circular(t));
......@@ -360,33 +361,40 @@ $ontext
= sum(tt(t_), ts_effGroupUnit(effSelector, unit, param_eff, f_solve, t_+dt_circular(t_))))
/ mInterval(mSolve, 'stepsPerInterval', counter);
$offtext
ts_influx_(gn(grid, node), f_solve, t, s)$sft(s, f, t)
= sum(tt(t_), ts_influx(grid, node, f_solve, t_ + (dt_scenarioOffset(grid, node, 'ts_influx', s)
+ dt_circular(t_)$(not gn_scenarios(grid, node, 'ts_influx')))))
ts_influx_(gn(grid, node), f, t, s)$sft(s, f, t)
= sum(tt(t_), ts_influx(grid, node, f + df_scenario(f, t),
t_ + (dt_scenarioOffset(grid, node, 'ts_influx', s)
+ dt_circular(t_)$(not gn_scenarios(grid, node, 'ts_influx')))))
/ mInterval(mSolve, 'stepsPerInterval', counter);
ts_cf_(flowNode(flow, node), f_solve, t, s)$sft(s, f, t)
= sum(tt(t_), ts_cf(flow, node, f_solve, t_ + (dt_scenarioOffset(flow, node, 'ts_cf', s)
+ dt_circular(t_)$(not gn_scenarios(flow, node, 'ts_cf')))))
ts_cf_(flowNode(flow, node), f, t, s)$sft(s, f, t)
= sum(tt(t_), ts_cf(flow, node, f + df_scenario(f, t),
t_ + (dt_scenarioOffset(flow, node, 'ts_cf', s)
+ dt_circular(t_)$(not gn_scenarios(flow, node, 'ts_cf')))))
/ mInterval(mSolve, 'stepsPerInterval', counter);
// Reserves relevant only until reserve_length
ts_reserveDemand_(restypeDirectionNode(restype, up_down, node), f, t)
${ord(t) <= tSolveFirst + p_nReserves(node, restype, 'reserve_length') }
= sum(tt(t_), ts_reserveDemand(restype, up_down, node, f_solve, t_+dt_circular(t_)))
= sum(tt(t_), ts_reserveDemand(restype, up_down, node,
f + df_scenario(f, t), t_+dt_circular(t_)))
/ mInterval(mSolve, 'stepsPerInterval', counter);
ts_node_(gn_state(grid, node), param_gnBoundaryTypes, f, t, s)
${p_gnBoundaryPropertiesForStates(grid, node, param_gnBoundaryTypes, 'useTimeseries')
and sft(s, f, t)}
// Take average if not a limit type
= (sum(tt(t_), ts_node(grid, node, param_gnBoundaryTypes, f_solve, t_ + (dt_scenarioOffset(grid, node, param_gnBoundaryTypes, s)
+ dt_circular(t_)$(not gn_scenarios(grid, node, 'ts_node')))))
= (sum(tt(t_), ts_node(grid, node, param_gnBoundaryTypes,
f + df_scenario(f, t), t_ + (dt_scenarioOffset(grid, node, param_gnBoundaryTypes, s)
+ dt_circular(t_)$(not gn_scenarios(grid, node, 'ts_node')))))
/ mInterval(mSolve, 'stepsPerInterval', counter))$(not (sameas(param_gnBoundaryTypes, 'upwardLimit') or sameas(param_gnBoundaryTypes, 'downwardLimit')))
// Maximum lower limit
+ smax(tt(t_), ts_node(grid, node, param_gnBoundaryTypes, f_solve, t_ + (dt_scenarioOffset(grid, node, param_gnBoundaryTypes, s)
+ dt_circular(t_)$(not gn_scenarios(grid, node, 'ts_node')))))
+ smax(tt(t_), ts_node(grid, node, param_gnBoundaryTypes,
f + df_scenario(f, t), t_ + (dt_scenarioOffset(grid, node, param_gnBoundaryTypes, s)
+ dt_circular(t_)$(not gn_scenarios(grid, node, 'ts_node')))))
$sameas(param_gnBoundaryTypes, 'downwardLimit')
// Minimum upper limit
+ smin(tt(t_), ts_node(grid, node, param_gnBoundaryTypes, f_solve, t_ + (dt_scenarioOffset(grid, node, param_gnBoundaryTypes, s)
+ dt_circular(t_)$(not gn_scenarios(grid, node, 'ts_node')))))
+ smin(tt(t_), ts_node(grid, node, param_gnBoundaryTypes,
f + df_scenario(f, t),
t_ + (dt_scenarioOffset(grid, node, param_gnBoundaryTypes, s)
+ dt_circular(t_)$(not gn_scenarios(grid, node, 'ts_node')))))
$sameas(param_gnBoundaryTypes, 'upwardLimit');
// Fuel price time series
ts_fuelPrice_(fuel, t)
......
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