


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.

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 http://www.pserc.cornell.edu/matpower/ 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 idx = full(cb_data.mpc_target.order.bus.e2i(idx_e)); 0193 if idx == 0 0194 error('cpf_default_callback: %d is not a valid bus number for MPOPT.cpf.plot.bus', idx_e); 0195 end 0196 end 0197 0198 %% set bounds for plot axes 0199 xmin = 0; 0200 xmax = max([max(nxx.lam_hat); max(nxx.lam)]); 0201 ymin = min([min(abs(nxx.V_hat(idx, :))); min(abs(nxx.V(idx, :)))]); 0202 ymax = max([max(abs(nxx.V_hat(idx, :))); max(abs(nxx.V(idx, :)))]); 0203 if xmax < xmin + cb_data.mpopt.cpf.step / 100; 0204 xmax = xmin + cb_data.mpopt.cpf.step / 100; 0205 end 0206 if ymax - ymin < 2e-5; 0207 ymax = ymax + 1e-5; 0208 ymin = ymin - 1e-5; 0209 end 0210 xmax = xmax * 1.05; 0211 ymax = ymax + 0.05 * (ymax-ymin); 0212 ymin = ymin - 0.05 * (ymax-ymin); 0213 0214 %%----- INITIAL call ----- 0215 if k == 0 0216 %% save default plot bus in the state so we don't have to detect it 0217 %% each time, since we don't want it to change in the middle of the run 0218 if plot_bus_default 0219 cx.cb.default.plot_bus_default = plot_bus_default; 0220 end 0221 0222 %% initialize lambda-V nose curve plot 0223 axis([xmin xmax ymin ymax]); 0224 plot(cxx.lam_hat(1), abs(cxx.V_hat(idx,1)), '-', 'Color', [0.25 0.25 1]); 0225 title(sprintf('Voltage at Bus %d', idx_e)); 0226 xlabel('\lambda'); 0227 ylabel('Voltage Magnitude'); 0228 hold on; 0229 %%----- ITERATION call ----- 0230 elseif k > 0 0231 %% plot single step of the lambda-V nose curve 0232 if plot_level > 1 0233 axis([xmin xmax ymin ymax]); 0234 plot([nxx.lam(k); nxx.lam_hat(k+1)], ... 0235 [abs(nxx.V(idx,k)); abs(nxx.V_hat(idx,k+1))], '-', ... 0236 'Color', 0.85*[1 0.75 0.75]); 0237 plot([nxx.lam_hat(k+1); nxx.lam(k+1)], ... 0238 [abs(nxx.V_hat(idx,k+1)); abs(nxx.V(idx,k+1))], '-', ... 0239 'Color', 0.85*[0.75 1 0.75]); 0240 plot(nxx.lam_hat(k+1), abs(nxx.V_hat(idx,k+1)), 'x', ... 0241 'Color', 0.85*[1 0.75 0.75]); 0242 plot(nxx.lam(k+1)', abs(nxx.V(idx,k+1))', '-o', ... 0243 'Color', [0.25 0.25 1]); 0244 drawnow; 0245 if plot_level > 2 0246 pause; 0247 end 0248 end 0249 %%----- FINAL call ----- 0250 else % k < 0 0251 %% finish final lambda-V nose curve plot 0252 axis([xmin xmax ymin ymax]); 0253 plot(nxx.lam', abs(nxx.V(idx,:))', '-', 'Color', [0.25 0.25 1]); 0254 hold off; 0255 end 0256 end