Home > matpower7.1 > lib > cpf_default_callback.m

cpf_default_callback

PURPOSE ^

CPF_DEFAULT_CALLBACK Default callback function for CPF

SYNOPSIS ^

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

DESCRIPTION ^

CPF_DEFAULT_CALLBACK   Default callback function for CPF
   [NX, CX, DONE, ROLLBACK, EVNTS, CB_DATA, RESULTS] = 
       CPF_DEFAULT_CALLBACK(K, NX, CX, PX, DONE, ROLLBACK, EVNTS, ...
                               CB_DATA, CB_ARGS, RESULTS)

   Default callback function used by RUNCPF that collects the resulst and
   optionally, plots the nose curve. Inputs and outputs are defined below,
   with the RESULTS argument being optional, used only for the final call
   when K is negative.

   Inputs:
       K - continuation step iteration count
       NX - next state (corresponding to proposed next step), struct with
            the following fields:
           lam_hat - value of LAMBDA from predictor
           V_hat - vector of complex bus voltages from predictor
           lam - value of LAMBDA from corrector
           V - vector of complex bus voltages from corrector
           z - normalized tangent predictor
           default_step - default step size
           default_parm - default parameterization
           this_step - step size for this step only
           this_parm - paramterization for this step only
           step - current step size
           parm - current parameterization
           events - struct array, event log
           cb - user state, for callbacks (replaces CB_STATE), the user may
               add fields containing any information the callback function
               would like to pass from one invokation to the next, taking
               care not to step on fields being used by other callbacks,
               such as the 'default' field used by this default callback
           ef - cell array of event function values
       CX - current state (corresponding to most recent successful step)
            (same structure as NX)
       PX - previous state (corresponding to last successful step prior to CX)
       DONE - struct, with flag to indicate CPF termination and reason,
           with fields:
           flag - termination flag, 1 => terminate, 0 => continue
           msg - string containing reason for termination
       ROLLBACK - scalar flag to indicate that the current step should be
           rolled back and retried with a different step size, etc.
       EVNTS - struct array listing any events detected for this step,
           see CPF_DETECT_EVENTS for details
       CB_DATA - struct containing potentially useful "static" data,
           with the following fields (all based on internal indexing):
           mpc_base - MATPOWER case struct of base state
           mpc_target - MATPOWER case struct of target state
           Sbusb - handle of function returning nb x 1 vector of complex
               base case injections in p.u. and derivatives w.r.t. |V|
           Sbust - handle of function returning nb x 1 vector of complex
               target case injections in p.u. and derivatives w.r.t. |V|
           Ybus - bus admittance matrix
           Yf - branch admittance matrix, "from" end of branches
           Yt - branch admittance matrix, "to" end of branches
           pv - vector of indices of PV buses
           pq - vector of indices of PQ buses
           ref - vector of indices of REF buses
           idx_pmax - vector of generator indices for generators fixed
               at their PMAX limits
           mpopt - MATPOWER options struct
       CB_ARGS - arbitrary data structure containing callback arguments
       RESULTS - initial value of output struct to be assigned to
           CPF field of results struct returned by RUNCPF

   Outputs:
       (all are updated versions of the corresponding input arguments)
       NX - user state ('cb' field ) should be updated here if ROLLBACK
           is false
       CX - may contain updated 'this_step' or 'this_parm' values to be used
           if ROLLBACK is true
       DONE - callback may have requested termination and set the msg field
       ROLLBACK - callback can request a rollback step, even if it was not
           indicated by an event function
       EVNTS - msg field for a given event may be updated
       CB_DATA - this data should only be modified if the underlying problem
           has been changed (e.g. generator limit reached) and should always
           be followed by a step of zero length, i.e. set NX.this_step to 0
           It is the job of any callback modifying CB_DATA to ensure that
           all data in CB_DATA is kept consistent.
       RESULTS - updated version of RESULTS input arg

   This function is called in three different contexts, distinguished by
   the value of K, as follows:
   (1) initial - called with K = 0, without RESULTS input/output args,
           after base power flow, before 1st CPF step.
   (2) iterations - called with K > 0, without RESULTS input/output args,
           at each iteration, after predictor-corrector step
   (3) final - called with K < 0, with RESULTS input/output args, after
           exiting predictor-corrector loop, inputs identical to last
           iteration call, except K which is negated

   User Defined CPF Callback Functions:
       The user can define their own callback functions which take
       the same form and are called in the same contexts as
       CPF_DEFAULT_CALLBACK. These are specified via the MATPOWER
       option 'cpf.user_callback'. This option can be a string containing
       the name of the callback function, or a struct with the following
       fields, where all but the first are optional:
           'fcn'       - string with name of callback function
           'priority'  - numerical value specifying callback priority
                (default = 20, see CPF_REGISTER_CALLBACK for details)
           'args'      - arbitrary value (any type) passed to the callback
                         as CB_ARGS each time it is invoked
       Multiple user callbacks can be registered by assigning a cell array
       of such strings and/or structs to the 'cpf.user_callback' option.

   See also RUNCPF, CPF_REGISTER_CALLBACK.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [nx, cx, done, rollback, evnts, cb_data, results] = ...
0002     cpf_default_callback(k, nx, cx, px, done, rollback, evnts, ...
0003                             cb_data, cb_args, results)
0004 %CPF_DEFAULT_CALLBACK   Default callback function for CPF
0005 %   [NX, CX, DONE, ROLLBACK, EVNTS, CB_DATA, RESULTS] =
0006 %       CPF_DEFAULT_CALLBACK(K, NX, CX, PX, DONE, ROLLBACK, EVNTS, ...
0007 %                               CB_DATA, CB_ARGS, RESULTS)
0008 %
0009 %   Default callback function used by RUNCPF that collects the resulst and
0010 %   optionally, plots the nose curve. Inputs and outputs are defined below,
0011 %   with the RESULTS argument being optional, used only for the final call
0012 %   when K is negative.
0013 %
0014 %   Inputs:
0015 %       K - continuation step iteration count
0016 %       NX - next state (corresponding to proposed next step), struct with
0017 %            the following fields:
0018 %           lam_hat - value of LAMBDA from predictor
0019 %           V_hat - vector of complex bus voltages from predictor
0020 %           lam - value of LAMBDA from corrector
0021 %           V - vector of complex bus voltages from corrector
0022 %           z - normalized tangent predictor
0023 %           default_step - default step size
0024 %           default_parm - default parameterization
0025 %           this_step - step size for this step only
0026 %           this_parm - paramterization for this step only
0027 %           step - current step size
0028 %           parm - current parameterization
0029 %           events - struct array, event log
0030 %           cb - user state, for callbacks (replaces CB_STATE), the user may
0031 %               add fields containing any information the callback function
0032 %               would like to pass from one invokation to the next, taking
0033 %               care not to step on fields being used by other callbacks,
0034 %               such as the 'default' field used by this default callback
0035 %           ef - cell array of event function values
0036 %       CX - current state (corresponding to most recent successful step)
0037 %            (same structure as NX)
0038 %       PX - previous state (corresponding to last successful step prior to CX)
0039 %       DONE - struct, with flag to indicate CPF termination and reason,
0040 %           with fields:
0041 %           flag - termination flag, 1 => terminate, 0 => continue
0042 %           msg - string containing reason for termination
0043 %       ROLLBACK - scalar flag to indicate that the current step should be
0044 %           rolled back and retried with a different step size, etc.
0045 %       EVNTS - struct array listing any events detected for this step,
0046 %           see CPF_DETECT_EVENTS for details
0047 %       CB_DATA - struct containing potentially useful "static" data,
0048 %           with the following fields (all based on internal indexing):
0049 %           mpc_base - MATPOWER case struct of base state
0050 %           mpc_target - MATPOWER case struct of target state
0051 %           Sbusb - handle of function returning nb x 1 vector of complex
0052 %               base case injections in p.u. and derivatives w.r.t. |V|
0053 %           Sbust - handle of function returning nb x 1 vector of complex
0054 %               target case injections in p.u. and derivatives w.r.t. |V|
0055 %           Ybus - bus admittance matrix
0056 %           Yf - branch admittance matrix, "from" end of branches
0057 %           Yt - branch admittance matrix, "to" end of branches
0058 %           pv - vector of indices of PV buses
0059 %           pq - vector of indices of PQ buses
0060 %           ref - vector of indices of REF buses
0061 %           idx_pmax - vector of generator indices for generators fixed
0062 %               at their PMAX limits
0063 %           mpopt - MATPOWER options struct
0064 %       CB_ARGS - arbitrary data structure containing callback arguments
0065 %       RESULTS - initial value of output struct to be assigned to
0066 %           CPF field of results struct returned by RUNCPF
0067 %
0068 %   Outputs:
0069 %       (all are updated versions of the corresponding input arguments)
0070 %       NX - user state ('cb' field ) should be updated here if ROLLBACK
0071 %           is false
0072 %       CX - may contain updated 'this_step' or 'this_parm' values to be used
0073 %           if ROLLBACK is true
0074 %       DONE - callback may have requested termination and set the msg field
0075 %       ROLLBACK - callback can request a rollback step, even if it was not
0076 %           indicated by an event function
0077 %       EVNTS - msg field for a given event may be updated
0078 %       CB_DATA - this data should only be modified if the underlying problem
0079 %           has been changed (e.g. generator limit reached) and should always
0080 %           be followed by a step of zero length, i.e. set NX.this_step to 0
0081 %           It is the job of any callback modifying CB_DATA to ensure that
0082 %           all data in CB_DATA is kept consistent.
0083 %       RESULTS - updated version of RESULTS input arg
0084 %
0085 %   This function is called in three different contexts, distinguished by
0086 %   the value of K, as follows:
0087 %   (1) initial - called with K = 0, without RESULTS input/output args,
0088 %           after base power flow, before 1st CPF step.
0089 %   (2) iterations - called with K > 0, without RESULTS input/output args,
0090 %           at each iteration, after predictor-corrector step
0091 %   (3) final - called with K < 0, with RESULTS input/output args, after
0092 %           exiting predictor-corrector loop, inputs identical to last
0093 %           iteration call, except K which is negated
0094 %
0095 %   User Defined CPF Callback Functions:
0096 %       The user can define their own callback functions which take
0097 %       the same form and are called in the same contexts as
0098 %       CPF_DEFAULT_CALLBACK. These are specified via the MATPOWER
0099 %       option 'cpf.user_callback'. This option can be a string containing
0100 %       the name of the callback function, or a struct with the following
0101 %       fields, where all but the first are optional:
0102 %           'fcn'       - string with name of callback function
0103 %           'priority'  - numerical value specifying callback priority
0104 %                (default = 20, see CPF_REGISTER_CALLBACK for details)
0105 %           'args'      - arbitrary value (any type) passed to the callback
0106 %                         as CB_ARGS each time it is invoked
0107 %       Multiple user callbacks can be registered by assigning a cell array
0108 %       of such strings and/or structs to the 'cpf.user_callback' option.
0109 %
0110 %   See also RUNCPF, CPF_REGISTER_CALLBACK.
0111 
0112 %   MATPOWER
0113 %   Copyright (c) 2013-2016, Power Systems Engineering Research Center (PSERC)
0114 %   by Ray Zimmerman, PSERC Cornell
0115 %
0116 %   This file is part of MATPOWER.
0117 %   Covered by the 3-clause BSD License (see LICENSE file for details).
0118 %   See https://matpower.org for more info.
0119 
0120 %% skip if rollback, except if it is a FINAL call
0121 if rollback && k > 0
0122     return;
0123 end
0124 
0125 %% initialize variables
0126 step    = nx.step;
0127 V       = nx.V;
0128 lam     = nx.lam;
0129 V_hat   = nx.V_hat;
0130 lam_hat = nx.lam_hat;
0131 
0132 %%-----  initialize/update state/results  -----
0133 if k == 0       %% INITIAL call
0134     %% initialize state
0135     cxx = struct(   'V_hat',    V_hat, ...
0136                     'lam_hat',  lam_hat, ...
0137                     'V',        V, ...
0138                     'lam',      lam, ...
0139                     'steps',    step, ...
0140                     'iterations', 0     );
0141     nxx = cxx;
0142     cx.cb.default = cxx;    %% update current callback state
0143     nx.cb.default = nxx;    %% updatenext callback state
0144 else
0145     nxx = nx.cb.default;    %% get next callback state
0146     if k > 0    %% ITERATION call
0147         %% update state
0148         nxx.V_hat   = [nxx.V_hat    V_hat];
0149         nxx.lam_hat = [nxx.lam_hat  lam_hat];
0150         nxx.V       = [nxx.V        V];
0151         nxx.lam     = [nxx.lam      lam];
0152         nxx.steps   = [nxx.steps    step];
0153         nxx.iterations = k;
0154         nx.cb.default = nxx;    %% update next callback state
0155     else            %% FINAL call
0156         %% assemble results struct
0157         results.V_hat       = nxx.V_hat;
0158         results.lam_hat     = nxx.lam_hat;
0159         results.V           = nxx.V;
0160         results.lam         = nxx.lam;
0161         results.steps       = nxx.steps;
0162         results.iterations  = -k;
0163         results.max_lam     = max(nxx.lam);
0164     end
0165 end
0166 
0167 %%-----  plot continuation curve  -----
0168 %% initialize plotting options
0169 plot_level  = cb_data.mpopt.cpf.plot.level;
0170 plot_bus    = cb_data.mpopt.cpf.plot.bus;
0171 plot_bus_default = 0;
0172 if plot_level
0173     if isempty(plot_bus) && ~isfield(nxx, 'plot_bus_default')   %% no bus specified
0174         %% pick PQ bus with largest transfer
0175         Sxfr = cb_data.Sbust(abs(V)) - cb_data.Sbusb(abs(V));
0176         [junk, idx] = max(Sxfr(cb_data.pq));
0177         if isempty(idx) %% or bus 1 if there are none
0178             idx = 1;
0179         else
0180             idx = cb_data.pq(idx(1));
0181         end
0182         idx_e = cb_data.mpc_target.order.bus.i2e(idx);
0183         
0184         %% save it to keep it from changing in subsequent calls
0185         plot_bus_default = idx_e;
0186     else
0187         if isempty(plot_bus)
0188             idx_e = nxx.plot_bus_default;   %% external bus number, saved
0189         else
0190             idx_e = plot_bus;               %% external bus number, provided
0191         end
0192         if any(idx_e > length(cb_data.mpc_target.order.bus.e2i))
0193             kk = find(idx_e > length(cb_data.mpc_target.order.bus.e2i));
0194             error('cpf_default_callback: %d is not a valid bus number for MPOPT.cpf.plot.bus', idx_e(kk(1)));
0195         end
0196         idx = full(cb_data.mpc_target.order.bus.e2i(idx_e));
0197         if any(idx == 0)
0198             kk = find(idx == 0);
0199             error('cpf_default_callback: %d is not a valid bus number for MPOPT.cpf.plot.bus', idx_e(kk(1)));
0200         end
0201     end
0202     nplots = length(idx_e);
0203 
0204     %% set bounds for plot axes
0205     xmin = 0;
0206     xmax = max([max(nxx.lam_hat); max(nxx.lam)]);
0207     ymin = min([min(min(abs(nxx.V_hat(idx, :)))); min(min(abs(nxx.V(idx, :))))]);
0208     ymax = max([max(max(abs(nxx.V_hat(idx, :)))); max(max(abs(nxx.V(idx, :))))]);
0209     if xmax < xmin + cb_data.mpopt.cpf.step / 100;
0210         xmax = xmin + cb_data.mpopt.cpf.step / 100;
0211     end
0212     if ymax - ymin < 2e-5;
0213         ymax = ymax + 1e-5;
0214         ymin = ymin - 1e-5;
0215     end
0216     xmax = xmax * 1.05;
0217     ymax = ymax + 0.05 * (ymax-ymin);
0218     ymin = ymin - 0.05 * (ymax-ymin);
0219 
0220     %%-----  INITIAL call  -----
0221     if k == 0
0222         %% save default plot bus in the state so we don't have to detect it
0223         %% each time, since we don't want it to change in the middle of the run
0224         if plot_bus_default
0225             cx.cb.default.plot_bus_default = plot_bus_default;
0226         end
0227         
0228         %% initialize lambda-V nose curve plot
0229         axis([xmin xmax ymin ymax]);
0230         plot(cxx.lam_hat(1), abs(cxx.V_hat(idx,1)), '-', 'Color', [0.25 0.25 1]);
0231         if nplots > 1
0232             title('Voltage at Multiple Buses');
0233         else
0234             title(sprintf('Voltage at Bus %d', idx_e));
0235         end
0236         xlabel('\lambda');
0237         ylabel('Voltage Magnitude');
0238         hold on;
0239     %%-----  ITERATION call  -----
0240     elseif k > 0
0241         %% plot single step of the lambda-V nose curve
0242         if plot_level > 1
0243             axis([xmin xmax ymin ymax]);
0244             for kk = 1:nplots
0245                 %% prediction line
0246                 plot([nxx.lam(k); nxx.lam_hat(k+1)], ...
0247                     [abs(nxx.V(idx(kk),k)); abs(nxx.V_hat(idx(kk),k+1))], '-', ...
0248                     'Color', 0.85*[1 0.75 0.75]);
0249                 %% correction line
0250                 plot([nxx.lam_hat(k+1); nxx.lam(k+1)], ...
0251                     [abs(nxx.V_hat(idx(kk),k+1)); abs(nxx.V(idx(kk),k+1))], '-', ...
0252                     'Color', 0.85*[0.75 1 0.75]);
0253                 %% prediciton point
0254                 plot(nxx.lam_hat(k+1), abs(nxx.V_hat(idx(kk),k+1)), 'x', ...
0255                     'Color', 0.85*[1 0.75 0.75]);
0256                 %% correction point
0257                 plot(nxx.lam(k+1)', abs(nxx.V(idx(kk),k+1))', '-o', ...
0258                     'Color', [0.25 0.25 1]);
0259                 drawnow;
0260             end
0261             if plot_level > 2
0262                 pause;
0263             end
0264         end
0265     %%-----  FINAL call  -----
0266     else    % k < 0
0267         %% finish final lambda-V nose curve plot
0268         axis([xmin xmax ymin ymax]);
0269         %% curve of corrected points
0270         if isprop(gca, 'ColorOrderIndex')
0271             set(gca, 'ColorOrderIndex', 1); %% start over with color 1
0272         end
0273         hp = plot(nxx.lam', abs(nxx.V(idx,:))',  '-');
0274         if nplots > 1
0275             leg = cell(nplots, 1);
0276             for kk = 1:nplots
0277                 leg{kk} = sprintf('Bus %d', idx_e(kk));
0278             end
0279             legend(hp, leg);
0280         end
0281         hold off;
0282     end
0283 end

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