Ipopt solves large-scale nonlinear problems

I’m new to Julia, I’m working on optimal power flow problems in the direction of power systems, and when solving large-scale problems with Julia (there are thousands of variables and constraints, of course, most of them are the same), I run out of memory and don’t know how to solve it

Is the problem sparse? If so, are you making use of sparse arrays to define the problem? The Hessian of the lagrangian and the constraint Jacobian are often sparse for such large problems, and using sparse matrices is then important for performance.

1 Like

I think you will find this post interesting,

And this talk,

2 Likes

The problem is sparse, but I don’t know how to modify and invoke it in Ipopt, and I always thought that in Julia, ipopt would be able to create and process sparse matrices on its own based on the model I provided

If you use JuMP or PowerModels, we do create sparse Jacobians and Hessians. See the benchmarks mentioned by Carleton. You can scale Ipopt to 10^5 and 10^6 variables and constraints on a laptop for optimal power flow.

If you still have trouble, it would be useful if you provided a reproducible example of exactly how you’re setting up and solving your models.

I’m not quite sure where benchmarks should look. I’m researching the most basic ACOPF model, and below is my code, which would be very grateful if you could provide me with some valuable input

using DataFrames
using CSV
using JuMP, Ipopt,Pardiso

mpc = CSV.read("E:\\RTS\\CSV_data\\case118.csv", header=false,DataFrame)  # return DataFrame
bus_data_row = findfirst(x -> x == "bus data", mpc[:, 1])[1]
gen_data_row = findfirst(x -> x == "gen data", mpc[:, 1])[1]
branch_data_row = findfirst(x -> x == "branch data", mpc[:, 1])[1]
gencost_data_row = findfirst(x -> x == "gencost data", mpc[:, 1])[1]
baseMVA_row = findfirst(x -> x == "baseMVA", mpc[:, 1])[1]
baseMVA =  parse(Int, mpc[baseMVA_row+1,1])
bus_num = gen_data_row -bus_data_row-2
gen_num = branch_data_row -gen_data_row -2
branch_num = gencost_data_row-branch_data_row -2

bus_i = parse.(Int,mpc[3:bus_num+2,1])   
bus_type = parse.(Int,mpc[3:bus_num+2,2])
bus_Pd =parse.(Float64,mpc[3:bus_num+2,3] )/baseMVA
bus_Qd =parse.(Float64,mpc[3:bus_num+2,4] )/baseMVA
bus_Gs =parse.(ComplexF64,mpc[3:bus_num+2,5])/baseMVA
bus_Bs =parse.(ComplexF64,mpc[3:bus_num+2,6])/baseMVA
bus_Vmax =parse.(Float64,mpc[3:bus_num+2,12])
bus_Vmin =parse.(Float64,mpc[3:bus_num+2,13])
balance_bus =  findall(bus_type .== 3)[1]
bus_Omax = fill(2*pi, bus_num)
bus_Omax[balance_bus] = 0
bus_Omin = fill(-2*pi, bus_num)
bus_Omin[balance_bus] = 0

gen_bus = parse.(Int,mpc[gen_data_row+2:gen_data_row+gen_num+1,1])
gen_PG = parse.(Float64,mpc[gen_data_row+2:gen_data_row+gen_num+1,2])
gen_QG = parse.(Float64,mpc[gen_data_row+2:gen_data_row+gen_num+1,3])
gen_Qmax = parse.(Float64,mpc[gen_data_row+2:gen_data_row+gen_num+1,4])
gen_Qmin = parse.(Float64,mpc[gen_data_row+2:gen_data_row+gen_num+1,5])
g_status = parse.(Int,mpc[gen_data_row+2:gen_data_row+gen_num+1,8])
gen_Pmax = parse.(Float64,mpc[gen_data_row+2:gen_data_row+gen_num+1,9])
gen_Pmin= parse.(Float64,mpc[gen_data_row+2:gen_data_row+gen_num+1,10])
gencost_cs = parse.(Float64,mpc[gencost_data_row+2:gencost_data_row+gen_num+1,7])
gencost_yc = parse.(Float64,mpc[gencost_data_row+2:gencost_data_row+gen_num+1,6])
gencost_ec = parse.(Float64,mpc[gencost_data_row+2:gencost_data_row+gen_num+1,5])
##############################################################################
gstart_num = count(x -> x == 1, g_status)
gen_on_bus = [gen_bus[i] for i in eachindex(g_status) if g_status[i] != 0]
gon_PG = [gen_PG[i] for i in eachindex(g_status) if g_status[i] != 0]/baseMVA
gon_QG = [gen_QG[i] for i in eachindex(g_status) if g_status[i] != 0]/baseMVA
gon_Qmax = [gen_Qmax[i] for i in eachindex(g_status) if g_status[i] != 0]/baseMVA
gon_Qmin = [gen_Qmin[i] for i in eachindex(g_status) if g_status[i] != 0]/baseMVA
gon_Pmax = [gen_Pmax[i] for i in eachindex(g_status) if g_status[i] != 0]/baseMVA
gon_Pmin = [gen_Pmin[i] for i in eachindex(g_status) if g_status[i] != 0]/baseMVA
goncost_cs = [gencost_cs[i] for i in eachindex(g_status) if g_status[i] != 0]
goncost_yc = [gencost_yc[i] for i in eachindex(g_status) if g_status[i] != 0]*baseMVA
goncost_ec = [gencost_ec[i] for i in eachindex(g_status) if g_status[i] != 0]*baseMVA^2
##############################################################################
ybranch_fbus = parse.(Int,mpc[branch_data_row+2:branch_data_row+branch_num+1,1])
ybranch_tbus = parse.(Int,mpc[branch_data_row+2:branch_data_row+branch_num+1,2])
branch_fbus =zeros(Int,length(ybranch_fbus))
branch_tbus =zeros(Int,length(ybranch_tbus))
for i in 1:branch_num
    branch_fbus[i] = findall(bus_i .== ybranch_fbus[i])[1] 
    branch_tbus[i] = findall(bus_i .== ybranch_tbus[i])[1] 
end  
branch_r = parse.(ComplexF64,mpc[branch_data_row+2:branch_data_row+branch_num+1,3])
branch_x = parse.(ComplexF64,mpc[branch_data_row+2:branch_data_row+branch_num+1,4])
branch_b = parse.(ComplexF64,mpc[branch_data_row+2:branch_data_row+branch_num+1,5])
branch_rate = parse.(Float64,mpc[branch_data_row+2:branch_data_row+branch_num+1,6])/baseMVA
branch_ratio = parse.(Float64,mpc[branch_data_row+2:branch_data_row+branch_num+1,9])
branch_ratio =[if x == 0 1 else x end for x in branch_ratio]   
branch_status =mpc[branch_data_row+2:branch_data_row+branch_num+1,11]

#Node admittance matrix
Y = zeros(ComplexF64,bus_num, bus_num)
for k in 1:branch_num
    k1 =  branch_fbus[k]
    k2 =  branch_tbus[k]
    Y[k1, k2] -=  1 / ((branch_r[k] + im*branch_x[k])* branch_ratio[k])
    Y[k2, k1]  = Y[k1, k2]
    Y[k1, k1] +=  1 / ((branch_r[k] + im*branch_x[k]) * branch_ratio[k] ^ 2) + im*branch_b[k]/2
    Y[k2, k2] +=  1 / (branch_r[k] + im*branch_x[k]) + im*branch_b[k]/2
end

for u in 1:bus_num
    if bus_Gs[u] != 0 || bus_Bs[u] != 0
        Y[u, u] += bus_Gs[u] + bus_Bs[u] * im
    end
end
G = real(Y)
B = imag(Y)

################Branch admittance matrix#################
y = zeros(ComplexF64, branch_num, 2)
for i in 1:branch_num
    y[i, 1] = 1 / ((branch_r[i] + im*branch_x[i]) * branch_ratio[i])
    y[i, 2] = y[i, 1]
end
g = real(y) 
b = imag(y)

#################Yijo = Yi0+Yij############
Yijo = zeros(ComplexF64, branch_num, 2)
for l in 1:branch_num
    if branch_ratio[l] == 1
        Yijo[l, 1] = im*branch_b[l]/2 + 1/((branch_r[l] + im*branch_x[l])* branch_ratio[l])  
        Yijo[l, 2] = Yijo[l, 1]
    else
        Yijo[l, 1] = 1 /((branch_r[l] + im*branch_x[l]) * branch_ratio[l] ^ 2 ) 
        Yijo[l, 2] = 1 /(branch_r[l] + im*branch_x[l])
    end
end

for u in 1:branch_num
    k1 = branch_fbus[u]
    k2 = branch_tbus[u]
    if bus_Gs[k1] != 0 || bus_Bs[k1] != 0 || bus_Gs[k2] != 0 || bus_Bs[k2] != 0
        Yijo[u, 1] += bus_Gs[k1] + bus_Bs[k1]*im
        Yijo[u, 2] += bus_Gs[k2] + bus_Bs[k2]*im
    end
end
Gijo = real(Yijo)
Bijo = imag(Yijo)


######################################################################
# Create model objects
model = Model(
    optimizer_with_attributes(
        Ipopt.Optimizer,
        "print_level" => 4

        )
        )


# Define decision variables
@variable(model, V[1:bus_num])
@variable(model, O[1:bus_num])
@variable(model, PG[1:gstart_num])
@variable(model, QG[1:gstart_num])

# Define the objective function
OPF_Object =sum(goncost_ec[i]*PG[i]^2+goncost_yc[i]*PG[i]+goncost_cs[i] for i in 1:gstart_num)
@objective(model, Min, OPF_Object)

# Define constraints
# local t = 0
for i in 1:bus_num
    if bus_i[i] in gen_on_bus #Generator node
        local q = findall(gen_on_bus .== bus_i[i]) 
        @NLconstraint(model, sum(PG[j] for j in q)-bus_Pd[i]-V[i]^2*G[i,i]-V[i]*sum(V[j]*(G[i,j]*cos(O[i]-O[j])+B[i,j]*sin(O[i]-O[j])) for j in 1:bus_num if j!=i) == 0)
        @NLconstraint(model, sum(QG[j] for j in q)-bus_Qd[i]+V[i]^2*B[i,i]-V[i]*sum(V[j]*(G[i,j]*sin(O[i]-O[j])-B[i,j]*cos(O[i]-O[j])) for j in 1:bus_num if j!=i) == 0)
    else #Non-generator nodes
        @NLconstraint(model, -bus_Pd[i]-V[i]^2*G[i,i]-V[i]*sum(V[j]*(G[i,j]*cos(O[i]-O[j])+B[i,j]*sin(O[i]-O[j])) for j in 1:bus_num if j!=i) == 0)
        @NLconstraint(model, -bus_Qd[i]+V[i]^2*B[i,i]-V[i]*sum(V[j]*(G[i,j]*sin(O[i]-O[j])-B[i,j]*cos(O[i]-O[j])) for j in 1:bus_num if j!=i) == 0)
    end
end

#Line constraints
for i in 1:branch_num
    if branch_rate[i] !=0
        local p = branch_fbus[i]
        local q = branch_tbus[i]
        @NLconstraint(model, -branch_rate[i]<=Gijo[i,1]*V[p]^2-V[p]*V[q]*(g[i,1]*cos(O[p]-O[q])+b[i,1]*sin(O[p]-O[q]))<=branch_rate[i])
        @NLconstraint(model, -branch_rate[i]<=Gijo[i,2]*V[q]^2-V[p]*V[q]*(g[i,2]*cos(O[q]-O[p])+b[i,2]*sin(O[q]-O[p]))<=branch_rate[i])
    end
end   

#Variable constraints
for i in 1:bus_num
    @NLconstraint(model,bus_Vmin[i]<=V[i]<=bus_Vmax[i])
    @NLconstraint(model,bus_Omin[i]<=O[i]<=bus_Omax[i])
end
for i in 1:gstart_num
    @NLconstraint(model,gon_Pmin[i]<=PG[i]<=gon_Pmax[i])
    @NLconstraint(model,gon_Qmin[i]<=QG[i]<=gon_Qmax[i])
end

# Set the initial value
for i in 1:bus_num
    set_start_value(V[i], 1)
    set_start_value(O[i], 0)
end 
for i in 1:gstart_num
    set_start_value(PG[i], gon_PG[i])
    set_start_value(QG[i], gon_QG[i])
end 

# Solve optimization problems
optimize!(model)

println("Optimal objective value: ", JuMP.objective_value(model))

I can’t run your code because I don’t have the .csv. The main thing I’d change with your code would be:

# Define decision variables
@variable(model, bus_Vmin[i] <= V[i=1:bus_num] <= bus_Vmax[i])
@variable(model, bus_Omin[i] <= O[i=1:bus_num] <= bus_Omax[i])
@variable(model, gon_Pmin[i] <= PG[i=1:gstart_num] <= gon_Pmax[i])
@variable(model, gon_Qmin[i] <= QG[i=1:gstart_num] <= gon_Qmax[i])

and delete the #Variable constraints blocks. My way adds variable bounds. Your way adds new rows to the constraint matrix.

Have you considered using PowerModels.jl? GitHub - lanl-ansi/PowerModels.jl: A Julia/JuMP Package for Power Network Optimization

You should also take a look at @ccoffrin’s rosetta-opf project: rosetta-opf/jump.jl at main · lanl-ansi/rosetta-opf · GitHub

If you’re just wanting to solve problems, there are plenty of examples in the PowerModels documentation: Getting Started · PowerModels.

If you want to build a JuMP model of the formulation and then do stuff to it, you can use:

using JuMP, PowerModels, Ipopt
download(
    "https://raw.githubusercontent.com/power-grid-lib/pglib-opf/master/pglib_opf_case118_ieee.m",
    "pglib_opf_case118_ieee.m",
)
model = Model(Ipopt.Optimizer)
power_model = PowerModels.instantiate_model(
    PowerModels.parse_file("pglib_opf_case118_ieee.m"),
    PowerModels.ACPPowerModel,
    PowerModels.build_opf;
    jump_model = model,
)
optimize!(model)

On my laptop, this solves in 0.4 seconds:

julia> optimize!(model)
This is Ipopt version 3.14.4, running with linear solver MUMPS 5.4.1.

Number of nonzeros in equality constraint Jacobian...:     4552
Number of nonzeros in inequality constraint Jacobian.:     1460
Number of nonzeros in Lagrangian Hessian.............:     8198

Total number of variables............................:     1053
                     variables with only lower bounds:        0
                variables with lower and upper bounds:      935
                     variables with only upper bounds:        0
Total number of equality constraints.................:      981
Total number of inequality constraints...............:      730
        inequality constraints with only lower bounds:      179
   inequality constraints with lower and upper bounds:        0
        inequality constraints with only upper bounds:      551

iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
   0  4.7812282e+02 2.76e+00 2.19e+01  -1.0 0.00e+00    -  0.00e+00 0.00e+00   0
   1  3.4413674e+04 2.00e+00 7.98e+01  -1.0 2.86e+00    -  3.58e-03 2.74e-01h  1
   2  3.5528977e+04 1.90e+00 7.55e+01  -1.0 6.95e+00    -  8.37e-02 5.16e-02h  1
   3  3.6121278e+04 1.78e+00 6.94e+01  -1.0 9.60e+00    -  2.78e-01 6.39e-02h  1
   4  4.3035932e+04 1.56e+00 6.06e+01  -1.0 5.99e+00    -  3.79e-01 1.25e-01h  1
   5  6.1165471e+04 9.99e-01 3.88e+01  -1.0 6.58e+00    -  5.19e-01 3.58e-01h  1
   6  7.0545871e+04 7.30e-01 3.17e+01  -1.0 8.66e+00    -  5.33e-01 2.69e-01h  1
   7  8.3787955e+04 3.59e-01 2.24e+01  -1.0 1.00e+01    -  9.37e-01 5.08e-01h  1
   8  9.0768955e+04 1.66e-01 8.62e+00  -1.0 1.30e+01    -  2.12e-01 5.38e-01h  1
   9  9.2115541e+04 1.22e-01 9.08e+00  -1.0 1.78e+01    -  8.00e-01 2.67e-01h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  10  9.4118086e+04 7.71e-02 5.72e+00  -1.0 8.50e+00    -  2.88e-01 3.66e-01h  1
  11  9.7131618e+04 1.91e-02 1.64e+00  -1.0 3.65e+00    -  1.00e+00 8.42e-01h  1
  12  9.7745336e+04 1.85e-03 6.29e+01  -1.0 4.66e+00    -  2.24e-01 1.00e+00H  1
  13  9.7687599e+04 7.47e-03 7.32e+00  -1.0 2.01e+00    -  1.00e+00 1.00e+00f  1
  14  9.7695486e+04 4.71e-04 1.96e-01  -1.0 7.26e-01    -  1.00e+00 1.00e+00h  1
  15  9.7487469e+04 4.57e-03 1.23e+00  -2.5 5.77e+00    -  7.89e-01 5.54e-01f  1
  16  9.7309870e+04 2.44e-03 2.29e-01  -2.5 1.86e+00    -  7.38e-01 7.83e-01f  1
  17  9.7248611e+04 2.04e-03 1.10e+00  -2.5 2.50e+00    -  9.51e-01 7.64e-01h  1
  18  9.7231319e+04 1.11e-03 1.34e-02  -2.5 9.23e-01    -  1.00e+00 1.00e+00h  1
  19  9.7233035e+04 2.49e-06 8.98e-05  -2.5 5.66e-02    -  1.00e+00 1.00e+00h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  20  9.7219104e+04 2.56e-04 1.84e-01  -3.8 6.46e-01    -  8.60e-01 7.15e-01f  1
  21  9.7214346e+04 6.81e-05 1.40e-01  -3.8 1.78e-01    -  8.75e-01 1.00e+00h  1
  22  9.7214571e+04 4.67e-06 1.27e-04  -3.8 2.43e-02    -  1.00e+00 1.00e+00h  1
  23  9.7213705e+04 6.33e-06 3.71e-03  -5.7 3.15e-02    -  9.22e-01 9.07e-01h  1
  24  9.7213619e+04 7.25e-07 2.59e-05  -5.7 7.28e-03    -  1.00e+00 1.00e+00h  1
  25  9.7213619e+04 1.13e-07 5.09e-06  -5.7 3.18e-03    -  1.00e+00 1.00e+00h  1
  26  9.7213607e+04 4.76e-08 3.72e-05  -8.6 2.04e-03    -  9.88e-01 1.00e+00h  1
  27  9.7213607e+04 1.05e-08 4.75e-07  -8.6 9.70e-04    -  1.00e+00 1.00e+00h  1
  28  9.7213607e+04 1.93e-09 8.74e-08  -8.6 4.15e-04    -  1.00e+00 1.00e+00h  1
  29  9.7213607e+04 1.51e-10 6.86e-09  -8.6 1.16e-04    -  1.00e+00 1.00e+00h  1

Number of Iterations....: 29

                                   (scaled)                 (unscaled)
Objective...............:   7.8032097059689613e+02    9.7213606938959332e+04
Dual infeasibility......:   6.8594320180172386e-09    8.5455876895626375e-07
Constraint violation....:   1.5122502902698010e-10    1.5122502902698010e-10
Variable bound violation:   6.5043916031015669e-08    6.5043916031015669e-08
Complementarity.........:   6.1117630289071873e-09    7.6141299693863464e-07
Overall NLP error.......:   6.8594320180172386e-09    8.5455876895626375e-07


Number of objective function evaluations             = 31
Number of objective gradient evaluations             = 30
Number of equality constraint evaluations            = 31
Number of inequality constraint evaluations          = 31
Number of equality constraint Jacobian evaluations   = 30
Number of inequality constraint Jacobian evaluations = 30
Number of Lagrangian Hessian evaluations             = 29
Total seconds in IPOPT                               = 0.370

EXIT: Optimal Solution Found.

You can find other cases at GitHub - power-grid-lib/pglib-opf: Benchmarks for the Optimal Power Flow Problem

1 Like

Thank you very much for your help, my code does have shortcomings, I also tried to run the PowerModels you mentioned and it worked

using JuMP, PowerModels, Ipopt
download(
    "https://raw.githubusercontent.com/power-grid-lib/pglib-opf/master/pglib_opf_case2736sp_k.m",
    "pglib_opf_case2736sp_k__api.m",
)
model = Model(Ipopt.Optimizer)
power_model = PowerModels.instantiate_model(
    PowerModels.parse_file("pglib_opf_case2736sp_k__api.m"),
    PowerModels.ACPPowerModel,
    PowerModels.build_opf;
    jump_model = model,
)
optimize!(model)
println("Optimal objective value: ", JuMP.objective_value(model))

Here is the result of my output

This is Ipopt version 3.13.4, running with linear solver mumps.
NOTE: Other linear solvers might be more efficient (see Ipopt documentation).

Number of nonzeros in equality constraint Jacobian...:    78762
Number of nonzeros in inequality constraint Jacobian.:    26128
Number of nonzeros in Lagrangian Hessian.............:   143837

Total number of variables............................:    18852
                     variables with only lower bounds:        0
                variables with lower and upper bounds:    16116
                     variables with only upper bounds:        0
Total number of equality constraints.................:    18549
Total number of inequality constraints...............:    13064
        inequality constraints with only lower bounds:     3263
   inequality constraints with lower and upper bounds:        0
        inequality constraints with only upper bounds:     9801

iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
   0  9.5127271e+05 7.87e+00 1.00e+02  -1.0 0.00e+00    -  0.00e+00 0.00e+00   0
   1  9.5469096e+05 7.79e+00 9.89e+01  -1.0 5.30e+00    -  6.92e-03 1.00e-02h  1
   2  9.5073275e+05 7.68e+00 9.81e+01  -1.0 1.65e+01    -  2.31e-03 1.42e-02f  1
   3  9.4740076e+05 7.56e+00 9.48e+01  -1.0 1.48e+01    -  3.95e-02 1.63e-02f  1
   4  9.4701858e+05 6.93e+00 8.21e+01  -1.0 9.56e+00    -  1.50e-01 8.32e-02f  1
   5  9.4725378e+05 6.41e+00 7.33e+01  -1.0 3.00e+01    -  1.37e-01 7.44e-02f  1
   6  9.4770877e+05 6.30e+00 7.66e+01  -1.0 4.81e+01    -  4.01e-02 1.82e-02h  1
   7  9.6460459e+05 5.94e+00 6.06e+01  -1.0 1.71e+01    -  4.50e-04 5.65e-02h  1
   8  9.8599397e+05 5.48e+00 5.58e+01  -1.0 1.97e+01    -  4.35e-02 7.80e-02h  1
   9  1.0047233e+06 5.08e+00 5.15e+01  -1.0 2.22e+01    -  3.91e-02 7.21e-02h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  10  1.0184715e+06 4.81e+00 4.88e+01  -1.0 2.21e+01    -  6.14e-02 5.45e-02h  1
  11  1.0354602e+06 4.50e+00 4.48e+01  -1.0 2.11e+01    -  2.40e-02 6.27e-02h  1
  12  1.1000420e+06 3.36e+00 3.30e+01  -1.0 2.59e+01    -  3.03e-02 2.55e-01h  1
  13  1.1207195e+06 3.00e+00 2.94e+01  -1.0 2.19e+01    -  1.37e-01 1.06e-01h  1
  14  1.1473702e+06 2.56e+00 2.51e+01  -1.0 1.74e+01    -  1.30e-01 1.49e-01h  1
  15  1.1718054e+06 2.16e+00 2.11e+01  -1.0 1.22e+01    -  2.24e-01 1.56e-01h  1
  16  1.2179292e+06 1.42e+00 1.40e+01  -1.0 1.17e+01    -  2.55e-01 3.44e-01h  1
  17  1.2462822e+06 9.74e-01 9.86e+00  -1.0 9.13e+00    -  5.15e-01 3.12e-01h  1
  18  1.2628349e+06 7.23e-01 9.08e+00  -1.0 6.47e+00    -  4.00e-01 2.58e-01h  1
  19  1.2968734e+06 2.15e-01 1.12e+01  -1.0 7.15e+00    -  9.91e-01 7.02e-01h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  20  1.3105249e+06 1.73e-02 3.45e+00  -1.0 2.23e+00    -  1.00e+00 9.20e-01h  1
  21  1.3117980e+06 8.26e-05 3.24e-02  -1.0 3.58e-01    -  1.00e+00 1.00e+00h  1
  22  1.3109731e+06 6.05e-04 1.18e+01  -2.5 9.02e-01    -  6.56e-01 5.72e-01f  1
  23  1.3099179e+06 2.55e-03 3.75e+00  -2.5 7.06e-01    -  2.45e-01 7.33e-01f  1
  24  1.3089933e+06 2.59e-03 1.62e+00  -2.5 3.43e-01    -  6.00e-01 8.98e-01f  1
  25  1.3085161e+06 1.71e-03 4.04e+00  -2.5 1.84e-01    -  2.80e-01 5.64e-01f  1
  26  1.3083348e+06 1.14e-03 7.77e+00  -2.5 3.12e-01    -  9.47e-01 3.89e-01f  1
  27  1.3082912e+06 9.33e-04 2.59e+01  -2.5 3.16e-01    -  1.00e+00 1.78e-01h  1
  28  1.3081319e+06 5.77e-04 3.64e+01  -2.5 2.42e-01    -  1.62e-01 9.66e-01f  1
  29  1.3081541e+06 3.35e-05 1.30e-02  -2.5 9.10e-02    -  1.00e+00 1.00e+00h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  30  1.3081003e+06 6.51e-05 2.75e+01  -3.8 1.80e-01    -  6.77e-01 3.07e-01f  1
  31  1.3080502e+06 1.95e-04 2.29e+01  -3.8 1.97e-01    -  7.50e-01 5.09e-01f  1
  32  1.3080315e+06 1.65e-04 1.62e+01  -3.8 1.74e-01    -  9.40e-01 5.14e-01h  1
  33  1.3080210e+06 9.02e-05 6.38e+00  -3.8 1.26e-01    -  1.00e+00 7.83e-01h  1
  34  1.3080197e+06 5.43e-06 2.19e-04  -3.8 3.17e-02    -  1.00e+00 1.00e+00h  1
  35  1.3080166e+06 7.57e-06 2.29e+00  -5.7 1.09e-01    -  8.60e-01 6.40e-01h  1
  36  1.3080154e+06 5.62e-06 1.72e+00  -5.7 1.01e-01    -  9.22e-01 7.20e-01h  1
  37  1.3080150e+06 1.70e-06 1.91e-02  -5.7 5.09e-02    -  1.00e+00 9.91e-01h  1
  38  1.3080150e+06 2.89e-08 8.45e-07  -5.7 3.68e-03    -  1.00e+00 1.00e+00h  1
  39  1.3080150e+06 1.85e-08 3.48e-02  -8.6 4.85e-03    -  8.25e-01 9.73e-01h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  40  1.3080150e+06 1.16e-09 5.34e-04  -8.6 1.05e-03    -  9.88e-01 1.00e+00h  1
  41  1.3080150e+06 2.67e-11 5.68e-09  -8.6 4.31e-05    -  1.00e+00 1.00e+00h  1

Number of Iterations....: 41

                                   (scaled)                 (unscaled)
Objective...............:   1.1275019335795156e+04    1.3080149931455960e+06
Dual infeasibility......:   5.6835424466209047e-09    6.5934775923249118e-07
Constraint violation....:   2.6710969373844318e-11    2.6710969373844318e-11
Complementarity.........:   5.5561117961707670e-09    6.4456452947377074e-07
Overall NLP error.......:   5.6835424466209047e-09    6.5934775923249118e-07


Number of objective function evaluations             = 42
Number of objective gradient evaluations             = 42
Number of equality constraint evaluations            = 42
Number of inequality constraint evaluations          = 42
Number of equality constraint Jacobian evaluations   = 42
Number of inequality constraint Jacobian evaluations = 42
Number of Lagrangian Hessian evaluations             = 41
Total CPU secs in IPOPT (w/o function evaluations)   =      4.523
Total CPU secs in NLP function evaluations           =      1.397

EXIT: Optimal Solution Found.
Optimal objective value: 1.308014993145596e6

This result is consistent with the MATPOWER result,but what I wanted to do was how to add some new constraints and variables to the original OPF model, which has been bothering me for a long time, but I see hope in PowerModels。

1 Like

download(...) is a tool that I did not know about until this post. Thanks for the tip @odow. If you want an even more Julia friendly version of PGLib data there is this package,

2 Likes

See PowerModelsAnnex.jl/ac-opf.jl at master · lanl-ansi/PowerModelsAnnex.jl · GitHub for a selection of models that you could use as the base to make modifications

How to call a class function you wrote in another file, something like this
`mutable struct PyClass
a::Float64
b::Float64
n::Int
end

PyClass() = PyClass(0.0, 0.0, 0)
function init(self::PyClass)
self.a = 1.0
self.b = 2.0
self.n = 10
end

function method1(self::PyClass)
self.n += 1
nothing
end

function method2(self::PyClass)
return self.a + self.b
end

mim = init(PyClass())
method1(mim)
method2(mim)`

You can use include("path/to/file.jl") to load another file.

Note that unlike Python, Julia doesn’t have classes, and it doesn’t have file-level namespaces.

Can I ask you again how to use the ‘OPFLearn’ package, if there are examples of running it, I think I can grasp it a little faster

I don’t know what this is. If you have specific questions and can provide more information, please start a new thread.

ok

using JuMP, PowerModels, Ipopt,SCS


file_name = "E:/Vscode——data/data/case300.m"

model = Model(Ipopt.Optimizer)
power_model = PowerModels.instantiate_model(
    PowerModels.parse_file(file_name),
    # println(PowerModels.parse_file(file_name)),
    PowerModels.DCPLLPowerModel,
    PowerModels.build_opf;
    jump_model = model,
)
optimize!(model)
println("Optimal objective value: ", JuMP.objective_value(model))

Can I replace the .m file here with a csv file and import it directly into this model to run. Or is there a way to modify the data directly in the .m file and import it into a later model

What is the format of the CSV file you want to use?

You could just edit the file manually?

Otherwise you can modify the elements of the dictionary returned by parse_file.

See Network Data Format · PowerModels

Manual editing is very difficult, my intention is to modify the load in the case300 study, I need to modify it thousands of times, and then output their final result

Then you may want to call parse_file once, and programmatically edit the elements inside it for each solve.