0001 function fname_out = savecase(fname, varargin)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 [PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
0039 VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;
0040 [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...
0041 MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...
0042 QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;
0043 [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
0044 TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
0045 ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;
0046 [PW_LINEAR, POLYNOMIAL, MODEL, STARTUP, SHUTDOWN, NCOST, COST] = idx_cost;
0047
0048
0049 if ischar(varargin{1}) || iscell(varargin{1})
0050 if ischar(varargin{1})
0051 comment = {varargin{1}};
0052 else
0053 comment = varargin{1};
0054 end
0055 [args{1:(length(varargin)-1)}] = deal(varargin{2:end});
0056 else
0057 comment = {''};
0058 args = varargin;
0059 end
0060 mpc_ver = '2';
0061 if isstruct(args{1})
0062 mpc = args{1};
0063 if length(args) > 1
0064 mpc.version = args{2};
0065 mpc_ver = mpc.version;
0066 end
0067 baseMVA = mpc.baseMVA;
0068 bus = mpc.bus;
0069 gen = mpc.gen;
0070 branch = mpc.branch;
0071 if isfield(mpc, 'areas')
0072 areas = mpc.areas;
0073 end
0074 if isfield(mpc, 'gencost')
0075 gencost = mpc.gencost;
0076 end
0077 else
0078 baseMVA = args{1};
0079 bus = args{2};
0080 gen = args{3};
0081 branch = args{4};
0082 mpc.baseMVA = baseMVA;
0083 mpc.bus = bus;
0084 mpc.gen = gen;
0085 mpc.branch = branch;
0086 if length(args) == 5
0087 gencost = args{5};
0088 mpc.gencost = gencost;
0089 end
0090 if length(args) == 6
0091 areas = args{5};
0092 gencost = args{6};
0093 mpc.areas = areas;
0094 mpc.gencost = gencost;
0095 end
0096 end
0097
0098
0099 if strcmp(mpc_ver, '1')
0100
0101 if size(gen, 2) >= MU_QMIN
0102 gen = gen(:, [1:PMIN, MU_PMAX:MU_QMIN]);
0103 else
0104 gen = gen(:, 1:PMIN);
0105 end
0106
0107 shift = MU_PMAX - PMIN - 1;
0108 tmp = num2cell([MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN] - shift);
0109 [MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN] = deal(tmp{:});
0110
0111
0112 if size(branch, 2) >= MU_ST
0113 branch = branch(:, [1:BR_STATUS, PF:MU_ST]);
0114 elseif size(branch, 2) >= QT
0115 branch = branch(:, [1:BR_STATUS, PF:QT]);
0116 else
0117 branch = branch(:, 1:BR_STATUS);
0118 end
0119
0120 shift = PF - BR_STATUS - 1;
0121 tmp = num2cell([PF, QF, PT, QT, MU_SF, MU_ST] - shift);
0122 [PF, QF, PT, QT, MU_SF, MU_ST] = deal(tmp{:});
0123 end
0124
0125
0126 [pathstr, fcn_name, extension] = fileparts(fname);
0127 if isempty(extension)
0128 extension = '.m';
0129 end
0130 if regexp(fcn_name, '\W')
0131 old_fcn_name = fcn_name;
0132 fcn_name = regexprep(fcn_name, '\W', '_');
0133 fprintf('WARNING: ''%s'' is not a valid function name, changed to ''%s''\n', old_fcn_name, fcn_name);
0134 end
0135 fname = fullfile(pathstr, [fcn_name extension]);
0136
0137
0138 if strcmp(upper(extension), '.MAT')
0139 vflag = '';
0140 if str2double(version('-release')) > 13
0141 vflag = '-v6';
0142 end
0143 if strcmp(mpc_ver, '1')
0144 if exist('areas', 'var') && exist('gencost', 'var')
0145 save(fname, 'baseMVA', 'bus', 'gen', 'branch', 'areas', 'gencost', vflag);
0146 else
0147 save(fname, 'baseMVA', 'bus', 'gen', 'branch', vflag);
0148 end
0149 else
0150 save(fname, 'baseMVA', 'mpc', vflag);
0151 end
0152 else
0153
0154 [fd, msg] = fopen(fname, 'wt');
0155 if fd == -1
0156 error(['savecase: ', msg]);
0157 end
0158
0159
0160 if strcmp(mpc_ver, '1')
0161 if exist('areas', 'var') && exist('gencost', 'var') && ~isempty(gencost)
0162 fprintf(fd, 'function [baseMVA, bus, gen, branch, areas, gencost] = %s\n', fcn_name);
0163 else
0164 fprintf(fd, 'function [baseMVA, bus, gen, branch] = %s\n', fcn_name);
0165 end
0166 prefix = '';
0167 else
0168 fprintf(fd, 'function mpc = %s\n', fcn_name);
0169 prefix = 'mpc.';
0170 end
0171 if isempty(comment{1})
0172 comment{1} = sprintf('%s', upper(fcn_name));
0173 else
0174 comment{1} = sprintf('%s %s', upper(fcn_name), comment{1});
0175 end
0176 for k = 1:length(comment)
0177 fprintf(fd, '%%%s\n', comment{k});
0178 end
0179 fprintf(fd, '\n%%%% MATPOWER Case Format : Version %s\n', mpc_ver);
0180 if ~strcmp(mpc_ver, '1')
0181 fprintf(fd, 'mpc.version = ''%s'';\n', mpc_ver);
0182 end
0183 fprintf(fd, '\n%%%%----- Power Flow Data -----%%%%\n');
0184 fprintf(fd, '%%%% system MVA base\n');
0185 fprintf(fd, '%sbaseMVA = %.9g;\n', prefix, baseMVA);
0186
0187
0188 ncols = size(bus, 2);
0189 fprintf(fd, '\n%%%% bus data\n');
0190 fprintf(fd, '%%\tbus_i\ttype\tPd\tQd\tGs\tBs\tarea\tVm\tVa\tbaseKV\tzone\tVmax\tVmin');
0191 if ncols >= MU_VMIN
0192 fprintf(fd, '\tlam_P\tlam_Q\tmu_Vmax\tmu_Vmin');
0193 end
0194 fprintf(fd, '\n%sbus = [\n', prefix);
0195 if ncols < MU_VMIN
0196 fprintf(fd, '\t%d\t%d\t%.9g\t%.9g\t%.9g\t%.9g\t%d\t%.9g\t%.9g\t%.9g\t%d\t%.9g\t%.9g;\n', bus(:, 1:VMIN).');
0197 else
0198 fprintf(fd, '\t%d\t%d\t%.9g\t%.9g\t%.9g\t%.9g\t%d\t%.9g\t%.9g\t%.9g\t%d\t%.9g\t%.9g\t%.4f\t%.4f\t%.4f\t%.4f;\n', bus(:, 1:MU_VMIN).');
0199 end
0200 fprintf(fd, '];\n');
0201
0202
0203 ncols = size(gen, 2);
0204 fprintf(fd, '\n%%%% generator data\n');
0205 fprintf(fd, '%%\tbus\tPg\tQg\tQmax\tQmin\tVg\tmBase\tstatus\tPmax\tPmin');
0206 if ~strcmp(mpc_ver, '1')
0207 fprintf(fd, '\tPc1\tPc2\tQc1min\tQc1max\tQc2min\tQc2max\tramp_agc\tramp_10\tramp_30\tramp_q\tapf');
0208 end
0209 if ncols >= MU_QMIN
0210 fprintf(fd, '\tmu_Pmax\tmu_Pmin\tmu_Qmax\tmu_Qmin');
0211 end
0212 fprintf(fd, '\n%sgen = [\n', prefix);
0213 if ncols < MU_QMIN
0214 if strcmp(mpc_ver, '1')
0215 fprintf(fd, '\t%d\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%d\t%.9g\t%.9g;\n', gen(:, 1:PMIN).');
0216 else
0217 fprintf(fd, '\t%d\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%d\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g;\n', gen(:, 1:APF).');
0218 end
0219 else
0220 if strcmp(mpc_ver, '1')
0221 fprintf(fd, '\t%d\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%d\t%.9g\t%.9g\t%.4f\t%.4f\t%.4f\t%.4f;\n', gen(:, 1:MU_QMIN).');
0222 else
0223 fprintf(fd, '\t%d\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%d\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.4f\t%.4f\t%.4f\t%.4f;\n', gen(:, 1:MU_QMIN).');
0224 end
0225 end
0226 fprintf(fd, '];\n');
0227
0228
0229 ncols = size(branch, 2);
0230 fprintf(fd, '\n%%%% branch data\n');
0231 fprintf(fd, '%%\tfbus\ttbus\tr\tx\tb\trateA\trateB\trateC\tratio\tangle\tstatus');
0232 if ~strcmp(mpc_ver, '1')
0233 fprintf(fd, '\tangmin\tangmax');
0234 end
0235 if ncols >= QT
0236 fprintf(fd, '\tPf\tQf\tPt\tQt');
0237 end
0238 if ncols >= MU_ST
0239 fprintf(fd, '\tmu_Sf\tmu_St');
0240 if ~strcmp(mpc_ver, '1')
0241 fprintf(fd, '\tmu_angmin\tmu_angmax');
0242 end
0243 end
0244 fprintf(fd, '\n%sbranch = [\n', prefix);
0245 if ncols < QT
0246 if strcmp(mpc_ver, '1')
0247 fprintf(fd, '\t%d\t%d\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%d;\n', branch(:, 1:BR_STATUS).');
0248 else
0249 fprintf(fd, '\t%d\t%d\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%d\t%.9g\t%.9g;\n', branch(:, 1:ANGMAX).');
0250 end
0251 elseif ncols < MU_ST
0252 if strcmp(mpc_ver, '1')
0253 fprintf(fd, '\t%d\t%d\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%d\t%.4f\t%.4f\t%.4f\t%.4f;\n', branch(:, 1:QT).');
0254 else
0255 fprintf(fd, '\t%d\t%d\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%d\t%.9g\t%.9g\t%.4f\t%.4f\t%.4f\t%.4f;\n', branch(:, 1:QT).');
0256 end
0257 else
0258 if strcmp(mpc_ver, '1')
0259 fprintf(fd, '\t%d\t%d\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%d\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f;\n', branch(:, 1:MU_ST).');
0260 else
0261 fprintf(fd, '\t%d\t%d\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%d\t%.9g\t%.9g\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f;\n', branch(:, 1:MU_ANGMAX).');
0262 end
0263 end
0264 fprintf(fd, '];\n');
0265
0266
0267 if (exist('areas', 'var') && ~isempty(areas)) || ...
0268 (exist('gencost', 'var') && ~isempty(gencost))
0269 fprintf(fd, '\n%%%%----- OPF Data -----%%%%');
0270 end
0271 if exist('areas', 'var') && ~isempty(areas)
0272
0273 fprintf(fd, '\n%%%% area data\n');
0274 fprintf(fd, '%%\tarea\trefbus\n');
0275 fprintf(fd, '%sareas = [\n', prefix);
0276 if ~isempty(areas)
0277 fprintf(fd, '\t%d\t%d;\n', areas(:, 1:2).');
0278 end
0279 fprintf(fd, '];\n');
0280 end
0281 if exist('gencost', 'var') && ~isempty(gencost)
0282
0283 fprintf(fd, '\n%%%% generator cost data\n');
0284 fprintf(fd, '%%\t1\tstartup\tshutdown\tn\tx1\ty1\t...\txn\tyn\n');
0285 fprintf(fd, '%%\t2\tstartup\tshutdown\tn\tc(n-1)\t...\tc0\n');
0286 fprintf(fd, '%sgencost = [\n', prefix);
0287 if ~isempty(gencost)
0288 n1 = 2 * max(gencost(gencost(:, MODEL) == PW_LINEAR, NCOST));
0289 n2 = max(gencost(gencost(:, MODEL) == POLYNOMIAL, NCOST));
0290 n = max([n1; n2]);
0291 if size(gencost, 2) < n + 4
0292 error('savecase: gencost data claims it has more columns than it does');
0293 end
0294 template = '\t%d\t%.9g\t%.9g\t%d';
0295 for i = 1:n
0296 template = [template, '\t%.9g'];
0297 end
0298 template = [template, ';\n'];
0299 fprintf(fd, template, gencost(:, 1:n+4).');
0300 end
0301 fprintf(fd, '];\n');
0302 end
0303
0304 if ~strcmp(mpc_ver, '1')
0305
0306 if (isfield(mpc, 'A') && ~isempty(mpc.A)) || ...
0307 (isfield(mpc, 'N') && ~isempty(mpc.N))
0308 fprintf(fd, '\n%%%%----- Generalized OPF User Data -----%%%%');
0309 end
0310
0311
0312 if isfield(mpc, 'A') && ~isempty(mpc.A)
0313
0314 fprintf(fd, '\n%%%% user constraints\n');
0315 print_sparse(fd, sprintf('%sA', prefix), mpc.A);
0316 if isfield(mpc, 'l') && ~isempty(mpc.l) && ...
0317 isfield(mpc, 'u') && ~isempty(mpc.u)
0318 fprintf(fd, 'lu = [\n');
0319 fprintf(fd, '\t%.9g\t%.9g;\n', [mpc.l mpc.u].');
0320 fprintf(fd, '];\n');
0321 fprintf(fd, '%sl = lu(:, 1);\n', prefix);
0322 fprintf(fd, '%su = lu(:, 2);\n\n', prefix);
0323 elseif isfield(mpc, 'l') && ~isempty(mpc.l)
0324 fprintf(fd, '%sl = [\n', prefix);
0325 fprintf(fd, '\t%.9g;\n', mpc.l);
0326 fprintf(fd, '];\n\n');
0327 elseif isfield(mpc, 'u') && ~isempty(mpc.u)
0328 fprintf(fd, '%su = [\n', prefix);
0329 fprintf(fd, '\t%.9g;\n', mpc.u);
0330 fprintf(fd, '];\n');
0331 end
0332 end
0333
0334
0335 if isfield(mpc, 'N') && ~isempty(mpc.N)
0336 fprintf(fd, '\n%%%% user costs\n');
0337 print_sparse(fd, sprintf('%sN', prefix), mpc.N);
0338 if isfield(mpc, 'H') && ~isempty(mpc.H)
0339 print_sparse(fd, sprintf('%sH', prefix), mpc.H);
0340 end
0341 if isfield(mpc, 'fparm') && ~isempty(mpc.fparm)
0342 fprintf(fd, 'Cw_fparm = [\n');
0343 fprintf(fd, '\t%.9g\t%d\t%.9g\t%.9g\t%.9g;\n', [mpc.Cw mpc.fparm].');
0344 fprintf(fd, '];\n');
0345 fprintf(fd, '%sCw = Cw_fparm(:, 1);\n', prefix);
0346 fprintf(fd, '%sfparm = Cw_fparm(:, 2:5);\n', prefix);
0347 else
0348 fprintf(fd, '%sCw = [\n', prefix);
0349 fprintf(fd, '\t%.9g;\n', mpc.Cw);
0350 fprintf(fd, '];\n');
0351 end
0352 end
0353
0354
0355 if isfield(mpc, 'z0') || isfield(mpc, 'zl') || isfield(mpc, 'zu')
0356 fprintf(fd, '\n%%%% user vars\n');
0357 end
0358 if isfield(mpc, 'z0') && ~isempty(mpc.z0)
0359 fprintf(fd, '%sz0 = [\n', prefix);
0360 fprintf(fd, '\t%.9g;\n', mpc.z0);
0361 fprintf(fd, '];\n');
0362 end
0363 if isfield(mpc, 'zl') && ~isempty(mpc.zl)
0364 fprintf(fd, '%szl = [\n', prefix);
0365 fprintf(fd, '\t%.9g;\n', mpc.zl);
0366 fprintf(fd, '];\n');
0367 end
0368 if isfield(mpc, 'zu') && ~isempty(mpc.zu)
0369 fprintf(fd, '%szu = [\n', prefix);
0370 fprintf(fd, '\t%.9g;\n', mpc.zu);
0371 fprintf(fd, '];\n');
0372 end
0373
0374
0375 if isfield(mpc, 'genfuel') && iscell(mpc.genfuel)
0376 ng = length(mpc.genfuel);
0377 if size(mpc.gen, 1) ~= ng
0378 warning('savecase: genfuel field does not have the expected dimensions (length = %d, expected %d)', ng, size(mpc.gen, 1));
0379 end
0380
0381 fprintf(fd, '\n%%%% generator fuel type\n');
0382 fprintf(fd, '%sgenfuel = {\n', prefix);
0383 for k = 1:ng
0384 fprintf(fd, '\t''%s'';\n', mpc.genfuel{k});
0385 end
0386 fprintf(fd, '};\n');
0387 end
0388
0389
0390 if isfield(mpc, 'bus_name') && iscell(mpc.bus_name)
0391 nb = length(mpc.bus_name);
0392 if size(mpc.bus, 1) ~= nb
0393 warning('savecase: bus_name field does not have the expected dimensions (length = %d, expected %d)', nb, size(mpc.bus, 1));
0394 end
0395
0396 fprintf(fd, '\n%%%% bus names\n');
0397 fprintf(fd, '%sbus_name = {\n', prefix);
0398 for k = 1:nb
0399 fprintf(fd, '\t''%s'';\n', mpc.bus_name{k});
0400 end
0401 fprintf(fd, '};\n');
0402 end
0403
0404
0405 if isfield(mpc, 'userfcn')
0406 run_userfcn(mpc.userfcn, 'savecase', mpc, fd, prefix);
0407 end
0408 end
0409
0410
0411 if fd ~= 1
0412 fclose(fd);
0413 end
0414 end
0415
0416 if nargout > 0
0417 fname_out = fname;
0418 end
0419
0420
0421
0422 function print_sparse(fd, varname, A)
0423
0424 [i, j, s] = find(A);
0425 [m, n] = size(A);
0426
0427 if isempty(s)
0428 fprintf(fd, '%s = sparse(%d, %d);\n', varname, m, n);
0429 else
0430 fprintf(fd, 'ijs = [\n');
0431 if m == 1
0432 fprintf(fd, '\t%d\t%d\t%.9g;\n', [i; j; s]);
0433 else
0434 fprintf(fd, '\t%d\t%d\t%.9g;\n', [i j s].');
0435 end
0436 fprintf(fd, '];\n');
0437 fprintf(fd, '%s = sparse(ijs(:, 1), ijs(:, 2), ijs(:, 3), %d, %d);\n', varname, m, n);
0438 end