├── LICENSE
├── README.md
├── container
├── branch_container.m
├── bus_container.m
├── bus_generator.m
├── container.m
└── numbering.m
├── data
├── activsg10000_12706.mat
├── activsg2000_3206.mat
├── activsg70000_88207.mat
├── data3_3.mat
├── data47_46.mat
├── data5_6.mat
├── data5_7.mat
├── data6_11.mat
├── data6_7.mat
├── data84_96.mat
├── data9_9.mat
├── ieee118_186.mat
├── ieee14_20.mat
├── ieee14_20_bad_data.mat
├── ieee300_411.mat
├── ieee30_41.mat
└── pegase1354_1991.mat
├── doc
└── figures
│ ├── generator_chart.svg
│ ├── logo.png
│ ├── modulemg.png
│ ├── modulepf.png
│ ├── modulese.png
│ ├── power_flow_chart.svg
│ └── state_estimation_chart.svg
├── experiments
└── ieee14_20_28-03-19_10-57-38.txt
├── extras
└── matpower_to_matgrid
│ ├── case14.m
│ └── matpower_to_matgrid.m
├── generator.m
├── generator
├── export_info.m
├── export_measurement.m
├── play_set.m
├── play_variance.m
├── rungen.m
├── runplay.m
├── set_produce.m
├── variable_device.m
└── variance_produce.m
├── moldable
├── check_bad_data.m
├── check_maxiter.m
├── check_measurement_set.m
├── check_measurement_variance.m
├── check_observe.m
├── check_start.m
├── load_measurements.m
├── load_power_system.m
├── settings_generator.m
├── settings_power_flow.m
└── settings_state_estimation.m
├── power_flow.m
├── power_flow
├── power_flow_ac
│ ├── decoupled_newton_raphson
│ │ ├── cq_dnr.m
│ │ ├── cv_dnr.m
│ │ ├── decoupled_newton_raphson.m
│ │ └── idx_par2_dnr.m
│ ├── fast_newton_raphson
│ │ ├── cq_fnr.m
│ │ ├── cv_fnr.m
│ │ └── fast_newton_raphson.m
│ ├── gauss_seidel
│ │ ├── gauss_seidel.m
│ │ ├── gs_cq.m
│ │ └── gs_cv.m
│ ├── newton_raphson
│ │ ├── cq.m
│ │ ├── cv.m
│ │ ├── data_jacobian.m
│ │ ├── idx_par1.m
│ │ ├── idx_par2.m
│ │ ├── jacobian11.m
│ │ ├── jacobian12.m
│ │ ├── jacobian21.m
│ │ ├── jacobian22.m
│ │ ├── newton_raphson.m
│ │ └── qv_limits.m
│ ├── processing_acpf.m
│ ├── result_acpf.m
│ └── ybus_ac.m
├── power_flow_dc
│ ├── processing_dcpf.m
│ ├── result_dcpf.m
│ ├── solve_dcpf.m
│ └── ybus_shift_dc.m
└── runpf.m
├── state_estimation.m
├── state_estimation
├── observability
│ ├── bus_branch_matrix.m
│ ├── irrelevant_branches.m
│ ├── observe_dc.m
│ ├── observe_islands.m
│ ├── restore_observability.m
│ └── unobservable_branches.m
├── runse.m
├── state_estimation_ac
│ ├── branch_data_acse.m
│ ├── compose_current.m
│ ├── compose_flow.m
│ ├── compose_injection.m
│ ├── compose_measurement.m
│ ├── compose_voltage.m
│ ├── evaluation_acse.m
│ ├── gauss_newton
│ │ ├── current_acse.m
│ │ ├── current_ph_acse.m
│ │ ├── flow_acse.m
│ │ ├── gauss_newton.m
│ │ ├── gauss_newton_bad_data.m
│ │ ├── gauss_newton_lav.m
│ │ ├── initial_point_acse.m
│ │ ├── injection_acse.m
│ │ └── voltage_acse.m
│ ├── name_unit_acse.m
│ ├── processing_acse.m
│ └── result_acse.m
├── state_estimation_dc
│ ├── error_dcse.m
│ ├── flow_dcse.m
│ ├── injection_dcse.m
│ ├── processing_dcse.m
│ ├── result_dcse.m
│ ├── solve_dcse_bad.m
│ ├── solve_dcse_lav.m
│ ├── solve_dcse_wls.m
│ ├── system_data_dcse.m
│ └── voltage_dcse.m
└── state_estimation_pmu
│ ├── evaluation_pmuse.m
│ ├── measurements_pmuse.m
│ ├── name_unit_bad_data.m
│ ├── name_unit_pmuse.m
│ ├── polar_to_rectangular.m
│ ├── result_pmuse.m
│ ├── solve_pmuse.m
│ ├── solve_pmuse_bad_data.m
│ └── solve_pmuse_lav.m
├── terminal
├── termianl_measurement_se.m
├── terminal_bad_data.m
├── terminal_bus_pf.m
├── terminal_bus_se.m
├── terminal_error_se.m
├── terminal_flow.m
├── terminal_info.m
└── terminal_observability.m
└── utility
├── diary_off.m
├── diary_on.m
├── produce_Abv.m
└── sparseinv
├── Contents.m
├── license.txt
├── sparseinv.c
├── sparseinv.h
├── sparseinv.m
├── sparseinv_install.m
├── sparseinv_mex.c
├── sparseinv_mex.mexw64
└── sparseinv_test.m
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Mirsad Cosovic
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## MATGRID
2 |
3 |
4 |
5 |
6 | MATGRID is an easy-to-use simulation tool for researchers and educators provided as a MATLAB package, with source code released under MIT License. MATGRID is inspired by Matpower and allows a variety of display and manipulation options.
7 |
8 | We have tested and verifed simulation tool using different scenarios to the best of our ability. As a user of this simulation tool, you can help us to improve future versions, we highly appreciate your feedback about any errors, inaccuracies, and bugs. For more information, please visit our [wiki](https://github.com/mcosovic/MATGRID/wiki/MATGRID) site.
9 |
10 | The software package provides the solution of the AC and DC power flow, non-linear and DC state estimation, as well as the state estimation with PMUs, with standalone measurement generator.
11 |
12 |

13 |
14 | MATGRID includes, inter alia, the weighted least-squares and least absolute values state estimation, optimal PMU placement, and bad data processing.
15 |
16 | ### Fast Run Power Flow
17 | ```
18 | runpf('ieee14_20', 'nr', 'main', 'flow');
19 | runpf('ieee14_20', 'dc', 'main', 'flow');
20 | ```
21 |
22 | ### Fast Run State Estimation
23 | ```
24 | runse('ieee118_186', 'nonlinear', 'estimate');
25 | runse('ieee118_186', 'dc', 'estimate');
26 | runse('ieee14_20', 'pmu', 'pmuOptimal', 'estimate');
27 | ```
28 |
29 | ### Changelog
30 | Major changes:
31 | - 2019-04-21 the DC state estimation with observability analysis and bad data processing optimized for large-scale systems
32 | - 2019-04-08 Added the DC observability analysis with identification of observable islands
33 | - 2019-04-03 Added observability analysis (DC state estimation only , beta version, please treat the results with attention)
34 | - 2019-03-28 Added Gauss-Seidel, decoupled Newton-Raphson and fast decoupled Newton-Raphson algorithm
35 | - 2019-03-21 Added least absolute value (LAV) state estimation
36 | - 2019-03-19 Added bad data processing
37 |
--------------------------------------------------------------------------------
/container/branch_container.m:
--------------------------------------------------------------------------------
1 | function [sys] = branch_container(data)
2 |
3 | %--------------------------------------------------------------------------
4 | % Builds the branch data container according to lines and transformers.
5 | %
6 | % According to status, outage branches are removed from outputs variables.
7 | % Using a unified branch model, for transmission lines tap ratio magnitude
8 | % is equal to one, while the phase shift angle is equal to zero, also,
9 | % shift angle is equal to zero for in-phase transformers. Further, branch
10 | % charging susceptances for in-phase and phase-shifting transformers are
11 | % zeros. Finally, preprocessing time is initialized here.
12 | %--------------------------------------------------------------------------
13 | % Input:
14 | % - data: input power system data that contains lines and/or transformers
15 | %
16 | % Outputs:
17 | % - sys.Nbr: number of branches
18 | % - sys.branch with columns:
19 | % (1)branch number; (2)indexes from bus(i); (3)indexes to bus(j);
20 | % (4)branch resistance(rij); (5)branch reactance(xij);
21 | % (6)branch charging susceptance(bsi); (7)tap ratio magnitude(tij);
22 | % (8)phase shift angle(fij)
23 | %--------------------------------------------------------------------------
24 | % Created by Mirsad Cosovic on 2018-06-05
25 | % Last revision by Mirsad Cosovic on 2019-03-27
26 | % MATGRID is released under MIT License.
27 | %--------------------------------------------------------------------------
28 |
29 |
30 | %-------------------------Transmission Line Data---------------------------
31 | tic
32 | if isfield(data, 'line')
33 | status = logical(data.line(:,6));
34 | Nli = nnz(status);
35 |
36 | Li = [data.line(status,1:5) ones(Nli,1) zeros(Nli,1)];
37 | else
38 | Li = [];
39 | Nli = 0;
40 | end
41 | %--------------------------------------------------------------------------
42 |
43 |
44 | %------------------------In-Phase Transformer Data-------------------------
45 | if isfield(data, 'inTransformer')
46 | status = logical(data.inTransformer(:,7));
47 | Ntri = nnz(status);
48 | Tri = [data.inTransformer(status,1:6) zeros(Ntri,1)];
49 | else
50 | Tri = [];
51 | Ntri = 0;
52 | end
53 | %--------------------------------------------------------------------------
54 |
55 |
56 | %---------------------Phase-Shifting Transformer Data----------------------
57 | if isfield(data, 'shiftTransformer')
58 | status = logical(data.shiftTransformer(:,8));
59 | Ntrp = nnz(status);
60 | Trp = data.shiftTransformer(status,1:7);
61 | else
62 | Trp = [];
63 | Ntrp = 0;
64 | end
65 | %--------------------------------------------------------------------------
66 |
67 |
68 | %-------------------------------Branch Data--------------------------------
69 | sys.Nbr = Nli + Ntri + Ntrp;
70 | sys.branch = [(1:sys.Nbr)' [Li; Tri; Trp]];
71 |
72 | sys.branch(:,8) = pi/180 * sys.branch(:,8);
73 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/container/bus_container.m:
--------------------------------------------------------------------------------
1 | function [sys] = bus_container(data, stop, sys)
2 |
3 | %--------------------------------------------------------------------------
4 | % Builds the bus and generator data containers according to inputs.
5 | %
6 | % According to status, outage generators are removed from outputs
7 | % variables. If generator data does not exist, the sys.bus variable
8 | % automatically expands with zeros (see bus_generator function). Further,
9 | % all corresponding values are normalized to per-unit system.
10 | %--------------------------------------------------------------------------
11 | % Inputs:
12 | % - data: input power system data that contains buses and/or generators
13 | % - stop: stopping iteration criteria for the non-linear algorithms
14 | % - sys: power system data
15 | %
16 | % Outputs:
17 | % - sys.base: power system base power in (MVA)
18 | % - sys.stop: stopping iteration criteria for the non-linear algorithms
19 | % - sys.sck: slack bus variable with bus number and voltage angle value
20 | % - sys.bus with columns:
21 | % (1)bus(i); (2)bus type; (3)initial voltage magnitude(Vo);
22 | % (4)initial voltage angle(To); (5)load active power(Pl);
23 | % (6)load reactive power(Ql); (7)shunt resistance(rsh);
24 | % (8)shunt reactance(xsh); (9)bus voltage limit(Vmin);
25 | % (10)bus voltage limit(Vmax)
26 | % - sys.generator with columns:
27 | % (1)bus(i); (2)generator active power(Pg);
28 | % (3)generator reactive power(Qg); (4)bus reactive power limit(Qmin);
29 | % (5)bus reactive power limit(Qmax)
30 | %--------------------------------------------------------------------------
31 | % Created by Mirsad Cosovic on 2018-06-05
32 | % Last revision by Mirsad Cosovic on 2019-03-27
33 | % MATGRID is released under MIT License.
34 | %--------------------------------------------------------------------------
35 |
36 |
37 | %--------------------------------Bus Data----------------------------------
38 | sys.bus = data.bus;
39 | sys.Nbu = size(data.bus,1);
40 |
41 | sys.bus(:,5:8) = sys.bus(:,5:8) ./ data.baseMVA;
42 | sys.bus(:,4) = pi/180 * sys.bus(:,4);
43 | %--------------------------------------------------------------------------
44 |
45 |
46 | %-----------------------------Generator Data-------------------------------
47 | if isfield(data, 'generator')
48 | status = logical(data.generator(:,7));
49 |
50 | sys.generator = data.generator(status,:);
51 | sys.generator(:,2:5) = sys.generator(:,2:5) ./ data.baseMVA;
52 | else
53 | sys.bus(:,11:14) = zeros(sys.Nbu,4);
54 | end
55 | %--------------------------------------------------------------------------
56 |
57 |
58 | %--------------------------------Slack Bus---------------------------------
59 | sys.sck = find(sys.bus(:,2) == 3);
60 | sys.sck = [sys.sck sys.bus(sys.sck,4)];
61 | %--------------------------------------------------------------------------
62 |
63 |
64 | %--------------------------------User Data---------------------------------
65 | sys.base = data.baseMVA;
66 | sys.stop = stop;
67 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/container/bus_generator.m:
--------------------------------------------------------------------------------
1 | function [sys] = bus_generator(sys)
2 |
3 | %--------------------------------------------------------------------------
4 | % Expands sys.bus variable with generators data.
5 | %
6 | % If there are more generators on the one bus, it is first necessary to sum
7 | % up active and reactive powers of generators, also for generator buses the
8 | % voltage magnitude is given. Finally, if corresponding bus is PV type, and
9 | % generators are disconnected, we change that bus to PQ. Ultimately the
10 | % generator data is added to sys.bus variable.
11 | %--------------------------------------------------------------------------
12 | % Input:
13 | % - sys: power system data
14 | %
15 | % Outputs:
16 | % - sys.bus with additional or changed columns:
17 | % (3)initial voltage magnitude(Vo);
18 | % (11)generator active power(Pg); (12)generator reactive power(Qg);
19 | % (13)bus reactive power limit(Qmin);
20 | % (14)bus reactive power limit(Qmax)
21 | %--------------------------------------------------------------------------
22 | % Created by Mirsad Cosovic on 2018-06-05
23 | % Last revision by Mirsad Cosovic on 2019-03-27
24 | % MATGRID is released under MIT License.
25 | %--------------------------------------------------------------------------
26 |
27 |
28 | %---------------------------Generation per Bus-----------------------------
29 | if isfield(sys, 'generator')
30 | Nge = size(sys.generator,1);
31 | A = sparse(sys.generator(:,1), (1:Nge)', 1, sys.Nbu, Nge);
32 |
33 | sys.bus(:,11) = A * sys.generator(:,2);
34 | sys.bus(:,12) = A * sys.generator(:,3);
35 | sys.bus(:,13) = A * sys.generator(:,4);
36 | sys.bus(:,14) = A * sys.generator(:,5);
37 |
38 | sys.bus(sys.generator(:,1),3) = sys.generator(:,6);
39 |
40 | sys.bus(:,2) = 1;
41 | sys.bus(sys.generator(:,1),2) = 2;
42 | sys.bus(sys.sck(1),2) = 3;
43 | end
44 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/container/container.m:
--------------------------------------------------------------------------------
1 | function [sys] = container(data)
2 |
3 | %--------------------------------------------------------------------------
4 | % Builds data containers.
5 | %
6 | % The function builds the branch, bus and generator data containers, and
7 | % defines the new numbering for buses and branches.
8 | %--------------------------------------------------------------------------
9 | % Input:
10 | % - data: power system data
11 | %
12 | % Outputs:
13 | % - sys.branch with columns:
14 | % (1)branch number; (2)indexes from bus(i); (3)indexes to bus(j);
15 | % (4)branch resistance(rij); (5)branch reactance(xij);
16 | % (6)charging susceptance(bsi); (7)tap ratio magnitude(tij);
17 | % (8)phase shift angle(fij); (9)original indexes from bus;
18 | % (10)original indexes to bus
19 | % - sys.bus with columns:
20 | % (1)bus(i); (2)bus type; (3)initial voltage magnitude(Vo);
21 | % (4)initial voltage angle(To); (5)load active power(Pl);
22 | % (6)load reactive power(Ql); (7)shunt resistance(rsh);
23 | % (8)shunt reactance(xsh); (9)bus voltage limit(Vmin);
24 | % (10)bus voltage limit(Vmax); (11)generator active power(Pg);
25 | % (12)generator reactive power(Qg); (13)bus reactive power limit(Qmin);
26 | % (14)bus reactive power limit(Qmax); (15)original bus numeration;
27 | % - sys.Nbr: number of branches
28 | % - sys.Nbu: number of buses
29 | % - sys.sck: slack bus variable with bus number and voltage angle value
30 | % - sys.base: power system base power in (MVA)
31 | % - sys.stop: stopping iteration criteria
32 | %--------------------------------------------------------------------------
33 | % Created by Mirsad Cosovic on 2018-06-05
34 | % Last revision by Mirsad Cosovic on 2019-03-27
35 | % MATGRID is released under MIT License.
36 | %--------------------------------------------------------------------------
37 |
38 |
39 | %----------------------------Power System Data-----------------------------
40 | [sys] = branch_container(data.system);
41 | [sys] = bus_container(data.system, data.stop, sys);
42 | [sys] = numbering(data.system, sys);
43 | [sys] = bus_generator(sys);
44 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/container/numbering.m:
--------------------------------------------------------------------------------
1 | function [sys] = numbering(data, sys)
2 |
3 | %--------------------------------------------------------------------------
4 | % Builds the new numbering for buses and branches, only if bus numbering
5 | % does not hold adequate form.
6 | %
7 | % The bus numbering is defined in form 1,2,...,sys.Nbu, and according to
8 | % it, we also define the new branch numbering. The new numbering is
9 | % reflected on sys.bus(:,1), sys.branch(:,2:3) and sys.generator(:,1).
10 | %--------------------------------------------------------------------------
11 | % Inputs:
12 | % - data: power system data
13 | % - sys: power system data
14 | %
15 | % Outputs:
16 | % - sys.bus with additional or changed columns:
17 | % (1)new bus(i); (15)original bus numeration(i)
18 | % - sys.branch with additional or changed columns:
19 | % (2)new indexes from bus(i); (3)new indexes to bus(j)
20 | % (9)original indexes from bus(i); (10)original indexes to bus(j)
21 | % - sys.generator with additional or changed columns:
22 | % (1)new bus(i)
23 | %--------------------------------------------------------------------------
24 | % Created by Mirsad Cosovic on 2018-06-05
25 | % Last revision by Mirsad Cosovic on 2019-03-27
26 | % MATGRID is released under MIT License.
27 | %--------------------------------------------------------------------------
28 |
29 |
30 | %---------------------------Original Numbering-----------------------------
31 | sys.branch(:,9:10) = [sys.branch(:,2) sys.branch(:,3)];
32 | sys.bus(:,15) = sys.bus(:,1);
33 | %--------------------------------------------------------------------------
34 |
35 |
36 | %------------------------------New Numbering-------------------------------
37 | bus = (1:sys.Nbu)';
38 |
39 | if max(bus ~= sys.bus(:,1)) == 1
40 | [~, b] = ismember(sys.branch(:,2), sys.bus(:,1));
41 | sys.branch(:,2) = bus(b);
42 |
43 | [~, b] = ismember(sys.branch(:,3), sys.bus(:,1));
44 | sys.branch(:,3) = bus(b);
45 |
46 | if isfield(data, 'generator')
47 | [~, b] = ismember(sys.generator(:,1), sys.bus(:,1));
48 | sys.generator(:,1) = bus(b);
49 | end
50 |
51 | sys.bus(:,1) = bus;
52 | end
53 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/data/activsg10000_12706.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/data/activsg10000_12706.mat
--------------------------------------------------------------------------------
/data/activsg2000_3206.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/data/activsg2000_3206.mat
--------------------------------------------------------------------------------
/data/activsg70000_88207.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/data/activsg70000_88207.mat
--------------------------------------------------------------------------------
/data/data3_3.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/data/data3_3.mat
--------------------------------------------------------------------------------
/data/data47_46.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/data/data47_46.mat
--------------------------------------------------------------------------------
/data/data5_6.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/data/data5_6.mat
--------------------------------------------------------------------------------
/data/data5_7.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/data/data5_7.mat
--------------------------------------------------------------------------------
/data/data6_11.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/data/data6_11.mat
--------------------------------------------------------------------------------
/data/data6_7.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/data/data6_7.mat
--------------------------------------------------------------------------------
/data/data84_96.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/data/data84_96.mat
--------------------------------------------------------------------------------
/data/data9_9.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/data/data9_9.mat
--------------------------------------------------------------------------------
/data/ieee118_186.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/data/ieee118_186.mat
--------------------------------------------------------------------------------
/data/ieee14_20.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/data/ieee14_20.mat
--------------------------------------------------------------------------------
/data/ieee14_20_bad_data.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/data/ieee14_20_bad_data.mat
--------------------------------------------------------------------------------
/data/ieee300_411.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/data/ieee300_411.mat
--------------------------------------------------------------------------------
/data/ieee30_41.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/data/ieee30_41.mat
--------------------------------------------------------------------------------
/data/pegase1354_1991.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/data/pegase1354_1991.mat
--------------------------------------------------------------------------------
/doc/figures/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/doc/figures/logo.png
--------------------------------------------------------------------------------
/doc/figures/modulemg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/doc/figures/modulemg.png
--------------------------------------------------------------------------------
/doc/figures/modulepf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/doc/figures/modulepf.png
--------------------------------------------------------------------------------
/doc/figures/modulese.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/doc/figures/modulese.png
--------------------------------------------------------------------------------
/extras/matpower_to_matgrid/matpower_to_matgrid.m:
--------------------------------------------------------------------------------
1 | clc
2 | clearvars
3 |
4 | %--------------------------------------------------------------------------
5 | % Builds the power system data from Matpower case format Version 2.
6 | %
7 | % Load Matpower test case as the variable 'mpc' (see line 21), where
8 | % Matpower m.file is in the same directory as this function.
9 | %--------------------------------------------------------------------------
10 | % Input:
11 | % - load Matpower test case
12 | %
13 | % Output:
14 | % - data: power system data compatible with the package
15 | %--------------------------------------------------------------------------
16 | % Created by Mirsad Cosovic on 2019-02-14
17 | % Last revision by Mirsad Cosovic on 2019-03-27
18 | % MATGRID is released under MIT License.
19 | %--------------------------------------------------------------------------
20 |
21 |
22 | %---------------------------Load Matpower Case-----------------------------
23 | mpc = case14;
24 | %--------------------------------------------------------------------------
25 |
26 |
27 | %-------------------------------Description--------------------------------
28 | data.case = 'case';
29 | data.reference = 'reference';
30 | data.grid = 'Transmission';
31 | %--------------------------------------------------------------------------
32 |
33 |
34 | %--------------------------------Bus Data----------------------------------
35 | data.system.bus = [mpc.bus(:,1:2) mpc.bus(:,8:9) mpc.bus(:,3:4) ...
36 | mpc.bus(:,5:6) mpc.bus(:,13) mpc.bus(:,12)];
37 | %--------------------------------------------------------------------------
38 |
39 |
40 | %-----------------------------Generator Data-------------------------------
41 | data.system.generator = [mpc.gen(:,1:3) mpc.gen(:,5) mpc.gen(:,4) ...
42 | mpc.gen(:,6) mpc.gen(:,8)];
43 | %--------------------------------------------------------------------------
44 |
45 |
46 | %--------------------------------Line Data---------------------------------
47 | idxl = mpc.branch(:,9) == 0 & mpc.branch(:,10) == 0;
48 | data.system.line = [mpc.branch(idxl,1:5) mpc.branch(idxl,11)];
49 | %--------------------------------------------------------------------------
50 |
51 |
52 | %------------------------In-Phase Transformer Data-------------------------
53 | idxit = mpc.branch(:,9) ~= 0 & mpc.branch(:,10) == 0;
54 | data.system.inTransformer = [mpc.branch(idxit,1:5) ...
55 | mpc.branch(idxit,9) mpc.branch(idxit,11)];
56 | %--------------------------------------------------------------------------
57 |
58 |
59 | %---------------------Phase-Shifting Transformer Data----------------------
60 | idxpt = mpc.branch(:,10) ~= 0;
61 | data.system.shiftTransformer = [mpc.branch(idxpt,1:5) ...
62 | mpc.branch(idxpt,9:11)];
63 |
64 | tap = data.system.shiftTransformer(:,6) == 0;
65 | data.system.shiftTransformer(tap,6) = 1;
66 | %--------------------------------------------------------------------------
67 |
68 |
69 | %-------------------------Remove Empty Variables---------------------------
70 | fn = fieldnames(data.system);
71 | tf = cellfun(@(c) isempty(data.system.(c)), fn);
72 | data.system = rmfield(data.system, fn(tf));
73 | %--------------------------------------------------------------------------
74 |
75 |
76 | %---------------Base Power and Iterative Stopping Threshold----------------
77 | data.system.baseMVA = mpc.baseMVA;
78 | data.stop = 10^-8;
79 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/generator/play_set.m:
--------------------------------------------------------------------------------
1 | function [data] = play_set(user, data, sys, msr)
2 |
3 | %--------------------------------------------------------------------------
4 | % Builds measurement data.
5 | %
6 | % The function produces measurement sets according to user inputs and
7 | % options.
8 | %--------------------------------------------------------------------------
9 | % Inputs:
10 | % - user: user inputs
11 | % - data: input power system data
12 | % - sys: power system data
13 | % - msr: measurement data
14 | %
15 | % Outputs
16 | % - data.legacy.flow with changed columns:
17 | % (5)active power flow measurements turn on/off;
18 | % (8)reactive power flow measurement turn on/off;
19 | % - data.legacy.current with changed columns:
20 | % (5)line current magnitude measurement turn on/off;
21 | % - data.legacy.injection with changed columns:
22 | % (4)active power injection measurements turn on/off;
23 | % (7)reactive power injection measurements turn on/off;
24 | % - data.legacy.voltage with changed columns:
25 | % (4)bus voltage magnitude measurements turn on/off;
26 | % - data.pmu.current with changed columns:
27 | % (5)line current magnitude measurements turn on/off;
28 | % (8)line current angle measurements turn on/off;
29 | % - data.pmu.voltage with changed columns:
30 | % (4)bus voltage magnitude measurements turn on/off;
31 | % (7)bus voltage angle measurements turn on/off;
32 | %--------------------------------------------------------------------------
33 | % Created by Mirsad Cosovic on 2019-02-24
34 | % Last revision by Mirsad Cosovic on 2019-03-27
35 | % MATGRID is released under MIT License.
36 | %--------------------------------------------------------------------------
37 |
38 |
39 | %-------------------------Legacy Measurement Set---------------------------
40 | if any(ismember({'legRedundancy', 'legDevice', 'noLegacy'}, user.list))
41 | data.legacy.flow(:,5) = msr.set{1}(1:2*msr.w);
42 | data.legacy.flow(:,8) = msr.set{1}(2*msr.w+1:4*msr.w);
43 | data.legacy.current(:,5) = msr.set{1}(4*msr.w+1:6*msr.w);
44 | data.legacy.injection(:,4) = msr.set{1}(6*msr.w+1:6*msr.w+sys.Nbu);
45 | data.legacy.injection(:,7) = msr.set{1}(6*msr.w+sys.Nbu+1:6*msr.w+2*sys.Nbu);
46 | data.legacy.voltage(:,4) = msr.set{1}(6*msr.w+2*sys.Nbu+1:end);
47 | end
48 | %--------------------------------------------------------------------------
49 |
50 |
51 | %-------------------------Phasor Measurement Set---------------------------
52 | if any(ismember({'pmuRedundancy', 'pmuDevice', 'pmuOptimal', 'noPmu'}, user.list))
53 | data.pmu.current(:,5) = msr.set{2}(1:2*msr.w);
54 | data.pmu.current(:,8) = msr.set{2}(2*msr.w+1:4*msr.w);
55 | data.pmu.voltage(:,4) = msr.set{2}(4*msr.w+1:4*msr.w+sys.Nbu);
56 | data.pmu.voltage(:,7) = msr.set{2}(4*msr.w+sys.Nbu+1:end);
57 | end
58 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/generator/variable_device.m:
--------------------------------------------------------------------------------
1 | function [msr] = variable_device(sys)
2 |
3 | %--------------------------------------------------------------------------
4 | % Builds measurement statistics.
5 | %
6 | % The function forms different variables that are used to generate
7 | % measurements, according to different options.
8 | %--------------------------------------------------------------------------
9 | % Input:
10 | % - sys: power system data
11 | %
12 | % Outputs:
13 | % - msr.w: number of branches
14 | % - msr.state: number of state variables
15 | % - msr.total: total number of legacy and phasor measurements
16 | % - msr.tleg: number of legacy measurements per type
17 | % - msr.tpmu: number of phasor measurements per type
18 | % - msr.dleg: number of legacy measurements per device
19 | % - msr.dpmu: number of phasor measurements per device
20 | % - msr.mred: maximum redundancy for legacy and phasor measurements
21 | %--------------------------------------------------------------------------
22 | % Created by Mirsad Cosovic on 2019-02-24
23 | % Last revision by Mirsad Cosovic on 2019-03-27
24 | % MATGRID is released under MIT License.
25 | %--------------------------------------------------------------------------
26 |
27 |
28 | %-------------------------Measurement Statistics---------------------------
29 | msr.w = sys.Nbr;
30 |
31 | msr.state = 2 * sys.Nbu - 1;
32 | msr.total = [6 * msr.w + 3 * sys.Nbu; 4 * msr.w + 2 * sys.Nbu];
33 | msr.tleg = [2 * msr.w; 2 * msr.w; 2 * msr.w; sys.Nbu; sys.Nbu; sys.Nbu];
34 | msr.tpmu = [2 * msr.w; 2 * msr.w; sys.Nbu; sys.Nbu];
35 | msr.dleg = [2 * msr.w; 2 * msr.w; sys.Nbu; sys.Nbu];
36 | msr.dpmu = sys.Nbu;
37 | msr.mred = msr.total ./ msr.state;
38 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/generator/variance_produce.m:
--------------------------------------------------------------------------------
1 | function [msr] = variance_produce(user, msr)
2 |
3 | %--------------------------------------------------------------------------
4 | % Forms vector of measurement variances.
5 | %
6 | % The function forms measurement variances according to user inputs and
7 | % options.
8 | %--------------------------------------------------------------------------
9 | % Inputs:
10 | % - user: user inputs
11 | % - msr: measurement data
12 | %
13 | % Outputs:
14 | % - msr.var{1}: variances for legacy measurements
15 | % - msr.var{2}: variances for phasor measurements
16 | %--------------------------------------------------------------------------
17 | % Created by Mirsad Cosovic on 2019-02-24
18 | % Last revision by Mirsad Cosovic on 2019-03-27
19 | % MATGRID is released under MIT License.
20 | %--------------------------------------------------------------------------
21 |
22 |
23 | %-----------------------------Unique Variance------------------------------
24 | if ismember('legUnique', user.list)
25 | var = user.legUnique;
26 | msr.var{1} = var * ones(msr.total(1),1);
27 | end
28 |
29 | if ismember('pmuUnique', user.list)
30 | var = user.pmuUnique;
31 | msr.var{2} = var * ones(msr.total(2),1);
32 | end
33 | %--------------------------------------------------------------------------
34 |
35 |
36 | %----------------------------Random Variances------------------------------
37 | if ismember('legRandom', user.list)
38 | std_min = min(user.legRandom);
39 | std_max = max(user.legRandom);
40 | msr.var{1} = std_min + (std_max - std_min) .* rand(msr.total(1),1);
41 | end
42 |
43 | if ismember('pmuRandom', user.list)
44 | std_min = min(user.pmuRandom);
45 | std_max = max(user.pmuRandom);
46 | msr.var{2} = std_min + (std_max - std_min) .* rand(msr.total(2),1);
47 | end
48 | %--------------------------------------------------------------------------
49 |
50 |
51 | %-----------------------------Type Variances-------------------------------
52 | if ismember('legType', user.list)
53 | var = user.legType;
54 | msr.var{1} = repelem(var, msr.tleg,1);
55 | end
56 |
57 | if ismember('pmuType', user.list)
58 | var = user.pmuType;
59 | msr.var{2} = repelem(var, msr.tpmu,1);
60 | end
61 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/moldable/check_bad_data.m:
--------------------------------------------------------------------------------
1 | function [user] = check_bad_data(user)
2 |
3 | %--------------------------------------------------------------------------
4 | % Checks input values for bad data processing.
5 | %
6 | % The function checks values of variable 'bad', given as input arguments of
7 | % the function runse.
8 | %--------------------------------------------------------------------------
9 | % Input:
10 | % - user: user inputs
11 | %
12 | % Outputs:
13 | % - user.badThreshold: bad data identification threshold
14 | % - user.badPass: maximum number of the state estimation algorithm passes
15 | %--------------------------------------------------------------------------
16 | % Created by Mirsad Cosovic on 2019-03-18
17 | % Last revision by Mirsad Cosovic on 2019-03-27
18 | % MATGRID is released under MIT License.
19 | %--------------------------------------------------------------------------
20 |
21 |
22 | %--------------------------Check Bad Data Inputs---------------------------
23 | if ismember('bad', user.list) && ~isempty(user.badSet) && (~isvector(user.badSet) || ~(any(length(user.badSet) == [1 2])))
24 | user.badThreshold = 3;
25 | user.badPass = 10;
26 | warning('se:Threshold', ['The value pair argument of the variable ' ...
27 | '"bad" has invalid type. The algorithm proceeds with default ' ...
28 | 'value: [%1.f %1.f].\n'], 3, 10)
29 | elseif ismember('bad', user.list) && isempty(user.badSet)
30 | user.badThreshold = 3;
31 | user.badPass = 10^60;
32 | elseif ismember('bad', user.list) && length(user.badSet) == 1
33 | user.badThreshold = user.badSet(1);
34 | user.badPass = 10^60;
35 | elseif ismember('bad', user.list) && length(user.badSet) == 2
36 | user.badThreshold = user.badSet(1);
37 | user.badPass = user.badSet(2);
38 | end
39 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/moldable/check_maxiter.m:
--------------------------------------------------------------------------------
1 | function [user] = check_maxiter(user)
2 |
3 | %--------------------------------------------------------------------------
4 | % Checks input values for maximum number of iterations.
5 | %
6 | % The function checks values of variable 'maxIter', given as input
7 | % arguments of the function runpf.
8 | %--------------------------------------------------------------------------
9 | % Input:
10 | % - user: user inputs
11 | %
12 | % Output:
13 | % - user.maxIter: maximum number of iterations
14 | %--------------------------------------------------------------------------
15 | % Created by Mirsad Cosovic on 2019-03-25
16 | % Last revision by Mirsad Cosovic on 2019-03-27
17 | % MATGRID is released under MIT License.
18 | %--------------------------------------------------------------------------
19 |
20 |
21 | %-----------------------Check Number of Iterations-------------------------
22 | if (ismember('maxIter', user.list) && (~isvector(user.maxIter) || ~(length(user.maxIter) == 1) || user.maxIter <= 0)) || ~ismember('maxIter', user.list)
23 | if ismember('nr', user.list)
24 | user.maxIter = 500;
25 | end
26 | if ismember('gs', user.list)
27 | user.maxIter = 500;
28 | end
29 | if ismember('dnr', user.list)
30 | user.maxIter = 500;
31 | end
32 | if ismember('fdnr', user.list)
33 | user.maxIter = 500;
34 | end
35 | if ismember('nonlinear', user.list)
36 | user.maxIter = 500;
37 | end
38 | end
39 | %--------------------------------------------------------------------------
40 |
--------------------------------------------------------------------------------
/moldable/check_observe.m:
--------------------------------------------------------------------------------
1 | function [user] = check_observe(user)
2 |
3 | %--------------------------------------------------------------------------
4 | % Checks input values for the observability analysis.
5 | %
6 | % The function checks values of variable 'observe', given as input
7 | % arguments of the function runse.
8 | %--------------------------------------------------------------------------
9 | % Input:
10 | % - user: user inputs
11 | %
12 | % Output:
13 | % - user.psvar: variance of pseudo-measurements
14 | %--------------------------------------------------------------------------
15 | % Created by Mirsad Cosovic on 2019-04-01
16 | % Last revision by Mirsad Cosovic on 2019-04-17
17 | % MATGRID is released under MIT License.
18 | %--------------------------------------------------------------------------
19 |
20 |
21 | %------------------------Check observability Input-------------------------
22 | if ismember('observe', user.list) && ~isempty(user.psvar) && (~isvector(user.psvar) || ~(any(length(user.psvar) == 1)) || user.psvar <= 0)
23 | user.psvar = 10^6;
24 | warning('se:psvar', ['The value pair argument of the variable ' ...
25 | '"observe" has invalid type. The algorithm proceeds with default ' ...
26 | 'value: %1.e.\n'], 10^6)
27 | elseif ismember('observe', user.list) && isempty(user.psvar)
28 | user.psvar = 10^6;
29 | end
30 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/moldable/check_start.m:
--------------------------------------------------------------------------------
1 | function [user] = check_start(user)
2 |
3 | %--------------------------------------------------------------------------
4 | % Checks input values for the Gasuss-Newton method start.
5 | %
6 | % The function checks initialization values of variables 'flat', 'random',
7 | % given as input arguments of the function runse.
8 | %--------------------------------------------------------------------------
9 | % Input:
10 | % - user: user inputs
11 | %
12 | % Outputs:
13 | % - user.flat: initial point, flat start
14 | % - user.random: initial point, random perturbation
15 | %--------------------------------------------------------------------------
16 | % Created by Mirsad Cosovic on 2019-03-05
17 | % Last revision by Mirsad Cosovic on 2019-03-27
18 | % MATGRID is released under MIT License.
19 | %--------------------------------------------------------------------------
20 |
21 |
22 | %---------------------------Check Start Inputs-----------------------------
23 | if ismember('flat', user.list) && ~isempty(user.flat) && (~isvector(user.flat) || ~(length(user.flat) == 2))
24 | user.flat = [0 1];
25 | warning('se:startFlat', ['The value pair argument of the variable ' ...
26 | '"flat" has invalid type. The algorithm proceeds with default ' ...
27 | 'value: [%1.f %1.f].\n'], 0,1)
28 | elseif ismember('flat', user.list) && isempty(user.flat)
29 | user.flat = [0 1];
30 | end
31 |
32 | if ismember('random', user.list) && ~isempty(user.random) && (~isvector(user.random) || ~(length(user.random) == 4))
33 | user.random = [-0.5 0.5 0.95 1.05];
34 | warning('se:startFlat', ['The value pair argument of the variable ' ...
35 | '"random" has invalid type. The algorithm proceeds with default ' ...
36 | 'value: [%1.2f %1.2f %1.2f %1.2f].\n'], -0.5,0.5,0.95,1.05)
37 | elseif ismember('random', user.list) && isempty(user.random)
38 | user.random = [-0.5 0.5 0.95 1.05];
39 | end
40 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/moldable/load_measurements.m:
--------------------------------------------------------------------------------
1 | function [data] = load_measurements(user, data)
2 |
3 | %--------------------------------------------------------------------------
4 | % Checks measurement data for the state estimation.
5 | %
6 | % The function checks legacy, pmu, flow, injection, voltages, and currents
7 | % variables defined in the input mat-file. If device type or measurements
8 | % are missing, we add mask variable, which allows to execute a code without
9 | % errors.
10 | %--------------------------------------------------------------------------
11 | % Inputs:
12 | % - user: user inputs
13 | % - data: input power system data with measurements
14 | %
15 | % Output:
16 | % - data: input power system data with measurements
17 | %--------------------------------------------------------------------------
18 | % Created by Mirsad Cosovic on 2019-03-18
19 | % Last revision by Mirsad Cosovic on 2019-03-27
20 | % MATGRID is released under MIT License.
21 | %--------------------------------------------------------------------------
22 |
23 |
24 | %--------------Check Measurements for DC/AC State Estimation---------------
25 | se = isfield(data, {'legacy', 'pmu'});
26 |
27 | if se(1) == 1
28 | leg = isfield(data.legacy, {'flow', 'injection', 'voltage', 'current'});
29 | end
30 | if se(2) == 1
31 | pmu = isfield(data.pmu, {'voltage', 'current'});
32 | end
33 |
34 | if se(1) == 1 && any(leg == 1) || se(2) == 1 && any(pmu == 1)
35 | else
36 | error('data:legacyPmuMissed', 'Invalid measurement data structure, measurements not found.\n')
37 | end
38 | if ismember('dc', user.list) && (se(1) == 0 && all(leg(1:2) == 0) || se(2) == 0 && pmu(1) == 0)
39 | error('data:legacyPmuDC', 'Invalid measurement data structure, measurements not found.\n')
40 | end
41 | %--------------------------------------------------------------------------
42 |
43 |
44 | %----------------------Mask for Missing Measurements-----------------------
45 | if se(1) == 0
46 | data.legacy.flow = zeros(1,11);
47 | data.legacy.injection = zeros(1,11);
48 | data.legacy.voltage = zeros(1,11);
49 | data.legacy.current = zeros(1,11);
50 | end
51 | if se(1) == 1 && leg(1) == 0
52 | data.legacy.flow = zeros(1,11);
53 | end
54 | if se(1) == 1 && leg(2) == 0
55 | data.legacy.injection = zeros(1,11);
56 | end
57 | if se(1) == 1 && leg(3) == 0
58 | data.legacy.voltage = zeros(1,11);
59 | end
60 | if se(1) == 1 && leg(4) == 0
61 | data.legacy.current = zeros(1,11);
62 | end
63 |
64 | if se(2) == 0
65 | data.pmu.current = zeros(1,11);
66 | data.pmu.voltage = zeros(1,11);
67 | end
68 | if se(2) == 1 && pmu(1) == 0
69 | data.pmu.current = zeros(1,11);
70 | end
71 | if se(2) == 1 && pmu(2) == 0
72 | data.pmu.voltage = zeros(1,11);
73 | end
74 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/moldable/load_power_system.m:
--------------------------------------------------------------------------------
1 | function [data] = load_power_system(data, user)
2 |
3 | %--------------------------------------------------------------------------
4 | % Checks load power system data.
5 | %
6 | % The function checks 'baseMVA', 'bus', 'line', 'inTransformer',
7 | % 'shiftTransformer', 'stop' and 'case' variables defined in the input
8 | % mat-file. If variables 'baseMVA', 'stop' and 'case' are missing, the
9 | % function adds default values.
10 | %--------------------------------------------------------------------------
11 | % Inputs:
12 | % - data: load power system data
13 | % - user: user input list
14 | %
15 | % Output:
16 | % - data: power system data
17 | %--------------------------------------------------------------------------
18 | % Created by Mirsad Cosovic on 2019-03-18
19 | % Last revision by Mirsad Cosovic on 2019-03-27
20 | % MATGRID is released under MIT License.
21 | %--------------------------------------------------------------------------
22 |
23 |
24 | %----------------------------Check Power Grid------------------------------
25 | if ~isfield(data, 'system')
26 | error('pg:system', 'Invalid power flow data structure, variable "data.system" not found.\n')
27 | end
28 |
29 | in = isfield(data.system, {'bus', 'line', 'inTransformer', 'shiftTransformer', 'baseMVA'});
30 |
31 | if ~in(1)
32 | error('pg:bus', 'Invalid power flow data structure, variable "data.system.bus" not found.\n')
33 | end
34 | if ~in(2) && ~in(3) && ~in(4)
35 | error('pg:branch', 'Invalid power flow data structure, variables "data.system.line", "data.system.inTransformer" or "data.system.shiftTransformer" not found.\n')
36 | end
37 | if ~in(5)
38 | data.system.baseMVA = 100;
39 | warning('pg:baseMVA','The variable "data.system.baseMVA" not found. The algorithm proceeds with default value: %1.f(MVA). \n', data.system.baseMVA)
40 | end
41 |
42 | if ~isfield(data, 'stop') && any(ismember(user, {'nr', 'gs', 'dnr', 'fdnr'}))
43 | data.stop = 10^-6;
44 | warning('pg:stop','The variable "data.stop" not found. The algorithm proceeds with default value: %1.e.\n', data.stop)
45 | end
46 | if ~isfield(data, 'case')
47 | data.case = 'unknown';
48 | end
49 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/moldable/settings_power_flow.m:
--------------------------------------------------------------------------------
1 | function [data, user] = settings_power_flow(var) %#ok<*STOUT>
2 |
3 | %--------------------------------------------------------------------------
4 | % Checks user inputs and if those are missing, adds default values and
5 | % loads power system data
6 | %
7 | % The function checks 'ac', 'dc', 'gs', 'dnr', 'fdnr', 'reactive',
8 | % 'voltage', 'maxIter', 'main', 'flow' and 'save' variables given as input
9 | % arguments of the function runpf, and loads power system data according to
10 | % the grid variable. Default inputs are: 'ieee30_41'; 'ac'.
11 | %--------------------------------------------------------------------------
12 | % Input:
13 | % - var: native user input arguments
14 | %
15 | % Outputs:
16 | % - data: load power system data
17 | % - user: user settings
18 | %--------------------------------------------------------------------------
19 | % Created by Mirsad Cosovic on 2019-02-18
20 | % Last revision by Mirsad Cosovic on 2019-03-27
21 | % MATGRID is released under MIT License.
22 | %--------------------------------------------------------------------------
23 |
24 |
25 | %---------------------------------Inputs-----------------------------------
26 | var = cellfun(@num2str, var, 'un', 0);
27 | %--------------------------------------------------------------------------
28 |
29 |
30 | %-------------------------------Empty Input--------------------------------
31 | if isempty(var)
32 | var{1} = 'ieee30_41';
33 | warning('pf:empty', ['Invalid input data structure. The algorithm '...
34 | 'proceeds with %s power system.\n'], strcat(var{1},'.mat'))
35 | end
36 | var = string([var, ' ']);
37 | %--------------------------------------------------------------------------
38 |
39 |
40 | %-----------------Check AC or DC and Power Flow Algorithm------------------
41 | in = ismember(var, {'nr', 'gs', 'dnr', 'fdnr', 'dc'});
42 | pf = var(find(in, 1, 'first'));
43 |
44 | if isempty(pf)
45 | pf = 'nr';
46 | warning('pf:module', ['The power flow requires at least "nr" or ' ...
47 | '"dc" input arguments for the AC or DC power flow analysis. '...
48 | 'The algorithm proceeds with the AC power flow.\n'])
49 | end
50 | %--------------------------------------------------------------------------
51 |
52 |
53 | %---------------------------Check Limit Inputs-----------------------------
54 | in = ismember(var, {'reactive', 'voltage'});
55 | cs = var(find(in, 1, 'first'));
56 | %--------------------------------------------------------------------------
57 |
58 |
59 | %---------------------Check Terminal and Save Inputs-----------------------
60 | in = ismember(var, {'main', 'flow', 'save'});
61 | tr = var(in);
62 | %--------------------------------------------------------------------------
63 |
64 |
65 | %-----------------------Check Number of Iterations-------------------------
66 | in = ismember(var, 'maxIter');
67 | v1 = find(in);
68 | it = var(v1);
69 |
70 | if strcmp(it, 'maxIter')
71 | user.maxIter = round(str2num(var(v1+1)));
72 | end
73 | %--------------------------------------------------------------------------
74 |
75 |
76 | %--------------------------------Load Data---------------------------------
77 | try
78 | gd = strcat(var{1},'.mat');
79 | load(gd, '-mat', 'data')
80 | catch
81 | error('pf:gridLoad', 'The power system data "%s" not found.\n', gd)
82 | end
83 | %--------------------------------------------------------------------------
84 |
85 |
86 | %------------------------------User Settings-------------------------------
87 | user.list = [pf, cs, tr, it, gd];
88 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow.m:
--------------------------------------------------------------------------------
1 | clc
2 | clearvars
3 |
4 | %--------------------------------------------------------------------------
5 | % Runs the AC or DC power flow analysis.
6 | %
7 | % The AC power flow routine by default uses the Newton-Raphson Algorithm,
8 | % where reactive power and voltage magnitudes constraints can be used, and
9 | % only one constraint can be used for one simulation run. Additional
10 | % algorithms that can be used are: Gauss-Seidel, decoupled Newton-Raphson,
11 | % and fast decoupled Newton-Raphson (version BX) algorithm.
12 | %
13 | % Examples:
14 | % runpf('ieee14_20', 'nr', 'main');
15 | % runpf('ieee14_20', 'nr', 'maxIter', 100, 'main');
16 | % runpf('ieee14_20', 'dnr', 'reactive', 'main');
17 | % runpf('ieee14_20', 'fdnr', 'voltage', 'main');
18 | % runpf('ieee14_20', 'dc', 'main', 'flow' 'save');
19 | %--------------------------------------------------------------------------
20 | % Syntax:
21 | % runpf(DATA, METHOD)
22 | % runpf(DATA, METHOD, LIMIT)
23 | % runpf(DATA, METHOD, LIMIT, ATTACH)
24 | % runpf(DATA, METHOD, LIMIT, ATTACH, DISPLAY, EXPORT)
25 | %
26 | % Description:
27 | % - runpf(DATA, METHOD) computes power flow problem
28 | % - runpf(DATA, METHOD, LIMIT) considering constraints
29 | % - runpf(DATA, METHOD, LIMIT, ATTACH) maximum number of iterations
30 | % - runpf(DATA, METHOD, LIMIT, ATTACH, DISPLAY, EXPORT) allows to show
31 | % results and export models
32 | %
33 | % Input Arguments:
34 | % - DATA: the first input argument in the runpf function must contain
35 | % a name of the mat-file that contains power system data
36 | % - METHOD:
37 | % - 'nr': AC power flow analysis using Newton-Raphson algorithm
38 | % - 'gs': AC power flow analysis using Gauss-Seidel algorithm
39 | % - 'dnr': AC power flow analysis using decoupled
40 | % Newton-Raphson algorithm
41 | % - 'fdnr': AC power flow analysis using fast decoupled
42 | % Newton-Raphson algorithm (version BX)
43 | % - 'dc': DC power flow analysis
44 | % - LIMIT
45 | % - 'reactive': forces reactive power constraints
46 | % - 'voltage': forces voltage magnitude constraints
47 | % - ATTACH
48 | % - 'maxIter', X: AC power flow maximum number of iterations(X)
49 | % - DISPLAY
50 | % - 'main': main bus data display
51 | % - 'flow': power flow data display
52 | % - EXPORT
53 | % - 'save': save data display
54 | %
55 | % Although the syntax is given in a certain order, for methodological
56 | % reasons, only DATA must appear as the first input argument, and the order
57 | % of other inputs is arbitrary, as well as their appearance.
58 | %--------------------------------------------------------------------------
59 | % Outputs:
60 | % - result: power flow results
61 | % - data: input power system data
62 | %--------------------------------------------------------------------------
63 |
64 |
65 | %---------------------------Generate Path Name-----------------------------
66 | addpath(genpath(fileparts(which(mfilename))));
67 | %--------------------------------------------------------------------------
68 |
69 |
70 | %---------------------------Power Flow Analysis----------------------------
71 | [result, data] = runpf('ieee118_186', 'nr', 'main', 'flow', 'voltage');
72 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_ac/decoupled_newton_raphson/cq_dnr.m:
--------------------------------------------------------------------------------
1 | function [sys, alg, idx, pf, V, T, Qgl] = cq_dnr(sys, alg, idx, pf, V, T, Qgl, Vc, Pgl)
2 |
3 | %--------------------------------------------------------------------------
4 | % Checks the bus reactive power constraints.
5 | %
6 | % If constraint Qmin or Qmax is violated, the type of buses is changed from
7 | % PV bus to PQ bus, and then a generator has the new reactive power, where
8 | % we compute a new complex voltage for the bus where reactive power is
9 | % violated. The function saves a bus number when the constraint is
10 | % violated.
11 | %--------------------------------------------------------------------------
12 | % Inputs:
13 | % - sys: power system data
14 | % - alg: algorithm data
15 | % - idx: indexes data
16 | % - pf: power flow data
17 | % - V, T: bus voltage magnitude and angle vector
18 | % - Qgl: reactive power at bus
19 | % - Vc: complex bus voltages
20 | % - Pgl: active power at bus
21 | %
22 | % Outputs:
23 | % - sys.bus with changed columns:
24 | % (2)bus type; (12)generator reactive power(Qg);
25 | % - sys.Qcon with changed column: (3)limit on/off;
26 | % - pf.alg: algorithm data
27 | % - idx: indexes data
28 | % - pf.limit with columns:
29 | % (1)bus indicator where minimum limits violated;
30 | % (2)bus indicator where maximum limits violated;
31 | % - V, T: bus voltage magnitude and angle vector
32 | % - Qgl: generator reactive power at bus
33 | %--------------------------------------------------------------------------
34 | % Created by Mirsad Cosovic on 2019-03-25
35 | % Last revision by Mirsad Cosovic on 2019-03-27
36 | % MATGRID is released under MIT License.
37 | %--------------------------------------------------------------------------
38 |
39 |
40 | %--------------------Check Reactive Power Constraints----------------------
41 | Q = -imag(conj(Vc) .* (sys.Ybu * Vc));
42 | mnq = find(Q < sys.Qcon(:,1) & sys.Qcon(:,3) == 1);
43 | mxq = find(Q > sys.Qcon(:,2) & sys.Qcon(:,3) == 1);
44 | %--------------------------------------------------------------------------
45 |
46 |
47 | %-------------------------------Check Qmin---------------------------------
48 | if ~isempty(mnq)
49 | sys.bus(mnq,2) = 1;
50 | sys.Qcon(mnq,3) = 0;
51 |
52 | sys.bus(mnq,12) = sys.Qcon(mnq,1) + sys.bus(mnq,6);
53 |
54 | diago = sub2ind(size(sys.Ybu), mnq, mnq);
55 | Vc(mnq) = (1 ./ sys.Ybu(diago)) .* ((Pgl(mnq) - 1i * ...
56 | sys.Qcon(mnq,1)) ./ conj(Vc(mnq)) - sys.Yij(mnq,:) * Vc);
57 | end
58 | %--------------------------------------------------------------------------
59 |
60 |
61 | %-------------------------------Check Qmax---------------------------------
62 | if ~isempty(mxq)
63 | sys.bus(mxq,2) = 1;
64 | sys.Qcon(mxq,3) = 0;
65 |
66 | sys.bus(mxq,12) = sys.Qcon(mxq,2) + sys.bus(mxq,6);
67 |
68 | diago = sub2ind(size(sys.Ybu), mxq, mxq);
69 | Vc(mxq) = (1 ./ sys.Ybu(diago)) .* ((Pgl(mxq) - 1i * ...
70 | sys.Qcon(mxq,2)) ./ conj(Vc(mxq)) - sys.Yij(mxq,:) * Vc);
71 | end
72 | %--------------------------------------------------------------------------
73 |
74 |
75 | %------------------------Indexes, Parameters, Data-------------------------
76 | if ~isempty(mnq) || ~isempty(mxq)
77 | [alg, idx] = idx_par2_dnr(sys, alg, idx);
78 |
79 | V = abs(Vc);
80 | T = angle(Vc);
81 | Qgl = sys.bus(:,12) - sys.bus(:,6);
82 |
83 | pf.limit(mnq,1) = 1;
84 | pf.limit(mxq,2) = 1;
85 | end
86 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_ac/decoupled_newton_raphson/cv_dnr.m:
--------------------------------------------------------------------------------
1 | function [sys, alg, idx, pf, V, T] = cv_dnr(sys, alg, idx, pf, V, T, Pgl)
2 |
3 | %--------------------------------------------------------------------------
4 | % Checks the bus voltage magnitude constraints.
5 | %
6 | % If constraint Vmin or Vmax is violated, the type of buses is changed from
7 | % PQ bus to PV bus, and then a generator has the new voltage, where we
8 | % compute a new reactive power for the bus where voltage magnitude is
9 | % violated. The function saves a bus number when the constraint is
10 | % violated.
11 | %--------------------------------------------------------------------------
12 | % Inputs:
13 | % - sys: power system data
14 | % - alg: algorithm data
15 | % - idx: indexes data
16 | % - pf: power flow data
17 | % - V, T: bus voltage magnitude and angle vector
18 | % - Pgl: active power at bus
19 | %
20 | % Outputs:
21 | % - sys.bus with changed column: (2)bus type;
22 | % - sys.Vcon with changed column: (3)limit on/off;
23 | % - pf.alg: algorithm data
24 | % - idx: indexes data
25 | % - pf.limit with columns:
26 | % (1)bus indicator where minimum limits violated;
27 | % (2)bus indicator where maximum limits violated;
28 | % - V, T: bus voltage magnitude and angle vector
29 | %--------------------------------------------------------------------------
30 | % Created by Mirsad Cosovic on 2019-03-25
31 | % Last revision by Mirsad Cosovic on 2019-03-27
32 | % MATGRID is released under MIT License.
33 | %--------------------------------------------------------------------------
34 |
35 |
36 | %-------------------Check Voltage Magnitude Constraints--------------------
37 | mnv = find(V < sys.Vcon(:,1) & sys.Vcon(:,3) == 1);
38 | mxv = find(V > sys.Vcon(:,2) & sys.Vcon(:,3) == 1);
39 | %--------------------------------------------------------------------------
40 |
41 |
42 | %-------------------------------Check Vmin---------------------------------
43 | if ~isempty(mnv)
44 | sys.bus(mnv,2) = 2;
45 | sys.Vcon(mnv,3) = 0;
46 |
47 | V(mnv) = sys.Vcon(mnv,1);
48 | Vp = V .* exp(1j * T);
49 |
50 | Q = -imag(conj(Vp(mnv)) .* (sys.Ybu(mnv,:) * Vp));
51 |
52 | diago = sub2ind(size(sys.Ybu), mnv, mnv);
53 | T(mnv) = angle((1 ./ sys.Ybu(diago)) .* ((Pgl(mnv) - 1j * Q) ./...
54 | conj(Vp(mnv)) - sys.Yij(mnv,:) * Vp));
55 | end
56 | %--------------------------------------------------------------------------
57 |
58 |
59 | %-------------------------------Check Vmax---------------------------------
60 | if ~isempty(mxv)
61 | sys.bus(mxv,2) = 2;
62 | sys.Vcon(mxv,3) = 0;
63 |
64 | V(mxv) = sys.Vcon(mxv,2);
65 | Vp = V .* exp(1j * T);
66 |
67 | Q = -imag(conj(Vp(mxv)) .* (sys.Ybu(mxv,:) * Vp));
68 |
69 | diago = sub2ind(size(sys.Ybu), mxv, mxv);
70 | T(mxv) = angle((1 ./ sys.Ybu(diago)) .* ((Pgl(mxv) - 1j * Q) ./...
71 | conj(Vp(mxv)) - sys.Yij(mxv,:) * Vp));
72 | end
73 | %--------------------------------------------------------------------------
74 |
75 |
76 | %------------------------Indexes, Parameters, Data-------------------------
77 | if ~isempty(mnv) || ~isempty(mxv)
78 | [alg, idx] = idx_par2_dnr(sys, alg, idx);
79 |
80 | pf.limit(mnv,1) = 1;
81 | pf.limit(mxv,2) = 1;
82 | end
83 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_ac/decoupled_newton_raphson/idx_par2_dnr.m:
--------------------------------------------------------------------------------
1 | function [alg, idx] = idx_par2_dnr(sys, alg, idx)
2 |
3 | %--------------------------------------------------------------------------
4 | % Forms indexes and defines parameters to compute and form Jacobian
5 | % matrix J22.
6 | %
7 | % To form indexes and parameters, corresponding elements with the slack
8 | % bus are removed. The function is called in the initialization step, and
9 | % each time when limits are violated.
10 | %--------------------------------------------------------------------------
11 | % Inputs:
12 | % - sys: power system data
13 | % - alg: algorithm data
14 | % - idx: indexes data
15 | %
16 | % Outputs:
17 | % - alg.pq, alg.Npq: PQ buses and number of PQ buses
18 | % - alg.fdi, alg.fdj, alg.fij: indexes for the Jacobian J22
19 | % - alg.Bii: parameters for Jacobian J22
20 | % - idx.j22: indexes for the Jacobians J22
21 | %--------------------------------------------------------------------------
22 | % Created by Mirsad Cosovic on 2019-03-25
23 | % Last revision by Mirsad Cosovic on 2019-03-27
24 | % MATGRID is released under MIT License.
25 | %--------------------------------------------------------------------------
26 |
27 | %--------------------------------PQ Buses----------------------------------
28 | alg.pq = find(sys.bus(:,2) == 1);
29 | alg.Npq = length(alg.pq);
30 | %--------------------------------------------------------------------------
31 |
32 |
33 | %------------------Indexes for Summation - Only PQ Buses-------------------
34 | [alg.fdi, alg.fdj] = find(sys.Yij(alg.pq,:));
35 | alg.fij = ismember(alg.i, alg.pq);
36 | %--------------------------------------------------------------------------
37 |
38 |
39 | %-------------------------------Parameters---------------------------------
40 | GiiBii = sys.Ybu(sub2ind([sys.Nbu sys.Nbu], alg.pq, alg.pq));
41 | alg.Bii = full(imag(GiiBii));
42 | %--------------------------------------------------------------------------
43 |
44 |
45 | %--------------------------Jacobian J22 Indexes----------------------------
46 | ij = ismember(alg.j, alg.pq);
47 | mn = ismember(alg.i, alg.pq);
48 | idx.j22.ij = logical(ij .* mn);
49 | idx.j22.i = alg.i(idx.j22.ij);
50 |
51 | Yii = sys.Yii(alg.pq, :);
52 | [c, d] = find(Yii(:, alg.pq));
53 |
54 | Yij = sys.Yij(alg.pq, :);
55 | [q, w] = find(Yij(:, alg.pq));
56 |
57 | idx.j22.jci = [c; q];
58 | idx.j22.jcj = [d; w];
59 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_ac/fast_newton_raphson/cq_fnr.m:
--------------------------------------------------------------------------------
1 | function [sys, pf, V, T, Qgl, pq, Npq, Bppi] = cq_fnr(sys, pf, V, T, Qgl, Vc, Pgl, pq, Npq, Bp2, Bppi)
2 |
3 | %--------------------------------------------------------------------------
4 | % Checks the bus reactive power constraints.
5 | %
6 | % If constraint Qmin or Qmax is violated, the type of buses is changed from
7 | % PV bus to PQ bus, and then a generator has the new reactive power, where
8 | % we compute a new complex voltage for the bus where reactive power is
9 | % violated. The function saves a bus number when the constraint is
10 | % violated.
11 | %--------------------------------------------------------------------------
12 | % Inputs:
13 | % - sys: power system data
14 | % - pf: power flow data
15 | % - V, T: bus voltage magnitude and angle vector
16 | % - Qgl: reactive power at bus
17 | % - Vc: complex bus voltages
18 | % - Pgl: active power at bus
19 | % - pq: PQ bus indexes
20 | % - Npq: number of PQ buses
21 | % - Bppi: inverse of Bprime2
22 | %
23 | % Outputs:
24 | % - sys.bus with changed columns
25 | % (2)bus type; (12)generator reactive power(Qg);
26 | % - pf.limit with columns:
27 | % (1)bus indicator where minimum limits violated;
28 | % (2)bus indicator where maximum limits violated;
29 | % - V, T: bus voltage magnitude and angle vector
30 | % - Qgl: reactive power at bus
31 | % - pq: PQ bus indexes
32 | % - Npq: number of PQ buses
33 | % - Bp2: full matrix Bp2
34 | % - Bppi: inverse of Bprime2
35 | %--------------------------------------------------------------------------
36 | % Created by Mirsad Cosovic on 2019-03-25
37 | % Last revision by Mirsad Cosovic on 2019-03-27
38 | % MATGRID is released under MIT License.
39 | %--------------------------------------------------------------------------
40 |
41 |
42 | %--------------------Check Reactive Power Constraints----------------------
43 | Q = -imag(conj(Vc) .* (sys.Ybu * Vc));
44 | mnq = find(Q < sys.Qcon(:,1) & sys.Qcon(:,3) == 1);
45 | mxq = find(Q > sys.Qcon(:,2) & sys.Qcon(:,3) == 1);
46 | %--------------------------------------------------------------------------
47 |
48 |
49 | %-------------------------------Check Qmin---------------------------------
50 | if ~isempty(mnq)
51 | sys.bus(mnq,2) = 1;
52 | sys.Qcon(mnq,3) = 0;
53 |
54 | sys.bus(mnq,12) = sys.Qcon(mnq,1) + sys.bus(mnq,6);
55 |
56 | diago = sub2ind(size(sys.Ybu), mnq, mnq);
57 | Vc(mnq) = (1 ./ sys.Ybu(diago)) .* ((Pgl(mnq) - 1i * ...
58 | sys.Qcon(mnq,1)) ./ conj(Vc(mnq)) - sys.Yij(mnq,:) * Vc);
59 | end
60 | %--------------------------------------------------------------------------
61 |
62 |
63 | %-------------------------------Check Qmax---------------------------------
64 | if ~isempty(mxq)
65 | sys.bus(mxq,2) = 1;
66 | sys.Qcon(mxq,3) = 0;
67 |
68 | sys.bus(mxq,12) = sys.Qcon(mxq,2) + sys.bus(mxq,6);
69 |
70 | diago = sub2ind(size(sys.Ybu), mxq, mxq);
71 | Vc(mxq) = (1 ./ sys.Ybu(diago)) .* ((Pgl(mxq) - 1i * ...
72 | sys.Qcon(mxq,2)) ./ conj(Vc(mxq)) - sys.Yij(mxq,:) * Vc);
73 | end
74 | %--------------------------------------------------------------------------
75 |
76 |
77 | %------------------------Indexes, Parameters, Data-------------------------
78 | if ~isempty(mnq) || ~isempty(mxq)
79 | pq = find(sys.bus(:,2) == 1);
80 | Npq = length(pq);
81 |
82 | Bpp = Bp2;
83 | Bpp = Bpp(:,pq);
84 | Bpp = Bpp(pq, :);
85 | Bppi = Bpp \ speye([Npq, Npq]);
86 |
87 | V = abs(Vc);
88 | T = angle(Vc);
89 |
90 | Qgl = sys.bus(:,12) - sys.bus(:,6);
91 |
92 | pf.limit(mnq,1) = 1;
93 | pf.limit(mxq,2) = 1;
94 | end
95 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_ac/fast_newton_raphson/cv_fnr.m:
--------------------------------------------------------------------------------
1 | function [sys, pf, V, T, pq, Npq, Bppi] = cv_fnr(sys, pf, V, T, Pgl, pq, Npq, Bp2, Bppi)
2 |
3 | %--------------------------------------------------------------------------
4 | % Checks the bus voltage magnitude constraints.
5 | %
6 | % If constraint Vmin or Vmax is violated, the type of buses is changed from
7 | % PQ bus to PV bus, and then a generator has the new voltage, where we
8 | % compute a new reactive power for the bus where voltage magnitude is
9 | % violated. The function saves a bus number when the constraint is
10 | % violated.
11 | %--------------------------------------------------------------------------
12 | % Inputs:
13 | % - sys: power system data
14 | % - alg: algorithm data
15 | % - idx: indexes data
16 | % - pf: power flow data
17 | % - DelPQ: mismatch
18 | % - V, T: bus voltage magnitude and angle vector
19 | % - Qgl: reactive power at bus
20 | % - Pgl: active power at bus
21 | %
22 | % Outputs:
23 | % - sys.bus with changed column: (2)bus type;
24 | % - pf.alg: algorithm data
25 | % - idx: indexes data
26 | % - pf.limit with columns:
27 | % (1)bus indicator where minimum limits violated;
28 | % (2)bus indicator where maximum limits violated;
29 | % - DelPQ: an active and reactive power mismatch matrix for all buses
30 | % - V, T: bus voltage magnitude and angle vector
31 | %--------------------------------------------------------------------------
32 | % Created by Mirsad Cosovic on 2019-03-25
33 | % Last revision by Mirsad Cosovic on 2019-03-27
34 | % MATGRID is released under MIT License.
35 | %--------------------------------------------------------------------------
36 |
37 |
38 | %-------------------Check Voltage Magnitude Constraints--------------------
39 | mnv = find(V < sys.Vcon(:,1) & sys.Vcon(:,3) == 1);
40 | mxv = find(V > sys.Vcon(:,2) & sys.Vcon(:,3) == 1);
41 | %--------------------------------------------------------------------------
42 |
43 |
44 | %-------------------------------Check Vmin---------------------------------
45 | if ~isempty(mnv)
46 | sys.bus(mnv,2) = 2;
47 | sys.Vcon(mnv,3) = 0;
48 |
49 | V(mnv) = sys.Vcon(mnv,1);
50 | Vp = V .* exp(1j * T);
51 |
52 | Q = -imag(conj(Vp(mnv)) .* (sys.Ybu(mnv,:) * Vp));
53 |
54 | diago = sub2ind(size(sys.Ybu), mnv, mnv);
55 | T(mnv) = angle((1 ./ sys.Ybu(diago)) .* ((Pgl(mnv) - 1j * Q) ./...
56 | conj(Vp(mnv)) - sys.Yij(mnv,:) * Vp));
57 | end
58 | %--------------------------------------------------------------------------
59 |
60 |
61 | %-------------------------------Check Vmax---------------------------------
62 | if ~isempty(mxv)
63 | sys.bus(mxv,2) = 2;
64 | sys.Vcon(mxv,3) = 0;
65 |
66 | V(mxv) = sys.Vcon(mxv,2);
67 | Vp = V .* exp(1j * T);
68 |
69 | Q = -imag(conj(Vp(mxv)) .* (sys.Ybu(mxv,:) * Vp));
70 |
71 | diago = sub2ind(size(sys.Ybu), mxv, mxv);
72 | T(mxv) = angle((1 ./ sys.Ybu(diago)) .* ((Pgl(mxv) - 1j * Q) ./...
73 | conj(Vp(mxv)) - sys.Yij(mxv,:) * Vp));
74 | end
75 | %--------------------------------------------------------------------------
76 |
77 |
78 | %------------------------Indexes, Parameters, Data-------------------------
79 | if ~isempty(mnv) || ~isempty(mxv)
80 | pq = find(sys.bus(:,2) == 1);
81 | Npq = length(pq);
82 |
83 | Bpp = Bp2;
84 | Bpp = Bpp(:,pq);
85 | Bpp = Bpp(pq, :);
86 | Bppi = Bpp \ speye([Npq, Npq]);
87 |
88 | V = abs(Vp);
89 | T = angle(Vp);
90 |
91 | pf.limit(mnv,1) = 1;
92 | pf.limit(mxv,2) = 1;
93 | end
94 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_ac/gauss_seidel/gs_cq.m:
--------------------------------------------------------------------------------
1 | function [sys, pf, Vc, Q] = gs_cq(sys, pf, Vc, Q, Pgl)
2 |
3 | %--------------------------------------------------------------------------
4 | % Checks the bus reactive power constraints.
5 | %
6 | % If constraint Qmin or Qmax is violated, the type of buses is changed from
7 | % PV bus to PQ bus, and then a generator has the new reactive power. The
8 | % function saves a bus number when the constraint is violated.
9 | %--------------------------------------------------------------------------
10 | % Inputs:
11 | % - sys: power system data
12 | % - pf: power flow data
13 | % - Vc: complex bus voltages
14 | % - Q: reactive power at bus
15 | % - Pgl: active power at bus
16 | %
17 | % Outputs:
18 | % - sys.bus with changed columns:
19 | % (2)bus type; (12)generator reactive power(Qg);
20 | % - sys.Qcon with changed column: (3)limit on/off;
21 | % - pf.limit with columns:
22 | % (1)bus indicator where minimum limits violated;
23 | % (2)bus indicator where maximum limits violated;
24 | % - Vc: complex bus voltages
25 | % - Q: reactive power at bus
26 | %--------------------------------------------------------------------------
27 | % Created by Mirsad Cosovic on 2019-03-25
28 | % Last revision by Mirsad Cosovic on 2019-03-27
29 | % MATGRID is released under MIT License.
30 | %--------------------------------------------------------------------------
31 |
32 |
33 | %--------------------Check Reactive Power Constraints----------------------
34 | mnq = find(Q < sys.Qcon(:,1) & sys.Qcon(:,3) == 1);
35 | mxq = find(Q > sys.Qcon(:,2) & sys.Qcon(:,3) == 1);
36 | %--------------------------------------------------------------------------
37 |
38 |
39 | %-------------------------------Check Qmin---------------------------------
40 | if ~isempty(mnq)
41 | sys.bus(mnq,2) = 1;
42 | sys.Qcon(mnq,3) = 0;
43 |
44 | sys.bus(mnq,12) = sys.Qcon(mnq,1) + sys.bus(mnq,6);
45 |
46 | diago = sub2ind(size(sys.Ybu), mnq, mnq);
47 | Vc(mnq) = (1 ./ sys.Ybu(diago)) .* ((Pgl(mnq) - 1i * ...
48 | sys.Qcon(mnq,1)) ./ conj(Vc(mnq)) - sys.Yij(mnq,:) * Vc);
49 | end
50 | %--------------------------------------------------------------------------
51 |
52 |
53 | %-------------------------------Check Qmax---------------------------------
54 | if ~isempty(mxq)
55 | sys.bus(mxq,2) = 1;
56 | sys.Qcon(mxq,3) = 0;
57 |
58 | sys.bus(mxq,12) = sys.Qcon(mxq,2) + sys.bus(mxq,6);
59 |
60 | diago = sub2ind(size(sys.Ybu), mxq, mxq);
61 | Vc(mxq) = (1 ./ sys.Ybu(diago)) .* ((Pgl(mxq) - 1i * ...
62 | sys.Qcon(mxq,2)) ./ conj(Vc(mxq)) - sys.Yij(mxq,:) * Vc);
63 | end
64 | %--------------------------------------------------------------------------
65 |
66 |
67 | %------------------------Indexes, Parameters, Data-------------------------
68 | if ~isempty(mnq) || ~isempty(mxq)
69 | Q = sys.bus(:,12) - sys.bus(:,6);
70 |
71 | pf.limit(mnq,1) = 1;
72 | pf.limit(mxq,2) = 1;
73 | end
74 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_ac/gauss_seidel/gs_cv.m:
--------------------------------------------------------------------------------
1 | function [sys, pf, Vc, Vcp] = gs_cv(sys, pf, Vc, Vcp, Pgl)
2 |
3 | %--------------------------------------------------------------------------
4 | % Checks the bus voltage magnitude constraints.
5 | %
6 | % If constraint Vmin or Vmax is violated, the type of buses is changed from
7 | % PQ bus to PV bus, then we put |V| on Vmin or Vmax, where |V| is specified
8 | % (now this is PV bus), and it needs voltage correction. Finally, we
9 | % compute a reactive power injection and complex bus voltage for for PV
10 | % bus. The function saves a bus number when the constraint is violated.
11 | %--------------------------------------------------------------------------
12 | % Inputs:
13 | % - sys: power system data
14 | % - pf: power flow data
15 | % - Vc, Vcp: complex bus voltages
16 | % - Pgl: active power at bus
17 | %
18 | % Outputs:
19 | % - sys.bus with changed column: (2)bus type;
20 | % - sys.Vcon with changed column: (3)limit on/off;
21 | % - pf.limit with columns:
22 | % (1)bus indicator where minimum limits violated;
23 | % (2)bus indicator where maximum limits violated;
24 | % - Vc, Vcp: complex bus voltages
25 | %--------------------------------------------------------------------------
26 | % Created by Mirsad Cosovic on 2019-03-25
27 | % Last revision by Mirsad Cosovic on 2019-03-27
28 | % MATGRID is released under MIT License.
29 | %--------------------------------------------------------------------------
30 |
31 |
32 | %-------------------Check Voltage Magnitude Constraints--------------------
33 | V = abs(Vc);
34 | T = angle(Vc);
35 | mnv = find(V < sys.Vcon(:,1) & sys.Vcon(:,3) == 1);
36 | mxv = find(V > sys.Vcon(:,2) & sys.Vcon(:,3) == 1);
37 | %--------------------------------------------------------------------------
38 |
39 |
40 | %-------------------------------Check Vmin---------------------------------
41 | if ~isempty(mnv)
42 | sys.bus(mnv,2) = 2;
43 | sys.Vcon(mnv,3) = 0;
44 |
45 | V(mnv) = sys.Vcon(mnv,1);
46 | Vp = V .* exp(1j * T);
47 |
48 | Q = -imag(conj(Vp(mnv)) .* (sys.Ybu(mnv,:) * Vp));
49 |
50 | diago = sub2ind(size(sys.Ybu), mnv, mnv);
51 | T(mnv) = angle((1 ./ sys.Ybu(diago)) .* ((Pgl(mnv) - 1j * Q) ./...
52 | conj(Vp(mnv)) - sys.Yij(mnv,:) * Vp));
53 | end
54 | %--------------------------------------------------------------------------
55 |
56 |
57 | %-------------------------------Check Vmax---------------------------------
58 | if ~isempty(mxv)
59 | sys.bus(mxv,2) = 2;
60 | sys.Vcon(mxv,3) = 0;
61 |
62 | V(mxv) = sys.Vcon(mxv,2);
63 | Vp = V .* exp(1j * T);
64 |
65 | Q = -imag(conj(Vp(mxv)) .* (sys.Ybu(mxv,:) * Vp));
66 |
67 | diago = sub2ind(size(sys.Ybu), mxv, mxv);
68 | T(mxv) = angle((1 ./ sys.Ybu(diago)) .* ((Pgl(mxv) - 1j * Q) ./...
69 | conj(Vp(mxv)) - sys.Yij(mxv,:) * Vp));
70 | end
71 | %--------------------------------------------------------------------------
72 |
73 |
74 | %------------------------Indexes, Parameters, Data-------------------------
75 | if ~isempty(mnv) || ~isempty(mxv)
76 | Vc = V .* exp(1j * T);
77 | Vcp = Vc;
78 |
79 | pf.limit(mnv,1) = 1;
80 | pf.limit(mxv,2) = 1;
81 | end
82 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_ac/newton_raphson/cq.m:
--------------------------------------------------------------------------------
1 | function [sys, alg, idx, pf, V, T, Qgl, DelPQ] = cq(sys, alg, idx, pf, V, T, Qgl, Pgl, DelPQ)
2 |
3 | %--------------------------------------------------------------------------
4 | % Checks the bus reactive power constraints.
5 | %
6 | % If constraint Qmin or Qmax is violated, the type of buses is changed from
7 | % PV bus to PQ bus, and then a generator has the new reactive power, where
8 | % we compute a new complex voltage for the bus where reactive power is
9 | % violated. The function saves a bus number when the constraint is
10 | % violated.
11 | %--------------------------------------------------------------------------
12 | % Inputs:
13 | % - sys: power system data
14 | % - alg: algorithm data
15 | % - idx: indexes data
16 | % - pf: power flow data
17 | % - V, T: bus voltage magnitude and angle vector
18 | % - Qgl: reactive power at bus
19 | % - Pgl: active power at bus
20 | % - DelPQ: an active and reactive power mismatch matrix for all buses
21 | %
22 | % Outputs:
23 | % - sys.bus with changed columns:
24 | % (2)bus type; (12)generator reactive power(Qg);
25 | % - sys.Qcon with changed column: (3)limit on/off;
26 | % - pf.alg: algorithm data
27 | % - idx: indexes data
28 | % - pf.bus with changed columns:
29 | % (1)bus indicator where minimum limits violated;
30 | % (2)bus indicator where maximum limits violated;
31 | % - V, T: bus voltage magnitude and angle vector
32 | % - Qgl: generator reactive power at bus
33 | % - DelPQ: an active and reactive power mismatch matrix for all buses
34 | %--------------------------------------------------------------------------
35 | % Created by Mirsad Cosovic on 2019-02-21
36 | % Last revision by Mirsad Cosovic on 2019-03-27
37 | % MATGRID is released under MIT License.
38 | %--------------------------------------------------------------------------
39 |
40 |
41 | %--------------------Check Reactive Power Constraints----------------------
42 | Vc = V .* exp(1i * T);
43 | Q = -imag(conj(Vc) .* (sys.Ybu * Vc));
44 | mnq = find(Q < sys.Qcon(:,1) & sys.Qcon(:,3) == 1);
45 | mxq = find(Q > sys.Qcon(:,2) & sys.Qcon(:,3) == 1);
46 | %--------------------------------------------------------------------------
47 |
48 |
49 | %-------------------------------Check Qmin---------------------------------
50 | if ~isempty(mnq)
51 | sys.bus(mnq,2) = 1;
52 | sys.Qcon(mnq,3) = 0;
53 |
54 | sys.bus(mnq,12) = sys.Qcon(mnq,1) + sys.bus(mnq,6);
55 |
56 | diago = sub2ind(size(sys.Ybu), mnq, mnq);
57 | Vc(mnq) = (1 ./ sys.Ybu(diago)) .* ((Pgl(mnq) - 1i * ...
58 | sys.Qcon(mnq,1)) ./ conj(Vc(mnq)) - sys.Yij(mnq,:) * Vc);
59 | end
60 | %--------------------------------------------------------------------------
61 |
62 |
63 | %-------------------------------Check Qmax---------------------------------
64 | if ~isempty(mxq)
65 | sys.bus(mxq,2) = 1;
66 | sys.Qcon(mxq,3) = 0;
67 |
68 | sys.bus(mxq,12) = sys.Qcon(mxq,2) + sys.bus(mxq,6);
69 |
70 | diago = sub2ind(size(sys.Ybu), mxq, mxq);
71 | Vc(mxq) = (1 ./ sys.Ybu(diago)) .* ((Pgl(mxq) - 1i * ...
72 | sys.Qcon(mxq,2)) ./ conj(Vc(mxq)) - sys.Yij(mxq,:) * Vc);
73 | end
74 | %--------------------------------------------------------------------------
75 |
76 |
77 | %------------------------Indexes, Parameters, Data-------------------------
78 | if ~isempty(mnq) || ~isempty(mxq)
79 | [alg, idx] = idx_par2(sys, alg, idx);
80 |
81 | T = angle(Vc);
82 | V = abs(Vc);
83 | Qgl = sys.bus(:,12) - sys.bus(:,6);
84 |
85 | DelS = Vc .* conj(sys.Ybu * Vc) - (Pgl + 1i * Qgl);
86 | DelPQ = [real(DelS(alg.ii)); imag(DelS(alg.pq))];
87 |
88 | pf.limit(mnq,1) = 1;
89 | pf.limit(mxq,2) = 1;
90 | end
91 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_ac/newton_raphson/cv.m:
--------------------------------------------------------------------------------
1 | function [sys, alg, idx, pf, DelPQ, V, T] = cv(sys, alg, idx, pf, DelPQ, V, T, Pgl, Qgl)
2 |
3 | %--------------------------------------------------------------------------
4 | % Checks the bus voltage magnitude constraints.
5 | %
6 | % If constraint Vmin or Vmax is violated, the type of buses is changed from
7 | % PQ bus to PV bus, and then a generator has the new voltage, where we
8 | % compute a new reactive power for the bus where voltage magnitude is
9 | % violated. The function saves a bus number when the constraint is
10 | % violated.
11 | %--------------------------------------------------------------------------
12 | % Inputs:
13 | % - sys: power system data
14 | % - alg: algorithm data
15 | % - idx: indexes data
16 | % - pf: power flow data
17 | % - DelPQ: mismatch
18 | % - V, T: bus voltage magnitude and angle vector
19 | % - Qgl: reactive power at bus
20 | % - Pgl: active power at bus
21 | %
22 | % Outputs:
23 | % - sys.bus with changed column: (2)bus type;
24 | % - sys.Vcon with changed column: (3)limit on/off;
25 | % - pf.alg: algorithm data
26 | % - idx: indexes data
27 | % - pf.bus with changed columns:
28 | % (1)bus indicator where minimum limits violated;
29 | % (2)bus indicator where maximum limits violated;
30 | % - DelPQ: an active and reactive power mismatch matrix for all buses
31 | % - V, T: bus voltage magnitude and angle vector
32 | %--------------------------------------------------------------------------
33 | % Created by Mirsad Cosovic on 2019-02-21
34 | % Last revision by Mirsad Cosovic on 2019-03-27
35 | % MATGRID is released under MIT License.
36 | %--------------------------------------------------------------------------
37 |
38 |
39 | %-------------------Check Voltage Magnitude Constraints--------------------
40 | mnv = find(V < sys.Vcon(:,1) & sys.Vcon(:,3) == 1);
41 | mxv = find(V > sys.Vcon(:,2) & sys.Vcon(:,3) == 1);
42 | %--------------------------------------------------------------------------
43 |
44 |
45 | %-------------------------------Check Vmin---------------------------------
46 | if ~isempty(mnv)
47 | sys.bus(mnv,2) = 2;
48 | sys.Vcon(mnv,3) = 0;
49 |
50 | V(mnv) = sys.Vcon(mnv,1);
51 | Vp = V .* exp(1j * T);
52 |
53 | Q = -imag(conj(Vp(mnv)) .* (sys.Ybu(mnv,:) * Vp));
54 |
55 | diago = sub2ind(size(sys.Ybu), mnv, mnv);
56 | T(mnv) = angle((1 ./ sys.Ybu(diago)) .* ((Pgl(mnv) - 1j * Q) ./...
57 | conj(Vp(mnv)) - sys.Yij(mnv,:) * Vp));
58 | end
59 | %--------------------------------------------------------------------------
60 |
61 |
62 | %-------------------------------Check Vmax---------------------------------
63 | if ~isempty(mxv)
64 | sys.bus(mxv,2) = 2;
65 | sys.Vcon(mxv,3) = 0;
66 |
67 | V(mxv) = sys.Vcon(mxv,2);
68 | Vp = V .* exp(1j * T);
69 |
70 | Q = -imag(conj(Vp(mxv)) .* (sys.Ybu(mxv,:) * Vp));
71 |
72 | diago = sub2ind(size(sys.Ybu), mxv, mxv);
73 | T(mxv) = angle((1 ./ sys.Ybu(diago)) .* ((Pgl(mxv) - 1j * Q) ./...
74 | conj(Vp(mxv)) - sys.Yij(mxv,:) * Vp));
75 | end
76 | %--------------------------------------------------------------------------
77 |
78 |
79 | %------------------------Indexes, Parameters, Data-------------------------
80 | if ~isempty(mnv) || ~isempty(mxv)
81 | [alg, idx] = idx_par2(sys, alg, idx);
82 |
83 | Vp = V.* exp(1j * T);
84 | DelS = Vp .* conj(sys.Ybu * Vp) - (Pgl + 1i * Qgl);
85 | DelPQ = [real(DelS(alg.ii)); imag(DelS(alg.pq))];
86 |
87 | pf.limit(mnv,1) = 1;
88 | pf.limit(mxv,2) = 1;
89 | end
90 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_ac/newton_raphson/data_jacobian.m:
--------------------------------------------------------------------------------
1 | function [alg] = data_jacobian(T, V, alg, Nbu)
2 |
3 | %--------------------------------------------------------------------------
4 | % Computes elements used for Jacobian matrices.
5 | %
6 | % The function computes Ti - Tj; Gij*sin(Ti-Tj) - Bij*cos(Ti-Tj);
7 | % Gij*cos(Ti-Tj) + Bij*sin(Ti-Tj); Vi*Vj, and forms corresponding
8 | % summations.
9 | %--------------------------------------------------------------------------
10 | % Inputs:
11 | % - V, T: bus voltage magnitude and angle vector
12 | % - alg: algorithm data
13 | % - Nbu: number of buses
14 | %
15 | % Output:
16 | % - alg: algorithm data
17 | %--------------------------------------------------------------------------
18 | % Created by Mirsad Cosovic on 2019-02-21
19 | % Last revision by Mirsad Cosovic on 2019-03-27
20 | % MATGRID is released under MIT License.
21 | %--------------------------------------------------------------------------
22 |
23 |
24 | %------------------------------Jacobian Data-------------------------------
25 | Tij = T(alg.i) - T(alg.j);
26 |
27 | alg.Te1 = alg.Gij .* sin(Tij) - alg.Bij .* cos(Tij);
28 | alg.Te2 = alg.Gij .* cos(Tij) + alg.Bij .* sin(Tij);
29 |
30 | alg.fD1 = sparse(alg.fd1i, alg.j, -alg.Te1, Nbu - 1, Nbu) * V;
31 | alg.fD2 = sparse(alg.fdi, alg.fdj, alg.Te2(alg.fij), alg.Npq, Nbu) * V;
32 | alg.fD3 = sparse(alg.fdi, alg.fdj, alg.Te1(alg.fij), alg.Npq, Nbu) * V;
33 |
34 | alg.Vpq = V(alg.pq);
35 | alg.Vij = V(alg.i) .* V(alg.j);
36 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_ac/newton_raphson/idx_par1.m:
--------------------------------------------------------------------------------
1 | function [alg, idx] = idx_par1(sys)
2 |
3 | %--------------------------------------------------------------------------
4 | % Forms indexes and defines parameters to compute and form Jacobian
5 | % matrices.
6 | %
7 | % To form indexes and parameters, corresponding elements with the slack
8 | % bus are removed. The function is called only in the initialization step,
9 | % and data remains constant, even when limits are violated for reactive and
10 | % voltage magnitude quantities.
11 | %--------------------------------------------------------------------------
12 | % Input:
13 | % - sys: power system data
14 | %
15 | % Outputs:
16 | % - alg.i, alg.j, alg.Gij, alg.Bij: to compute elements Ti-Tj, Vi*Vj,
17 | % Gij*sin(Tij)-Bij*cos(Tij), Gij*cos(Tij)+Bij*sin(Tij)
18 | % - alg.fd1i, alg.ii, idx.j11.ij, idx.j11.jci, idx.j11.jcj: indexes
19 | % for the Jacobian J11
20 | %--------------------------------------------------------------------------
21 | % Created by Mirsad Cosovic on 2019-02-21
22 | % Last revision by Mirsad Cosovic on 2019-03-27
23 | % MATGRID is released under MIT License.
24 | %--------------------------------------------------------------------------
25 |
26 |
27 | %------------------Global System Indexes and Parameters--------------------
28 | Yte = sys.Yij;
29 |
30 | sys.Yij(sys.sck(1),:) = 0;
31 | [alg.i, alg.j] = find(sys.Yij);
32 |
33 | GijBij = sys.Ybu(sub2ind([sys.Nbu sys.Nbu], alg.i, alg.j));
34 | alg.Gij = full(real(GijBij));
35 | alg.Bij = full(imag(GijBij));
36 | %--------------------------------------------------------------------------
37 |
38 |
39 | %----------------Indexes for Summation - Without Slack Bus-----------------
40 | Yte(sys.sck(1),:) = [];
41 | [alg.fd1i, ~] = find(Yte);
42 | %--------------------------------------------------------------------------
43 |
44 |
45 | %--------------------------Jacobian J11 Indexes----------------------------
46 | alg.ii = sys.bus(:,1);
47 | alg.ii(sys.sck(1)) = [];
48 |
49 | idx.j11.ij = alg.j ~= sys.sck(1);
50 |
51 | Yte(:,sys.sck(1)) = [];
52 | [q, w] = find(Yte);
53 | bu = (1:sys.Nbu - 1)';
54 |
55 | idx.j11.jci = [bu; q];
56 | idx.j11.jcj = [bu; w];
57 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_ac/newton_raphson/idx_par2.m:
--------------------------------------------------------------------------------
1 | function [alg, idx] = idx_par2(sys, alg, idx)
2 |
3 | %--------------------------------------------------------------------------
4 | % Forms indexes and defines parameters to compute and form Jacobian
5 | % matrices.
6 | %
7 | % To form indexes and parameters, corresponding elements with the slack
8 | % bus are removed. The function is called in the initialization step, and
9 | % each time when limits are violated.
10 | %--------------------------------------------------------------------------
11 | % Inputs:
12 | % - sys: power system data
13 | % - alg: algorithm data
14 | % - idx: indexes data
15 | %
16 | % Outputs:
17 | % - alg.pq, alg.Npq: PQ buses and number of PQ buses
18 | % - alg.fdi, alg.fdj, alg.fij: indexes for the Jacobians J12, J21, J22
19 | % - alg.Gii, alg.Bii: parameters for Jacobians J12 and J22
20 | % - idx.j12: indexes for the Jacobians J12
21 | % - idx.j21: indexes for the Jacobians J21
22 | % - idx.j22: indexes for the Jacobians J22
23 | %--------------------------------------------------------------------------
24 | % Created by Mirsad Cosovic on 2019-02-21
25 | % Last revision by Mirsad Cosovic on 2019-03-27
26 | % MATGRID is released under MIT License.
27 | %--------------------------------------------------------------------------
28 |
29 |
30 | %--------------------------------PQ Buses----------------------------------
31 | alg.pq = find(sys.bus(:,2) == 1);
32 | alg.Npq = length(alg.pq);
33 | %--------------------------------------------------------------------------
34 |
35 |
36 | %------------------Indexes for Summation - Only PQ Buses-------------------
37 | [alg.fdi, alg.fdj] = find(sys.Yij(alg.pq,:));
38 | alg.fij = ismember(alg.i, alg.pq);
39 | %--------------------------------------------------------------------------
40 |
41 |
42 | %-------------------------------Parameters---------------------------------
43 | GiiBii = sys.Ybu(sub2ind([sys.Nbu sys.Nbu], alg.pq, alg.pq));
44 | alg.Gii = full(real(GiiBii));
45 | alg.Bii = full(imag(GiiBii));
46 | %--------------------------------------------------------------------------
47 |
48 |
49 | %--------------------------Jacobian J12 Indexes----------------------------
50 | idx.j12.ij = ismember(alg.j, alg.pq);
51 | idx.j12.i = alg.i(idx.j12.ij);
52 |
53 | Yii = sys.Yii(:,alg.pq);
54 | Yii(sys.sck(1),:) = [];
55 | [c, d] = find(Yii);
56 |
57 | Yij = sys.Yij(:,alg.pq);
58 | Yij(sys.sck(1),:) = [];
59 | [q, w] = find(Yij);
60 |
61 | idx.j12.jci = [c; q];
62 | idx.j12.jcj = [d; w];
63 | %--------------------------------------------------------------------------
64 |
65 |
66 | %--------------------------Jacobian J21 Indexes----------------------------
67 | mn = ismember(alg.i, alg.pq);
68 | idx.j21.ij = logical(idx.j11.ij .* mn);
69 |
70 | Yii = sys.Yii(alg.pq,:);
71 | Yii(:, sys.sck(1)) = [];
72 | [c, d] = find(Yii);
73 |
74 | Yij = sys.Yij(alg.pq,:);
75 | Yij(:, sys.sck(1)) = [];
76 | [q, w] = find(Yij);
77 |
78 | if alg.Npq == 1
79 | idx.j21.jci = [c; q'];
80 | idx.j21.jcj = [d; w'];
81 | else
82 | idx.j21.jci = [c; q];
83 | idx.j21.jcj = [d; w];
84 | end
85 | %--------------------------------------------------------------------------
86 |
87 |
88 | %--------------------------Jacobian J22 Indexes----------------------------
89 | idx.j22.ij = logical(idx.j12.ij .* mn);
90 | idx.j22.i = alg.i(idx.j22.ij);
91 |
92 | Yii = sys.Yii(alg.pq,:);
93 | [c, d] = find(Yii(:,alg.pq));
94 |
95 | Yij = sys.Yij(alg.pq,:);
96 | [q, w] = find(Yij(:,alg.pq));
97 |
98 | idx.j22.jci = [c; q];
99 | idx.j22.jcj = [d; w];
100 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_ac/newton_raphson/jacobian11.m:
--------------------------------------------------------------------------------
1 | function [J11] = jacobian11(V, alg, idx, Nbu)
2 |
3 | %--------------------------------------------------------------------------
4 | % Computes the Jacobian matrix J11.
5 | %
6 | % The function computes a partial derivative of active power injection into
7 | % buses with respect to bus voltage angles, where we compute diagonal and
8 | % non-diagonal elements separately.
9 | %--------------------------------------------------------------------------
10 | % Inputs:
11 | % - V: bus voltage magnitude vector
12 | % - alg: algorithm data
13 | % - idx: indexes data
14 | % - Nbu: number of buses
15 | %
16 | % Output:
17 | % - J11: Jacobian matrix
18 | %--------------------------------------------------------------------------
19 | % Created by Mirsad Cosovic on 2019-02-21
20 | % Last revision by Mirsad Cosovic on 2019-03-27
21 | % MATGRID is released under MIT License.
22 | %--------------------------------------------------------------------------
23 |
24 |
25 | %---------------------------Jacobian Matrix J11----------------------------
26 | D = V(alg.ii) .* alg.fD1;
27 | N = alg.Vij(idx.ij) .* alg.Te1(idx.ij);
28 |
29 | J11 = sparse(idx.jci, idx.jcj, [D; N], Nbu - 1, Nbu - 1);
30 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_ac/newton_raphson/jacobian12.m:
--------------------------------------------------------------------------------
1 | function [J12] = jacobian12(V, alg, idx, Nbu)
2 |
3 | %--------------------------------------------------------------------------
4 | % Computes the Jacobian matrix J12.
5 | %
6 | % The function computes a partial derivative of active power injection into
7 | % buses with respect to bus voltage magnitudes, where we compute diagonal
8 | % and non-diagonal elements separately.
9 | %--------------------------------------------------------------------------
10 | % Inputs:
11 | % - V: bus voltage magnitude vector
12 | % - alg: algorithm data
13 | % - idx: indexes data
14 | % - Nbu: number of buses
15 | %
16 | % Output:
17 | % - J12: Jacobian matrix
18 | %--------------------------------------------------------------------------
19 | % Created by Mirsad Cosovic on 2019-02-21
20 | % Last revision by Mirsad Cosovic on 2019-03-27
21 | % MATGRID is released under MIT License.
22 | %--------------------------------------------------------------------------
23 |
24 |
25 | %---------------------------Jacobian Matrix J12----------------------------
26 | D = alg.fD2 + 2 * alg.Gii .* alg.Vpq;
27 | N = V(idx.i) .* alg.Te2(idx.ij);
28 |
29 | J12 = sparse(idx.jci, idx.jcj, [D; N], Nbu - 1, alg.Npq);
30 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_ac/newton_raphson/jacobian21.m:
--------------------------------------------------------------------------------
1 | function [J21] = jacobian21(alg, idx, Nbu)
2 |
3 | %--------------------------------------------------------------------------
4 | % Computes the Jacobian matrix J21.
5 | %
6 | % The function computes a partial derivative of reactive power injection
7 | % into buses with respect to bus voltage angles, where we compute diagonal
8 | % and non-diagonal elements separately.
9 | %--------------------------------------------------------------------------
10 | % Inputs:
11 | % - alg: algorithm data
12 | % - idx: indexes data
13 | % - Nbu: number of buses
14 | %
15 | % Output:
16 | % - J21: Jacobian matrix
17 | %--------------------------------------------------------------------------
18 | % Created by Mirsad Cosovic on 2019-02-21
19 | % Last revision by Mirsad Cosovic on 2019-03-27
20 | % MATGRID is released under MIT License.
21 | %--------------------------------------------------------------------------
22 |
23 |
24 | %---------------------------Jacobian Matrix J21----------------------------
25 | D = alg.Vpq .* alg.fD2;
26 | N = -alg.Vij(idx.ij) .* alg.Te2(idx.ij);
27 |
28 | J21 = sparse(idx.jci, idx.jcj, [D; N], alg.Npq, Nbu - 1);
29 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_ac/newton_raphson/jacobian22.m:
--------------------------------------------------------------------------------
1 | function [J22] = jacobian22(V, alg, idx)
2 |
3 | %--------------------------------------------------------------------------
4 | % Computes the Jacobian matrix J22.
5 | %
6 | % The function computes a partial derivative of reactive power injection
7 | % into buses with respect to bus voltage magnitudes, where we compute
8 | % diagonal and non-diagonal elements separately.
9 | %--------------------------------------------------------------------------
10 | % Inputs:
11 | % - V: bus voltage magnitude vector
12 | % - alg: algorithm data
13 | % - idx: indexes data
14 | %
15 | % Output:
16 | % - J22: Jacobian matrix
17 | %--------------------------------------------------------------------------
18 | % Created by Mirsad Cosovic on 2019-02-21
19 | % Last revision by Mirsad Cosovic on 2019-03-27
20 | % MATGRID is released under MIT License.
21 | %--------------------------------------------------------------------------
22 |
23 |
24 | %---------------------------Jacobian Matrix J22----------------------------
25 | D = alg.fD3 - 2 * alg.Bii .* alg.Vpq;
26 | N = V(idx.i) .* alg.Te1(idx.ij);
27 |
28 | J22 = sparse(idx.jci, idx.jcj, [D; N], alg.Npq, alg.Npq);
29 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_ac/newton_raphson/qv_limits.m:
--------------------------------------------------------------------------------
1 | function [sys] = qv_limits(user, sys)
2 |
3 | %--------------------------------------------------------------------------
4 | % Checks constraints according to the type of buses.
5 | %
6 | % The algorithm can force one type of inequalities per run. Reactive power
7 | % constraints are allowed within PV(2) buses and must be Qmin < Qmax, while
8 | % voltage magnitude constraints are allowed within PQ(1) bus and must be
9 | % Vmin < Vmax. The reactive power limits given in the input data are
10 | % related with generator reactive powers.
11 | %--------------------------------------------------------------------------
12 | % Inputs:
13 | % - user: user data
14 | % - sys: power system data
15 | %
16 | % Outputs:
17 | % - sys.Qcon: bus reactive power injection constraint matrix
18 | % - sys.Vcon: bus voltage magnitude constraint matrix
19 | %--------------------------------------------------------------------------
20 | % Created by Mirsad Cosovic on 2019-02-21
21 | % Last revision by Mirsad Cosovic on 2019-03-27
22 | % MATGRID is released under MIT License.
23 | %--------------------------------------------------------------------------
24 |
25 |
26 | %-------------------------Inequalities for Buses---------------------------
27 | on = sparse(sys.Nbu,1);
28 |
29 | if ismember('reactive', user.list)
30 | on(sys.bus(:,2) == 2 & sys.bus(:,13) < sys.bus(:,14)) = 1;
31 | sys.Qcon = [sys.bus(:,13)-sys.bus(:,6) sys.bus(:,14)-sys.bus(:,6) on];
32 | elseif ismember('voltage', user.list)
33 | on(sys.bus(:,2) == 1 & sys.bus(:,9) < sys.bus(:,10)) = 1;
34 | sys.Vcon = [sys.bus(:,9:10) on];
35 | end
36 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_ac/ybus_ac.m:
--------------------------------------------------------------------------------
1 | function [sys] = ybus_ac(sys)
2 |
3 | %--------------------------------------------------------------------------
4 | % Builds the Ybus matrix (sys.Nbu x sys.Nbu).
5 | %
6 | % The function builds the Ybus matrix, as well as its derivatives, and
7 | % forms the unified branch model.
8 | %--------------------------------------------------------------------------
9 | % Input:
10 | % - sys: power system data
11 | %
12 | % Outputs:
13 | % - sys.branch with additional columns:
14 | % (11)branch admittance(yij); (12)admittance charging susceptance(ysi);
15 | % (13)complex tap ratio(aij); (14)yij + bsi; (15)yij/aij^2;
16 | % (16)-yij/conj(aij); (17)-yij/aij
17 | % - sys.Ybu: Ybus matrix
18 | % - sys.ysh: shunt elements vector
19 | % - sys.Yij: Ybus matrix with only non-diagonal elements
20 | % - sys.Yii: Ybus matrix with only diagonal elements
21 | %--------------------------------------------------------------------------
22 | % Created by Mirsad Cosovic on 2019-02-21
23 | % Last revision by Mirsad Cosovic on 2019-03-27
24 | % MATGRID is released under MIT License.
25 | %--------------------------------------------------------------------------
26 |
27 |
28 | %------------Branch Admittance and Branch Charging Susceptance-------------
29 | sys.branch(:,11) = 1 ./ complex(sys.branch(:,4), sys.branch(:,5));
30 | sys.branch(:,12) = 1i * sys.branch(:,6) / 2;
31 | %--------------------------------------------------------------------------
32 |
33 |
34 | %--------------------------------Tap Ratio---------------------------------
35 | sys.branch(:,13) = sys.branch(:,7) .* exp(1i * sys.branch(:,8));
36 | %--------------------------------------------------------------------------
37 |
38 |
39 | %--------------------------Unified Branch Model----------------------------
40 | sys.branch(:,14) = sys.branch(:,11) + sys.branch(:,12);
41 | sys.branch(:,15) = sys.branch(:,14) ./ (conj(sys.branch(:,13)) .* sys.branch(:,13));
42 | sys.branch(:,16) = -sys.branch(:,11) ./ conj(sys.branch(:,13));
43 | sys.branch(:,17) = -sys.branch(:,11) ./ sys.branch(:,13);
44 | %--------------------------------------------------------------------------
45 |
46 |
47 | %---------------------------Branch-Bus Matrices----------------------------
48 | row = [sys.branch(:,1); sys.branch(:,1)];
49 | col = [sys.branch(:,2); sys.branch(:,3)];
50 |
51 | Ai = sparse(sys.branch(:,1), sys.branch(:,2), 1, sys.Nbr, sys.Nbu);
52 | Yi = sparse(row, col, [sys.branch(:,15); sys.branch(:,16)], sys.Nbr, sys.Nbu);
53 |
54 | Aj = sparse(sys.branch(:,1), sys.branch(:,3), 1, sys.Nbr, sys.Nbu);
55 | Yj = sparse(row, col, [sys.branch(:,17); sys.branch(:,14)], sys.Nbr, sys.Nbu);
56 | %--------------------------------------------------------------------------
57 |
58 |
59 | %--------------------------Diagonal Shunt Matrix---------------------------
60 | sys.ysh = complex(sys.bus(:,7), sys.bus(:,8));
61 | Ysh = sparse(sys.bus(:,1), sys.bus(:,1), sys.ysh, sys.Nbu, sys.Nbu);
62 | %--------------------------------------------------------------------------
63 |
64 |
65 | %-----------------------------Full Bus Matrix------------------------------
66 | sys.Ybu = Ai' * Yi + Aj' * Yj + Ysh;
67 | %--------------------------------------------------------------------------
68 |
69 |
70 | %---------------------------Diagonal Bus Matrix----------------------------
71 | sys.Yii = sparse(sys.Nbu, sys.Nbu);
72 | sys.Yii = spdiags(spdiags(sys.Ybu,0), 0, sys.Yii);
73 | %--------------------------------------------------------------------------
74 |
75 |
76 | %-------------------------Non-diagonal Bus Matrix--------------------------
77 | sys.Yij = sys.Ybu - sys.Yii;
78 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_dc/processing_dcpf.m:
--------------------------------------------------------------------------------
1 | function [pf] = processing_dcpf(sys, pf)
2 |
3 | %--------------------------------------------------------------------------
4 | % Computes the DC power flow (active power flows and injections).
5 | %
6 | % The active power flow for the DC problem is defined as Pij = 1/(tij*xij)
7 | % * (Ti - Tj - fij), and holds Pij = -Pji. Also, the active power injection
8 | % is given as Pi = Ybus*T + Psh + rsh. In general, according to the
9 | % convention, a negative power value indicates the power flow direction in
10 | % a bus, while a positive power value means direction out a bus. Finally,
11 | % the postprocessing time is obtained here.
12 | %--------------------------------------------------------------------------
13 | % Inputs:
14 | % - sys: power system data
15 | % - pf: power flow data
16 | %
17 | % Outputs:
18 | % - pf.Pij: active power flows
19 | % - pf.Pi: active power injections
20 | % - pf.Pg: generation active powers
21 | %--------------------------------------------------------------------------
22 | % Created by Mirsad Cosovic on 2019-02-20
23 | % Last revision by Mirsad Cosovic on 2019-04-21
24 | % MATGRID is released under MIT License.
25 | %--------------------------------------------------------------------------
26 |
27 |
28 | %----------------------Active Power Flow at Branches-----------------------
29 | i = sys.branch(:,2);
30 | j = sys.branch(:,3);
31 |
32 | pf.Pij = sys.branch(:,11) .* (pf.Va(i) - pf.Va(j) - sys.branch(:,8));
33 | %--------------------------------------------------------------------------
34 |
35 |
36 | %------------------Injection Active Power with Slack Bus-------------------
37 | pf.Pi = sys.Ybu * pf.Va + sys.bus(:,16) + sys.bus(:,7);
38 | %--------------------------------------------------------------------------
39 |
40 |
41 | %-----------------Generation Active Power with Slack Bus-------------------
42 | pf.Pg = sys.bus(:,11);
43 | pf.Pg(sys.sck(1)) = pf.Pi(sys.sck(1)) + sys.bus(sys.sck(1),5);
44 | %--------------------------------------------------------------------------
45 |
46 |
47 | %---------------------------Postprocessing Time----------------------------
48 | pf.time.pos = toc;
49 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_dc/result_dcpf.m:
--------------------------------------------------------------------------------
1 | function [re] = result_dcpf(sys, pf)
2 |
3 | %--------------------------------------------------------------------------
4 | % Forms the result data for the DC power flow.
5 | %--------------------------------------------------------------------------
6 | % Inputs:
7 | % - sys: power system data
8 | % - pf: power flow data
9 | %
10 | % Outputs:
11 | % - pf.bus: bus table results
12 | % - pf.branch: branch table results
13 | % - pf.time: time table results
14 | %--------------------------------------------------------------------------
15 | % Created by Mirsad Cosovic on 2019-04-13
16 | % Last revision by Mirsad Cosovic on 2019-04-20
17 | % MATGRID is released under MIT License.
18 | %--------------------------------------------------------------------------
19 |
20 |
21 | %-----------------------Units Conversion and Method------------------------
22 | todeg = 180/pi;
23 | tomw = sys.base;
24 |
25 | re.method = pf.method;
26 | %--------------------------------------------------------------------------
27 |
28 |
29 | %-------------------------------Bus Results--------------------------------
30 | re.bus = table(sys.bus(:,15), pf.Va*todeg, pf.Pi*tomw, pf.Pg*tomw, sys.bus(:,5)*tomw, sys.bus(:,7)*tomw);
31 |
32 | re.bus.Properties.VariableNames = {'Bus' 'Vang' 'Pinj' 'Pgen' 'Pload' 'Psh'};
33 | re.bus.Properties.VariableDescriptions = {'Bus Indexes' 'Bus Voltage Angles' 'Bus Active Power Injections' 'Active Power of Generation Units' 'Active Power of Load Units' 'Active Power of Shunt Elements'};
34 | re.bus.Properties.VariableUnits = {'' 'Degree (deg)' 'Megawatt (MW)' 'Megawatt (MW)' 'Megawatt (MW)' 'Megawatt (MW)'};
35 | %--------------------------------------------------------------------------
36 |
37 |
38 | %-----------------------------Branch Results-------------------------------
39 | re.branch = table(sys.branch(:,9), sys.branch(:,10), pf.Pij*tomw);
40 |
41 | re.branch.Properties.VariableNames = {'From' 'To' 'Pflow'};
42 | re.branch.Properties.VariableDescriptions = {'From Bus Ends' 'To Bus Ends' 'Branch Active Power Flows'};
43 | re.branch.Properties.VariableUnits{3} = 'Megawatt (MW)';
44 | %--------------------------------------------------------------------------
45 |
46 |
47 | %------------------------------Time Results--------------------------------
48 | re.time = table(pf.time.pre, pf.time.con, toc);
49 |
50 | re.time.Properties.VariableNames = {'Preprocess' 'Convergence', 'Postprocess'};
51 | re.time.Properties.VariableDescriptions = {'Preprocessing Time' 'Convergence Time' 'Postprocessing Time'};
52 | re.time.Properties.VariableUnits = {'Second (s)' 'Second (s)' 'Second (s)'};
53 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_dc/solve_dcpf.m:
--------------------------------------------------------------------------------
1 | function [pf] = solve_dcpf(sys)
2 |
3 | %--------------------------------------------------------------------------
4 | % Solves the DC power flow problem and computes the vector of the bus
5 | % voltage angles.
6 | %
7 | % The DC power flow is based on the equation Pg - Pl = Ybus*T + Psh + rsh,
8 | % thus the least-squares solution is T = Ybus \ (Pg - Pl - Psh - rsh).
9 | % Further, the voltage angle on the slack bus is known, and consequently,
10 | % it should be removed from the system. Finally, the preprocessing time is
11 | % over, and the convergence time is obtained here, while the postprocessing
12 | % time is initialized.
13 | %--------------------------------------------------------------------------
14 | % Input:
15 | % - sys: power system data
16 | %
17 | % Outputs:
18 | % - pf.Va: bus voltage angles
19 | % - pf.method: method name
20 | % - pf.grid: name of the analyzed power system
21 | % - pf.time.pre: preprocessing time
22 | % - pf.time.con: convergence time
23 | %--------------------------------------------------------------------------
24 | % Created by Mirsad Cosovic on 2018-06-15
25 | % Last revision by Mirsad Cosovic on 2019-03-27
26 | % MATGRID is released under MIT License.
27 | %--------------------------------------------------------------------------
28 |
29 |
30 | %---------------------------------Method-----------------------------------
31 | pf.method = 'DC Power Flow';
32 | %--------------------------------------------------------------------------
33 |
34 |
35 | %--------------------------B Matix and b Vector----------------------------
36 | sys.Ybu(:,sys.sck(1)) = [];
37 | sys.Ybu(sys.sck(1),:) = [];
38 |
39 | b = sys.bus(:,11) - sys.bus(:,5) - sys.bus(:,16) - sys.bus(:,7);
40 | b(sys.sck(1)) = [];
41 | %--------------------------------------------------------------------------
42 |
43 |
44 | %---------------------------Preprocessing Time-----------------------------
45 | pf.time.pre = toc; tic
46 | %--------------------------------------------------------------------------
47 |
48 |
49 | %---------------------------Bus Voltage Angles-----------------------------
50 | pf.Va = sys.Ybu \ b;
51 | insert = @(a, x, n) cat(1, x(1:n), a, x(n + 1:end));
52 | pf.Va = insert(0, pf.Va, sys.sck(1) - 1);
53 | pf.Va = sys.sck(2) * ones(sys.Nbu,1) + pf.Va;
54 | %--------------------------------------------------------------------------
55 |
56 |
57 | %----------------------------Convergence Time------------------------------
58 | pf.time.con = toc; tic
59 | %------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------
/power_flow/power_flow_dc/ybus_shift_dc.m:
--------------------------------------------------------------------------------
1 | function [sys] = ybus_shift_dc(sys)
2 |
3 | %--------------------------------------------------------------------------
4 | % Builds the Ybus matrix (sys.Nbu x sys.Nbu) and shift angle vector
5 | % (sys.Nbu x 1) for the DC power flow problem.
6 | %
7 | % The DC power flow is based on the power balance equation Pg - Pl = Ybus*T
8 | % + Psh + rsh, where T is the vector of bus voltage angles and Psh is shift
9 | % angle vector. Here, we form Ybus and Psh.
10 | %--------------------------------------------------------------------------
11 | % Input:
12 | % - sys: power system data
13 | %
14 | % Outputs:
15 | % - sys.bus with additional column: (16)shift vector(Psh)
16 | % - sys.branch with additional column: (11)1/(tij*xij)
17 | % - sys.Ybu: Ybus matrix
18 | %--------------------------------------------------------------------------
19 | % Created by Mirsad Cosovic on 2018-06-15
20 | % Last revision by Mirsad Cosovic on 2019-04-15
21 | % MATGRID is released under MIT License.
22 | %--------------------------------------------------------------------------
23 |
24 |
25 | %---------------------------Branch-Bus Matrices----------------------------
26 | sys.branch(:,11) = 1 ./ (sys.branch(:,5) .* sys.branch(:,7));
27 |
28 | row = [sys.branch(:,1); sys.branch(:,1)];
29 | col = [sys.branch(:,2); sys.branch(:,3)];
30 | ind = ones(sys.Nbr,1);
31 |
32 | Ai = sparse(row, col, [ind; -ind], sys.Nbr, sys.Nbu);
33 | Yi = sparse(row, col, [sys.branch(:,11); -sys.branch(:,11)], sys.Nbr, sys.Nbu);
34 | %--------------------------------------------------------------------------
35 |
36 |
37 | %-----------------------------Full Bus Matrix------------------------------
38 | sys.Ybu = Ai' * Yi;
39 | %--------------------------------------------------------------------------
40 |
41 |
42 | %---------------------------Phase Shift Vector-----------------------------
43 | sys.bus(:,16) = -Ai' * (sys.branch(:,11) .* sys.branch(:,8));
44 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/observability/bus_branch_matrix.m:
--------------------------------------------------------------------------------
1 | function [Ai] = bus_branch_matrix(branch, Nbu)
2 |
3 | %--------------------------------------------------------------------------
4 | % Builds the branch to bus incidence matrix
5 | %
6 | % The corresponding matrix describes a directed graph.
7 | %--------------------------------------------------------------------------
8 | % Inputs:
9 | % - branch: from and to bus ends
10 | % - Nbu: number of buses (number of columns)
11 | %
12 | % Output:
13 | % - Ai: branch to bus incidence matrix
14 | %--------------------------------------------------------------------------
15 | % Created by Mirsad Cosovic on 2019-04-17
16 | % Last revision by Mirsad Cosovic on 2019-04-17
17 | % MATGRID is released under MIT License.
18 | %--------------------------------------------------------------------------
19 |
20 |
21 | %---------------------Branch to Bus Incidence Matrix-----------------------
22 | Nbr = size(branch,1);
23 | row = (1:Nbr)';
24 |
25 | row = [row; row];
26 | col = [branch(:,1); branch(:,2)];
27 | ind = ones(Nbr,1);
28 |
29 | Ai = sparse(row, col, [ind; -ind], Nbr, Nbu);
30 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/observability/irrelevant_branches.m:
--------------------------------------------------------------------------------
1 | function [branch, irrelevant, Ai] = irrelevant_branches(se, af, ai, va)
2 |
3 | %--------------------------------------------------------------------------
4 | % Removes irrelevant branches for the DC state estimation.
5 | %
6 | % Function finds irrelevant branches, that have no incident measurements.
7 | % Also, we include the slack bus immediately in the observability analysis.
8 | %--------------------------------------------------------------------------
9 | % Inputs:
10 | % - se: state estimation system data
11 | % - af: active power flow measurement data
12 | % - ai: active power injection measurement data
13 | % - va: voltage angle measurement data
14 | %
15 | % Outputs:
16 | % - branch: indexes of relevant branches
17 | % - irrelevant: indicator of irrelevant branches
18 | % - Ai: branch to bus incidence matrix
19 | %--------------------------------------------------------------------------
20 | % Created by Mirsad Cosovic on 2019-04-04
21 | % Last revision by Mirsad Cosovic on 2019-04-20
22 | % MATGRID is released under MIT License.
23 | %--------------------------------------------------------------------------
24 |
25 |
26 | %--------------------------------Slack Bus---------------------------------
27 | if va.on(se.sck(1)) == 0
28 | va.bus(se.sck(1))= se.sck(1);
29 | end
30 | %--------------------------------------------------------------------------
31 |
32 |
33 | %-----------------------Remove Irrelevant Branches-------------------------
34 | branch = se.branch(:,2:3);
35 |
36 | idxPf1 = ismember(branch, [af.from af.to], 'rows');
37 | idxPf2 = ismember(branch, [af.to af.from], 'rows');
38 | idxPf = idxPf1 | idxPf2;
39 | idxPi = any(ismember(branch, ai.bus), 2);
40 | idxTi = any(ismember(branch, va.bus), 2);
41 |
42 | irrelevant = ~(idxPf | idxPi | idxTi);
43 |
44 | branch(irrelevant,:) = [];
45 |
46 | [Ai] = bus_branch_matrix(branch, se.Nbu);
47 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/observability/observe_dc.m:
--------------------------------------------------------------------------------
1 | function [data, user, se, af, ai] = observe_dc(data, user, se, af, ai, va)
2 |
3 | %--------------------------------------------------------------------------
4 | % Observability analysis using LDL factorization for the DC model.
5 | %
6 | % Using the gain matrix, we observe (G'*G)*T = t. If the matrix G has full
7 | % column rank, these properties will be valid: every columns of G has a
8 | % pivot, the null space of G contains only zero vector T = 0, it means only
9 | % for t = 0 will be T = 0. If there exists an estimate T, which yields a
10 | % nonzero branch flow P = A*T, the system is unobservable, and branches
11 | % with nonzero flows will be unobservable.
12 | %--------------------------------------------------------------------------
13 | % Inputs:
14 | % - data: input power system data
15 | % - user: user inputs
16 | % - se: state estimation system data
17 | % - af: active power flow measurement data
18 | % - ai: active power injection measurement data
19 | % - va: voltage angle measurement data
20 | %
21 | % Outputs:
22 | % - data: measurement data with pseudo-measurements
23 | % - user.list: flag if the system is unobservable
24 | % - se.observe: observability analysis data
25 | % - ai: active power injection measurements with pseudo-measurements
26 | % - af: active power flow measurements with pseudo-measurements
27 | %--------------------------------------------------------------------------
28 | % Created by Mirsad Cosovic on 2019-03-29
29 | % Last revision by Mirsad Cosovic on 2019-04-20
30 | % MATGRID is released under MIT License.
31 | %--------------------------------------------------------------------------
32 |
33 |
34 | %---------------------Processing Inputs and Settings-----------------------
35 | [user] = check_observe(user);
36 | %--------------------------------------------------------------------------
37 |
38 |
39 | %---------------------------Irrelevant Branches----------------------------
40 | [br, ir, Ai] = irrelevant_branches(se, af, ai, va);
41 | %--------------------------------------------------------------------------
42 |
43 |
44 | %-------------------------Observability Analysis---------------------------
45 | [user, se, br, Ai] = unobservable_branches(data, user, se, af, ai, va, br, Ai);
46 | %--------------------------------------------------------------------------
47 |
48 |
49 | %---------------------Islands and Pseudo-measurements----------------------
50 | if ismember('unobservable', user.list)
51 | [se] = observe_islands(se, br, ir, Ai);
52 | [data, se, af, ai] = restore_observability(data, user, se);
53 | end
54 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/observability/observe_islands.m:
--------------------------------------------------------------------------------
1 | function [se] = observe_islands(se, branch, irr, Ai)
2 |
3 | %--------------------------------------------------------------------------
4 | % Forms observe islands.
5 | %
6 | % Observable branches will forms new bus-branch model, and connected part
7 | % of that model will define observable islands.
8 | %--------------------------------------------------------------------------
9 | % Inputs:
10 | % - se: state estimation system data
11 | % - branch: indexes of branches
12 | % - irr: indicator of irrelevant branches
13 | % - Ai: branch to bus incidence matrix
14 | %
15 | % Outputs:
16 | % - se.observe.island with columns:
17 | % (1)bus index; (2)island index
18 | % - se.observe.branch with columns:
19 | % (1)from bus; (2)to bus; (3)indicator observable or unobservable
20 | % (4)indicator irrelevant or relevant
21 | %--------------------------------------------------------------------------
22 | % Created by Mirsad Cosovic on 2019-03-29
23 | % Last revision by Mirsad Cosovic on 2019-04-20
24 | % MATGRID is released under MIT License.
25 | %--------------------------------------------------------------------------
26 |
27 |
28 | %-------------------------Islands and Branch Data--------------------------
29 | A = Ai' * Ai;
30 | G = graph(A);
31 | b = conncomp(G);
32 |
33 | observe = ismember(se.branch(:,2:3), branch, 'row');
34 |
35 | se.observe.island = [se.bus(:,15) b'];
36 | se.observe.branch = [se.branch(:,9:10) observe ~= 0 ~irr];
37 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/observability/restore_observability.m:
--------------------------------------------------------------------------------
1 | function [data, se, af, ai] = restore_observability(data, user, se)
2 |
3 | %--------------------------------------------------------------------------
4 | % Adds pseudo-measurements to restore observability.
5 | %
6 | % The function forms pseudo-measurement list and adds pseudo-measurements.
7 | % Pseudo-measurements are defined as regular measurements from input data,
8 | % but variance of those can be defined separately.
9 | %--------------------------------------------------------------------------
10 | % Inputs:
11 | % - data: input power system data
12 | % - user: user inputs
13 | % - se: state estimation system data
14 | %
15 | % Outputs:
16 | % - data: measurement data with pseudo-measurements
17 | % - se.observe.psm: pseudo-measurement indicators
18 | % - ai: active power injection measurements with pseudo-measurements
19 | % - af: active power flow measurements with pseudo-measurements
20 | %--------------------------------------------------------------------------
21 | % Created by Mirsad Cosovic on 2019-03-29
22 | % Last revision by Mirsad Cosovic on 2019-04-20
23 | % MATGRID is released under MIT License.
24 | %--------------------------------------------------------------------------
25 |
26 |
27 | %-------------------------Pseudo-measurement List--------------------------
28 | fromIsland = se.observe.island(se.branch(:,2),2);
29 | toIsland = se.observe.island(se.branch(:,3),2);
30 |
31 | tie = fromIsland ~= toIsland;
32 | tie = se.branch(tie,2:3);
33 |
34 | injList = unique(tie(:));
35 | floList = [tie; tie(:,2) tie(:,1)];
36 |
37 | Ni = length(injList);
38 | Nf = size(floList,1);
39 | %--------------------------------------------------------------------------
40 |
41 |
42 | %----------------------Pseudo-measurement Jacobians------------------------
43 | temp = data;
44 | temp.legacy.injection(:,4) = 0;
45 | temp.legacy.injection(injList,4) = 1;
46 | [pi] = injection_dcse(temp.legacy.injection, se);
47 |
48 | on = ismember([se.from se.to], [floList(:,1) floList(:,2)], 'rows');
49 | temp.legacy.flow(:,5) = 0;
50 | temp.legacy.flow(on,5) = 1;
51 | [pf] = flow_dcse(temp.legacy.flow, se);
52 |
53 | Hc = [pi.H; pf.H];
54 | % --------------------------------------------------------------------------
55 |
56 |
57 | %--------------------------Restore Observability---------------------------
58 | id = logical(diag(se.D) <= 1e-5);
59 | Te = speye(se.Nbu, se.Nbu);
60 | W = Te(id,:) / se.L;
61 | B = (Hc * se.P * W')';
62 |
63 | [~, R, E] = qr(B,0);
64 | if ~isvector(R)
65 | diagr = abs(diag(R));
66 | else
67 | diagr = R(1);
68 | end
69 |
70 | r = find(diagr >= (10^-5)*diagr(1), 1, 'last');
71 | p = sort(E(1:r));
72 |
73 | if isempty(p)
74 | p = 1;
75 | end
76 | %--------------------------------------------------------------------------
77 |
78 |
79 | %---------------------------Pseudo-measurements----------------------------
80 | inj = (1:Ni)';
81 | inj = injList(ismember(inj, p));
82 |
83 | data.legacy.injection(inj,3) = user.psvar;
84 | data.legacy.injection(inj,4) = 1;
85 |
86 | [ai] = injection_dcse(data.legacy.injection, se);
87 |
88 | flo = (Ni+1:1:Ni+Nf)';
89 | flo = floList(ismember(flo, p),:);
90 | flo = ismember([se.from se.to], flo, 'rows');
91 |
92 | data.legacy.flow(flo,4) = user.psvar;
93 | data.legacy.flow(flo,5) = 1;
94 |
95 | [af] = flow_dcse(data.legacy.flow, se);
96 | %--------------------------------------------------------------------------
97 |
98 |
99 | %----------------------Pseudo-measurement Indicators-----------------------
100 | injOn = data.legacy.injection(:,4);
101 | injOn(inj) = 2;
102 |
103 | floOn = data.legacy.flow(:,5);
104 | floOn(flo) = 2;
105 |
106 | se.observe.psm = [floOn; injOn];
107 | se.observe.psm = find(se.observe.psm == 2);
108 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/observability/unobservable_branches.m:
--------------------------------------------------------------------------------
1 | function [user, se, branch, Ai] = unobservable_branches(data, user, se, af, ai, va, branch, Ai)
2 |
3 | %--------------------------------------------------------------------------
4 | % Observability analysis using LDL factorization for the DC model.
5 | %
6 | % Using the gain matrix, we perform LDL factorization, and for zero pivots,
7 | % we add the pseudo-measurement of the voltage angles at buses that
8 | % corresponding to zero pivots. Then, we solve the DC state estimator
9 | % equation and evaluate branch flows.
10 | %--------------------------------------------------------------------------
11 | % Inputs:
12 | % - data: input power system data
13 | % - user: user inputs
14 | % - se: state estimation system data
15 | % - af: active power flow measurement data
16 | % - ai: active power injection measurement data
17 | % - va: voltage angle measurement data
18 | % - branch: from and to bus ends
19 | % - Ai: branch to bus incidence matrix
20 | %
21 | % Output:
22 | % - user.list: flag if the system is unobservable
23 | % - se.L, se.D, se.P: matrices from LDL factorization
24 | % - branch: observable branches
25 | % - Ai: branch to bus incidence matrix
26 | %--------------------------------------------------------------------------
27 | % Created by Mirsad Cosovic on 2019-03-29
28 | % Last revision by Mirsad Cosovic on 2019-04-20
29 | % MATGRID is released under MIT License.
30 | %--------------------------------------------------------------------------
31 |
32 |
33 | %--------------------------------Slack Bus---------------------------------
34 | if va.on(se.sck(1)) == 0
35 | va.H = [va.H; sparse(1, se.sck(1), 1, 1, se.Nbu)];
36 | end
37 | %--------------------------------------------------------------------------
38 |
39 |
40 | %-------------------------Observability Analysis---------------------------
41 | Pf = 9999;
42 | user.list = [user.list 'unobservable'];
43 |
44 | while sum(Pf)
45 | H = [af.H; ai.H; va.H];
46 | G = H' * H;
47 | [L,D,P] = ldl(G);
48 |
49 | idx = logical(diag(P*D*P') <= 1e-5);
50 | N = sum(idx);
51 |
52 | if N == 0
53 | user.list(end) = [];
54 | break
55 | end
56 |
57 | if Pf == 9999
58 | se.L = L; se.D = D; se.P = P;
59 | end
60 |
61 | H = [H; sparse((1:N)', find(idx), 1, N, se.Nbu)]; %#ok
62 | ta = zeros(se.Nbu,1);
63 | ta(idx) = (1:1:N)';
64 | T = (H' * H) \ ta;
65 | Pf = abs(Ai * T) >= 1e-5;
66 |
67 | nonOb = branch(Pf, :);
68 | idxPf = ismember([se.from se.to], [nonOb; nonOb(:,2) nonOb(:,1)], 'rows');
69 | idxPi = any(ismember(se.bus(:,1), nonOb), 2);
70 |
71 | data.legacy.flow(idxPf,5) = 0;
72 | data.legacy.injection(idxPi,4) = 0;
73 | [af] = flow_dcse(data.legacy.flow, se);
74 | [ai] = injection_dcse(data.legacy.injection, se);
75 |
76 | branch(Pf, :) = [];
77 | [Ai] = bus_branch_matrix(branch, se.Nbu);
78 | end
79 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_ac/branch_data_acse.m:
--------------------------------------------------------------------------------
1 | function [bra] = branch_data_acse(sys)
2 |
3 | %--------------------------------------------------------------------------
4 | % Builds the global branch indexes and parameters.
5 | %
6 | % The function defines branch indexes and parameters that are used for
7 | % branch measurements, active and reactive power flow, and line current
8 | % magnitude and angle measurements.
9 | %--------------------------------------------------------------------------
10 | % Input:
11 | % - sys: power system data
12 | %
13 | % Outputs:
14 | % - bra.no: branch number
15 | % - bra.i: indexies i
16 | % - bra.j : indexies j
17 | % - bra.gij: conductance gij
18 | % - bra.bij: susceptance bij
19 | % - bra.bsi: branch charging susceptances bsi
20 | % - bra.tij: transformer tap ratio magnitude tij
21 | % - bra.pij: transformer tap ratio magnitude pij
22 | % - bra.fij: transformer phase shift angle fij
23 | %--------------------------------------------------------------------------
24 | % Created by Mirsad Cosovic on 2018-08-10
25 | % Last revision by Mirsad Cosovic on 2019-03-27
26 | % MATGRID is released under MIT License.
27 | %--------------------------------------------------------------------------
28 |
29 |
30 | %-------------------------------Branch Data--------------------------------
31 | bra.no = (1:2 * sys.Nbr)';
32 | bra.i = [sys.branch(:,2); sys.branch(:,3)];
33 | bra.j = [sys.branch(:,3); sys.branch(:,2)];
34 | bra.gij = [real(sys.branch(:,11)); real(sys.branch(:,11))];
35 | bra.bij = [imag(sys.branch(:,11)); imag(sys.branch(:,11))];
36 | bra.bsi = [sys.branch(:,6) / 2; sys.branch(:,6) / 2];
37 | bra.tij = [1./sys.branch(:,7); ones(sys.Nbr,1)];
38 | bra.pij = [1./sys.branch(:,7); 1./sys.branch(:,7)];
39 | bra.fij = [sys.branch(:,8); -sys.branch(:,8)];
40 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_ac/compose_flow.m:
--------------------------------------------------------------------------------
1 | function [sys] = compose_flow(flow, sys, bra)
2 |
3 | %--------------------------------------------------------------------------
4 | % Builds data associated with active and reactive power flow measurements.
5 | %
6 | % The function defines the active and reactive power flow measurement data
7 | % according to available measurements (i.e., turn on measurements).
8 | %--------------------------------------------------------------------------
9 | % Inputs:
10 | % - flow: legacy power flow measurement data
11 | % - sys: power system data
12 | % - bra: branch indexes and parameters
13 | %
14 | % Outputs:
15 | % - sys.Pf: set indexes and parameters associated with active power flow
16 | % measurements
17 | % - sys.Qf: set indexes and parameters associated with reactive power
18 | % flow measurements
19 | %--------------------------------------------------------------------------
20 | % Created by Mirsad Cosovic on 2019-02-26
21 | % Last revision by Mirsad Cosovic on 2019-03-27
22 | % MATGRID is released under MIT License.
23 | %--------------------------------------------------------------------------
24 |
25 |
26 | %------------------Active Power Flow Legacy Measurements-------------------
27 | sys.Pf.idx = logical(flow(:,5));
28 | sys.Pf.i = bra.i(sys.Pf.idx);
29 | sys.Pf.j = bra.j(sys.Pf.idx);
30 | sys.Pf.z = flow(sys.Pf.idx,3);
31 | sys.Pf.v = flow(sys.Pf.idx,4);
32 | sys.Pf.N = size(sys.Pf.i,1);
33 |
34 | sys.Pf.gij = bra.gij(sys.Pf.idx);
35 | sys.Pf.bij = bra.bij(sys.Pf.idx);
36 | sys.Pf.tgij = bra.tij(sys.Pf.idx).^2 .* sys.Pf.gij;
37 | sys.Pf.pij = bra.pij(sys.Pf.idx);
38 | sys.Pf.fij = bra.fij(sys.Pf.idx);
39 |
40 | num = (1:sys.Pf.N)';
41 | sys.Pf.jci = [num; num];
42 | sys.Pf.jcj = [sys.Pf.i; sys.Pf.j];
43 | %--------------------------------------------------------------------------
44 |
45 |
46 | %------------------Reactive Power Flow Legacy Measurements-----------------
47 | sys.Qf.idx = logical(flow(:,8));
48 | sys.Qf.i = bra.i(sys.Qf.idx);
49 | sys.Qf.j = bra.j(sys.Qf.idx);
50 | sys.Qf.z = flow(sys.Qf.idx,6);
51 | sys.Qf.v = flow(sys.Qf.idx,7);
52 | sys.Qf.N = size(sys.Qf.i,1);
53 |
54 | sys.Qf.gij = bra.gij(sys.Qf.idx);
55 | sys.Qf.bij = bra.bij(sys.Qf.idx);
56 | sys.Qf.bsi = bra.bsi(sys.Qf.idx);
57 | sys.Qf.tbij = bra.tij(sys.Qf.idx).^2 .* (sys.Qf.bij + sys.Qf.bsi);
58 | sys.Qf.pij = bra.pij(sys.Qf.idx);
59 | sys.Qf.fij = bra.fij(sys.Qf.idx);
60 |
61 | num = (1:sys.Qf.N)';
62 | sys.Qf.jci = [num; num];
63 | sys.Qf.jcj = [sys.Qf.i; sys.Qf.j];
64 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_ac/compose_injection.m:
--------------------------------------------------------------------------------
1 | function [sys] = compose_injection(inj, sys)
2 |
3 | %--------------------------------------------------------------------------
4 | % Builds data associated with active and reactive power injection
5 | % measurements.
6 | %
7 | % The function defines the active and reactive power injection measurement
8 | % data according to available measurements (i.e., turn on measurements).
9 | %--------------------------------------------------------------------------
10 | % Inputs:
11 | % - inj: legacy power injection measurement data
12 | % - sys: power system data
13 | %
14 | % Outputs:
15 | % - sys.Pi: set indexes and parameters associated with active power
16 | % injection measurements
17 | % - sys.Qi: set indexes and parameters associated with reactive power
18 | % injection measurements
19 | %--------------------------------------------------------------------------
20 | % Created by Mirsad Cosovic on 2019-02-26
21 | % Last revision by Mirsad Cosovic on 2019-03-27
22 | % MATGRID is released under MIT License.
23 | %--------------------------------------------------------------------------
24 |
25 |
26 | %---------------Active Power Injection Legacy Measurements-----------------
27 | sys.Pi.idx = logical(inj(:,4));
28 | sys.Pi.z = inj(sys.Pi.idx,2);
29 | sys.Pi.v = inj(sys.Pi.idx,3);
30 | sys.Pi.N = size(sys.Pi.z,1);
31 |
32 | [i, j] = find(sys.Ybu);
33 | sys.Pi.bus = sys.bus(sys.Pi.idx,1);
34 | idx1 = ismember(i, sys.Pi.bus);
35 | sys.Pi.i = i(idx1);
36 | sys.Pi.j = j(idx1);
37 |
38 | Ybus = sys.Ybu(sys.Pi.bus,:);
39 | idx2 = find(Ybus);
40 | [sys.Pi.ii, ~] = find(Ybus);
41 | sys.Pi.Gij = real(Ybus(idx2));
42 | sys.Pi.Bij = imag(Ybus(idx2));
43 |
44 | lnidx = sub2ind(size(sys.Ybu), sys.Pi.bus, sys.Pi.bus);
45 | sys.Pi.Gii = real(sys.Ybu(lnidx));
46 | sys.Pi.Bii = imag(sys.Ybu(lnidx));
47 |
48 | sys.Pi.ij = sys.Pi.i ~= sys.Pi.j;
49 |
50 | [r, c] = find(sys.Yij(sys.Pi.bus,:));
51 | [rr, cc] = find(sys.Yii(sys.Pi.bus,:));
52 |
53 | if sys.Pi.N == 1
54 | sys.Pi.ii = sys.Pi.ii';
55 | sys.Pi.Gij = sys.Pi.Gij';
56 | sys.Pi.Bij = sys.Pi.Bij';
57 | sys.Pi.jci = [rr; r'];
58 | sys.Pi.jcj = [cc; c'];
59 | else
60 | sys.Pi.jci = [rr; r];
61 | sys.Pi.jcj = [cc; c];
62 | end
63 | %--------------------------------------------------------------------------
64 |
65 |
66 | %--------------Reactive Power Injection Legacy Measurements----------------
67 | sys.Qi.idx = logical(inj(:,7));
68 | sys.Qi.z = inj(sys.Qi.idx,5);
69 | sys.Qi.v = inj(sys.Qi.idx,6);
70 | sys.Qi.N = size(sys.Qi.z,1);
71 |
72 | sys.Qi.bus = sys.bus(sys.Qi.idx,1);
73 | idx1 = ismember(i, sys.Qi.bus);
74 | sys.Qi.i = i(idx1);
75 | sys.Qi.j = j(idx1);
76 |
77 | Ybus = sys.Ybu(sys.Qi.bus,:);
78 | idx2 = find(Ybus);
79 | [sys.Qi.ii, ~] = find(Ybus);
80 | sys.Qi.Gij = real(Ybus(idx2));
81 | sys.Qi.Bij = imag(Ybus(idx2));
82 |
83 | lnidx = sub2ind(size(sys.Ybu), sys.Qi.bus, sys.Qi.bus);
84 | sys.Qi.Gii = real(sys.Ybu(lnidx));
85 | sys.Qi.Bii = imag(sys.Ybu(lnidx));
86 |
87 | sys.Qi.ij = sys.Qi.i ~= sys.Qi.j;
88 |
89 | [r, c] = find(sys.Yij(sys.Qi.bus,:));
90 | [rr, cc] = find(sys.Yii(sys.Qi.bus,:));
91 |
92 | if sys.Qi.N == 1
93 | sys.Qi.ii = sys.Qi.ii';
94 | sys.Qi.Gij = sys.Qi.Gij';
95 | sys.Qi.Bij = sys.Qi.Bij';
96 | sys.Qi.jci = [rr; r'];
97 | sys.Qi.jcj = [cc; c'];
98 | else
99 | sys.Qi.jci = [rr; r];
100 | sys.Qi.jcj = [cc; c];
101 | end
102 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_ac/compose_measurement.m:
--------------------------------------------------------------------------------
1 | function [sys, se] = compose_measurement(sys)
2 |
3 | %--------------------------------------------------------------------------
4 | % Builds data associated with all available measurements.
5 | %
6 | % The function defines the the total number of measurements, and forms
7 | % vectors of measurement values and variances, and the diagonal weighted
8 | % matrix.
9 | %--------------------------------------------------------------------------
10 | % Input:
11 | % - sys: power system data
12 | %
13 | % Outputs:
14 | % - sys.Nleg: number of legacy measurements
15 | % - sys.Npmu: number of phasor measurements
16 | % - sys.Ntot: total number of measurements
17 | % - se.estimate with columns:
18 | % (1)measurement values; (2)measurement variances
19 | % - sys.W: diagonal weighted matrix
20 | %--------------------------------------------------------------------------
21 | % Created by Mirsad Cosovic on 2019-02-26
22 | % Last revision by Mirsad Cosovic on 2019-03-27
23 | % MATGRID is released under MIT License.
24 | %--------------------------------------------------------------------------
25 |
26 |
27 | %--------------------------Compose Measurements----------------------------
28 | sys.Nleg = sys.Pf.N + sys.Qf.N + sys.Cm.N + sys.Pi.N + sys.Qi.N + sys.Vml.N;
29 | sys.Npmu = sys.Vmp.N + sys.Vap.N + sys.Cmp.N + sys.Cap.N;
30 | sys.Ntot = sys.Nleg + sys.Npmu;
31 |
32 | se.estimate = [sys.Pf.z; sys.Qf.z; sys.Cm.z; sys.Pi.z; sys.Qi.z; sys.Vml.z; ...
33 | sys.Vmp.z; sys.Vap.z; sys.Cmp.z; sys.Cap.z];
34 |
35 | se.estimate(:,2) = [sys.Pf.v; sys.Qf.v; sys.Cm.v; sys.Pi.v; sys.Qi.v; sys.Vml.v; ...
36 | sys.Vmp.v; sys.Vap.v; sys.Cmp.v; sys.Cap.v];
37 |
38 | sys.C = spdiags(se.estimate(:,2), 0, sys.Ntot, sys.Ntot);
39 | sys.W = sys.C \ speye(sys.Ntot, sys.Ntot);
40 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_ac/compose_voltage.m:
--------------------------------------------------------------------------------
1 | function [sys] = compose_voltage(leg, pmu, sys)
2 |
3 | %--------------------------------------------------------------------------
4 | % Builds data associated with voltage measurements, and forms associated
5 | % Jacobian matrix.
6 | %
7 | % The function defines the voltage measurement data according to available
8 | % legacy and phasor measurements (i.e., turn on measurements).
9 | %--------------------------------------------------------------------------
10 | % Inputs:
11 | % - leg: legacy voltage magnitude measurement data
12 | % - pmu: phasor voltage measurement data
13 | % - sys: power system data
14 | %
15 | % Outputs:
16 | % - sys.Vml: set indexes and parameters associated with legacy voltage
17 | % magnitude measurements
18 | % - sys.Vmp: set indexes and parameters associated with phasor voltage
19 | % magnitude measurements
20 | % - sys.Vap: set indexes and parameters associated with phasor voltage
21 | % angle measurements
22 | % - sys.Jvol: Jacobian matrix associated with voltage measurements
23 | %--------------------------------------------------------------------------
24 | % Created by Mirsad Cosovic on 2019-02-26
25 | % Last revision by Mirsad Cosovic on 2019-03-27
26 | % MATGRID is released under MIT License.
27 | %--------------------------------------------------------------------------
28 |
29 |
30 | %------------------Voltage Magnitude Legacy Measurements-------------------
31 | sys.Vml.idx = logical(leg(:,4));
32 | sys.Vml.i = sys.bus(sys.Vml.idx,1);
33 | sys.Vml.z = leg(sys.Vml.idx, 2);
34 | sys.Vml.v = leg(sys.Vml.idx, 3);
35 | sys.Vml.N = size(sys.Vml.i,1);
36 | %--------------------------------------------------------------------------
37 |
38 |
39 | %-------------------Voltage Magnitude PMU Measurements---------------------
40 | sys.Vmp.idx = logical(pmu(:,4));
41 | sys.Vmp.i = sys.bus(sys.Vmp.idx,1);
42 | sys.Vmp.z = pmu(sys.Vmp.idx,2);
43 | sys.Vmp.v = pmu(sys.Vmp.idx,3);
44 | sys.Vmp.N = size(sys.Vmp.i,1);
45 | %--------------------------------------------------------------------------
46 |
47 |
48 | %---------------------Voltage Angle PMU Measurements-----------------------
49 | sys.Vap.idx = logical(pmu(:,7));
50 | sys.Vap.i = sys.bus(sys.Vap.idx,1);
51 | sys.Vap.z = pmu(sys.Vap.idx,5);
52 | sys.Vap.v = pmu(sys.Vap.idx,6);
53 | sys.Vap.N = size(sys.Vap.i,1);
54 | %--------------------------------------------------------------------------
55 |
56 |
57 | %------------------Voltage Magnitude and Angle Jacobian--------------------
58 | Vleg_V = sparse((1:sys.Vml.N)', sys.Vml.i, 1, sys.Vml.N, sys.Nbu);
59 | Vleg_T = sparse(sys.Vml.N, sys.Nbu);
60 |
61 | Vpmu_V = sparse((1:sys.Vmp.N)', sys.Vmp.i, 1, sys.Vmp.N, sys.Nbu);
62 | Vpmu_T = sparse(sys.Vmp.N, sys.Nbu);
63 |
64 | Tpmu_V = sparse(sys.Vap.N, sys.Nbu);
65 | Tpmu_T = sparse((1:sys.Vap.N)', sys.Vap.i, 1, sys.Vap.N, sys.Nbu);
66 |
67 | sys.Jv = [Vleg_T Vleg_V; Vpmu_T Vpmu_V; Tpmu_T Tpmu_V];
68 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_ac/evaluation_acse.m:
--------------------------------------------------------------------------------
1 | function [sys, se] = evaluation_acse(data, sys, se)
2 |
3 | %--------------------------------------------------------------------------
4 | % Computes different metrics used to measure the accuracy of the non-linear
5 | % state estimation.
6 | %
7 | % The function computes the root mean squared error (RMSE), mean absolute
8 | % error (MAE) and weighted residual sum of squares (WRSS) between estimated
9 | % values and: i) corresponding measurement values; ii) corresponding exact
10 | % values
11 | %--------------------------------------------------------------------------
12 | % Inputs:
13 | % - data: input power system data with measurements
14 | % - sys: power system data
15 | % - se: state estimation data
16 | %
17 | % Outputs:
18 | % - se.estimate with additional columns:
19 | % (3)estimated measurement values; (5) exact values
20 | % - se.error.mae1, se.error.rmse1, se.error.wrss1: errors between
21 | % estimated values and corresponding measurement values
22 | % - se.error.mae2, se.error.rmse2, se.error.wrss2: errors between
23 | % estimated values and corresponding exact values
24 | % - se.error.mae3, se.error.rmse3: errors between estimated state
25 | % variables and corresponding exact values
26 | % - sys.exact: flag for exact values
27 | %--------------------------------------------------------------------------
28 | % Created by Mirsad Cosovic on 2019-02-26
29 | % Last revision by Mirsad Cosovic on 2019-03-27
30 | % MATGRID is released under MIT License.
31 | %--------------------------------------------------------------------------
32 |
33 |
34 | %---------------------------Measurement Values-----------------------------
35 | V = abs(se.Vc);
36 | T = angle(se.Vc);
37 |
38 | [Ff, ~] = flow_acse(V, T, sys.Pf, sys.Qf, sys.Nbu);
39 | [Fc, ~] = current_acse(V, T, sys.Cm, sys.Nbu);
40 | [Fi, ~] = injection_acse(V, T, sys.Pi, sys.Qi, sys.Nbu);
41 | [Fp, ~] = current_ph_acse(V, T, sys.Cmp, sys.Cap, sys.Nbu);
42 | [Fv] = voltage_acse(V, T, sys.Vml.i, sys.Vmp.i, sys.Vap.i);
43 |
44 | se.estimate(:,3) = [Ff; Fc; Fi; Fv; Fp];
45 | %--------------------------------------------------------------------------
46 |
47 |
48 | %------------------------------Exact Values--------------------------------
49 | try
50 | se.exact = 1;
51 | se.estimate(:,5) = [data.legacy.flow(sys.Pf.idx,9); data.legacy.flow(sys.Qf.idx,10);
52 | data.legacy.current(sys.Cm.idx,6); data.legacy.injection(sys.Pi.idx,8);
53 | data.legacy.injection(sys.Qi.idx,9); data.legacy.voltage(sys.Vml.idx,5);
54 | data.pmu.voltage(sys.Vmp.idx,8); data.pmu.voltage(sys.Vap.idx,9);
55 | data.pmu.current(sys.Cmp.idx,9); data.pmu.current(sys.Cap.idx,10)];
56 |
57 | sv_true = [data.pmu.voltage(:,8); data.pmu.voltage(:,9)];
58 | sv_esti = [V; T];
59 | catch
60 | se.exact = 0;
61 | end
62 | %--------------------------------------------------------------------------
63 |
64 |
65 | %-----------------Estimated Values to Measurement Values-------------------
66 | d1 = se.estimate(:,3) - se.estimate(:,1);
67 |
68 | MAE = sum(abs(d1)) / sys.Ntot;
69 | RMSE = ((sum(d1.^2)) / sys.Ntot)^(1/2);
70 | WRSS = sum(((d1.^2)) ./ se.estimate(:,2));
71 |
72 | se.error = [MAE; RMSE; WRSS];
73 | %--------------------------------------------------------------------------
74 |
75 |
76 | %--------------------Estimated Values to Exact Values----------------------
77 | if se.exact == 1
78 | d2 = se.estimate(:,3) - se.estimate(:,5);
79 | d3 = sv_esti - sv_true;
80 |
81 | MAE2 = sum(abs(d2)) / sys.Ntot;
82 | MAE3 = sum(abs(d3)) / (2 * sys.Nbu);
83 |
84 | RMSE2 = ((sum(d2).^2) / sys.Ntot)^(1/2);
85 | RMSE3 = ((sum(d3).^2)/ (2 * sys.Nbu))^(1/2);
86 |
87 | WRSS2 = sum(((d2).^2) ./ se.estimate(:,2));
88 |
89 | se.error(:,2) = [MAE2; RMSE2; WRSS2];
90 | se.error(:,3) = [MAE3; RMSE3; 0];
91 | end
92 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_ac/gauss_newton/current_acse.m:
--------------------------------------------------------------------------------
1 | function [Fc, Jc] = current_acse(V, T, c, Nbu)
2 |
3 | %--------------------------------------------------------------------------
4 | % Computes the legacy line current magnitude functions and corresponding
5 | % Jacobian matrices.
6 | %
7 | % The function computes values of function Iij(V,T), and a partial
8 | % derivative of function Iij with respect to bus voltage angles and
9 | % magnitudes.
10 | %--------------------------------------------------------------------------
11 | % Inputs:
12 | % - V: bus voltage magnitude vector
13 | % - T: bus voltage angle vector
14 | % - c: set indexes and parameters associated with line current magnitude
15 | % measurements
16 | % - Nbu: number of buses
17 | %
18 | % Outputs:
19 | % - Fc: vector associated with line current magnitude measurement values
20 | % - Jc: Jacobian matrix associated with line current magnitude
21 | % measurements
22 | %--------------------------------------------------------------------------
23 | % Created by Mirsad Cosovic on 2019-02-26
24 | % Last revision by Mirsad Cosovic on 2019-03-27
25 | % MATGRID is released under MIT License.
26 | %--------------------------------------------------------------------------
27 |
28 |
29 | %---------------------Line Current Magnitude Function----------------------
30 | U = T(c.i) - T(c.j) - c.fij;
31 | Vi = V(c.i);
32 | Vj = V(c.j);
33 |
34 | Tc1 = c.C .* cos(U) - c.D .* sin(U);
35 | Fc = (c.A .* Vi.^2 + c.B .* Vj.^2 - 2 * Vi .* Vj .* Tc1).^(1/2);
36 | %--------------------------------------------------------------------------
37 |
38 |
39 | %---------------------Line Current Magnitude Jacobian----------------------
40 | Tc2 = c.C .* sin(U) + c.D .* cos(U);
41 | Iij_Ti = Vi .* Vj .* Tc2 ./ Fc;
42 | Iij_Tj = -Iij_Ti;
43 |
44 | Iij_Vi = (-Vj .* Tc1 + c.A .* Vi) ./ Fc;
45 | Iij_Vj = (-Vi .* Tc1 + c.B .* Vj) ./ Fc;
46 |
47 | J31 = sparse(c.jci, c.jcj, [Iij_Ti; Iij_Tj], c.N, Nbu);
48 | J32 = sparse(c.jci, c.jcj, [Iij_Vi; Iij_Vj], c.N, Nbu);
49 |
50 | Jc = [J31 J32];
51 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_ac/gauss_newton/current_ph_acse.m:
--------------------------------------------------------------------------------
1 | function [Fp, Jp] = current_ph_acse (V, T, m, a, Nbu)
2 |
3 | %--------------------------------------------------------------------------
4 | % Computes the line current magnitude and angles functions and
5 | % corresponding Jacobian matrices.
6 | %
7 | % The function computes values of functions Iij(V,T) nad Fij(V,T), and a
8 | % partial derivative of functions Iij and Fij with respect to bus voltage
9 | % angles and magnitudes.
10 | %--------------------------------------------------------------------------
11 | % Inputs:
12 | % - V: bus voltage magnitude vector
13 | % - T: bus voltage angle vector
14 | % - m: set indexes and parameters associated with line current magnitude
15 | % measurements
16 | % - a: set indexes and parameters associated with line current angle
17 | % measurements
18 | % - Nbu: number of buses
19 | %
20 | % Outputs:
21 | % - Fp: vector associated with line current measurement values
22 | % - Jp: Jacobian matrix associated with line current measurements
23 | %--------------------------------------------------------------------------
24 | % Created by Mirsad Cosovic on 2019-02-26
25 | % Last revision by Mirsad Cosovic on 2019-03-27
26 | % MATGRID is released under MIT License.
27 | %--------------------------------------------------------------------------
28 |
29 |
30 | %---------------------Line Current Magnitude Function----------------------
31 | U = T(m.i) - T(m.j) - m.fij;
32 | Vi = V(m.i);
33 | Vj = V(m.j);
34 |
35 | Tm1 = m.C .* cos(U) - m.D .* sin(U);
36 | Fm = (m.A .* Vi.^2 + m.B .* Vj.^2 - 2 * Vi .* Vj .* Tm1).^(1/2);
37 | %--------------------------------------------------------------------------
38 |
39 |
40 | %---------------------Line Current Magnitude Jacobian----------------------
41 | Tm2 = m.C .* sin(U) + m.D .* cos(U);
42 | Iij_Ti = Vi .* Vj .* Tm2 ./ Fm;
43 | Iij_Tj = -Iij_Ti;
44 |
45 | Iij_Vi = (-Vj .* Tm1 + m.A .* Vi) ./ Fm;
46 | Iij_Vj = (-Vi .* Tm1 + m.B .* Vj) ./ Fm;
47 |
48 | J61 = sparse(m.jci, m.jcj, [Iij_Ti; Iij_Tj], m.N, Nbu);
49 | J62 = sparse(m.jci, m.jcj, [Iij_Vi; Iij_Vj], m.N, Nbu);
50 | %--------------------------------------------------------------------------
51 |
52 |
53 | %-----------------------Line Current Angle Function------------------------
54 | U = T(a.j) + a.fij;
55 | Ti = T(a.i);
56 | Vi = V(a.i);
57 | Vj = V(a.j);
58 |
59 | Iijc = (a.Aa.*cos(Ti) - a.Ba.*sin(Ti)).*Vi - (a.Ca.*cos(U) - a.Da.*sin(U)).*Vj + ...
60 | 1i* ((a.Aa.*sin(Ti) + a.Ba.*cos(Ti)).*Vi - (a.Ca.*sin(U) + a.Da.*cos(U)).*Vj);
61 | Fa = angle(Iijc);
62 | Fma = abs(Iijc).^2;
63 | %--------------------------------------------------------------------------
64 |
65 |
66 | %----------------------Line Angle Magnitude Jacobian-----------------------
67 | U = T(a.i) - T(a.j) - a.fij;
68 | Tm1 = a.Cc .* cos(U) - a.Dc .* sin(U);
69 |
70 | Ta1 = - Vi .* Vj .* Tm1;
71 | Bij_Ti = (a.Ac .* Vi.^2 + Ta1) ./ Fma;
72 | Bij_Tj = (a.Bc .* Vj.^2 + Ta1) ./ Fma;
73 |
74 | Ta2 = a.Cc .* sin(U) + a.Dc .* cos(U);
75 | Bij_Vi = -Vj .* Ta2 ./ Fma;
76 | Bij_Vj = Vi .* Ta2 ./ Fma;
77 |
78 | J71 = sparse(a.jci, a.jcj, [Bij_Ti; Bij_Tj], a.N, Nbu);
79 | J72 = sparse(a.jci, a.jcj, [Bij_Vi; Bij_Vj], a.N, Nbu);
80 | %--------------------------------------------------------------------------
81 |
82 |
83 | %-----------------------Line Current Phasor Jacobian-----------------------
84 | Fp = [Fm; Fa];
85 | Jp = [J61 J62; J71 J72];
86 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_ac/gauss_newton/flow_acse.m:
--------------------------------------------------------------------------------
1 | function [Ff, Jf] = flow_acse(V, T, p, q, Nbu)
2 |
3 | %--------------------------------------------------------------------------
4 | % Computes the active and reactive power flow functions and corresponding
5 | % Jacobian matrices.
6 | %
7 | % The function computes values of functions Pij(V,T) and Qij(V,T), and a
8 | % partial derivative of functions Pij and Qij with respect to bus voltage
9 | % angles and magnitudes.
10 | %--------------------------------------------------------------------------
11 | % Inputs:
12 | % - V: bus voltage magnitude vector
13 | % - T: bus voltage angle vector
14 | % - p: set indexes and parameters associated with active power flow
15 | % measurements
16 | % - q: set indexes and parameters associated with active power flow
17 | % measurements
18 | % - Nbu: number of buses
19 | %
20 | % Outputs:
21 | % - Ff: vector associated with power flow measurement values
22 | % - Jf: Jacobian matrix associated with power flow measurements
23 | %--------------------------------------------------------------------------
24 | % Created by Mirsad Cosovic on 2019-02-26
25 | % Last revision by Mirsad Cosovic on 2019-03-27
26 | % MATGRID is released under MIT License.
27 | %--------------------------------------------------------------------------
28 |
29 |
30 | %-----------------------Active Power Flow Function-------------------------
31 | U = T(p.i) - T(p.j) - p.fij;
32 | Vi = V(p.i);
33 | Vj = V(p.j);
34 |
35 | Tp1 = p.gij .* cos(U) + p.bij .* sin(U);
36 | Pij = Vi.^2 .* p.tgij - p.pij .* Vi .* Vj .* Tp1;
37 | %--------------------------------------------------------------------------
38 |
39 |
40 | %-----------------------Active Power Flow Jacobian-------------------------
41 | Tp2 = p.gij .* sin(U) - p.bij .* cos(U);
42 | Pij_Ti = p.pij .* Vi .* Vj .* Tp2;
43 | Pij_Tj = -Pij_Ti;
44 |
45 | Pij_Vi = 2 * p.tgij .* Vi - p.pij .* Vj .* Tp1;
46 | Pij_Vj = -p.pij .* Vi .* Tp1 ;
47 |
48 | J11 = sparse(p.jci, p.jcj, [Pij_Ti; Pij_Tj], p.N, Nbu);
49 | J12 = sparse(p.jci, p.jcj, [Pij_Vi; Pij_Vj], p.N, Nbu);
50 | %--------------------------------------------------------------------------
51 |
52 |
53 | %----------------------Reactive Power Flow Function------------------------
54 | U = T(q.i) - T(q.j) - q.fij;
55 | Vi = V(q.i);
56 | Vj = V(q.j);
57 |
58 | Tq1 = q.gij .* sin(U) - q.bij .* cos(U);
59 | Qij = - q.tbij .* Vi.^2 - q.pij .* Vi .* Vj .* Tq1;
60 | %--------------------------------------------------------------------------
61 |
62 |
63 | %----------------------Reactive Power Flow Jacobian------------------------
64 | Tq2 = q.gij .* cos(U) + q.bij .* sin(U);
65 | Qij_Ti = -q.pij .* Vi .* Vj .* Tq2;
66 | Qij_Tj = -Qij_Ti;
67 |
68 | Qij_Vi = - 2 * q.tbij .* Vi - q.pij .* Vj .* Tq1;
69 | Qij_Vj = -q.pij .* Vi .* Tq1;
70 |
71 | J21 = sparse(q.jci, q.jcj, [Qij_Ti; Qij_Tj], q.N, Nbu);
72 | J22 = sparse(q.jci, q.jcj, [Qij_Vi; Qij_Vj], q.N, Nbu);
73 | %--------------------------------------------------------------------------
74 |
75 |
76 | %--------------------Power Flow Function and Jacobian----------------------
77 | Ff = [Pij; Qij];
78 | Jf = [J11 J12; J21 J22];
79 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_ac/gauss_newton/gauss_newton.m:
--------------------------------------------------------------------------------
1 | function [se] = gauss_newton(user, sys, se, data)
2 |
3 | %--------------------------------------------------------------------------
4 | % Solves the non-linear state estimation problem and computes the complex
5 | % bus voltages.
6 | %
7 | % The function uses the Gauss-Newton method to solve non-linear state
8 | % estimation problem. Also, the preprocessing time is over, and the
9 | % convergence time is obtained here, while the postprocessing time is
10 | % initialized.
11 | %--------------------------------------------------------------------------
12 | % Inputs:
13 | % - user: user inputs
14 | % - sys: power system data
15 | % - se: state estimation data
16 | % - data: power system data with measurement data
17 | %
18 | % Outputs:
19 | % - se.bus with column: (1)complex bus voltages
20 | % - se.time.pre: preprocessing time
21 | % - se.time.conv: convergence time
22 | % - se.No: number of iterations
23 | %--------------------------------------------------------------------------
24 | % Created by Mirsad Cosovic on 2019-02-26
25 | % Last revision by Mirsad Cosovic on 2019-03-27
26 | % MATGRID is released under MIT License.
27 | %--------------------------------------------------------------------------
28 |
29 |
30 | %-----------------------------Initialization-------------------------------
31 | se.method = 'Non-linear State Estimation using Gauss-Newton Method';
32 | [T, V] = initial_point_acse(user, sys, data);
33 |
34 | x = [T; V];
35 | z = se.estimate(:,1);
36 | No = 0;
37 | eps = 9999;
38 | %--------------------------------------------------------------------------
39 |
40 |
41 | %---------------------------Preprocessing Time-----------------------------
42 | se.time.pre = toc; tic
43 | %--------------------------------------------------------------------------
44 |
45 |
46 | %===========================Gauss-Newton Method============================
47 | while eps > sys.stop && No < user.maxIter
48 | No = No+1;
49 |
50 | %----------------------Vector f(x) and Jacobian H(x)-----------------------
51 | [Ff, Jf] = flow_acse(V, T, sys.Pf, sys.Qf, sys.Nbu);
52 | [Fc, Jc] = current_acse(V, T, sys.Cm, sys.Nbu);
53 | [Fi, Ji] = injection_acse(V, T, sys.Pi, sys.Qi, sys.Nbu);
54 | [Fp, Jp] = current_ph_acse(V, T, sys.Cmp, sys.Cap, sys.Nbu);
55 | [Fv] = voltage_acse(V, T, sys.Vml.i, sys.Vmp.i, sys.Vap.i);
56 |
57 | f = [Ff; Fc; Fi; Fv; Fp];
58 | H = [Jf; Jc; Ji; sys.Jv; Jp];
59 |
60 | H(:, sys.sck(1)) = [];
61 | %--------------------------------------------------------------------------
62 |
63 |
64 | %---------------------------------Delta x----------------------------------
65 | dx = (H' * sys.W * H) \ (H' * sys.W * (z - f));
66 |
67 | ins = @(a, x, n) cat(1, x(1:n), a, x(n + 1:end));
68 | dx = ins(0, dx, sys.sck(1) - 1);
69 | %--------------------------------------------------------------------------
70 |
71 |
72 | %-----------------------------Postprocessing-------------------------------
73 | x = x + dx;
74 |
75 | T = x(1:sys.Nbu);
76 | V = x(sys.Nbu + 1:end);
77 |
78 | eps = norm(dx, inf);
79 | %--------------------------------------------------------------------------
80 |
81 | end
82 | %==========================================================================
83 |
84 |
85 | %--------------------------------Save Data---------------------------------
86 | se.time.con = toc; tic
87 | se.Vc = V .* exp(T * 1i);
88 | se.iteration = No;
89 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_ac/gauss_newton/initial_point_acse.m:
--------------------------------------------------------------------------------
1 | function [T, V] = initial_point_acse(user, sys, data)
2 |
3 | %--------------------------------------------------------------------------
4 | % Defines the initial point for the Gauss-Newton algorithm.
5 | %
6 | % The function according to user input defines different initial points for
7 | % the Gauss-Newton algorithm: flat start, warm star or start with random
8 | % perturbation.
9 | %--------------------------------------------------------------------------
10 | % Inputs:
11 | % - user: user inputs
12 | % - sys: power system data
13 | % - data: power system data with measurement data
14 | %
15 | % Outputs:
16 | % - T: vector of initial bus voltage angles
17 | % - V: vector of initial bus voltage magnitudes
18 | %--------------------------------------------------------------------------
19 | % Created by Mirsad Cosovic on 2019-02-26
20 | % Last revision by Mirsad Cosovic on 2019-03-27
21 | % MATGRID is released under MIT License.
22 | %--------------------------------------------------------------------------
23 |
24 |
25 | %-------------------------------Flat Start---------------------------------
26 | if ismember('flat', user.list)
27 | T = pi/180 * user.flat(1) * ones(sys.Nbu,1);
28 | T(sys.sck(1)) = sys.sck(2);
29 | V = user.flat(2) * ones(sys.Nbu,1);
30 | end
31 | %--------------------------------------------------------------------------
32 |
33 |
34 | %-------------------------------Warm Start---------------------------------
35 | if ismember('exact', user.list)
36 | try
37 | T = data.pmu.voltage(:,9);
38 | V = data.pmu.voltage(:,8);
39 | catch
40 | rem = ismember(user.list, 'exact');
41 | user.list(rem) = [];
42 | user.list = [user.list, 'warm'];
43 | warning('se:startExact','Exact values were not found. The algorithm proceeds with the same initial point as the one applied in AC power flow.\n')
44 | end
45 | end
46 | if ismember('warm', user.list)
47 | [sys] = bus_generator(sys);
48 | T = sys.bus(:,4);
49 | V = sys.bus(:,3);
50 | end
51 | %--------------------------------------------------------------------------
52 |
53 |
54 | %---------------------Start with Random Perturbation-----------------------
55 | if ismember('random', user.list)
56 | a = pi/180 * [user.random(1) user.random(2)];
57 | T = (max(a)-min(a)).*rand(sys.Nbu,1) + min(a);
58 | T(sys.sck(1)) = sys.sck(2);
59 | a = [user.random(3) user.random(4)];
60 | V = (max(a)-min(a)).*rand(sys.Nbu,1) + min(a);
61 | end
62 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_ac/gauss_newton/injection_acse.m:
--------------------------------------------------------------------------------
1 | function [Fi, Ji] = injection_acse(V, T, p, q, Nbu)
2 |
3 | %--------------------------------------------------------------------------
4 | % Computes the active and reactive power injection functions and
5 | % corresponding Jacobian matrices.
6 | %
7 | % The function computes values of functions Pi(V,T) and Qi(V,T), and a
8 | % partial derivative of functions Pi and Qi with respect to bus voltage
9 | % angles and magnitudes.
10 | %--------------------------------------------------------------------------
11 | % Inputs:
12 | % - V: bus voltage magnitude vector
13 | % - T: bus voltage angle vector
14 | % - p: set indexes and parameters associated with active power injection
15 | % measurements
16 | % - q: set indexes and parameters associated with reactive power
17 | % injection measurements
18 | % - Nbu: number of buses
19 | %
20 | % Outputs:
21 | % - Fi: vector associated with power injection measurement values
22 | % - Ji: Jacobian matrix associated with power injection measurements
23 | %--------------------------------------------------------------------------
24 | % Created by Mirsad Cosovic on 2019-02-26
25 | % Last revision by Mirsad Cosovic on 2019-03-27
26 | % MATGRID is released under MIT License.
27 | %--------------------------------------------------------------------------
28 |
29 |
30 | %-------------------------Active Power Injection---------------------------
31 | U = T(p.i) - T(p.j);
32 | Vi = V(p.i);
33 | Vj = V(p.j);
34 | Vb = V(p.bus);
35 |
36 | Tp1 = p.Gij .* cos(U) + p.Bij .* sin(U);
37 | Pi = Vb .* sparse(p.ii, p.j, Tp1, p.N, Nbu) * V;
38 | %--------------------------------------------------------------------------
39 |
40 |
41 | %---------------------Active Power Injection Jacobian----------------------
42 | Tp2 = -p.Gij .* sin(U) + p.Bij .* cos(U);
43 | Pi_Ti = Vb .* sparse(p.ii, p.j, Tp2, p.N, Nbu) * V - Vb.^2 .* p.Bii;
44 | Pi_Tj = -Vi(p.ij) .* Vj(p.ij) .* Tp2(p.ij);
45 |
46 | Pi_Vi = sparse(p.ii, p.j, Tp1, p.N, Nbu) * V + Vb .* p.Gii;
47 | Pi_Vj = Vi(p.ij) .* Tp1(p.ij);
48 |
49 | J41 = sparse(p.jci, p.jcj, [Pi_Ti; Pi_Tj], p.N, Nbu);
50 | J42 = sparse(p.jci, p.jcj, [Pi_Vi; Pi_Vj], p.N, Nbu);
51 | %--------------------------------------------------------------------------
52 |
53 |
54 | %------------------------Reactive Power Injection--------------------------
55 | U = T(q.i) - T(q.j);
56 | Vi = V(q.i);
57 | Vj = V(q.j);
58 | Vb = V(q.bus);
59 |
60 | Tq1 = q.Gij .* sin(U) - q.Bij .* cos(U);
61 | Qi = Vb .* sparse(q.ii, q.j, Tq1, q.N, Nbu) * V;
62 | %--------------------------------------------------------------------------
63 |
64 |
65 | %--------------------Reactive Power Injection Jacobian---------------------
66 | Tq2 = q.Gij .* cos(U) + q.Bij .* sin(U);
67 | Qi_Ti = Vb .* sparse(q.ii, q.j, Tq2, q.N, Nbu) * V - Vb.^2 .* q.Gii;
68 | Qi_Tj = -Vi(q.ij) .* Vj(q.ij) .* Tq2(q.ij);
69 |
70 | Qi_Vi = sparse(q.ii, q.j, Tq1, q.N, Nbu) * V - Vb .* q.Bii;
71 | Qi_Vj = Vi(q.ij) .* Tq1(q.ij);
72 |
73 | J51 = sparse(q.jci, q.jcj, [Qi_Ti; Qi_Tj], q.N, Nbu);
74 | J52 = sparse(q.jci, q.jcj, [Qi_Vi; Qi_Vj], q.N, Nbu);
75 | %--------------------------------------------------------------------------
76 |
77 |
78 | %------------------Power Injection Function and Jacobian-------------------
79 | Fi = [Pi; Qi];
80 | Ji = [J41 J42; J51 J52];
81 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_ac/gauss_newton/voltage_acse.m:
--------------------------------------------------------------------------------
1 | function [Fv] = voltage_acse(V, T, ml, mp, ap)
2 |
3 | %--------------------------------------------------------------------------
4 | % Computes the line current magnitude and angles functions and
5 | % corresponding Jacobian matrices.
6 | %
7 | % The function computes values of functions Iij(V,T) nad Fij(V,T) and a
8 | % partial derivative of functions Iij and Fij with respect to bus voltage
9 | % angles and magnitudes.
10 | %--------------------------------------------------------------------------
11 | % Inputs:
12 | % - V: bus voltage magnitude vector
13 | % - T: bus voltage angle vector
14 | % - ml: indexes associated with legacy bus voltage magnitude
15 | % measurements
16 | % - mp: indexes associated with PMU bus voltage magnitude
17 | % measurements
18 | % - ap: indexes associated with PMU bus voltage angle
19 | % measurements
20 | % - Nbu: number of buses
21 | %
22 | % Output:
23 | % - Fv: vector associated with bus voltage measurement values
24 | %--------------------------------------------------------------------------
25 | % Created by Mirsad Cosovic on 2019-02-26
26 | % Last revision by Mirsad Cosovic on 2019-03-27
27 | % MATGRID is released under MIT License.
28 | %--------------------------------------------------------------------------
29 |
30 |
31 | %------------------Voltage Magnitude and Angle Function--------------------
32 | Fv = [V(ml); V(mp); T(ap)];
33 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_dc/error_dcse.m:
--------------------------------------------------------------------------------
1 | function [se] = error_dcse(data, se)
2 |
3 | %--------------------------------------------------------------------------
4 | % Computes different metrics used to measure the accuracy of the DC state
5 | % estimation.
6 | %
7 | % The function computes the root mean squared error (RMSE), mean absolute
8 | % error (MAE) and weighted residual sum of squares (WRSS) between estimated
9 | % values and: i) corresponding measurement values; ii) corresponding exact
10 | % values
11 | %--------------------------------------------------------------------------
12 | % Inputs:
13 | % - data: input power system data with measurements
14 | % - se: state estimation data
15 | %
16 | % Outputs:
17 | % - se.error(:,1): errors between estimated values and corresponding
18 | % measurement values
19 | % - se.error(:,2): errors between estimated values and corresponding
20 | % exact values
21 | % - se.error(:,3): errors between estimated state variables and c
22 | % corresponding exact values
23 | %--------------------------------------------------------------------------
24 | % Created by Mirsad Cosovic on 2017-08-04
25 | % Last revision by Mirsad Cosovic on 2019-04-20
26 | % MATGRID is released under MIT License.
27 | %--------------------------------------------------------------------------
28 |
29 |
30 | %-----------------Estimated Values to Measurement Values-------------------
31 | Ntot = se.Nleg + se.Npmu;
32 |
33 | MAE = sum(se.estimate(:,4)) / Ntot;
34 | RMSE = ((sum(se.estimate(:,4).^2)) / Ntot)^(1/2);
35 | WRSS = sum(((se.estimate(:,4).^2)) ./ se.estimate(:,2));
36 |
37 | se.error = [MAE; RMSE; WRSS];
38 | %--------------------------------------------------------------------------
39 |
40 |
41 | %--------------------Estimated Values to Exact Values----------------------
42 | if se.exact
43 | d = se.Va - data.pmu.voltage(:,9);
44 |
45 | MAE2 = sum(se.estimate(:,6)) / Ntot;
46 | MAE3 = sum(abs(d)) / se.Nbu;
47 |
48 | RMSE2 = ((sum(se.estimate(:,6)).^2) / Ntot)^(1/2);
49 | RMSE3 = ((sum(d).^2)/ se.Nbu)^(1/2);
50 |
51 | WRSS2 = sum(((se.estimate(:,6)).^2) ./ se.estimate(:,2));
52 |
53 | se.error(:,2) = [MAE2; RMSE2; WRSS2];
54 | se.error(:,3) = [MAE3; RMSE3; 0];
55 | end
56 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_dc/flow_dcse.m:
--------------------------------------------------------------------------------
1 | function [af] = flow_dcse(flow, se)
2 |
3 | %--------------------------------------------------------------------------
4 | % Builds data associated with active power flow measurements for the DC
5 | % state estimation
6 | %
7 | % The function defines the active power flow measurement data according to
8 | % available measurements (i.e., turn on measurements).
9 | %--------------------------------------------------------------------------
10 | % Inputs:
11 | % - flow: legacy power flow measurement data
12 | % - se: state estimation system data
13 | %
14 | % Outputs:
15 | % - af.on: measurement set (logical indexes)
16 | % - af.z: measurement values
17 | % - af.v: measurement variances
18 | % - af.n: number of measurements
19 | % - af.from: from bus end indexes
20 | % - af.to: to bus end indexes
21 | % - af.H: Jacobian matrix
22 | % - af.b: vector of the shift measurement values
23 | % - af.W: weighting matrix
24 | %--------------------------------------------------------------------------
25 | % Created by Mirsad Cosovic on 2019-04-01
26 | % Last revision by Mirsad Cosovic on 2019-04-15
27 | % MATGRID is released under MIT License.
28 | %--------------------------------------------------------------------------
29 |
30 |
31 | %-----------------------------Measurement Set------------------------------
32 | af.on = logical(flow(:,5));
33 | %--------------------------------------------------------------------------
34 |
35 |
36 | %----------------------------Measurement Data------------------------------
37 | af.z = flow(af.on,3);
38 | af.v = flow(af.on,4);
39 | af.n = sum(af.on);
40 |
41 | af.from = se.from(af.on);
42 | af.to = se.to(af.on);
43 | %--------------------------------------------------------------------------
44 |
45 |
46 | %------------------------------System Model--------------------------------
47 | n = (1:af.n)';
48 |
49 | af.H = sparse([n; n], [af.from; af.to], [se.bij(af.on); -se.bij(af.on)], af.n, se.Nbu);
50 | af.b = af.z - se.fij(af.on);
51 | af.W = spdiags(1 ./ af.v, 0, af.n, af.n);
52 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_dc/injection_dcse.m:
--------------------------------------------------------------------------------
1 | function [ai] = injection_dcse(injection, se)
2 |
3 | %--------------------------------------------------------------------------
4 | % Builds data associated with active power injection measurements for the
5 | % DC state estimation
6 | %
7 | % The function defines the active power injection measurement data
8 | % according to available measurements (i.e., turn on measurements).
9 | %--------------------------------------------------------------------------
10 | % Inputs:
11 | % - injection: legacy power injection measurement data
12 | % - se: state estimation system data
13 | %
14 | % Outputs:
15 | % - ai.on: measurement set (logical indexes)
16 | % - ai.z: measurement values
17 | % - ai.v: measurement variances
18 | % - ai.n: number of measurements
19 | % - ai.bus: bus indexes
20 | % - ai.H: Jacobian matrix
21 | % - ai.b: vector of the shift measurement values
22 | % - ai.W: weighting matrix
23 | %--------------------------------------------------------------------------
24 | % Created by Mirsad Cosovic on 2019-04-01
25 | % Last revision by Mirsad Cosovic on 2019-04-20
26 | % MATGRID is released under MIT License.
27 | %--------------------------------------------------------------------------
28 |
29 |
30 | %-----------------------------Measurement Set------------------------------
31 | ai.on = logical(injection(:,4));
32 | %--------------------------------------------------------------------------
33 |
34 |
35 | %----------------------------Measurement Data------------------------------
36 | ai.z = injection(ai.on,2);
37 | ai.v = injection(ai.on,3);
38 | ai.n = sum(ai.on);
39 |
40 | ai.bus = se.bus(ai.on,1);
41 | %--------------------------------------------------------------------------
42 |
43 |
44 | %------------------------------System Model--------------------------------
45 | ai.H = se.Ybu(ai.on,:);
46 | ai.b = ai.z - se.psh(ai.on);
47 | ai.W = spdiags(1 ./ ai.v, 0, ai.n, ai.n);
48 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_dc/processing_dcse.m:
--------------------------------------------------------------------------------
1 | function [se] = processing_dcse(data, se, af, ai, va)
2 |
3 | %--------------------------------------------------------------------------
4 | % Computes the DC power flow (active power flows and injections) after DC
5 | % state estimation.
6 | %
7 | % The active power flow for the DC problem is defined as Pij = 1/(tij*xij)
8 | % * (Ti - Tj - fij), and holds Pij = -Pji. Also, the active power injection
9 | % is given as Pi = Ybus*T + Psh + rsh. In general, according to the
10 | % convention, a negative power value indicates the power flow direction in
11 | % a bus, while a positive power value means direction out a bus. Also, the
12 | % function forms estimation data.
13 | %--------------------------------------------------------------------------
14 | % Inputs:
15 | % - data: input data
16 | % - se: state estimation system data
17 | % - af: active power flow measurement data
18 | % - ai: active power injection measurement data
19 | % - va: voltage angle measurement data
20 | %
21 | % Outputs:
22 | % - se.Pi:active power injection
23 | % - se.Pij: active power flow
24 | % - se.exact: flag indicator for exact values
25 | % - se.Nleg: number of legacy measurements
26 | % - se.Npmu: number of phasor measurements
27 | % - se.estimate with columns:
28 | % (1)measurement values; (2) measurement variances;
29 | % (3)estimated measurement values; (4)residual between between
30 | % estimated and measurement values; (5)exact values;
31 | % (6)residual between estimated and exact values
32 | %--------------------------------------------------------------------------
33 | % Created by Mirsad Cosovic on 2017-08-04
34 | % Last revision by Mirsad Cosovic on 2019-04-20
35 | % MATGRID is released under MIT License.
36 | %--------------------------------------------------------------------------
37 |
38 |
39 | %---------------------------Measurement Numbers----------------------------
40 | se.Nleg = af.n + ai.n;
41 | se.Npmu = va.n;
42 | %--------------------------------------------------------------------------
43 |
44 |
45 | %----------------------Active Power Flow at Branches-----------------------
46 | i = se.branch(:,2);
47 | j = se.branch(:,3);
48 |
49 | se.Pij = se.branch(:,11) .* (se.Va(i) - se.Va(j) - se.branch(:,8));
50 | %--------------------------------------------------------------------------
51 |
52 |
53 | %------------------Injection Active Power with Slack Bus-------------------
54 | se.Pi = se.Ybu * se.Va + se.bus(:,16) + se.bus(:,7);
55 | %--------------------------------------------------------------------------
56 |
57 |
58 | %--------------------Estimation Data for Measurements----------------------
59 | Pij = [se.Pij; -se.Pij];
60 |
61 | se.estimate(:,1) = [af.z; ai.z; va.z];
62 | se.estimate(:,2) = [af.v; ai.v; va.v];
63 | se.estimate(:,3) = [Pij(af.on); se.Pi(ai.on); se.Va(va.on)];
64 | se.estimate(:,4) = abs(se.estimate(:,3) - se.estimate(:,1));
65 |
66 | try
67 | flo = data.legacy.flow(af.on,9);
68 | inj = data.legacy.injection(ai.on,8);
69 | ang = data.pmu.voltage(va.on,9);
70 |
71 | se.estimate(:,5) = [flo; inj; ang];
72 | se.estimate(:,6) = abs(se.estimate(:,3) - se.estimate(:,5));
73 |
74 | se.exact = 1;
75 | catch
76 | se.exact = 0;
77 | end
78 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_dc/solve_dcse_lav.m:
--------------------------------------------------------------------------------
1 | function [se] = solve_dcse_lav(se, af, ai, va)
2 |
3 | %--------------------------------------------------------------------------
4 | % Solves the DC linear least absolute value state estimation problem and
5 | % computes the vector of bus voltage angles.
6 | %
7 | % The least absolute value state estimation can be formulated as a linear
8 | % programming problem, which in turn can be solved by applying one of the
9 | % LP solution methods. Finally, preprocessing time is over, and the
10 | % convergence time is obtained here, while postprocessing time is
11 | % initialized.
12 | %--------------------------------------------------------------------------
13 | % Inputs:
14 | % - se: state estimation system data
15 | % - af: active power flow measurement data
16 | % - ai: active power injection measurement data
17 | % - va: voltage angle measurement data
18 | %
19 | % Outputs:
20 | % - se.Va: estimated values of the bus voltage angles
21 | % - se.method: method name
22 | % - se.time.pre: preprocessing time
23 | % - se.time.con: convergence time
24 | %--------------------------------------------------------------------------
25 | % Created by Mirsad Cosovic on 2019-03-19
26 | % Last revision by Mirsad Cosovic on 2019-04-20
27 | % MATGRID is released under MIT License.
28 | %--------------------------------------------------------------------------
29 |
30 |
31 | %---------------------------------Method-----------------------------------
32 | se.method = 'DC Least Absolute Value State Estimation';
33 | %--------------------------------------------------------------------------
34 |
35 |
36 | %---------------------------Preprocessing Data-----------------------------
37 | H = [af.H; ai.H; va.H];
38 | b = [af.b; ai.b; va.b];
39 | %--------------------------------------------------------------------------
40 |
41 |
42 | %---------------------------Preprocessing Time-----------------------------
43 | se.time.pre = toc; tic
44 | %--------------------------------------------------------------------------
45 |
46 |
47 | %---------------------------Bus Voltage Angles-----------------------------
48 | H(:, se.sck(1)) = [];
49 | Nbu = se.Nbu - 1;
50 | Nm = size(H,1);
51 |
52 | c = [zeros(Nbu,1); zeros(Nbu,1); ones(2*Nm,1)];
53 | A = [H -H eye(Nm,Nm) -eye(Nm,Nm)];
54 | lb = zeros(2*Nbu + 2*Nm, 1);
55 |
56 | options = optimoptions('linprog','Display','off');
57 | disp(' Linear programming is running to find least absolute value estimator.')
58 |
59 | [s, ~, flag] = linprog(c, [], [], A, b, lb, [], options);
60 |
61 | if flag == 1
62 | disp(' Optimal solution found.')
63 |
64 | se.Va = s(1:Nbu) - s(Nbu+1:2*Nbu);
65 | insert = @(a, x, n) cat(1, x(1:n), a, x(n + 1:end));
66 | se.Va = insert(0, se.Va, se.sck(1) - 1);
67 | se.Va = se.sck(2) * ones(se.Nbu,1) + se.Va;
68 | else
69 | error('lavDc:noFeasible', 'No feasible point found.\n')
70 | end
71 | %--------------------------------------------------------------------------
72 |
73 |
74 | %----------------------------Convergence Time------------------------------
75 | se.time.con = toc; tic
76 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_dc/solve_dcse_wls.m:
--------------------------------------------------------------------------------
1 | function [se] = solve_dcse_wls(se, af, ai, va)
2 |
3 | %--------------------------------------------------------------------------
4 | % Solves the DC state estimation problem and computes the vector of bus
5 | % voltage angles using weighted least-squares.
6 | %
7 | % The weighted least-squares DC state estimation solution for an observable
8 | % system can be obtained by solving problem T = (H'WH)\H'Wz. Further, the
9 | % voltage angle on the slack bus is known, and consequently, it should be
10 | % removed from the system. Finally, preprocessing time is over, and the
11 | % convergence time is obtained here, while postprocessing time is
12 | % initialized.
13 | %--------------------------------------------------------------------------
14 | % Inputs:
15 | % - se: state estimation system data
16 | % - af: active power flow measurement data
17 | % - ai: active power injection measurement data
18 | % - va: voltage angle measurement data
19 | %
20 | % Outputs:
21 | % - se.Va: estimated values of the bus voltage angles
22 | % - se.method: method name
23 | % - se.time.pre: preprocessing time
24 | % - se.time.con: convergence time
25 | %--------------------------------------------------------------------------
26 | % Created by Mirsad Cosovic on 2017-08-04
27 | % Last revision by Mirsad Cosovic on 2019-04-20
28 | % MATGRID is released under MIT License.
29 | %--------------------------------------------------------------------------
30 |
31 |
32 | %---------------------------------Method-----------------------------------
33 | se.method = 'Weighted Least-Squares DC State Estimation';
34 | %--------------------------------------------------------------------------
35 |
36 |
37 | %---------------------------Preprocessing Data-----------------------------
38 | H = [af.H; ai.H; va.H];
39 | b = [af.b; ai.b; va.b];
40 | W = blkdiag(af.W, ai.W, va.W);
41 | %--------------------------------------------------------------------------
42 |
43 |
44 | %---------------------------Preprocessing Time-----------------------------
45 | se.time.pre = toc; tic
46 | %--------------------------------------------------------------------------
47 |
48 |
49 | %---------------------------Bus Voltage Angles-----------------------------
50 | H(:, se.sck(1)) = [];
51 |
52 | se.Va = (H' * W * H) \ (H' * W * b);
53 | %--------------------------------------------------------------------------
54 |
55 |
56 | %---------------------------Data with Slack Bus----------------------------
57 | insert = @(a, x, n) cat(1, x(1:n), a, x(n + 1:end));
58 | se.Va = insert(0, se.Va, se.sck(1) - 1);
59 | se.Va = se.sck(2) * ones(se.Nbu,1) + se.Va;
60 | %--------------------------------------------------------------------------
61 |
62 |
63 | %----------------------------Convergence Time------------------------------
64 | se.time.con = toc; tic
65 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_dc/system_data_dcse.m:
--------------------------------------------------------------------------------
1 | function [se] = system_data_dcse(se)
2 |
3 | %--------------------------------------------------------------------------
4 | % Builds the global branch indexes and parameters for the DC state
5 | % estimation.
6 | %
7 | % The function defines branch and bus indexes and parameters that are used
8 | % for the DC state estimation.
9 | %--------------------------------------------------------------------------
10 | % Input:
11 | % - se: state estimation system data
12 | %
13 | % Outputs:
14 | % - se.from: from bus ends
15 | % - se.to: to bus ends
16 | % - se.bij: coefficients [1/(tij*xij); 1/(tij*xij)]
17 | % - se.fij: transformer phase shift angle [fij -fij]
18 | % - se.psh: power injection shift vector
19 | % - se.ts: voltage angle slack bus shift vector
20 | %--------------------------------------------------------------------------
21 | % Created by Mirsad Cosovic on 2018-04-01
22 | % Last revision by Mirsad Cosovic on 2019-04-20
23 | % MATGRID is released under MIT License.
24 | %--------------------------------------------------------------------------
25 |
26 |
27 | %------------------------DC State Estimation Data--------------------------
28 | se.from = [se.branch(:,2); se.branch(:,3)];
29 | se.to = [se.branch(:,3); se.branch(:,2)];
30 | se.bij = [se.branch(:,11); se.branch(:,11)];
31 | se.fij = [se.branch(:,8); -se.branch(:,8)];
32 | se.psh = se.bus(:,16);
33 | se.ts = se.sck(2) * ones(se.Nbu,1);
34 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_dc/voltage_dcse.m:
--------------------------------------------------------------------------------
1 | function [va] = voltage_dcse(voltage, se)
2 |
3 | %--------------------------------------------------------------------------
4 | % Builds data associated with voltage angle measurements for the DC state
5 | % estimation
6 | %
7 | % The function defines the voltage angle measurement data according to
8 | % available measurements (i.e., turn on measurements).
9 | %--------------------------------------------------------------------------
10 | % Inputs:
11 | % - voltage: PMU voltage angle measurement data
12 | % - se: state estimation system data
13 | %
14 | % Outputs:
15 | % - va.on: measurement set (logical indexes)
16 | % - va.z: measurement values
17 | % - va.v: measurement variances
18 | % - va.n: number of measurements
19 | % - va.bus: bus indexes
20 | % - va.H: Jacobian matrix
21 | % - va.b: vector of the shift measurement values
22 | % - va.W: weighting matrix
23 | %--------------------------------------------------------------------------
24 | % Created by Mirsad Cosovic on 2019-04-01
25 | % Last revision by Mirsad Cosovic on 2019-04-20
26 | % MATGRID is released under MIT License.
27 | %--------------------------------------------------------------------------
28 |
29 |
30 | %-----------------------------Measurement Set------------------------------
31 | va.on = logical(voltage(:,7));
32 | %--------------------------------------------------------------------------
33 |
34 |
35 | %----------------------------Measurement Data------------------------------
36 | va.z = voltage(va.on,5);
37 | va.v = voltage(va.on,6);
38 | va.n = sum(va.on);
39 |
40 | va.bus = se.bus(va.on,1);
41 | %--------------------------------------------------------------------------
42 |
43 |
44 | %------------------------------System Model--------------------------------
45 | va.H = sparse((1:va.n)', va.bus, 1, va.n, se.Nbu);
46 | va.b = va.z - se.ts(va.on);
47 | va.W = spdiags(1 ./ va.v, 0, va.n, va.n);
48 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_pmu/name_unit_bad_data.m:
--------------------------------------------------------------------------------
1 | function [sys] = name_unit_bad_data(data, sys)
2 |
3 | %--------------------------------------------------------------------------
4 | % Builds the data of measurement types for the bad data terminal.
5 | %
6 | % Each measurement is associated with an associated name that we defines
7 | % those here.
8 | %--------------------------------------------------------------------------
9 | % Inputs:
10 | % - sys: power system data
11 | % - data: data corresponding with active phasor measurements
12 | %
13 | % Outputs:
14 | % - sys.device with column: (1)measurement type
15 | %--------------------------------------------------------------------------
16 | % Created by Mirsad Cosovic on 2019-03-05
17 | % Last revision by Mirsad Cosovic on 2019-03-27
18 | % MATGRID is released under MIT License.
19 | %--------------------------------------------------------------------------
20 |
21 |
22 | %--------------------------Name of Measurements----------------------------
23 | i = [sys.branch(:,9); sys.branch(:,10)];
24 | j = [sys.branch(:,10); sys.branch(:,9)];
25 |
26 | V = repmat({'V'}, [sys.Nv,1]);
27 | C = repmat({'I'}, [sys.Nc,1]);
28 |
29 | V = strcat(V,strtrim(cellstr(num2str(sys.bus(data.pmu.voltage(:,14),15)))));
30 |
31 | a = strtrim(cellstr(num2str(i(data.pmu.current(:,15)))));
32 | b = strtrim(cellstr(num2str(j(data.pmu.current(:,15)))));
33 | C = strcat(C,a,{','},b);
34 |
35 | sys.device = [V; C; V; C];
36 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_pmu/name_unit_pmuse.m:
--------------------------------------------------------------------------------
1 | function [se] = name_unit_pmuse(sys, se, data)
2 |
3 | %--------------------------------------------------------------------------
4 | % Builds the data of measurement types and units.
5 | %
6 | % Each measurement is associated with an associated name and unit. Also,
7 | % the vector for conversion from per-unit to real unit system is formed.
8 | % Finally, the postprocessing time is obtained here.
9 | %--------------------------------------------------------------------------
10 | % Inputs:
11 | % - sys: power system data
12 | % - se: state estimation data
13 | % - data: data corresponding with active phasor measurements
14 | %
15 | % Outputs:
16 | % - se.device with columns: (1)measurement type; (2)measurement unit
17 | % - se.estimate with additional column: (4)unit conversion
18 | %--------------------------------------------------------------------------
19 | % Created by Mirsad Cosovic on 2019-03-05
20 | % Last revision by Mirsad Cosovic on 2019-03-27
21 | % MATGRID is released under MIT License.
22 | %--------------------------------------------------------------------------
23 |
24 |
25 | %--------------------------Name of Measurements----------------------------
26 | i = [sys.branch(:,9); sys.branch(:,10)];
27 | j = [sys.branch(:,10); sys.branch(:,9)];
28 |
29 | Vap = repmat({'T'}, [sys.Nv,1]);
30 | Vmp = repmat({'V'}, [sys.Nv,1]);
31 | Cmp = repmat({'I'}, [sys.Nc,1]);
32 | Cap = repmat({'D'}, [sys.Nc,1]);
33 |
34 | Vmpt = strcat(Vmp,strtrim(cellstr(num2str(sys.bus(data.pmu.voltage(:,14),15)))));
35 | Vapt = strcat(Vap,strtrim(cellstr(num2str(sys.bus(data.pmu.voltage(:,14),15)))));
36 |
37 | a = strtrim(cellstr(num2str(i(data.pmu.current(:,15)))));
38 | b = strtrim(cellstr(num2str(j(data.pmu.current(:,15)))));
39 | Cmpt = strcat(Cmp,a,{','},b);
40 |
41 | a = strtrim(cellstr(num2str(i(data.pmu.current(:,15)))));
42 | b = strtrim(cellstr(num2str(j(data.pmu.current(:,15)))));
43 | Capt = strcat(Cap,a,{','},b);
44 |
45 | se.device = [Vmpt; Vapt; Cmpt; Capt];
46 | %--------------------------------------------------------------------------
47 |
48 |
49 | %---------------------------Unit of Measurements---------------------------
50 | Vap = repmat({'[deg]'}, [sys.Nv,1]);
51 | Vmp = repmat({'[pu]'}, [sys.Nv,1]);
52 | Cmp = repmat({'[pu]'}, [sys.Nc,1]);
53 | Cap = repmat({'[deg]'}, [sys.Nc,1]);
54 |
55 | se.device(:,2) = [Vmp; Vap; Cmp; Cap];
56 | %--------------------------------------------------------------------------
57 |
58 |
59 | %------------------------Measurement to Real Units-------------------------
60 | se.estimate(:,4) = [ones(sys.Nv,1); repmat(180 / pi, sys.Nv, 1);
61 | ones(sys.Nc,1); repmat(180 / pi, sys.Nc, 1)];
62 | %--------------------------------------------------------------------------
63 |
64 |
65 | %---------------------------Postprocessing Time----------------------------
66 | se.time.pos = toc;
67 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_pmu/solve_pmuse.m:
--------------------------------------------------------------------------------
1 | function [se] = solve_pmuse(sys)
2 |
3 | %--------------------------------------------------------------------------
4 | % Solves the PMU linear state estimation problem and computes the vector of
5 | % bus voltage angles.
6 | %
7 | % The state estimation solution for the system observable only by PMUs can
8 | % be obtained by solving weighted least-squares problem T = (H'WH)\H'Wz.
9 | % Finally, preprocessing time is over, and the convergence time is obtained
10 | % here, while postprocessing time is initialized.
11 | %--------------------------------------------------------------------------
12 | % Input:
13 | % - sys: power system data
14 | %
15 | % Outputs:
16 | % - se.bus: complex bus voltages
17 | % - se.method: method name
18 | % - se.time.pre: preprocessing time
19 | % - se.time.con: convergence time
20 | %--------------------------------------------------------------------------
21 | % Created by Mirsad Cosovic on 2019-03-05
22 | % Last revision by Mirsad Cosovic on 2019-03-27
23 | % MATGRID is released under MIT License.
24 | %--------------------------------------------------------------------------
25 |
26 |
27 | %---------------------------------Method-----------------------------------
28 | se.method = 'Linear Weighted Least-Squares State Estimation only with PMUs';
29 | %--------------------------------------------------------------------------
30 |
31 |
32 | %---------------------------Preprocessing Time-----------------------------
33 | se.time.pre = toc; tic
34 | %--------------------------------------------------------------------------
35 |
36 |
37 | %--------------------------Bus Voltage Estimates---------------------------
38 | W = spdiags(sys.v, 0, sys.Ntot, sys.Ntot) \ speye(sys.Ntot, sys.Ntot);
39 |
40 | VrVi = (sys.H' * W * sys.H) \ (sys.H' * W * sys.b);
41 |
42 | se.Vc = VrVi(1:sys.Nbu) + 1i * VrVi(sys.Nbu+1:end);
43 | %--------------------------------------------------------------------------
44 |
45 |
46 | %----------------------------Convergence Time------------------------------
47 | se.time.con = toc; tic
48 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/state_estimation/state_estimation_pmu/solve_pmuse_lav.m:
--------------------------------------------------------------------------------
1 | function [se] = solve_pmuse_lav(sys)
2 |
3 | %--------------------------------------------------------------------------
4 | % Solves the PMU linear least absolute value state estimation problem and
5 | % computes the vector of complex bus voltages.
6 | %
7 | % The least absolute value state estimation can be formulated as a linear
8 | % programming problem, which in turn can be solved by applying one of the
9 | % LP solution methods. Finally, preprocessing time is over, and the
10 | % convergence time is obtained here, while postprocessing time is
11 | % initialized.
12 | %--------------------------------------------------------------------------
13 | % Input:
14 | % - sys: power system data
15 | %
16 | % Outputs:
17 | % - se.bus: complex bus voltages
18 | % - se.method: method name
19 | % - se.time.pre: preprocessing time
20 | % - se.time.conv: convergence time
21 | %--------------------------------------------------------------------------
22 | % Created by Mirsad Cosovic on 2019-03-17
23 | % Last revision by Mirsad Cosovic on 2019-03-27
24 | % MATGRID is released under MIT License.
25 | %--------------------------------------------------------------------------
26 |
27 |
28 | %---------------------------------Method-----------------------------------
29 | se.method = 'Linear Least Absolute Value State Estimation only with PMUs';
30 | %--------------------------------------------------------------------------
31 |
32 |
33 | %---------------------------Preprocessing Time-----------------------------
34 | se.time.pre = toc; tic
35 | %--------------------------------------------------------------------------
36 |
37 |
38 | %--------------------------Bus Voltage Estimates---------------------------
39 | c = [zeros(2*sys.Nbu,1); zeros(2*sys.Nbu,1); ones(2*sys.Ntot,1)];
40 | A = [sys.H -sys.H eye(sys.Ntot,sys.Ntot) -eye(sys.Ntot,sys.Ntot)];
41 | lb = zeros(4*sys.Nbu + 2*sys.Ntot, 1);
42 |
43 | options = optimoptions('linprog','Display','off');
44 | disp(' Linear programming is running to find least absolute value estimator.')
45 |
46 | [s, ~, flag] = linprog(c, [], [], A, sys.b, lb, [], options);
47 |
48 | if flag == 1
49 | disp(' Optimal solution found.')
50 | VrVi = s(1:2*sys.Nbu) - s(2*sys.Nbu+1:4*sys.Nbu);
51 | se.Vc = VrVi(1:sys.Nbu) + 1i * VrVi(sys.Nbu+1:end);
52 | else
53 | error('lavPmu:noFeasible', 'No feasible point found.\n')
54 | end
55 | %--------------------------------------------------------------------------
56 |
57 |
58 | %----------------------------Convergence Time------------------------------
59 | se.time.con = toc; tic
60 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/terminal/terminal_bad_data.m:
--------------------------------------------------------------------------------
1 | function terminal_bad_data(in, re, sys, user)
2 |
3 | %--------------------------------------------------------------------------
4 | % Displays bad data processing.
5 | %--------------------------------------------------------------------------
6 | % Inputs:
7 | % - in: input se data
8 | % - re: result data
9 | % - sys: power system data
10 | % - user: user input list
11 | %--------------------------------------------------------------------------
12 | % Created by Mirsad Cosovic on 2019-03-19
13 | % Last revision by Mirsad Cosovic on 2019-04-20
14 | % MATGRID is released under MIT License.
15 | %--------------------------------------------------------------------------
16 |
17 |
18 | %% Bad Data Identification Non-linear State Estimation
19 | if ismember('nonlinear', user)
20 | N = size(in.bad, 1);
21 | A = [(1:N)' in.bad];
22 | d = in.device(in.bad(:,3));
23 | o = [repmat({'Remove'}, [N-1,1]); ' '];
24 |
25 | disp(' ')
26 | disp(' _______________________________________________________________________________________________________________')
27 | disp(' | Gauss-Newton Pass Number of Iterations Suspected Bad Data Normalized Residual Status |')
28 | disp(' | --------------------------------------------------------------------------------------------------------------|')
29 | for i = 1:N
30 | fprintf(' |\t %10.f %20.f %25s %18.2e %13s |\n',...
31 | A(i,1), A(i,2), d{i,1}, A(i,3), o{i,1} )
32 | end
33 | disp(' |_______________________________________________________________________________________________________________|')
34 | end
35 |
36 | %% Bad Data Identification DC State Estimation
37 | if ismember('dc', user)
38 | N = size(in.bad, 1);
39 | num = string(1:N)';
40 | res = compose('%1.2e', re.bad.Residual);
41 | bad = [num re.bad.Device res re.bad.Status]';
42 |
43 | disp(' ')
44 | disp(' ____________________________________________________________________________')
45 | disp(' | WLS Pass Suspected Bad Data Normalized Residual Status |')
46 | disp(' | ---------------------------------------------------------------------------|')
47 | fprintf(' | %7s %-13s %16s %-10s |\n', bad{:})
48 | disp(' |____________________________________________________________________________|')
49 | end
50 |
51 | %% Bad Data Identification PMU State Estimation
52 | if ismember('pmu', user)
53 | N = size(in.bad,1 );
54 | A = [(1:N)' in.bad];
55 | d = sys.device(in.bad(:,2));
56 | o = [repmat({'Remove'}, [N-1,1]); ' '];
57 |
58 | disp(' ')
59 | disp(' ___________________________________________________________________________________')
60 | disp(' | WLS Pass Suspected Phasor Bad Data Normalized Residual Status |')
61 | disp(' | ----------------------------------------------------------------------------------|')
62 | for i = 1:N
63 | fprintf(' |\t %4.f %20s %22.2e %14s |\n',...
64 | A(i,1), d{i,1}, A(i,2), o{i,1} )
65 | end
66 | disp(' |___________________________________________________________________________________|')
67 | end
--------------------------------------------------------------------------------
/terminal/terminal_bus_pf.m:
--------------------------------------------------------------------------------
1 | function terminal_bus_pf(in, sys, user)
2 |
3 | %--------------------------------------------------------------------------
4 | % Displays power flow bus data.
5 | %--------------------------------------------------------------------------
6 | % Inputs:
7 | % - in: input result data
8 | % - sys: power system data
9 | % - user: user input list
10 | %--------------------------------------------------------------------------
11 | % Created by Mirsad Cosovic on 2019-01-26
12 | % Last revision by Mirsad Cosovic on 2019-03-27
13 | % MATGRID is released under MIT License.
14 | %--------------------------------------------------------------------------
15 |
16 |
17 | %% Bus Data for the AC power Flow
18 | if any(ismember({'nr', 'gs', 'dnr', 'fdnr'}, user))
19 | A = [in.bus.Bus in.bus.Vmag in.bus.Vang in.bus.Pinj in.bus.Qinj in.bus.Pgen in.bus.Qgen in.bus.Pload in.bus.Qload in.bus.Psh in.bus.Qsh];
20 | B = [sum(in.bus.Pinj) sum(in.bus.Qinj) sum(in.bus.Pgen) sum(in.bus.Qgen) sum(in.bus.Pload) sum(in.bus.Qload) sum(in.bus.Psh) sum(in.bus.Qsh)];
21 |
22 | disp(' ')
23 | disp(' ___________________________________________________________________________________________________________________________________________________')
24 | disp(' | Bus Voltage Injection Power | Generation Consumption | Shunt Element |')
25 | disp(' | Vm[pu] | Va[deg] P[MW] | Q[MVAr] | P[MW] | Q[MVAr] P[MW] | Q[MVAr] | P[MW] | Q[MVAr] |')
26 | disp(' | ------------------------------------------------------------------|---------------------------------------------------|---------------------------|')
27 | fprintf(' | %-8.f %11.4f %11.4f %12.2f %10.2f | %9.2f %11.2f %11.2f %11.2f | %9.2f %11.2f |\n', A')
28 | disp(' |-------------------------------------------------------------------|---------------------------------------------------|---------------------------|')
29 | fprintf(' | Sum %44.2f %11.2f | %9.2f %11.2f %11.2f %11.2f | %9.2f %11.2f |\n', B')
30 | disp(' |___________________________________________________________________|___________________________________________________|___________________________|')
31 | end
32 |
33 | %% Bus Data for the DC power Flow
34 | if ismember('dc', user)
35 | A = [in.bus.Bus ones(sys.Nbu,1) in.bus.Vang in.bus.Pinj in.bus.Pgen in.bus.Pload in.bus.Psh];
36 | B = [sum(in.bus.Pinj) sum(in.bus.Pgen) sum(in.bus.Pload) sum(in.bus.Psh)];
37 |
38 | disp(' ')
39 | disp(' _________________________________________________________________________________________________________________________________')
40 | disp(' | Bus Voltage Injection Power | Generation Consumption | Shunt Element |')
41 | disp(' | Vm[pu] | Va[deg] P[MW] | P[MW] P[MW] | P[MW] |')
42 | disp(' | -----------------------------------------------------------------|--------------------------------------|-----------------------|')
43 | fprintf(' | %-8.f %11.4f %11.4f %18.2f | %12.2f %16.2f | %13.2f |\n', A')
44 | disp(' |------------------------------------------------------------------|--------------------------------------|-----------------------|')
45 | fprintf(' | Sum %50.2f | %12.2f %16.2f | %13.2f |\n', B')
46 | disp(' |__________________________________________________________________|______________________________________|_______________________|')
47 | end
--------------------------------------------------------------------------------
/terminal/terminal_bus_se.m:
--------------------------------------------------------------------------------
1 | function terminal_bus_se(in, sys, user)
2 |
3 | %--------------------------------------------------------------------------
4 | % Displays bus data after state estimation algorithms.
5 | %--------------------------------------------------------------------------
6 | % Inputs:
7 | % - in: input result data
8 | % - sys: power system data
9 | % - user: user input list
10 | %--------------------------------------------------------------------------
11 | % Created by Mirsad Cosovic on 2019-01-26
12 | % Last revision by Mirsad Cosovic on 2019-03-27
13 | % MATGRID is released under MIT License.
14 | %--------------------------------------------------------------------------
15 |
16 |
17 | %% Bus Data for the Non-linear and PMU State Estimation
18 | if any(ismember({'nonlinear', 'pmu'}, user))
19 | A = [in.bus.Bus in.bus.Vmag in.bus.Vang in.bus.Pinj in.bus.Qinj in.bus.Psh in.bus.Qsh];
20 | B = [sum(in.bus.Pinj) sum(in.bus.Qinj) sum(in.bus.Psh) sum(in.bus.Qsh)];
21 |
22 |
23 | disp(' ')
24 | disp(' _______________________________________________________________________________________________')
25 | disp(' | Bus Voltage Injection Power | Shunt Element |')
26 | disp(' | Vm[pu] | Va[deg] P[MW] | Q[MVAr] | P[MW] | Q[MVAr] |')
27 | disp(' | ------------------------------------------------------------------|---------------------------|')
28 | fprintf(' | %-8.f %11.4f %11.4f %12.2f %10.2f | %9.2f %11.2f |\n', A')
29 | disp(' |-------------------------------------------------------------------|---------------------------|')
30 | fprintf(' | Sum %44.2f %11.2f | %9.2f %11.2f |\n', B')
31 | disp(' |___________________________________________________________________|___________________________|')
32 | end
33 |
34 | %% Bus Data for the DC State Estimation
35 | if ismember('dc', user)
36 | A = [in.bus.Bus ones(sys.Nbu, 1) in.bus.Vang in.bus.Pinj in.bus.Psh];
37 | B = [sum(in.bus.Pinj) sum(in.bus.Psh)];
38 |
39 | disp(' ')
40 | disp(' __________________________________________________________________________________________')
41 | disp(' | Bus Voltage Injection Power | Shunt Element |')
42 | disp(' | Vm[pu] | Va[deg] P[MW] | P[MW] |')
43 | disp(' | -----------------------------------------------------------------|-----------------------|')
44 | fprintf(' |\t %-8.f %11.4f %11.4f %18.2f | %13.2f |\n', A')
45 | disp(' |------------------------------------------------------------------|-----------------------|')
46 | fprintf(' |\tSum %51.2f | %13.2f |\n', B')
47 | disp(' |__________________________________________________________________|_______________________|')
48 | end
--------------------------------------------------------------------------------
/terminal/terminal_error_se.m:
--------------------------------------------------------------------------------
1 | function [] = terminal_error_se(in, re)
2 |
3 | %--------------------------------------------------------------------------
4 | % Displays state estimation evolution.
5 | %--------------------------------------------------------------------------
6 | % Inputs:
7 | % - in: input result data
8 | % - sys: power system data
9 | %--------------------------------------------------------------------------
10 | % Created by Mirsad Cosovic on 2019-01-26
11 | % Last revision by Mirsad Cosovic on 2019-04-17
12 | % MATGRID is released under MIT License.
13 | %--------------------------------------------------------------------------
14 |
15 | %% State Estimation Evaluation
16 | disp(' ')
17 | disp(' ________________________________________________________________________________________________________')
18 | disp(' | State Estimation Evaluation |')
19 | disp(' | |')
20 | disp(' | Description MAE RMSE WRSS |')
21 | disp(' |--------------------------------------------------------------------------------------------------------|')
22 | fprintf(' |\t Estimate Values and Measurement Values %20.4e %16.4e %16.4e |\n', re.error.EstimateMean)
23 | if in.exact
24 | fprintf(' |\t Estimate Values and Exact Values %20.4e %16.4e %16.4e |\n', re.error.EstimateExact)
25 | fprintf(' |\t Estimate State Variables and Exact Values %20.4e %16.4e \t\t\t\t\t |\n', re.error.EstimateExactState(1:2))
26 | end
27 | disp(' |________________________________________________________________________________________________________|')
--------------------------------------------------------------------------------
/terminal/terminal_flow.m:
--------------------------------------------------------------------------------
1 | function terminal_flow(in, sys, user)
2 |
3 | %--------------------------------------------------------------------------
4 | % Displays power flow.
5 | %--------------------------------------------------------------------------
6 | % Inputs:
7 | % - in: input result data
8 | % - sys: power system data
9 | % - user: user input list
10 | %--------------------------------------------------------------------------
11 | % Created by Mirsad Cosovic on 2019-01-26
12 | % Last revision by Mirsad Cosovic on 2019-03-27
13 | % MATGRID is released under MIT License.
14 | %--------------------------------------------------------------------------
15 |
16 |
17 | %% AC Power Flow
18 | if any(ismember({'nr', 'gs', 'dnr', 'fdnr', 'nonlinear', 'pmu'}, user))
19 | A = [sys.branch(:,1) in.branch.From in.branch.Pfrom in.branch.Qfrom in.branch.Pto in.branch.Qto in.branch.To in.branch.Qinj in.branch.Ploss in.branch.Qloss];
20 |
21 | disp(' ')
22 | disp(' _____________________________________________________________________________________________________________________________________________')
23 | disp(' | Active and Reactive Power Flow | Injection | Series Impedance Loss |')
24 | disp(' | | | |')
25 | disp(' | No. From Bus P[MW] | Q[MVAr] P[MW] | Q[MVAr] To Bus | Q[MVAr] | P[MW] | Q[MVAr] |')
26 | disp(' |-----------------------------------------------------------------------------------------|-------------------|-------------------------------|')
27 | fprintf(' | %-8.f %6.f %13.2f %11.2f %13.2f %11.2f %10.f | %12.2f | %11.2f %11.2f |\n', A')
28 | disp(' |-----------------------------------------------------------------------------------------|-------------------|-------------------------------|')
29 | fprintf(' | Sum %82s | %12.2f | %11.2f %11.2f |\n', [], sum(in.branch.Qinj), sum(in.branch.Ploss), sum(in.branch.Qloss))
30 | disp(' |_________________________________________________________________________________________|___________________|_______________________________|')
31 | end
32 |
33 | %% DC Power Flow
34 | if ismember('dc', user)
35 | A = [sys.branch(:,1) in.branch.From in.branch.Pflow -in.branch.Pflow in.branch.To];
36 |
37 | disp(' ')
38 | disp(' _________________________________________________________________')
39 | disp(' | Active Power Flow |')
40 | disp(' | |')
41 | disp(' | No. From Bus P[MW] P[MW] To Bus | ')
42 | disp(' |-----------------------------------------------------------------|')
43 | fprintf(' | %-8.f %6.f %13.2f %13.2f %10.f |\n', A')
44 | disp(' |-----------------------------------------------------------------|')
45 | disp(' |_________________________________________________________________|')
46 | end
--------------------------------------------------------------------------------
/terminal/terminal_info.m:
--------------------------------------------------------------------------------
1 | function terminal_info(in, sys, user)
2 |
3 | %--------------------------------------------------------------------------
4 | % Displays info data.
5 | %--------------------------------------------------------------------------
6 | % Inputs:
7 | % - in: input result data
8 | % - sys: power system data
9 | % - user: user input list
10 | %--------------------------------------------------------------------------
11 | % Created by Mirsad Cosovic on 2019-01-10
12 | % Last revision by Mirsad Cosovic on 2019-04-21
13 | % MATGRID is released under MIT License.
14 | %--------------------------------------------------------------------------
15 |
16 |
17 | %% Main Information
18 | disp(' ')
19 | disp(' ')
20 | fprintf('\tMethod: %s\n', in.method);
21 | fprintf('\tPower System: %s\n', user{end});
22 | fprintf(['\tDate: ', datestr(now, 'dd.mm.yyyy HH:MM:SS \n')])
23 | disp(' ')
24 | fprintf('\tPreprocessing time: %2.5f seconds\n', in.time.Preprocess)
25 | fprintf('\tConvergence time: %2.5f seconds\n', in.time.Convergence)
26 | fprintf('\tPostprocessing time: %2.5f seconds\n', in.time.Postprocess)
27 |
28 | %% Non-Linear Main Information
29 | if any(ismember({'nr', 'gs', 'dnr', 'fdnr', 'nonlinear'}, user))
30 | disp(' ')
31 | fprintf('\tStopping condition for iterative process: %s\n ', num2str(sys.stop))
32 | fprintf ('\tNumber of iterations: %d\n', in.iteration)
33 | end
34 |
35 | %% Violated Limits for the AC Power Flow
36 | if any(ismember({'nr', 'gs', 'dnr', 'fdnr'}, user))
37 | if any(in.bus.MinLim)
38 | fprintf('\tMinimum equality constraint violated at buses: %s\n', sprintf('%d ', in.bus.Bus(logical(in.bus.MinLim))))
39 | end
40 | if any(in.bus.MaxLim)
41 | fprintf('\tMaximum equality constraint violated at buses: %s\n', sprintf('%d ', in.bus.Bus(logical(in.bus.MaxLim))))
42 | end
43 | end
--------------------------------------------------------------------------------
/terminal/terminal_observability.m:
--------------------------------------------------------------------------------
1 | function terminal_observability(in, re, user)
2 |
3 | %--------------------------------------------------------------------------
4 | % Displays observability analysis.
5 | %--------------------------------------------------------------------------
6 | % Inputs:
7 | % - in: input se data
8 | % - re: result data
9 | % - user: user input list
10 | %--------------------------------------------------------------------------
11 | % Created by Mirsad Cosovic on 2019-04-02
12 | % Last revision by Mirsad Cosovic on 2019-04-20
13 | % MATGRID is released under MIT License.
14 | %--------------------------------------------------------------------------
15 |
16 |
17 | %% Observability Analysis DC State Estimation
18 | if ismember('dc', user)
19 | disp(' ')
20 | if ~ismember('unobservable', user)
21 | fprintf('\tObservability analysis: Power system is observable\n');
22 | else
23 | fprintf('\tObservability analysis: Power system is unobservable\n');
24 |
25 | Ni = max(in.observe.island(:,2));
26 | Nb = sum(in.observe.branch(:,3) == 0);
27 | Np = length(in.observe.psm);
28 | Nm = max([Ni Nb Np]);
29 |
30 | Nic = (1:Ni)';
31 | ai = hist(in.observe.island(:,2), Nic);
32 | island = string([Nic ai']);
33 | island = [island; strings(Nm-Ni,2)];
34 |
35 | obs = ~logical(in.observe.branch(:,3));
36 | irr = ~logical(in.observe.branch(:,4));
37 | branch = re.branch(obs|irr,:);
38 | Nbc = (1:Nb)';
39 | branch = [string(Nbc) string(branch.From) string(branch.To) branch.Status; strings(Nm-Nb,4)];
40 |
41 | index = find(contains(re.estimate.Type,'pseudo-measurement'));
42 | mean = compose('%1.2f', re.estimate.Mean(index));
43 | var = compose('%1.e', re.estimate.Variance(index));
44 | restore = [re.estimate.Device(index) mean var; strings(Nm-Np,3)];
45 |
46 | ter = [island branch restore]';
47 |
48 | disp(' ')
49 | disp(' ____________________________________________________________________________________________________________________')
50 | disp(' | Island Data | Branch Data | Restore Observability Data |')
51 | disp(' | Island Buses | No. To Bus From Bus Label | Pseudo-measurement Value Variance |')
52 | disp(' | ------------------------|--------------------------------------------|---------------------------------------------|')
53 | fprintf(' | %6s %8s | %5s %8s %9s %-14s| %12s %16s %9s | \n', ter{:})
54 | disp(' |_________________________|____________________________________________|_____________________________________________|')
55 | end
56 | end
--------------------------------------------------------------------------------
/utility/diary_off.m:
--------------------------------------------------------------------------------
1 | function diary_off(user)
2 |
3 | %--------------------------------------------------------------------------
4 | % Ends record display data in txt-file.
5 | %
6 | % If the flag is 1, the function ends to record the display data.
7 | %--------------------------------------------------------------------------
8 | % Inputs:
9 | % - user: user input list data
10 | %--------------------------------------------------------------------------
11 | % Created by Mirsad Cosovic on 2019-03-04
12 | % Last revision by Mirsad Cosovic on 2019-03-27
13 | % MATGRID is released under MIT License.
14 | %--------------------------------------------------------------------------
15 |
16 |
17 | %------------------------------Turn off Diary------------------------------
18 | if ismember('save', user)
19 | diary off
20 | end
21 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/utility/diary_on.m:
--------------------------------------------------------------------------------
1 | function diary_on(user, case_in)
2 |
3 | %--------------------------------------------------------------------------
4 | % Saves display data in txt-file.
5 | %
6 | % If the flag is 1, the function starts to record the display data.
7 | %--------------------------------------------------------------------------
8 | % Inputs:
9 | % - user: user input list data
10 | % - case_in: name of the load power system
11 | %--------------------------------------------------------------------------
12 | % Created by Mirsad Cosovic on 2019-03-04
13 | % Last revision by Mirsad Cosovic on 2019-03-27
14 | % MATGRID is released under MIT License.
15 | %--------------------------------------------------------------------------
16 |
17 |
18 | %------------------------------Turn on Diary-------------------------------
19 | if ismember('save', user)
20 | cd('experiments')
21 | diary(strcat(case_in, datestr(now,'_dd-mm-yy','local'),'_', datestr(now,'hh-MM-ss','local'), '.txt'))
22 | cd('../')
23 | end
24 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/utility/produce_Abv.m:
--------------------------------------------------------------------------------
1 | function [data] = produce_Abv(data, sys, se, user)
2 |
3 | %--------------------------------------------------------------------------
4 | % Exports the system in the matrix and vector forms, for the linear state
5 | % estimation cases.
6 | %
7 | % The function exports the matrix and vector forms for the DC and PMU state
8 | % estimation. Export of data is possible to do without slack bus
9 | % (estimate.linear = 1), or with slack bus (estimate.linear = 2).
10 | %--------------------------------------------------------------------------
11 | % Input:
12 | % - data: input power system data with measurements
13 | % - sys: power system data
14 | % - se: state estimation data
15 | %
16 | % Outputs:
17 | % - data.A: Jacobian matrix
18 | % - data.b: vector of observations;
19 | % - data.v: variances vector
20 | %--------------------------------------------------------------------------
21 | % Created by Mirsad Cosovic on 2019-03-04
22 | % Last revision by Mirsad Cosovic on 2019-03-27
23 | % MATGRID is released under MIT License.
24 | %--------------------------------------------------------------------------
25 |
26 |
27 | %-------------------------------Export System------------------------------
28 | if ismember('export', user) && any(ismember({'dc', 'pmu'}, user))
29 | data.extras.A = sys.H;
30 | data.extras.b = sys.b;
31 | data.extras.v = se.estimate(:,2);
32 | end
33 |
34 | if ismember('exportSlack', user) && ismember('dc', user)
35 | h = sparse(1, sys.Nbu);
36 | h(sys.sck(1)) = 1;
37 |
38 | data.extras.As = [sys.H; h];
39 | data.extras.bs = [sys.b; sys.sck(2)];
40 | data.extras.vs = [se.estimate(:,2); 10^-30];
41 | end
42 | %--------------------------------------------------------------------------
--------------------------------------------------------------------------------
/utility/sparseinv/Contents.m:
--------------------------------------------------------------------------------
1 | % SPARSEINV The sparseinv function computes the sparse inverse subset of a
2 | % sparse matrix A. These entries in the inverse subset correspond to nonzero
3 | % entries in the factorization of A. They can be computed without computing
4 | % all of the entries in inv(A), so this method is much faster and takes much
5 | % less memory than inv(A). If A is symmetric and positive definite, then all
6 | % entries of the diagona of inv(A) are computed (as well as many off-diagonal
7 | % terms. This version is restricted to real sparse matrices. A complex
8 | % version is left for future work.
9 | %
10 | % Copyright (c) 2011, Timothy A. Davis
11 | %
12 | % Files
13 | % sparseinv - computes the sparse inverse subset of a real sparse square matrix A.
14 | % sparseinv_install - compiles and installs the sparseinv function.
15 | % sparseinv_test - tests the sparseinv function.
16 |
--------------------------------------------------------------------------------
/utility/sparseinv/license.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014, Tim Davis
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are
6 | met:
7 |
8 | * Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | * Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in
12 | the documentation and/or other materials provided with the distribution
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/utility/sparseinv/sparseinv.h:
--------------------------------------------------------------------------------
1 | #ifndef _SPARSEINV_H_
2 | #define _SPARSEINV_H_
3 | #include
4 | #ifdef MATLAB_MEX_FILE
5 | #include "mex.h"
6 | #define Int mwSignedIndex
7 | #else
8 | #define Int ptrdiff_t
9 | #endif
10 |
11 | Int sparseinv /* returns 1 if OK, 0 if failure */
12 | (
13 | /* inputs, not modified on output: */
14 | Int n, /* L, U, D, and Z are n-by-n */
15 |
16 | Int *Lp, /* L is sparse, lower triangular, stored by column */
17 | Int *Li, /* the row indices of L must be sorted */
18 | double *Lx, /* diagonal of L, if present, is ignored */
19 |
20 | double *d, /* diagonal of D, of size n */
21 |
22 | Int *Up, /* U is sparse, upper triangular, stored by row */
23 | Int *Uj, /* the column indices of U need not be sorted */
24 | double *Ux, /* diagonal of U, if present, is ignored */
25 |
26 | Int *Zp, /* Z is sparse, stored by column */
27 | Int *Zi, /* the row indices of Z must be sorted */
28 |
29 | /* output, not defined on input: */
30 | double *Zx,
31 |
32 | /* workspace: */
33 | double *z, /* size n, zero on input, restored as such on output */
34 | Int *Zdiagp, /* size n */
35 | Int *Lmunch /* size n */
36 | ) ;
37 |
38 | #endif
39 |
--------------------------------------------------------------------------------
/utility/sparseinv/sparseinv_install.m:
--------------------------------------------------------------------------------
1 | function sparseinv_install
2 | %SPARSEINV_INSTALL compiles and installs the sparseinv function.
3 | % Your current working directory must be the sparseinv directory for this
4 | % function to work.
5 | %
6 | % Example:
7 | % sparseinv_install
8 | %
9 | % See also sparseinv, sparseinv_test
10 |
11 | % Copyright 2011, Timothy A. Davis, http://www.suitesparse.com
12 |
13 | is64 = ~isempty (strfind (computer, '64')) ;
14 | if (is64)
15 | fprintf ('Compiling sparseinv (64-bit)\n') ;
16 | mex -largeArrayDims sparseinv_mex.c sparseinv.c
17 | else
18 | fprintf ('Compiling sparseinv (32-bit)\n') ;
19 | mex sparseinv_mex.c sparseinv.c
20 | end
21 | addpath (pwd)
22 |
--------------------------------------------------------------------------------
/utility/sparseinv/sparseinv_mex.c:
--------------------------------------------------------------------------------
1 | #include "sparseinv.h"
2 |
3 | /*
4 | Z = sparseinv_mex (L, d, UT, Zpattern)
5 |
6 | Given (L+I)*D*(UT+I)' = A, and the symbolic Cholesky factorization of A+A',
7 | compute the sparse inverse subset, Z. UT is stored by column, so U = UT'
8 | is implicitly stored by row, and is implicitly unit-diagonal. The diagonal
9 | is not present. L is stored by column, and is also unit-diagonal. The
10 | diagonal is not present in L, either. d is a full vector of size n.
11 |
12 | This mexFunction is only meant to be called from the sparsinv m-file.
13 | An optional 2nd output argument returns the flop count.
14 |
15 | Copyright 2011, Timothy A. Davis, http://www.suitesparse.com
16 | */
17 |
18 | void mexFunction
19 | (
20 | int nargout,
21 | mxArray *pargout [ ],
22 | int nargin,
23 | const mxArray *pargin [ ]
24 | )
25 | {
26 | Int *Zp, *Zi, *Lp, *Li, *Up, *Uj, *Zpatp, *Zpati, n, *Zdiagp, *Lmunch,
27 | znz, j, p, flops ;
28 | double *Zx, *Lx, *Ux, *z, *d ;
29 |
30 | /* check inputs */
31 | if (nargin != 4 || nargout > 2)
32 | {
33 | mexErrMsgTxt ("Usage: [Z flops] = sparseinv_mex (L, d, UT, Zpattern)") ;
34 | }
35 | n = mxGetN (pargin [0]) ;
36 | for (j = 0 ; j < 4 ; j++)
37 | {
38 | if (j == 1) continue ;
39 | if (!mxIsSparse (pargin [j]) || mxIsComplex (pargin [j]) ||
40 | (mxGetM (pargin [j]) != n) || (mxGetN (pargin [j]) != n))
41 | {
42 | mexErrMsgTxt ("Matrices must be sparse, real, square, & same size");
43 | }
44 | }
45 | if (mxIsSparse (pargin [1]) || mxIsComplex (pargin [1]) ||
46 | (mxGetM (pargin [1]) != n) || (mxGetN (pargin [1]) != 1))
47 | {
48 | mexErrMsgTxt ("Input d must be a real dense vector of right size") ;
49 | }
50 |
51 | /* get inputs */
52 | Lp = (Int *) mxGetJc (pargin [0]) ;
53 | Li = (Int *) mxGetIr (pargin [0]) ;
54 | Lx = mxGetPr (pargin [0]) ;
55 |
56 | d = mxGetPr (pargin [1]) ;
57 |
58 | Up = (Int *) mxGetJc (pargin [2]) ;
59 | Uj = (Int *) mxGetIr (pargin [2]) ;
60 | Ux = mxGetPr (pargin [2]) ;
61 |
62 | Zpatp = (Int *) mxGetJc (pargin [3]) ;
63 | Zpati = (Int *) mxGetIr (pargin [3]) ;
64 | znz = Zpatp [n] ;
65 |
66 | /* create output */
67 | pargout [0] = mxCreateSparse (n, n, znz, mxREAL) ;
68 | Zx = mxGetPr (pargout [0]) ;
69 |
70 | /* get workspace */
71 | z = mxCalloc (n, sizeof (double)) ;
72 | Zdiagp = mxMalloc (n * sizeof (Int)) ;
73 | Lmunch = mxMalloc (n * sizeof (Int)) ;
74 |
75 | /* do the work */
76 | flops = sparseinv (n, Lp, Li, Lx, d, Up, Uj, Ux, Zpatp, Zpati, Zx,
77 | z, Zdiagp, Lmunch) ;
78 |
79 | /* free workspace */
80 | mxFree (z) ;
81 | mxFree (Zdiagp) ;
82 | mxFree (Lmunch) ;
83 |
84 | /* return results to MATLAB */
85 | Zp = (Int *) mxGetJc (pargout [0]) ;
86 | Zi = (Int *) mxGetIr (pargout [0]) ;
87 | for (j = 0 ; j <= n ; j++)
88 | {
89 | Zp [j] = Zpatp [j] ;
90 | }
91 | for (p = 0 ; p < znz ; p++)
92 | {
93 | Zi [p] = Zpati [p] ;
94 | }
95 |
96 | /* drop explicit zeros from the output Z matrix */
97 | znz = 0 ;
98 | for (j = 0 ; j < n ; j++)
99 | {
100 | p = Zp [j] ; /* get current location of col j */
101 | Zp [j] = znz ; /* record new location of col j */
102 | for ( ; p < Zp [j+1] ; p++)
103 | {
104 | if (Zx [p] != 0)
105 | {
106 | Zx [znz] = Zx [p] ; /* keep Z(i,j) */
107 | Zi [znz++] = Zi [p] ;
108 | }
109 | }
110 | }
111 | Zp [n] = znz ; /* finalize Z */
112 |
113 | if (nargout > 1)
114 | {
115 | pargout [1] = mxCreateDoubleScalar ((double) flops) ;
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/utility/sparseinv/sparseinv_mex.mexw64:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcosovic/MATGRID/8c92814f25b0696004d067541945cb2e65e39ed7/utility/sparseinv/sparseinv_mex.mexw64
--------------------------------------------------------------------------------