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