Commit a36b5415 authored by Erkka Rinne's avatar Erkka Rinne
Browse files

Also support long-term scenarios for ts_node

Note: Smoothing for ts_node is not implemented yet
parent 8729161a
......@@ -117,7 +117,7 @@ Sets
s_active(s) "Samples with non-zero probability in the current model solve"
ss(s, s) "Previous sample of sample"
s_prev(s) "Temporary set for previous sample"
longtermSamples(*, node) "Which grid/flow and node have data for long-term scenarios"
longtermSamples(*, node, *) "Which grid/flow, node and timeseries/param have data for long-term scenarios"
* --- Sets used for the changing unit aggregation and efficiency approximations
uft(unit, f, t) "Active units on intervals, enables aggregation of units for later intervals"
......
......@@ -104,7 +104,7 @@ Parameters
dt_starttypeUnitCounter(starttype, unit, counter) "Displacement needed to account for starttype constraints (in time steps)"
dt_downtimeUnitCounter(unit, counter) "Displacement needed to account for downtime constraints (in time steps)"
dt_uptimeUnitCounter(unit, counter) "Displacement needed to account for uptime constraints (in time steps)"
dt_sampleOffset(*, node, s) "Time offset to make periodic time series data (for grid/flow, unit) to go into different samples"
dt_sampleOffset(*, node, *, s) "Time offset to make periodic time series data (for grid/flow, unit, label) to go into different samples"
// Forecast displacement arrays
df(f, t) "Displacement needed to reach the realized forecast on the current time step"
......
......@@ -184,5 +184,5 @@ Parameters
d_cop(unit, f, t) "Coefficients of performance of conversion units"
d_eff(unit, f, t) "Efficiency of generation units using fuel"
d_capacityFactor(flow, node, s, f, t) "Diagnostic capacity factors (accounting for GAMS plotting error)"
d_nodeState(grid, node, param_gnBoundaryTypes, f, t) "Diagnostic temperature forecasts (accounting for GAMS plotting error)"
d_nodeState(grid, node, param_gnBoundaryTypes, s, f, t) "Diagnostic temperature forecasts (accounting for GAMS plotting error)"
;
......@@ -1285,7 +1285,7 @@ q_stateSlack(gn_stateSlack(grid, node), slack, sft(s, f, t))${ p_gnBoundaryProp
* [
+ v_state(grid, node, s, f, t)
- p_gnBoundaryPropertiesForStates(grid, node, slack, 'constant')$p_gnBoundaryPropertiesForStates(grid, node, slack, 'useConstant')
- ts_node_(grid, node, slack, f, t)${ p_gnBoundaryPropertiesForStates(grid, node, slack, 'useTimeSeries') }
- ts_node_(grid, node, slack, f, t, s)${ p_gnBoundaryPropertiesForStates(grid, node, slack, 'useTimeSeries') }
] // END * p_slackDirection
;
......@@ -1300,7 +1300,7 @@ q_stateUpwardLimit(gn_state(grid, node), msft(m, s, f, t))${ sum(gn2gnu(grid,
+ [
// Upper boundary of the variable
+ p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'constant')${p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'useConstant')}
+ ts_node_(grid, node, 'upwardLimit', f, t)${ p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'useTimeseries') }
+ ts_node_(grid, node, 'upwardLimit', f, t, s)${ p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'useTimeseries') }
// Investments
+ sum(gnu(grid, node, unit),
......@@ -1376,7 +1376,7 @@ q_stateDownwardLimit(gn_state(grid, node), msft(m, s, f, t))${ sum(gn2gnu(grid,
// Lower boundary of the variable
- p_gnBoundaryPropertiesForStates(grid, node, 'downwardLimit', 'constant')${p_gnBoundaryPropertiesForStates(grid, node, 'downwardLimit', 'useConstant')}
- ts_node_(grid, node, 'downwardLimit', f, t)${ p_gnBoundaryPropertiesForStates(grid, node, 'downwardLimit', 'useTimeseries') }
- ts_node_(grid, node, 'downwardLimit', f, t, s)${ p_gnBoundaryPropertiesForStates(grid, node, 'downwardLimit', 'useTimeseries') }
] // END Headroom
* [
// Conversion to energy
......
......@@ -137,12 +137,19 @@ tSolveFirst = ord(tSolve); // tSolveFirst: the start of the current solve, t0 u
Option clear = dt_sampleOffset;
loop(gn(grid, node)$longtermSamples(grid, node),
dt_sampleOffset(grid, node, s)$(ord(s) > 1)
= (ord(s) - 2) * mSettings(mSolve, 'sampleLength');
loop(gn(grid, node),
loop(longtermSamples(grid, node, timeseries),
dt_sampleOffset(grid, node, timeseries, s)$(ord(s) > 1)
= (ord(s) - 2) * mSettings(mSolve, 'sampleLength');
);
loop(longtermSamples(grid, node, param_gnBoundaryTypes),
dt_sampleOffset(grid, node, param_gnBoundaryTypes, s)$(ord(s) > 1)
= (ord(s) - 2) * mSettings(mSolve, 'sampleLength');
);
);
loop(flowNode(flow, node)$longtermSamples(flow, node),
dt_sampleOffset(flow, node, s)$(ord(s) > 1)
loop((flowNode(flow, node), longtermSamples(flow, node, timeseries)),
dt_sampleOffset(flow, node, timeseries, s)$(ord(s) > 1)
= (ord(s) - 2) * mSettings(mSolve, 'sampleLength');
);
......@@ -244,9 +251,9 @@ loop(cc(counter),
// Select time series data matching the intervals, for stepsPerInterval = 1, this is trivial.
loop(ft(f_solve, tt_block(t)),
ts_cf_(flowNode(flow, node), f_solve, t, s)$msf(mSolve, s, f_solve)
= ts_cf(flow, node, f_solve, t + (dt_sampleOffset(flow, node, s) + dt_circular(t)));
= ts_cf(flow, node, f_solve, t + (dt_sampleOffset(flow, node, 'ts_cf', s) + dt_circular(t)));
ts_influx_(gn(grid, node), f_solve, t, s)$msf(mSolve, s, f_solve)
= ts_influx(grid, node, f_solve, t + (dt_sampleOffset(grid, node, s) + dt_circular(t)));
= ts_influx(grid, node, f_solve, t + (dt_sampleOffset(grid, node, 'ts_influx', s) + dt_circular(t)));
ts_unit_(unit, param_unit, f_solve, t)
${p_unit(unit, 'useTimeseries')} // Only include units that have timeseries attributed to them
= ts_unit(unit, param_unit, f_solve, t+dt_circular(t));
......@@ -254,9 +261,10 @@ loop(cc(counter),
ts_reserveDemand_(restypeDirectionNode(restype, up_down, node), f_solve, 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)
${p_gnBoundaryPropertiesForStates(grid, node, param_gnBoundaryTypes, 'useTimeseries')}
= ts_node(grid, node, param_gnBoundaryTypes, f_solve, t+dt_circular(t));
ts_node_(gn_state(grid, node), param_gnBoundaryTypes, f_solve, t, s)
${p_gnBoundaryPropertiesForStates(grid, node, param_gnBoundaryTypes, 'useTimeseries')
and msf(mSolve, s, f_solve)}
= ts_node(grid, node, param_gnBoundaryTypes, f_solve, t + (dt_sampleOffset(grid, node, param_gnBoundaryTypes, s) + dt_circular(t)));
// Fuel price time series
ts_fuelPrice_(fuel, t)
= ts_fuelPrice(fuel, t+dt_circular(t));
......@@ -316,10 +324,10 @@ loop(cc(counter),
}
= yes;
ts_influx_(gn(grid, node), f_solve, t, s)$msf(mSolve, s, f_solve)
= sum(tt(t_), ts_influx(grid, node, f_solve, t_ + (dt_sampleOffset(grid, node, s) + dt_circular(t_))))
= sum(tt(t_), ts_influx(grid, node, f_solve, t_ + (dt_sampleOffset(grid, node, 'ts_influx', s) + dt_circular(t_))))
/ p_stepLength(mSolve, f_solve, t);
ts_cf_(flowNode(flow, node), f_solve, t, s)$msf(mSolve, s, f_solve)
= sum(tt(t_), ts_cf(flow, node, f_solve, t_ + (dt_sampleOffset(flow, node, s) + dt_circular(t_))))
= sum(tt(t_), ts_cf(flow, node, f_solve, t_ + (dt_sampleOffset(flow, node, 'ts_cf', s) + dt_circular(t_))))
/ p_stepLength(mSolve, f_solve, t);
ts_unit_(unit, param_unit, f_solve, t)
${ p_unit(unit, 'useTimeseries')} // Only include units with timeseries attributed to them
......@@ -330,9 +338,10 @@ loop(cc(counter),
${ord(t) <= tSolveFirst + p_nReserves(node, restype, 'reserve_length') }
= sum(tt(t_), ts_reserveDemand(restype, up_down, node, f_solve, t_+dt_circular(t_)))
/ p_stepLength(mSolve, f_solve, t);
ts_node_(gn_state(grid, node), param_gnBoundaryTypes, f_solve, t)
${p_gnBoundaryPropertiesForStates(grid, node, param_gnBoundaryTypes, 'useTimeseries')}
= sum(tt(t_), ts_node(grid, node, param_gnBoundaryTypes, f_solve, t_+dt_circular(t_)))
ts_node_(gn_state(grid, node), param_gnBoundaryTypes, f_solve, t, s)
${p_gnBoundaryPropertiesForStates(grid, node, param_gnBoundaryTypes, 'useTimeseries')
and msf(mSolve, s, f_solve)}
= sum(tt(t_), ts_node(grid, node, param_gnBoundaryTypes, f_solve, t_ + (dt_sampleOffset(grid, node, param_gnBoundaryTypes, s) + dt_circular(t_))))
/ p_stepLength(mSolve, f_solve, t);
// Fuel price time series
ts_fuelPrice_(fuel, t)
......
......@@ -57,14 +57,14 @@ v_state.fx(gn_state(grid, node), sft(s, f,t))${ mft_lastSteps(mSolve, f, t)
v_state.up(gn_state(grid, node), sft(s, f, t))${ p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'useTimeSeries')
and not df_central(f,t)
}
= ts_node_(grid, node, 'upwardLimit', f, t)
* p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'multiplier')
= ts_node_(grid, node, 'upwardLimit', f, t, s)
* p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'multiplier')
;
// Lower bound
v_state.lo(gn_state(grid, node), sft(s, f, t))${ p_gnBoundaryPropertiesForStates(grid, node, 'downwardLimit', 'useTimeSeries')
and not df_central(f,t)
}
= ts_node_(grid, node, 'downwardLimit', f, t)
= ts_node_(grid, node, 'downwardLimit', f, t, s)
* p_gnBoundaryPropertiesForStates(grid, node, 'downwardLimit', 'multiplier')
;
// Fixed value
......@@ -72,7 +72,7 @@ v_state.fx(gn_state(grid, node), sft(s, f, t))${ p_gn(grid, node, 'boundAll')
and p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'useTimeSeries')
and not df_central(f,t)
}
= ts_node_(grid, node, 'reference', f, t)
= ts_node_(grid, node, 'reference', f, t, s)
* p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'multiplier')
;
// BoundEnd to a timeseries value
......@@ -80,7 +80,7 @@ v_state.fx(gn_state(grid, node), sft(s, f,t))${ mft_lastSteps(mSolve, f, t)
and p_gn(grid, node, 'boundEnd')
and p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'useTimeSeries')
}
= ts_node_(grid, node, 'reference', f, t)
= ts_node_(grid, node, 'reference', f, t, s)
* p_gnBoundaryPropertiesForStates(grid, node, 'reference', 'multiplier');
// BoundStartToEnd: bound the last interval in the horizon to the value just before the horizon
......@@ -115,7 +115,7 @@ v_spill.lo(gn(grid, node_spill), sft(s, f, t))${ p_gnBoundaryPropertiesForSta
* p_gnBoundaryPropertiesForStates(grid, node_spill, 'minSpill', 'multiplier')
;
v_spill.lo(gn(grid, node_spill), sft(s, f, t))${ p_gnBoundaryPropertiesForStates(grid, node_spill, 'minSpill', 'useTimeSeries') }
= ts_node_(grid, node_spill, 'minSpill', f, t)
= ts_node_(grid, node_spill, 'minSpill', f, t, s)
* p_gnBoundaryPropertiesForStates(grid, node_spill, 'minSpill', 'multiplier')
;
v_spill.up(gn(grid, node_spill), sft(s, f, t))${ p_gnBoundaryPropertiesForStates(grid, node_spill, 'maxSpill', 'constant') }
......@@ -123,7 +123,7 @@ v_spill.up(gn(grid, node_spill), sft(s, f, t))${ p_gnBoundaryPropertiesForSta
* p_gnBoundaryPropertiesForStates(grid, node_spill, 'maxSpill', 'multiplier')
;
v_spill.up(gn(grid, node_spill), sft(s, f, t))${ p_gnBoundaryPropertiesForStates(grid, node_spill, 'maxSpill', 'useTimeSeries') }
= ts_node_(grid, node_spill, 'maxSpill', f, t)
= ts_node_(grid, node_spill, 'maxSpill', f, t, s)
* p_gnBoundaryPropertiesForStates(grid, node_spill, 'maxSpill', 'multiplier')
;
......
......@@ -163,17 +163,19 @@ r_qGen(inc_dec, gn(grid, node), f, t)
d_capacityFactor(flowNode(flow, node), s, f_solve(f), t_active(t))${sft(s, f, t)
and sum(flowUnit(flow, unit), nu(node, unit)) }
= ts_cf_(flow, node, f, t, s)
+ ts_cf(flow, node, f, t + dt_sampleOffset(flow, node, s))${ not ts_cf_(flow, node, f, t, s) }
+ ts_cf(flow, node, f, t + dt_sampleOffset(flow, node, 'ts_cf', s))${ not ts_cf_(flow, node, f, t, s) }
- 1e-3${ not ts_cf_(flow, node, f, t, s)
and not ts_cf(flow, node, f, t + dt_sampleOffset(flow, node, s))
and not ts_cf(flow, node, f, t + dt_sampleOffset(flow, node, 'ts_cf', s))
}
;
// Temperature forecast for examining the error
d_nodeState(gn_state(grid, node), param_gnBoundaryTypes, f_solve(f), t_active(t))${ p_gnBoundaryPropertiesForStates(grid, node, param_gnBoundaryTypes, 'useTimeseries') }
= ts_node_(grid, node, param_gnBoundaryTypes, f, t)
+ ts_node(grid, node, param_gnBoundaryTypes, f, t)${ not ts_node_(grid, node, param_gnBoundaryTypes, f, t) }
- 1e-3${ not ts_node_(grid, node, param_gnBoundaryTypes, f, t)
and not ts_node_(grid, node, param_gnBoundaryTypes, f, t)
d_nodeState(gn_state(grid, node), param_gnBoundaryTypes, s, f_solve(f), t_active(t))
${p_gnBoundaryPropertiesForStates(grid, node, param_gnBoundaryTypes, 'useTimeseries')
and sft(s, f, t)}
= ts_node_(grid, node, param_gnBoundaryTypes, f, t, s)
+ ts_node(grid, node, param_gnBoundaryTypes, f, t)${ not ts_node_(grid, node, param_gnBoundaryTypes, f, t, s)}
- 1e-3${ not ts_node_(grid, node, param_gnBoundaryTypes, f, t, s)
and not ts_node_(grid, node, param_gnBoundaryTypes, f, t, s)
}
;
......
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