Commit 2d671e00 authored by Tomi J. Lindroos's avatar Tomi J. Lindroos
Browse files

Remaining efficiency updates from Antti Lehtilä. Merged here with the latest master version.

parent 5e096cdc
......@@ -218,3 +218,13 @@ alias(group, group_);
sets
tt_agg_circular(t, t, t) "Alternative aggregation ordering with embedded circulars"
startp(t) "Temporary subset for time steps"
s_realized(s) "All s among realized sft (redundant if always equivalent to s)"
sft_resdgn(restype, up_down, grid, node, s,f,t) "Temporary tuplet for reserves by restypeDirectionGridNode"
;
......@@ -545,6 +545,12 @@ option clear = tt_aggregate;
tt_aggregate(t_current(t+dt_active(t)), tt(t))
= yes;
// Make alternative aggregation ordering
option clear=tt_agg_circular; tt_agg_circular(t, t_+dt_circular(t_), t_) $= tt_aggregate(t, t_);
$macro tt_aggcircular(t, t_) tt_agg_circular(t, t_, t__)
*$macro tt_aggcircular(t, t_) (tt_aggregate(t, t__), t_(t__+dt_circular(t__)))
* =============================================================================
* --- Defining unit aggregations and ramps ------------------------------------
* =============================================================================
......
......@@ -329,32 +329,36 @@ loop(cc(counter),
// Select and average time series data matching the intervals
ts_unit_(unit_timeseries(unit), param_unit, ft(f, tt_interval(t)))
= sum(tt_aggregate(t, t_),
ts_unit(unit, param_unit, f, t_+dt_circular(t_))
= sum(tt_aggcircular(t, t_),
ts_unit(unit, param_unit, f, t_)
)
/ mInterval(mSolve, 'stepsPerInterval', counter);
$ontext
* Should these be handled here at all? See above comment
ts_effUnit_(effGroupSelectorUnit(effSelector, unit_timeseries(unit), effSelector), param_eff, ft(f, tt_interval(t)))
= sum(tt_aggregate(t, t_),
ts_effUnit(effSelector, unit, effSelector, param_eff, f, t_+dt_circular(t_))
= sum(tt_aggcircular(t, t_),
ts_effUnit(effSelector, unit, effSelector, param_eff, f, t_)
)
/ mInterval(mSolve, 'stepsPerInterval', counter);
ts_effGroupUnit_(effSelector, unit_timeseries(unit), param_eff, ft(f, tt_interval(t)))
= sum(tt_aggregate(t, t_),
ts_effGroupUnit(effSelector, unit, param_eff, f, t_+dt_circular(t_))
= sum(tt_aggcircular(t, t_),
ts_effGroupUnit(effSelector, unit, param_eff, f, t_)
)
/ mInterval(mSolve, 'stepsPerInterval', counter);
$offtext
ts_influx_(gn(grid, node), sft(s, f, tt_interval(t)))
ts_influx_(gn, sft(s, f, tt_interval(t)))$gn_scenarios(gn, 'ts_influx')
= sum(tt_aggregate(t, t_),
ts_influx(grid, node,
f + ( df_realization(f, t)$(not gn_forecasts(grid, node, 'ts_influx'))
+ df_scenario(f, t)$gn_scenarios(grid, node, 'ts_influx')),
t_+ (+ dt_scenarioOffset(grid, node, 'ts_influx', s)
+ dt_circular(t_)$(not gn_scenarios(grid, node, 'ts_influx'))))
)
/ mInterval(mSolve, 'stepsPerInterval', counter);
ts_influx(gn,
f + ( df_realization(f, t)$(not gn_forecasts(gn, 'ts_influx'))
+ df_scenario(f, t)),
t_+ (+ dt_scenarioOffset(gn, 'ts_influx', s)))
) / mInterval(mSolve, 'stepsPerInterval', counter);
ts_influx_(gn, sft(s, f, tt_interval(t)))$(not gn_scenarios(gn, 'ts_influx'))
= sum(tt_aggcircular(t, t_),
ts_influx(gn,
f + ( df_realization(f, t)$(not gn_forecasts(gn, 'ts_influx'))),
t_ )
) / mInterval(mSolve, 'stepsPerInterval', counter);
ts_cf_(flowNode(flow, node), sft(s, f, tt_interval(t)))
= sum(tt_aggregate(t, t_),
ts_cf(flow, node,
......@@ -367,10 +371,10 @@ $offtext
// Reserves relevant only until reserve_length
ts_reserveDemand_(restypeDirectionGroup(restype, up_down, group), ft(f, tt_interval(t)))
${ord(t) <= tSolveFirst + p_groupReserves(group, restype, 'reserve_length') }
= sum(tt_aggregate(t, t_),
= sum(tt_aggcircular(t, t_),
ts_reserveDemand(restype, up_down, group,
f + ( df_realization(f, t)${not sum(gnGroup(grid, node, group), gn_forecasts(restype, node, 'ts_reserveDemand'))}
+ df_scenario(f, t)${sum(gnGroup(grid, node, group), gn_scenarios(restype, node, 'ts_reserveDemand'))} ), t_+ dt_circular(t_))
+ df_scenario(f, t)${sum(gnGroup(grid, node, group), gn_scenarios(restype, node, 'ts_reserveDemand'))} ), t_)
)
/ mInterval(mSolve, 'stepsPerInterval', counter);
ts_node_(gn_state(grid, node), param_gnBoundaryTypes, sft(s, f, tt_interval(t)))
......@@ -404,6 +408,7 @@ $offtext
+ dt_circular(t_)$(not gn_scenarios(grid, node, 'ts_node'))))
)
$(sameas(param_gnBoundaryTypes, 'upwardLimit') or upwardSlack(param_gnBoundaryTypes));
ts_gnn_(gn2n_timeseries(grid, node, node_, param_gnn), ft(f, tt_interval(t)))
= sum(tt_aggregate(t, t_),
ts_gnn(grid, node, node_, param_gnn, f, t_+dt_circular(t_))
......@@ -414,17 +419,17 @@ $offtext
ts_vomCost_(gnu(grid, node, unit), tt_interval(t))
= + p_gnu(grid, node, unit, 'vomCosts')
// input node cost
+ p_price(node, 'price')${un_commodity_in(unit, node) and p_price(node, 'useConstant')}
+ sum(tt_aggregate(t, t_)${un_commodity_in(unit, node) and p_price(node, 'useTimeSeries')},
+ ts_price(node, t_+dt_circular(t_))
)
/ mInterval(mSolve, 'stepsPerInterval', counter)
+ (
+ p_price(node, 'price')$p_price(node, 'useConstant')
+ sum(tt_aggcircular(t, t_), ts_price(node, t_))$p_price(node, 'useTimeSeries')
/ mInterval(mSolve, 'stepsPerInterval', counter)
)$un_commodity_in(unit, node)
// output node cost (if price > 0 --> ts_vomCost_ < 0, i.e. considered as revenue)
- p_price(node, 'price')${un_commodity_out(unit, node) and p_price(node, 'useConstant')}
- sum(tt_aggregate(t, t_)${un_commodity_out(unit, node) and p_price(node, 'useTimeSeries')},
+ ts_price(node, t_+dt_circular(t_))
)
/ mInterval(mSolve, 'stepsPerInterval', counter)
- (
+ p_price(node, 'price')$p_price(node, 'useConstant')
+ sum(tt_aggcircular(t, t_), ts_price(node, t_))$p_price(node, 'useTimeSeries')
/ mInterval(mSolve, 'stepsPerInterval', counter)
)$un_commodity_out(unit, node)
// emission cost
+ sum(emission$p_unitEmissionCost(unit, node, emission), // Emission taxes
+ p_unitEmissionCost(unit, node, emission)
......@@ -444,9 +449,9 @@ $offtext
+ p_unStartup(unit, node, starttype) // MWh/start-up
* [
+ p_price(node, 'price')$p_price(node, 'useConstant') // CUR/MWh
+ sum(tt_aggregate(t, t_)$p_price(node, 'useTimeseries'),
+ ts_price(node, t_+dt_circular(t_)) // CUR/MWh
)
+ sum(tt_aggcircular(t, t_),
+ ts_price(node, t_) // CUR/MWh
)$p_price(node, 'useTimeseries')
/ mInterval(mSolve, 'stepsPerInterval', counter)
] // END * p_uStartup
) // END sum(node)
......
......@@ -31,110 +31,112 @@ if(tSolveFirst >= mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializa
+ v_online_MIP.l(unit, s, f_solve, t)$unit_online_MIP(unit);
);
);
// Improve performance & readibility by using a few helper sets
option clear=startp, clear=sft_resdgn, s_realized < sft_realized;
startp(t)$(ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod'))=yes;
// Realized state history
loop(sft_realized(s, f, t),
r_state(gn_state(grid, node), f, t)$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
loop(ms(mSolve, s_realized(s)),
r_state(gn_state(grid, node), f, startp(t))$sft_realized(s, f, t)
= 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))
}
= v_state.l(grid, node, s, f, t+dt(t))
r_state(gn_state(grid, node), f_solve(f), t_(t+dt(t)))$(mst_start(ms, t)$sft_realized(s, f, t)$startp(t))
= v_state.l(grid, node, s, f, t_)
;
// Realized unit online history
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) }
r_online(uft_online(unit, f, startp(t)))$sft_realized(s, f, t)
= 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, f, t)${ uft_online(unit, f, t) and [ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')] }
= v_startup_LP.l(unit, starttype, s, f, t)${ uft_onlineLP(unit, f, t) }
+ v_startup_MIP.l(unit, starttype, s, f, t)${ uft_onlineMIP(unit, f, t) }
r_startup(unit, starttype, f, startp(t))$(uft_online(unit, f, t)$sft_realized(s, f, t))
= v_startup_LP.l(unit, starttype, s, f, t)$uft_onlineLP(unit, f, t)
+ v_startup_MIP.l(unit, starttype, s, f, t)$uft_onlineMIP(unit, f, t)
;
r_shutdown(uft_online(unit, f, t))$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= v_shutdown_LP.l(unit, s, f, t)${ uft_onlineLP(unit, f, t) }
+ v_shutdown_MIP.l(unit, s, f, t)${ uft_onlineMIP(unit, f, t) }
r_shutdown(uft_online(unit, f, startp(t)))$sft_realized(s, f, t)
= v_shutdown_LP.l(unit, s, f, t)$uft_onlineLP(unit, f, t)
+ v_shutdown_MIP.l(unit, s, f, t)$uft_onlineMIP(unit, f, t)
;
);
* --- Reserve results ---------------------------------------------------------
// Loop over reserve horizon, as the reserve variables use a different ft-structure due to commitment
loop((restypeDirectionGridNode(restype, up_down, grid, node), sft(s, f, t))
${ ord(t) <= tSolveFirst + p_gnReserves(grid, node, restype, 'reserve_length')
and ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')
},
sft_resdgn(restypeDirectionGridNode(restype, up_down, gn), sft(s, f, startp(t)))
${ord(t) <= tSolveFirst + p_gnReserves(gn, restype, 'reserve_length')} = yes;
loop(s,
// Reserve provisions of units
r_reserve(gnuRescapable(restype, up_down, grid, node, unit), f+df_reserves(grid, node, restype, f, t), t)
${ not [ restypeReleasedForRealization(restype)
and sft_realized(s, f+df_reserves(grid, node, restype, f, t), t)
]
}
= + v_reserve.l(restype, up_down, grid, node, unit, s, f+df_reserves(grid, node, restype, f, t), t)
+ sum(restype_$p_gnuRes2Res(grid, node, unit, restype_, up_down, restype),
+ v_reserve.l(restype_, up_down, grid, node, unit, s, f+df_reserves(grid, node, restype_, f, t), t)
* p_gnuRes2Res(grid, node, unit, restype_, up_down, restype)
r_reserve(gnuRescapable(restype, up_down, gn, unit), f_(f+df_reserves(gn, restype, f, t)), t)
${ (not sft_realized(s, f_, t)$restypeReleasedForRealization(restype))$sft_resdgn(restype,up_down,gn,s,f,t) }
= + v_reserve.l(restype, up_down, gn, unit, s, f_, t)
+ sum(restype_$p_gnuRes2Res(gn, unit, restype_, up_down, restype),
+ v_reserve.l(restype_, up_down, gn, unit, s, f+df_reserves(gn, restype_, f, t), t)
* p_gnuRes2Res(gn, unit, restype_, up_down, restype)
);
// Reserve transfer capacity for links defined out from this node
r_resTransferRightward(restype, up_down, gn2n_directional(gn, to_node), f_(f+df_reserves(gn, restype, f, t)), t)
${ restypeDirectionGridNodeNode(restype, up_down, gn, to_node)$sft_resdgn(restype,up_down,gn,s,f,t) }
= v_resTransferRightward.l(restype, up_down, gn, to_node, s, f_, t);
r_resTransferLeftward(restype, up_down, gn2n_directional(gn(grid, node), to_node), f_(f+df_reserves(grid, to_node, restype, f, t)), t)
${ restypeDirectionGridNodeNode(restype, up_down, grid, to_node, node)$sft_resdgn(restype,up_down,gn,s,f,t) }
= v_resTransferLeftward.l(restype, up_down, gn, to_node, s, f_, t);
); // END loop(restypeDirectionNode, sft)
// Loop over group reserve horizon
loop((restypeDirectionGroup(restype, up_down, group), f_(f+df_reservesGroup(group, restype, f, t)), sft(s, f, startp(t)))
${ord(t) <= tSolveFirst + p_groupReserves(group, restype, 'reserve_length')},
// Reserve requirement due to N-1 reserve constraint
r_resDemandLargestInfeedUnit(restypeDirectionGroup(restype, 'up', group), f+df_reserves(grid, node, restype, f, t), t)
${ sum((gnGroup(grid, node, group), unit_fail), p_gnuReserves(grid, node, unit_fail, restype, 'portion_of_infeed_to_reserve')) } // Calculate only for groups with units that can fail.
= smax(unit_fail(unit_)${ sum(gnGroup(grid, node, group), p_gnuReserves(grid, node, unit_, restype, 'portion_of_infeed_to_reserve')) },
+ v_gen.l(grid, node, unit_, s, f, t)
* p_gnuReserves(grid, node, unit_, restype, 'portion_of_infeed_to_reserve')
r_resDemandLargestInfeedUnit(restype, 'up', group, f_, t)
${ sum((gnGroup(gn, group),unit_fail)$p_gnuReserves(gn, unit_fail, restype, 'portion_of_infeed_to_reserve'),1) } // Calculate only for groups with units that can fail.
= smax((gnGroup(gn, group),unit_fail)$p_gnuReserves(gn, unit_fail, restype, 'portion_of_infeed_to_reserve'),
+ v_gen.l(gn, unit_fail, s, f, t)
* p_gnuReserves(gn, unit_fail, restype, 'portion_of_infeed_to_reserve')
) // END smax(unit_fail)
;
// Reserve transfer capacity for links defined out from this node
r_resTransferRightward(restype, up_down, grid, node, to_node, f+df_reserves(grid, node, restype, f, t), t)
${ gn2n_directional(grid, node, to_node)
and restypeDirectionGridNodeNode(restype, up_down, grid, node, to_node)
}
= v_resTransferRightward.l(restype, up_down, grid, node, to_node, s, f+df_reserves(grid, node, restype, f, t), t);
r_resTransferLeftward(restype, up_down, grid, node, to_node, f+df_reserves(grid, to_node, restype, f, t), t)
${ gn2n_directional(grid, node, to_node)
and restypeDirectionGridNodeNode(restype, up_down, grid, to_node, node)
}
= v_resTransferLeftward.l(restype, up_down, grid, node, to_node, s, f+df_reserves(grid, to_node, restype, f, t), t);
// Dummy reserve demand changes
r_qResDemand(restype, up_down, group, f+df_reservesGroup(group, restype, f, t), t)
= vq_resDemand.l(restype, up_down, group, s, f+df_reservesGroup(group, restype, f, t), t);
r_qResDemand(restype, up_down, group, f_, t)
= vq_resDemand.l(restype, up_down, group, s, f_, t);
r_qResMissing(restype, up_down, group, f+df_reservesGroup(group, restype, f, t), t)
= vq_resMissing.l(restype, up_down, group, s, f+df_reservesGroup(group, restype, f, t), t);
r_qResMissing(restype, up_down, group, f_, t)
= vq_resMissing.l(restype, up_down, group, s, f_, t);
); // END loop(restypeDirectionNode, sft)
); // END loop(restypeDirectionGroup, sft)
* --- Interesting results -----------------------------------------------------
loop(sft_realized(s, f, t),
loop(s_realized(s),
// Unit generation and consumption
r_gen(gnuft(grid, node, unit, f, t))$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
r_gen(gnuft(grid, node, unit, f, startp(t)))$sft_realized(s, f, t)
= v_gen.l(grid, node, unit, s, f, t)
;
// Fuel use of units
r_fuelUse(node, uft(unit_commodity, f, t))$[un_commodity(unit_commodity, node) and ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
= - sum(grid$gnu(grid, node, unit_commodity), v_gen.l(grid, node, unit_commodity, s, f, t))
r_fuelUse(node, uft(unit_commodity, f, startp(t)))$(un_commodity(unit_commodity, node)$sft_realized(s, f, t))
= - sum(gnu(grid, node, unit_commodity), v_gen.l(grid, node, unit_commodity, s, f, t))
;
// Transfer of energy between nodes
r_transfer(gn2n(grid, from_node, to_node), f, t)$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
r_transfer(gn2n(grid, from_node, to_node), f, startp(t))$sft_realized(s, f, t)
= v_transfer.l(grid, from_node, to_node, s, f, t)
;
// Transfer of energy from first node to second node
r_transferRightward(gn2n_directional(grid, from_node, to_node), f, t)$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
r_transferRightward(gn2n_directional(grid, from_node, to_node), f, startp(t))$sft_realized(s, f, t)
= v_transferRightward.l(grid, from_node, to_node, s, f, t)
;
// Transfer of energy from second node to first node
r_transferLeftward(gn2n_directional(grid, to_node, from_node), f, t)$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
r_transferLeftward(gn2n_directional(grid, to_node, from_node), f, startp(t))$sft_realized(s, f, t)
= v_transferLeftward.l(grid, to_node, from_node, s, f, t)
;
// Energy spilled from nodes
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)
r_spill(gn, f, startp(t))$sft_realized(s, f, t)
= v_spill.l(gn, s, f, t)
;
);
......@@ -144,17 +146,17 @@ r_totalObj(tSolve)
;
// q_balance marginal values
loop(sft_realized(s, 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)
loop(s_realized(s),
r_balanceMarginal(gn, f, startp(t))$sft_realized(s, f, t)
= q_balance.m(gn, mSolve, s, f, t)
;
// q_resDemand marginal values
r_resDemandMarginal(restypeDirectionGroup(restype, up_down, group), f, t)$[ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')]
r_resDemandMarginal(restypeDirectionGroup(restype, up_down, group), f, startp(t))$sft_realized(s, f, t)
= q_resDemand.m(restype, up_down, group, s, f, t)
;
// v_stateSlack values for calculation of realized costs later on
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)
r_stateSlack(gn_stateSlack(gn), slack, f, startp(t))$sft_realized(s, f, t)
= v_stateSlack.l(gn, slack, s, f, t)
;
);
// Unit investments
......@@ -175,16 +177,12 @@ r_investTransfer(grid, node, node_, t_invest(t))${ p_gnn(grid, node, node_, 'tra
* --- Feasibility results -----------------------------------------------------
loop(sft_realized(s, f, t),
// Dummy generation & consumption
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, s, f, t)
r_qGen(inc_dec, gn, f, startp(t))
= vq_gen.l(inc_dec, gn, s, f, t)
;
// Dummy capacity
r_qCapacity(gn(grid, node), f, t)
${ ord(t) > mSettings(mSolve, 't_start') + mSettings(mSolve, 't_initializationPeriod')
}
= vq_capacity.l(grid, node, s, f, t)
r_qCapacity(gn, f, startp(t))
= vq_capacity.l(gn, s, f, t)
;
);
......
......@@ -15,6 +15,10 @@ You should have received a copy of the GNU Lesser General Public License
along with Backbone. If not, see <http://www.gnu.org/licenses/>.
$offtext
// for performance, get rid of any zeros in r_gen (r_gen was already missing many zero values anyway)
r_gen(gnu, f, t)$((r_gen(gnu, f, t)=0)$r_gen(gnu, f, t))=0;
* =============================================================================
* --- Time Step Dependent Results ---------------------------------------------
* =============================================================================
......@@ -22,17 +26,18 @@ $offtext
// Need to loop over the model dimension, as this file is no longer contained in the modelSolves loop...
loop(m,
option clear=startp; startp(t)$(ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod'))=yes;
* --- Realized Individual Costs ----------------------------------------------
// Variable O&M costs
r_gnuVOMCost(gnu(grid, node, unit), ft_realizedNoReset(f,t))$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]
r_gnuVOMCost(gnu(grid, node, unit), ft_realizedNoReset(f,startp(t)))
= 1e-6 // Scaling to MEUR
* p_stepLengthNoReset(m, f, t)
* abs(r_gen(grid, node, unit, f, t))
* p_gnu(grid, node, unit, 'vomCosts');
// Fuel and emission costs during normal operation
r_uFuelEmissionCost(commodity, unit_commodity(unit), ft_realizedNoReset(f,t))${ un_commodity(unit, commodity) and [ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]}
r_uFuelEmissionCost(commodity, unit_commodity(unit), ft_realizedNoReset(f,startp(t)))$un_commodity(unit, commodity)
= 1e-6 // Scaling to MEUR
* p_stepLengthNoReset(m, f, t)
* r_fuelUse(commodity, unit, f, t)
......@@ -43,7 +48,7 @@ loop(m,
];
// Unit startup costs
r_uStartupCost(unit, ft_realizedNoReset(f,t))${sum(starttype, unitStarttype(unit, starttype)) and [ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]}
r_uStartupCost(unit, ft_realizedNoReset(f,startp(t)))$sum(starttype, unitStarttype(unit, starttype))
= 1e-6 // Scaling to MEUR
* sum(unitStarttype(unit, starttype),
+ r_startup(unit, starttype, f, t)
......@@ -65,7 +70,7 @@ loop(m,
); // END sum(starttype)
//Variable Trnasfer Costs
r_gnnVariableTransCost(gn2n_directional(grid, node_, node), ft_realizedNoReset(f,t))$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]
r_gnnVariableTransCost(gn2n_directional(grid, node_, node), ft_realizedNoReset(f,startp(t)))
= 1e-6 // Scaling to MEUR
* p_stepLengthNoReset(m, f, t)
*[+ p_gnn(grid, node, node_, 'variableTransCost')
......@@ -74,7 +79,7 @@ loop(m,
* r_transferRightward(grid, node_, node, f, t)];
// Node state slack costs
r_gnStateSlackCost(gn_stateSlack(grid, node), ft_realizedNoReset(f,t))$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]
r_gnStateSlackCost(gn_stateSlack(grid, node), ft_realizedNoReset(f,startp(t)))
= 1e-6 // Scaling to MEUR
* p_stepLengthNoReset(m, f, t)
* sum(slack${ p_gnBoundaryPropertiesForStates(grid, node, slack, 'slackCost') },
......@@ -106,35 +111,35 @@ loop(m,
// Total VOM costs
r_gnuTotalVOMCost(gnu_output(grid, node, unit))
= sum(ft_realizedNoReset(f,t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
= sum(ft_realizedNoReset(f,startp(t)),
+ r_gnuVOMCost(grid, node, unit, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s) * p_s_discountFactor(s))
);
// Total Variable Transfer costs
r_gnnTotalVariableTransCost(gn2n_directional(grid, node_, node))
= sum(ft_realizedNoReset(f,t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
= sum(ft_realizedNoReset(f,startp(t)),
+ r_gnnVariableTransCost(grid, node_, node, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s) * p_s_discountFactor(s))
);
// Total fuel & emission costs
r_uTotalFuelEmissionCost(commodity, unit)$un_commodity(unit, commodity)
= sum(ft_realizedNoReset(f,t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
= sum(ft_realizedNoReset(f,startp(t)),
+ r_uFuelEmissionCost(commodity, unit, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s) * p_s_discountFactor(s))
);
// Total unit startup costs
r_uTotalStartupCost(unit)${ sum(starttype, unitStarttype(unit, starttype)) }
= sum(ft_realizedNoReset(f,t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
r_uTotalStartupCost(unit)$sum(starttype, unitStarttype(unit, starttype))
= sum(ft_realizedNoReset(f,startp(t)),
+ r_uStartupCost(unit, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s) * p_s_discountFactor(s))
);
// Total state variable slack costs
r_gnTotalStateSlackCost(gn_stateSlack(grid, node))
= sum(ft_realizedNoReset(f,t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
= sum(ft_realizedNoReset(f,startp(t)),
+ r_gnStateSlackCost(grid, node, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s) * p_s_discountFactor(s))
);
......@@ -185,19 +190,17 @@ loop(m,
* --- Realized Nodal System Costs ---------------------------------------------
// Total realized gn operating costs
r_gnRealizedOperatingCost(gn(grid, node), ft_realizedNoReset(f, t))$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]
r_gnRealizedOperatingCost(gn(grid, node), ft_realizedNoReset(f, startp(t)))
= + sum(gnu(grid, node, unit),
// VOM costs
+ r_gnuVOMCost(grid, node, unit, f, t)
)
// Allocate fuel and startup costs on energy basis, but for output nodes only
+ sum(unit$gnu(grid, node, unit),
+ [
+ abs{r_gen(grid, node, unit, f, t)} // abs is due to potential negative outputs like energy from a cooling unit. It's the energy contribution that matters, not direction.
/ sum(gnu_output(grid_output, node_output, unit),
+ abs{r_gen(grid_output, node_output, unit, f, t)}
) // END sum(gnu_output)
]$(gnu_output(grid, node, unit) and abs{r_gen(grid, node, unit, f, t)} > eps)
+ sum(unit$(r_gen(grid, node, unit, f, t)$gnu_output(grid, node, unit)),
+ abs{r_gen(grid, node, unit, f, t)} // abs is due to potential negative outputs like energy from a cooling unit. It's the energy contribution that matters, not direction.
/ sum(gnu_output(grid_output, node_output, unit),
+ abs{r_gen(grid_output, node_output, unit, f, t)}
) // END sum(gnu_output)
*
{
+ sum(un_commodity(unit, commodity), r_uFuelEmissionCost(commodity, unit, f, t))
......@@ -214,7 +217,7 @@ loop(m,
* --- Realized Nodal Energy Consumption ---------------------------------------
// !!! NOTE !!! This is a bit of an approximation at the moment !!!!!!!!!!!!!!!
r_gnConsumption(gn(grid, node), ft_realizedNoReset(f, t))$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]
r_gnConsumption(gn(grid, node), ft_realizedNoReset(f, startp(t)))
= p_stepLengthNoReset(m, f, t)
* [
+ min(ts_influx(grid, node, f, t), 0) // Not necessarily a good idea, as ts_influx contains energy gains as well...
......@@ -227,7 +230,7 @@ loop(m,
// Total energy generation
r_gnuTotalGen(gnu_output(grid, node, unit))
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
= sum(ft_realizedNoReset(f, startp(t)),
+ r_gen(grid, node, unit, f, t)
* p_stepLengthNoReset(m, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
......@@ -235,7 +238,7 @@ loop(m,
r_gen_gnUnittype(gn(grid, node), unittype)$sum(unit$unitUnittype(unit, unittype), 1)
= sum(gnu(grid,node,unit)$unitUnittype(unit, unittype),
sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
sum(ft_realizedNoReset(f, startp(t)),
+ r_gen(grid, node, unit, f, t)
* p_stepLengthNoReset(m, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
......@@ -243,8 +246,7 @@ loop(m,
);
// Energy generation by fuels
r_genFuel(gn(grid, node), commodity, ft_realizedNoReset(f, t))$[ sum(gnu_input(grid_, node_, unit)$gnu_output(grid, node, unit), r_gen(grid_, node_, unit, f, t))
and ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]
r_genFuel(gn(grid, node), commodity, ft_realizedNoReset(f, startp(t)))$sum(gnu_input(grid_, commodity, unit)$gnu_output(grid, node, unit),r_gen(grid_, commodity, unit, f, t))
= sum(gnu_output(grid, node, unit)$sum(gnu_input(grid_, commodity, unit), 1),
+ r_gen(grid, node, unit, f, t)
);
......@@ -258,17 +260,14 @@ loop(m,
+ r_gen(grid, node, unit, f, t));
// Energy generation by fuels
r_genUnittype(gn(grid, node), unittype, ft_realizedNoReset(f,t))
${ sum(unit,gnu_output(grid, node, unit))
and [ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]
}
= sum(unit${unitUnittype(unit, unittype) and gnu_output(grid, node, unit)},
r_genUnittype(gn(grid, node), unittype, ft_realizedNoReset(f,startp(t)))
= sum(gnu_output(grid, node, unit)$unitUnittype(unit, unittype),
+ r_gen(grid, node, unit, f, t)
); // END sum(unit)
// Total generation on each node by fuels
r_gnTotalGenFuel(gn(grid, node), commodity)
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
= sum(ft_realizedNoReset(f, startp(t)),
+ r_genFuel(grid, node, commodity, f, t)
* p_stepLengthNoReset(m, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
......@@ -276,7 +275,7 @@ loop(m,
// Total dummy generation/consumption
r_gnTotalqGen(inc_dec, gn(grid, node))
= sum(ft_realizedNoReset(f,t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
= sum(ft_realizedNoReset(f,startp(t)),
+ r_qGen(inc_dec, grid, node, f, t)
* p_stepLengthNoReset(m, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
......@@ -285,7 +284,7 @@ loop(m,
* --- Emission Results --------------------------------------------------------
// Emissions of units (only for commodities, not including startup fuels)
r_emissions(commodity, emission, unit, ft_realizedNoReset(f,t))$ {un_commodity(unit, commodity) and [ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]}
r_emissions(commodity, emission, unit, ft_realizedNoReset(f,startp(t)))$un_commodity(unit, commodity)
= + p_stepLengthNoReset(m, f, t)
* r_fuelUse(commodity, unit, f, t)
* p_nEmission(commodity, emission)
......@@ -295,7 +294,7 @@ loop(m,
// Emission sums
r_nuTotalEmissions (commodity, unit, emission)
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
= sum(ft_realizedNoReset(f, startp(t)),
+ r_emissions(commodity, emission, unit, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
)
......@@ -317,7 +316,7 @@ loop(m,
// Total sub-unit-hours for units over the simulation
r_uTotalOnline(unit)
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
= sum(ft_realizedNoReset(f, startp(t)),
+ r_online(unit, f, t)
* p_stepLengthNoReset(m, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
......@@ -340,7 +339,7 @@ loop(m,
// Total reserve provisions over the simulation
r_gnuTotalReserve(gnuRescapable(restype, up_down, grid, node, unit))
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
= sum(ft_realizedNoReset(f, startp(t)),
+ r_reserve(restype, up_down, grid, node, unit, f, t)
* p_stepLengthNoReset(m, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
......@@ -348,7 +347,7 @@ loop(m,
// Total dummy reserve provisions over the simulation
r_groupTotalqResDemand(restypeDirectionGroup(restype, up_down, group))
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
= sum(ft_realizedNoReset(f, startp(t)),
+ r_qResDemand(restype, up_down, group, f, t)
* p_stepLengthNoReset(m, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
......@@ -358,7 +357,7 @@ loop(m,
// Total transfer of energy between nodes
r_gnnTotalTransfer(gn2n(grid, from_node, to_node))
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
= sum(ft_realizedNoReset(f, startp(t)),
+ r_transfer(grid, from_node, to_node, f, t)
* p_stepLengthNoReset(m, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
......@@ -366,7 +365,7 @@ loop(m,
// Total energy spill from nodes
r_gnTotalSpill(grid, node_spill(node))
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
= sum(ft_realizedNoReset(f, startp(t)),
+ r_spill(grid, node, f, t)
* p_stepLengthNoReset(m, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
......@@ -379,11 +378,11 @@ loop(m,
* --- Scaling Marginal Values to EUR/MWh from MEUR/MWh ------------------------
// Energy balance
r_balanceMarginal(gn(grid, node), ft_realizedNoReset(f, t))$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]
r_balanceMarginal(gn(grid, node), ft_realizedNoReset(f, startp(t)))
= 1e6 * r_balanceMarginal(grid, node, f, t);
// Reserve balance
r_resDemandMarginal(restypeDirectionGroup(restype, up_down, group), ft_realizedNoReset(f, t))$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]
r_resDemandMarginal(restypeDirectionGroup(restype, up_down, group), ft_realizedNoReset(f, startp(t)))
= 1e6 * r_resDemandMarginal(restype, up_down, group, f, t);
* --- Total Generation Results ------------------------------------------------
......@@ -416,7 +415,7 @@ r_gTotalqGen(inc_dec, grid)
// Total consumption on each gn over the simulation
r_gnTotalConsumption(gn(grid, node))
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
= sum(ft_realizedNoReset(f, startp(t)),
+ r_gnConsumption(grid, node, f ,t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
);
......@@ -460,7 +459,7 @@ r_gnTotalSpillShare(gn(grid, node_spill))${ r_gTotalSpill(grid) > 0 }
// Total realized operating costs on each gn over the simulation
r_gnTotalRealizedOperatingCost(gn(grid, node))
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
= sum(ft_realizedNoReset(f, startp(t)),
+ r_gnRealizedOperatingCost(grid, node, f ,t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s) * p_s_discountFactor(s))
);
......@@ -581,14 +580,14 @@ r_uTotalOnlinePerUnit(unit)${ p_unit(unit, 'unitCount') > 0 }
// Total sub-unit startups over the simulation
r_uTotalStartup(unit, starttype)
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
= sum(ft_realizedNoReset(f, startp(t)),
+ r_startup(unit, starttype, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
); // END sum(ft_realizedNoReset)
// Total sub-unit shutdowns over the simulation
r_uTotalShutdown(unit)
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
= sum(ft_realizedNoReset(f, startp(t)),
+ r_shutdown(unit, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
); // END sum(ft_realizedNoReset)
...