Commit 2272d487 authored by Erkka Rinne's avatar Erkka Rinne
Browse files

Added sample dimension to most variables and equations

Samples can now be used to describe uncertain future after the forecast horizon
parent 361c76b2
......@@ -44,6 +44,7 @@ Sets
// Samples and Forecasts
samples, // Number of active samples
sampleLength "Length of a period in time steps"
forecasts, // Number of active forecasts
t_forecastLengthUnchanging, // Length of forecasts in time steps - this does not decrease when the solve moves forward (requires forecast data that is longer than the horizon at first)
t_forecastLengthDecreasesFrom, // Length of forecasts in time steps - this decreases when the solve moves forward until the new forecast data is read (then extends back to full length)
......
......@@ -100,7 +100,8 @@ Sets
ft_reservesFixed(node, restype, f, t) "Forecast-time steps with reserves fixed due to commitments on a previous solve."
mft(mType, f, t) "Combination of forecasts and t:s in the current model solve"
msf(mType, s, f) "Combination of samples and forecasts in the models"
msft(mType, s, f, t) "Combination of samples, forecasts and t:s in the current model solve"
msft(mType, s, f, t) "Combination of models, samples, forecasts and t's"
sft(s, f, t) "Combination of samples, forecasts and t's in the current model solve"
msft_realizedNoReset(mType, s, f, t) "Combination of realized samples, forecasts and t:s in the current model solve and previously realized t:s"
mft_start(mType, f, t) "Start point of the current model solve"
mf_realization(mType, f) "fRealization of the forecasts"
......
......@@ -37,6 +37,7 @@ Scalars
tmp_dist "Temporary parameter for calculating the distance between operating points"
tmp_op "Temporary parameter for operating point"
tmp_count_op "Counting the number of valid operating points in the unit data"
tmp_offset "Offset of sample in time steps"
f_improve / 12 /
tRealizedLast "counter (ord) for the last realized t in the solve"
firstResultsOutputSolve /1/;
......@@ -102,12 +103,17 @@ 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(*, s) "Time offset to make periodic time series data to go into different samples"
// Forecast displacement arrays
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"
// Sample displacement arrays
ds(s, t) "Displacement needed to reach the sample of previous time step"
ds_state(grid, node, s, t) "Displacement needed to reach the sample of previous time step at this node"
// Temporary displacement arrays
ddt(t) "Temporary time displacement array"
ddf(f, t) "Temporary forecast displacement array"
......@@ -133,9 +139,9 @@ Parameters
ts_unavailability(unit, t) "Unavailability of a unit in the time step (p.u.)"
// Aliases used for intervals (time step aggregation)
ts_influx_(grid, node, f, t)
ts_influx_temp(grid, node, f, t)
ts_influx_(grid, node, f, t, s)
ts_cf_(flow, node, f, t)
ts_influx_temp(grid, node, s, f, t)
ts_reserveDemand_(restype, up_down, node, f, t)
ts_node_(grid, node, param_gnBoundaryTypes, f, t)
ts_fuelPrice_(fuel, t)
......
......@@ -17,41 +17,41 @@ $offtext
Free variable v_obj "Total operating cost (monetary unit)";
Free variables
v_gen(grid, node, unit, f, t) "Energy generation or consumption in an interval (MW)"
v_state(grid, node, f, t) "State variable for nodes that maintain a state (MWh, unless modified by energyStoredPerUnitOfState and diffCoeff parameters)"
v_genRamp(grid, node, unit, f, t) "Change in energy generation or consumption over an interval (MW/h)"
v_transfer(grid, node, node, f, t) "Average electricity transmission level from node to node during an interval (MW)"
v_gen(grid, node, unit, s, f, t) "Energy generation or consumption in an interval (MW)"
v_state(grid, node, s, f, t) "State variable for nodes that maintain a state (MWh, unless modified by energyStoredPerUnitOfState and diffCoeff parameters)"
v_genRamp(grid, node, unit, s, f, t) "Change in energy generation or consumption over an interval (MW/h)"
v_transfer(grid, node, node, s, f, t) "Average electricity transmission level from node to node during an interval (MW)"
;
Integer variables
v_online_MIP(unit, f, t) "Number of sub-units online for units with unit commitment restrictions"
v_online_MIP(unit, s, f, t) "Number of sub-units online for units with unit commitment restrictions"
v_invest_MIP(unit, t) "Number of invested sub-units"
v_investTransfer_MIP(grid, node, node, t) "Number of invested transfer links"
;
SOS2 variables
v_sos2(unit, f, t, effSelector) "Intermediate lambda variable for SOS2 based piece-wise linear efficiency curve"
v_sos2(unit, s, f, t, effSelector) "Intermediate lambda variable for SOS2 based piece-wise linear efficiency curve"
;
Positive variables
v_fuelUse(fuel, unit, f, t) "Fuel use of a unit during an interval (MWh_fuel)"
v_startup(unit, starttype, f, t) "Sub-units started up after/during an interval (p.u.)"
v_shutdown(unit, f, t) "Sub-units shut down after/during an interval (p.u.)"
v_genRampUpDown(grid, node, unit, slack, f, t) "Change in energy generation or consumption over an interval, separated into different 'slacks' (MW/h)"
v_spill(grid, node, f, t) "Spill of energy from storage node during an interval (MWh)"
v_transferRightward(grid, node, node, f, t) "Average electricity transmission level from the first node to the second node during an interval (MW)"
v_transferLeftward(grid, node, node, f, t) "Average electricity transmission level from the second node to the first node during an interval (MW)"
v_resTransferRightward(restype, up_down, node, node, f, t) "Electricity transmission capacity from the first node to the second node reserved for providing reserves (MW)"
v_resTransferLeftward(restype, up_down, node, node, f, t) "Electricity transmission capacity from the second node to the first 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_fuelUse(fuel, unit, s, f, t) "Fuel use of a unit during an interval (MWh_fuel)"
v_startup(unit, starttype, s, f, t) "Sub-units started up after/during an interval (p.u.)"
v_shutdown(unit, s, f, t) "Sub-units shut down after/during an interval (p.u.)"
v_genRampUpDown(grid, node, unit, slack, s, f, t) "Change in energy generation or consumption over an interval, separated into different 'slacks' (MW/h)"
v_spill(grid, node, s, f, t) "Spill of energy from storage node during an interval (MWh)"
v_transferRightward(grid, node, node, s, f, t) "Average electricity transmission level from the first node to the second node during an interval (MW)"
v_transferLeftward(grid, node, node, s, f, t) "Average electricity transmission level from the second node to the first node during an interval (MW)"
v_resTransferRightward(restype, up_down, node, node, s, f, t) "Electricity transmission capacity from the first node to the second node reserved for providing reserves (MW)"
v_resTransferLeftward(restype, up_down, node, node, s, f, t) "Electricity transmission capacity from the second node to the first node reserved for providing reserves (MW)"
v_reserve(restype, up_down, node, unit, s, f, t) "Unit capacity reserved for providing reserve of specific type (MW)"
v_investTransfer_LP(grid, node, node, t) "Invested transfer capacity (MW)"
v_online_LP(unit, f, t) "Number of sub-units online for 'units' with unit commitment restrictions (LP variant)"
v_online_LP(unit, s, f, t) "Number of sub-units online for 'units' with unit commitment restrictions (LP variant)"
v_invest_LP(unit, t) "Number of invested 'sub-units' (LP variant)"
;
* --- Feasibility control -----------------------------------------------------
Positive variables
v_stateSlack(grid, node, slack, f, t) "Slack variable for different v_state slack categories, permits e.g. costs for exceeding acceptable v_states (MWh, unless modified by energyCapacity parameter)"
vq_gen(inc_dec, grid, node, f, t) "Dummy energy generation (increase) or consumption (generation decrease) to ensure equation feasibility (MW)"
vq_resDemand(restype, up_down, node, f, t) "Dummy to decrease demand for a reserve (MW) before the reserve has been locked"
vq_resMissing(restype, up_down, node, f, t) "Dummy to decrease demand for a reserve (MW) after the reserve has been locked"
vq_capacity(grid, node, f, t) "Dummy variable to ensure capacity margin equation feasibility (MW)"
v_stateSlack(grid, node, slack, s, f, t) "Slack variable for different v_state slack categories, permits e.g. costs for exceeding acceptable v_states (MWh, unless modified by energyCapacity parameter)"
vq_gen(inc_dec, grid, node, s, f, t) "Dummy energy generation (increase) or consumption (generation decrease) to ensure equation feasibility (MW)"
vq_resDemand(restype, up_down, node, s, f, t) "Dummy to decrease demand for a reserve (MW) before the reserve has been locked"
vq_resMissing(restype, up_down, node, s, f, t) "Dummy to decrease demand for a reserve (MW) after the reserve has been locked"
vq_capacity(grid, node, s, f, t) "Dummy variable to ensure capacity margin equation feasibility (MW)"
;
......@@ -48,53 +48,53 @@ PENALTY_CAPACITY(grid, node) = 0.5*%def_penalty%;
equations
// Objective Function, Energy Balance, and Reserve demand
q_obj "Objective function"
q_balance(grid, node, mType, f, t) "Energy demand must be satisfied at each node"
q_resDemand(restype, up_down, node, f, t) "Procurement for each reserve type is greater than demand"
q_balance(grid, node, mType, s, f, t) "Energy demand must be satisfied at each node"
q_resDemand(restype, up_down, node, s, f, t) "Procurement for each reserve type is greater than demand"
// Unit Operation
q_maxDownward(mType, grid, node, unit, f, t) "Downward commitments will not undercut power plant minimum load constraints or maximum elec. consumption"
q_maxUpward(mType, grid, node, unit, f, t) "Upward commitments will not exceed maximum available capacity or consumed power"
q_reserveProvision(restype, up_down, node, unit, f, t) "Reserve provision limited for units"
q_startshut(mType, unit, f, t) "Online capacity now minus online capacity in the previous interval is equal to started up minus shut down capacity"
q_startuptype(mType, starttype, unit, f, t) "Startup type depends on the time the unit has been non-operational"
q_onlineOnStartUp(unit, f, t) "Unit must be online after starting up"
q_offlineAfterShutdown(unit, f, t) "Unit must be offline after shutting down"
q_onlineLimit(mType, unit, f, t) "Number of online units limited for units with startup constraints, minimum down time, or investment possibility"
q_onlineMinUptime(mType, unit, f, t) "Number of online units constrained for units with minimum up time"
q_maxDownward(mType, s, grid, node, unit, f, t) "Downward commitments will not undercut power plant minimum load constraints or maximum elec. consumption"
q_maxUpward(mType, s, grid, node, unit, f, t) "Upward commitments will not exceed maximum available capacity or consumed power"
q_reserveProvision(restype, up_down, node, unit, s, f, t) "Reserve provision limited for units"
q_startshut(mType, s, unit, f, t) "Online capacity now minus online capacity in the previous interval is equal to started up minus shut down capacity"
q_startuptype(mType, s, starttype, unit, f, t) "Startup type depends on the time the unit has been non-operational"
q_onlineOnStartUp(s, unit, f, t) "Unit must be online after starting up"
q_offlineAfterShutdown(s, unit, f, t) "Unit must be offline after shutting down"
q_onlineLimit(mType, s, unit, f, t) "Number of online units limited for units with startup constraints, minimum down time, or investment possibility"
q_onlineMinUptime(mType, s, unit, f, t) "Number of online units constrained for units with minimum up time"
q_genRamp(mType, s, grid, node, unit, f, t) "Record the ramps of units with ramp restricitions or costs"
q_rampUpLimit(mType, s, grid, node, unit, f, t) "Up ramping limited for units"
q_rampDownLimit(mType, s, grid, node, unit, f, t) "Down ramping limited for units"
q_rampUpDown(mType, s, grid, node, unit, f, t) "Ramping separated into possibly several upward and downward parts (for different cost levels)"
q_rampSlack(mType, s, grid, node, unit, slack, f, t) "Upward and downward ramps constrained by slack boundaries (for different cost levels)"
q_outputRatioFixed(grid, node, grid, node, unit, f, t) "Force fixed ratio between two energy outputs into different energy grids"
q_outputRatioConstrained(grid, node, grid, node, unit, f, t) "Constrained ratio between two grids of energy output; e.g. electricity generation is greater than cV times unit_heat generation in extraction plants"
q_conversionDirectInputOutput(effSelector, unit, f, t) "Direct conversion of inputs to outputs (no piece-wise linear part-load efficiencies)"
q_conversionSOS2InputIntermediate(effSelector, unit, f, t) "Intermediate output when using SOS2 variable based part-load piece-wise linearization"
q_conversionSOS2Constraint(effSelector, unit, f, t) "Sum of v_sos2 has to equal v_online"
q_conversionSOS2IntermediateOutput(effSelector, unit, f, t) "Output is forced equal with v_sos2 output"
q_fuelUseLimit(fuel, unit, f, t) "Fuel use cannot exceed limits"
q_outputRatioFixed(grid, node, grid, node, unit, s, f, t) "Force fixed ratio between two energy outputs into different energy grids"
q_outputRatioConstrained(grid, node, grid, node, unit, s, f, t) "Constrained ratio between two grids of energy output; e.g. electricity generation is greater than cV times unit_heat generation in extraction plants"
q_conversionDirectInputOutput(s, effSelector, unit, f, t) "Direct conversion of inputs to outputs (no piece-wise linear part-load efficiencies)"
q_conversionSOS2InputIntermediate(s, effSelector, unit, f, t) "Intermediate output when using SOS2 variable based part-load piece-wise linearization"
q_conversionSOS2Constraint(s, effSelector, unit, f, t) "Sum of v_sos2 has to equal v_online"
q_conversionSOS2IntermediateOutput(s, effSelector, unit, f, t) "Output is forced equal with v_sos2 output"
q_fuelUseLimit(s, fuel, unit, f, t) "Fuel use cannot exceed limits"
// Energy Transfer
q_transfer(grid, node, node, f, t) "Rightward and leftward transfer must match the total transfer"
q_transferRightwardLimit(grid, node, node, f, t) "Transfer of energy and capacity reservations to the rightward direction are less than the transfer capacity"
q_transferLeftwardLimit(grid, node, node, f, t) "Transfer of energy and capacity reservations to the leftward direction are less than the transfer capacity"
q_resTransferLimitRightward(grid, node, node, f, t) "Transfer of energy and capacity reservations are less than the transfer capacity to the rightward direction"
q_resTransferLimitLeftward(grid, node, node, f, t) "Transfer of energy and capacity reservations are less than the transfer capacity to the leftward direction"
q_reserveProvisionRightward(restype, up_down, node, node, f, t) "Rightward reserve provision limited"
q_reserveProvisionLeftward(restype, up_down, node, node, f, t) "Leftward reserve provision limited"
q_transfer(grid, node, node, s, f, t) "Rightward and leftward transfer must match the total transfer"
q_transferRightwardLimit(grid, node, node, s, f, t) "Transfer of energy and capacity reservations to the rightward direction are less than the transfer capacity"
q_transferLeftwardLimit(grid, node, node, s, f, t) "Transfer of energy and capacity reservations to the leftward direction are less than the transfer capacity"
q_resTransferLimitRightward(grid, node, node, s, f, t) "Transfer of energy and capacity reservations are less than the transfer capacity to the rightward direction"
q_resTransferLimitLeftward(grid, node, node, s, f, t) "Transfer of energy and capacity reservations are less than the transfer capacity to the leftward direction"
q_reserveProvisionRightward(restype, up_down, node, node, s, f, t) "Rightward reserve provision limited"
q_reserveProvisionLeftward(restype, up_down, node, node, s, f, t) "Leftward reserve provision limited"
// State Variables
q_stateSlack(grid, node, slack, f, t) "Slack variable greater than the difference between v_state and the slack boundary"
q_stateUpwardLimit(grid, node, mType, f, t) "Limit the commitments of a node with a state variable to the available headrooms"
q_stateDownwardLimit(grid, node, mType, f, t) "Limit the commitments of a node with a state variable to the available headrooms"
q_boundStateMaxDiff(grid, node, node, mType, f, t) "Node state variables bounded by other nodes (maximum state difference)"
q_stateSlack(grid, node, slack, s, f, t) "Slack variable greater than the difference between v_state and the slack boundary"
q_stateUpwardLimit(grid, node, mType, s, f, t) "Limit the commitments of a node with a state variable to the available headrooms"
q_stateDownwardLimit(grid, node, mType, s, f, t) "Limit the commitments of a node with a state variable to the available headrooms"
q_boundStateMaxDiff(grid, node, node, mType, s, f, t) "Node state variables bounded by other nodes (maximum state difference)"
q_boundCyclic(grid, node, s, s, mType) "Cyclic bound for the first and the last states of samples"
// Policy
q_inertiaMin(group, f, t) "Minimum inertia in a group of nodes"
q_instantaneousShareMax(group, f, t) "Maximum instantaneous share of generation and controlled import from a group of units and links"
q_constrainedOnlineMultiUnit(group, f, t) "Constrained number of online units for a group of units"
q_capacityMargin(grid, node, f, t) "There needs to be enough capacity to cover energy demand plus a margin"
q_inertiaMin(group, s, f, t) "Minimum inertia in a group of nodes"
q_instantaneousShareMax(group, s, f, t) "Maximum instantaneous share of generation and controlled import from a group of units and links"
q_constrainedOnlineMultiUnit(group, s, f, t) "Constrained number of online units for a group of units"
q_capacityMargin(grid, node, s, f, t) "There needs to be enough capacity to cover energy demand plus a margin"
q_constrainedCapMultiUnit(group, t) "Constrained unit number ratios and sums for a group of units"
q_emissioncap(group, emission) "Limit for emissions"
q_energyShareMax(group) "Maximum energy share of generation and import from a group of units"
......
......@@ -36,13 +36,13 @@ q_obj ..
* [
// Variable O&M costs
+ sum(gnuft(gnu_output(grid, node, unit), f, t), // Calculated only for output energy
+ v_gen(grid, node, unit, f, t)
+ v_gen(grid, node, unit, s, f, t)
* p_unit(unit, 'omCosts')
) // END sum(gnu_output)
// Fuel and emission costs
+ sum(uFuel(unit, 'main', fuel)${uft(unit, f, t)},
+ v_fuelUse(fuel, unit, f, t)
+ v_fuelUse(fuel, unit, s, f, t)
* [
+ ts_fuelPrice_(fuel ,t)
+ sum(emission, // Emission taxes
......@@ -54,7 +54,7 @@ q_obj ..
// Node state slack variable costs
+ sum(gn_stateSlack(grid, node),
+ sum(slack${p_gnBoundaryPropertiesForStates(grid, node, slack, 'slackCost')},
+ v_stateSlack(grid, node, slack, f, t)
+ v_stateSlack(grid, node, slack, s, f, t)
* p_gnBoundaryPropertiesForStates(grid, node, slack, 'slackCost')
) // END sum(slack)
) // END sum(gn_stateSlack)
......@@ -63,7 +63,7 @@ q_obj ..
// Energy balance feasibility dummy varible penalties
+ sum(inc_dec,
+ sum(gn(grid, node),
+ vq_gen(inc_dec, grid, node, f, t)
+ vq_gen(inc_dec, grid, node, s, f, t)
*( PENALTY_BALANCE(grid, node)${not p_gnBoundaryPropertiesForStates(grid, node, 'balancePenalty', 'useTimeSeries')}
+ ts_node(grid, node, 'balancePenalty', f, t)${p_gnBoundaryPropertiesForStates(grid, node, 'balancePenalty', 'useTimeSeries')}
)
......@@ -72,15 +72,15 @@ q_obj ..
// Reserve provision feasibility dummy variable penalties
+ sum(restypeDirectionNode(restype, up_down, node),
+ vq_resDemand(restype, up_down, node, f+df_reserves(node, restype, f, t), t)
+ vq_resDemand(restype, up_down, node, s, f+df_reserves(node, restype, f, t), t)
* PENALTY_RES(restype, up_down)
+ vq_resMissing(restype, up_down, node, f+df_reserves(node, restype, f, t), t)${ ft_reservesFixed(node, restype, f+df_reserves(node, restype, f, t), t) }
+ vq_resMissing(restype, up_down, node, s, f+df_reserves(node, restype, f, t), t)${ ft_reservesFixed(node, restype, f+df_reserves(node, restype, f, t), t) }
* PENALTY_RES_MISSING(restype, up_down)
) // END sum(restypeDirectionNode)
// Capacity margin feasibility dummy variable penalties
+ sum(gn(grid, node),
+ vq_capacity(grid, node, f, t)
+ vq_capacity(grid, node, s, f, t)
* PENALTY_CAPACITY(grid, node)
) // END sum(gn)
] // END * p_stepLength
......@@ -88,7 +88,7 @@ q_obj ..
// Start-up costs, initial startup free as units could have been online before model started
+ sum(uft_online(unit, f, t),
+ sum(unitStarttype(unit, starttype),
+ v_startup(unit, starttype, f, t) // Cost of starting up
+ v_startup(unit, starttype, s, f, t) // Cost of starting up
* [ // Startup variable costs
+ p_uStartup(unit, starttype, 'cost')
......@@ -110,7 +110,7 @@ q_obj ..
// Ramping costs
+ sum(gnuft_rampCost(grid, node, unit, slack, f, t),
+ p_gnuBoundaryProperties(grid, node, unit, slack, 'rampCost')
* v_genRampUpDown(grid, node, unit, slack, f, t)
* v_genRampUpDown(grid, node, unit, slack, s, f, t)
) // END sum(gnuft_rampCost)
] // END * p_sft_probability(s,f,t)
......@@ -122,19 +122,19 @@ q_obj ..
+ sum(mft_start(m, f, t)${ p_storageValue(grid, node, t)
and active(m, 'storageValue')
},
+ v_state(grid, node, f+df_central(f,t), t)
* p_storageValue(grid, node, t)
+ p_storageValue(grid, node, t)
* sum(ms(m, s)${ p_msft_probability(m, s, f, t) },
+ p_msft_probability(m, s, f, t)
* v_state(grid, node, s, f+df_central(f,t), t)
) // END sum(s)
) // END sum(mftStart)
- sum(mft_lastSteps(m, f, t)${ p_storageValue(grid, node, t)
and active(m, 'storageValue')
},
+ v_state(grid, node, f+df_central(f,t), t)
* p_storageValue(grid, node, t)
+ p_storageValue(grid, node, t)
* sum(ms(m, s)${p_msft_probability(m, s, f, t)},
+ p_msft_probability(m, s, f, t)
* v_state(grid, node, s, f+df_central(f,t), t)
) // END sum(s)
) // END sum(mftLastSteps)
) // END sum(gn_state)
......
This diff is collapsed.
......@@ -140,6 +140,7 @@ Option clear = p_stepLength;
Option clear = msft;
Option clear = mft;
Option clear = ft;
Option clear = sft;
// Initialize the set of active t:s and counters
Option clear = t_active;
......@@ -214,10 +215,11 @@ loop(cc(counter),
// Reduce the model dimension
ft(f_solve, tt_interval(t)) = mft(mSolve, f_solve, t);
sft(s, f, t)$msft(mSolve, s, f, t) = ft(f, t);
// Select time series data matching the intervals, for stepsPerInterval = 1, this is trivial.
ts_influx_(gn(grid, node), ft(f_solve, tt_interval(t))) = ts_influx(grid, node, f_solve, t+dt_circular(t));
ts_cf_(flowNode(flow, node), ft(f_solve, tt_interval(t))) = ts_cf(flow, node, f_solve, t+dt_circular(t));
ts_influx_(gn(grid, node), ft(f_solve, tt_interval(t)), s)$sft(s, f_solve, t) = ts_influx(grid, node, f_solve, t + (dt_sampleOffset(node, s) + dt_circular(t)));
ts_unit_(unit, param_unit, ft(f_solve, tt_interval(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));
// Reserve demand relevant only up until reserve_length
......@@ -264,7 +266,8 @@ loop(cc(counter),
// Set of locked combinations of forecasts and intervals for the reserves?
// Reduce the model dimension
ft(f_solve, tt_interval(t)) = mft(mSolve, f_solve, t)
ft(f_solve, tt_interval(t)) = mft(mSolve, f_solve, t);
sft(s, f, t)$msft(mSolve, s, f, t) = ft(f, t);
// Select and average time series data matching the intervals, for stepsPerInterval > 1
// Loop over the t:s of the interval
......@@ -276,8 +279,8 @@ loop(cc(counter),
and ord(t_) < ord(t) + mInterval(mSolve, 'stepsPerInterval', counter)
}
= yes;
ts_influx_(gn(grid, node), f_solve, t)
= sum(tt(t_), ts_influx(grid, node, f_solve, t_+dt_circular(t_)))
ts_influx_(gn(grid, node), f_solve, t, s)
= sum(tt(t_), ts_influx(grid, node, f_solve, t_ + (dt_sampleOffset(node, s) + dt_circular(t_))))
/ p_stepLength(mSolve, f_solve, t);
ts_cf_(flowNode(flow, node), f_solve, t)
= sum(tt(t_), ts_cf(flow, node, f_solve, t_+dt_circular(t_)))
......@@ -351,11 +354,11 @@ if(tSolveFirst = mSettings(mSolve, 't_start'),
tmp = 1;
tmp_ = 1;
loop(t_active(t),
if(tmp and ord(t) > msStart(mSolve, s),
if(tmp and ord(t) - tSolveFirst + 1 > msStart(mSolve, s),
mst_start(mSolve, s, t) = yes;
tmp = 0;
);
if(tmp_ and ord(t) > msEnd(mSolve, s),
if(tmp_ and ord(t) - tSolveFirst + 1 > msEnd(mSolve, s),
mst_end(mSolve, s, t+dt(t)) = yes;
tmp_ = 0;
);
......@@ -414,6 +417,13 @@ ft_reservesFixed(node, restype, f_solve(f), t_active(t))
]
}
= yes;
Options clear = ds, clear = ds_state;
loop(ms(mSolve, s),
ds(s, t) = -(ord(s) - 1)$(ord(t) = tSolveFirst + msStart(mSolve, s));
ds_state(gn_state(grid, node), s, t)${not sum(s_, gnss_bound(grid, node, s_, s))
and not sum(s_, gnss_bound(grid, node, s, s_))}
= ds(s, t);
);
* =============================================================================
* --- Defining unit aggregations and ramps ------------------------------------
......@@ -626,6 +636,3 @@ loop(unit$(p_u_shutdownTimeIntervals(unit)),
);
);
);
This diff is collapsed.
......@@ -20,43 +20,45 @@ $offtext
* =============================================================================
* --- Result arrays required by model dynamics --------------------------------
if(tSolveFirst >= mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod') - mSettings(mSolve, 't_jump') and firstResultsOutputSolve,
loop(msft(mSolve, s, f_solve, t),
firstResultsOutputSolve = 0;
r_state(gn_state(grid, node), f_solve, t) $[ord(t) = mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= v_state.l(grid, node, f_solve, t);
= v_state.l(grid, node, s, f_solve, t);
r_online(unit, f_solve, t)$[unit_online(unit) and ord(t) = mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= v_online_LP.l(unit, f_solve, t)$unit_online_LP(unit)
+ v_online_MIP.l(unit, f_solve, t)$unit_online_MIP(unit);
= v_online_LP.l(unit, s, f_solve, t)$unit_online_LP(unit)
+ v_online_MIP.l(unit, s, f_solve, t)$unit_online_MIP(unit);
);
);
// Realized state history
r_state(gn_state(grid, node), ft_realized(f, t))$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= v_state.l(grid, node, f, t)
;
loop(msft(mSolve, s, ft_realized(f, t)),
r_state(gn_state(grid, node), f, t)$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= v_state.l(grid, node, s, f, t);
// Realized state history - initial state values in samples
r_state(gn_state(grid, node), f_solve(f), t+dt(t))${ ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')
and sum(ms(mSolve, s), mst_start(mSolve, s, t))
and ft_realized(f, t)
}
= v_state.l(grid, node, f, t+dt(t))
= v_state.l(grid, node, s, f, t+dt(t))
;
// Realized unit online history
r_online(uft_online(unit, ft_realized(f, t)))$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= v_online_LP.l(unit, f, t)${ uft_onlineLP(unit, f, t) }
+ v_online_MIP.l(unit, f, t)${ uft_onlineMIP(unit, f, t) }
r_online(uft_online(unit, f, t))$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= v_online_LP.l(unit, s, f, t)${ uft_onlineLP(unit, f, t) }
+ v_online_MIP.l(unit, s, f, t)${ uft_onlineMIP(unit, f, t) }
;
// Unit startup and shutdown history
r_startup(unit, starttype, ft_realized(f, t))${ uft_online(unit, f, t) and [ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')] }
= v_startup.l(unit, starttype, f, t)
r_startup(unit, starttype, f, t)${ uft_online(unit, f, t) and [ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')] }
= v_startup.l(unit, starttype, s, f, t)
;
r_shutdown(uft_online(unit, ft_realized(f, t)))$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= v_shutdown.l(unit, f, t)
r_shutdown(uft_online(unit, f, t))$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= v_shutdown.l(unit, s, f, t)
;
);
* --- Reserve results ---------------------------------------------------------
// Loop over reserve horizon, as the reserve variables use a different ft-structure due to commitment
loop((restypeDirectionNode(restype, up_down, node), ft(f, t))
loop((restypeDirectionNode(restype, up_down, node), sft(s, f, t))
${ df_reserves(node, restype, f, t)
and ord(t) <= tSolveFirst + p_nReserves(node, restype, 'reserve_length')
and ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')
......@@ -68,62 +70,66 @@ loop((restypeDirectionNode(restype, up_down, node), ft(f, t))
and ft_realized(f+df_reserves(node, restype, f, t), t)
]
}
= v_reserve.l(restype, up_down, node, unit, f+df_reserves(node, restype, f, t), t);
= v_reserve.l(restype, up_down, node, unit, s, f+df_reserves(node, restype, f, t), t);
// Reserve transfer capacity
r_resTransferRightward(restype, up_down, node, to_node, f+df_reserves(node, restype, f, t), t)
${ restypeDirectionNode(restype, up_down, to_node)
}
= v_resTransferRightward.l(restype, up_down, node, to_node, f+df_reserves(node, restype, f, t), t);
= v_resTransferRightward.l(restype, up_down, node, to_node, s, f+df_reserves(node, restype, f, t), t);
r_resTransferLeftward(restype, up_down, node, to_node, f+df_reserves(node, restype, f, t), t)
${ restypeDirectionNode(restype, up_down, to_node)
}
= v_resTransferLeftward.l(restype, up_down, node, to_node, f+df_reserves(node, restype, f, t), t);
= v_resTransferLeftward.l(restype, up_down, node, to_node, s, f+df_reserves(node, restype, f, t), t);
// Dummy reserve demand changes
r_qResDemand(restype, up_down, node, f+df_reserves(node, restype, f, t), t)
= vq_resDemand.l(restype, up_down, node, f+df_reserves(node, restype, f, t), t);
= vq_resDemand.l(restype, up_down, node, s, f+df_reserves(node, restype, f, t), t);
r_qResMissing(restype, up_down, node, f+df_reserves(node, restype, f, t), t)
= vq_resMissing.l(restype, up_down, node, f+df_reserves(node, restype, f, t), t);
= vq_resMissing.l(restype, up_down, node, s, f+df_reserves(node, restype, f, t), t);
); // END loop(restypeDirectionNode, ft)
); // END loop(restypeDirectionNode, sft)
* --- Interesting results -----------------------------------------------------
loop(msft(mSolve, s, ft_realized(f, t)),
// Unit generation and consumption
r_gen(gnuft(grid, node, unit, ft_realized(f, t)))$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= v_gen.l(grid, node, unit, f, t)
r_gen(gnuft(grid, node, unit, f, t))$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= v_gen.l(grid, node, unit, s, f, t)
;
// Fuel use of units
r_fuelUse(fuel, uft(unit_fuel, ft_realized(f, t)))$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= v_fuelUse.l(fuel, unit_fuel, f, t)
r_fuelUse(fuel, uft(unit_fuel, f, t))$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= v_fuelUse.l(fuel, unit_fuel, s, f, t)
;
// Transfer of energy between nodes
r_transfer(gn2n(grid, from_node, to_node), ft_realized(f, t))$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= v_transfer.l(grid, from_node, to_node, f, t)
r_transfer(gn2n(grid, from_node, to_node), f, t)$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= v_transfer.l(grid, from_node, to_node, s, f, t)
;
// Energy spilled from nodes
r_spill(gn(grid, node), ft_realized(f, t))$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= v_spill.l(grid, node, f, t)
r_spill(gn(grid, node), f, t)$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= v_spill.l(grid, node, s, f, t)
;
// Total Objective function
r_totalObj
= r_totalObj + v_obj.l
;
);
// q_balance marginal values
r_balanceMarginal(gn(grid, node), ft_realized(f, t))$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= q_balance.m(grid, node, mSolve, f, t)
loop(msft(mSolve, s, ft_realized(f, t)),
r_balanceMarginal(gn(grid, node), f, t)$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= q_balance.m(grid, node, mSolve, s, f, t)
;
// q_resDemand marginal values
r_resDemandMarginal(restypeDirectionNode(restype, up_down, node), ft_realized(f, t))$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= q_resDemand.m(restype, up_down, node, f, t)
r_resDemandMarginal(restypeDirectionNode(restype, up_down, node), f, t)$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= q_resDemand.m(restype, up_down, node, s, f, t)
;
// v_stateSlack values for calculation of realized costs later on
r_stateSlack(gn_stateSlack(grid, node), slack, ft_realized(f, t))$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= v_stateSlack.l(grid, node, slack, f, t)
r_stateSlack(gn_stateSlack(grid, node), slack, f, t)$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= v_stateSlack.l(grid, node, slack, s, f, t)
;
);
// Unit investments
r_invest(unit)${unit_investLP(unit) or unit_investMIP(unit)}
= sum(t_invest, v_invest_LP.l(unit, t_invest) + v_invest_MIP.l(unit, t_invest))
......@@ -138,13 +144,14 @@ r_investTransfer(grid, node, node_, t_invest(t))${ p_gnn(grid, node, node_, 'tra
;
* --- Feasibility results -----------------------------------------------------
loop(msft(mSolve, s, ft_realized(f, t)),
// Dummy generation & consumption
r_qGen(inc_dec, gn(grid, node), ft_realized(f, t))
r_qGen(inc_dec, gn(grid, node), f, t)
${ ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')
}
= vq_gen.l(inc_dec, grid, node, f, t)
= vq_gen.l(inc_dec, grid, node, s, f, t)
;
);
* =============================================================================
* --- Diagnostics Results -----------------------------------------------------
......
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