Home > matpower7.1 > lib > cpf_plim_event_cb.m

cpf_plim_event_cb

PURPOSE ^

CPF_PLIM_EVENT_CB Callback to handle PLIM events

SYNOPSIS ^

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

DESCRIPTION ^

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

   Callback to handle PLIM (generator active power limit violation) events,
   triggered by event function CPF_PLIM_EVENT to indicate the point at which
   an upper active power output limit is reached for a generator.

   When an active power limit is encountered, this function zeros out
   subsequent transfers from that generator, 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 all generators reach PMAX.

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

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