I would start with one of the simplest convex relaxations. That is the SOC relaxation in the W space. The idea is, defined new voltage product variables W^R_{i,j} + i*W^I_{i,j} , which will represent the complex voltage products V_i * V_j . You go through your model and make these replacements,
|V_i||V_i| \rightarrow W_{ii} \\
|V_i||V_j| cos(\theta_i - \theta_j) \rightarrow W^R_{ij} \\
|V_i||V_j| sin(\theta_i - \theta_j) \rightarrow W^I_{ij}
You then add this constraint,
(W^R_{ij})^2 + (W^I_{ij})^2 \leq W^R_{ii}*W^I_{ii}
As a refrence implementation here is how AC and SOC models are constructed in PowerModels,
export build_ac_opf, build_soc_opf, build_qc_opf, build_dc_opf
"""
Given a JuMP model and a PowerModels network data structure,
Builds an AC-OPF formulation of the given data and returns the JuMP model
"""
function build_ac_opf(data::Dict{String,Any}, model=Model())
@assert !haskey(data, "multinetwork")
@assert !haskey(data, "conductors")
PowerModels.standardize_cost_terms!(data, order=2)
ref = PowerModels.build_ref(data)[:it][_PM.pm_it_sym][:nw][nw_id_default]
@variable(model, va[i in keys(ref[:bus])])
@variable(model, ref[:bus][i]["vmin"] <= vm[i in keys(ref[:bus])] <= ref[:bus][i]["vmax"], start=1.0)
@variable(model, ref[:gen][i]["pmin"] <= pg[i in keys(ref[:gen])] <= ref[:gen][i]["pmax"])
end
return model
end
"""
Given a JuMP model and a PowerModels network data structure,
Builds an SOC-OPF formulation of the given data and returns the JuMP model
"""
function build_soc_opf(data::Dict{String,Any}, model=Model())
@assert !haskey(data, "multinetwork")
@assert !haskey(data, "conductors")
PowerModels.standardize_cost_terms!(data, order=2)
ref = PowerModels.build_ref(data)[:it][_PM.pm_it_sym][:nw][nw_id_default]
@variable(model, ref[:bus][i]["vmin"]^2 <= w[i in keys(ref[:bus])] <= ref[:bus][i]["vmax"]^2, start=1.001)
wr_min, wr_max, wi_min, wi_max = PowerModels.ref_calc_voltage_product_bounds(ref[:buspairs])
1 Like