├── 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 --------------------------------------------------------------------------------