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.OPFBlocks
— TypeOPFBlocks(
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.
Internally, each block is represented as follows.
ProxAL.AbstractBlockModel
— TypeAbstractBlockModel
Abstract supertype for the definition of block subproblems.
ProxAL.init!
— Functioninit!(block::AbstractBlockModel, algparams::AlgParams)
Initialize the optimization model by populating the model with variables and constraints.
ProxAL.add_variables!
— Functionadd_variables!(block::AbstractBlockModel, algparams::AlgParams)
Add all optimization variables into the decomposed optimization model block
.
ProxAL.set_objective!
— Functionset_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.
ProxAL.optimize!
— Functionoptimize!(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
.
ProxAL.set_start_values!
— Functionset_start_values!(block::AbstractBlockModel, x0::AbstractArray)
Set x0
as the initial point for the optimization of model block
.
ProxAL.get_solution
— Functionget_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 solverminimum::Float64
: optimal objective foundvm::AbstractArray
: optimal values of voltage magnitudesva::AbstractArray
: optimal values of voltage anglespg::AbstractArray
: optimal values of active power generationsqg::AbstractArray
: optimal values of reactive power generationsωt::AbstractArray
: optimal values of frequency variablest::AbstractArray
: optimal values of slack variables for rampingsk::AbstractArray
: optimal values of slack variables for contingencies (OPTIONAL)zk::AbstractArray
: optimal values of penalty variables for contingencies (OPTIONAL)
Backends
ProxAL.JuMPBackend
— TypeJuMPBackend <: AbstractBackend
Solve OPF in full-space with JuMP/MOI.
ProxAL.JuMPBlockBackend
— TypeJuMPBlockBackend(
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 modelopfdata::OPFData
: data used to build the optimal power flow problem.raw_data::RawData
: same data, in raw formatalgparams::AlgParams
: algorithm parametersmodelinfo::ModelInfo
: model parameterst::Int
: current time period index. Value should be between1
andT
.k::Int
: current contingency indexT::Int
: final time period index
ProxAL.AdmmBackend
— TypeExaAdmmBackend <: AbstractBackend
Solve OPF by decomposition using ExaAdmm.
ProxAL.AdmmBlockBackend
— TypeAdmmBlockBackend(
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 modelopfdata::OPFData
: data used to build the optimal power flow problem.raw_data::RawData
: same data, in raw formatalgparams::AlgParams
: algorithm parametersmodelinfo::ModelInfo
: model parameterst::Int
: current time period index. Value should be between1
andT
.k::Int
: current contingency indexT::Int
: final time period index
ProxAL.ExaPFBackend
— TypeExaPFBackend <: AbstractBackend
Solve OPF in reduced-space with ExaPF.
OPF
ProxAL.opf_block_get_auglag_penalty_expr
— Functionopf_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 fromprimal.Pg
andprimal.St
$\lambda$ (without
k
subscript) must be taken fromdual.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)