Home > matpower7.1 > lib > cpf_qlim_event_cb.m

cpf_qlim_event_cb

PURPOSE ^

CPF_QLIM_EVENT_CB Callback to handle QLIM events

SYNOPSIS ^

function [nx, cx, done, rollback, evnts, cb_data, results] = cpf_qlim_event_cb(k, nx, cx, px, done, rollback, evnts, cb_data, cb_args, results)

DESCRIPTION ^

CPF_QLIM_EVENT_CB  Callback to handle QLIM events
   [NX, CX, DONE, ROLLBACK, EVNTS, CB_DATA, RESULTS] =
       CPF_QLIM_EVENT_CB(K, NX, CX, PX, DONE, ROLLBACK, EVNTS, ...
                               CB_DATA, CB_ARGS, RESULTS)

   Callback to handle QLIM (generator reactive power limit violation) events,
   triggered by event function CPF_QLIM_EVENT to indicate the point at which
   an upper or lower reactive power output limit is reached for a generator.

   When a reactive power limit is encountered, this function zeros out
   subsequent transfers from that generator, changes it's bus type to PQ,
   chooses a new reference bus if necessary, and updates the CB_DATA
   accordingly, setting the next step size to zero. The event msg is updated
   with the details of the changes. It also requests termination if no more
   PV or REF buses remain.

   See CPF_DEFAULT_CALLBACK for details of the input and output arguments.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [nx, cx, done, rollback, evnts, cb_data, results] = cpf_qlim_event_cb(...
0002         k, nx, cx, px, done, rollback, evnts, cb_data, cb_args, results)
0003 %CPF_QLIM_EVENT_CB  Callback to handle QLIM events
0004 %   [NX, CX, DONE, ROLLBACK, EVNTS, CB_DATA, RESULTS] =
0005 %       CPF_QLIM_EVENT_CB(K, NX, CX, PX, DONE, ROLLBACK, EVNTS, ...
0006 %                               CB_DATA, CB_ARGS, RESULTS)
0007 %
0008 %   Callback to handle QLIM (generator reactive power limit violation) events,
0009 %   triggered by event function CPF_QLIM_EVENT to indicate the point at which
0010 %   an upper or lower reactive power output limit is reached for a generator.
0011 %
0012 %   When a reactive power limit is encountered, this function zeros out
0013 %   subsequent transfers from that generator, changes it's bus type to PQ,
0014 %   chooses a new reference bus if necessary, and updates the CB_DATA
0015 %   accordingly, setting the next step size to zero. The event msg is updated
0016 %   with the details of the changes. It also requests termination if no more
0017 %   PV or REF buses remain.
0018 %
0019 %   See CPF_DEFAULT_CALLBACK for details of the input and output arguments.
0020 
0021 %   MATPOWER
0022 %   Copyright (c) 2016, Power Systems Engineering Research Center (PSERC)
0023 %   by Ray Zimmerman, PSERC Cornell
0024 %   and Shrirang Abhyankar, Argonne National Laboratory
0025 %
0026 %   This file is part of MATPOWER.
0027 %   Covered by the 3-clause BSD License (see LICENSE file for details).
0028 %   See https://matpower.org for more info.
0029 
0030 %% skip if initialize, finalize or done
0031 if k <= 0 || done.flag
0032     return;
0033 end
0034 
0035 %% define named indices into bus, gen, branch matrices
0036 [PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
0037     VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;
0038 [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...
0039     MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...
0040     QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;
0041 
0042 mpc = [];
0043 
0044 %% handle event
0045 for i = 1:length(evnts)
0046     if strcmp(evnts(i).name, 'QLIM') && evnts(i).zero
0047         %% get updated MPC, if necessary
0048         if isempty(mpc)
0049             d = cb_data;
0050             if length(d.ref) ~= 1
0051                 error('cpf_qlim_event_cb: ''cpf.enforce_qlims'' option only valid for systems with exactly one REF bus')
0052             end
0053             mpc = cpf_current_mpc(d.mpc_base, d.mpc_target, ...
0054                 d.Ybus, d.Yf, d.Yt, d.ref, d.pv, d.pq, nx.V, nx.lam, d.mpopt);
0055             ng = size(mpc.gen, 1);
0056             i2e_bus = mpc.order.bus.i2e;
0057             i2e_gen = mpc.order.gen.i2e;
0058         end
0059 
0060         %% find the generator(s) and which lim(s)
0061         if cb_data.mpopt.verbose > 3
0062             msg = sprintf('%s\n    ', evnts(i).msg);
0063         else
0064             msg = '';
0065         end
0066         ig = evnts(i).idx;
0067         for j = 1:length(ig)
0068             g = ig(j);                  %% index of gen of interest
0069             maxlim = 1;
0070             if g > ng
0071                 g = g - ng;
0072                 maxlim = 0;
0073             end
0074             ib = mpc.gen(g, GEN_BUS);   %% corresponding bus index
0075             if maxlim
0076                 msg = sprintf('%sgen %d @ bus %d reached %g MVAr Qmax lim @ lambda = %.4g : bus %d converted to PQ', ...
0077                     msg, i2e_gen(g), i2e_bus(ib), mpc.gen(g, QMAX), nx.lam, i2e_bus(ib));
0078             else
0079                 msg = sprintf('%sgen %d @ bus %d reached %g MVAr Qmin lim @ lambda = %.4g : bus %d converted to PQ', ...
0080                     msg, i2e_gen(g), i2e_bus(ib), mpc.gen(g, QMIN), nx.lam, i2e_bus(ib));
0081             end
0082 
0083             %% set Qg to exact limit and convert the generator's bus to PQ bus
0084             if maxlim
0085                 mpc.gen(g, QG) = mpc.gen(g, QMAX);
0086             else
0087                 mpc.gen(g, QG) = mpc.gen(g, QMIN);
0088             end
0089             mpc.bus(ib, BUS_TYPE) = PQ;
0090 
0091             %% infeasibility check
0092             on = find(mpc.gen(:, GEN_STATUS) > 0 & ...  %% which generators are on?
0093                       mpc.bus(mpc.gen(:, GEN_BUS), BUS_TYPE) ~= PQ);  %% ... and are not PQ buses
0094 
0095             if isempty(on)
0096                 done.flag = 1;
0097                 done.msg = 'No REF or PV buses remaining.';
0098             else
0099                 oldref = cb_data.ref;   %% save previous ref bus
0100                 [ref, pv, pq] = bustypes(mpc.bus, mpc.gen);
0101                 if oldref ~= ref        %% ref bus changed
0102                     mpc.bus(ref, BUS_TYPE) = REF;
0103                 end
0104 
0105                 %% update new bus types, including in base and target cases
0106                 cb_data.ref = ref;
0107                 cb_data.pv  = pv;
0108                 cb_data.pq  = pq;
0109                 cb_data.mpc_base.bus(  :, BUS_TYPE) = mpc.bus(:, BUS_TYPE);
0110                 cb_data.mpc_target.bus(:, BUS_TYPE) = mpc.bus(:, BUS_TYPE);
0111             
0112                 %% update QG for Q limited gen in base and target
0113                 %% (no more reactive transfer for this gen)
0114                 cb_data.mpc_base.gen(  g, QG) = mpc.gen(g, QG);
0115                 cb_data.mpc_target.gen(g, QG) = mpc.gen(g, QG);
0116 
0117                 %% update PG for previous slack gen in base and target
0118                 %% (no more active transfer for this gen)
0119                 if oldref ~= ref
0120                     cb_data.mpc_base.gen(  g, PG) = mpc.gen(g,PG);
0121                     cb_data.mpc_target.gen(g, PG) = mpc.gen(g,PG);
0122                 end
0123                 
0124                 %% update functions
0125                 b = cb_data.mpc_base;
0126                 t = cb_data.mpc_target;
0127                 cb_data.Sbusb = @(Vm)makeSbus(b.baseMVA, b.bus, b.gen, d.mpopt, Vm);
0128                 cb_data.Sbust = @(Vm)makeSbus(t.baseMVA, t.bus, t.gen, d.mpopt, Vm);
0129                 
0130                 %% set size of next step to zero
0131                 nx.this_step = 0;
0132             end
0133         end
0134         evnts(i).msg = msg;
0135     end
0136 end

Generated on Fri 09-Oct-2020 11:21:31 by m2html © 2005