Skip to content

Commit 92e0e2a

Browse files
committed
Add implementation of legacy DC line element type via mp.xt_legacy_dcline
1 parent 749012c commit 92e0e2a

18 files changed

+1312
-10
lines changed

lib/t/+mp/dmce_legacy_dcline_mpc2.m

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
classdef dmce_legacy_dcline_mpc2 < mp.dmc_element % & mp.dmce_legacy_dcline
2+
% mp.dmce_legacy_dcline_mpc2 - Data model converter element for legacy DC line for |MATPOWER| case v2.
3+
4+
% MATPOWER
5+
% Copyright (c) 2021-2024, Power Systems Engineering Research Center (PSERC)
6+
% by Ray Zimmerman, PSERC Cornell
7+
%
8+
% This file is part of MATPOWER.
9+
% Covered by the 3-clause BSD License (see LICENSE file for details).
10+
% See https://matpower.org for more info.
11+
12+
methods
13+
function name = name(obj)
14+
%
15+
name = 'legacy_dcline';
16+
end
17+
18+
function df = data_field(obj)
19+
%
20+
df = 'dcline';
21+
end
22+
23+
function vmap = table_var_map(obj, dme, mpc)
24+
%
25+
vmap = [email protected]_element(obj, dme, mpc);
26+
27+
%% define named indices into data matrices
28+
c = idx_dcline;
29+
30+
gcip_fcn = @(ob, mpc, spec, vn)dcline_cost_import(ob, mpc, spec, vn);
31+
gcep_fcn = @(ob, dme, mpc, spec, vn, ridx)dcline_cost_export(ob, dme, mpc, spec, vn, ridx);
32+
33+
%% mapping for each name, default is {'col', []}
34+
vmap.uid = {'IDs'}; %% consecutive IDs, starting at 1
35+
vmap.name = {'cell', ''}; %% empty char
36+
vmap.status{2} = c.BR_STATUS;
37+
vmap.source_uid = {'cell', ''}; %% empty char
38+
vmap.bus_fr{2} = c.F_BUS;
39+
vmap.bus_to{2} = c.T_BUS;
40+
vmap.loss0{2} = c.LOSS0;
41+
vmap.loss1{2} = c.LOSS1;
42+
vmap.vm_setpoint_fr{2} = c.VF;
43+
vmap.vm_setpoint_to{2} = c.VT;
44+
vmap.p_fr_lb{2} = c.PMIN;
45+
vmap.p_fr_ub{2} = c.PMAX;
46+
vmap.q_fr_lb{2} = c.QMINF;
47+
vmap.q_fr_ub{2} = c.QMAXF;
48+
vmap.q_to_lb{2} = c.QMINT;
49+
vmap.q_to_ub{2} = c.QMAXT;
50+
vmap.p_fr{2} = c.PF;
51+
vmap.q_fr{2} = c.QF;
52+
vmap.p_to{2} = c.PT;
53+
vmap.q_to{2} = c.QT;
54+
if isfield(vmap, 'cost')
55+
vmap.cost = {'fcn', gcip_fcn, gcep_fcn};
56+
vmap.mu_p_fr_lb{2} = c.MU_PMIN;
57+
vmap.mu_p_fr_ub{2} = c.MU_PMAX;
58+
vmap.mu_q_fr_lb{2} = c.MU_QMINF;
59+
vmap.mu_q_fr_ub{2} = c.MU_QMAXF;
60+
vmap.mu_q_to_lb{2} = c.MU_QMINT;
61+
vmap.mu_q_to_ub{2} = c.MU_QMAXT;
62+
end
63+
end
64+
65+
function dt = default_export_data_table(obj, spec)
66+
%
67+
68+
%% define named indices into data matrices
69+
c = idx_dcline;
70+
71+
nr = obj.default_export_data_nrows(spec);
72+
dt = zeros(nr, c.QMAXT);
73+
end
74+
75+
function val = dcline_cost_import(obj, mpc, spec, vn)
76+
%
77+
if isfield(mpc, 'dclinecost') && spec.nr
78+
val = mp.dmce_gen_mpc2.gencost2cost_table(mpc.dclinecost);
79+
else
80+
val = [];
81+
end
82+
end
83+
84+
function mpc = dcline_cost_export(obj, dme, mpc, spec, vn, ridx)
85+
%
86+
87+
if dme.have_cost()
88+
cost = mp.dmce_gen_mpc2.cost_table2gencost( ...
89+
[], dme.tab.cost, ridx);
90+
mpc.dclinecost(1:spec.nr, 1:size(cost, 2)) = cost;
91+
end
92+
end
93+
end %% methods
94+
end %% classdef

lib/t/+mp/dme_legacy_dcline.m

+204
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
classdef dme_legacy_dcline < mp.dm_element
2+
% mp.dme_legacy_dcline - Data model element for legacy DC line.
3+
4+
% MATPOWER
5+
% Copyright (c) 2020-2024, Power Systems Engineering Research Center (PSERC)
6+
% by Ray Zimmerman, PSERC Cornell
7+
%
8+
% This file is part of MATPOWER.
9+
% Covered by the 3-clause BSD License (see LICENSE file for details).
10+
% See https://matpower.org for more info.
11+
12+
properties
13+
fbus % bus index vector for "from" port (port 1) (all DC lines)
14+
tbus % bus index vector for "to" port (port 2) (all DC lines)
15+
fbus_on % vector of "from" bus indices into online buses (in-service DC lines)
16+
tbus_on % vector of "to" bus indices into online buses (in-service DC lines)
17+
loss0 % constant term of loss function (p.u.) (in-service DC lines)
18+
loss1 % linear coefficient of loss function (in-service DC lines)
19+
p_fr_start % initial active power (p.u.) at "from" port (in-service DC lines)
20+
p_to_start % initial active power (p.u.) at "to" port (in-service DC lines)
21+
q_fr_start % initial reactive power (p.u.) at "from" port (in-service DC lines)
22+
q_to_start % initial reactive power (p.u.) at "to" port (in-service DC lines)
23+
vm_setpoint_fr % from bus voltage magnitude setpoint (p.u.) (in-service DC lines)
24+
vm_setpoint_to % to bus voltage magnitude setpoint (p.u.) (in-service DC lines)
25+
p_fr_lb % p.u. lower bound on active power flow at "from" port (in-service DC lines)
26+
p_fr_ub % p.u. upper bound on active power flow at "from" port (in-service DC lines)
27+
q_fr_lb % p.u. lower bound on reactive power flow at "from" port (in-service DC lines)
28+
q_fr_ub % p.u. upper bound on reactive power flow at "from" port (in-service DC lines)
29+
q_to_lb % p.u. lower bound on reactive power flow at "to" port (in-service DC lines)
30+
q_to_ub % p.u. upper bound on reactive power flow at "to" port (in-service DC lines)
31+
end %% properties
32+
33+
methods
34+
function name = name(obj)
35+
%
36+
name = 'legacy_dcline';
37+
end
38+
39+
function label = label(obj)
40+
%
41+
label = 'DC Line';
42+
end
43+
44+
function label = labels(obj)
45+
%
46+
label = 'DC Lines';
47+
end
48+
49+
function name = cxn_type(obj)
50+
%
51+
name = 'bus';
52+
end
53+
54+
function name = cxn_idx_prop(obj)
55+
%
56+
name = {'fbus', 'tbus'};
57+
end
58+
59+
function names = main_table_var_names(obj)
60+
%
61+
names = horzcat( [email protected]_element(obj), ...
62+
{'bus_fr', 'bus_to', 'loss0', 'loss1', ...
63+
'vm_setpoint_fr', 'vm_setpoint_to', ...
64+
'p_fr_lb', 'p_fr_ub', ...
65+
'q_fr_lb', 'q_fr_ub', 'q_to_lb', 'q_to_ub', ...
66+
'p_fr', 'q_fr', 'p_to', 'q_to'} );
67+
end
68+
69+
function vars = export_vars(obj)
70+
%
71+
vars = {'p_fr', 'q_fr', 'p_to', 'q_to'};
72+
end
73+
74+
function s = export_vars_offline_val(obj)
75+
%
76+
77+
s = [email protected]_element(obj); %% call parent
78+
s.p_fr = 0;
79+
s.q_fr = 0;
80+
s.p_to = 0;
81+
s.q_to = 0;
82+
end
83+
84+
function TorF = have_cost(obj)
85+
%
86+
TorF = 0;
87+
end
88+
89+
function obj = initialize(obj, dm)
90+
%
91+
[email protected]_element(obj, dm); %% call parent
92+
93+
%% get bus mapping info
94+
b2i = dm.elements.bus.ID2i; %% bus num to idx mapping
95+
96+
%% set bus index vectors for port connectivity
97+
obj.fbus = b2i(obj.tab.bus_fr);
98+
obj.tbus = b2i(obj.tab.bus_to);
99+
end
100+
101+
function obj = update_status(obj, dm)
102+
%
103+
104+
%% get bus status info
105+
bus_dme = dm.elements.bus;
106+
bs = bus_dme.tab.status; %% bus status
107+
108+
%% update status of branches connected to isolated/offline buses
109+
obj.tab.status = obj.tab.status & bs(obj.fbus) & ...
110+
bs(obj.tbus);
111+
112+
%% call parent to fill in on/off
113+
[email protected]_element(obj, dm);
114+
115+
%% for all online DC lines ...
116+
%% ... set terminal buses (except ref) to PV type
117+
idx = [obj.fbus(obj.on); obj.tbus(obj.on)]; %% all terminal buses
118+
idx(bus_dme.type(idx) == mp.NODE_TYPE.REF) = []; %% except ref
119+
bus_dme.set_bus_type_pv(dm, idx);
120+
121+
%% set bus_dme.vm_control
122+
obj.fbus_on = bus_dme.i2on(obj.fbus(obj.on));
123+
obj.tbus_on = bus_dme.i2on(obj.tbus(obj.on));
124+
bus_dme.vm_control(obj.fbus_on) = 1;
125+
bus_dme.vm_control(obj.tbus_on) = 1;
126+
end
127+
128+
function obj = apply_vm_setpoints(obj, dm)
129+
%
130+
131+
% set starting bus voltage, if bus is voltage-controlled
132+
bus_dme = dm.elements.bus;
133+
i_fr = find(bus_dme.vm_control(obj.fbus_on));
134+
i_to = find(bus_dme.vm_control(obj.tbus_on));
135+
bus_dme.vm_start(obj.fbus_on(i_fr)) = obj.vm_setpoint_fr(i_fr);
136+
bus_dme.vm_start(obj.tbus_on(i_to)) = obj.vm_setpoint_to(i_to);
137+
end
138+
139+
function obj = build_params(obj, dm)
140+
%
141+
obj.loss0 = obj.tab.loss0(obj.on) / dm.base_mva;
142+
obj.loss1 = obj.tab.loss1(obj.on);
143+
obj.p_fr_start = obj.tab.p_fr(obj.on) / dm.base_mva;
144+
obj.p_to_start = (obj.loss1 - 1) .* obj.p_fr_start + obj.loss0;
145+
obj.q_fr_start = -obj.tab.q_fr(obj.on) / dm.base_mva;
146+
obj.q_to_start = -obj.tab.q_to(obj.on) / dm.base_mva;
147+
obj.vm_setpoint_fr = obj.tab.vm_setpoint_fr(obj.on);
148+
obj.vm_setpoint_to = obj.tab.vm_setpoint_to(obj.on);
149+
obj.p_fr_lb = obj.tab.p_fr_lb(obj.on) / dm.base_mva;
150+
obj.p_fr_ub = obj.tab.p_fr_ub(obj.on) / dm.base_mva;
151+
obj.q_fr_lb = obj.tab.q_fr_lb(obj.on) / dm.base_mva;
152+
obj.q_fr_ub = obj.tab.q_fr_ub(obj.on) / dm.base_mva;
153+
obj.q_to_lb = obj.tab.q_to_lb(obj.on) / dm.base_mva;
154+
obj.q_to_ub = obj.tab.q_to_ub(obj.on) / dm.base_mva;
155+
156+
obj.apply_vm_setpoints(dm);
157+
end
158+
159+
function TorF = pp_have_section_sum(obj, mpopt, pp_args)
160+
%
161+
TorF = true;
162+
end
163+
164+
function obj = pp_data_sum(obj, dm, rows, out_e, mpopt, fd, pp_args)
165+
%
166+
167+
%% call parent
168+
[email protected]_element(obj, dm, rows, out_e, mpopt, fd, pp_args);
169+
170+
%% print DC line summary
171+
fprintf(fd, ' %-29s %12.2f MW', 'Total DC line losses', ...
172+
sum(obj.tab.p_fr(obj.on)) - sum(obj.tab.p_to(obj.on)) );
173+
if mpopt.model(1) ~= 'D' %% AC model
174+
fprintf(fd, ' %12.2f MVAr', ...
175+
sum(obj.tab.q_fr(obj.on)) + sum(obj.tab.q_to(obj.on)) );
176+
end
177+
fprintf(fd, '\n');
178+
end
179+
180+
function h = pp_get_headers_det(obj, dm, out_e, mpopt, pp_args)
181+
%
182+
h = [ [email protected]_element(obj, dm, out_e, mpopt, pp_args) ...
183+
{ ' DC Line From To Power Flow (MW) Loss Reactive Inj (MVAr)', ...
184+
' ID Bus ID Bus ID Status From To (MW) From To', ...
185+
'-------- -------- -------- ------ -------- -------- -------- -------- --------' } ];
186+
%% 1234567 123456789 123456789 -----1 1234567.90 123456.89 123456.89 123456.89 123456.89
187+
end
188+
189+
function TorF = pp_have_section_det(obj, mpopt, pp_args)
190+
%
191+
TorF = true;
192+
end
193+
194+
function str = pp_data_row_det(obj, dm, k, out_e, mpopt, fd, pp_args)
195+
%
196+
str = sprintf('%7d %9d %9d %6d %10.2f %9.2f %9.2f %9.2f %9.2f', ...
197+
obj.tab.uid(k), obj.tab.bus_fr(k), obj.tab.bus_to(k), ...
198+
obj.tab.status(k), ...
199+
obj.tab.p_fr(k), obj.tab.p_to(k), ...
200+
obj.tab.p_fr(k) - obj.tab.p_to(k), ...
201+
obj.tab.q_fr(k), obj.tab.q_to(k) );
202+
end
203+
end %% methods
204+
end %% classdef

0 commit comments

Comments
 (0)