Skip to content

Commit

Permalink
Add implementation of legacy DC line element type via mp.xt_legacy_dc…
Browse files Browse the repository at this point in the history
…line
  • Loading branch information
rdzman committed Jan 24, 2024
1 parent 749012c commit 92e0e2a
Show file tree
Hide file tree
Showing 18 changed files with 1,312 additions and 10 deletions.
94 changes: 94 additions & 0 deletions lib/t/+mp/dmce_legacy_dcline_mpc2.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
classdef dmce_legacy_dcline_mpc2 < mp.dmc_element % & mp.dmce_legacy_dcline
% mp.dmce_legacy_dcline_mpc2 - Data model converter element for legacy DC line for |MATPOWER| case v2.

% MATPOWER
% Copyright (c) 2021-2024, Power Systems Engineering Research Center (PSERC)
% by Ray Zimmerman, PSERC Cornell
%
% This file is part of MATPOWER.
% Covered by the 3-clause BSD License (see LICENSE file for details).
% See https://matpower.org for more info.

methods
function name = name(obj)
%
name = 'legacy_dcline';
end

function df = data_field(obj)
%
df = 'dcline';
end

function vmap = table_var_map(obj, dme, mpc)
%
vmap = [email protected]_element(obj, dme, mpc);

%% define named indices into data matrices
c = idx_dcline;

gcip_fcn = @(ob, mpc, spec, vn)dcline_cost_import(ob, mpc, spec, vn);
gcep_fcn = @(ob, dme, mpc, spec, vn, ridx)dcline_cost_export(ob, dme, mpc, spec, vn, ridx);

%% mapping for each name, default is {'col', []}
vmap.uid = {'IDs'}; %% consecutive IDs, starting at 1
vmap.name = {'cell', ''}; %% empty char
vmap.status{2} = c.BR_STATUS;
vmap.source_uid = {'cell', ''}; %% empty char
vmap.bus_fr{2} = c.F_BUS;
vmap.bus_to{2} = c.T_BUS;
vmap.loss0{2} = c.LOSS0;
vmap.loss1{2} = c.LOSS1;
vmap.vm_setpoint_fr{2} = c.VF;
vmap.vm_setpoint_to{2} = c.VT;
vmap.p_fr_lb{2} = c.PMIN;
vmap.p_fr_ub{2} = c.PMAX;
vmap.q_fr_lb{2} = c.QMINF;
vmap.q_fr_ub{2} = c.QMAXF;
vmap.q_to_lb{2} = c.QMINT;
vmap.q_to_ub{2} = c.QMAXT;
vmap.p_fr{2} = c.PF;
vmap.q_fr{2} = c.QF;
vmap.p_to{2} = c.PT;
vmap.q_to{2} = c.QT;
if isfield(vmap, 'cost')
vmap.cost = {'fcn', gcip_fcn, gcep_fcn};
vmap.mu_p_fr_lb{2} = c.MU_PMIN;
vmap.mu_p_fr_ub{2} = c.MU_PMAX;
vmap.mu_q_fr_lb{2} = c.MU_QMINF;
vmap.mu_q_fr_ub{2} = c.MU_QMAXF;
vmap.mu_q_to_lb{2} = c.MU_QMINT;
vmap.mu_q_to_ub{2} = c.MU_QMAXT;
end
end

function dt = default_export_data_table(obj, spec)
%

%% define named indices into data matrices
c = idx_dcline;

nr = obj.default_export_data_nrows(spec);
dt = zeros(nr, c.QMAXT);
end

function val = dcline_cost_import(obj, mpc, spec, vn)
%
if isfield(mpc, 'dclinecost') && spec.nr
val = mp.dmce_gen_mpc2.gencost2cost_table(mpc.dclinecost);
else
val = [];
end
end

function mpc = dcline_cost_export(obj, dme, mpc, spec, vn, ridx)
%

if dme.have_cost()
cost = mp.dmce_gen_mpc2.cost_table2gencost( ...
[], dme.tab.cost, ridx);
mpc.dclinecost(1:spec.nr, 1:size(cost, 2)) = cost;
end
end
end %% methods
end %% classdef
204 changes: 204 additions & 0 deletions lib/t/+mp/dme_legacy_dcline.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
classdef dme_legacy_dcline < mp.dm_element
% mp.dme_legacy_dcline - Data model element for legacy DC line.

% MATPOWER
% Copyright (c) 2020-2024, Power Systems Engineering Research Center (PSERC)
% by Ray Zimmerman, PSERC Cornell
%
% This file is part of MATPOWER.
% Covered by the 3-clause BSD License (see LICENSE file for details).
% See https://matpower.org for more info.

properties
fbus % bus index vector for "from" port (port 1) (all DC lines)
tbus % bus index vector for "to" port (port 2) (all DC lines)
fbus_on % vector of "from" bus indices into online buses (in-service DC lines)
tbus_on % vector of "to" bus indices into online buses (in-service DC lines)
loss0 % constant term of loss function (p.u.) (in-service DC lines)
loss1 % linear coefficient of loss function (in-service DC lines)
p_fr_start % initial active power (p.u.) at "from" port (in-service DC lines)
p_to_start % initial active power (p.u.) at "to" port (in-service DC lines)
q_fr_start % initial reactive power (p.u.) at "from" port (in-service DC lines)
q_to_start % initial reactive power (p.u.) at "to" port (in-service DC lines)
vm_setpoint_fr % from bus voltage magnitude setpoint (p.u.) (in-service DC lines)
vm_setpoint_to % to bus voltage magnitude setpoint (p.u.) (in-service DC lines)
p_fr_lb % p.u. lower bound on active power flow at "from" port (in-service DC lines)
p_fr_ub % p.u. upper bound on active power flow at "from" port (in-service DC lines)
q_fr_lb % p.u. lower bound on reactive power flow at "from" port (in-service DC lines)
q_fr_ub % p.u. upper bound on reactive power flow at "from" port (in-service DC lines)
q_to_lb % p.u. lower bound on reactive power flow at "to" port (in-service DC lines)
q_to_ub % p.u. upper bound on reactive power flow at "to" port (in-service DC lines)
end %% properties

methods
function name = name(obj)
%
name = 'legacy_dcline';
end

function label = label(obj)
%
label = 'DC Line';
end

function label = labels(obj)
%
label = 'DC Lines';
end

function name = cxn_type(obj)
%
name = 'bus';
end

function name = cxn_idx_prop(obj)
%
name = {'fbus', 'tbus'};
end

function names = main_table_var_names(obj)
%
names = horzcat( [email protected]_element(obj), ...
{'bus_fr', 'bus_to', 'loss0', 'loss1', ...
'vm_setpoint_fr', 'vm_setpoint_to', ...
'p_fr_lb', 'p_fr_ub', ...
'q_fr_lb', 'q_fr_ub', 'q_to_lb', 'q_to_ub', ...
'p_fr', 'q_fr', 'p_to', 'q_to'} );
end

function vars = export_vars(obj)
%
vars = {'p_fr', 'q_fr', 'p_to', 'q_to'};
end

function s = export_vars_offline_val(obj)
%

s = [email protected]_element(obj); %% call parent
s.p_fr = 0;
s.q_fr = 0;
s.p_to = 0;
s.q_to = 0;
end

function TorF = have_cost(obj)
%
TorF = 0;
end

function obj = initialize(obj, dm)
%
[email protected]_element(obj, dm); %% call parent

%% get bus mapping info
b2i = dm.elements.bus.ID2i; %% bus num to idx mapping

%% set bus index vectors for port connectivity
obj.fbus = b2i(obj.tab.bus_fr);
obj.tbus = b2i(obj.tab.bus_to);
end

function obj = update_status(obj, dm)
%

%% get bus status info
bus_dme = dm.elements.bus;
bs = bus_dme.tab.status; %% bus status

%% update status of branches connected to isolated/offline buses
obj.tab.status = obj.tab.status & bs(obj.fbus) & ...
bs(obj.tbus);

%% call parent to fill in on/off
[email protected]_element(obj, dm);

%% for all online DC lines ...
%% ... set terminal buses (except ref) to PV type
idx = [obj.fbus(obj.on); obj.tbus(obj.on)]; %% all terminal buses
idx(bus_dme.type(idx) == mp.NODE_TYPE.REF) = []; %% except ref
bus_dme.set_bus_type_pv(dm, idx);

%% set bus_dme.vm_control
obj.fbus_on = bus_dme.i2on(obj.fbus(obj.on));
obj.tbus_on = bus_dme.i2on(obj.tbus(obj.on));
bus_dme.vm_control(obj.fbus_on) = 1;
bus_dme.vm_control(obj.tbus_on) = 1;
end

function obj = apply_vm_setpoints(obj, dm)
%

% set starting bus voltage, if bus is voltage-controlled
bus_dme = dm.elements.bus;
i_fr = find(bus_dme.vm_control(obj.fbus_on));
i_to = find(bus_dme.vm_control(obj.tbus_on));
bus_dme.vm_start(obj.fbus_on(i_fr)) = obj.vm_setpoint_fr(i_fr);
bus_dme.vm_start(obj.tbus_on(i_to)) = obj.vm_setpoint_to(i_to);
end

function obj = build_params(obj, dm)
%
obj.loss0 = obj.tab.loss0(obj.on) / dm.base_mva;
obj.loss1 = obj.tab.loss1(obj.on);
obj.p_fr_start = obj.tab.p_fr(obj.on) / dm.base_mva;
obj.p_to_start = (obj.loss1 - 1) .* obj.p_fr_start + obj.loss0;
obj.q_fr_start = -obj.tab.q_fr(obj.on) / dm.base_mva;
obj.q_to_start = -obj.tab.q_to(obj.on) / dm.base_mva;
obj.vm_setpoint_fr = obj.tab.vm_setpoint_fr(obj.on);
obj.vm_setpoint_to = obj.tab.vm_setpoint_to(obj.on);
obj.p_fr_lb = obj.tab.p_fr_lb(obj.on) / dm.base_mva;
obj.p_fr_ub = obj.tab.p_fr_ub(obj.on) / dm.base_mva;
obj.q_fr_lb = obj.tab.q_fr_lb(obj.on) / dm.base_mva;
obj.q_fr_ub = obj.tab.q_fr_ub(obj.on) / dm.base_mva;
obj.q_to_lb = obj.tab.q_to_lb(obj.on) / dm.base_mva;
obj.q_to_ub = obj.tab.q_to_ub(obj.on) / dm.base_mva;

obj.apply_vm_setpoints(dm);
end

function TorF = pp_have_section_sum(obj, mpopt, pp_args)
%
TorF = true;
end

function obj = pp_data_sum(obj, dm, rows, out_e, mpopt, fd, pp_args)
%

%% call parent
[email protected]_element(obj, dm, rows, out_e, mpopt, fd, pp_args);

%% print DC line summary
fprintf(fd, ' %-29s %12.2f MW', 'Total DC line losses', ...
sum(obj.tab.p_fr(obj.on)) - sum(obj.tab.p_to(obj.on)) );
if mpopt.model(1) ~= 'D' %% AC model
fprintf(fd, ' %12.2f MVAr', ...
sum(obj.tab.q_fr(obj.on)) + sum(obj.tab.q_to(obj.on)) );
end
fprintf(fd, '\n');
end

function h = pp_get_headers_det(obj, dm, out_e, mpopt, pp_args)
%
h = [ [email protected]_element(obj, dm, out_e, mpopt, pp_args) ...
{ ' DC Line From To Power Flow (MW) Loss Reactive Inj (MVAr)', ...
' ID Bus ID Bus ID Status From To (MW) From To', ...
'-------- -------- -------- ------ -------- -------- -------- -------- --------' } ];
%% 1234567 123456789 123456789 -----1 1234567.90 123456.89 123456.89 123456.89 123456.89
end

function TorF = pp_have_section_det(obj, mpopt, pp_args)
%
TorF = true;
end

function str = pp_data_row_det(obj, dm, k, out_e, mpopt, fd, pp_args)
%
str = sprintf('%7d %9d %9d %6d %10.2f %9.2f %9.2f %9.2f %9.2f', ...
obj.tab.uid(k), obj.tab.bus_fr(k), obj.tab.bus_to(k), ...
obj.tab.status(k), ...
obj.tab.p_fr(k), obj.tab.p_to(k), ...
obj.tab.p_fr(k) - obj.tab.p_to(k), ...
obj.tab.q_fr(k), obj.tab.q_to(k) );
end
end %% methods
end %% classdef
Loading

0 comments on commit 92e0e2a

Please sign in to comment.