To use the cpf code on IEEE 14 bus system. You need to:
1) Open 'test_cpf.m'. Set 'casename' to be 'case14', and set 'loadvarloc' to be
the interested load change location. Basically, that's it. It works for
MATPOWER v3.0.
2) However, to run with MATPOWER v3.2 and later versions, you have to change
"feval(casename)" to "loadcase(casename)" in both cpf.m and drawPVcurve.m, just
like what Michael pointed out.
For your convenience, I am attaching the revised copy of cpf.m and
drawPVcurve.m, which may be used to override your current version. A test file
'test_cpf_14bus.m' is also enclosed, which you can run by typing in
'test_cpf_14bus' in MATLAB Command Window.
Please note that presently only single bus load variation is supported. In the
future it will be enhanced to support load changes at multiple buses. Users may
also need to adjust 'sigmaForLambda', 'sigmaForVoltage' (in test_cpf.m), and
even 'slopeThresh_Phase1' and 'slopeThresh_Phase2' (in cpf.m) in running the
CPF module for different systems.
Regards,
Rui Bo
[email protected]
----- Original Message -----
From: An Shevchenko
To: MATPOWER discussion forum
Sent: Wednesday, January 06, 2010 5:09 PM
Subject: Re: Test_cpf in Matpower 4.0b1
Dear Michael Power
Can u guide me on how you solve this problem?
I want to adapt these test_cpf codes with ieee 14 bus system.
Thanks
function test_cpf_14bus
% function: test continuation power flow (CPF)
% created by Rui Bo on Jan 6, 2010
casename = 'case14';%'case6bus'; %'case30'
%% test cpf
fprintf('\n------------testing continuation power flow (CPF) solver\n');
loadvarloc = 4;%4;%5 % bus number at which load changes
sigmaForLambda = 0.2;%0.05; % stepsize for Lambda
sigmaForVoltage = 0.05;%0.025; % stepsize for voltage
[max_lambda, predicted_list, corrected_list, combined_list, success, et] =
cpf(casename, loadvarloc, sigmaForLambda, sigmaForVoltage);
fprintf('maximum lambda is %f\n\n', max_lambda);
%% draw PV curve
flag_combinedCurve = true;
busesToDraw = [];%[3:6];
drawPVcurves(casename, loadvarloc, corrected_list, combined_list,
flag_combinedCurve, busesToDraw);
function [max_lambda, predicted_list, corrected_list, combined_list, success,
et] = cpf(casename, loadvarloc, sigmaForLambda, sigmaForVoltage)
% function: run continuation power flow (CPF) solver
% [INPUT PARAMETERS]
% loadvarloc: load variation location(in external bus numbering). Single bus
supported so far.
% sigmaForLambda: stepsize for lambda
% sigmaForVoltage: stepsize for voltage
% [OUTPUT PARAMETERS]
% max_lambda: the lambda in p.u. w.r.t. baseMVA at (or near) the nose point of
PV curve
% NOTE: the first column in return parameters 'predicted_list,
% corrected_list, combined_list' is bus number; the last row is lambda.
% created by Rui Bo on 2007/11/12
%% define named indices into bus, gen, branch matrices
[PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;
[F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, ...
RATE_C, TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST] = idx_brch;
[GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, ...
GEN_STATUS, PMAX, PMIN, MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN] = idx_gen;
%% assign default parameters
if nargin < 3
sigmaForLambda = 0.1; % stepsize for lambda
sigmaForVoltage = 0.025; % stepsize for voltage
end
%% options
max_iter = 400; % depends on selection of stepsizes
verbose = 1;
%% instead of using condition number as criteria for switching between
%% modes...
% % condNumThresh_Phase1 = 0.2e-2; % condition number shreshold for voltage
prediction-correction (lambda increasing)
% % condNumThresh_Phase2 = 0.2e-2; % condition number shreshold for lambda
prediction-correction
% % condNumThresh_Phase3 = 0.1e-5; % condition number shreshold for voltage
prediction-correction in backward direction (lambda decreasing)
%% ...we use PV curve slopes as the criteria for switching modes
slopeThresh_Phase1 = 0.5; % PV curve slope shreshold for voltage
prediction-correction (with lambda increasing)
slopeThresh_Phase2 = 0.3; % PV curve slope shreshold for lambda
prediction-correction
%% load the case & convert to internal bus numbering
[baseMVA, bus, gen, branch] = loadcase(casename);
[i2e, bus, gen, branch] = ext2int(bus, gen, branch);
e2i = sparse(max(i2e), 1);
e2i(i2e) = [1:size(bus, 1)]';
loadvarloc_i = e2i(loadvarloc);
%% get bus index lists of each type of bus
[ref, pv, pq] = bustypes(bus, gen);
%% generator info
on = find(gen(:, GEN_STATUS) > 0); %% which generators are on?
gbus = gen(on, GEN_BUS); %% what buses are they at?
%% form Ybus matrix
[Ybus, Yf, Yt] = makeYbus(baseMVA, bus, branch);
%% set up indexing
npv = length(pv);
npq = length(pq);
pv_bus = ~isempty(find(pv == loadvarloc_i));
%% initialize parameters
% set lambda to be increasing
flag_lambdaIncrease = true; % flag indicating lambda is increasing or
decreasing
if bus(loadvarloc_i, PD) == 0
initQPratio = 0;
fprintf('\t[Warning]:\tLoad real power at bus %d is 0. Q/P ratio will be
fixed at 0.\n', loadvarloc);
else
initQPratio = bus(loadvarloc_i, QD)./bus(loadvarloc_i, PD);
end
lambda0 = 0;
lambda = lambda0;
Vm = ones(size(bus, 1), 1); %% flat start
Va = bus(ref(1), VA) * Vm;
V = Vm .* exp(sqrt(-1) * pi/180 * Va);
V(gbus) = gen(on, VG) ./ abs(V(gbus)).* V(gbus);
pointCnt = 0;
%% do voltage correction (ie, power flow) to get initial voltage profile
lambda_predicted = lambda;
V_predicted = V;
[V, lambda, success, iterNum] = cpf_correctVoltage(baseMVA, bus, gen, Ybus,
V_predicted, lambda_predicted, initQPratio, loadvarloc_i);
%% record data
pointCnt = pointCnt + 1;
corrected_list(:, pointCnt) = [V;lambda];
%%------------------------------------------------
%% do cpf prediction-correction iterations
%%------------------------------------------------
t0 = clock;
%% --- Start Phase 1: voltage prediction-correction (lambda increasing)
if verbose > 0
fprintf('Start Phase 1: voltage prediction-correction (lambda
increasing).\n');
end
i = 0;
while i < max_iter
%% update iteration counter
i = i + 1;
% save good data
V_saved = V;
lambda_saved = lambda;
%% do voltage prediction to find predicted point (predicting voltage)
[V_predicted, lambda_predicted, J] = cpf_predict(Ybus, ref, pv, pq, V,
lambda, sigmaForLambda, 1, initQPratio, loadvarloc, flag_lambdaIncrease);
%% do voltage correction to find corrected point
[V, lambda, success, iterNum] = cpf_correctVoltage(baseMVA, bus, gen, Ybus,
V_predicted, lambda_predicted, initQPratio, loadvarloc_i);
%% calculate slope (dP/dLambda) at current point
slope = abs(V(loadvarloc_i) - V_saved(loadvarloc_i))/(lambda -
lambda_saved);
%% instead of using condition number as criteria for switching between
%% modes...
%% if rcond(J) <= condNumThresh_Phase1 | success == false % Jacobian
matrix is ill-conditioned, or correction step fails
%% ...we use PV curve slopes as the criteria for switching modes
if abs(slope) >= slopeThresh_Phase1 | success == false % Approaching nose
area of PV curve, or correction step fails
% restore good data
V = V_saved;
lambda = lambda_saved;
if verbose > 0
fprintf('\t[Info]:\tApproaching nose area of PV curve, or voltage
correction fails.\n');
end
break;
else
if verbose > 2
fprintf('\nVm_predicted\tVm_corrected\n');
[[abs(V_predicted);lambda_predicted] [abs(V);lambda]]
end
%% record data
pointCnt = pointCnt + 1;
predicted_list(:, pointCnt-1) = [V_predicted;lambda_predicted];
corrected_list(:, pointCnt) = [V;lambda];
end
end
pointCnt_Phase1 = pointCnt; % collect number of points obtained at this phase
if verbose > 0
fprintf('\t[Info]:\t%d data points contained in phase 1.\n',
pointCnt_Phase1);
end
%% --- Switch to Phase 2: lambda prediction-correction (voltage decreasing)
if verbose > 0
fprintf('Switch to Phase 2: lambda prediction-correction (voltage
decreasing).\n');
end
k = 0;
while k < max_iter
%% update iteration counter
k = k + 1;
% save good data
V_saved = V;
lambda_saved = lambda;
%% do lambda prediction to find predicted point (predicting lambda)
[V_predicted, lambda_predicted, J] = cpf_predict(Ybus, ref, pv, pq, V,
lambda, sigmaForVoltage, 2, initQPratio, loadvarloc);
%% do lambda correction to find corrected point
Vm_assigned = abs(V_predicted);
[V, lambda, success, iterNum] = cpf_correctLambda(baseMVA, bus, gen, Ybus,
Vm_assigned, V_predicted, lambda_predicted, initQPratio, loadvarloc, ref, pv,
pq);
%% calculate slope (dP/dLambda) at current point
slope = abs(V(loadvarloc_i) - V_saved(loadvarloc_i))/(lambda -
lambda_saved);
%% instead of using condition number as criteria for switching between
%% modes...
%% if rcond(J) >= condNumThresh_Phase2 | success == false % Jacobian
matrix is good-conditioned, or correction step fails
%% ...we use PV curve slopes as the criteria for switching modes
if abs(slope) <= slopeThresh_Phase2 | success == false % Leaving nose area
of PV curve, or correction step fails
% restore good data
V = V_saved;
lambda = lambda_saved;
%% ---change to voltage prediction-correction (lambda decreasing)
if verbose > 0
fprintf('\t[Info]:\tLeaving nose area of PV curve, or lambda
correction fails.\n');
end
break;
else
if verbose > 2
fprintf('\nVm_predicted\tVm_corrected\n');
[[abs(V_predicted);lambda_predicted] [abs(V);lambda]]
end
%% record data
pointCnt = pointCnt + 1;
predicted_list(:, pointCnt-1) = [V_predicted;lambda_predicted];
corrected_list(:, pointCnt) = [V;lambda];
end
end
pointCnt_Phase2 = pointCnt - pointCnt_Phase1; % collect number of points
obtained at this phase
if verbose > 0
fprintf('\t[Info]:\t%d data points contained in phase 2.\n',
pointCnt_Phase2);
end
%% --- Switch to Phase 3: voltage prediction-correction (lambda decreasing)
if verbose > 0
fprintf('Switch to Phase 3: voltage prediction-correction (lambda
decreasing).\n');
end
% set lambda to be decreasing
flag_lambdaIncrease = false;
i = 0;
while i < max_iter
%% update iteration counter
i = i + 1;
%% do voltage prediction to find predicted point (predicting voltage)
[V_predicted, lambda_predicted, J] = cpf_predict(Ybus, ref, pv, pq, V,
lambda, sigmaForLambda, 1, initQPratio, loadvarloc, flag_lambdaIncrease);
%% do voltage correction to find corrected point
[V, lambda, success, iterNum] = cpf_correctVoltage(baseMVA, bus, gen, Ybus,
V_predicted, lambda_predicted, initQPratio, loadvarloc_i);
%% calculate slope (dP/dLambda) at current point
slope = abs(V(loadvarloc_i) - V_saved(loadvarloc_i))/(lambda -
lambda_saved);
if lambda < 0 % lambda is less than 0, then stops CPF simulation
if verbose > 0
fprintf('\t[Info]:\tlambda is less than 0.\n\t\t\tCPF finished.\n');
end
break;
end
%% instead of using condition number as criteria for switching between
%% modes...
%% if rcond(J) <= condNumThresh_Phase3 | success == false % Jacobian
matrix is ill-conditioned, or correction step fails
%% ...we use PV curve slopes as the criteria for switching modes
if success == false % voltage correction step fails.
if verbose > 0
fprintf('\t[Info]:\tVoltage correction step fails..\n');
end
break;
else
if verbose > 2
fprintf('\nVm_predicted\tVm_corrected\n');
[[abs(V_predicted);lambda_predicted] [abs(V);lambda]]
end
%% record data
pointCnt = pointCnt + 1;
predicted_list(:, pointCnt-1) = [V_predicted;lambda_predicted];
corrected_list(:, pointCnt) = [V;lambda];
end
end
pointCnt_Phase3 = pointCnt - pointCnt_Phase2 - pointCnt_Phase1; % collect
number of points obtained at this phase
if verbose > 0
fprintf('\t[Info]:\t%d data points contained in phase 3.\n',
pointCnt_Phase3);
end
et = etime(clock, t0);
%% combine the prediction and correction data in the sequence of appearance
% NOTE: number of prediction data is one less than that of correction data
predictedCnt = size(predicted_list, 2);
combined_list(:, 1) = corrected_list(:, 1);
for i = 1:predictedCnt
combined_list(:, 2*i) = predicted_list(:, i);
combined_list(:, 2*i+1) = corrected_list(:, i+1);
end
%% convert back to original bus numbering & print results
[bus, gen, branch] = int2ext(i2e, bus, gen, branch);
%% add bus number as the first column to the prediction, correction, and
combined data list
nb = size(bus, 1);
max_lambda = max(corrected_list(nb+1, :));
predicted_list = [[bus(:, BUS_I);0] predicted_list];
corrected_list = [[bus(:, BUS_I);0] corrected_list];
combined_list = [[bus(:, BUS_I);0] combined_list];
if verbose > 1
Vm_corrected = abs(corrected_list);
Vm_predicted = abs(predicted_list);
Vm_combined = abs(combined_list);
Vm_corrected
Vm_predicted
Vm_combined
pointCnt_Phase1
pointCnt_Phase2
pointCnt_Phase3
pointCnt
end
function drawPVcurves(casename, loadvarloc, corrected_list, combined_list,
flag_combinedCurve, busesToDraw)
% function: draw PV curves for specified buses
% [INPUT PARAMETERS]
% corrected_list, combined_list: data points obtained from CPF solver
% loadvarloc: load variation location(in external bus numbering). Single bus
supported so far.
% flag_combinedCurve: flag indicating if the prediction-correction curve will
be drawn
% busesToDraw: bus indices whose PV curve will be be drawn
% created by Rui Bo on 2008/01/13
%% assign default parameters
if nargin < 6
busesToDraw = loadvarloc; % draw the curve for the load changing bus
end
if isempty(busesToDraw)
busesToDraw = loadvarloc; % draw the curve for the load changing bus
end
%% load the case & convert to internal bus numbering
[baseMVA, bus, gen, branch] = loadcase(casename);
nb = size(bus, 1);
correctedDataNum = size(corrected_list, 2) - 1;
combinedDataNum = size(combined_list, 2) - 1;
%% prepare data for drawing
lambda_corrected = corrected_list(nb+1, [2:correctedDataNum+1]);
lambda_combined = combined_list(nb+1, [2:combinedDataNum+1]);
fprintf('Start plotting CPF curve(s)...\n');
for j = 1:length(busesToDraw)%for i = 1+npv+1:1+npv+npq
i = find(corrected_list(:, 1) == busesToDraw(j)); % find row index
%% get voltage magnitudes
Vm_corrected = abs(corrected_list(i, [2:correctedDataNum+1]));
Vm_combined = abs(combined_list(i, [2:combinedDataNum+1]));
%% create a new figure
figure;
hold on;
%% plot PV curve
plot(lambda_corrected, Vm_corrected, 'bx-');
%% plot CPF prediction-correction curve
if flag_combinedCurve == true
plot(lambda_combined, Vm_combined, 'r.-');
legend('CPF Curve', 'Prediction-Correction Curve');
legend('Location', 'Best');
end
%% add plot title
title(['Vm at bus ' int2str(busesToDraw(j)) ' w.r.t. load (p.u.) at '
int2str(loadvarloc)]);
end
fprintf('Plotting is done.\n');