2d_constraints.gms 131 KB
 Erkka Rinne committed Aug 04, 2017 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ``````\$ontext This file is part of Backbone. Backbone is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Backbone is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Backbone. If not, see . \$offtext `````` 18 `````` `````` Topi Rasku committed Oct 11, 2017 19 ``````* ============================================================================= `````` Niina Helistö committed Jul 06, 2018 20 ``````* --- Constraint Equation Definitions ----------------------------------------- `````` Topi Rasku committed Oct 11, 2017 21 22 23 24 ``````* ============================================================================= * --- Energy Balance ---------------------------------------------------------- `````` Topi Rasku committed Apr 04, 2019 25 26 27 ``````q_balance(gn(grid, node), msft(m, s, f, t)) // Energy/power balance dynamics solved using implicit Euler discretization \${ not p_gn(grid, node, 'boundAll') } .. `````` Topi Rasku committed Oct 11, 2017 28 29 30 31 `````` // The left side of the equation is the change in the state (will be zero if the node doesn't have a state) + p_gn(grid, node, 'energyStoredPerUnitOfState')\${gn_state(grid, node)} // Unit conversion between v_state of a particular node and energy variables (defaults to 1, but can have node based values if e.g. v_state is in Kelvins and each node has a different heat storage capacity) * [ `````` Erkka Rinne committed Nov 02, 2018 32 33 `````` + v_state(grid, node, s, f+df_central(f,t), t) // The difference between current - v_state(grid, node, s+ds_state(grid,node,s,t), f+df(f,t+dt(t)), t+dt(t)) // ... and previous state of the node `````` Topi Rasku committed Oct 11, 2017 34 35 36 37 38 39 40 41 `````` ] =E= // The right side of the equation contains all the changes converted to energy terms + p_stepLength(m, f, t) // Multiply with the length of the timestep to convert power into energy * ( // Self discharge out of the model boundaries `````` Topi Rasku committed Jun 05, 2018 42 `````` - p_gn(grid, node, 'selfDischargeLoss')\${ gn_state(grid, node) } `````` Erkka Rinne committed Nov 02, 2018 43 `````` * v_state(grid, node, s, f+df_central(f,t), t) // The current state of the node `````` Topi Rasku committed Oct 11, 2017 44 45 `````` // Energy diffusion from this node to neighbouring nodes `````` Topi Rasku committed Apr 03, 2019 46 `````` - sum(gnn_state(grid, node, to_node), `````` Topi Rasku committed Oct 11, 2017 47 `````` + p_gnn(grid, node, to_node, 'diffCoeff') `````` Erkka Rinne committed Nov 02, 2018 48 `````` * v_state(grid, node, s, f+df_central(f,t), t) `````` Topi Rasku committed Oct 11, 2017 49 50 51 `````` ) // END sum(to_node) // Energy diffusion from neighbouring nodes to this node `````` Topi Rasku committed Apr 03, 2019 52 `````` + sum(gnn_state(grid, from_node, node), `````` Topi Rasku committed Oct 11, 2017 53 `````` + p_gnn(grid, from_node, node, 'diffCoeff') `````` Erkka Rinne committed Nov 02, 2018 54 `````` * v_state(grid, from_node, s, f+df_central(f,t), t) // Incoming diffusion based on the state of the neighbouring node `````` Topi Rasku committed Oct 11, 2017 55 56 57 `````` ) // END sum(from_node) // Controlled energy transfer, applies when the current node is on the left side of the connection `````` Topi Rasku committed Apr 03, 2019 58 `````` - sum(gn2n_directional(grid, node, node_), `````` Topi Rasku committed Oct 11, 2017 59 `````` + (1 - p_gnn(grid, node, node_, 'transferLoss')) // Reduce transfer losses `````` Erkka Rinne committed Nov 02, 2018 60 `````` * v_transfer(grid, node, node_, s, f, t) `````` Topi Rasku committed Oct 11, 2017 61 `````` + p_gnn(grid, node, node_, 'transferLoss') // Add transfer losses back if transfer is from this node to another node `````` Erkka Rinne committed Nov 02, 2018 62 `````` * v_transferRightward(grid, node, node_, s, f, t) `````` Topi Rasku committed Oct 11, 2017 63 64 65 `````` ) // END sum(node_) // Controlled energy transfer, applies when the current node is on the right side of the connection `````` Topi Rasku committed Apr 03, 2019 66 `````` + sum(gn2n_directional(grid, node_, node), `````` Erkka Rinne committed Nov 02, 2018 67 `````` + v_transfer(grid, node_, node, s, f, t) `````` Topi Rasku committed Oct 11, 2017 68 `````` - p_gnn(grid, node_, node, 'transferLoss') // Reduce transfer losses if transfer is from another node to this node `````` Erkka Rinne committed Nov 02, 2018 69 `````` * v_transferRightward(grid, node_, node, s, f, t) `````` Topi Rasku committed Oct 11, 2017 70 71 72 73 `````` ) // END sum(node_) // Interactions between the node and its units + sum(gnuft(grid, node, unit, f, t), `````` Erkka Rinne committed Nov 02, 2018 74 `````` + v_gen(grid, node, unit, s, f, t) // Unit energy generation and consumption `````` Juha Kiviluoma committed Dec 05, 2016 75 `````` ) `````` Topi Rasku committed Oct 11, 2017 76 77 `````` // Spilling energy out of the endogenous grids in the model `````` Erkka Rinne committed Nov 02, 2018 78 `````` - v_spill(grid, node, s, f, t)\${node_spill(node)} `````` Topi Rasku committed Oct 11, 2017 79 80 `````` // Power inflow and outflow timeseries to/from the node `````` Erkka Rinne committed Nov 02, 2018 81 `````` + ts_influx_(grid, node, f, t, s) // Incoming (positive) and outgoing (negative) absolute value time series `````` Topi Rasku committed Oct 11, 2017 82 83 `````` // Dummy generation variables, for feasibility purposes `````` Erkka Rinne committed Nov 02, 2018 84 85 `````` + vq_gen('increase', grid, node, s, f, t) // Note! When stateSlack is permitted, have to take caution with the penalties so that it will be used first - vq_gen('decrease', grid, node, s, f, t) // Note! When stateSlack is permitted, have to take caution with the penalties so that it will be used first `````` Topi Rasku committed Oct 11, 2017 86 `````` ) // END * p_stepLength `````` 87 ``````; `````` Topi Rasku committed Oct 11, 2017 88 89 `````` * --- Reserve Demand ---------------------------------------------------------- `````` Topi Rasku committed Oct 05, 2018 90 91 ``````// NOTE! Currently, there are multiple identical instances of the reserve balance equation being generated for each forecast branch even when the reserves are committed and identical between the forecasts. // NOTE! This could be solved by formulating a new "ft_reserves" set to cover only the relevant forecast-time steps, but it would possibly make the reserves even more confusing. `````` Topi Rasku committed Oct 11, 2017 92 `````` `````` Erkka Rinne committed Nov 02, 2018 93 ``````q_resDemand(restypeDirectionNode(restype, up_down, node), sft(s, f, t)) `````` Topi Rasku committed Oct 05, 2018 94 95 `````` \${ ord(t) < tSolveFirst + p_nReserves(node, restype, 'reserve_length') and not [ restypeReleasedForRealization(restype) `````` Erkka Rinne committed Nov 15, 2018 96 `````` and sft_realized(s, f, t)] `````` Topi Rasku committed Oct 05, 2018 97 `````` } .. `````` Topi Rasku committed Apr 04, 2019 98 `````` `````` Topi Rasku committed Oct 11, 2017 99 100 `````` // Reserve provision by capable units on this node + sum(nuft(node, unit, f, t)\${nuRescapable(restype, up_down, node, unit)}, `````` Erkka Rinne committed Nov 02, 2018 101 `````` + v_reserve(restype, up_down, node, unit, s, f+df_reserves(node, restype, f, t), t) `````` Topi Rasku committed Jan 15, 2019 102 103 104 105 `````` * [ // Account for reliability of reserves + 1\${sft_realized(s, f+df_reserves(node, restype, f, t), t)} // reserveReliability limits the reliability of reserves locked ahead of time. + p_nuReserves(node, unit, restype, 'reserveReliability')\${not sft_realized(s, f+df_reserves(node, restype, f, t), t)} ] // END * v_reserve `````` Topi Rasku committed Oct 11, 2017 106 107 `````` ) // END sum(nuft) `````` 108 `````` // Reserve provision from other reserve categories when they can be shared `````` Topi Rasku committed Dec 05, 2018 109 `````` + sum((nuft(node, unit, f, t), restype_)\${p_nuRes2Res(node, unit, restype_, up_down, restype)}, `````` Erkka Rinne committed Dec 12, 2018 110 `````` + v_reserve(restype_, up_down, node, unit, s, f+df_reserves(node, restype_, f, t), t) `````` Topi Rasku committed Dec 05, 2018 111 `````` * p_nuRes2Res(node, unit, restype_, up_down, restype) `````` Topi Rasku committed Jan 15, 2019 112 113 114 115 116 `````` * [ // Account for reliability of reserves + 1\${sft_realized(s, f+df_reserves(node, restype, f, t), t)} // reserveReliability limits the reliability of reserves locked ahead of time. + p_nuReserves(node, unit, restype, 'reserveReliability')\${not sft_realized(s, f+df_reserves(node, restype, f, t), t)} * p_nuReserves(node, unit, restype_, 'reserveReliability') ] // END * v_reserve `````` 117 118 `````` ) // END sum(nuft) `````` Topi Rasku committed Oct 11, 2017 119 `````` // Reserve provision to this node via transfer links `````` 120 `````` + sum(gn2n_directional(grid, node_, node)\${restypeDirectionNodeNode(restype, up_down, node_, node)}, `````` Topi Rasku committed Oct 11, 2017 121 `````` + (1 - p_gnn(grid, node_, node, 'transferLoss') ) `````` Erkka Rinne committed Nov 02, 2018 122 `````` * v_resTransferRightward(restype, up_down, node_, node, s, f+df_reserves(node_, restype, f, t), t) // Reserves from another node - reduces the need for reserves in the node `````` Topi Rasku committed Oct 11, 2017 123 `````` ) // END sum(gn2n_directional) `````` 124 `````` + sum(gn2n_directional(grid, node, node_)\${restypeDirectionNodeNode(restype, up_down, node_, node)}, `````` Topi Rasku committed Oct 11, 2017 125 `````` + (1 - p_gnn(grid, node, node_, 'transferLoss') ) `````` Erkka Rinne committed Nov 02, 2018 126 `````` * v_resTransferLeftward(restype, up_down, node, node_, s, f+df_reserves(node_, restype, f, t), t) // Reserves from another node - reduces the need for reserves in the node `````` Topi Rasku committed Oct 11, 2017 127 128 129 130 131 132 133 134 `````` ) // END sum(gn2n_directional) =G= // Demand for reserves + ts_reserveDemand_(restype, up_down, node, f, t)\${p_nReserves(node, restype, 'use_time_series')} + p_nReserves(node, restype, up_down)\${not p_nReserves(node, restype, 'use_time_series')} `````` Niina Helistö committed Nov 02, 2018 135 136 `````` // Reserve demand increase because of units + sum(nuft(node, unit, f, t)\${p_nuReserves(node, unit, restype, 'reserve_increase_ratio')}, // Could be better to have 'reserve_increase_ratio' separately for up and down directions `````` Erkka Rinne committed Nov 11, 2018 137 `````` + sum(gnu(grid, node, unit), v_gen(grid, node, unit, s, f, t)) // Reserve sets and variables are currently lacking the grid dimension... `````` Niina Helistö committed Nov 02, 2018 138 139 140 `````` * p_nuReserves(node, unit, restype, 'reserve_increase_ratio') ) // END sum(nuft) `````` Topi Rasku committed Oct 11, 2017 141 `````` // Reserve provisions to another nodes via transfer links `````` 142 `````` + sum(gn2n_directional(grid, node, node_)\${restypeDirectionNodeNode(restype, up_down, node, node_)}, // If trasferring reserves to another node, increase your own reserves by same amount `````` Erkka Rinne committed Nov 02, 2018 143 `````` + v_resTransferRightward(restype, up_down, node, node_, s, f+df_reserves(node, restype, f, t), t) `````` Topi Rasku committed Oct 11, 2017 144 `````` ) // END sum(gn2n_directional) `````` 145 `````` + sum(gn2n_directional(grid, node_, node)\${restypeDirectionNodeNode(restype, up_down, node, node_)}, // If trasferring reserves to another node, increase your own reserves by same amount `````` Erkka Rinne committed Nov 02, 2018 146 `````` + v_resTransferLeftward(restype, up_down, node_, node, s, f+df_reserves(node, restype, f, t), t) `````` Topi Rasku committed Oct 11, 2017 147 148 149 `````` ) // END sum(gn2n_directional) // Reserve demand feasibility dummy variables `````` Erkka Rinne committed Nov 02, 2018 150 151 `````` - vq_resDemand(restype, up_down, node, s, 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)} `````` 152 ``````; `````` Topi Rasku committed Oct 11, 2017 153 `````` `````` ran li committed Nov 25, 2018 154 155 156 157 ``````* --- N-1 Reserve Demand ---------------------------------------------------------- // NOTE! Currently, there are multiple identical instances of the reserve balance equation being generated for each forecast branch even when the reserves are committed and identical between the forecasts. // NOTE! This could be solved by formulating a new "ft_reserves" set to cover only the relevant forecast-time steps, but it would possibly make the reserves even more confusing. `````` Erkka Rinne committed Jan 17, 2019 158 ``````q_resDemandLargestInfeedUnit(grid, restypeDirectionNode(restype, 'up', node), unit_fail(unit_), sft(s, f, t)) `````` ran li committed Nov 25, 2018 159 `````` \${ ord(t) < tSolveFirst + p_nReserves(node, restype, 'reserve_length') `````` Juha Kiviluoma committed Feb 01, 2019 160 `````` and gn(grid, node) `````` ran li committed Nov 25, 2018 161 162 163 `````` and not [ restypeReleasedForRealization(restype) and ft_realized(f, t) ] `````` 164 `````` and p_nuReserves(node, unit_, restype, 'portion_of_infeed_to_reserve') `````` ran li committed Nov 25, 2018 165 `````` } .. `````` Topi Rasku committed Apr 04, 2019 166 `````` `````` ran li committed Nov 25, 2018 167 168 `````` // Reserve provision by capable units on this node excluding the failing one + sum(nuft(node, unit, f, t)\${nuRescapable(restype, 'up', node, unit) and (ord(unit_) ne ord(unit))}, `````` Erkka Rinne committed Dec 12, 2018 169 `````` + v_reserve(restype, 'up', node, unit, s, f+df_reserves(node, restype, f, t), t) `````` Topi Rasku committed Jan 15, 2019 170 171 172 173 `````` * [ // Account for reliability of reserves + 1\${sft_realized(s, f+df_reserves(node, restype, f, t), t)} // reserveReliability limits the reliability of reserves locked ahead of time. + p_nuReserves(node, unit, restype, 'reserveReliability')\${not sft_realized(s, f+df_reserves(node, restype, f, t), t)} ] // END * v_reserve `````` ran li committed Nov 25, 2018 174 175 176 `````` ) // END sum(nuft) // Reserve provision from other reserve categories when they can be shared `````` Topi Rasku committed Dec 05, 2018 177 `````` + sum((nuft(node, unit, f, t), restype_)\${p_nuRes2Res(node, unit, restype_, 'up', restype)}, `````` Erkka Rinne committed Dec 12, 2018 178 `````` + v_reserve(restype_, 'up', node, unit, s, f+df_reserves(node, restype_, f, t), t) `````` Topi Rasku committed Dec 05, 2018 179 `````` * p_nuRes2Res(node, unit, restype_, 'up', restype) `````` Topi Rasku committed Jan 15, 2019 180 181 182 183 184 `````` * [ // Account for reliability of reserves + 1\${sft_realized(s, f+df_reserves(node, restype, f, t), t)} // reserveReliability limits the reliability of reserves locked ahead of time. + p_nuReserves(node, unit, restype, 'reserveReliability')\${not sft_realized(s, f+df_reserves(node, restype, f, t), t)} * p_nuReserves(node, unit, restype_, 'reserveReliability') ] // END * v_reserve `````` ran li committed Nov 25, 2018 185 186 187 188 189 `````` ) // END sum(nuft) // Reserve provision to this node via transfer links + sum(gn2n_directional(grid, node_, node)\${restypeDirectionNodeNode(restype, 'up', node_, node)}, + (1 - p_gnn(grid, node_, node, 'transferLoss') ) `````` Erkka Rinne committed Dec 12, 2018 190 `````` * v_resTransferRightward(restype, 'up', node_, node, s, f+df_reserves(node_, restype, f, t), t) // Reserves from another node - reduces the need for reserves in the node `````` ran li committed Nov 25, 2018 191 192 193 `````` ) // END sum(gn2n_directional) + sum(gn2n_directional(grid, node, node_)\${restypeDirectionNodeNode(restype, 'up', node_, node)}, + (1 - p_gnn(grid, node, node_, 'transferLoss') ) `````` Erkka Rinne committed Dec 12, 2018 194 `````` * v_resTransferLeftward(restype, 'up', node, node_, s, f+df_reserves(node_, restype, f, t), t) // Reserves from another node - reduces the need for reserves in the node `````` ran li committed Nov 25, 2018 195 196 197 198 199 `````` ) // END sum(gn2n_directional) =G= // Demand for reserves of the failing one `````` Erkka Rinne committed Jan 17, 2019 200 `````` v_gen(grid,node,unit_,s,f,t) * p_nuReserves(node, unit_, restype, 'portion_of_infeed_to_reserve') `````` ran li committed Nov 25, 2018 201 202 `````` // Reserve provisions to another nodes via transfer links `````` Niina Helistö committed Feb 12, 2019 203 `````` + sum(gn2n_directional(grid, node, node_)\${restypeDirectionNodeNode(restype, 'up', node, node_)}, // If trasferring reserves to another node, increase your own reserves by same amount `````` Erkka Rinne committed Dec 12, 2018 204 `````` + v_resTransferRightward(restype, 'up', node, node_, s, f+df_reserves(node, restype, f, t), t) `````` ran li committed Nov 25, 2018 205 `````` ) // END sum(gn2n_directional) `````` Niina Helistö committed Feb 12, 2019 206 `````` + sum(gn2n_directional(grid, node_, node)\${restypeDirectionNodeNode(restype, 'up', node, node_)}, // If trasferring reserves to another node, increase your own reserves by same amount `````` Erkka Rinne committed Dec 12, 2018 207 `````` + v_resTransferLeftward(restype, 'up', node_, node, s, f+df_reserves(node, restype, f, t), t) `````` ran li committed Nov 25, 2018 208 209 210 `````` ) // END sum(gn2n_directional) // Reserve demand feasibility dummy variables `````` Erkka Rinne committed Dec 12, 2018 211 212 `````` - vq_resDemand(restype, 'up', node, s, f+df_reserves(node, restype, f, t), t) - vq_resMissing(restype, 'up', node, s, f+df_reserves(node, restype, f, t), t)\${ft_reservesFixed(node, restype, f+df_reserves(node, restype, f, t), t)} `````` ran li committed Nov 25, 2018 213 ``````; `````` Topi Rasku committed Oct 11, 2017 214 215 ``````* --- Maximum Downward Capacity ----------------------------------------------- `````` Topi Rasku committed Aug 09, 2019 216 ``````q_maxDownward(gnu(grid, node, unit), msft(m, s, f, t)) `````` Topi Rasku committed Apr 04, 2019 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 `````` \${ gnuft(grid, node, unit, f, t) and { [ ord(t) < tSolveFirst + smax(restype, p_nReserves(node, restype, 'reserve_length')) // Unit is either providing and sum(restype, nuRescapable(restype, 'down', node, unit)) // downward reserves ] // NOTE!!! Could be better to form a gnuft_reserves subset? or [ // the unit has an online variable uft_online(unit, f, t) and [ (unit_minLoad(unit) and p_gnu(grid, node, unit, 'unitSizeGen')) // generators with a min. load or p_gnu(grid, node, unit, 'maxCons') // or consuming units with an online variable ] ] // END or or [ // consuming units with investment possibility gnu_input(grid, node, unit) and [unit_investLP(unit) or unit_investMIP(unit)] ] }} .. `````` Topi Rasku committed Oct 11, 2017 236 `````` // Energy generation/consumption `````` Erkka Rinne committed Nov 02, 2018 237 `````` + v_gen(grid, node, unit, s, f, t) `````` Topi Rasku committed Oct 11, 2017 238 239 `````` // Considering output constraints (e.g. cV line) `````` 240 241 `````` + sum(gngnu_constrainedOutputRatio(grid, node, grid_output, node_, unit), + p_gnu(grid_output, node_, unit, 'cV') `````` Erkka Rinne committed Nov 02, 2018 242 `````` * v_gen(grid_output, node_, unit, s, f, t) `````` Topi Rasku committed Oct 11, 2017 243 244 245 `````` ) // END sum(gngnu_constrainedOutputRatio) // Downward reserve participation `````` 246 `````` - sum(nuRescapable(restype, 'down', node, unit)\${ord(t) < tSolveFirst + p_nReserves(node, restype, 'reserve_length')}, `````` Erkka Rinne committed Nov 02, 2018 247 `````` + v_reserve(restype, 'down', node, unit, s, f+df_reserves(node, restype, f, t), t) // (v_reserve can be used only if the unit is capable of providing a particular reserve) `````` Topi Rasku committed Oct 11, 2017 248 249 250 251 252 253 `````` ) // END sum(nuRescapable) =G= // Must be greater than minimum load or maximum consumption (units with min-load and both generation and consumption are not allowed) // Generation units, greater than minload + p_gnu(grid, node, unit, 'unitSizeGen') `````` Topi Rasku committed Nov 09, 2017 254 `````` * sum(suft(effGroup, unit, f, t), // Uses the minimum 'lb' for the current efficiency approximation `````` Topi Rasku committed Oct 11, 2017 255 256 257 258 `````` + p_effGroupUnit(effGroup, unit, 'lb')\${not ts_effGroupUnit(effGroup, unit, 'lb', f, t)} + ts_effGroupUnit(effGroup, unit, 'lb', f, t) ) // END sum(effGroup) * [ // Online variables should only be generated for units with restrictions `````` Erkka Rinne committed Nov 02, 2018 259 260 `````` + v_online_LP(unit, s, f+df_central(f,t), t)\${uft_onlineLP(unit, f+df_central(f,t), t)} // LP online variant + v_online_MIP(unit, s, f+df_central(f,t), t)\${uft_onlineMIP(unit, f+df_central(f,t), t)} // MIP online variant `````` Topi Rasku committed Oct 11, 2017 261 262 `````` ] // END v_online `````` Topi Rasku committed Jan 24, 2019 263 264 265 266 `````` // Units in run-up phase neet to keep up with the run-up rate + p_gnu(grid, node, unit, 'unitSizeGen') * sum(unitStarttype(unit, starttype)\${uft_startupTrajectory(unit, f, t)}, sum(runUpCounter(unit, counter)\${t_active(t+dt_trajectory(counter))}, // Sum over the run-up intervals `````` Topi Rasku committed Apr 04, 2019 267 268 `````` + [ + v_startup_LP(unit, starttype, s, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) `````` Topi Rasku committed Apr 04, 2019 269 `````` \${ uft_onlineLP_withPrevious(unit, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) } `````` Topi Rasku committed Apr 04, 2019 270 `````` + v_startup_MIP(unit, starttype, s, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) `````` Topi Rasku committed Apr 04, 2019 271 `````` \${ uft_onlineMIP_withPrevious(unit, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) } `````` Topi Rasku committed Apr 04, 2019 272 `````` ] `````` Topi Rasku committed Jan 25, 2019 273 `````` * p_uCounter_runUpMin(unit, counter) `````` Topi Rasku committed Jan 24, 2019 274 275 276 277 278 279 `````` ) // END sum(runUpCounter) ) // END sum(unitStarttype) // Units in shutdown phase need to keep up with the shutdown rate + p_gnu(grid, node, unit, 'unitSizeGen') * sum(shutdownCounter(unit, counter)\${t_active(t+dt_trajectory(counter)) and uft_shutdownTrajectory(unit, f, t)}, // Sum over the shutdown intervals `````` Topi Rasku committed Apr 04, 2019 280 281 282 283 284 285 `````` + [ + v_shutdown_LP(unit, s, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) \${ uft_onlineLP_withPrevious(unit, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) } + v_shutdown_MIP(unit, s, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) \${ uft_onlineMIP_withPrevious(unit, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) } ] `````` Topi Rasku committed Jan 25, 2019 286 `````` * p_uCounter_shutdownMin(unit, counter) `````` Topi Rasku committed Jan 24, 2019 287 `````` ) // END sum(shutdownCounter) `````` Juha Kiviluoma committed Apr 06, 2018 288 `````` `````` Topi Rasku committed Oct 11, 2017 289 290 291 292 293 `````` // Consuming units, greater than maxCons // Available capacity restrictions - p_unit(unit, 'availability') * [ // Capacity factors for flow units `````` Topi Rasku committed Jun 05, 2018 294 `````` + sum(flowUnit(flow, unit), `````` Erkka Rinne committed Nov 02, 2018 295 `````` + ts_cf_(flow, node, f, t, s) `````` Topi Rasku committed Oct 11, 2017 296 297 298 299 300 301 `````` ) // END sum(flow) + 1\${not unit_flow(unit)} ] // END * p_unit(availability) * [ // Online capacity restriction + p_gnu(grid, node, unit, 'maxCons')\${not uft_online(unit, f, t)} // Use initial maximum if no online variables `````` 302 303 304 305 `````` // !!! TEMPORARY SOLUTION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + [ + p_gnu(grid, node, unit, 'unitSizeCons') + p_gnu(grid, node, unit, 'maxCons')\${not p_gnu(grid, node, unit, 'unitSizeCons') > 0} `````` Topi Rasku committed Aug 09, 2019 306 `````` / ( p_unit(unit, 'unitCount') + 1\${not p_unit(unit, 'unitCount') > 0} ) `````` 307 308 `````` ] // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! `````` Topi Rasku committed Oct 11, 2017 309 `````` * [ `````` 310 `````` // Capacity online `````` Erkka Rinne committed Nov 02, 2018 311 312 `````` + v_online_LP(unit, s, f+df_central(f,t), t)\${uft_onlineLP(unit, f, t)} + v_online_MIP(unit, s, f+df_central(f,t), t)\${uft_onlineMIP(unit, f, t)} `````` 313 314 315 316 317 318 319 320 `````` // Investments to additional non-online capacity + sum(t_invest(t_)\${ ord(t_)<=ord(t) and not uft_online(unit, f, t) }, + v_invest_LP(unit, t_)\${unit_investLP(unit)} // NOTE! v_invest_LP also for consuming units is positive + v_invest_MIP(unit, t_)\${unit_investMIP(unit)} // NOTE! v_invest_MIP also for consuming units is positive ) // END sum(t_invest) `````` Topi Rasku committed Oct 11, 2017 321 322 `````` ] // END * p_gnu(unitSizeCons) ] // END * p_unit(availability) `````` Topi Rasku committed Mar 29, 2017 323 ``````; `````` Topi Rasku committed Oct 11, 2017 324 325 326 `````` * --- Maximum Upwards Capacity ------------------------------------------------ `````` Topi Rasku committed Aug 09, 2019 327 ``````q_maxUpward(gnu(grid, node, unit), msft(m, s, f, t)) `````` Topi Rasku committed Apr 04, 2019 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 `````` \${ gnuft(grid, node, unit, f, t) and { [ ord(t) < tSolveFirst + smax(restype, p_nReserves(node, restype, 'reserve_length')) // Unit is either providing and sum(restype, nuRescapable(restype, 'up', node, unit)) // upward reserves ] or [ uft_online(unit, f, t) // or the unit has an online variable and [ [unit_minLoad(unit) and p_gnu(grid, node, unit, 'unitSizeCons')] // consuming units with min_load or [p_gnu(grid, node, unit, 'maxGen')] // generators with an online variable ] ] or [ gnu_output(grid, node, unit) // generators with investment possibility and (unit_investLP(unit) or unit_investMIP(unit)) ] }}.. `````` Topi Rasku committed Oct 11, 2017 346 `````` // Energy generation/consumption `````` Erkka Rinne committed Nov 02, 2018 347 `````` + v_gen(grid, node, unit, s, f, t) `````` Topi Rasku committed Oct 11, 2017 348 349 350 351 `````` // Considering output constraints (e.g. cV line) + sum(gngnu_constrainedOutputRatio(grid, node, grid_output, node_, unit), + p_gnu(grid_output, node_, unit, 'cV') `````` Erkka Rinne committed Nov 02, 2018 352 `````` * v_gen(grid_output, node_, unit, s, f, t) `````` Topi Rasku committed Oct 11, 2017 353 354 355 `````` ) // END sum(gngnu_constrainedOutputRatio) // Upwards reserve participation `````` 356 `````` + sum(nuRescapable(restype, 'up', node, unit)\${ord(t) < tSolveFirst + p_nReserves(node, restype, 'reserve_length')}, `````` Erkka Rinne committed Nov 02, 2018 357 `````` + v_reserve(restype, 'up', node, unit, s, f+df_reserves(node, restype, f, t), t) `````` Topi Rasku committed Oct 11, 2017 358 359 360 361 362 `````` ) // END sum(nuRescapable) =L= // must be less than available/online capacity // Consuming units `````` Niina Helistö committed Mar 01, 2019 363 `````` - p_gnu(grid, node, unit, 'unitSizeCons') `````` Topi Rasku committed Nov 09, 2017 364 `````` * sum(suft(effGroup, unit, f, t), // Uses the minimum 'lb' for the current efficiency approximation `````` Topi Rasku committed Oct 11, 2017 365 366 367 368 `````` + p_effGroupUnit(effGroup, unit, 'lb')\${not ts_effGroupUnit(effGroup, unit, 'lb', f, t)} + ts_effGroupUnit(effGroup, unit, 'lb', f, t) ) // END sum(effGroup) * [ `````` Erkka Rinne committed Nov 02, 2018 369 370 `````` + v_online_LP(unit, s, f+df_central(f,t), t)\${uft_onlineLP(unit, f, t)} // Consuming units are restricted by their min. load (consuming is negative) + v_online_MIP(unit, s, f+df_central(f,t), t)\${uft_onlineMIP(unit, f, t)} // Consuming units are restricted by their min. load (consuming is negative) `````` Topi Rasku committed Oct 11, 2017 371 372 373 374 375 376 377 `````` ] // END * p_gnu(unitSizeCons) // Generation units // Available capacity restrictions + p_unit(unit, 'availability') // Generation units are restricted by their (available) capacity * [ // Capacity factor for flow units `````` Topi Rasku committed Jun 05, 2018 378 `````` + sum(flowUnit(flow, unit), `````` Erkka Rinne committed Nov 02, 2018 379 `````` + ts_cf_(flow, node, f, t, s) `````` Topi Rasku committed Oct 11, 2017 380 381 382 383 384 385 386 387 `````` ) // END sum(flow) + 1\${not unit_flow(unit)} ] // END * p_unit(availability) * [ // Online capacity restriction + p_gnu(grid, node, unit, 'maxGen')\${not uft_online(unit, f, t)} // Use initial maxGen if no online variables + p_gnu(grid, node, unit, 'unitSizeGen') * [ `````` 388 `````` // Capacity online `````` Erkka Rinne committed Nov 02, 2018 389 390 `````` + v_online_LP(unit, s, f+df_central(f,t), t)\${uft_onlineLP(unit, f ,t)} + v_online_MIP(unit, s, f+df_central(f,t), t)\${uft_onlineMIP(unit, f, t)} `````` 391 392 393 394 395 396 397 398 `````` // Investments to non-online capacity + sum(t_invest(t_)\${ ord(t_)<=ord(t) and not uft_online(unit, f ,t) }, + v_invest_LP(unit, t_)\${unit_investLP(unit)} + v_invest_MIP(unit, t_)\${unit_investMIP(unit)} ) // END sum(t_invest) `````` Topi Rasku committed Oct 11, 2017 399 400 `````` ] // END * p_gnu(unitSizeGen) ] // END * p_unit(availability) `````` Juha Kiviluoma committed Apr 06, 2018 401 `````` `````` Topi Rasku committed Jan 24, 2019 402 403 404 405 `````` // Units in run-up phase neet to keep up with the run-up rate + p_gnu(grid, node, unit, 'unitSizeGen') * sum(unitStarttype(unit, starttype)\${uft_startupTrajectory(unit, f, t)}, sum(runUpCounter(unit, counter)\${t_active(t+dt_trajectory(counter))}, // Sum over the run-up intervals `````` Topi Rasku committed Apr 04, 2019 406 407 `````` + [ + v_startup_LP(unit, starttype, s, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) `````` Topi Rasku committed Apr 04, 2019 408 `````` \${ uft_onlineLP_withPrevious(unit, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) } `````` Topi Rasku committed Apr 04, 2019 409 `````` + v_startup_MIP(unit, starttype, s, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) `````` Topi Rasku committed Apr 04, 2019 410 `````` \${ uft_onlineMIP_withPrevious(unit, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) } `````` Topi Rasku committed Apr 04, 2019 411 `````` ] `````` Topi Rasku committed Jan 25, 2019 412 `````` * p_uCounter_runUpMax(unit, counter) `````` Topi Rasku committed Jan 24, 2019 413 414 415 416 417 418 `````` ) // END sum(runUpCounter) ) // END sum(unitStarttype) // Units in shutdown phase need to keep up with the shutdown rate + p_gnu(grid, node, unit, 'unitSizeGen') * sum(shutdownCounter(unit, counter)\${t_active(t+dt_trajectory(counter)) and uft_shutdownTrajectory(unit, f, t)}, // Sum over the shutdown intervals `````` Topi Rasku committed Apr 04, 2019 419 420 421 422 423 424 `````` + [ + v_shutdown_LP(unit, s, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) \${ uft_onlineLP_withPrevious(unit, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) } + v_shutdown_MIP(unit, s, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) \${ uft_onlineMIP_withPrevious(unit, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) } ] `````` Topi Rasku committed Jan 25, 2019 425 `````` * p_uCounter_shutdownMax(unit, counter) `````` Topi Rasku committed Jan 24, 2019 426 `````` ) // END sum(shutdownCounter) `````` 427 ``````; `````` Topi Rasku committed Oct 11, 2017 428 `````` `````` Niina Helistö committed Nov 01, 2018 429 430 ``````* --- Reserve Provision of Units with Investments ----------------------------- `````` Topi Rasku committed Apr 04, 2019 431 432 433 434 435 436 437 ``````q_reserveProvision(nuRescapable(restypeDirectionNode(restype, up_down, node), unit), sft(s, f, t)) \${ ord(t) <= tSolveFirst + p_nReserves(node, restype, 'reserve_length') and nuft(node, unit, f, t) and (unit_investLP(unit) or unit_investMIP(unit)) and not ft_reservesFixed(node, restype, f+df_reserves(node, restype, f, t), t) } .. `````` Erkka Rinne committed Nov 02, 2018 438 `````` + v_reserve(restype, up_down, node, unit, s, f+df_reserves(node, restype, f, t), t) `````` Niina Helistö committed Nov 01, 2018 439 440 441 442 443 444 445 446 447 448 449 450 451 `````` =L= + p_nuReserves(node, unit, restype, up_down) * [ + sum(grid, p_gnu(grid, node, unit, 'maxGen') + p_gnu(grid, node, unit, 'maxCons') ) // Reserve sets and variables are currently lacking the grid dimension... + sum(t_invest(t_)\${ ord(t_)<=ord(t) }, + v_invest_LP(unit, t_)\${unit_investLP(unit)} * sum(grid, p_gnu(grid, node, unit, 'unitSizeTot')) // Reserve sets and variables are currently lacking the grid dimension... + v_invest_MIP(unit, t_)\${unit_investMIP(unit)} * sum(grid, p_gnu(grid, node, unit, 'unitSizeTot')) // Reserve sets and variables are currently lacking the grid dimension... ) // END sum(t_) ] `````` Niina Helistö committed Nov 02, 2018 452 453 454 455 `````` * p_unit(unit, 'availability') // Taking into account availability... * [ // ... and capacity factor for flow units + sum(flowUnit(flow, unit), `````` Erkka Rinne committed Nov 02, 2018 456 `````` + ts_cf_(flow, node, f, t, s) `````` Niina Helistö committed Nov 02, 2018 457 458 `````` ) // END sum(flow) + 1\${not unit_flow(unit)} `````` Niina Helistö committed Nov 01, 2018 459 460 461 `````` ] // How to consider reserveReliability in the case of investments when we typically only have "realized" time steps? ; `````` Topi Rasku committed Oct 11, 2017 462 463 ``````* --- Unit Startup and Shutdown ----------------------------------------------- `````` Topi Rasku committed Apr 04, 2019 464 465 466 467 ``````q_startshut(ms(m, s), uft_online(unit, f, t)) \${ msft(m, s, f, t) }.. `````` Niina Helistö committed Aug 09, 2018 468 `````` // Units currently online `````` Erkka Rinne committed Nov 02, 2018 469 470 `````` + v_online_LP (unit, s, f+df_central(f,t), t)\${uft_onlineLP (unit, f, t)} + v_online_MIP(unit, s, f+df_central(f,t), t)\${uft_onlineMIP(unit, f, t)} `````` Topi Rasku committed Oct 11, 2017 471 472 `````` // Units previously online `````` Niina Helistö committed Aug 09, 2018 473 `````` // The same units `````` Erkka Rinne committed Nov 02, 2018 474 `````` - v_online_LP (unit, s+ds(s,t), f+df(f,t+dt(t)), t+dt(t))\${ uft_onlineLP_withPrevious(unit, f+df(f,t+dt(t)), t+dt(t)) `````` Niina Helistö committed Aug 09, 2018 475 `````` and not uft_aggregator_first(unit, f, t) } // This reaches to tFirstSolve when dt = -1 `````` Erkka Rinne committed Nov 02, 2018 476 `````` - v_online_MIP(unit, s+ds(s,t), f+df(f,t+dt(t)), t+dt(t))\${ uft_onlineMIP_withPrevious(unit, f+df(f,t+dt(t)), t+dt(t)) `````` Niina Helistö committed Aug 09, 2018 477 478 479 480 `````` and not uft_aggregator_first(unit, f, t) } // Aggregated units just before they are turned into aggregator units - sum(unit_\${unitAggregator_unit(unit, unit_)}, `````` Erkka Rinne committed Nov 02, 2018 481 482 `````` + v_online_LP (unit_, s, f+df(f,t+dt(t)), t+dt(t))\${uft_onlineLP_withPrevious(unit_, f+df(f,t+dt(t)), t+dt(t))} + v_online_MIP(unit_, s, f+df(f,t+dt(t)), t+dt(t))\${uft_onlineMIP_withPrevious(unit_, f+df(f,t+dt(t)), t+dt(t))} `````` Niina Helistö committed Aug 15, 2018 483 `````` )\${uft_aggregator_first(unit, f, t)} // END sum(unit_) `````` Topi Rasku committed Nov 02, 2017 484 `````` `````` Juha Kiviluoma committed Apr 06, 2018 485 486 `````` =E= `````` Topi Rasku committed Oct 11, 2017 487 `````` // Unit startup and shutdown `````` Juha Kiviluoma committed Jul 31, 2018 488 `````` `````` Niina Helistö committed Aug 09, 2018 489 `````` // Add startup of units dt_toStartup before the current t (no start-ups for aggregator units before they become active) `````` Topi Rasku committed Nov 07, 2017 490 `````` + sum(unitStarttype(unit, starttype), `````` Topi Rasku committed Apr 04, 2019 491 `````` + v_startup_LP(unit, starttype, s, f+df(f,t+dt_toStartup(unit, t)), t+dt_toStartup(unit, t)) `````` Topi Rasku committed Apr 04, 2019 492 `````` \${ uft_onlineLP_withPrevious(unit, f+df(f,t+dt_toStartup(unit, t)), t+dt_toStartup(unit, t)) } `````` Topi Rasku committed Apr 04, 2019 493 `````` + v_startup_MIP(unit, starttype, s, f+df(f,t+dt_toStartup(unit, t)), t+dt_toStartup(unit, t)) `````` Topi Rasku committed Apr 04, 2019 494 `````` \${ uft_onlineMIP_withPrevious(unit, f+df(f,t+dt_toStartup(unit, t)), t+dt_toStartup(unit, t)) } `````` Niina Helistö committed Aug 09, 2018 495 `````` )\${not [unit_aggregator(unit) and ord(t) + dt_toStartup(unit, t) <= tSolveFirst + p_unit(unit, 'lastStepNotAggregated')]} // END sum(starttype) `````` Juha Kiviluoma committed Jul 31, 2018 496 `````` `````` Niina Helistö committed Aug 09, 2018 497 498 499 500 `````` // NOTE! According to 3d_setVariableLimits, // cannot start a unit if the time when the unit would become online is outside // the horizon when the unit has an online variable // --> no need to add start-ups of aggregated units to aggregator units `````` Juha Kiviluoma committed Jul 31, 2018 501 `````` `````` Niina Helistö committed Aug 09, 2018 502 `````` // Shutdown of units at time t `````` Topi Rasku committed Apr 04, 2019 503 504 505 506 `````` - v_shutdown_LP(unit, s, f, t) \${ uft_onlineLP(unit, f, t) } - v_shutdown_MIP(unit, s, f, t) \${ uft_onlineMIP(unit, f, t) } `````` 507 ``````; `````` Topi Rasku committed Oct 11, 2017 508 `````` `````` 509 ``````*--- Startup Type ------------------------------------------------------------- `````` Topi Rasku committed Nov 06, 2017 510 ``````// !!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! `````` Topi Rasku committed Nov 06, 2017 511 512 513 ``````// This formulation doesn't work as intended when unitCount > 1, as one recent // shutdown allows for multiple hot/warm startups on subsequent time steps. // Pending changes. `````` 514 `````` `````` Topi Rasku committed Apr 04, 2019 515 516 517 518 ``````q_startuptype(ms(m, s), starttypeConstrained(starttype), uft_online(unit, f, t)) \${ msft(m, s, f, t) and unitStarttype(unit, starttype) } .. `````` 519 520 `````` // Startup type `````` Topi Rasku committed Apr 04, 2019 521 522 `````` + v_startup_LP(unit, starttype, s, f, t)\${ uft_onlineLP(unit, f, t) } + v_startup_MIP(unit, starttype, s, f, t)\${ uft_onlineMIP(unit, f, t) } `````` 523 524 525 526 `````` =L= // Subunit shutdowns within special startup timeframe `````` Topi Rasku committed Apr 04, 2019 527 528 529 530 531 532 533 `````` + sum(unitCounter(unit, counter)\${ dt_starttypeUnitCounter(starttype, unit, counter) and t_active(t+(dt_starttypeUnitCounter(starttype, unit, counter)+1)) }, + v_shutdown_LP(unit, s, f+df(f,t+(dt_starttypeUnitCounter(starttype, unit, counter)+1)), t+(dt_starttypeUnitCounter(starttype, unit, counter)+1)) \${ uft_onlineLP_withPrevious(unit, f+df(f,t+(dt_starttypeUnitCounter(starttype, unit, counter)+1)), t+(dt_starttypeUnitCounter(starttype, unit, counter)+1)) } + v_shutdown_MIP(unit, s, f+df(f,t+(dt_starttypeUnitCounter(starttype, unit, counter)+1)), t+(dt_starttypeUnitCounter(starttype, unit, counter)+1)) \${ uft_onlineMIP_withPrevious(unit, f+df(f,t+(dt_starttypeUnitCounter(starttype, unit, counter)+1)), t+(dt_starttypeUnitCounter(starttype, unit, counter)+1)) } `````` Niina Helistö committed Aug 15, 2018 534 535 536 `````` ) // END sum(counter) // NOTE: for aggregator units, shutdowns for aggregated units are not considered `````` 537 ``````; `````` 538 `````` `````` Juha Kiviluoma committed Apr 03, 2018 539 `````` `````` 540 541 ``````*--- Online Limits with Startup Type Constraints and Investments -------------- `````` Topi Rasku committed Apr 04, 2019 542 543 544 545 546 547 548 549 550 ``````q_onlineLimit(ms(m, s), uft_online(unit, f, t)) \${ msft(m, s, f, t) and { p_unit(unit, 'minShutdownHours') or p_u_runUpTimeIntervals(unit) or unit_investLP(unit) or unit_investMIP(unit) }} .. `````` 551 `````` // Online variables `````` Erkka Rinne committed Nov 02, 2018 552 553 `````` + v_online_LP(unit, s, f+df_central(f,t), t)\${uft_onlineLP(unit, f, t)} + v_online_MIP(unit, s, f+df_central(f,t), t)\${uft_onlineMIP(unit, f ,t)} `````` 554 555 556 557 558 559 `````` =L= // Number of existing units + p_unit(unit, 'unitCount') `````` Niina Helistö committed May 25, 2018 560 `````` // Number of units unable to become online due to restrictions `````` Topi Rasku committed Apr 04, 2019 561 562 563 564 565 566 567 `````` - sum(unitCounter(unit, counter)\${ dt_downtimeUnitCounter(unit, counter) and t_active(t+(dt_downtimeUnitCounter(unit, counter) + 1)) }, + v_shutdown_LP(unit, s, f+df(f,t+(dt_downtimeUnitCounter(unit, counter) + 1)), t+(dt_downtimeUnitCounter(unit, counter) + 1)) \${ uft_onlineLP_withPrevious(unit, f+df(f,t+(dt_downtimeUnitCounter(unit, counter) + 1)), t+(dt_downtimeUnitCounter(unit, counter) + 1)) } + v_shutdown_MIP(unit, s, f+df(f,t+(dt_downtimeUnitCounter(unit, counter) + 1)), t+(dt_downtimeUnitCounter(unit, counter) + 1)) \${ uft_onlineMIP_withPrevious(unit, f+df(f,t+(dt_downtimeUnitCounter(unit, counter) + 1)), t+(dt_downtimeUnitCounter(unit, counter) + 1)) } `````` Niina Helistö committed Aug 15, 2018 568 569 570 `````` ) // END sum(counter) // Number of units unable to become online due to restrictions (aggregated units in the past horizon or if they have an online variable) `````` Topi Rasku committed Jan 24, 2019 571 `````` - sum(unitAggregator_unit(unit, unit_), `````` Topi Rasku committed Apr 04, 2019 572 573 574 575 576 577 578 `````` + sum(unitCounter(unit, counter)\${ dt_downtimeUnitCounter(unit, counter) and t_active(t+(dt_downtimeUnitCounter(unit, counter) + 1)) }, + v_shutdown_LP(unit_, s, f+df(f,t+(dt_downtimeUnitCounter(unit, counter) + 1)), t+(dt_downtimeUnitCounter(unit, counter) + 1)) \${ uft_onlineLP_withPrevious(unit_, f+df(f,t+(dt_downtimeUnitCounter(unit, counter) + 1)), t+(dt_downtimeUnitCounter(unit, counter) + 1)) } + v_shutdown_MIP(unit_, s, f+df(f,t+(dt_downtimeUnitCounter(unit, counter) + 1)), t+(dt_downtimeUnitCounter(unit, counter) + 1)) \${ uft_onlineMIP_withPrevious(unit_, f+df(f,t+(dt_downtimeUnitCounter(unit, counter) + 1)), t+(dt_downtimeUnitCounter(unit, counter) + 1)) } `````` Niina Helistö committed Aug 15, 2018 579 580 `````` ) // END sum(counter) )\${unit_aggregator(unit)} // END sum(unit_) `````` 581 582 583 `````` // Investments into units + sum(t_invest(t_)\${ord(t_)<=ord(t)}, `````` Niina Helistö committed Mar 26, 2018 584 585 `````` + v_invest_LP(unit, t_)\${unit_investLP(unit)} + v_invest_MIP(unit, t_)\${unit_investMIP(unit)} `````` 586 587 588 `````` ) // END sum(t_invest) ; `````` Juha Kiviluoma committed Apr 10, 2018 589 590 591 592 ``````*--- Both q_offlineAfterShutdown and q_onlineOnStartup work when there is only one unit. * These equations prohibit single units turning on and off at the same time step. * Unfortunately there seems to be no way to prohibit this when unit count is > 1. * (it shouldn't be worthwhile anyway if there is a startup cost, but it can fall within the solution gap). `````` Topi Rasku committed Apr 04, 2019 593 594 595 596 ``````q_onlineOnStartUp(s_active(s), uft_online(unit, f, t)) \${ sft(s, f, t) and sum(starttype, unitStarttype(unit, starttype)) }.. `````` Juha Kiviluoma committed Apr 06, 2018 597 598 `````` // Units currently online `````` Erkka Rinne committed Nov 02, 2018 599 600 `````` + v_online_LP(unit, s, f+df_central(f,t), t)\${uft_onlineLP(unit, f, t)} + v_online_MIP(unit, s, f+df_central(f,t), t)\${uft_onlineMIP(unit, f, t)} `````` Juha Kiviluoma committed Apr 06, 2018 601 602 603 604 `````` =G= + sum(unitStarttype(unit, starttype), `````` Topi Rasku committed Apr 04, 2019 605 `````` + v_startup_LP(unit, starttype, s, f+df(f,t+dt_toStartup(unit, t)), t+dt_toStartup(unit, t)) //dt_toStartup displaces the time step to the one where the unit would be started up in order to reach online at t `````` Topi Rasku committed Apr 04, 2019 606 `````` \${ uft_onlineLP_withPrevious(unit, f+df(f,t+dt_toStartup(unit, t)), t+dt_toStartup(unit, t)) } `````` Topi Rasku committed Apr 04, 2019 607 `````` + v_startup_MIP(unit, starttype, s, f+df(f,t+dt_toStartup(unit, t)), t+dt_toStartup(unit, t)) //dt_toStartup displaces the time step to the one where the unit would be started up in order to reach online at t `````` Topi Rasku committed Apr 04, 2019 608 `````` \${ uft_onlineMIP_withPrevious(unit, f+df(f,t+dt_toStartup(unit, t)), t+dt_toStartup(unit, t)) } `````` Juha Kiviluoma committed Apr 06, 2018 609 610 611 `````` ) // END sum(starttype) ; `````` Topi Rasku committed Apr 04, 2019 612 613 614 615 ``````q_offlineAfterShutdown(s_active(s), uft_online(unit, f, t)) \${ sft(s, f, t) and sum(starttype, unitStarttype(unit, starttype)) }.. `````` Juha Kiviluoma committed Apr 06, 2018 616 `````` `````` Juha Kiviluoma committed Apr 10, 2018 617 618 619 620 621 `````` // Number of existing units + p_unit(unit, 'unitCount') // Investments into units + sum(t_invest(t_)\${ord(t_)<=ord(t)}, `````` Niina Helistö committed Apr 10, 2018 622 623 `````` + v_invest_LP(unit, t_)\${unit_investLP(unit)} + v_invest_MIP(unit, t_)\${unit_investMIP(unit)} `````` Juha Kiviluoma committed Apr 10, 2018 624 625 `````` ) // END sum(t_invest) `````` Juha Kiviluoma committed Apr 06, 2018 626 `````` // Units currently online `````` Erkka Rinne committed Nov 02, 2018 627 628 `````` - v_online_LP(unit, s, f+df_central(f,t), t)\${uft_onlineLP(unit, f, t)} - v_online_MIP(unit, s, f+df_central(f,t), t)\${uft_onlineMIP(unit, f, t)} `````` Juha Kiviluoma committed Apr 06, 2018 629 630 631 `````` =G= `````` Topi Rasku committed Apr 04, 2019 632 633 634 635 `````` + v_shutdown_LP(unit, s, f, t) \${ uft_onlineLP(unit, f, t) } + v_shutdown_MIP(unit, s, f, t) \${ uft_onlineMIP(unit, f, t) } `````` Juha Kiviluoma committed Apr 06, 2018 636 637 ``````; `````` 638 639 ``````*--- Minimum Unit Uptime ------------------------------------------------------ `````` Topi Rasku committed Apr 04, 2019 640 641 642 643 ``````q_onlineMinUptime(ms(m, s), uft_online(unit, f, t)) \${ msft(m, s, f, t) and p_unit(unit, 'minOperationHours') } .. `````` 644 645 `````` // Units currently online `````` Erkka Rinne committed Nov 02, 2018 646 647 `````` + v_online_LP(unit, s, f+df_central(f,t), t)\${uft_onlineLP(unit, f, t)} + v_online_MIP(unit, s, f+df_central(f,t), t)\${uft_onlineMIP(unit, f, t)} `````` 648 649 650 651 `````` =G= // Units that have minimum operation time requirements active `````` Topi Rasku committed Apr 04, 2019 652 653 654 `````` + sum(unitCounter(unit, counter)\${ dt_uptimeUnitCounter(unit, counter) and t_active(t+(dt_uptimeUnitCounter(unit, counter)+dt_toStartup(unit, t) + 1)) // Don't sum over counters that don't point to an active time step }, `````` Topi Rasku committed Nov 07, 2017 655 `````` + sum(unitStarttype(unit, starttype), `````` Topi Rasku committed Apr 04, 2019 656 `````` + v_startup_LP(unit, starttype, s, f+df(f,t+(dt_uptimeUnitCounter(unit, counter)+dt_toStartup(unit, t) + 1)), t+(dt_uptimeUnitCounter(unit, counter)+dt_toStartup(unit, t) + 1)) `````` Topi Rasku committed Apr 04, 2019 657 `````` \${ uft_onlineLP_withPrevious(unit, f+df(f,t+(dt_uptimeUnitCounter(unit, counter)+dt_toStartup(unit, t) + 1)), t+(dt_uptimeUnitCounter(unit, counter)+dt_toStartup(unit, t) + 1)) } `````` Topi Rasku committed Apr 04, 2019 658 `````` + v_startup_MIP(unit, starttype, s, f+df(f,t+(dt_uptimeUnitCounter(unit, counter)+dt_toStartup(unit, t) + 1)), t+(dt_uptimeUnitCounter(unit, counter)+dt_toStartup(unit, t) + 1)) `````` Topi Rasku committed Apr 04, 2019 659 `````` \${ uft_onlineMIP_withPrevious(unit, f+df(f,t+(dt_uptimeUnitCounter(unit, counter)+dt_toStartup(unit, t) + 1)), t+(dt_uptimeUnitCounter(unit, counter)+dt_toStartup(unit, t) + 1)) } `````` 660 `````` ) // END sum(starttype) `````` Niina Helistö committed Aug 15, 2018 661 662 663 `````` ) // END sum(counter) // Units that have minimum operation time requirements active (aggregated units in the past horizon or if they have an online variable) `````` Topi Rasku committed Oct 19, 2018 664 `````` + sum(unitAggregator_unit(unit, unit_), `````` Topi Rasku committed Apr 04, 2019 665 666 667 `````` + sum(unitCounter(unit, counter)\${ dt_uptimeUnitCounter(unit, counter) and t_active(t+(dt_uptimeUnitCounter(unit, counter)+dt_toStartup(unit, t) + 1)) // Don't sum over counters that don't point to an active time step }, `````` Niina Helistö committed Aug 15, 2018 668 `````` + sum(unitStarttype(unit, starttype), `````` Topi Rasku committed Apr 04, 2019 669 `````` + v_startup_LP(unit, starttype, s, f+df(f,t+(dt_uptimeUnitCounter(unit, counter)+dt_toStartup(unit, t) + 1)), t+(dt_uptimeUnitCounter(unit, counter)+dt_toStartup(unit, t) + 1)) `````` Topi Rasku committed Apr 04, 2019 670 `````` \${ uft_onlineLP_withPrevious(unit, f+df(f,t+(dt_uptimeUnitCounter(unit, counter)+dt_toStartup(unit, t) + 1)), t+(dt_uptimeUnitCounter(unit, counter)+dt_toStartup(unit, t) + 1)) } `````` Topi Rasku committed Apr 04, 2019 671 `````` + v_startup_MIP(unit, starttype, s, f+df(f,t+(dt_uptimeUnitCounter(unit, counter)+dt_toStartup(unit, t) + 1)), t+(dt_uptimeUnitCounter(unit, counter)+dt_toStartup(unit, t) + 1)) `````` Topi Rasku committed Apr 04, 2019 672 `````` \${ uft_onlineMIP_withPrevious(unit, f+df(f,t+(dt_uptimeUnitCounter(unit, counter)+dt_toStartup(unit, t) + 1)), t+(dt_uptimeUnitCounter(unit, counter)+dt_toStartup(unit, t) + 1)) } `````` Niina Helistö committed Aug 15, 2018 673 674 675 `````` ) // END sum(starttype) ) // END sum(counter) )\${unit_aggregator(unit)} // END sum(unit_) `````` 676 677 ``````; `````` Niina Helistö committed Jan 28, 2019 678 679 ``````* --- Cyclic Boundary Conditions for Online State ----------------------------- `````` Topi Rasku committed Apr 04, 2019 680 681 682 683 684 ``````q_onlineCyclic(uss_bound(unit, s_, s), m) \${ ms(m, s_) and ms(m, s) and tSolveFirst = mSettings(m, 't_start') }.. `````` Niina Helistö committed Jan 28, 2019 685 686 687 688 `````` // Initial value of the state of the unit at the start of the sample + sum(mst_start(m, s, t), + sum(sft(s, f, t), `````` Topi Rasku committed Apr 12, 2019 689 690 691 692 `````` + v_online_LP(unit, s, f+df(f,t+dt(t)), t+dt(t)) \${uft_onlineLP_withPrevious(unit, f+df(f,t+dt(t)), t+dt(t))} + v_online_MIP(unit, s, f+df(f,t+dt(t)), t+dt(t)) \${uft_onlineMIP_withPrevious(unit, f+df(f,t+dt(t)), t+dt(t))} `````` Niina Helistö committed Jan 28, 2019 693 694 695 696 697 698 699 700 701 702 703 704 705 706 `````` ) // END sum(ft) ) // END sum(mst_start) =E= // State of the unit at the end of the sample + sum(mst_end(m, s_, t_), + sum(sft(s_, f_, t_), + v_online_LP(unit, s_, f_, t_)\${uft_onlineLP(unit, f_, t_)} + v_online_MIP(unit, s_, f_, t_)\${uft_onlineMIP(unit, f_, t_)} ) // END sum(ft) ) // END sum(mst_end) ; `````` Topi Rasku committed Oct 11, 2017 707 ``````* --- Ramp Constraints -------------------------------------------------------- `````` 708 `````` `````` Topi Rasku committed Apr 04, 2019 709 710 711 712 ``````q_genRamp(ms(m, s), gnuft_ramp(grid, node, unit, f, t)) \${ ord(t) > msStart(m, s) + 1 and msft(m, s, f, t) } .. `````` Topi Rasku committed Oct 11, 2017 713 `````` `````` Topi Rasku committed Jan 25, 2019 714 715 `````` + v_genRamp(grid, node, unit, s, f, t) * p_stepLength(m, f, t) `````` Niina Helistö committed Jul 12, 2018 716 `````` `````` Topi Rasku committed Apr 03, 2017 717 `````` =E= `````` Niina Helistö committed Jul 12, 2018 718 `````` `````` Niina Helistö committed Aug 09, 2018 719 `````` // Change in generation over the interval: v_gen(t) - v_gen(t-1) `````` Erkka Rinne committed Nov 02, 2018 720 `````` + v_gen(grid, node, unit, s, f, t) `````` 721 `````` `````` Niina Helistö committed Aug 09, 2018 722 `````` // Unit generation at t-1 (except aggregator units right before the aggregation threshold, see next term) `````` Erkka Rinne committed Nov 02, 2018 723 `````` - v_gen(grid, node, unit, s+ds(s,t), f+df(f,t+dt(t)), t+dt(t))\${not uft_aggregator_first(unit, f, t)} `````` Niina Helistö committed Aug 09, 2018 724 725 `````` // Unit generation at t-1, aggregator units right before the aggregation threshold + sum(unit_\${unitAggregator_unit(unit, unit_)}, `````` Erkka Rinne committed Nov 02, 2018 726 `````` - v_gen(grid, node, unit_, s+ds(s,t), f+df(f,t+dt(t)), t+dt(t)) `````` Niina Helistö committed Aug 09, 2018 727 `````` )\${uft_aggregator_first(unit, f, t)} `````` Topi Rasku committed Apr 03, 2017 728 ``````; `````` Topi Rasku committed Oct 11, 2017 729 `````` `````` 730 ``````* --- Ramp Up Limits ---------------------------------------------------------- `````` 731 `````` `````` Topi Rasku committed Apr 04, 2019 732 733 734 735 736 737 738 739 740 741 742 743 ``````q_rampUpLimit(ms(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') and [ sum(restype, nuRescapable(restype, 'up', node, unit)) or uft_online(unit, f, t) or unit_investLP(unit) or unit_investMIP(unit) ] } .. // Ramp speed of the unit? `````` Erkka Rinne committed Nov 02, 2018 744 `````` + v_genRamp(grid, node, unit, s, f, t) `````` 745 `````` + sum(nuRescapable(restype, 'up', node, unit)\${ord(t) < tSolveFirst + p_nReserves(node, restype, 'reserve_length')}, `````` Erkka Rinne committed Nov 02, 2018 746 `````` + v_reserve(restype, 'up', node, unit, s, f+df_reserves(node, restype, f, t), t) // (v_reserve can be used only if the unit is capable of providing a particular reserve) `````` Niina Helistö committed Jul 12, 2018 747 748 749 750 751 `````` ) // END sum(nuRescapable) / p_stepLength(m, f, t) =L= `````` Juha Kiviluoma committed May 17, 2018 752 `````` // Ramping capability of units without an online variable `````` Niina Helistö committed Jul 12, 2018 753 754 755 756 757 758 759 760 761 762 763 764 `````` + ( + ( 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_gnu(grid, node, unit, 'maxRampUp') * 60 // Unit conversion from [p.u./min] to [p.u./h] `````` Juha Kiviluoma committed May 17, 2018 765 `````` // Ramping capability of units with an online variable `````` Niina Helistö committed Jul 12, 2018 766 `````` + ( `````` Topi Rasku committed Apr 12, 2019 767 768 769 770 `````` + v_online_LP(unit, s, f+df_central(f,t), t) \${uft_onlineLP(unit, f, t)} + v_online_MIP(unit, s, f+df_central(f,t), t) \${uft_onlineMIP(unit, f, t)} `````` Niina Helistö committed Jul 12, 2018 771 772 773 774 775 `````` ) * p_gnu(grid, node, unit, 'unitSizeTot') * p_gnu(grid, node, unit, 'maxRampUp') * 60 // Unit conversion from [p.u./min] to [p.u./h] `````` Niina Helistö committed Mar 08, 2019 776 777 778 779 780 781 782 783 784 785 786 787 788 `````` // Generation units not be able to ramp from zero to min. load within one time interval according to their maxRampUp + sum(unitStarttype(unit, starttype)\${ uft_online(unit, f, t) and gnu_output(grid, node, unit) and not uft_startupTrajectory(unit, f, t) and ( + sum(suft(effGroup, unit, f, t), // Uses the minimum 'lb' for the current efficiency approximation + p_effGroupUnit(effGroup, unit, 'lb')\${not ts_effGroupUnit(effGroup, unit, 'lb', f, t)} + ts_effGroupUnit(effGroup, unit, 'lb', f, t) ) // END sum(effGroup) / p_stepLength(m, f, t) - p_gnu(grid, node, unit, 'maxRampUp') * 60 > 0 ) }, `````` Topi Rasku committed Apr 04, 2019 789 790 791 792 `````` + v_startup_LP(unit, starttype, s, f, t) \${ uft_onlineLP(unit, f, t) } + v_startup_MIP(unit, starttype, s, f, t) \${ uft_onlineMIP(unit, f, t) } `````` Niina Helistö committed Mar 08, 2019 793 794 795 796 797 798 799 800 801 802 803 804 `````` ) // END sum(starttype) * p_gnu(grid, node, unit, 'unitSizeTot') * ( + sum(suft(effGroup, unit, f, t), // Uses the minimum 'lb' for the current efficiency approximation + p_effGroupUnit(effGroup, unit, 'lb')\${not ts_effGroupUnit(effGroup, unit, 'lb', f, t)} + ts_effGroupUnit(effGroup, unit, 'lb', f, t) ) // END sum(effGroup) / p_stepLength(m, f, t) - p_gnu(grid, node, unit, 'maxRampUp') * 60 // Unit conversion from [p.u./min] to [p.u./h] ) // END * v_startup `````` Topi Rasku committed Jan 24, 2019 805 806 807 808 `````` // Units in the run-up phase need to keep up with the run-up rate + p_gnu(grid, node, unit, 'unitSizeTot') * sum(unitStarttype(unit, starttype)\${uft_startupTrajectory(unit, f, t)}, sum(runUpCounter(unit, counter)\${t_active(t+dt_trajectory(counter))}, // Sum over the run-up intervals `````` Topi Rasku committed Apr 04, 2019 809 810 `````` + [ + v_startup_LP(unit, starttype, s, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) `````` Topi Rasku committed Apr 04, 2019 811 `````` \${ uft_onlineLP_withPrevious(unit, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) } `````` Topi Rasku committed Apr 04, 2019 812 `````` + v_startup_MIP(unit, starttype, s, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) `````` Topi Rasku committed Apr 04, 2019 813 `````` \${ uft_onlineMIP_withPrevious(unit, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) } `````` Topi Rasku committed Apr 04, 2019 814 `````` ] `````` Topi Rasku committed Jan 24, 2019 815 816 817 818 819 820 821 822 `````` * [ + p_unit(unit, 'rampSpeedToMinLoad') + ( p_gnu(grid, node, unit, 'maxRampUp') - p_unit(unit, 'rampSpeedToMinLoad') )\${ not runUpCounter(unit, counter+1) } // Ramp speed adjusted for the last run-up interval * ( p_u_runUpTimeIntervalsCeil(unit) - p_u_runUpTimeIntervals(unit) ) ] * 60 // Unit conversion from [p.u./min] into [p.u./h] ) // END sum(runUpCounter) ) // END sum(unitStarttype) `````` Niina Helistö committed Jul 12, 2018 823 `````` `````` Niina Helistö committed Mar 08, 2019 824 `````` // Shutdown of consumption units according to maxRampUp `````` Topi Rasku committed Apr 04, 2019 825 826 827 828 829 830 `````` + [ + v_shutdown_LP(unit, s, f, t) \${uft_onlineLP(unit, f, t) and gnu_input(grid, node, unit)} + v_shutdown_MIP(unit, s, f, t) \${uft_onlineMIP(unit, f, t) and gnu_input(grid, node, unit)} ] `````` Niina Helistö committed Jul 12, 2018 831 `````` * p_gnu(grid, node, unit, 'unitSizeTot') `````` Niina Helistö committed Mar 08, 2019 832 833 834 `````` * p_gnu(grid, node, unit, 'maxRampUp') * 60 // Unit conversion from [p.u./min] to [p.u./h] // Consumption units not be able to ramp from min. load to zero within one time interval according to their maxRampUp `````` Topi Rasku committed Apr 04, 2019 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 `````` + [ + v_shutdown_LP(unit, s, f, t) \${ uft_onlineLP(unit, f, t) } + v_shutdown_MIP(unit, s, f, t) \${ uft_onlineMIP(unit, f, t) } ] \${ gnu_input(grid, node, unit) and ( + sum(suft(effGroup, unit, f, t), // Uses the minimum 'lb' for the current efficiency approximation + p_effGroupUnit(effGroup, unit, 'lb')\${not ts_effGroupUnit(effGroup, unit, 'lb', f, t)} + ts_effGroupUnit(effGroup, unit, 'lb', f, t) ) // END sum(effGroup) / p_stepLength(m, f, t) - p_gnu(grid, node, unit, 'maxRampUp') * 60 > 0 ) } `````` Niina Helistö committed Mar 08, 2019 851 852 853 854 855 856 857 858 859 `````` * p_gnu(grid, node, unit, 'unitSizeTot') * ( + sum(suft(effGroup, unit, f, t), // Uses the minimum 'lb' for the current efficiency approximation + p_effGroupUnit(effGroup, unit, 'lb')\${not ts_effGroupUnit(effGroup, unit, 'lb', f, t)} + ts_effGroupUnit(effGroup, unit, 'lb', f, t) ) // END sum(effGroup) / p_stepLength(m, f, t) - p_gnu(grid, node, unit, 'maxRampUp') * 60 // Unit conversion from [p.u./min] to [p.u./h] `````` Niina Helistö committed Mar 11, 2019 860 `````` ) // END * v_shutdown `````` Topi Rasku committed Mar 21, 2017 861 ``````; `````` Juha Kiviluoma committed Apr 06, 2018 862 `````` `````` 863 ``````* --- Ramp Down Limits -------------------------------------------------------- `````` 864 `````` `````` Topi Rasku committed Apr 04, 2019 865 866 867 868 869 870 871 872 873 874 875 876 ``````q_rampDownLimit(ms(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') and [ sum(restype, nuRescapable(restype, 'down', node, unit)) or uft_online(unit, f, t) or unit_investLP(unit) or unit_investMIP(unit) ] } .. // Ramp speed of the unit? `````` Erkka Rinne committed Nov 02, 2018 877 `````` + v_genRamp(grid, node, unit, s, f, t) `````` 878 `````` - sum(nuRescapable(restype, 'down', node, unit)\${ord(t) < tSolveFirst + p_nReserves(node, restype, 'reserve_length')}, `````` Erkka Rinne committed Nov 02, 2018 879 `````` + v_reserve(restype, 'down', node, unit, s, f+df_reserves(node, restype, f, t), t) // (v_reserve can be used only if the unit is capable of providing a particular reserve) `````` Niina Helistö committed Jul 12, 2018 880 881 882 883 884 `````` ) // END sum(nuRescapable) / p_stepLength(m, f, t) =G= `````` 885 `````` // Ramping capability of units without online variable `````` Niina Helistö committed Jul 12, 2018 886 `````` - ( `````` Topi Rasku committed Apr 12, 2019 887 888 `````` + ( p_gnu(grid, node, unit, 'maxGen') + p_gnu(grid, node, unit, 'maxCons') ) \${not uft_online(unit, f, t)} `````` Niina Helistö committed Jul 12, 2018 889 `````` + sum(t_invest(t_)\${ ord(t_)<=ord(t) }, `````` Topi Rasku committed Apr 12, 2019 890 891 `````` + v_invest_LP(unit, t_) \${not uft_onlineLP(unit, f, t) and unit_investLP(unit)} `````` Niina Helistö committed Jul 12, 2018 892 `````` * p_gnu(grid, node, unit, 'unitSizeTot') `````` Topi Rasku committed Apr 12, 2019 893 894 `````` + v_invest_MIP(unit, t_) \${not uft_onlineMIP(unit, f, t) and unit_investMIP(unit)} `````` Niina Helistö committed Jul 12, 2018 895 896 897 898 899 900 `````` * p_gnu(grid, node, unit, 'unitSizeTot') ) ) * p_gnu(grid, node, unit, 'maxRampDown') * 60 // Unit conversion from [p.u./min] to [p.u./h] `````` Juha Kiviluoma committed May 17, 2018 901 `````` // Ramping capability of units that are online `````` Niina Helistö committed Jul 12, 2018 902 `````` - ( `````` Topi Rasku committed Apr 12, 2019 903 904 905 906 `````` + v_online_LP(unit, s, f+df_central(f,t), t) \${uft_onlineLP(unit, f, t)} + v_online_MIP(unit, s, f+df_central(f,t), t) \${uft_onlineMIP(unit, f, t)} `````` Niina Helistö committed Jul 12, 2018 907 908 909 910 911 `````` ) * p_gnu(grid, node, unit, 'unitSizeTot') * p_gnu(grid, node, unit, 'maxRampDown') * 60 // Unit conversion from [p.u./min] to [p.u./h] `````` Niina Helistö committed Mar 08, 2019 912 `````` // Shutdown of generation units according to maxRampDown `````` Topi Rasku committed Apr 04, 2019 913 914 915 916 917 918 919 920 921 `````` - [ + v_shutdown_LP(unit, s, f, t) \${ uft_onlineLP(unit, f, t) } + v_shutdown_MIP(unit, s, f, t) \${ uft_onlineMIP(unit, f, t) } ] \${ gnu_output(grid, node, unit) and not uft_shutdownTrajectory(unit, f, t) } `````` Niina Helistö committed Jul 12, 2018 922 `````` * p_gnu(grid, node, unit, 'unitSizeTot') `````` Niina Helistö committed Mar 08, 2019 923 924 925 `````` * p_gnu(grid, node, unit, 'maxRampDown') * 60 // Unit conversion from [p.u./min] to [p.u./h] // Generation units not be able to ramp from min. load to zero within one time interval according to their maxRampDown `````` Topi Rasku committed Apr 04, 2019 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 `````` - [ + v_shutdown_LP(unit, s, f, t) \${ uft_onlineLP(unit, f, t) } + v_shutdown_MIP(unit, s, f, t) \${ uft_onlineMIP(unit, f, t) } ] \${ gnu_output(grid, node, unit) and not uft_shutdownTrajectory(unit, f, t) and ( + sum(suft(effGroup, unit, f, t), // Uses the minimum 'lb' for the current efficiency approximation + p_effGroupUnit(effGroup, unit, 'lb')\${not ts_effGroupUnit(effGroup, unit, 'lb', f, t)} + ts_effGroupUnit(effGroup, unit, 'lb', f, t) ) // END sum(effGroup) / p_stepLength(m, f, t) - p_gnu(grid, node, unit, 'maxRampDown') * 60 > 0 ) } `````` Niina Helistö committed Mar 08, 2019 943 944 945 946 947 948 949 950 951 952 `````` * p_gnu(grid, node, unit, 'unitSizeTot') * ( + sum(suft(effGroup, unit, f, t), // Uses the minimum 'lb' for the current efficiency approximation + p_effGroupUnit(effGroup, unit, 'lb')\${not ts_effGroupUnit(effGroup, unit, 'lb', f, t)} + ts_effGroupUnit(effGroup, unit, 'lb', f, t) ) // END sum(effGroup) / p_stepLength(m, f, t) - p_gnu(grid, node, unit, 'maxRampDown') * 60 // Unit conversion from [p.u./min] to [p.u./h] ) // END * v_shutdown `````` Niina Helistö committed Jul 11, 2018 953 `````` `````` Topi Rasku committed Jan 24, 2019 954 955 `````` // Units in shutdown phase need to keep up with the shutdown ramp rate - p_gnu(grid, node, unit, 'unitSizeGen') `````` Topi Rasku committed Jan 25, 2019 956 957 `````` * [ + sum(shutdownCounter(unit, counter)\${t_active(t+dt_trajectory(counter)) and uft_shutdownTrajectory(unit, f, t)}, // Sum over the shutdown intervals `````` Topi Rasku committed Apr 04, 2019 958 959 960 961 962 963 `````` + [ + v_shutdown_LP(unit, s, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) \${ uft_onlineLP_withPrevious(unit, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) } + v_shutdown_MIP(unit, s, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) \${ uft_onlineMIP_withPrevious(unit, f+df(f, t+dt_trajectory(counter)), t+dt_trajectory(counter)) } ] `````` Topi Rasku committed Jan 25, 2019 964 `````` * [ `````` Niina Helistö committed Mar 13, 2019 965 966 967 `````` + p_gnu(grid, node, unit, 'maxRampDown')\${ not shutdownCounter(unit, counter-1) } // Normal maxRampDown limit applies to the time interval when v_shutdown happens, i.e. over the change from online to offline (symmetrical to v_startup) + p_unit(unit, 'rampSpeedFromMinLoad')\${ shutdownCounter(unit, counter-1) } // Normal trajectory ramping + ( p_gnu(grid, node, unit, 'maxRampDown') - p_unit(unit, 'rampSpeedFromMinLoad') )\${ shutdownCounter(unit, counter-1) and not shutdownCounter(unit, counter-2) } // Ramp speed adjusted for the first shutdown interval `````` Topi Rasku committed Jan 25, 2019 968 969 970 `````` * ( p_u_shutdownTimeIntervalsCeil(unit) - p_u_shutdownTimeIntervals(unit) ) ] ) // END sum(shutdownCounter) `````` Topi Rasku committed Jan 24, 2019 971 `````` // Units need to be able to shut down after shut down trajectory `````` Topi Rasku committed Apr 04, 2019 972 973 974 975 976 977 978 `````` + [ + v_shutdown_LP(unit, s, f+df(f, t+dt_toShutdown(unit, t)), t+dt_toShutdown(unit, t)) \${ uft_onlineLP_withPrevious(unit, f+df(f, t+dt_toShutdown(unit, t)), t+dt_toShutdown(unit, t)) } + v_shutdown_MIP(unit, s, f+df(f, t+dt_toShutdown(unit, t)), t+dt_toShutdown(unit, t)) \${ uft_onlineMIP_withPrevious(unit, f+df(f, t+dt_toShutdown(unit, t)), t+dt_toShutdown(unit, t)) } ] \${uft_shutdownTrajectory(unit, f, t)} `````` Niina Helistö committed Mar 13, 2019 979 980 981 982 983 `````` * [ + p_unit(unit, 'rampSpeedFromMinload') + ( p_gnu(grid, node, unit, 'maxRampDown') - p_unit(unit, 'rampSpeedFromMinLoad') )\${ sum(shutdownCounter(unit, counter), 1) = 1 } // Ramp speed adjusted if the unit has only one shutdown interval * ( p_u_shutdownTimeIntervalsCeil(unit) - p_u_shutdownTimeIntervals(unit) ) ] `````` Topi Rasku committed Jan 25, 2019 984 985 `````` ] * 60 // Unit conversion from [p.u./min] to [p.u./h] `````` Niina Helistö committed Mar 08, 2019 986 987 988 989 990 991 992 993 994 995 996 997 998 `````` // Consumption units not be able to ramp from zero to min. load within one time interval according to their maxRampDown - sum(unitStarttype(unit, starttype)\${ uft_online(unit, f, t) and gnu_input(grid, node, unit) and ( + sum(suft(effGroup, unit, f, t), // Uses the minimum 'lb' for the current efficiency approximation + p_effGroupUnit(effGroup, unit, 'lb')\${not ts_effGroupUnit(effGroup, unit, 'lb', f, t)} + ts_effGroupUnit(effGroup, unit, 'lb', f, t) ) // END sum(effGroup) / p_stepLength(m, f, t) - p_gnu(grid, node, unit, 'maxRampDown') * 60 > 0 ) }, `````` Topi Rasku committed Apr 04, 2019 999 1000 `````` + v_startup_LP(unit, starttype, s, f, t) \${ uft_onlineLP(unit, f, t) } ``````