NLP blocks and backends

NLP Blocks

The Formulation is decomposed into smaller nonlinear programming (NLP) blocks. Blocks are coupled together using a OPFBlocks structure.

ProxAL.OPFBlocksType
OPFBlocks(
    opfdata::OPFData,
    rawdata::RawData;
    modelinfo::ModelInfo = ModelInfo(),
    backend=JuMPBlockBackend,
    algparams::AlgParams = AlgParams()
)

Create a structure OPFBlocks to decompose the original OPF problem specified in opfdata timestep by timestep, by dualizing the ramping constraint. One block corresponds to one optimization subproblem (and hence, to a particular timestep), and the attribute blkCount enumerates the total number of subproblems. The subproblems are specified using AbstractBlockModel objects, allowing to define them either with JuMP (if backend=JuMPBlockBackend is chosen) or with ExaPF (backend=ExaBlockBackend).

Decomposition by contingencies

By default, OPFBlocks decomposes the problem only timestep by timestep (single-period multiple-contingency scheme), leading to a total of T subproblems. However, if the option algparams.decompCtgs is set to true, the original problem is also decomposed contingency by contingency (single-period single-contingency scheme). In this case the total number of subproblems is T * K (with K the total number of contingencies).

Deporting the resolution on the GPU

When the backend is set to ExaAdmmBackend (and a CUDA GPU is available), the user could chose to deport the resolution of each subproblem directly on the GPU simply by setting algparams.device=GPU. However, note that we could not instantiate more subproblems on the GPU than the number of GPU available.

source

Internally, each block is represented as follows.

ProxAL.init!Function
init!(block::AbstractBlockModel, algparams::AlgParams)

Initialize the optimization model by populating the model with variables and constraints.

source
ProxAL.add_variables!Function
add_variables!(block::AbstractBlockModel, algparams::AlgParams)

Add all optimization variables into the decomposed optimization model block.

source
ProxAL.set_objective!Function
set_objective!(
    block::AbstractBlockModel,
    algparams::AlgParams,
    primal::AbstractPrimalSolution,
    dual::AbstractDualSolution
)

Update the objective inside block's optimization subproblem. The new objective updates the coefficients of the penalty terms with respect to the reference primal and dual solutions passed in the arguments.

source
ProxAL.optimize!Function
optimize!(block::AbstractBlockModel, x0::AbstractArray, algparams::AlgParams)

Solve the optimization problem, starting from an initial point x0. The optimization solver is specified in field algparams.optimizer.

source
ProxAL.set_start_values!Function
set_start_values!(block::AbstractBlockModel, x0::AbstractArray)

Set x0 as the initial point for the optimization of model block.

source
ProxAL.get_solutionFunction
get_solution(block::AbstractBlockModel, output)

Return the solution of the optimization as a named tuple solution, with fields

  • status::MOI.TerminationStatus: final status returned by the solver
  • minimum::Float64: optimal objective found
  • vm::AbstractArray: optimal values of voltage magnitudes
  • va::AbstractArray: optimal values of voltage angles
  • pg::AbstractArray: optimal values of active power generations
  • qg::AbstractArray: optimal values of reactive power generations
  • ωt::AbstractArray: optimal values of frequency variable
  • st::AbstractArray: optimal values of slack variables for ramping
  • sk::AbstractArray: optimal values of slack variables for contingencies (OPTIONAL)
  • zk::AbstractArray: optimal values of penalty variables for contingencies (OPTIONAL)
source

Backends

ProxAL.JuMPBlockBackendType
JuMPBlockBackend(
    blk::Int,
    opfdata::OPFData,
    raw_data::RawData,
    algparams::AlgParams,
    modelinfo::ModelInfo,
    t::Int, k::Int, T::Int,
)

Use the JuMP backend to define the optimal power flow inside the block model. This function is called inside the constructor of the structure OPFBlocks.

Arguments

  • blk::Int: ID of the block represented by this model
  • opfdata::OPFData: data used to build the optimal power flow problem.
  • raw_data::RawData: same data, in raw format
  • algparams::AlgParams: algorithm parameters
  • modelinfo::ModelInfo: model parameters
  • t::Int: current time period index. Value should be between 1 and T.
  • k::Int: current contingency index
  • T::Int: final time period index
source
ProxAL.AdmmBlockBackendType
AdmmBlockBackend(
    blk::Int,
    opfdata::OPFData,
    raw_data::RawData,
    algparams::AlgParams,
    modelinfo::ModelInfo,
    t::Int, k::Int, T::Int;
)

Arguments

  • blk::Int: ID of the block represented by this model
  • opfdata::OPFData: data used to build the optimal power flow problem.
  • raw_data::RawData: same data, in raw format
  • algparams::AlgParams: algorithm parameters
  • modelinfo::ModelInfo: model parameters
  • t::Int: current time period index. Value should be between 1 and T.
  • k::Int: current contingency index
  • T::Int: final time period index
source

OPF

ProxAL.opf_block_get_auglag_penalty_exprFunction
opf_block_get_auglag_penalty_expr(
    opfmodel::JuMP.Model,
    modelinfo::ModelInfo,
    opfdata::OPFData,
    k::Int, t::Int,
    algparams::AlgParams,
    primal::OPFPrimalSolution,
    dual::OPFDualSolution
)

Let k and t denote the contingency number and time period of the NLP block. Then, depending on algparams.decompCtgs, this function must return an appropriate expression.

We use $\mathbb{I}[...]$ to denote the indicator function. Also, unless otherwise indicated,

  • $z_g$ are parameters and must be taken from primal.Zt

  • $p_g$ and $s_g$ variables that are not indexed with t are parameters and must be taken from primal.Pg and primal.St

  • $\lambda$ (without k subscript) must be taken from dual.ramping

  • $\rho_t$ must be taken from algparams.ρ_t

  • $\tau$ must be taken from algparams.τ

  • If algparams.decompCtgs == false, then this function must return:

\[\begin{aligned} \sum_{g \in G} \Bigg\{ & 0.5\tau [p^0_{g,t} - \mathrm{primal}.p^0_{g,t}]^2 \\ &+\mathbb{I}[t > 1]\Big( \lambda_{gt}[p^0_{g,t-1} - p^0_{g,t} + s_{g,t} + z_{g,t} - r_g] + 0.5\rho_{t}[p^0_{g,t-1} - p^0_{g,t} + s_{g,t} + z_{g,t} - r_g]^2 \Big) \\ &+\mathbb{I}[t < T]\Big( \lambda_{g,t+1}[p^0_{g,t} - p^0_{g,t+1} + s_{g,t+1} + z_{g,t+1} - r_g] + 0.5\rho_{t}[p^0_{g,t} - p^0_{g,t+1} + s_{g,t+1} + z_{g,t+1} - r_g]^2 \Big) \Bigg\} \end{aligned}\]

  • If algparams.decompCtgs == true, then this function must return:

(to do)

source