function t_opf(quiet)
%T_OPF  Tests for optimal power flow.

%   MATPOWER
%   $Id: t_opf.m,v 1.12 2006/09/14 19:08:44 ray Exp $
%   by Ray Zimmerman, PSERC Cornell
%   Copyright (c) 2004 by Power System Engineering Research Center (PSERC)
%   See http://www.pserc.cornell.edu/matpower/ for more info.

if nargin < 1
    quiet = 0;
end

num_tests = 105;

t_begin(num_tests, quiet);

[GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...
    MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...
    QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;
[F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
    TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
    ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;

casefile = 't_case9_opf';
if quiet
    verbose = 0;
else
    verbose = 0;
end
mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose);

%% get solved AC power flow case from MAT-file
load soln9_opf;     %% defines bus_soln, gen_soln, branch_soln, f_soln

%% run default OPF
t = 'default OPF : ';
[baseMVA, bus, gen, gencost, branch, f, success, et] = runopf(casefile, mpopt);
t_ok(success, [t 'success']);
t_is(f, f_soln, 3, [t 'f']);
t_is(bus, bus_soln, 3, [t 'bus']);
t_is(gen, gen_soln, 3, [t 'gen']);
t_is(branch(:,1:MU_ST), branch_soln, 3, [t 'branch']);

%% run minopf OPF
if have_fcn('minopf')
    t = 'minopf OPF : ';
    mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose, 'OPF_ALG', 500);
    [baseMVA, bus, gen, gencost, branch, f, success, et] = runopf(casefile, mpopt);
    t_ok(success, [t 'success']);
    t_is(f, f_soln, 2, [t 'f']);
    t_is(bus, bus_soln, 3, [t 'bus']);
    t_is(gen, gen_soln, 2, [t 'gen']);
    t_is(branch(:,1:MU_ST), branch_soln, 2, [t 'branch']);
else
    t_skip(5, 'MINOPF not available');
end

%% run fmincon OPF
if have_fcn('fmincon')
    t = 'fmincon OPF : ';
    mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose, 'OPF_ALG', 520);
    [baseMVA, bus, gen, gencost, branch, f, success, et] = runopf(casefile, mpopt);
    t_ok(success, [t 'success']);
    t_is(f, f_soln, 2, [t 'f']);
    t_is(bus, bus_soln, 2, [t 'bus']);
    t_is(gen, gen_soln, 2, [t 'gen']);
    t_is(branch(:,1:MU_ST), branch_soln, 2, [t 'branch']);
else
    t_skip(5, 'fmincon not available');
end

%% run constr OPF
if have_fcn('constr')
    t = 'constr OPF : ';
    mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose, 'OPF_ALG', 200);
    [baseMVA, bus, gen, gencost, branch, f, success, et] = runopf(casefile, mpopt);
    t_ok(success, [t 'success']);
    t_is(f, f_soln, 2, [t 'f']);
    t_is(bus, bus_soln, 2, [t 'bus']);
    t_is(gen, gen_soln, 2, [t 'gen']);
    t_is(branch, branch_soln, 2, [t 'branch']);
else
    t_skip(5, 'constr not available');
end

%% run dense LP-based OPF
t = 'dense LP-based OPF : ';
mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose, 'OPF_ALG', 220);
[baseMVA, bus, gen, gencost, branch, f, success, et] = runopf(casefile, mpopt);
t_ok(success, [t 'success']);
t_is(f, f_soln, 2, [t 'f']);
t_is(bus, bus_soln, 2, [t 'bus']);
t_is(gen, gen_soln, 2, [t 'gen']);
t_is(branch, branch_soln, 2, [t 'branch']);

%% run sparse (relaxed) LP-based OPF
t = 'sparse (relaxed) LP-based OPF : ';
mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose, 'OPF_ALG', 240);
[baseMVA, bus, gen, gencost, branch, f, success, et] = runopf(casefile, mpopt);
t_ok(success, [t 'success']);
t_is(f, f_soln, 2, [t 'f']);
t_is(bus, bus_soln, 2, [t 'bus']);
t_is(gen, gen_soln, 2, [t 'gen']);
t_is(branch, branch_soln, 2, [t 'branch']);

%% run sparse (full) LP-based OPF
t = 'sparse (full) LP-based OPF : ';
mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose, 'OPF_ALG', 260);
[baseMVA, bus, gen, gencost, branch, f, success, et] = runopf(casefile, mpopt);
t_ok(success, [t 'success']);
t_is(f, f_soln, 2, [t 'f']);
t_is(bus, bus_soln, 2, [t 'bus']);
t_is(gen, gen_soln, 2, [t 'gen']);
t_is(branch, branch_soln, 2, [t 'branch']);

%% get solved AC power flow case from MAT-file
load soln9_opf_Plim;       %% defines bus_soln, gen_soln, branch_soln, f_soln

%% run fmincon OPF with active power line limits
if have_fcn('fmincon')
    t = 'fmincon OPF (P line lim) : ';
    mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose, 'OPF_P_LINE_LIM', 1, 'OPF_ALG', 520);
    [baseMVA, bus, gen, gencost, branch, f, success, et] = runopf(casefile, mpopt);
    t_ok(success, [t 'success']);
    t_is(f, f_soln, 2, [t 'f']);
    t_is(bus(:,1:15), bus_soln(:,1:15), 1, [t 'bus']);  %% skip MU_VMAX, MU_VMIN multipliers
    t_is(gen, gen_soln, 1, [t 'gen']);
    t_is(branch(:,1:MU_ST), branch_soln, 1, [t 'branch']);
else
    t_skip(5, 'fmincon not available');
end

%% run constr OPF with active power line limits
if have_fcn('constr')
    t = 'constr OPF (P line lim) : ';
    mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose, 'OPF_P_LINE_LIM', 1, 'OPF_ALG', 200);
    [baseMVA, bus, gen, gencost, branch, f, success, et] = runopf(casefile, mpopt);
    t_ok(success, [t 'success']);
    t_is(f, f_soln, 2, [t 'f']);
    t_is(bus, bus_soln, 2, [t 'bus']);
    t_is(gen, gen_soln, 2, [t 'gen']);
    t_is(branch, branch_soln, 2, [t 'branch']);
else
    t_skip(5, 'constr not available');
end

%% run sparse (relaxed) LP-based OPF with active power line limits
t = 'sparse (relaxed) LP-based OPF (P line lim) : ';
mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose, 'OPF_P_LINE_LIM', 1, 'OPF_ALG', 240);
[baseMVA, bus, gen, gencost, branch, f, success, et] = runopf(casefile, mpopt);
t_ok(success, [t 'success']);
t_is(f, f_soln, 2, [t 'f']);
t_is(bus, bus_soln, 2, [t 'bus']);
t_is(gen, gen_soln, 2, [t 'gen']);
t_is(branch, branch_soln, 2, [t 'branch']);

%% get solved DC power flow case from MAT-file
load soln9_dcopf;       %% defines bus_soln, gen_soln, branch_soln, f_soln

%% run DC OPF
t = 'DC OPF : ';
mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose);
[baseMVA, bus, gen, gencost, branch, f, success, et] = rundcopf(casefile, mpopt);
t_ok(success, [t 'success']);
t_is(f, f_soln, 3, [t 'f']);
t_is(bus, bus_soln, 3, [t 'bus']);
t_is(gen, gen_soln, 3, [t 'gen']);
t_is(branch, branch_soln, 3, [t 'branch']);

%%-----  test OPF with quadratic gen costs moved to generalized costs  -----
mpc = loadcase(casefile);
mpc.gencost = [
    2   1500    0   3   0.11    5   0;
    2   2000    0   3   0.085   1.2 0;
    2   3000    0   3   0.1225  1   0;
];
mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose);
[baseMVA, bus_soln, gen_soln, gencost, branch_soln, f_soln, success, et] = runopf(mpc, mpopt);
branch_soln = branch_soln(:,1:MU_ST);

A = [];
l = [];
u = [];
nb = size(mpc.bus, 1);      % number of buses
ng = size(mpc.gen, 1);      % number of gens
thbas = 1;                thend    = thbas+nb-1;
vbas     = thend+1;       vend     = vbas+nb-1;
pgbas    = vend+1;        pgend    = pgbas+ng-1;
qgbas    = pgend+1;       qgend    = qgbas+ng-1;
nxyz = 2*nb + 2*ng;
N = sparse([1:ng]', [pgbas:pgend]', mpc.baseMVA * ones(ng,1), ng, nxyz);
fparm = ones(ng,1) * [ 1 0 0 1 ];
[junk, ix] = sort(mpc.gen(:, 1));
H = 2 * spdiags(mpc.gencost(ix, 5), 0, ng, ng);
Cw = mpc.gencost(ix, 6);
mpc.gencost(:, 5:7) = 0;

%% run minopf OPF with quadratic gen costs moved to generalized costs
if have_fcn('minopf')
    t = 'minopf OPF w/quadratic generalized gen cost : ';
    mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose, 'OPF_ALG', 500);
   [bus, gen, branch, f, success, info, et] = ...
        opf(mpc, A, l, u, mpopt, N, fparm, H, Cw);
    t_ok(success, [t 'success']);
    t_is(f, f_soln, 3, [t 'f']);
    t_is(bus, bus_soln, 3, [t 'bus']);
    t_is(gen, gen_soln, 3, [t 'gen']);
    t_is(branch(:,1:MU_ST), branch_soln, 3, [t 'branch']);
else
    t_skip(5, 'MINOPF not available');
end

%% run fmincon OPF with quadratic gen costs moved to generalized costs
if have_fcn('fmincon')
    t = 'fmincon OPF w/quadratic generalized gen cost : ';
    mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose, 'OPF_ALG', 520);
   [bus, gen, branch, f, success, info, et] = ...
        opf(mpc, A, l, u, mpopt, N, fparm, H, Cw);
    t_ok(success, [t 'success']);
    t_is(f, f_soln, 3, [t 'f']);
    t_is(bus, bus_soln, 3, [t 'bus']);
    t_is(gen, gen_soln, 3, [t 'gen']);
    t_is(branch(:,1:MU_ST), branch_soln, 3, [t 'branch']);
else
    t_skip(5, 'fmincon not available');
end

%%-----  run OPF with extra linear user constraints & costs  -----
%% single new z variable constrained to be greater than or equal to
%% deviation from 1 pu voltage at bus 1, linear cost on this z
%% get solved AC power flow case from MAT-file
load soln9_opf_extras1;   %% defines bus_soln, gen_soln, branch_soln, f_soln
A = sparse([1;1;2;2],[10;25;10;25],[-1;1;1;1],2,25);
u = [Inf; Inf];
l = [-1; 1];

N = sparse(1, 25, 1, 1, 25);    %% new z variable only
fparm = [1 0 0 1];              %% w = r = z
H = sparse(1,1);                %% no quadratic term
Cw = 100;

if have_fcn('minopf')
    t = 'minopf OPF w/extra constraints & costs 1 : ';
    mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose, 'OPF_ALG', 500);
    [bus, gen, branch, f, success] = opf(casefile, A, l, u, mpopt, N, fparm, H, Cw);
    t_ok(success, [t 'success']);
    t_is(f, f_soln, 3, [t 'f']);
    t_is(bus, bus_soln, 3, [t 'bus']);
    t_is(gen, gen_soln, 3, [t 'gen']);
    t_is(branch(:,1:MU_ST), branch_soln, 3, [t 'branch']);
else
    t_skip(5, 'MINOPF not available');
end

if have_fcn('fmincon')
    t = 'fmincon OPF w/extra constraints & costs 1 : ';
    mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose, 'OPF_ALG', 520);
    [bus, gen, branch, f, success] = opf(casefile, A, l, u, mpopt, N, fparm, H, Cw);
    t_ok(success, [t 'success']);
    t_is(f, f_soln, 3, [t 'f']);
    t_is(bus, bus_soln, 3, [t 'bus']);
    t_is(gen, gen_soln, 3, [t 'gen']);
    t_is(branch(:,1:MU_ST), branch_soln, 3, [t 'branch']);
else
    t_skip(5, 'fmincon not available');
end

%%-----  test OPF with capability curves  -----
mpc = loadcase('t_case9_opfv2');
mpc.gen(2:3, [PC1, PC2, QC1MIN, QC1MAX, QC2MIN, QC2MAX]) = ...
        [   0   200 -20 20  -10 10;
            0   200 -30 30  -15 15  ];

%% get solved AC power flow case from MAT-file
load soln9_opf_PQcap;   %% defines bus_soln, gen_soln, branch_soln, f_soln
    
%% run minopf OPF with capability curves
if have_fcn('minopf')
    t = 'minopf OPF w/capability curves : ';
    mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose, 'OPF_ALG', 500);
    [baseMVA, bus, gen, gencost, branch, f, success, et] = runopf(mpc, mpopt);
    t_ok(success, [t 'success']);
    t_is(f, f_soln, 3, [t 'f']);
    t_is(bus, bus_soln, 3, [t 'bus']);
    t_is(gen, gen_soln, 3, [t 'gen']);
    t_is(branch(:,1:MU_ST), branch_soln, 3, [t 'branch']);
else
    t_skip(5, 'MINOPF not available');
end

%% run fmincon OPF with capability curves
if have_fcn('fmincon')
    t = 'fmincon OPF w/capability curves : ';
    mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose, 'OPF_ALG', 520);
    [baseMVA, bus, gen, gencost, branch, f, success, et] = runopf(mpc, mpopt);
    t_ok(success, [t 'success']);
    t_is(f, f_soln, 3, [t 'f']);
    t_is(bus, bus_soln, 3, [t 'bus']);
    t_is(gen, gen_soln, 3, [t 'gen']);
    t_is(branch(:,1:MU_ST), branch_soln, 3, [t 'branch']);
else
    t_skip(5, 'fmincon not available');
end

%%-----  test OPF with angle difference limits  -----
mpc = loadcase('t_case9_opfv2');
mpc.branch(1, ANGMAX) = 2.48;
mpc.branch(9, ANGMIN) = -2;

%% get solved AC power flow case from MAT-file
load soln9_opf_ang;   %% defines bus_soln, gen_soln, branch_soln, f_soln
    
%% run minopf OPF with angle difference limits
if have_fcn('minopf')
    t = 'minopf OPF w/angle difference limits : ';
    mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose, 'OPF_ALG', 500);
    [baseMVA, bus, gen, gencost, branch, f, success, et] = runopf(mpc, mpopt);
    t_ok(success, [t 'success']);
    t_is(f, f_soln, 3, [t 'f']);
    t_is(bus, bus_soln, 3, [t 'bus']);
    t_is(gen, gen_soln, 3, [t 'gen']);
    t_is(branch, branch_soln, 3, [t 'branch']);
else
    t_skip(5, 'MINOPF not available');
end

%% run fmincon OPF with angle difference limits
if have_fcn('fmincon')
    t = 'fmincon OPF w/angle difference limits : ';
    mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose, 'OPF_ALG', 520);
    [baseMVA, bus, gen, gencost, branch, f, success, et] = runopf(mpc, mpopt);
    t_ok(success, [t 'success']);
    t_is(f, f_soln, 3, [t 'f']);
    t_is(bus, bus_soln, 2, [t 'bus']);
    t_is(gen, gen_soln, 3, [t 'gen']);
    t_is(branch, branch_soln, 3, [t 'branch']);
else
    t_skip(5, 'fmincon not available');
end

%%-----  test OPF with ignored angle difference limits  -----
%% get solved AC power flow case from MAT-file
load soln9_opf;   %% defines bus_soln, gen_soln, branch_soln, f_soln
branch_soln(1, ANGMAX) = 2.48;
branch_soln(9, ANGMIN) = -2;

%% run minopf OPF with ignored angle difference limits
if have_fcn('minopf')
    t = 'minopf OPF w/ignored angle difference limits : ';
    mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose, 'OPF_ALG', 500, 'OPF_IGNORE_ANG_LIM', 1);
    [baseMVA, bus, gen, gencost, branch, f, success, et] = runopf(mpc, mpopt);
    t_ok(success, [t 'success']);
    t_is(f, f_soln, 3, [t 'f']);
    t_is(bus, bus_soln, 3, [t 'bus']);
    t_is(gen, gen_soln, 3, [t 'gen']);
    t_is(branch(:,1:MU_ST), branch_soln, 3, [t 'branch']);
else
    t_skip(5, 'MINOPF not available');
end

%% run fmincon OPF with ignored angle difference limits
if have_fcn('fmincon')
    t = 'fmincon OPF w/ignored angle difference limits : ';
    mpopt = mpoption('OUT_ALL', 0, 'VERBOSE', verbose, 'OPF_ALG', 520, 'OPF_IGNORE_ANG_LIM', 1);
    [baseMVA, bus, gen, gencost, branch, f, success, et] = runopf(mpc, mpopt);
    t_ok(success, [t 'success']);
    t_is(f, f_soln, 3, [t 'f']);
    t_is(bus, bus_soln, 2, [t 'bus']);
    t_is(gen, gen_soln, 3, [t 'gen']);
    t_is(branch(:,1:MU_ST), branch_soln, 3, [t 'branch']);
else
    t_skip(5, 'fmincon not available');
end

t_end;

return;
