--- jupytext: text_representation: extension: .md format_name: myst format_version: 0.13 jupytext_version: 1.16.2 kernelspec: display_name: Python 3 (ipykernel) language: python name: python3 --- (reserves)= # Reserves +++ SHOP can model 8 different types of reserve capacity products with different technical limitations. The names of the different reserve capacities are: - FCR-N up and down - FCR-D up and down - FRR up and down - RR up and down The names are based on a naming convention from the Norwegian TSO which is now outdated, but the reserve capacity products still persist. The **FCR-N** reserve capacity corresponds to capacity used for primary frequency control in the normal deviation band, defined as 50 $\pm$ 0.1 Hz in Norway. FCR-N reserve capacity can be defined for both upward and downward directions, though a symmetric requirement is usually imposed. The **FCR-D** reserve capacity is used for frequency control for deviations outside the normal range of 0.1 Hz, between 49.9 and 49.5 Hz and 50.1 and 50.5 Hz. **FRR** reserve capacity in the upward and downward directions are slower secondary reserves that still have to be rotating, while the tertiary reserves, labelled as **RR** reserves in SHOP, can be delivered even if the unit is not spinning (depending on the direction). The amount of reserves that can be delivered from a spinning [generating unit](generator) is normally limited by the head-dependent maximum and minimum production (see [max_prod_individual](generator:max_prod_individual) and [min_prod_individual](generator:min_prod_individual)), in addition to the optimized [production](generator:production) level. Active production constraints on the unit, see the [max_p_constr](generator:max_p_constr) and [min_p_constr](generator:max_p_constr), are also considered in the reserve capacity constraints. An example illustration of a reserve capacity allocation on a generator is shown in the figure below. The behaviour is similar for variable speed [pumps](pump), though the upward and downward directions are flipped since the pump is consuming power. ![](./img/reserve_allocation.png) As indicated by the picture above, the amount of reserve capacity possible to allocate on a single unit is closely linked to the unit commitment (on/off) constraints of the unit. It is therefore recommended that binary unit commitment variables are active for units participating in the delivery of reserve capacity in the full SHOP iterations. This can be controlled by the [mip_flag](plant:mip_flag) attribute on the [plant object](plant), or by the [set universal_mip](set_universal_mip) command. If a unit is delivering reserve capacity in a time period without binary on/off variables, unexpected behaviour due to the relaxed unit commitment constraints can occur. For instance, a fractional startup will shift the upper and lower limits in the figure above and alter the amount of reserve capacity that can be delivered. This can again lead to penalties in incremental iterations when all units are fully turned on or off. All of the reserve capacity functionality implemented in SHOP is tied to the **SHOP_RESERVE_GROUP** license. +++ ## Primary reserves The FCR-N and FCR-D reserves are limited by the droop setting of the unit in addition to the standard capacity limits visualized in the figure above. The amount of FCR reserves that can be delivered $\left(r_{fcr}\right)$ depends on the static nominal unit production $\left(P_{nom}\right)$, the size of the frequency band $\left(\Delta_f\right)$, and the inverse of the unit droop $\left(d\right)$: $r_{fcr} \leq 2\cdot\Delta_f\cdot P_{nom}\cdot \frac{1}{d}$. The nominal production is specified by the [p_nom](generator:p_nom) double attribute on the generator and pump objects, and the default value of the frequency band is 0.1 for FCR-N and 0.4 for FCR-D. The frequency ranges can be changed by setting the double attributes [fcr_n_band](global_settings:fcr_n_band) and [fcr_d_band](global_settings:fcr_d_band) on the [global_settings object](global_settings). The default behaviour in SHOP is to let the unit droop be a free variable bound between 1 and 12: $1 \leq d \leq 12$. A generator/pump TXY attribute called [fixed_droop](generator:fixed_droop) with an accompanying [fixed_droop_flag](generator:fixed_droop_flag) can be specified to lock the droop variable to the given value. Other TXY attributes on the generator/pump object can be specified to change the upper and lower droop bounds, namely [droop_min](generator:droop_min) and [droop_max](generator:droop_max). The output TXY attribute [droop_result](generator:droop_result) holds the optimized value of the droop. It is also possible to define a TXY attribute [droop_cost](generator:droop_cost) for each generator/pump, which adds a cost in the objective function for the droop variable. However, since the *inverse* of the droop appears in the FCR reserve limit constraint, SHOP uses the *inverse* of the droop as a variable to keep the constraints linear. This means that a high droop_cost will be applied to the inverse droop variable, favouring high droop settings (low inverse droop). The droop is often restricted to take on a set of discrete values in the real world, such as the integers from 1 to 12 instead of all real numbers in the same range. The **droop discretization functionality** under the **SHOP_DISCRETE_DROOP** license in SHOP is a heuristic approach for fixing the droop variables to pre-defined legal droop values between iterations. The [discrete droop example](discrete-droop) describes the droop discretization functionality in more detail. It is also possible for some generators to have separate droop settings for different FCR products. The **separate droop functionality** under the **SHOP_SEPARATE_DROOP** license allows a unit to have separate droop variables built for FCR-N, FCR-D up, and FCR-D down. Note that the droop for FCR-N is the same in both directions, while separate variables are built for FCR-D up and FCR-D down. The separate droop functionality is turned on for individual generators by setting the attribute [separate_droop](generator:separate_droop) to 1. FCR specific attributes can be used to bound the droop, such as [fcr_n_droop_min](generator:fcr_n_droop_min) and [fcr_d_up_fixed_droop](generator:fcr_d_up_fixed_droop). Please refer to the attribute table on the SHOP Portal a complete list of the available separate droop attributes. All of the separate droop attributes also exist on the [pump object](pump). It is possible to specify upper and lower production limits for the delivery of FCR reserves that are less strict than the normal minimum and maximum production limits of the unit. The TXY attributes [p_fcr_min](generator:p_fcr_min) and [p_fcr_max](generator:p_fcr_max) on the generator and pump objects overrides the normal bounds for FCR reserves. The same p_fcr_min and p_fcr_max attributes also exist on the [needle_combination object](needle_combination) that is used for [Pelton turbines](pelton), which allows each needle combination to have individual upper and lower FCR limits. Several system operators require that the procured fcr_n reserve capacity on every unit is symmetric in the upward and downward directions. The building of symmetric fcr_n constraints can be turned on and off by changing the [fcr_n_equality_flag](global_settings:fcr_n_equality_flag) attribute. In some cases, the TSO may stipulate a capacity limit rule which requires a certain fraction of a generator's maximal production capacity to be available if the unit is used to provide FCR reserve capacity. This constraint can be activated with the [fcr_mip_flag](generator:fcr_mip_flag) TXY attribute on the generator object, and will additional binary variables to enforce the limit. The free capacity limit can be changed from the default value of 2% by changing the [gen_reserve_min_free_cap_factor](global_settings:gen_reserve_min_free_cap_factor) attribute. +++ ## Secondary reserves Similar to FCR reserves, the secondary FRR reserves can only be delivered on running units. The FRR capacity it is possible to deliver is limited by the distance between scheduled production/consumption and the minimum and maximum generation limits, as well as the delivery of the other reserve types. Generator and needle_combination objects can specify [p_frr_max](generator:p_frr_max) and [p_frr_min](generator:p_frr_min) TXYs to extend the upper and lower production limit for delivering FRR reserves. This is especially useful for allowing pelton turbines with overlapping needle combinations to deliver FRR reserves over the whole operating range of the generator. Otherwise, the [p_min](needle_combination:p_min) and [p_max](needle_combination:p_max) limits on each individual needle_combination object will constrain the FRR delivery. +++ ## Tertiary reserves The RR reserve capacity can be delivered from units that are turned off, which means that RR up is handled in a special way for generators to allow delivery from offline units, and RR down is handled in an equivalent way for pumps. This requires binary variables for a precise modelling, so allowing SHOP to use binary variables for generators delivering RR up and pumps delivering RR down is especially beneficial. RR down reserves on generators also require special care since they can be delivered down to a full stop. Allowing delivery of RR down below the minimum production can be done by specifying the [p_rr_min](generator:p_rr_min) TXY attribute and setting its value to zero. This modelling does not require additional binary variables, but it allows delivery of RR down into the forbidden production region between zero and p_min. In addition, other types of spinning reserve capacity can still be allocated to the generator even if it delivers RR down all the way to a full stop. To remedy these issues, it is possible to turn on the use of additional binary variables to properly handle RR down stop allocation with the integer attribute [](global_settings:rr_down_stop_mip) on global_settings. Local flags that will override the global_settings attribute can be set on each generator object with the attribute [](generator:rr_down_stop_mip_flag). The additional binary variables could increase calculation time, but will ensure that RR down is either delivered spinning or down to a full stop, and that no other spinning reserve capacity can be allocated simultaneously with a RR down stop allocation. Note that RR up reserve capacity can still be allocated at the same time as an RR down stop allocation. Equivalent constraints to ensure proper RR up stop allocations for pumps have also been implemented. +++ ## Optimal reserve capacity distribution The reserve capacity functionality in SHOP was tailored to be used with the [reserve_group object](reserve_group) to optimally distribute a shared reserve capacity obligation among a defined group of units. The reserve_group is used to specify the different reserve obligations as TXY attributes called *\_\_obligation*, such as [fcr_n_up_obligation](reserve_group:fcr_n_up_obligation) and [rr_down_obligation](reserve_group:rr_down_obligation). The reserve obligation(s) in the reserve_group has to be covered by the connected generator and pump objects. Unlike the energy obligation in the spot market, reserving more capacity than specified in the reserve_group obligation is not inherently problematic. Any overfulfillment is recorded by the TXY attributes *\_\_slack* in the reserve_group, and is penalized by a low cost in the objective function, see the [reserve_group_slack_cost](global_settings:reserve_group_slack_cost) attribute. A much higher penalty is incurred if the amount of allocated reserve capacity is less than the obligation, recorded as *\_\_violation* on the reserve_group. Violations of the reserve obligation are penalized by either the general [reserve_group_penalty_cost](global_settings:reserve_group_penalty_cost) attribute or the reserve_group-specific *\_penalty_cost* attributes. +++ ## Fixed reserve capacity schedules It is possible to specify fixed reserve schedules for individual units by using the TXY attributes called *\_\_schedule*, such as [fcr_d_up_schedule](generator:fcr_d_up_schedule) on the generator object and [fcr_d_up_schedule](pump:fcr_d_up_schedule) on pump object. The reserve capacity schedule constraints will be built independent of the reserve_group constraints, but will also count towards a reserve_group obligation if the unit is connected to a reserve_group. Not following the reserve schedule is penalized by the general [reserve_schedule_penalty_cost](global_settings:reserve_schedule_penalty_cost) attribute, and the unit specific output TXY attributes *\_\_schedule_penalty* record the amount of scheduled reserve capacity that has not been fulfilled. +++ ## Reserve capacity markets A reserve capacity [](market) can be defined in SHOP by specifying the [market_type](market:market_type) attribute on the market object and connecting the market to a reserve_group object. The market_type signifies which reserve capacity that can be traded in the market. If there is a reserve obligation matching the market_type in the reserve_group connected to a reserve market, this is added as a load to the reserve market balance constraints. The penalties for violating the reserve market load is the same as described for the reserve_group obligation. The reserve market will otherwise function similarly to a normal energy market in SHOP, where the reserve capacity sold is remunerated with the sale price defined for the market object. The [reserve market example](reserve-market-example) shows how a simple reserve capacity market can be modelled in SHOP. +++ ## Minimum and maximum reserve capacity limits It is possible to specify minimum and maximum limits for the reserve capacity participation of individual units. The TXY attributes are called *\_\_max* and *\_\_min*, such as [rr_up_max](generator:rr_up_max) and [fcr_n_down_min](generator:fcr_n_down_min). These max and min limits bound the delivery of a single reserve type and should not be confused with the p_fcr_min, p_fcr_max, and p_rr_min attributes described earlier. For instance, the fcr_n_up_max TXY attribute applies a direct bound on the amount of FCR-N capacity the unit can deliver in the upward direction, while p_fcr_max extends the physical upper production limit of the unit for delivery of FCR-N and FCR-D. Applying these min and max constraints are treated similarly to the production bound constraints for generating units, as a new binary variable ($u$) is introduced to force the reserve capacity allocation ($r$) to be either zero or between the specified min and max bounds: $R^{min}\cdot u \leq r \leq R^{max}\cdot u$. Be aware that it is easy to create conflicting constraints when min and max reserve delivery constraints are used together with reserve schedules and reserve group obligations, which could lead to penalties and otherwise unexpected behaviour. +++ ## Plant reserve limits Some reserve capacity constraints can be specified for the generators located in the same plant. Minimum and maximum limits for the amount of FRR reserves delivered from each plant can be specified using the TXY attributes *frr_\_\* on the plant object. A TXY attribute for the minimum amount of allocated RR reserves in the upward direction, [rr_up_min](plant:rr_up_min), also exists on the plant level, but there are no plant level FCR constraints. The minimum and maximum constraints are implemented in a similar way to the unit-specific reserve constraints mentioned above. In addition, the [frr_symmetric_flag](plant:frr_symmetric_flag) TXY flag series attribute can be used to make the total FRR reserve capacity allocated on the plant symmetric in the time steps where the flag is non-zero. +++ ## Reserve ramping and clustering There is no explicit cost difference between delivering reserve capacity on two different units in SHOP. If there is available capacity on both units, meaning that the optimal production set point does not have to be changed to create the available capacity, the optimization solver used in SHOP will arbitrarily choose how to distribute the capacity between the two units. This can lead to a reserve capacity allocation that switches often between the units, which is not ideal for real world applications. Using a small cost for changing the reserve capacity allocation between time steps will encourage a more stable allocation. Reserve ramping costs can be defined by attributes on the global_settings object, [gen_reserve_ramping_cost](global_settings:gen_reserve_ramping_cost) and [pump_reserve_ramping_cost](global_settings:pump_reserve_ramping_cost), or by using the unit specific and directional TXY attributes [reserve_ramping_cost_up](generator:reserve_ramping_cost_up) and [reserve_ramping_cost_down](generator:reserve_ramping_cost_down) on the generator and pump objects. Note that the reserve ramping functionality requires the **SHOP_RESERVE_CLUSTERING** license. The license also enables users to set a [reserve_contribution_cost](global_settings:reserve_contribution_cost) double attribute on the global_settings object to add a cost to the objective function for each unit that has any reserve capacity allocated in each time step. Adding a reserve contribution cost can help aggregate the reserve capacity allocation so that fewer units are used to reserve capacity.