7.6 Example Extensions

Matpower includes three OPF extensions implementing via callbacks, respectively, the co-optimization of energy and reserves, interface flow limits and dispatchable DC transmission lines.

7.6.1 Fixed Zonal Reserves

This extension is a more complete version of the example of fixed zonal reserve requirements used for illustration above in Sections 7.3 and 7.4. The details of the extensions to the standard OPF problem are given in equations (7.2)–(7.5) and a description of the relevant input and output data structures is summarized in Tables 7-5 and 7-6, respectively.

Table 7-5:Input Data Structures for Fixed Zonal Reserves
name

description

mpc

Matpower case struct

  reserves

additional field in mpc containing input parameters for zonal reserves in the following sub-fields:

    cost

(ng  or ngr   ) ×1  vector of reserve costs in $/MW, c  from (7.3)

    qty

(ng  or ngr   ) × 1  vector of reserve quantity upper bounds in MW, ith  element is rimax

    zones

nrz × ng  matrix of reserve zone definitions

zones(k,j) = {
 1if gen j belongs to reserve zone k (j ∈ Zk)
 0otherwise (j∈∕Zk)

    req

nrz × 1  vector of zonal reserve requirements in MW,  th
k  element is Rk  from (7.5)

Here ngr  is the number of generators belonging to at least one reserve zone.

Table 7-6:Output Data Structures for Fixed Zonal Reserves
name

description

results

OPF results struct, superset of mpc with additional fields for output data

  reserves

zonal reserve data, with results in the following sub-fields:

    R

reserve allocation ri  , in MW

    Rmin

lower bound of ri  in MW from (7.2), i.e. all zeros

    Rmax

upper bound of ri  in MW from (7.2), i.e.      max
min(ri  ,Δi)

    mu

shadow prices on constraints in $/MW

      l

shadow price on lower bound of ri  in (7.2)

      u

shadow price on upper bound of ri  in (7.2)

      Pmax

shadow price on capacity constraint (7.4)

    prc

reserve price in $/MW, computed for unit i  as the sum of the shadow prices of constraints k  in (7.5) in which unit i  participates (k | i ∈ Zk  )

All zonal reserve result sub-fields are ng× 1  vectors, where the values are set to zero for units not participating in the provision of reserves.

The code for implementing the callbacks can be found in toggle_reserves. A wrapper around runopf that turns on this extension before running the OPF is provided in runopf_w_res, allowing you to run a case with an appropriate reserves field, such as t_case30_userfcns, as follows.

results = runopf_w_res('t_case30_userfcns');

See help runopf_w_res and help toggle_reserves for more information. Examples of using this extension and a case file defining the necessary input data can be found in t_opf_userfcns and t_case30_userfcns, respectively. Additional tests for runopf_w_res are included in t_runopf_w_res.

7.6.2 Interface Flow Limits

This extension adds interface flow limits based on flows computed from a DC network model. It is implemented in toggle_iflims. A flow interface k  is defined as a set ℬk  of branch indices i  and a direction for each branch. If pi  represents the real power flow (“from” bus → “to” bus) in branch i  and di  is equal to 1 or −  1  to indicate the direction,53 then the interface flow f
 k  for interface k  is defined as

        ∑
fk(Θ) =     dipi(Θ),
        i∈ℬk
(7.6)

where each branch flow pi  is an approximation calculated as a linear function of the bus voltage angles based on the DC power flow model from equation (3.29).

This extension adds to the OPF problem a set of nif   doubly-bounded constraints on these flows.

F mkin ≤ fk(Θ ) ≤ Fmkax   ∀k ∈ ℐf
(7.7)

where Fmin
 k  and F max
 k  are the specified lower and upper bounds on the interface flow, and ℐf  is a the set indices of interfaces whose flow limits are to be enforced.

The data for the problem is specified in an additional if field in the Matpower case struct mpc. This field is itself a struct with two sub-fields, map and lims, used for input data, and two others, P and mu, used for output data. The format of this data is described in detail in Tables 7-7 and 7-8.

Table 7-7:Input Data Structures for Interface Flow Limits
name

description

mpc

Matpower case struct

  if

additional field in mpc containing input parameters for interface flow limits in the following sub-fields:

    map

∑
( k nk)× 2  matrix defining the interfaces, where nk  is the number branches that belong to interface k  . The nk  branches of interface k  are defined by nk  rows in the matrix, where the first column in each is equal to k  and the second is equal to the corresponding branch index i  multiplied by di  to indicate the direction.

    lims

nif × 3  matrix of interface limits, where nif  is the number of interface limits to be enforced. The first column is the index k  of the interface, and the second and third columns are  min
Fk  and  max
Fk  , the lower and upper limits respectively, on the DC model flow limits (in MW) for the interface.

Table 7-8:Output Data Structures for Interface Flow Limits
name

description

results

OPF results struct, superset of mpc with additional fields for output data

  if

additional field in results containing output parameters for interface flow limits in the following sub-fields:

    P

nif × 1  vector of actual flow in MW across the corresponding interface (as measured at the “from” end of associated branches)

    mu.l

nif × 1  vector of shadow prices on lower flow limits (u  /MW)

    mu.u

nif × 1  vector of shadow prices on upper flow limits (u  /MW)

Here we assume the objective function has units u  .

See help toggle_iflims for more information. Examples of using this extension and a case file defining the necessary input data for it can be found in t_opf_userfcns and t_case30_userfcns, respectively. Note that, while this extension can be used for AC OPF problems, the actual AC interface flows will not necessarily be limited to the specified values, since it is a DC flow approximation that is used for the constraint.

Running a case that includes the interface flow limits is as simple as loading the case, turning on the extension and running it. Unlike with the reserves extension, Matpower does not currently have a wrapper function to automate this.

mpc = loadcase('t_case30_userfcns');
mpc = toggle_iflims(mpc, 'on');
results = runopf(mpc);
7.6.3 DC Transmission Lines

Beginning with version 4.1, Matpower also includes a simple model for dispatchable DC transmission lines. While the implementation is based on the extensible OPF architecture described above, it can be used for simple power flow problems as well, in which the case the (OPF only) formulation callback is skipped.

A DC line in Matpower is modeled as two linked “dummy” generators, as shown in Figures 7-2 and 7-3, one with negative capacity extracting real power from the network at the “from” end of the line and another with positive capacity injecting power into the network at the “to” end. These dummy generators are added by the ext2int callback and removed by the int2ext callback. The real power flow pf  on the DC line at the “from” end is defined to be equal to the negative of the injection of corresponding dummy generator. The flow at the “to” end pt  is defined to be equal to the injection of the corresponding generator.

Figure 7-2:DC Line Model

Figure 7-3:Equivalent “Dummy” Generators

Matpower links the values of pf  and pt  using the following relationship, which includes a linear approximation of the real power loss in the line.

pict

Here the linear coefficient l1   is assumed to be a small (≪  1  ) positive number. Obviously, this is not applicable for bi-directional lines, where the flow could go either direction, resulting in decreasing losses for increasing flow in the “to” →  “from” direction. There are currently two options for handling bi-directional lines. The first is to use a constant loss model by setting l =  0
 1  . The second option is to create two separate but identical lines oriented in opposite directions. In this case, it is important that the lower limit on the flow and the constant term of the loss model l0   be set to zero to ensure that only one of the two lines has non-zero flow at a time.54

Upper and lower bounds on the value of the flow can be specified for each DC line, along with an optional operating cost. It is also assumed that the terminals of the line have a range of reactive power capability that can be used to maintain a voltage setpoint. Just as with a normal generator, the voltage setpoint is only used for simple power flow; the OPF dispatches the voltage anywhere between the lower and upper bounds specified for the bus. Similarly, in a simple power flow the input value for p
 f  and the corresponding value for pt  , computed from (7.8), are used to specify the flow in the line.

Most of the data for DC lines is stored in a dcline field in the Matpower case struct mpc. This field is a matrix similar to the branch matrix, where each row corresponds to a particular DC line. The columns of the matrix are defined in Table B-5 and include connection bus indices, line status, flows, terminal reactive injections, voltage setpoints, limits on power flow and VAr injections, and loss parameters. Also, similar to the branch or gen matrices, some of the columns are used for input values, some for results, and some, such as PF can be either input or output, depending on whether the problem is a simple power flow or an optimal power flow. The idx_dcline function defines a set of constants for use as named column indices for the dcline matrix.

An optional dclinecost matrix, in the same form as gencost, can be used to specify a cost to be applied to pf  in the OPF. If the dclinecost field is not present, the cost is assumed to be zero.

Matpower’s DC line handling is implemented in toggle_dcline and examples of using it can be found in t_dcline. The case file t_case9_dcline includes some example DC line data. See help toggle_dcline for more information.

Running a case that includes DC lines is as simple as loading the case, turning on the extension and running it. Unlike with the reserves extension, Matpower does not currently have a wrapper function to automate this.

mpc = loadcase('t_case9_dcline');
mpc = toggle_dcline(mpc, 'on');
results = runopf(mpc);
7.6.4 OPF Soft Limits

Matpower includes an extension that replaces limits (such as branch flow limits, voltage magnitude bounds, generator limits, etc.) in an optimal power flow with soft limits, that is, limits that can be violated with some linear penalty cost. This can be useful in identifying the cause of infeasibility in some optimal power flow problems. The extension is implemented in toggle_softlims. A limited version for branch flow constraints in a DC model only, was introduced in Matpower 5.0, with a generalization to all of the standard OPF limits added in Matpower 7.0. The soft AC branch flow limit implemention provides an example of user-defined nonlinear constraints.

In general, replacing a hard constraint of the form

hi(x) ≤ 0
(7.9)

with a soft limit involves introducing a new non-negative variable si  to represent the violation of the original constraint. The original hard constraint (7.9) is replaced by one in which this violation variable is used to “relax” the constraint by adding it to the right-hand.

pict

Finally, a penalty cost on violations is implemented via a linear cost coefficient, civ   , applied to each violation variable si  , so that the additional user defined cost term from (6.47) for the set of soft limits looks like

fu(ˆx ) = cvTs.
(7.12)

Take, as an example, branch flow limits. The flow constraints in (6.9) and (6.10) are rewritten by replacing the right hand side with a flow violation variable sirate a

pict

In the case of AC flow constraints, the flow functions fif  and fit  are nonlinear and can be either apparent power, active power, or current as shown in (6.11). In the case of DC flow constraints, where there are no losses, these flows can be implemented in terms of the flow at the from end of the line and its negative, both linear functions of the bus voltage angles, based on (6.30) and (6.31).

pict

The feasible area for the DC case is illustrated in Figure 7-4.

Figure 7-4:Feasible Region for Branch Flow Violation Constraints

Matpower implements soft limits for each of the types of constraints listed in Table 7-9, where the formulation for each constraint type is shown.

Table 7-9:Soft Limit Formulation
name hard-limit formulation soft-limit formulation
VMIN, VMAX vim ≥ vi,mmin  , vim ≤ vi,mmax  vim + sivmin ≥ vim,min  , vim − sivmax ≤ vi,mmax
RATE_A |        |
||fi(Θ, V )|| ≤ fi
  f    m     max  |        |
||f i(Θ,V  )||− s  - ≤ f i
 f    m      ratea   max
|| i      ||   i
 ft(Θ, Vm) ≤ fmax  || i      ||          i
ft(Θ,Vm ) − srate-a ≤ fmax
PMIN, PMAX  i   i,min
pg ≥ pg  ,  i    i,max
pg ≤ pg   i          i,min
pg + spmin ≥ pg  ,  i          i,max
pg − spmax ≤ pg
QMIN, QMAX  i   i,min
qg ≥ qg  ,  i   i,max
qg ≤ qg   i          i,min
qg +sqmin ≥ qg  ,  i         i,max
qg − sqmax ≤ qg
ANGMIN  i   i     i,min
𝜃f − 𝜃t ≥ Δ 𝜃   i    i            i,min
𝜃f − 𝜃t + sangmin ≥ Δ 𝜃
ANGMAX  i   i     i,max
𝜃f − 𝜃t ≤ Δ 𝜃   i    i            i,max
𝜃f − 𝜃t − sangmax ≤ Δ 𝜃

Only applicable for the AC OPF. Example of a user-defined nonlinear constraint in the AC version.

The parameters for the problem are specified in an additional softlims field in the Matpower case struct mpc. This field is itself a struct where each sub-field corresponds to the name of one of the limits listed in Table 7-9. For each of the limits, the input parameters are specified in the fields detailed in Table 7-10, with defaults summarized in Table 7-11.

Table 7-10:Input Data Structures for OPF Soft Limits
name

description

mpc

Matpower case struct

  softlims

additional field in mpc containing OPF soft limit input parameters for the possible limits, each of which is optional.*

    <LIM>

<LIM> refers to the name of the limit, i.e. one of the following: ANGMIN, ANGMAX, RATE_A, PMIN, PMAX, QMIN, QMAX, VMIN, VMAX. Each of these is a struct with input parameters defining the soft limits for this type of constraint in the following optional fields (see Table 7-11 for defaults):

      idx

nsl × 1  vector of row indices for bus, branch or gen matrix, depending on <LIM>, specifying the elements for which corresponding soft limits are to be applied

      busnum

nsl × 1  vector of external bus numbers specifying the buses to which soft limits are to be applied

      cost

scalar or nsl × 1  vector cv  of linear cost coefficients for limit violation costs

      hl_mod§

string indicating type of modification to original hard limit:

  

'none'

do not add soft limit, no change to original hard limit

'remove'

add soft limit, relax hard limit by removing it completely

'replace'

add soft limit, relax hard limit by replacing original with value specified in hl_val

'scale'

add soft limit, relax hard limit by scaling original by value specified in hl_val

'shift'

add soft limit, relax hard limit by shifting original by value specified in hl_val

      hl_val§

scalar or nsl × 1  vector value used to modify hard limit according to hl_mod. Ignored for 'none' and 'remove', required for 'replace', and optional, with the following defaults, for 'scale' and 'shift':

  

'scale'

2 for positive upper limits or negative lower limits, 0.5 otherwise

'shift'

0.25 for VMAX and VMIN, 10 otherwise

* For fields not present, the value of the 'opf.softlims.defaults' option determines whether the corresponding limit is unchanged (= 0) or converted (= 1, default) to a soft limit using default values from Table 7-11. For bus constraints, idx overrides busnum if both are provided. Only applicable for bus constraints, i.e. <LIM> is VMIN or VMAX. § Any new, relaxed hard limits are implemented via bounds on the violation variables. See Table 7-12 for details.

Table 7-11:Default Soft Limit Values
name

description

VMIN

voltage magnitude lower bound

    idx

all buses

    cost

$100,000/p.u.

    hl_mod

'replace'

    hl_val

0

VMAX

voltage magnitude upper bound

    idx

all buses

    cost

$100,000/p.u.

    hl_mod

'remove'

RATE_A

branch flow limit

    idx

all on-line branches with bounded flow limits

    cost

$1000/MVA, $1000/MW, or $1000/(kA⋅VbasekV )   where the units depend on 'opf.flow_lim'

    hl_mod

'remove'

PMIN

generator active power lower bound

    idx

all on-line generators, excluding dispatchable loads

    cost

$1000/MW

    hl_mod

'replace'

    hl_val

0 if P i,gmin≥ 0  , − ∞ otherwise

PMAX, QMIN, QMAX

generator active power upper bound, reactive power lower/upper bounds

    idx

all on-line generators, excluding dispatchable loads

    cost

$1000/MW or $1000/MVAr

    hl_mod

'remove'

ANGMIN, ANGMAX

branch angle difference lower/upper bounds

    idx

all on-line branches with angle difference limits, Δ 𝜃  , where          ∘
|Δ𝜃| < 360

    cost

$1000/deg

    hl_mod

'remove'

Unless the maximum marginal cost at Pmax  across all online generators, which we call cmax
 g  , exceeds $1000/MWh, in which case the numerical value of the default cost is cmgax  instead of 1000 (or 100⋅cmgax  instead of 100,000, for VMIN or VMAX).

Depending on whether the original constraint in (7.10) is an upper bound or a lower bound, it can be written as one of the following

        {
  i       ¯hi(x) − hi,lim     (upper bound )
h (x) =    i,lim   ¯ i
          h    − h (x )    (lower  bound )
(7.19)

where hi,lim   is the actual value of the hard limit. When introducing a soft limit, this original hard limit can be removed completely or modified to have a new value. Matpower provides a several ways of modifying the original hard limit based on fields hl_mod (“hard limit modification”) and hl_val (“hard limit value”) in the respective limit structures. This new hard limit is implemented via an upper bound on the corresponding violation variable si  . Table 7-12 summarizes the new hard limits and the corresponding bounds on the violation variable as functions of the values of hl_mod and hl_val.

Table 7-12:Possible Hard-Limit Modifications
h_mod new hard limit hi,nliewm  upper bound on violation variable si
'remove' ±∞ ∞
'replace' hl val ||         i,lim||
|hl val − horig |
'scale' hl val ⋅hi,orliigm  |                |
||(hl val − 1)⋅hi,orliigm||
'shift' hi,lim ± hl val
 orig hl-val

Plus sign for upper bounds and minus sign for lower bounds.

Unspecified limits in the mpc.softlims input parameters are handled differently, depending on the value of the Matpower option 'opf.softlims.default' (see Table C-5).

Soft limit outputs, summarized in Table 7-13, include the amount and cost of any overloads, that is, violations of the original hard limits. These can be found as additional fields, overload and ov_cost, under each limit in results.softlims. The Kuhn-Tucker multipliers on the soft limit constraints are also included in the usual columns of the corresponding matrix in the results, e.g. bus(:, MU_VMAX), branch(:, MU_SF), etc. When there are no violations, these shadow prices are the same as if hard limits were imposed. When there is a violation, they are equal to the cost cv   associated with the violation variable, except in the case where a modified hard limit is also binding, in which case it also reflects the shadow price on this modified hard constraint.

Table 7-13:Output Data Structures for OPF Soft Limits
name

description

results

Matpower case struct

  softlims

additional field in results containing OPF soft limit outputs for each limit type

    <LIM>

<LIM> refers to the name of the limit, i.e. one of the following: ANGMIN, ANGMAX, RATE_A, PMIN, PMAX, QMIN, QMAX, VMIN, VMAX. Each of these is a struct with the following output fields:

      overload

nb∕l∕g × 1  vector of overload quantities for this limit (amount of original hard limit violation)

      ov_cost

n    × 1
 b∕l∕g  vector of overload penalty costs for this limit

  branch(:, MU_ANGMIN)

Kuhn-Tucker multipliers on angle difference lower bounds

  branch(:, MU_ANGMAX)

Kuhn-Tucker multipliers on angle difference upper bounds

  branch(:, MU_SF)

Kuhn-Tucker multipliers on branch flow limits (from end)

  branch(:, MU_ST)

Kuhn-Tucker multipliers on branch flow limits (to end)

  gen(:, MU_PMIN)

Kuhn-Tucker multipliers on active gen lower bounds

  gen(:, MU_PMAX)

Kuhn-Tucker multipliers on active gen upper bounds

  gen(:, MU_QMIN)

Kuhn-Tucker multipliers on reactive gen lower bounds

  gen(:, MU_QMAX)

Kuhn-Tucker multipliers on reactive gen upper bounds

  bus(:, MU_VMIN)

Kuhn-Tucker multipliers on voltage magnitude lower bounds

  bus(:, MU_VMAX)

Kuhn-Tucker multipliers on voltage magnitude upper bounds

The dimensions of overload and ov_cost correspond to all buses, branches or generators (depending on <LIM>), not just those whose limits were converted to soft limits. Entries corresponding to those not included (implicitly or explicitly) in idx are set to zero. For limits that have been converted to soft limits, these are the shadow prices on the soft limit constraints. When there is no violation of the soft limit, this shadow price is the same as it would be for the original hard limit. When there is a violation, it is equal to the corresponding user-supplied violation cost civ  , unless an updated hard constraint is also binding.

See help toggle_softlims for more information on this extension. Examples of using this extension can be found in t_opf_softlims. Running a case that includes the default soft limits is as simple as loading the case, turning on the extension and running it. Unlike with the reserves extension, Matpower does not currently have a wrapper function to automate this.

mpc = loadcase('case2383wp');
mpc = toggle_softlims(mpc, 'on');
results = runopf(mpc, mpopt);