Commit 2ab312f0 authored by Niina Helistö's avatar Niina Helistö
Browse files

Adding ramping costs. Upward and downward ramps separated into different tiers...

Adding ramping costs. Upward and downward ramps separated into different tiers (or 'slacks') with different costs.
parent 5f74e625
......@@ -36,6 +36,8 @@ Model invest /
q_genRamp
q_rampUpLimit
q_rampDownLimit
q_rampUpDown
q_rampSlack
q_outputRatioFixed
q_outputRatioConstrained
q_conversionDirectInputOutput
......
......@@ -36,6 +36,8 @@ Model schedule /
q_genRamp
q_rampUpLimit
q_rampDownLimit
q_rampUpDown
q_rampSlack
q_outputRatioFixed
q_outputRatioConstrained
q_conversionDirectInputOutput
......
......@@ -67,6 +67,7 @@ v_online_LP
v_online_MIP
v_startup
v_shutdown
v_genRampUpDown
v_resTransferRightward
v_resTransferLeftward
v_reserve
......@@ -92,6 +93,8 @@ v_invest_MIP
q_genRamp
q_rampUpLimit
q_rampDownLimit
q_rampUpDown
q_rampSlack
q_outputRatioFixed
q_outputRatioConstrained
q_conversionDirectInputOutput
......
......@@ -264,6 +264,11 @@ param_gnu "Set of possible data parameters for grid, node, unit" /
unitSizeMVA "Generator MVA rating (MVA)"
/
param_gnuBoundaryProperties "Properties that can be set for the different boundaries" /
rampLimit "Maximum ramp speed (p.u. / min)"
rampCost "Wear and tear cost of ramping up (€/MW)"
/
param_unit "Set of possible data parameters for units" /
unitCount "Number of subunits if aggregated"
outputCapacityTotal "Output capacity of the unit, calculated by summing all the outputs together by default, unless defined in data"
......
......@@ -110,6 +110,7 @@ Sets
nuft(node, unit, f, t) "Enables aggregation of nodes and units for later time periods"
gnuft(grid, node, unit, f, t) "Enables aggregation of nodes and units for later time periods"
gnuft_ramp(grid, node, unit, f, t) "Units with ramp requirements or costs"
gnuft_rampCost(grid, node, unit, slack, f, t) "Units with ramp costs"
suft(effSelector, unit, f, t) "Selecting conversion efficiency equations"
sufts(effSelector, unit, f, t, effSelector) "Selecting conversion efficiency equations"
effGroup(effSelector) "Group name for efficiency selector set, e.g. DirectOff and Lambda02"
......
......@@ -46,6 +46,7 @@ Parameters
p_gnBoundaryPropertiesForStates(grid, node, param_gnBoundaryTypes, param_gnBoundaryProperties) "Properties of different state boundaries and limits"
p_gnn(grid, node, node, param_gnn) "Data for interconnections between energy nodes"
p_gnu(grid, node, unit, param_gnu) "Unit data where energy type matters"
p_gnuBoundaryProperties(grid, node, unit, slack, param_gnuBoundaryProperties) "Properties for unit boundaries where energy type matters"
p_unit(unit, *) "Unit data where energy type does not matter"
p_nReserves(node, restype, *) "Data defining the reserve rules in each node"
p_nuReserves(node, unit, restype, *) "Reserve provision data for units"
......
......@@ -33,6 +33,7 @@ $loaddc effLevelGroupUnit
$loaddc p_gn
$loaddc p_gnn
$loaddc p_gnu
$loaddc p_gnuBoundaryProperties
$loaddc p_unit
$loaddc ts_unit
$loaddc restype
......
......@@ -34,7 +34,7 @@ Positive variables
v_fuelUse(fuel, unit, f, t) "Fuel use of a unit during time period (MWh_fuel)"
v_startup(unit, starttype, f, t) "Unit started up after/during the time period/slice (p.u.)"
v_shutdown(unit, f, t) "Capacity shut down after/during the time period/slice (MW)"
// v_genRampChange(grid, node, unit, up_down, f, t) "Rate of change in energy generation between time steps (MW/h)"
v_genRampUpDown(grid, node, unit, slack, f, t) "Change in energy generation or consumption over a time step, separated into different 'slacks' (MW/h)"
v_spill(grid, node, f, t) "Spill of energy from storage node during time period (MWh)"
v_transferRightward(grid, node, node, f, t) "Average electricity transmission level from the first node to the second node during time period/slice (MW)"
v_transferLeftward(grid, node, node, f, t) "Average electricity transmission level from the second node to the first node during time period/slice (MW)"
......
......@@ -54,9 +54,11 @@ equations
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 and investment possibility"
q_onlineMinUptime(mType, unit, f, t) "Unit must stay operational if it has started up during the previous minOperationHours hours"
q_genRamp(mType, grid, node, s, unit, f, t) "Record the ramps of units with ramp restricitions or costs"
q_rampUpLimit(mType, grid, node, s, unit, f, t) "Up ramping limited for units"
q_rampDownLimit(grid, node, mType, s, unit, f, t) "Down ramping limited for units"
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)"
......
......@@ -98,16 +98,12 @@ q_obj ..
] // END * v_startup
) // END sum(starttype)
) // END sum(uft_online)
$ontext
// !!! PENDING CHANGES !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Ramping costs
+ sum(gnuft_ramp(grid, node, unit, f, t)${ p_gnu(grid, node, unit, 'rampUpCost')
or p_gnu(grid, node, unit, 'rampDownCost')
},
+ p_gnu(grid, node, unit, 'rampUpCost') * v_genRampChange(grid, node, unit, 'up', f, t)
+ p_gnu(grid, node, unit, 'rampDownCost') * v_genRampChange(grid, node, unit, 'down', f, t)
) // END sum(gnuft_ramp)
$offtext
+ sum(gnuft_rampCost(grid, node, unit, slack, f, t),
+ p_gnuBoundaryProperties(grid, node, unit, slack, 'rampCost') * v_genRampUpDown(grid, node, unit, slack, f, t)
) // END sum(gnuft_rampCost)
] // END * p_sft_probability(s,f,t)
) // END sum over msft(m, s, f, t)
......
......@@ -444,10 +444,10 @@ q_onlineMinUptime(m, uft_online(unit, f, t))${ p_unit(unit, 'minOperationHours'
;
* --- Ramp Constraints --------------------------------------------------------
q_genRamp(m, gn(grid, node), s, uft(unit, f, t))${ gnuft_ramp(grid, node, unit, f, t)
and ord(t) > msStart(m, s) + 1
and msft(m, s, f, t)
} ..
q_genRamp(m, s, gnuft_ramp(grid, node, unit, f, t))${ ord(t) > msStart(m, s) + 1
and msft(m, s, f, t)
} ..
+ v_genRamp(grid, node, unit, f, t)
* p_stepLength(m, f, t)
......@@ -458,11 +458,11 @@ q_genRamp(m, gn(grid, node), s, uft(unit, f, t))${ gnuft_ramp(grid, node, unit,
;
* --- Ramp Up Limits ----------------------------------------------------------
q_rampUpLimit(m, gn(grid, node), s, uft(unit, f, t))${ gnuft_ramp(grid, node, unit, f, t)
and ord(t) > msStart(m, s) + 1
and msft(m, s, f, t)
and p_gnu(grid, node, unit, 'maxRampUp')
} ..
q_rampUpLimit(m, s, gnuft_ramp(grid, node, unit, f, t))${ ord(t) > msStart(m, s) + 1
and msft(m, s, f, t)
and p_gnu(grid, node, unit, 'maxRampUp')
} ..
+ v_genRamp(grid, node, unit, f, t)
+ sum(nuRescapable(restype, 'up', node, unit)${ord(t) < tSolveFirst + mSettings(m, 't_reserveLength')},
+ v_reserve(restype, 'up', node, unit, f+df_nReserves(node, restype, f, t), t) // (v_reserve can be used only if the unit is capable of providing a particular reserve)
......@@ -518,11 +518,11 @@ q_rampUpLimit(m, gn(grid, node), s, uft(unit, f, t))${ gnuft_ramp(grid, node, u
;
* --- Ramp Down Limits --------------------------------------------------------
q_rampDownLimit(gn(grid, node), m, s, uft(unit, f, t))${ gnuft_ramp(grid, node, unit, f, t)
and ord(t) > msStart(m, s) + 1
and msft(m, s, f, t)
and p_gnu(grid, node, unit, 'maxRampDown')
} ..
q_rampDownLimit(m, s, gnuft_ramp(grid, node, unit, f, t))${ ord(t) > msStart(m, s) + 1
and msft(m, s, f, t)
and p_gnu(grid, node, unit, 'maxRampDown')
} ..
+ v_genRamp(grid, node, unit, f, t)
- sum(nuRescapable(restype, 'down', node, unit)${ord(t) < tSolveFirst + mSettings(m, 't_reserveLength')},
+ v_reserve(restype, 'down', node, unit, f+df_nReserves(node, restype, f, t), t) // (v_reserve can be used only if the unit is capable of providing a particular reserve)
......@@ -553,6 +553,79 @@ q_rampDownLimit(gn(grid, node), m, s, uft(unit, f, t))${ gnuft_ramp(grid, nod
* p_gnu(grid, node, unit, 'unitSizeTot')
;
* --- Ramps separated into upward and downward ramps --------------------------
q_rampUpDown(m, s, gnuft_ramp(grid, node, unit, f, t))${ ord(t) > msStart(m, s) + 1
and msft(m, s, f, t)
and sum(slack, gnuft_rampCost(grid, node, unit, slack, f, t))
} ..
+ v_genRamp(grid, node, unit, f, t)
=E=
// Upward and downward ramp categories
+ sum(slack${ gnuft_rampCost(grid, node, unit, slack, f, t) },
+ v_genRampUpDown(grid, node, unit, slack, f, t)$upwardSlack(slack)
- v_genRampUpDown(grid, node, unit, slack, f, t)$downwardSlack(slack)
) // END sum(slack)
;
* --- Upward and downward ramps constrained by slack boundaries -----------------------
q_rampSlack(m, s, gnuft_rampCost(grid, node, unit, slack, f, t))${ ord(t) > msStart(m, s) + 1
and msft(m, s, f, t)
} ..
+ v_genRampUpDown(grid, node, unit, slack, f, t)
=L=
// Ramping capability of units without an online variable
+ (
+ ( p_gnu(grid, node, unit, 'maxGen') + p_gnu(grid, node, unit, 'maxCons') )${not uft_online(unit, f, t)}
+ sum(t_invest(t_)${ ord(t_)<=ord(t) },
+ v_invest_LP(unit, t_)${not uft_onlineLP(unit, f, t) and unit_investLP(unit)}
* p_gnu(grid, node, unit, 'unitSizeTot')
+ v_invest_MIP(unit, t_)${not uft_onlineMIP(unit, f, t) and unit_investMIP(unit)}
* p_gnu(grid, node, unit, 'unitSizeTot')
)
)
* p_gnuBoundaryProperties(grid, node, unit, slack, 'rampLimit')
* 60 // Unit conversion from [p.u./min] to [p.u./h]
// Ramping capability of units with an online variable
+ (
+ v_online_LP(unit, f+df_central(f,t), t)${uft_onlineLP(unit, f, t)}
+ v_online_MIP(unit, f+df_central(f,t), t)${uft_onlineMIP(unit, f, t)}
)
* p_gnu(grid, node, unit, 'unitSizeTot')
* p_gnuBoundaryProperties(grid, node, unit, slack, 'rampLimit')
* 60 // Unit conversion from [p.u./min] to [p.u./h]
// Units that are in the run-up phase need to keep up with the run-up ramp rate (contained in p_ut_runUp)
+ p_gnu(grid, node, unit, 'unitSizeGen')
* sum(t_activeNoReset(t_)${ ord(t_) >= ord(t) + dt_next(t) + dt_toStartup(unit, t + dt_next(t))
and ord(t_) <= ord(t) and uft_online(unit, f, t)},
+ sum(unitStarttype(unit, starttype),
+ v_startup(unit, starttype, f+df_central(f,t), t_)
* p_gnuBoundaryProperties(grid, node, unit, slack, 'rampLimit')
* 60 // Unit conversion from [p.u./min] to [p.u./h]
) // END sum(unitStarttype)
)$p_u_runUpTimeIntervals(unit) // END sum(t_)
// Shutdown of consumption units from full load
+ v_shutdown(unit, f+df_central(f,t), t)${uft_online(unit, f, t) and gnu_input(grid, node, unit)}
* p_gnu(grid, node, unit, 'unitSizeTot')
* p_gnuBoundaryProperties(grid, node, unit, slack, 'rampLimit')
* 60 // Unit conversion from [p.u./min] to [p.u./h]
// Shutdown of generation units from full load
+ v_shutdown(unit, f+df_central(f,t), t)${uft_online(unit, f, t) and gnu_output(grid, node, unit)}
* p_gnu(grid, node, unit, 'unitSizeTot')
* p_gnuBoundaryProperties(grid, node, unit, slack, 'rampLimit')
* 60 // Unit conversion from [p.u./min] to [p.u./h]
;
* --- Fixed Output Ratio ------------------------------------------------------
......
......@@ -39,6 +39,7 @@ $iftheni.debug NOT '%debug%' == 'yes'
Option clear = v_fuelUse;
Option clear = v_startup;
Option clear = v_shutdown;
Option clear = v_genRampUpDown;
Option clear = v_spill;
Option clear = v_transferRightward;
Option clear = v_transferLeftward;
......@@ -72,6 +73,8 @@ $iftheni.debug NOT '%debug%' == 'yes'
Option clear = q_genRamp;
Option clear = q_rampUpLimit;
Option clear = q_rampDownLimit;
Option clear = q_rampUpDown;
Option clear = q_rampSlack;
Option clear = q_outputRatioFixed;
Option clear = q_outputRatioConstrained;
Option clear = q_conversionDirectInputOutput;
......@@ -391,12 +394,17 @@ Option clear = gnuft;
gnuft(gn(grid, node), uft(unit, f, t))${ nuft(node, unit, f, t) }
= yes
;
// Active (grid, node, unit, slack, up_down) on each forecast-time step with ramp restrictions
Option clear = gnuft_rampCost;
gnuft_rampCost(gnu(grid, node, unit), slack, ft(f, t))${ gnuft(grid, node, unit, f, t)
and p_gnuBoundaryProperties(grid, node, unit, slack, 'rampCost')
}
= yes;
// Active (grid, node, unit) on each forecast-time step with ramp restrictions
Option clear = gnuft_ramp;
gnuft_ramp(gnuft(grid, node, unit, f, t))${ p_gnu(grid, node, unit, 'maxRampUp')
OR p_gnu(grid, node, unit, 'maxRampDown')
OR p_gnu(grid, node, unit, 'rampUpCost')
OR p_gnu(grid, node, unit, 'rampDownCost')
OR sum(slack, gnuft_rampCost(grid, node, unit, slack, f, t))
}
= yes;
......
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