Dear @odow, thanks for the quick reply. I guessed I should provide the whole code, so here is a simple (silly) example that shows what I mean.
First, the IEEE case14 casefile including storage - to be saved as “case14.m” (MatPower/MATLAB):
%% MATPOWER Case Format : Version 2
mpc.version = '2';
%%----- Power Flow Data -----%%
%% system MVA base
mpc.baseMVA = 100;
%% bus data
% bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin
mpc.bus = [
1 3 0 0 0 0 1 1.06 0 0 1 1.06 0.94;
2 2 21.7 12.7 0 0 1 1.045 -4.98 0 1 1.06 0.94;
3 2 94.2 19 0 0 1 1.01 -12.72 0 1 1.06 0.94;
4 1 47.8 -3.9 0 0 1 1.019 -10.33 0 1 1.06 0.94;
5 1 7.6 1.6 0 0 1 1.02 -8.78 0 1 1.06 0.94;
6 2 11.2 7.5 0 0 1 1.07 -14.22 0 1 1.06 0.94;
7 1 0 0 0 0 1 1.062 -13.37 0 1 1.06 0.94;
8 2 0 0 0 0 1 1.09 -13.36 0 1 1.06 0.94;
9 1 29.5 16.6 0 19 1 1.056 -14.94 0 1 1.06 0.94;
10 1 9 5.8 0 0 1 1.051 -15.1 0 1 1.06 0.94;
11 1 3.5 1.8 0 0 1 1.057 -14.79 0 1 1.06 0.94;
12 1 6.1 1.6 0 0 1 1.055 -15.07 0 1 1.06 0.94;
13 1 13.5 5.8 0 0 1 1.05 -15.16 0 1 1.06 0.94;
14 1 14.9 5 0 0 1 1.036 -16.04 0 1 1.06 0.94;
];
%% generator data
% bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf
mpc.gen = [
1 232.4 -16.9 10 0 1.06 100 1 332.4 0 0 0 0 0 0 0 0 0 0 0 0;
2 40 42.4 50 -40 1.045 100 1 140 0 0 0 0 0 0 0 0 0 0 0 0;
3 0 23.4 40 0 1.01 100 1 100 0 0 0 0 0 0 0 0 0 0 0 0;
6 0 12.2 24 -6 1.07 100 1 100 0 0 0 0 0 0 0 0 0 0 0 0;
8 0 17.4 24 -6 1.09 100 1 100 0 0 0 0 0 0 0 0 0 0 0 0;
];
%% branch data
% fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax
mpc.branch = [
1 2 0.01938 0.05917 0.0528 0 0 0 0 0 1 -360 360;
1 5 0.05403 0.22304 0.0492 0 0 0 0 0 1 -360 360;
2 3 0.04699 0.19797 0.0438 0 0 0 0 0 1 -360 360;
2 4 0.05811 0.17632 0.034 0 0 0 0 0 1 -360 360;
2 5 0.05695 0.17388 0.0346 0 0 0 0 0 1 -360 360;
3 4 0.06701 0.17103 0.0128 0 0 0 0 0 1 -360 360;
4 5 0.01335 0.04211 0 0 0 0 0 0 1 -360 360;
4 7 0 0.20912 0 0 0 0 0.978 0 1 -360 360;
4 9 0 0.55618 0 0 0 0 0.969 0 1 -360 360;
5 6 0 0.25202 0 0 0 0 0.932 0 1 -360 360;
6 11 0.09498 0.1989 0 0 0 0 0 0 1 -360 360;
6 12 0.12291 0.25581 0 0 0 0 0 0 1 -360 360;
6 13 0.06615 0.13027 0 0 0 0 0 0 1 -360 360;
7 8 0 0.17615 0 0 0 0 0 0 1 -360 360;
7 9 0 0.11001 0 0 0 0 0 0 1 -360 360;
9 10 0.03181 0.0845 0 0 0 0 0 0 1 -360 360;
9 14 0.12711 0.27038 0 0 0 0 0 0 1 -360 360;
10 11 0.08205 0.19207 0 0 0 0 0 0 1 -360 360;
12 13 0.22092 0.19988 0 0 0 0 0 0 1 -360 360;
13 14 0.17093 0.34802 0 0 0 0 0 0 1 -360 360;
];
%%----- OPF Data -----%%
%% generator cost data
% 1 startup shutdown n x1 y1 ... xn yn
% 2 startup shutdown n c(n-1) ... c0
mpc.gencost = [
2 0 0 3 0.01 10 0;
2 0 0 3 0.07 20 0;
2 0 0 3 0.05 50 0;
2 0 0 3 0.04 40 0;
2 0 0 3 0.02 30 0;
];
% hours
mpc.time_elapsed = 1.0
%% storage data
% storage_bus ps qs energy energy_rating charge_rating discharge_rating charge_efficiency discharge_efficiency thermal_rating qmin qmax r x p_loss q_loss status
mpc.storage = [
6 0.0 0.0 20.0 100.0 50.0 70.0 0.8 0.9 100.0 -50.0 70.0 0.1 0.0 0.0 0.0 1;
7 0.0 0.0 30.0 100.0 50.0 70.0 0.9 0.8 100.0 -50.0 70.0 0.1 0.0 0.0 0.0 1;
];
Then, the code that runs optimal power flow (OPF):
using PowerModels, JuMP, Ipopt, Juniper
# optimizer
optimizer = Juniper.Optimizer
nl_solver = optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 3)
minlp_solver = optimizer_with_attributes(optimizer, "nl_solver" => nl_solver, "log_levels" => [])
# time horizon (replica)
# T = 5
T = 15
# T = 30
# Multinetwork
net_single = PowerModels.parse_file("case14.m")
net_multi = replicate(net_single , T)
# OPF
results = PowerModels.solve_mn_opf_strg(net_multi, PowerModels.ACPPowerModel, minlp_solver)
The output is that it does converge, however there are several iterations of IPOPT (with larger T more iterations), like this:
[...]
Total number of variables............................: 1585
variables with only lower bounds: 0
variables with lower and upper bounds: 457
variables with only upper bounds: 0
Total number of equality constraints.................: 1404
Total number of inequality constraints...............: 312
inequality constraints with only lower bounds: 48
inequality constraints with lower and upper bounds: 240
inequality constraints with only upper bounds: 24
Number of Iterations....: 17
(scaled) (unscaled)
Objective...............: 8.2689288055489249e+02 4.1344643945171869e+04
Dual infeasibility......: 3.4937205317300841e-13 1.7468602623762453e-11
Constraint violation....: 9.1315843775419125e-15 9.1315843775419125e-15
Variable bound violation: 1.0499368707783674e-08 1.0499368707783674e-08
Complementarity.........: 9.3111609659656525e-10 4.6555804736847871e-08
Overall NLP error.......: 9.3111609659656525e-10 4.6555804736847871e-08
Number of objective function evaluations = 21
Number of objective gradient evaluations = 18
Number of equality constraint evaluations = 21
Number of inequality constraint evaluations = 21
Number of equality constraint Jacobian evaluations = 18
Number of inequality constraint Jacobian evaluations = 18
Number of Lagrangian Hessian evaluations = 17
Total seconds in IPOPT = 0.827
EXIT: Optimal Solution Found.
Total number of variables............................: 1584
variables with only lower bounds: 0
variables with lower and upper bounds: 456
variables with only upper bounds: 0
Total number of equality constraints.................: 1404
Total number of inequality constraints...............: 312
inequality constraints with only lower bounds: 48
inequality constraints with lower and upper bounds: 240
inequality constraints with only upper bounds: 24
Number of Iterations....: 19
(scaled) (unscaled)
Objective...............: 8.2689420825235823e+02 4.1344710330045025e+04
Dual infeasibility......: 3.3940203096770292e-13 1.6970101514492774e-11
Constraint violation....: 7.6327832942979512e-15 7.6327832942979512e-15
Variable bound violation: 1.0500180280814675e-08 1.0500180280814675e-08
Complementarity.........: 1.1374174929826561e-09 5.6870874535551351e-08
Overall NLP error.......: 1.1374174929826561e-09 5.6870874535551351e-08
Number of objective function evaluations = 25
Number of objective gradient evaluations = 20
Number of equality constraint evaluations = 25
Number of inequality constraint evaluations = 25
Number of equality constraint Jacobian evaluations = 20
Number of inequality constraint Jacobian evaluations = 20
Number of Lagrangian Hessian evaluations = 19
Total seconds in IPOPT = 0.538
EXIT: Optimal Solution Found.
Total number of variables............................: 1584
variables with only lower bounds: 0
variables with lower and upper bounds: 456
variables with only upper bounds: 0
Total number of equality constraints.................: 1404
Total number of inequality constraints...............: 312
inequality constraints with only lower bounds: 48
inequality constraints with lower and upper bounds: 240
inequality constraints with only upper bounds: 24
Number of Iterations....: 17
(scaled) (unscaled)
Objective...............: 8.2689288055486543e+02 4.1344643945170516e+04
Dual infeasibility......: 4.6103210505637627e-13 2.3051605206780574e-11
Constraint violation....: 8.5487172896137054e-15 8.5487172896137054e-15
Variable bound violation: 1.0499368707783674e-08 1.0499368707783674e-08
Complementarity.........: 9.3111301238100338e-10 4.6555650526070085e-08
Overall NLP error.......: 9.3111301238100338e-10 4.6555650526070085e-08
Number of objective function evaluations = 21
Number of objective gradient evaluations = 18
Number of equality constraint evaluations = 21
Number of inequality constraint evaluations = 21
Number of equality constraint Jacobian evaluations = 18
Number of inequality constraint Jacobian evaluations = 18
Number of Lagrangian Hessian evaluations = 17
Total seconds in IPOPT = 0.492
EXIT: Optimal Solution Found.
Dict{String, Any} with 8 entries:
"solve_time" => 90.632
"optimizer" => "Juniper"
"termination_status" => LOCALLY_SOLVED
"dual_status" => NO_SOLUTION
"primal_status" => FEASIBLE_POINT
"objective" => 41344.7
"solution" => Dict{String, Any}("multiinfrastructure"=>false, "multinetwork"=>true, "nw"=>Dict{String, Any}("4"=>Dict{String, Any}("baseMVA"=>100, "branch"=>Dict{String, Any}("4"=>Dict{String, Any}("qf"=>-0.0149719, "qt"=>0.0252754, "pt"=>-0.511128, "pf"=>0.526193), "1"=>Dict{String, Any}("qf"=>-0.… "objective_lb" => 41344.7
My problem is that, if I have a more complex problem (volatile and negative loads, curtailment generators, more storage units), it takes a lot longer to compute even at T=12 (several hours to not finishing…).
Hence, my question is, whether this is as it should be or whether I overlooked something that makes my code faster (e.g. Multithreading doesn’t work here)?
Thanks a lot!