Julia OPF API (eDisGo_OPF)

Note

This page is generated automatically from the docstrings in the eDisGo_OPF Julia source (edisgo/opf/eDisGo_OPF.jl/src/). Only documented symbols are listed, so the reference fills in on its own as docstrings are added at the source.

The optimal power flow (OPF) is implemented in Julia, in the eDisGo_OPF package, which extends PowerModels.jl with a branch-flow formulation for distribution grids and eDisGo’s flexibilities (storage, electromobility, heat pumps, demand-side management, curtailment).

From Python the OPF is run via pm_optimize(), which serialises the grid and flexibility data to JSON, hands it to eDisGo_OPF and reads the results back. For the modelling background — branch-flow physics, the SOC vs. non-convex relaxations and the opf_version variants — see Multi-period optimal power flow.

The three exported problem formulations are BFPowerModelEdisgo (base branch-flow), SOCBFPowerModelEdisgo (second-order-cone relaxation, convex) and NCBFPowerModelEdisgo (non-convex, exact).

Problem formulations

Source: edisgo/opf/eDisGo_OPF.jl/src/core/types.jl

AbstractBFModelEdisgo

abstract type AbstractBFModelEdisgo <: AbstractBFQPModel

Abstract supertype for all eDisGo branch-flow OPF models. Concrete subtypes (BFPowerModelEdisgo, SOCBFPowerModelEdisgo, NCBFPowerModelEdisgo) select how the branch-flow equations are treated (base, second-order-cone relaxation, or non-convex/exact).

BFPowerModelEdisgo

mutable struct BFPowerModelEdisgo <: AbstractBFModelEdisgo

Base radial branch-flow model for the eDisGo OPF — the eDisGo extension of PowerModels’ branch-flow (DistFlow) formulation. Applicable to problem formulations whose name ends in _bf (e.g. build_mn_opf_bf_flex).

The branch-flow model is the natural formulation for the tree-shaped (radial) distribution grids eDisGo works with. For every branch i j it couples the sending-end active and reactive power (P, Q), the squared branch current ccm (= ) and the squared bus voltages w (= ), together with a nodal power balance at each bus, thermal/current limits, voltage limits and the flexibility power/energy bands. The defining coupling between power, current and voltage is the quadratic relation + = V²·I², which is what makes an exact AC OPF non-convex.

This type carries the shared model structure; how that quadratic coupling is enforced is fixed by the concrete subtypes SOCBFPowerModelEdisgo (convex relaxation) and NCBFPowerModelEdisgo (exact, non-convex) — one of those is what you actually solve. All quantities are in per-unit on the common base power s_base.

SOCBFPowerModelEdisgo

mutable struct SOCBFPowerModelEdisgo <: AbstractSOCBFModelEdisgo

Second-order-cone (SOC) relaxation of the radial branch-flow model. Applicable to problem formulations whose name ends in _bf.

The non-convex coupling + = V²·I² is relaxed to the convex inequality + V²·I² — a second-order cone (see constraint_model_current for AbstractSOCBFModelEdisgo). This turns the OPF into a convex program, solved with Gurobi: fast, reliable and globally optimal. For radial grids the relaxation is usually exact — the inequality is tight at the optimum, so the solution is also feasible for the original AC problem. check_SOC_equality flags any branches and time steps where it is not tight; there, running with warm_start=true recovers a feasible AC solution by polishing with the non-convex model (NCBFPowerModelEdisgo). This is the model behind the default method="soc".

NCBFPowerModelEdisgo

mutable struct NCBFPowerModelEdisgo <: AbstractNCBFModelEdisgo

Non-convex (NC), exact radial branch-flow model. Applicable to problem formulations whose name ends in _bf.

Keeps the exact quadratic equality + = V²·I² (added as a nonlinear @NLconstraint; see constraint_model_current for AbstractNCBFModelEdisgo), so no relaxation is involved. The resulting non-convex program is solved with the Ipopt interior-point solver: more accurate in principle, but slower and only guaranteed to find a local optimum. Selected via method="nc" (cold start), or used automatically as the warm-started polishing step when method="soc" is run with warm_start=true, starting from the exact Gurobi SOC solution.

Problem definition & build

Source: edisgo/opf/eDisGo_OPF.jl/src/prob/opf_bf.jl

solve_mn_opf_bf_flex

function solve_mn_opf_bf_flex(file, model_type::Type{T}, optimizer; kwargs...) where T <: AbstractBFModel

Solve multinetwork branch flow OPF with multiple flexibilities

build_mn_opf_bf_flex

function build_mn_opf_bf_flex(pm::AbstractBFModelEdisgo)

Build multinetwork branch flow OPF with multiple flexibilities

Model setup

Source: edisgo/opf/eDisGo_OPF.jl/src/core/base.jl

solve_model

function solve_model(data::Dict{String,<:Any}, model_type::Type, optimizer, build_method;
        ref_extensions=[], solution_processors=[], relax_integrality=false,
        multinetwork=false, multiconductor=false, kwargs...)

Instantiate and solve an eDisGo OPF model.

Builds a model of type model_type from the network data using build_method (e.g. build_mn_opf_bf_flex), optimises it with the given JuMP optimizer (Gurobi or Ipopt), and returns the tuple (result, pm), where result is the PowerModels solution dict and pm is the constructed model object. The keyword arguments mirror PowerModels’ solve_model/instantiate_model (ref_extensions, solution_processors, relax_integrality, multinetwork, multiconductor).

instantiate_model

function instantiate_model(data::Dict{String,<:Any}, model_type::Type, build_method; kwargs...)

Instantiate an eDisGo OPF model without solving it — a thin wrapper around InfrastructureModels.instantiate_model with eDisGo’s ref_add_core! reference extension and the global keys. Used internally by solve_model.

ref_add_core!

function ref_add_core!(ref::Dict{Symbol,Any})

Returns a dict that stores commonly used pre-computed data from of the data dictionary, primarily for converting data-types, filtering out deactivated components, and storing system-wide values that need to be computed globally.

Some of the common keys include:

  • :off_angmin and :off_angmax (see calc_theta_delta_bounds(data)),

  • :bus – the set {(i, bus) in ref[:bus] : bus["bus_type"] != 4},

  • :gen – the set {(i, gen) in ref[:gen] : gen["gen_status"] == 1 && gen["gen_bus"] in keys(ref[:bus])},

  • :branch – the set of branches that are active in the network (based on the component status values),

  • :arcs_from – the set [(i,b["f_bus"],b["t_bus"]) for (i,b) in ref[:branch]],

  • :arcs_to – the set [(i,b["t_bus"],b["f_bus"]) for (i,b) in ref[:branch]],

  • :arcs – the set of arcs from both arcs_from and arcs_to,

  • :bus_arcs – the mapping Dict(i => [(l,i,j) for (l,i,j) in ref[:arcs]]),

  • :bus_arcs_to – the mapping Dict(j => [(l,i,j) for (l,i,j) in ref[:arcs_from]]),

  • :bus_arcs_from – the mapping Dict(i => [(l,i,j) for (l,i,j) in ref[:arcs_from]]),

  • :bus_lines_to – the mapping Dict(j => [l for (l,i,j) in ref[:arcs_from]]),

  • :buspairs – (see buspair_parameters(ref[:arcs_from], ref[:branch], ref[:bus])),

  • :bus_gens – the mapping Dict(i => [gen["gen_bus"] for (i,gen) in ref[:gen]]).

  • :bus_gens_nd – the mapping Dict(i => [gen_nd["gen_bus"] for (i,gen) in ref[:gen_nd]]).

  • :bus_gens_slack – the mapping Dict(i => [gen_slack["gen_bus"] for (i,gen) in ref[:gen_slack]]).

  • :bus_loads – the mapping Dict(i => [load["load_bus"] for (i,load) in ref[:load]]).

  • :bus_shunts – the mapping Dict(i => [shunt["shunt_bus"] for (i,shunt) in ref[:shunt]]).

  • :bus_dsm – the mapping Dict(i => [dsm["dsm_bus"] for (i,dsm) in ref[:dsm]]).

  • :bus_cps – the mapping Dict(i => [cp["cp_bus"] for (i,cp) in ref[:electromobility]]).

  • :bus_hps – the mapping Dict(i => [hp["hp_bus"] for (i,hp) in ref[:heatpumps]]).

  • :arcs_from_dc – the set [(i,b["f_bus"],b["t_bus"]) for (i,b) in ref[:dcline]],

  • :arcs_to_dc – the set [(i,b["t_bus"],b["f_bus"]) for (i,b) in ref[:dcline]],

  • :arcs_dc – the set of arcs from both arcs_from_dc and arcs_to_dc,

  • :bus_arcs_dc – the mapping Dict(i => [(l,i,j) for (l,i,j) in ref[:arcs_dc]]), and

  • :buspairs_dc – (see buspair_parameters(ref[:arcs_from_dc], ref[:dcline], ref[:bus])),

If :ne_branch exists, then the following keys are also available with similar semantics:

  • :ne_branch, :ne_arcs_from, :ne_arcs_to, :ne_arcs, :ne_bus_arcs, :ne_buspairs.

Added keys for eDisGo OPF include:

  • :bus_arcs_to – the mapping Dict(j => [(l,i,j) for (l,i,j) in ref[:arcs_from]]),

  • :bus_arcs_from – the mapping Dict(i => [(l,i,j) for (l,i,j) in ref[:arcs_from]]),

  • :bus_lines_to – the mapping Dict(j => [l for (l,i,j) in ref[:arcs_from]]),

  • :bus_gens_nd – the mapping Dict(i => [gen_nd["gen_bus"] for (i,gen) in ref[:gen_nd]]).

  • :bus_gens_slack – the mapping Dict(i => [gen_slack["gen_bus"] for (i,gen) in ref[:gen_slack]]).

  • :bus_dsm – the mapping Dict(i => [dsm["dsm_bus"] for (i,dsm) in ref[:dsm]]).

  • :bus_cps – the mapping Dict(i => [cp["cp_bus"] for (i,cp) in ref[:electromobility]]).

  • :bus_hps – the mapping Dict(i => [hp["hp_bus"] for (i,hp) in ref[:heatpumps]]).

Variables

Source: edisgo/opf/eDisGo_OPF.jl/src/core/variables.jl

variable_branch_power_radial

function variable_branch_power_radial(pm::AbstractPowerModel; kwargs...)

Create the branch power-flow variables for the radial branch-flow model: both the active (p) and reactive (q) flow on every branch. Wrapper around variable_branch_power_real_radial and variable_branch_power_imaginary_radial.

variable_branch_power_real_radial

function variable_branch_power_real_radial(pm::AbstractPowerModel; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

variable: p[l,i,j] for (l,i,j) in arcs_from

variable_branch_power_imaginary_radial

function variable_branch_power_imaginary_radial(pm::AbstractPowerModel; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

variable: q[l,i,j] for (l,i,j) in arcs

variable_bus_voltage_magnitude_sqr

function variable_bus_voltage_magnitude_sqr(pm::AbstractPowerModel; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

Variable w[i] for each non-storage bus i: the squared voltage magnitude (= ), bounded by vmin²/vmax².

variable_max_line_loading

function variable_max_line_loading(pm::AbstractPowerModel; kwargs...)

Create the maximum-line-loading variable ll (wrapper around variable_line_loading_max), used by the line-loading-minimising objectives (opf_version 1 and 3).

variable_line_loading_max

function variable_line_loading_max(pm::AbstractPowerModel; nw::Int=nw_id_default, report::Bool=true)

variable: ll[l,i,j] for (l,i,j) in arcs_from

variable_gen_power_curt

function variable_gen_power_curt(pm::AbstractPowerModel; kwargs...)

generates variables for both active and reactive non-dispatchable power generation curtailment

variable_gen_power_curt_real

function variable_gen_power_curt_real(pm::AbstractPowerModel; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

variable: pgc[j] for j in gen_nd

variable_gen_power_curt_imaginary

function variable_gen_power_curt_imaginary(pm::AbstractPowerModel; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

variable: qgc[j] for j in gen_nd

variable_battery_storage

function variable_battery_storage(pm::AbstractPowerModel; kwargs...)

variables for modeling storage units, includes grid injection and internal variables

variable_battery_storage_power_real

function variable_battery_storage_power_real(pm::AbstractPowerModel; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

Variable ps[i] for i in storage: the active power of each battery storage unit (charging/discharging), bounded by the unit’s pmin and pmax.

variable_battery_storage_power_imaginary

function variable_battery_storage_power_imaginary(pm::AbstractPowerModel; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

Variable qs[i] for i in storage: the reactive power of each battery storage unit, bounded by the unit’s qmin and qmax. (Optional; by default reactive storage power is derived from the power factor in the power-balance constraint.)

variable_dsm_storage_power

function variable_dsm_storage_power(pm::AbstractPowerModel; kwargs...)

variables for modeling dsm storage units, includes grid injection and internal variables

variable_dsm_storage_power_real

function variable_dsm_storage_power_real(pm::AbstractPowerModel; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

Variable pdsm[i] for i in dsm: the demand-side-management load-shift power of each DSM unit, bounded by p_min/p_max.

variable_dsm_storage_power_imaginary

function variable_dsm_storage_power_imaginary(pm::AbstractPowerModel; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

Variable qdsm[i] for i in dsm: the reactive power of each DSM unit, bounded by q_min/q_max. (Optional; by default derived from the power factor.)

variable_dsm_storage_energy

function variable_dsm_storage_energy(pm::AbstractPowerModel; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

Variable dsme[i] for i in dsm: the accumulated shifted energy of each DSM unit, bounded by e_min/e_max. Coupled to pdsm over time by the DSM storage constraints.

variable_heat_storage

function variable_heat_storage(pm::AbstractPowerModel; kwargs...)

variables for modeling heat storage units, includes grid injection and internal variables

variable_heat_storage_power

function variable_heat_storage_power(pm::AbstractPowerModel; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

Variable phs[i] for i in heat_storage: the (dis)charging thermal power of each heat storage unit, bounded by ±capacity.

variable_heat_storage_energy

function variable_heat_storage_energy(pm::AbstractPowerModel; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

Variable hse[i] for i in heat_storage: the stored thermal energy (state of charge) of each heat storage unit, between 0 and its capacity.

variable_heat_pump_power

function variable_heat_pump_power(pm::AbstractPowerModel; kwargs...)

variables for modeling heat pumps, includes grid injection and internal variables

variable_heat_pump_power_real

function variable_heat_pump_power_real(pm::AbstractPowerModel; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

Variable php[i] for i in heatpumps: the electrical power drawn by each heat pump, bounded by p_min/p_max.

variable_heat_pump_power_imaginary

function variable_heat_pump_power_imaginary(pm::AbstractPowerModel; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

Variable qhp[i] for i in heatpumps: the reactive power of each heat pump, bounded by q_min/q_max. (Optional; by default derived from the power factor.)

variable_cp_power

function variable_cp_power(pm::AbstractPowerModel; kwargs...)

variables for modeling charging points, includes grid injection and internal variables

variable_cp_power_real

function variable_cp_power_real(pm::AbstractPowerModel; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

Variable pcp[i] for i in electromobility: the charging power of each charging park, bounded by p_min/p_max.

variable_cp_power_imaginary

function variable_cp_power_imaginary(pm::AbstractPowerModel; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

Variable qcp[i] for i in electromobility: the reactive power of each charging park, bounded by q_min/q_max. (Optional; by default derived from the power factor.)

variable_cp_energy

function variable_cp_energy(pm::AbstractPowerModel; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

Variable cpe[i] for i in electromobility: the accumulated charged energy of each charging park, bounded by e_min/e_max (the flexibility band). Coupled to pcp over time by the charging-point constraints.

variable_slack_grid_restrictions

function variable_slack_grid_restrictions(pm::AbstractBFModelEdisgo; kwargs...)

slack variables for grid restrictions

variable_slack_heat_pump_storage

function variable_slack_heat_pump_storage(pm::AbstractBFModelEdisgo; kwargs...)

Create the heat-pump / heat-storage operation slack variables (wrapper around variable_hs_slack and variable_hp2_slack), which keep the heat-pump energy balance feasible at a penalty.

variable_hs_slack

function variable_hs_slack(pm::AbstractBFModelEdisgo; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

heat storage slack variable

variable_hp2_slack

function variable_hp2_slack(pm::AbstractBFModelEdisgo; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

heat pump operation slack variable

variable_hp_slack

function variable_hp_slack(pm::AbstractBFModelEdisgo; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

heat pump slack variable

variable_load_slack

function variable_load_slack(pm::AbstractBFModelEdisgo; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

load slack variable

variable_gen_slack

function variable_gen_slack(pm::AbstractBFModelEdisgo; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

gen slack variable

variable_ev_slack

function variable_ev_slack(pm::AbstractBFModelEdisgo; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

EV slack variable

variable_slack_gen

function variable_slack_gen(pm::AbstractBFModelEdisgo; kwargs...)

slack generator variables

variable_slack_gen_real

function variable_slack_gen_real(pm::AbstractBFModelEdisgo; nw::Int=nw_id_default, report::Bool=true)

Variable pgs[i] for i in gen_slack: the active power of each slack generator (the substation / feed-in node), left unbounded.

variable_slack_gen_imaginary

function variable_slack_gen_imaginary(pm::AbstractBFModelEdisgo; nw::Int=nw_id_default, report::Bool=true)

Variable qgs[i] for i in gen_slack: the reactive power of each slack generator (the substation / feed-in node), left unbounded.

variable_slack_HV_requirements

function variable_slack_HV_requirements(pm::AbstractPowerModel; kwargs...)

slack variables for HV requirement constraints

variable_slack_HV_requirements_real

function variable_slack_HV_requirements_real(pm::AbstractPowerModel; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

Variable phvs[i] for i in HV_requirements: the active-power slack on each overlying-grid (HV) flexibility requirement, allowing the dispatch requested by the higher voltage level to be missed at a penalty (opf_version 3 and 4).

variable_slack_HV_requirements_imaginary

function variable_slack_HV_requirements_imaginary(pm::AbstractPowerModel; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

Variable qhvs[i] for i in HV_requirements: the reactive-power counterpart of phvs. (Optional; not used by default.)

Constraints — flexibilities & HV requirements

Source: edisgo/opf/eDisGo_OPF.jl/src/core/constraint.jl

constraint_store_state_initial

function constraint_store_state_initial(pm::AbstractBFModelEdisgo, n::Int, i::Int, energy, charge_eff, discharge_eff, time_elapsed, kind, p_loss)

Initial-time-step state constraint for a storage kind ("storage" battery, "heat_storage", or "dsm").

Sets the stored energy after the first time step from the unit’s initial state of charge and its (dis)charging power, and pins the final state of charge to the required end value — Eq. (3.9)/(3.10) for batteries, (3.22)/(3.23) for heat storage and (3.32)/(3.33) for DSM in the eDisGo OPF formulation.

constraint_store_state

function constraint_store_state(pm::AbstractBFModelEdisgo, n_1::Int, n_2::Int, i::Int, charge_eff, discharge_eff, time_elapsed, kind, p_loss)

Inter-time-step state-of-charge coupling for a storage kind between networks n_1 and n_2: the stored energy in n_2 equals that in n_1 plus the energy (dis)charged over the elapsed time — Eq. (3.10), (3.23), (3.33) of the eDisGo OPF formulation. For heat storage the previous energy is reduced by the standing-loss factor.

constraint_cp_state_initial

function constraint_cp_state_initial(pm::AbstractBFModelEdisgo, n::Int, i::Int, eta)

Initial-time-step state constraint for charging park i: sets the charged energy after the first time step from the midpoint of the flexibility band (e_min+e_max)/2 and the charging power, scaled by the charging efficiency eta — Eq. (3.25) of the eDisGo OPF formulation.

constraint_cp_state

function constraint_cp_state(pm::AbstractBFModelEdisgo, n_1::Int, n_2::Int, i::Int, eta)

Inter-time-step energy coupling for charging park i between networks n_1 and n_2: the charged energy in n_2 equals that in n_1 plus the energy charged over the elapsed time (scaled by the efficiency eta) — Eq. (3.26). In the last time step the energy is pinned back to the midpoint of the flexibility band (Eq. (3.25)).

constraint_hp_operation

function constraint_hp_operation(pm::AbstractBFModelEdisgo, i::Int, nw::Int=nw_id_default)

Heat-pump energy balance for heat pump i in network nw: the electrical power drawn (php, plus the operation slack phps2) times the coefficient of performance cop must cover the heat demand pd plus the net heat-storage (dis)charge (phss - phs) — Eq. (3.19) of the eDisGo OPF formulation.

constraint_HV_requirements

function constraint_HV_requirements(pm::AbstractBFModelEdisgo, i::Int, nw::Int=nw_id_default)

Overlying-grid requirement constraint i in network nw (opf_version 3 and 4): forces the total dispatch of the addressed flexibility (DSM, curtailment, storage, heat pumps or charging points) to meet the active power P requested by the higher voltage level, up to the slack phvs.

Constraint templates

Source: edisgo/opf/eDisGo_OPF.jl/src/core/constraint_template.jl

constraint_power_balance_bf

function constraint_power_balance_bf(pm::AbstractBFModelEdisgo, i::Int; nw::Int=nw_id_default)

power balance for radial branch flow model

constraint_voltage_magnitude_difference_radial

function constraint_voltage_magnitude_difference_radial(pm::AbstractBFModelEdisgo, i::Int; nw::Int=nw_id_default)

Apply the branch-flow voltage-magnitude-difference equation for branch i in network nw.

Relates the squared voltage magnitudes at the two ends of the branch to the active/reactive power flows and the squared current magnitude (Eq. (3.5) of the eDisGo OPF formulation). Virtual storage branches are skipped, as they do not represent a physical line.

constraint_store_state

function constraint_store_state(pm::AbstractBFModelEdisgo, i::Int; nw::Int=nw_id_default, kind::String)

First-time-step storage state constraint for unit i of type kind ("storage", "heat_storage" or "dsm") in network nw. Looks up the unit’s parameters (initial energy, charge/discharge efficiency, standing loss, elapsed time) and forwards to constraint_store_state_initial — Eq. (3.9)/(3.22)/(3.32).

constraint_store_state

function constraint_store_state(pm::AbstractBFModelEdisgo, i::Int, nw_1::Int, nw_2::Int, kind::String)

Couple the state of charge of storage unit i of type kind between two consecutive time steps (networks nw_1 and nw_2).

kind is one of "storage" (battery), "heat_storage" or "dsm". Links the stored energy in nw_2 to that in nw_1 via the (dis)charging power and the elapsed time (Eq. (3.10), (3.23), (3.33) of the eDisGo OPF formulation; heat storage additionally accounts for standing losses). If the unit is inactive in nw_1, the initial-state constraint is applied from nw_2’s data instead.

constraint_model_current

function constraint_model_current(pm::AbstractPowerModel; nw::Int=nw_id_default)

Template for the current/power/voltage coupling constraint: forwards to the formulation-specific method for network nw — the convex second-order-cone inequality (AbstractSOCBFModelEdisgo) or the exact nonlinear equality (AbstractNCBFModelEdisgo).

Branch-flow formulation

Source: edisgo/opf/eDisGo_OPF.jl/src/form/bf.jl

variable_branch_current

function variable_branch_current(pm::AbstractBFModel; kwargs...)

Create the squared branch-current-magnitude variables for the branch-flow model (wrapper around variable_buspair_current_magnitude_sqr, which defines ccm[i]).

variable_bus_voltage

function variable_bus_voltage(pm::AbstractBFModel; kwargs...)

Create the bus-voltage variable for the branch-flow model (wrapper around variable_bus_voltage_magnitude_sqr, which defines w[i] = ).

variable_buspair_current_magnitude_sqr

function variable_buspair_current_magnitude_sqr(pm::AbstractBFModel; nw::Int=nw_id_default, bounded::Bool=true, report::Bool=true)

Variable ccm[i] for each branch i: the squared branch current magnitude (= ). Lower-bounded by 0 and upper-bounded from the branch rating and the sending-bus voltage ((rate_a·tap / vmin)²); in the unbounded model only storage (virtual) branches receive the upper bound.

constraint_voltage_magnitude_difference

function constraint_voltage_magnitude_difference(pm::AbstractBFModelEdisgo, n::Int, i, f_bus, t_bus, f_idx, t_idx, r, x, tm)

Low-level branch-flow voltage-drop equation for branch i (network n): relates the squared voltages at the two ends to the active/reactive flows, the squared current ccm and the branch impedance r, x (with tap tm) — Eq. (3.5) of the eDisGo OPF formulation. At the slack bus the squared voltage is fixed to 1 p.u. Called by constraint_voltage_magnitude_difference_radial.

constraint_model_current

function constraint_model_current(pm::AbstractSOCBFModelEdisgo, n::Int) # Eq. (3.9)

Current/power/voltage coupling for the SOC (convex) branch-flow model in network n: the second-order-cone inequality + (w/tm²)·ccm on every branch — the convex relaxation (Eq. (3.6i) of the eDisGo OPF formulation) of the exact equality.

constraint_model_current

function constraint_model_current(pm::AbstractNCBFModelEdisgo, n::Int) # Eq. (3.5)

Current/power/voltage coupling for the non-convex branch-flow model in network n: the exact nonlinear equality + = (w/tm²)·ccm (a JuMP @NLconstraint) on every non-storage branch — Eq. (3.6) of the eDisGo OPF formulation.

constraint_max_line_loading

function constraint_max_line_loading(pm::AbstractSOCBFModelEdisgo, n::Int)

Maximum-line-loading constraint for network n: bounds the squared apparent power on every non-storage branch by the loading variable ll, (p² + q²)/s_nom² ll — Eq. (3.40) of the eDisGo OPF formulation. Together with the line-loading objective this minimises the worst-case loading (opf_version 1 and 3).

constraint_max_line_loading

function constraint_max_line_loading(pm::AbstractNCBFModelEdisgo, n::Int)

Non-convex-model version of the maximum-line-loading constraint (p² + q²)/s_nom² ll (identical formulation to the SOC method) — Eq. (3.40).

constraint_power_balance

function constraint_power_balance(pm::AbstractBFModelEdisgo, n::Int, i, bus_gens, bus_gens_nd, bus_gens_slack, bus_loads, bus_arcs_to, bus_arcs_from, bus_lines_to, bus_storage, bus_pg, bus_qg, bus_pg_nd, bus_qg_nd, bus_pd, bus_qd, branch_r, branch_x, bus_dsm, bus_hps, bus_cps, bus_storage_pf, bus_dsm_pf, bus_hps_pf, bus_cps_pf, bus_gen_nd_pf, bus_gen_d_pf, bus_loads_pf, branch_strg_pf)

Nodal active- and reactive-power balance (Kirchhoff’s current law) at bus i in network n for the radial branch-flow model — Eq. (3.3)/(3.4) of the eDisGo OPF formulation.

Equates the power flowing into the bus on incoming branches to the power leaving on outgoing branches plus the net injection of every component connected to the bus: conventional and non-dispatchable generators, slack generator, loads, battery storage, DSM, heat pumps and charging points, plus the ohmic branch losses (ccm·r for active, ccm·x for reactive power). For opf_version 2 and 4 the balance additionally includes the load-shedding / curtailment slack variables (generation curtailment pgc, dispatchable-generation slack pgens, load slack pds, charging-point slack pcps, heat-pump slack phps). Reactive injections of the flexibilities are derived from their active power via the power factor (tan(acos(pf))).

This low-level method receives the pre-collected per-bus component maps from constraint_power_balance_bf.

Objective functions

Source: edisgo/opf/eDisGo_OPF.jl/src/core/objective.jl

objective_min_losses

function objective_min_losses(pm::AbstractBFModelEdisgo)

Objective: minimise total ohmic line losses, summed over all time steps, as Σ ccm[b]·r[b] over the non-storage branches. (Defined as an alternative objective; the multi-network build uses objective_min_line_loading_max for opf_version 1.)

objective_min_losses_slacks

function objective_min_losses_slacks(pm::AbstractBFModelEdisgo)

Objective for opf_version 2 — Eq. (3.2 iii) of the eDisGo OPF formulation: minimise a weighted sum of line losses and the grid-restriction slacks. Combines ohmic losses (Σ ccm·r) with penalties on non-dispatchable curtailment (pgc), dispatchable-generation curtailment (pgens), load shedding (pds), charging-point shedding (pcps) and heat-pump shedding (phps), weighted by factor_slacks, plus a large penalty on the heat-storage / heat-pump operation slacks (phss, phps2).

objective_min_line_loading_max

function objective_min_line_loading_max(pm::AbstractBFModelEdisgo)

Objective for opf_version 1 — Eq. (3.2 ii) of the eDisGo OPF formulation: minimise a weighted sum of line losses (Σ ccm·r) and the maximum line loading ll (weighted by factor_ll, scaled by branch cost × length) over the non-storage branches.

objective_min_losses_slacks_OG

function objective_min_losses_slacks_OG(pm::AbstractBFModelEdisgo)

Objective for opf_version 4 (with overlying grid): like objective_min_losses_slacks, but additionally penalises the overlying-grid (HV) requirement slacks phvs (with a reduced weight for DSM requirements). The HV penalty factor is scaled from the branch resistances.

objective_min_line_loading_max_OG

function objective_min_line_loading_max_OG(pm::AbstractBFModelEdisgo)

Objective for opf_version 3 (with overlying grid): like objective_min_line_loading_max (losses + maximum line loading), but additionally penalises the overlying-grid (HV) requirement slacks phvs (reduced weight for DSM).

Data preparation

Source: edisgo/opf/eDisGo_OPF.jl/src/core/data.jl

set_ac_bf_start_values!

function set_ac_bf_start_values!(network::Dict{String,<:Any})

Seed warm-start values on a (single-network) data dict: copy each flexibility’s optimised power/energy results into the corresponding *_start fields, so a subsequent non-convex (Ipopt) solve can be warm-started from a previous solution. Used in the SOC → NC warm_start workflow.

correct_bus_types!

function correct_bus_types!(data::Dict{String,<:Any})

checks bus types are suitable for a power flow study, if not, fixes them.

the primary checks are that all type 2 buses (i.e., PV) have a connected and active generator and there is a single type 3 bus (i.e., slack bus) with an active connected generator.

assumes that the network is a single connected component

_correct_bus_types!

function _correct_bus_types!(pm_data::Dict{String,<:Any})

Internal worker for correct_bus_types!, operating on a single (non-multinetwork) PowerModels data dict.

Demotes PV buses (type 2) without an active generator to PQ (type 1), validates the slack bus (type 3), and — if no slack bus is found — promotes the bus of the largest generator to slack. See correct_bus_types! for the public entry point.

Solution processing

Source: edisgo/opf/eDisGo_OPF.jl/src/core/solution.jl

sol_component_value_radial

function sol_component_value_radial(aim::AbstractPowerModel, n::Int, comp_name::Symbol, field_name_to::Symbol, comp_ids_to, variables)

Solution processor: write a per-branch variable indexed by the directed arc (l, i, j) (e.g. the branch flows) back into the PowerModels solution dict under field_name_to, for the radial branch-flow model. The arc-indexed counterpart of PowerModels’ sol_component_value.

check_SOC_equality

function check_SOC_equality(result, data_edisgo)

Check whether the second-order-cone relaxation is tight in a solved SOC result.

For every non-storage branch and time step it compares pf² + qf² against ccm · w (the SOC inequality); a gap below -1e-1 means the cone is not tight there. Returns (soc_tight, soc_eq_dict), where soc_tight::Bool and soc_eq_dict maps each time step to its offending branches. Used to decide whether a warm_start AC polishing step is needed (see SOCBFPowerModelEdisgo).

I/O — network validation

Source: edisgo/opf/eDisGo_OPF.jl/src/io/common.jl

correct_network_data!

function correct_network_data!(data::Dict{String,<:Any})

Validate and normalise the parsed PowerModels network data before the OPF is built: runs the connectivity / status / limit checks, converts everything to per-unit (make_per_unit!), corrects transformer / voltage-angle / thermal / current limits and branch directions, checks storage / switch / voltage setpoints, and simplifies the cost terms. Called by parse_json when validation is enabled.

I/O — JSON parsing

Source: edisgo/opf/eDisGo_OPF.jl/src/io/json.jl

parse_json

function parse_json(io::Union{IO,String}; kwargs...)::Dict{String,Any}

Parses json from iostream or string