Home > matpower5.0 > toggle_dcline.m

toggle_dcline

PURPOSE ^

TOGGLE_DCLINE Enable, disable or check status of DC line modeling.

SYNOPSIS ^

function mpc = toggle_dcline(mpc, on_off)

DESCRIPTION ^

TOGGLE_DCLINE Enable, disable or check status of DC line modeling.
   MPC = TOGGLE_DCLINE(MPC, 'on')
   MPC = TOGGLE_DCLINE(MPC, 'off')
   T_F = TOGGLE_DCLINE(MPC, 'status')

   Enables, disables or checks the status of a set of OPF userfcn
   callbacks to implement DC lines as a pair of linked generators.
   While it uses the OPF extension mechanism, this implementation
   works for simple power flow as well as OPF problems.

   These callbacks expect to find a 'dcline' field in the input MPC,
   where MPC.dcline is an ndc x 17 matrix with columns as defined
   in IDX_DCLINE, where ndc is the number of DC lines.

   The 'int2ext' callback also packages up flow results and stores them
   in appropriate columns of MPC.dcline.

   NOTE: Because of the way this extension modifies the number of
   rows in the gen and gencost matrices, caution must be taken
   when using it with other extensions that deal with generators.

   Examples:
       mpc = loadcase('t_case9_dcline');
       mpc = toggle_dcline(mpc, 'on');
       results1 = runpf(mpc);
       results2 = runopf(mpc);

   See also IDX_DCLINE, ADD_USERFCN, REMOVE_USERFCN, RUN_USERFCN.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function mpc = toggle_dcline(mpc, on_off)
0002 %TOGGLE_DCLINE Enable, disable or check status of DC line modeling.
0003 %   MPC = TOGGLE_DCLINE(MPC, 'on')
0004 %   MPC = TOGGLE_DCLINE(MPC, 'off')
0005 %   T_F = TOGGLE_DCLINE(MPC, 'status')
0006 %
0007 %   Enables, disables or checks the status of a set of OPF userfcn
0008 %   callbacks to implement DC lines as a pair of linked generators.
0009 %   While it uses the OPF extension mechanism, this implementation
0010 %   works for simple power flow as well as OPF problems.
0011 %
0012 %   These callbacks expect to find a 'dcline' field in the input MPC,
0013 %   where MPC.dcline is an ndc x 17 matrix with columns as defined
0014 %   in IDX_DCLINE, where ndc is the number of DC lines.
0015 %
0016 %   The 'int2ext' callback also packages up flow results and stores them
0017 %   in appropriate columns of MPC.dcline.
0018 %
0019 %   NOTE: Because of the way this extension modifies the number of
0020 %   rows in the gen and gencost matrices, caution must be taken
0021 %   when using it with other extensions that deal with generators.
0022 %
0023 %   Examples:
0024 %       mpc = loadcase('t_case9_dcline');
0025 %       mpc = toggle_dcline(mpc, 'on');
0026 %       results1 = runpf(mpc);
0027 %       results2 = runopf(mpc);
0028 %
0029 %   See also IDX_DCLINE, ADD_USERFCN, REMOVE_USERFCN, RUN_USERFCN.
0030 
0031 %   MATPOWER
0032 %   $Id: toggle_dcline.m 2430 2014-12-02 16:25:08Z ray $
0033 %   by Ray Zimmerman, PSERC Cornell
0034 %   Copyright (c) 2011 by Power System Engineering Research Center (PSERC)
0035 %
0036 %   This file is part of MATPOWER.
0037 %   See http://www.pserc.cornell.edu/matpower/ for more info.
0038 %
0039 %   MATPOWER is free software: you can redistribute it and/or modify
0040 %   it under the terms of the GNU General Public License as published
0041 %   by the Free Software Foundation, either version 3 of the License,
0042 %   or (at your option) any later version.
0043 %
0044 %   MATPOWER is distributed in the hope that it will be useful,
0045 %   but WITHOUT ANY WARRANTY; without even the implied warranty of
0046 %   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0047 %   GNU General Public License for more details.
0048 %
0049 %   You should have received a copy of the GNU General Public License
0050 %   along with MATPOWER. If not, see <http://www.gnu.org/licenses/>.
0051 %
0052 %   Additional permission under GNU GPL version 3 section 7
0053 %
0054 %   If you modify MATPOWER, or any covered work, to interface with
0055 %   other modules (such as MATLAB code and MEX-files) available in a
0056 %   MATLAB(R) or comparable environment containing parts covered
0057 %   under other licensing terms, the licensors of MATPOWER grant
0058 %   you additional permission to convey the resulting work.
0059 
0060 if strcmp(upper(on_off), 'ON')
0061     %% define named indices into data matrices
0062     c = idx_dcline;
0063 
0064     %% check for proper input data
0065     if ~isfield(mpc, 'dcline') || size(mpc.dcline, 2) < c.LOSS1
0066         error('toggle_dcline: case must contain a ''dcline'' field, an ndc x %d matrix.', c.LOSS1);
0067     end
0068     if isfield(mpc, 'dclinecost') && size(mpc.dcline, 1) ~= size(mpc.dclinecost, 1)
0069         error('toggle_dcline: number of rows in ''dcline'' field (%d) and ''dclinecost'' field (%d) do not match.', ...
0070             size(mpc.dcline, 1), size(mpc.dclinecost, 1));
0071     end
0072 %     k = find(mpc.dcline(:, c.LOSS1) < 0);
0073 %     if ~isempty(k)
0074 %         warning('toggle_dcline: linear loss term is negative for DC line from bus %d to %d\n', ...
0075 %             [mpc.dcline(k, c.F_BUS:c.T_BUS)]');
0076 %     end
0077 
0078     %% add callback functions
0079     %% note: assumes all necessary data included in 1st arg (mpc, om, results)
0080     %%       so, no additional explicit args are needed
0081     mpc = add_userfcn(mpc, 'ext2int', @userfcn_dcline_ext2int);
0082     mpc = add_userfcn(mpc, 'formulation', @userfcn_dcline_formulation);
0083     mpc = add_userfcn(mpc, 'int2ext', @userfcn_dcline_int2ext);
0084     mpc = add_userfcn(mpc, 'printpf', @userfcn_dcline_printpf);
0085     mpc = add_userfcn(mpc, 'savecase', @userfcn_dcline_savecase);
0086     mpc.userfcn.status.dcline = 1;
0087 elseif strcmp(upper(on_off), 'OFF')
0088     mpc = remove_userfcn(mpc, 'savecase', @userfcn_dcline_savecase);
0089     mpc = remove_userfcn(mpc, 'printpf', @userfcn_dcline_printpf);
0090     mpc = remove_userfcn(mpc, 'int2ext', @userfcn_dcline_int2ext);
0091     mpc = remove_userfcn(mpc, 'formulation', @userfcn_dcline_formulation);
0092     mpc = remove_userfcn(mpc, 'ext2int', @userfcn_dcline_ext2int);
0093     mpc.userfcn.status.dcline = 0;
0094 elseif strcmp(upper(on_off), 'STATUS')
0095     if isfield(mpc, 'userfcn') && isfield(mpc.userfcn, 'status') && ...
0096             isfield(mpc.userfcn.status, 'dcline')
0097         mpc = mpc.userfcn.status.dcline;
0098     else
0099         mpc = 0;
0100     end
0101 else
0102     error('toggle_dcline: 2nd argument must be ''on'', ''off'' or ''status''');
0103 end
0104 
0105 
0106 %%-----  ext2int  ------------------------------------------------------
0107 function mpc = userfcn_dcline_ext2int(mpc, args)
0108 %
0109 %   mpc = userfcn_dcline_ext2int(mpc, args)
0110 %
0111 %   This is the 'ext2int' stage userfcn callback that prepares the input
0112 %   data for the formulation stage. It expects to find a 'dcline' field
0113 %   in mpc as described above. The optional args are not currently used.
0114 %   It adds two dummy generators for each in-service DC line, with the
0115 %   appropriate upper and lower generation bounds and corresponding
0116 %   entries in gencost. It also expands columns of any A and N matrices
0117 %   accordingly, if present.
0118 
0119 %% define named indices into data matrices
0120 [PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
0121     VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;
0122 [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...
0123     MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...
0124     QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;
0125 [PW_LINEAR, POLYNOMIAL, MODEL, STARTUP, SHUTDOWN, NCOST, COST] = idx_cost;
0126 c = idx_dcline;
0127 
0128 %% initialize some things
0129 if isfield(mpc, 'dclinecost')
0130     havecost = 1;
0131 else
0132     havecost = 0;
0133 end
0134 
0135 %% save version with external indexing
0136 mpc.order.ext.dcline = mpc.dcline;              %% external indexing
0137 if havecost
0138     mpc.order.ext.dclinecost = mpc.dclinecost;  %% external indexing
0139 end
0140 
0141 %% work with only in-service DC lines
0142 mpc.order.dcline.status.on  = find(mpc.dcline(:, c.BR_STATUS) >  0);
0143 mpc.order.dcline.status.off = find(mpc.dcline(:, c.BR_STATUS) <= 0);
0144 
0145 %% remove out-of-service DC lines
0146 dc = mpc.dcline(mpc.order.dcline.status.on, :); %% only in-service DC lines
0147 if havecost
0148     dcc = mpc.dclinecost(mpc.order.dcline.status.on, :);    %% only in-service DC lines
0149     mpc.dclinecost = dcc;
0150 end
0151 ndc = size(dc, 1);          %% number of in-service DC lines
0152 o = mpc.order;
0153 
0154 %%-----  convert stuff to internal indexing  -----
0155 dc(:, c.F_BUS) = o.bus.e2i(dc(:, c.F_BUS));
0156 dc(:, c.T_BUS) = o.bus.e2i(dc(:, c.T_BUS));
0157 mpc.dcline = dc;
0158 
0159 %%-----  create gens to represent DC line terminals  -----
0160 %% ensure consistency of initial values of PF, PT and losses
0161 %% (for simple power flow cases)
0162 dc(:, c.PT) = dc(:, c.PF) - (dc(:, c.LOSS0) + dc(:, c.LOSS1) .* dc(:, c.PF));
0163 
0164 %% create gens
0165 fg = zeros(ndc, size(mpc.gen, 2));
0166 fg(:, MBASE)        = 100;
0167 fg(:, GEN_STATUS)   =  dc(:, c.BR_STATUS);  %% status (should be all 1's)
0168 fg(:, PMIN)         = -Inf;
0169 fg(:, PMAX)         =  Inf;
0170 tg = fg;
0171 fg(:, GEN_BUS)      =  dc(:, c.F_BUS);      %% from bus
0172 tg(:, GEN_BUS)      =  dc(:, c.T_BUS);      %% to bus
0173 fg(:, PG)           = -dc(:, c.PF);         %% flow (extracted at "from")
0174 tg(:, PG)           =  dc(:, c.PT);         %% flow (injected at "to")
0175 fg(:, QG)           =  dc(:, c.QF);         %% VAr injection at "from"
0176 tg(:, QG)           =  dc(:, c.QT);         %% VAr injection at "to"
0177 fg(:, VG)           =  dc(:, c.VF);         %% voltage set-point at "from"
0178 tg(:, VG)           =  dc(:, c.VT);         %% voltage set-point at "to"
0179 k = find(dc(:, c.PMIN) >= 0);           %% min positive direction flow
0180 if ~isempty(k)                              %% contrain at "from" end
0181     fg(k, PMAX)     = -dc(k, c.PMIN);       %% "from" extraction lower lim
0182 end
0183 k = find(dc(:, c.PMAX) >= 0);           %% max positive direction flow
0184 if ~isempty(k)                              %% contrain at "from" end
0185     fg(k, PMIN)     = -dc(k, c.PMAX);       %% "from" extraction upper lim
0186 end
0187 k = find(dc(:, c.PMIN) < 0);            %% max negative direction flow
0188 if ~isempty(k)                              %% contrain at "to" end
0189     tg(k, PMIN)     =  dc(k, c.PMIN);       %% "to" injection lower lim
0190 end
0191 k = find(dc(:, c.PMAX) < 0);            %% min negative direction flow
0192 if ~isempty(k)                              %% contrain at "to" end
0193     tg(k, PMAX)     =  dc(k, c.PMAX);       %% "to" injection upper lim
0194 end
0195 fg(:, QMIN)         =  dc(:, c.QMINF);      %% "from" VAr injection lower lim
0196 fg(:, QMAX)         =  dc(:, c.QMAXF);      %% "from" VAr injection upper lim
0197 tg(:, QMIN)         =  dc(:, c.QMINT);      %%  "to"  VAr injection lower lim
0198 tg(:, QMAX)         =  dc(:, c.QMAXT);      %%  "to"  VAr injection upper lim
0199 
0200 %% fudge PMAX a bit if necessary to avoid triggering
0201 %% dispatchable load constant power factor constraints
0202 fg(isload(fg), PMAX) = -1e-6;
0203 tg(isload(tg), PMAX) = -1e-6;
0204 
0205 %% set all terminal buses to PV (except ref bus)
0206 refbus = find(mpc.bus(:, BUS_TYPE) == REF);
0207 mpc.bus(dc(:, c.F_BUS), BUS_TYPE) = PV;
0208 mpc.bus(dc(:, c.T_BUS), BUS_TYPE) = PV;
0209 mpc.bus(refbus, BUS_TYPE) = REF;
0210 
0211 %% expand A and N, if present
0212 nb = size(mpc.bus, 1);
0213 ng = size(mpc.gen, 1);
0214 if isfield(mpc, 'A') && ~isempty(mpc.A)
0215     [mA, nA] = size(mpc.A);
0216     if nA >= 2*nb + 2*ng    %% assume AC dimensions
0217         mpc.A = [   mpc.A(:, 1:2*nb+ng)      sparse(mA, 2*ndc) ...
0218                     mpc.A(:, 2*nb+ng+(1:ng)) sparse(mA, 2*ndc) ...
0219                     mpc.A(:, (2*nb+2*ng+1:nA)) ];
0220     else                    %% assume DC dimensions
0221         mpc.A = [   mpc.A(:, 1:nb+ng)   sparse(mA, 2*ndc) ...
0222                     mpc.A(:, (nb+ng+1:nA)) ];
0223     end
0224 end
0225 if isfield(mpc, 'N') && ~isempty(mpc.N)
0226     [mN, nN] = size(mpc.N);
0227     if nN >= 2*nb + 2*ng    %% assume AC dimensions
0228         mpc.N = [   mpc.N(:, 1:2*nb+ng)      sparse(mN, 2*ndc) ...
0229                     mpc.N(:, 2*nb+ng+(1:ng)) sparse(mN, 2*ndc) ...
0230                     mpc.N(:, (2*nb+2*ng+1:nN)) ];
0231     else                    %% assume DC dimensions
0232         mpc.N = [   mpc.N(:, 1:nb+ng)   sparse(mN, 2*ndc) ...
0233                     mpc.N(:, (nb+ng+1:nN)) ];
0234     end
0235 end
0236 
0237 %% append dummy gens
0238 mpc.gen = [mpc.gen; fg; tg];
0239 
0240 %% gencost
0241 if isfield(mpc, 'gencost') && ~isempty(mpc.gencost)
0242     [ngcr, ngcc] = size(mpc.gencost);   %% dimensions of gencost
0243     if havecost         %% user has provided costs
0244         ndccc = size(dcc, 2);           %% number of dclinecost columns
0245         ccc = max([ngcc; ndccc]);       %% number of columns in new gencost
0246         if ccc > ngcc                   %% right zero-pad gencost
0247             mpc.gencost = [mpc.gencost zeros(ngcr, ccc-ngcc)];
0248         end
0249 
0250         %% flip function across vertical axis and append to gencost
0251         %% (PF for DC line = -PG for dummy gen at "from" bus)
0252         for k = 1:ndc
0253             if dcc(k, MODEL) == POLYNOMIAL
0254                 nc = dcc(k, NCOST);
0255                 temp = dcc(k, NCOST+(1:nc));
0256                 %% flip sign on coefficients of odd terms
0257                 %% (every other starting with linear term,
0258                 %%  that is, the next to last one)
0259                 temp((nc-1):-2:1) = -temp((nc-1):-2:1);
0260             else  %% dcc(k, MODEL) == PW_LINEAR
0261                 nc = dcc(k, NCOST);
0262                 temp = dcc(k, NCOST+(1:2*nc));
0263                 %% switch sign on horizontal coordinate
0264                 xx = -temp(1:2:2*nc);
0265                 yy =  temp(2:2:2*nc);
0266                 temp(1:2:2*nc) = xx(end:-1:1);
0267                 temp(2:2:2*nc) = yy(end:-1:1);
0268             end
0269             padding = zeros(1, ccc-NCOST-length(temp));
0270             gck = [dcc(k, 1:NCOST) temp padding];
0271             
0272             %% append to gencost
0273             mpc.gencost = [mpc.gencost; gck];
0274         end
0275         %% use zero cost on "to" end gen
0276         tgc = ones(ndc, 1) * [2 0 0 2 zeros(1, ccc-4)];
0277         mpc.gencost = [mpc.gencost; tgc];        
0278     else
0279         %% use zero cost as default
0280         dcgc = ones(2*ndc, 1) * [2 0 0 2 zeros(1, ngcc-4)];
0281         mpc.gencost = [mpc.gencost; dcgc];
0282     end
0283 end
0284 
0285 
0286 %%-----  formulation  --------------------------------------------------
0287 function om = userfcn_dcline_formulation(om, args)
0288 %
0289 %   om = userfcn_dcline_formulation(om, args)
0290 %
0291 %   This is the 'formulation' stage userfcn callback that defines the
0292 %   user constraints for the dummy generators representing DC lines.
0293 %   It expects to find a 'dcline' field in the mpc stored in om, as
0294 %   described above. By the time it is passed to this callback,
0295 %   MPC.dcline should contain only in-service lines and the from and
0296 %   two bus columns should be converted to internal indexing. The
0297 %   optional args are not currently used.
0298 %
0299 %   If Pf, Pt and Ploss are the flow at the "from" end, flow at the
0300 %   "to" end and loss respectively, and L0 and L1 are the linear loss
0301 %   coefficients, the the relationships between them is given by:
0302 %       Pf - Ploss = Pt
0303 %       Ploss = L0 + L1 * Pf
0304 %   If Pgf and Pgt represent the injections of the dummy generators
0305 %   representing the DC line injections into the network, then
0306 %   Pgf = -Pf and Pgt = Pt, and we can combine all of the above to
0307 %   get the following constraint on Pgf ang Pgt:
0308 %       -Pgf - (L0 - L1 * Pgf) = Pgt
0309 %   which can be written:
0310 %       -L0 <= (1 - L1) * Pgf + Pgt <= -L0
0311 
0312 %% define named indices into data matrices
0313 c = idx_dcline;
0314 
0315 %% initialize some things
0316 mpc = get_mpc(om);
0317 dc = mpc.dcline;
0318 ndc = size(dc, 1);              %% number of in-service DC lines
0319 ng  = size(mpc.gen, 1) - 2*ndc; %% number of original gens/disp loads
0320 
0321 %% constraints
0322 nL0 = -dc(:, c.LOSS0) / mpc.baseMVA;
0323 L1  =  dc(:, c.LOSS1);
0324 Adc = [sparse(ndc, ng) spdiags(1-L1, 0, ndc, ndc) speye(ndc, ndc)];
0325 
0326 %% add them to the model
0327 om = add_constraints(om, 'dcline', Adc, nL0, nL0, {'Pg'});
0328 
0329 
0330 %%-----  int2ext  ------------------------------------------------------
0331 function results = userfcn_dcline_int2ext(results, args)
0332 %
0333 %   results = userfcn_dcline_int2ext(results, args)
0334 %
0335 %   This is the 'int2ext' stage userfcn callback that converts everything
0336 %   back to external indexing and packages up the results. It expects to
0337 %   find a 'dcline' field in the results struct as described for mpc
0338 %   above. It also expects that the last 2*ndc entries in the gen and
0339 %   gencost matrices correspond to the in-service DC lines (where ndc is
0340 %   the number of rows in MPC.dcline. These extra rows are removed from
0341 %   gen and gencost and the flow is taken from the PG of these gens and
0342 %   placed in the flow column of the appropiate dcline row. Corresponding
0343 %   columns are also removed from any A and N matrices, if present. The
0344 %   optional args are not currently used.
0345 
0346 %% define named indices into data matrices
0347 [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...
0348     MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...
0349     QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;
0350 c = idx_dcline;
0351 
0352 %% initialize some things
0353 o = results.order;
0354 k = find(o.ext.dcline(:, c.BR_STATUS));
0355 ndc = length(k);                    %% number of in-service DC lines
0356 ng  = size(results.gen, 1) - 2*ndc; %% number of original gens/disp loads
0357 nb  = size(results.bus, 1);
0358 
0359 %% extract dummy gens
0360 fg = results.gen(ng    +(1:ndc), :);
0361 tg = results.gen(ng+ndc+(1:ndc), :);
0362 
0363 %% remove dummy gens
0364 results.gen     = results.gen(1:ng, :);
0365 if isfield(results, 'gencost') && ~isempty(results.gencost)
0366     results.gencost = results.gencost(1:ng, :);
0367 end
0368 
0369 %% delete corresponding columns from A and N, if present
0370 if isfield(results, 'A') && ~isempty(results.A)
0371     [mA, nA] = size(results.A);
0372     if nA >= 2*nb + 2*ng + 4*ndc    %% assume AC dimensions
0373         results.A = results.A(:, [1:2*nb+ng 2*nb+ng+2*ndc+(1:ng) 2*nb+2*ng+4*ndc+1:nA]);
0374     else                            %% assume DC dimensions
0375         results.A = results.A(:, [1:nb+ng nb+ng+2*ndc+1:nA]);
0376     end
0377 end
0378 if isfield(results, 'N') && ~isempty(results.N)
0379     [mN, nN] = size(results.N);
0380     if nN >= 2*nb + 2*ng + 4*ndc    %% assume AC dimensions
0381         results.N = results.N(:, [1:2*nb+ng 2*nb+ng+2*ndc+(1:ng) 2*nb+2*ng+4*ndc+1:nN]);
0382     else                            %% assume DC dimensions
0383         results.N = results.N(:, [1:nb+ng nb+ng+2*ndc+1:nN]);
0384     end
0385 end
0386 
0387 %% get the solved flows
0388 results.dcline(:, c.PF) = -fg(:, PG);
0389 results.dcline(:, c.PT) =  tg(:, PG);
0390 results.dcline(:, c.QF) =  fg(:, QG);
0391 results.dcline(:, c.QT) =  tg(:, QG);
0392 results.dcline(:, c.VF) =  fg(:, VG);
0393 results.dcline(:, c.VT) =  tg(:, VG);
0394 if size(fg, 2) >= MU_QMIN
0395     results.dcline(:, c.MU_PMIN ) = fg(:, MU_PMAX) + tg(:, MU_PMIN);
0396     results.dcline(:, c.MU_PMAX ) = fg(:, MU_PMIN) + tg(:, MU_PMAX);
0397     results.dcline(:, c.MU_QMINF) = fg(:, MU_QMIN);
0398     results.dcline(:, c.MU_QMAXF) = fg(:, MU_QMAX);
0399     results.dcline(:, c.MU_QMINT) = tg(:, MU_QMIN);
0400     results.dcline(:, c.MU_QMAXT) = tg(:, MU_QMAX);
0401 end
0402 
0403 %%-----  convert stuff back to external indexing  -----
0404 results.order.int.dcline = results.dcline;  %% save internal version
0405 %% copy results to external version
0406 o.ext.dcline(k, c.PF:c.VT) = results.dcline(:, c.PF:c.VT);
0407 if size(results.dcline, 2) == c.MU_QMAXT
0408     o.ext.dcline(k, c.MU_PMIN:c.MU_QMAXT) = results.dcline(:, c.MU_PMIN:c.MU_QMAXT);
0409 end
0410 results.dcline = o.ext.dcline;              %% use external version
0411 
0412 
0413 %%-----  printpf  ------------------------------------------------------
0414 function results = userfcn_dcline_printpf(results, fd, mpopt, args)
0415 %
0416 %   results = userfcn_dcline_printpf(results, fd, mpopt, args)
0417 %
0418 %   This is the 'printpf' stage userfcn callback that pretty-prints the
0419 %   results. It expects a results struct, a file descriptor and a MATPOWER
0420 %   options struct. The optional args are not currently used.
0421 
0422 %% define named indices into data matrices
0423 c = idx_dcline;
0424 
0425 %% options
0426 SUPPRESS        = mpopt.out.suppress_detail;
0427 if SUPPRESS == -1
0428     if size(bus, 1) > 500
0429         SUPPRESS = 1;
0430     else
0431         SUPPRESS = 0;
0432     end
0433 end
0434 OUT_ALL = mpopt.out.all;
0435 OUT_BRANCH      = OUT_ALL == 1 || (OUT_ALL == -1 && ~SUPPRESS && mpopt.out.branch);
0436 if OUT_ALL == -1
0437     OUT_ALL_LIM = ~SUPPRESS * mpopt.out.lim.all;
0438 elseif OUT_ALL == 1
0439     OUT_ALL_LIM = 2;
0440 else
0441     OUT_ALL_LIM = 0;
0442 end
0443 if OUT_ALL_LIM == -1
0444     OUT_LINE_LIM    = ~SUPPRESS * mpopt.out.lim.line;
0445 else
0446     OUT_LINE_LIM    = OUT_ALL_LIM;
0447 end
0448 ctol = mpopt.opf.violation; %% constraint violation tolerance
0449 ptol = 1e-4;                %% tolerance for displaying shadow prices
0450 
0451 %%-----  print results  -----
0452 dc = results.dcline;
0453 ndc = size(dc, 1);
0454 kk = find(dc(:, c.BR_STATUS) ~= 0);
0455 if OUT_BRANCH
0456     fprintf(fd, '\n================================================================================');
0457     fprintf(fd, '\n|     DC Line Data                                                             |');
0458     fprintf(fd, '\n================================================================================');
0459     fprintf(fd, '\n Line    From     To        Power Flow           Loss     Reactive Inj (MVAr)');
0460     fprintf(fd, '\n   #      Bus     Bus   From (MW)   To (MW)      (MW)       From        To   ');
0461     fprintf(fd, '\n------  ------  ------  ---------  ---------  ---------  ---------  ---------');
0462     loss = 0;
0463     for k = 1:ndc
0464         if dc(k, c.BR_STATUS)   %% status on
0465             fprintf(fd, '\n%5d%8d%8d%11.2f%11.2f%11.2f%11.2f%11.2f', ...
0466                         k, dc(k, c.F_BUS:c.T_BUS), dc(k, c.PF:c.PT), ...
0467                         dc(k, c.PF) - dc(k, c.PT), dc(k, c.QF:c.QT) );
0468             loss = loss + dc(k, c.PF) - dc(k, c.PT);
0469         else
0470             fprintf(fd, '\n%5d%8d%8d%11s%11s%11s%11s%11s', ...
0471                         k, dc(k, c.F_BUS:c.T_BUS), '-  ', '-  ', '-  ', '-  ', '-  ');
0472         end
0473     end
0474     fprintf(fd, '\n                                              ---------');
0475     fprintf(fd, '\n                                     Total:%11.2f\n', loss);
0476 end
0477 
0478 if OUT_LINE_LIM == 2 || (OUT_LINE_LIM == 1 && ...
0479         (any(dc(kk, c.PF) > dc(kk, c.PMAX) - ctol) || ...
0480          any(dc(kk, c.MU_PMIN) > ptol) || ...
0481          any(dc(kk, c.MU_PMAX) > ptol)))
0482     fprintf(fd, '\n================================================================================');
0483     fprintf(fd, '\n|     DC Line Constraints                                                      |');
0484     fprintf(fd, '\n================================================================================');
0485     fprintf(fd, '\n Line    From     To          Minimum        Actual Flow       Maximum');
0486     fprintf(fd, '\n   #      Bus     Bus    Pmin mu     Pmin       (MW)       Pmax      Pmax mu ');
0487     fprintf(fd, '\n------  ------  ------  ---------  ---------  ---------  ---------  ---------');
0488     for k = 1:ndc
0489         if OUT_LINE_LIM == 2 || (OUT_LINE_LIM == 1 && ...
0490                 (dc(k, c.PF) > dc(k, c.PMAX) - ctol || ...
0491                  dc(k, c.MU_PMIN) > ptol || ...
0492                  dc(k, c.MU_PMAX) > ptol))
0493             if dc(k, c.BR_STATUS)   %% status on
0494                 fprintf(fd, '\n%5d%8d%8d', k, dc(k, c.F_BUS:c.T_BUS) );
0495                 if dc(k, c.MU_PMIN) > ptol
0496                     fprintf(fd, '%11.3f', dc(k, c.MU_PMIN) );
0497                 else
0498                     fprintf(fd, '%11s', '-  ' );
0499                 end
0500                 fprintf(fd, '%11.2f%11.2f%11.2f', ...
0501                             dc(k, c.PMIN), dc(k, c.PF), dc(k, c.PMAX) );
0502                 if dc(k, c.MU_PMAX) > ptol
0503                     fprintf(fd, '%11.3f', dc(k, c.MU_PMAX) );
0504                 else
0505                     fprintf(fd, '%11s', '-  ' );
0506                 end
0507             else
0508                 fprintf(fd, '\n%5d%8d%8d%11s%11s%11s%11s%11s', ...
0509                             k, dc(k, c.F_BUS:c.T_BUS), '-  ', '-  ', '-  ', '-  ', '-  ');
0510             end
0511         end
0512     end
0513     fprintf(fd, '\n');
0514 end
0515 
0516 
0517 %%-----  savecase  -----------------------------------------------------
0518 function mpc = userfcn_dcline_savecase(mpc, fd, prefix, args)
0519 %
0520 %   mpc = userfcn_dcline_savecase(mpc, fd, mpopt, args)
0521 %
0522 %   This is the 'savecase' stage userfcn callback that prints the M-file
0523 %   code to save the 'dcline' field in the case file. It expects a
0524 %   MATPOWER case struct (mpc), a file descriptor and variable prefix
0525 %   (usually 'mpc.'). The optional args are not currently used.
0526 
0527 %% define named indices into data matrices
0528 c = idx_dcline;
0529 
0530 %% save it
0531 ncols = size(mpc.dcline, 2);
0532 fprintf(fd, '\n%%%%-----  DC Line Data  -----%%%%\n');
0533 if ncols < c.MU_QMAXT
0534     fprintf(fd, '%%\tfbus\ttbus\tstatus\tPf\tPt\tQf\tQt\tVf\tVt\tPmin\tPmax\tQminF\tQmaxF\tQminT\tQmaxT\tloss0\tloss1\n');
0535 else
0536     fprintf(fd, '%%\tfbus\ttbus\tstatus\tPf\tPt\tQf\tQt\tVf\tVt\tPmin\tPmax\tQminF\tQmaxF\tQminT\tQmaxT\tloss0\tloss1\tmuPmin\tmuPmax\tmuQminF\tmuQmaxF\tmuQminT\tmuQmaxT\n');
0537 end
0538 template = '\t%d\t%d\t%d\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g';
0539 if ncols == c.MU_QMAXT
0540     template = [template, '\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f'];
0541 end
0542 template = [template, ';\n'];
0543 fprintf(fd, '%sdcline = [\n', prefix);
0544 fprintf(fd, template, mpc.dcline.');
0545 fprintf(fd, '];\n');
0546 
0547 %% to do, make it save mpc.dclinecost too (somehow I forgot this)
0548 %% have a look at the saving of gencost in savecase for template

Generated on Mon 26-Jan-2015 15:21:31 by m2html © 2005