├── Main.m ├── README.md ├── d9bus.m ├── data_ne.m ├── linearization.m ├── loadflow.m └── ybus.m /Main.m: -------------------------------------------------------------------------------- 1 | clc; 2 | clear all; 3 | 4 | %% initialize variables; 5 | global Ybus nbus sys_base 6 | 7 | sys_base=100;%MVA 8 | run data_ne; 9 | nbus=39; 10 | % run d9bus; 11 | % nbus=9; 12 | %% solve ybus 13 | Ybus=ybus; 14 | 15 | %% solve loadflow 16 | 17 | [Vg,thg,Pg,Qg,Pl,Ql,PV,PQ,Vbus,theta]=loadflow; 18 | % theta - bus angle in rad 19 | % Vbus - bus voltage magnitude in per unit 20 | 21 | %% Get A, B, C matrix 22 | [A, B] = linearization(Pg,Qg,Vg,thg,Vbus,theta,PV,PQ,Pl,Ql); 23 | 24 | %% Starting invariant zero analysis 25 | 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # power_system_simulation 2 | 3 | Power system small signal analysis, multi synchronous machine model linearisation 4 | 5 | This code follow exactly from the formulation in the textbook Power System dynamics and Stability by Peter W.Sauer and M.A.Pai, 6 | published in 1997 (updated in 2006) 7 | 8 | Steps to obtain a small signal model are: 9 | 1. Get correct input data for bus, trasmission line, generators, exciters and power system stabilizers. 10 | 2. Run loadflow.m to get the operating terminal voltages and angles. 11 | 3. Get the initial condition for all variables from the large signal model. 12 | 4. Plug in all the values and construct different matrices. 13 | 5. Perform matrix operation such as Kron reduction to get matrix Asys and B. 14 | 15 | ------------------------------------------- 16 | 17 | ## Note: 18 | This include a WSCC 9 Bus 3 Machine case and New England IEEE 39 Bus case. The code is proven to be consistence with the neumerical results in Sauer and Pai's book. 19 | -------------------------------------------------------------------------------- /d9bus.m: -------------------------------------------------------------------------------- 1 | 2 | disp('9bus3Machine') 3 | disp('------------------------------------'); 4 | global bus line mac_con pss_con exc_con 5 | 6 | 7 | % b# Vm Va Pgen Qgen Pl Ql ty 8 | 9 | 10 | bus=[... 11 | 1 1.04000 .0000 0.716 0.27 0 0 1 ; 12 | 2 1.02500 0 1.63 0.067 0 0 2 ; 13 | 3 1.02500 0 0.85 -0.109 0 0 2 ; 14 | 4 1.0260 0 0 0 0 0 3 ; 15 | 5 0.996 0 0 0 1.25 0.50 3 ; 16 | 6 1.013 0 0 0 0.9 0.3 3 ; 17 | 7 1.026 0 0 0 0 0 3 ; 18 | 8 1.016 0 0 0 1 0.35 3 ; 19 | 9 1.032 0 0 0 0 0 3 ; 20 | ]; 21 | 22 | %qmx and qmn set to +999 -999 default; Vmx Vmn set to 1.5 .5 default 23 | 24 | % fb tb r x charging tap 25 | line = [... 26 | 1 4 .00000 .05760 .00000 .00 ; 27 | 2 7 .00000 .0625 .00000 .00 ; 28 | 3 9 .00000 .0586 .00000 .00 ; 29 | 4 5 .01 .085 .088*2 .00 ; 30 | 4 6 .017 .09200 .079*2 .00 ; 31 | 5 7 .03200 .16100 .153*2 .00 ; 32 | 6 9 .0390 .170 .179*2 .00 ; 33 | 7 8 .0085 .072 .0745*2 .00 ; 34 | 8 9 .0119 .1008 .1045*2 .00 ]; 35 | % tap always at from bus 36 | % tap = 1 and phase = 0 by default 37 | 38 | 39 | % generator data 40 | 41 | % machine data 42 | % num bus b-mva x_1 r_a x_d x'_d x"_d T'_do T"_do 43 | % x_q x'_q x"_q T'_qo T"_qo 44 | % H d_o d_1 type s s apf rpf 45 | mac_con = [ ... 46 | 1 1 100 0 0 0.146 0.0608 0 8.96 0 ... 47 | 0.0969 0.0969 0 0.31 0 ... 48 | 23.64 0.0125 0 1 0 0;% classical model H = 22.64 damp 0 49 | 2 2 100 0 0 0.8958 0.1198 0 6.0 0 ... 50 | 0.8645 0.1969 0 0.535 0 ... 51 | 6.4 0.0068 0 2 0 0;%salient pole generator (type 2), no saturation, damping is so low as to be negligible 52 | 3 3 100 0 0 1.3125 0.1813 0 5.89 0 ... 53 | 1.2578 0.25 0 0.6 0 ... 54 | 3.01 0.0048 0 1 0 0;% classical model H = 3.10 55 | ]; 56 | 57 | %type machine-# T_R K_A T_A T_B T_C V_Rmax V_Rmin K_E... 58 | % T_E E_1 S_E(E_1) E_2 S_E(E_2) K_F T_F 59 | exc_con = [... 60 | 1 1 0 20 0.2 0 0 1.0 -1.0 1 ... 61 | 0.314 3.1 0.33 2.3 0.10 0.063 0.35; 62 | 1 2 0 20 0.2 0 0 1.0 -1.0 1 ... 63 | 0.314 3.1 0.33 2.3 0.10 0.063 0.35; 64 | 1 3 0 20 0.2 0 0 1.0 -1.0 1 ... 65 | 0.314 3.1 0.33 2.3 0.10 0.063 0.35; 66 | ]; 67 | 68 | -------------------------------------------------------------------------------- /data_ne.m: -------------------------------------------------------------------------------- 1 | % data for New England Test case 2 | 3 | disp('Input Case: New England data') 4 | disp('------------------------------------'); 5 | global bus line mac_con pss_con exc_con 6 | % ----------- 7 | % bus data 8 | %(1.bus#)(2. volt V )( 3.ang in deg )( 4. pgen )( 5. qgen ) 9 | %(6. pload )(7. qload )(8. bus type) 10 | bus=[ 11 | 1 1.048 -9.43 0.0000 0.0000 0.0000 0.0000 3 ; 12 | 2 1.0505 -6.89 0.0000 0.0000 0.0000 0.0000 3 ; 13 | 3 1.0341 -9.73 0.0000 0.0000 3.2200 0.0240 3 ; 14 | 4 1.0116 -10.53 0.0000 0.0000 5.0000 1.8400 3 ; 15 | 5 1.0165 -9.38 0.0000 0.0000 0.0000 0.0000 3 ; 16 | 6 1.0172 -8.68 0.0000 0.0000 0.0000 0.0000 3 ; 17 | 7 1.0067 -10.84 0.0000 0.0000 2.3380 8.4000 3 ; 18 | 8 1.0057 -11.34 0.0000 0.0000 5.2200 1.7600 3 ; 19 | 9 1.0322 -11.15 0.0000 0.0000 0.0000 0.0000 3 ; 20 | 10 1.0235 -6.31 0.0000 0.0000 0.0000 0.0000 3 ; 21 | 11 1.0201 -7.12 0.0000 0.0000 0.0000 0.0000 3 ; 22 | 12 1.0072 -7.14 0.0000 0.0000 0.0850 0.8800 3 ; 23 | 13 1.0207 -7.02 0.0000 0.0000 0.0000 0.0000 3 ; 24 | 14 1.0181 -8.66 0.0000 0.0000 0.0000 0.0000 3 ; 25 | 15 1.0194 -9.06 0.0000 0.0000 3.2000 1.5300 3 ; 26 | 16 1.0346 -7.66 0.0000 0.0000 3.2940 3.2300 3 ; 27 | 17 1.0365 -8.65 0.0000 0.0000 0.0000 0.0000 3 ; 28 | 18 1.0343 -9.49 0.0000 0.0000 1.5800 0.3000 3 ; 29 | 19 1.0509 -3.04 0.0000 0.0000 0.0000 0.0000 3 ; 30 | 20 0.9914 -4.45 0.0000 0.0000 6.8000 1.0300 3 ; 31 | 21 1.0337 -5.26 0.0000 0.0000 2.7400 1.1500 3 ; 32 | 22 1.0509 -0.82 0.0000 0.0000 0.0000 0.0000 3 ; 33 | 23 1.0459 -1.02 0.0000 0.0000 2.4750 0.8460 3 ; 34 | 24 1.0399 -7.54 0.0000 0.0000 3.0860 -0.922 3 ; 35 | 25 1.0587 -5.51 0.0000 0.0000 2.2400 0.4720 3 ; 36 | 26 1.0536 -6.77 0.0000 0.0000 1.3900 0.1700 3 ; 37 | 27 1.0399 -8.78 0.0000 0.0000 2.8100 0.7550 3 ; 38 | 28 1.0509 -3.27 0.0000 0.0000 2.0600 0.2760 3 ; 39 | 29 1.0505 -0.51 0.0000 0.0000 2.8350 1.2690 3 ; 40 | 30 1.0475 -4.47 2.5000 1.3621 0.0000 0.0000 2 ; 41 | 31 1.0400 0.00 5.7293 1.7036 0.0920 0.0460 2 ; 42 | 32 0.9831 1.63 6.5000 1.7590 0.0000 0.0000 2 ; 43 | 33 0.9972 2.18 6.3200 1.0335 0.0000 0.0000 2 ; 44 | 34 1.0123 0.74 5.0800 1.6400 0.0000 0.0000 2 ; 45 | 35 1.0493 4.14 6.5000 2.0884 0.0000 0.0000 2 ; 46 | 36 1.0635 6.83 5.6000 0.9688 0.0000 0.0000 2 ; 47 | 37 1.0278 1.26 5.4000 -0.0444 0.0000 0.0000 2 ; 48 | 38 1.0265 6.55 8.3000 0.1939 0.0000 0.0000 2 ; 49 | 39 1.0300 -10.96 10.000 0.6846 11.040 2.5000 1 ]; 50 | 51 | % ----------- 52 | % line data 53 | %1.b#1 2.b#2( 3.res R )( 4. rea X )(5.charg B)(6.tap ratio ) 54 | line = [ 55 | 1 2 0.00350 0.04110 0.69870 0.0000 ; 56 | 1 39 0.00100 0.02500 0.75000 0.0000 ; 57 | 2 3 0.00130 0.01510 0.25720 0.0000 ; 58 | 2 25 0.00700 0.00860 0.14600 0.0000 ; 59 | 2 30 0.00000 0.01810 0.00000 1.0250 ; 60 | 3 4 0.00130 0.02130 0.22140 0.0000 ; 61 | 3 18 0.00110 0.01330 0.21380 0.0000 ; 62 | 4 5 0.00080 0.01280 0.13420 0.0000 ; 63 | 4 14 0.00080 0.01290 0.13820 0.0000 ; 64 | 5 8 0.00080 0.01120 0.14760 0.0000 ; 65 | 6 5 0.00020 0.00260 0.04340 0.0000 ; 66 | 6 7 0.00060 0.00920 0.11300 0.0000 ; 67 | 6 11 0.00070 0.00820 0.13890 0.0000 ; 68 | 7 8 0.00040 0.00460 0.07800 0.0000 ; 69 | 8 9 0.00230 0.03630 0.38040 0.0000 ; 70 | 9 39 0.00100 0.02500 1.20000 0.0000 ; 71 | 10 11 0.00040 0.00430 0.07290 0.0000 ; 72 | 10 13 0.00040 0.00430 0.07290 0.0000 ; 73 | 10 32 0.00000 0.02000 0.00000 1.0700 ; 74 | 12 11 0.00160 0.04350 0.00000 1.0060 ; 75 | 12 13 0.00160 0.04350 0.00000 1.0060 ; 76 | 13 14 0.00090 0.01010 0.17230 0.0000 ; 77 | 14 15 0.00180 0.02170 0.36600 0.0000 ; 78 | 15 16 0.00090 0.00940 0.17100 0.0000 ; 79 | 16 17 0.00070 0.00890 0.13420 0.0000 ; 80 | 16 19 0.00160 0.01950 0.30400 0.0000 ; 81 | 16 21 0.00080 0.01350 0.25480 0.0000 ; 82 | 16 24 0.00030 0.00590 0.06800 0.0000 ; 83 | 17 18 0.00070 0.00820 0.13190 0.0000 ; 84 | 17 27 0.00130 0.01730 0.32160 0.0000 ; 85 | 19 33 0.00070 0.01420 0.00000 1.0700 ; 86 | 19 20 0.00070 0.01380 0.00000 1.0600 ; 87 | 20 34 0.00090 0.01800 0.00000 1.0090 ; 88 | 21 22 0.00080 0.01400 0.25650 0.0000 ; 89 | 22 23 0.00060 0.00960 0.18460 0.0000 ; 90 | 22 35 0.00000 0.01430 0.00000 1.0250 ; 91 | 23 24 0.00220 0.03500 0.36100 0.0000 ; 92 | 23 36 0.00050 0.02720 0.00000 1.0000 ; 93 | 25 26 0.00320 0.03230 0.51300 0.0000 ; 94 | 25 37 0.00060 0.02320 0.00000 1.0250 ; 95 | 26 27 0.00140 0.01470 0.23960 0.0000 ; 96 | 26 28 0.00430 0.04740 0.78020 0.0000 ; 97 | 26 29 0.00570 0.06250 1.02900 0.0000 ; 98 | 28 29 0.00140 0.01510 0.24900 0.0000 ; 99 | 29 38 0.00080 0.01560 0.00000 1.0250 ; 100 | 31 6 0.00000 0.02500 0.00000 1.0000 ]; 101 | 102 | % ----------- 103 | % machine data 104 | % num bus b-mva x_1 r_a x_d x'_d x"_d T'_do T"_do 105 | % x_q x'_q x"_q T'_qo T"_qo 106 | % H d_o d_1 types apf rpf 107 | mac_con = [ 108 | 1 30 1000.0 0.130 0 1.000 0.31 0.31 10.20 0.00 ... 109 | 0.690 0.69 0.69 1.500 0 ... 110 | 4.200 0 0.00 2 0 0; 111 | 2 31 1000.0 0.350 0 2.950 0.7 0.7 6.560 0.00 ... 112 | 2.820 1.7 1.7 1.500 0.00 ... 113 | 3.030 0 0.00 3 0 0; 114 | 3 32 1000.0 0.30 0 2.500 0.530 0.530 5.700 0.0 ... 115 | 2.370 0.88 0.88 1.500 0.0 ... 116 | 3.580 0 0.00 3 0 0; 117 | 4 33 1000.0 0.295 0 2.620 0.440 0.440 5.690 0.0 ... 118 | 2.580 1.66 1.66 1.500 0.0 ... 119 | 2.860 0 0.00 3 0 0; 120 | 5 34 1000.0 0.540 0 6.700 1.320 1.32 5.400 0.0 ... 121 | 6.200 1.660 1.66 0.440 0.0 ... 122 | 2.600 0 0.00 3 0 0; 123 | 6 35 1000.0 0.224 0 2.540 0.500 0.5 7.300 0.0 ... 124 | 2.410 0.810 0.81 0.400 0.0 ... 125 | 3.480 0 0.00 3 0 0; 126 | 7 36 1000.0 0.322 0 2.900 0.490 0.49 5.660 0.0 ... 127 | 2.800 1.86 1.86 1.500 0.0 ... 128 | 2.640 0 0.00 3 0 0; 129 | 8 37 1000.0 0.280 0 2.900 0.570 0.570 6.700 0.0 ... 130 | 2.800 0.91 0.91 0.410 0.0 ... 131 | 2.430 0 0.00 3 0 0; 132 | 9 38 1000.0 0.298 0 2.106 0.570 0.570 4.790 0.0 ... 133 | 2.050 0.590 0.590 1.960 0.0 ... 134 | 3.450 0 0.00 3 0 0; 135 | 10 39 1000.0 0.030 0 0.200 0.060 0.06 7.000 0 ... 136 | 0.190 0.080 0.08 0.700 0 ... 137 | 500 0 0.00 3 0 0; 138 | ]; 139 | 140 | % ----------- 141 | % exciter data data from IEEE recommended practice for excitation system 142 | % model for power system stability study 143 | % DC1A exciter 144 | % type machine-# T_R K_A T_A T_B T_C V_Rmax V_Rmin K_E... 145 | % T_E E_1 S_E(E_1) E_2 S_E(E_2) K_F T_F 146 | exc_con = [ 147 | 1 1 0 46.0 0.06 0 0 1.0 -1.0 0 ... 148 | 0.46 3.1 0.33 2.3 0.10 0.1 1.0; 149 | 1 2 0 46.0 0.06 0 0 1.0 -1.0 0 ... 150 | 0.46 3.1 0.33 2.3 0.10 0.1 1.0; 151 | 1 3 0 46.0 0.06 0 0 1.0 -1.0 0 ... 152 | 0.46 3.1 0.33 2.3 0.10 0.1 1.0; 153 | 1 4 0 46.0 0.06 0 0 1.0 -1.0 0 ... 154 | 0.46 3.1 0.33 2.3 0.10 0.1 1.0; 155 | 1 5 0 46.0 0.06 0 0 1.0 -1.0 0 ... 156 | 0.46 3.1 0.33 2.3 0.10 0.1 1.0; 157 | 1 6 0 46.0 0.06 0 0 1.0 -1.0 0 ... 158 | 0.46 3.1 0.33 2.3 0.10 0.1 1.0; 159 | 1 7 0 46.0 0.06 0 0 1.0 -1.0 0 ... 160 | 0.46 3.1 0.33 2.3 0.10 0.1 1.0; 161 | 1 8 0 46.0 0.06 0 0 1.0 -1.0 0 ... 162 | 0.46 3.1 0.33 2.3 0.10 0.1 1.0; 163 | 1 9 0 46.0 0.06 0 0 1.0 -1.0 0 ... 164 | 0.46 3.1 0.33 2.3 0.10 0.1 1.0; 165 | ]; 166 | 167 | 168 | 169 | 170 | % ----------- 171 | % pss data type PSS1A with speed input 172 | % column 1 type 1 for speed input 173 | % column 2 generator number 174 | % column 3 Gpss pss gain 175 | % column 4 Tw 176 | % column 5 Tn1 177 | % column 6 Td1 178 | % column 7 Tn2 179 | % column 8 Td2 180 | % column 9 ymax 181 | % column 10 ymin 182 | pss_con=[ 183 | 1 1 3.15 10.0 0.76 0.1 0.76 0.1 0.09 -0.09; 184 | 1 2 3.15 10.0 0.76 0.1 0.76 0.1 0.09 -0.09; 185 | 1 3 3.15 10.0 0.76 0.1 0.76 0.1 0.09 -0.09; 186 | 1 4 3.15 10.0 0.76 0.1 0.76 0.1 0.09 -0.09; 187 | 1 5 3.15 10.0 0.76 0.1 0.76 0.1 0.09 -0.09; 188 | 1 6 3.15 10.0 0.76 0.1 0.76 0.1 0.09 -0.09; 189 | 1 7 3.15 10.0 0.76 0.1 0.76 0.1 0.09 -0.09; 190 | 1 8 3.15 10.0 0.76 0.1 0.76 0.1 0.09 -0.09; 191 | 1 9 3.15 10.0 0.76 0.1 0.76 0.1 0.09 -0.09; 192 | ]; 193 | 194 | 195 | 196 | 197 | -------------------------------------------------------------------------------- /linearization.m: -------------------------------------------------------------------------------- 1 | function [Asys, Bsys] = linearization(Pg,Qg,Vg,thg,Vbus,theta,PV,PQ,Pl,Ql) 2 | % 3 | % 4 | disp('Starting to read all the data'); 5 | %% pre-define all variables 6 | global sys_base mac_con exc_con pss_con Ybus nbus 7 | 8 | %================= machine data========================= 9 | len_mac=size(mac_con,1); 10 | mac_indx = mac_con(:,1); 11 | mac_bus_indx = mac_con(:,2); 12 | BM=mac_con(:,3)/sys_base; % uniform base conversion matrix 13 | %xls=mac_con(:,4)./BM; % leakage reactance, unused 14 | Ra=mac_con(:,5)./BM; % resistance, unused 15 | xd=mac_con(:,6)./BM; % d-axis synchronous reactance 16 | xdd=mac_con(:,7)./BM; % d-axis transient reactance 17 | %xddd=mac_con(:,8)./BM; % d-axis subtransient reactance 18 | Td0d=mac_con(:,9); % d-axis time constant 19 | %Td0dd=mac_con(:,10); % d-axis subtransient time constant unused 20 | xq=mac_con(:,11)./BM; % q-axis reactance 21 | xqd=mac_con(:,12)./BM; % q-axis transient reactance 22 | %xqdd=mac_con(:,13)./BM; % q-axis subtransient reactance 23 | Tq0d=mac_con(:,14); % q-axis time constant 24 | %Tq0dd=mac_con(:,15); % q-axis subtransient time constant unused 25 | H=mac_con(:,16).*BM; % Inertial constant 26 | D=mac_con(:,17).*BM; % damping 27 | %D=[0;0;0]; 28 | f=60; % 60Hz base frequency 29 | wB=2*pi*f; %base frequency in rad/s 30 | M=2.*H/wB; 31 | N_Machine=size(mac_con,1); 32 | 33 | %===========machine end================= 34 | 35 | %===========exciter data================ 36 | Tr=ones(N_Machine,1); 37 | KA=zeros(N_Machine,1); 38 | Ta=ones(N_Machine,1); 39 | Ke=ones(N_Machine,1); 40 | Te=ones(N_Machine,1); 41 | Kf=zeros(N_Machine,1); 42 | Tf=ones(N_Machine,1); 43 | E1=zeros(N_Machine,1); 44 | E2=zeros(N_Machine,1); 45 | SEE1=zeros(N_Machine,1); 46 | SEE2=zeros(N_Machine,1); 47 | len_exc=size(exc_con,1); 48 | Exc_indx = exc_con(:,2); 49 | for i=1:len_exc 50 | Exc_m_indx=exc_con(i,2);%present machine index 51 | Tr(Exc_m_indx)=exc_con(i,3); 52 | Ta(Exc_m_indx)=exc_con(i,5); 53 | Ke(Exc_m_indx)=exc_con(i,10); 54 | Te(Exc_m_indx)=exc_con(i,11); 55 | Kf(Exc_m_indx)=exc_con(i,16); 56 | Tf(Exc_m_indx)=exc_con(i,17); 57 | KA(Exc_m_indx)=exc_con(i,4); 58 | E1(Exc_m_indx)=exc_con(i,12); 59 | E2(Exc_m_indx)=exc_con(i,14); 60 | SEE1(Exc_m_indx)=exc_con(i,13); 61 | SEE2(Exc_m_indx)=exc_con(i,15); 62 | end 63 | %================exciter end================= 64 | 65 | %================pss1A======================= 66 | Ks=zeros(N_Machine,1); 67 | Tw=ones(N_Machine,1); 68 | T1=ones(N_Machine,1); 69 | T2=ones(N_Machine,1); 70 | T3=ones(N_Machine,1); 71 | T4=ones(N_Machine,1); 72 | Vs_max=zeros(N_Machine,1); 73 | Vs_min=zeros(N_Machine,1); 74 | len_pss=size(pss_con,1); 75 | for i=1:len_pss 76 | Pss_m_indx=pss_con(i,2);%present machine index 77 | Ks(Pss_m_indx)=pss_con(i,3);%pssgain 78 | Tw(Pss_m_indx)=pss_con(i,4);%washout time constant 79 | T1(Pss_m_indx)=pss_con(i,5);%first lead time constant 80 | T2(Pss_m_indx)=pss_con(i,6);%first lag time constant 81 | T3(Pss_m_indx)=pss_con(i,7);%second lead time constant 82 | T4(Pss_m_indx)=pss_con(i,8);%second lag time constant 83 | Vs_max(Pss_m_indx)=pss_con(i,9);%maximum output limit 84 | Vs_min(Pss_m_indx)=pss_con(i,10);%minimum output limit 85 | end 86 | %==============pss end========================== 87 | disp('Finish reading all data!'); 88 | disp('---------------------------'); 89 | disp('Start to calculate initial values'); 90 | %% ==============calculate initial condition============ 91 | % 1. calculate complex injection current for all generator bus (page 190) 92 | j=sqrt(-1); 93 | voltage = Vg.*(cos(thg) + j*sin(thg)); %Vg in complex form 94 | current = conj((Pg+j*Qg)./voltage); % Ig in complex form 95 | % 2. compute delta0 (voltage angle reference) for generator 96 | delta0 = angle(voltage + (Ra+j.*xq).*current); % in rad 97 | % 3. compute w0 98 | w0 = wB; 99 | % 4. compute Id and Iq 100 | id0 = abs(current) .* sin(delta0 - angle(current)); 101 | iq0 = abs(current) .* cos(delta0 - angle(current)); 102 | vd0 = abs(voltage) .* (sin(delta0 - angle(voltage))); 103 | vq0 = abs(voltage) .* cos(delta0 - angle(voltage)); 104 | % 5. compute Eqd0,Edd0 105 | Edd0 = (xq-xqd) .* iq0; 106 | assert(max(abs(vd0+Ra.*id0-xqd.*iq0 - Edd0))<10e-10); 107 | Eqd0 = abs(voltage).*cos(delta0 - angle(voltage))+xdd.*id0; 108 | assert(max(abs(vq0+Ra.*iq0+xdd.*id0 - Eqd0))<10e-10); 109 | % 6. compute Efd 110 | Efd0=Eqd0+(xd-xdd).*id0; 111 | % compute Vref 112 | Vref0 = Efd0; % no exciter 113 | Vref0(Exc_indx,:) = Efd0(Exc_indx,:)./KA(Exc_indx,:) + Vg(Exc_indx,:);% with exciter 114 | % compute Tm 115 | Tm = Eqd0.*iq0+(xq-xdd).*id0.*iq0; 116 | %============end initial condition calculation======= 117 | disp('All the initial values has been calculated'); 118 | disp('------------------------------------'); 119 | %% =========get state space representation============ 120 | 121 | 122 | A1 = []; 123 | B1 = []; 124 | B2 = []; 125 | E_1 = []; 126 | C1=[]; 127 | D1=[]; 128 | D2=[]; 129 | C2=[]; 130 | for k=1:len_mac 131 | i=mac_indx(k); 132 | if find(Exc_indx==mac_indx(k)) %if the exciter exist, 7 states 133 | 134 | % calculate S_E(Efd) and its derivative--page 70, equation 4.22 135 | Bxi = log(SEE1(i)/SEE2(i))/(E1(i)-E2(i)); 136 | Axi = SEE1(i)/exp(Bxi*E1(i)); 137 | % Axi = 0.0039; 138 | % Bxi = 1.555; 139 | fsi = -(Ke(i)+Efd0(i)*Axi*Bxi*exp(Bxi*Efd0(i)) + Axi*exp(Bxi*Efd0(i)))/Te(i); 140 | % get sub matrices 141 | % A1i, B1i, B2i, E1i (eqn 8.27), page 220 142 | A1i = [ 143 | 0 1 0 0 0 0 0; %delta 144 | 0 -D(i)/M(i) -iq0(i)/M(i) -id0(i)/M(i) 0 0 0; %w 145 | 0 0 -1/Td0d(i) 0 1/Td0d(i) 0 0; %Eqd 146 | 0 0 0 -1/Tq0d(i) 0 0 0; %Edd 147 | 0 0 0 0 fsi 1/Te(i) 0; %Efd 148 | 0 0 0 0 -KA(i)*Kf(i)/Ta(i)/Tf(i) -1/Ta(i) KA(i)/Ta(i);%VR 149 | 0 0 0 0 Kf(i)/(Tf(i))^2 0 -1/Tf(i); %Rf 150 | ]; 151 | B1i = [ %id iq 152 | 0 0; 153 | (iq0(i)*(xdd(i)-xqd(i))-Edd0(i))/M(i) (id0(i)*(xdd(i)-xqd(i))-Eqd0(i))/M(i); 154 | -(xd(i)-xdd(i))/Td0d(i) 0; 155 | 0 (xq(i)-xqd(i))/Tq0d(i); 156 | 0 0; 157 | 0 0; 158 | 0 0; 159 | ]; 160 | B2i = [ % theta, V 161 | 0 0; 162 | 0 0; 163 | 0 0; 164 | 0 0; 165 | 0 0; 166 | 0 -KA(i)/Ta(i); 167 | 0 0; 168 | ]; 169 | E1i = [ % Tm Vref 170 | 0 0; 171 | 1/M(i) 0; 172 | 0 0; 173 | 0 0; 174 | 0 0; 175 | 0 KA(i)/Ta(i); 176 | 0 0; 177 | ]; 178 | 179 | % C1i, D1i, D2i (eqn 8.32) 180 | C1i =[ 181 | -Vg(i)*cos(delta0(i)-thg(i)) 0 0 1 0 0 0; 182 | Vg(i)*sin(delta0(i)-thg(i)) 0 1 0 0 0 0; 183 | ]; 184 | D1i =[ 185 | -Ra(i) xqd(i); 186 | -xdd(i) -Ra(i); 187 | ]; 188 | D2i=[ 189 | Vg(i)*cos(delta0(i)-thg(i)) -sin(delta0(i)-thg(i)); 190 | -Vg(i)*sin(delta0(i)-thg(i)) -cos(delta0(i)-thg(i)); 191 | ]; 192 | % C2 193 | C2i= [id0(i)*Vg(i)*cos(delta0(i)-thg(i))-iq0(i)*Vg(i)*sin(delta0(i)-thg(i)) 0 0 0 0 0 0; 194 | -iq0(i)*Vg(i)*cos(delta0(i)-thg(i))-id0(i)*Vg(i)*sin(delta0(i)-thg(i)) 0 0 0 0 0 0]; 195 | A1 =blkdiag(A1, A1i); 196 | B1 =blkdiag(B1, B1i); 197 | B2 =blkdiag(B2, B2i); 198 | E_1 =blkdiag(E_1, E1i); 199 | C1 =blkdiag(C1, C1i); 200 | D1 =blkdiag(D1, D1i); 201 | D2 =blkdiag(D2, D2i); 202 | C2 =blkdiag(C2, C2i); 203 | else %if the exciter do not exist, 4 states 204 | % only the first 4 equations 205 | % A1i, B1i, B2i, E1i (eqn 8.27), page 220 206 | A1i = [ 207 | 0 1 0 0 ; %delta 208 | 0 -D(i)/M(i) -iq0(i)/M(i) -id0(i)/M(i) ; %w 209 | 0 0 -1/Td0d(i) 0 ; %Eqd 210 | 0 0 0 -1/Tq0d(i) ; %Edd 211 | ]; 212 | B1i = [%Id, Iq 213 | 0 0; 214 | (iq0(i)*(xdd(i)-xqd(i))-Edd0(i))/M(i) (id0(i)*(xdd(i)-xqd(i))-Eqd0(i))/M(i); 215 | -(xd(i)-xdd(i))/Td0d(i) 0; 216 | 0 (xq(i)-xqd(i))/Tq0d(i); 217 | ]; 218 | B2i = zeros(4,2); 219 | E1i = [ % Tm Vref 220 | 0 0; 221 | 1/M(i) 0; 222 | 0 1/Td0d(i); 223 | 0 0; 224 | ]; 225 | 226 | % C1i, D1i, D2i (eqn 8.32) 227 | C1i =[ 228 | -Vg(i)*cos(delta0(i)-thg(i)) 0 0 1; 229 | Vg(i)*sin(delta0(i)-thg(i)) 0 1 0; 230 | ]; 231 | D1i =[ 232 | -Ra(i) xqd(i); 233 | -xdd(i) -Ra(i); 234 | ]; 235 | D2i=[ 236 | Vg(i)*cos(delta0(i)-thg(i)) -sin(delta0(i)-thg(i)); 237 | -Vg(i)*sin(delta0(i)-thg(i)) -cos(delta0(i)-thg(i)); 238 | ]; 239 | % C2 240 | C2i= [id0(i)*Vg(i)*cos(delta0(i)-thg(i))-iq0(i)*Vg(i)*sin(delta0(i)-thg(i)) 0 0 0; 241 | -iq0(i)*Vg(i)*cos(delta0(i)-thg(i))-id0(i)*Vg(i)*sin(delta0(i)-thg(i)) 0 0 0]; 242 | A1 =blkdiag(A1, A1i); 243 | B1 =blkdiag(B1, B1i); 244 | B2 =blkdiag(B2, B2i); 245 | E_1 =blkdiag(E_1, E1i); 246 | C1 =blkdiag(C1, C1i); 247 | D1 =blkdiag(D1, D1i); 248 | D2 =blkdiag(D2, D2i); 249 | C2 =blkdiag(C2, C2i); 250 | end 251 | end 252 | 253 | D3=[]; 254 | D4 = zeros(2*len_mac,2*len_mac); 255 | D5 = zeros(2*len_mac,2*(nbus-len_mac)); 256 | % D3, D4, D5 (eqn 8.36) 257 | for l=1:len_mac 258 | p=mac_indx(l); % index of generator, usually 1,2,3 259 | m=mac_bus_indx(l); % index of generator's bus 260 | % D3 261 | D3i =[Vg(p)*sin(delta0(p)-thg(p)) Vg(p)*cos(delta0(p)-thg(p)); 262 | Vg(p)*cos(delta0(p)-thg(p)) -Vg(p)*sin(delta0(p)-thg(p))]; % Id Iq 263 | D3 =blkdiag(D3, D3i); 264 | 265 | 266 | %!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 267 | % D4 m x 2len_mac 268 | for k=1:len_mac 269 | q = mac_indx(k); 270 | n = mac_bus_indx(k); 271 | if p==q 272 | % d_thetai 273 | D4(2*l-1,2*k-1)= -id0(p)*Vg(p)*cos(delta0(p)-thg(p))+iq0(p)*Vg(p)*sin(delta0(p)-thg(p)); 274 | D4(2*l,2*k-1) = iq0(p)*Vg(p)*cos(delta0(p)-thg(p))+id0(p)*Vg(p)*sin(delta0(p)-thg(p)); 275 | for kk = 1:nbus 276 | if kk ~= m 277 | D4(2*l-1,2*k-1)= D4(2*l-1,2*k-1) + Vg(p)* Vbus(kk)*abs(Ybus(m,kk))*sin(thg(p)-theta(kk)-angle(Ybus(m,kk))); 278 | D4(2*l,2*k-1)= D4(2*l,2*k-1) - Vg(p)* Vbus(kk)*abs(Ybus(m,kk))*cos(thg(p)-theta(kk)-angle(Ybus(m,kk))); 279 | end 280 | end 281 | % d_Vi 282 | D4(2*l-1,2*k)= id0(p)*sin(delta0(p)-thg(p))+iq0(p)*cos(delta0(p)-thg(p))... 283 | - Vg(p)*abs(Ybus(m,m))*cos(thg(p)-thg(p)-angle(Ybus(m,m))); 284 | D4(2*l,2*k)= -iq0(p)*sin(delta0(p)-thg(p))+id0(p)*cos(delta0(p)-thg(p))... 285 | - Vg(p)*abs(Ybus(m,m))*sin(thg(p)-thg(p)-angle(Ybus(m,m))); 286 | for kk = 1:nbus 287 | D4(2*l-1,2*k)=D4(2*l-1,2*k) - Vbus(kk)*abs(Ybus(m,kk))*cos(thg(p)-theta(kk)-angle(Ybus(m,kk))); 288 | D4(2*l,2*k)=D4(2*l,2*k)- Vbus(kk)*abs(Ybus(m,kk))*sin(thg(p)-theta(kk)-angle(Ybus(m,kk))); 289 | end 290 | else 291 | D4(2*l-1,2*k-1) = -Vg(p)*Vg(q)*abs(Ybus(m,n))*sin(thg(p)-thg(q)-angle(Ybus(m,n))); 292 | D4(2*l,2*k-1)= Vg(p)*Vg(q)*abs(Ybus(m,n))*cos(thg(p)-thg(q)-angle(Ybus(m,n))); 293 | D4(2*l-1,2*k) = -Vg(p)*abs(Ybus(m,n))*cos(thg(p)-thg(q)-angle(Ybus(m,n))); 294 | D4(2*l,2*k) = -Vg(p)*abs(Ybus(m,n))*sin(thg(p)-thg(q)-angle(Ybus(m,n))); 295 | end 296 | 297 | end 298 | %D5 m x 2(nbus-len_mac) 299 | for kp=1:(nbus-len_mac) 300 | kk = PQ(kp); 301 | D5(2*l-1,2*kp-1) = -Vg(p)*Vbus(kk)*abs(Ybus(m,kk))*sin(thg(p)-theta(kk)-angle(Ybus(m,kk))); 302 | D5(2*l,2*kp-1) = Vg(p)*Vbus(kk)*abs(Ybus(m,kk))*cos(thg(p)-theta(kk)-angle(Ybus(m,kk))); 303 | D5(2*l-1,2*kp) = -Vg(p)*abs(Ybus(m,kk))*cos(thg(p)-theta(kk)-angle(Ybus(m,kk))); 304 | D5(2*l,2*kp) = -Vg(p)*abs(Ybus(m,kk))*sin(thg(p)-theta(kk)-angle(Ybus(m,kk))); 305 | end 306 | %!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 307 | end 308 | D6=zeros(2*(nbus-len_mac),2*len_mac); 309 | D7=zeros(2*(nbus-len_mac),2*(nbus-len_mac)); 310 | % D6, D7 (eqn 8.40) 311 | for l=1:(nbus-len_mac) 312 | % D6 2npq x 2npv 313 | m = PQ(l); % index of PQ bus 314 | for kg = 1:len_mac 315 | n = PV(kg); 316 | D6(2*l-1,2*kg-1)=-Vbus(m)*Vbus(n)*abs(Ybus(m,n))*sin(theta(m)-theta(n)-angle(Ybus(m,n))); 317 | D6(2*l,2*kg-1)= Vbus(m)*Vbus(n)*abs(Ybus(m,n))*cos(theta(m)-theta(n)-angle(Ybus(m,n))); 318 | D6(2*l-1,2*kg)=-Vbus(m)*abs(Ybus(m,n))*cos(theta(m)-theta(n)-angle(Ybus(m,n))); 319 | D6(2*l,2*kg)=-Vbus(m)*abs(Ybus(m,n))*sin(theta(m)-theta(n)-angle(Ybus(m,n))); 320 | end 321 | % D7 2npq x 2npq 322 | for k = 1:(nbus-len_mac) 323 | n = PQ(k); 324 | if m == n 325 | for kk = 1:nbus 326 | %d_theta 327 | if kk ~= m 328 | D7(2*l-1,2*k-1)= D7(2*l-1,2*k-1)+ Vbus(m)*Vbus(kk)*abs(Ybus(m,kk))*sin(theta(m)-theta(kk)-angle(Ybus(m,kk))); 329 | D7(2*l,2*k-1)= D7(2*l,2*k-1)-Vbus(m)*Vbus(kk)*abs(Ybus(m,kk))*cos(theta(m)-theta(kk)-angle(Ybus(m,kk))); 330 | end 331 | end 332 | D7(2*l-1,2*k)= -Vbus(m)*abs(Ybus(m,n))*cos(theta(m)-theta(n)-angle(Ybus(m,n))); 333 | D7(2*l,2*k)= -Vbus(m)*abs(Ybus(m,n))*sin(theta(m)-theta(n)-angle(Ybus(m,n))); 334 | for kk = 1:nbus 335 | D7(2*l-1,2*k)= D7(2*l-1,2*k) - Vbus(kk)*abs(Ybus(m,kk))*cos(theta(m)-theta(kk)-angle(Ybus(m,kk))); 336 | D7(2*l,2*k)= D7(2*l,2*k) -Vbus(kk)*abs(Ybus(m,kk))*sin(theta(m)-theta(kk)-angle(Ybus(m,kk))); 337 | end 338 | else 339 | D7(2*l-1,2*k-1)= -Vbus(m)*Vbus(n)*abs(Ybus(m,n))* sin(theta(m)-theta(n)-angle(Ybus(m,n))); 340 | D7(2*l,2*k-1) = Vbus(m)*Vbus(n)*abs(Ybus(m,n))* cos(theta(m)-theta(n)-angle(Ybus(m,n))); 341 | D7(2*l-1,2*k)= -Vbus(m)*abs(Ybus(m,n))*cos(theta(m)-theta(n)-angle(Ybus(m,n))); 342 | D7(2*l,2*k)= -Vbus(m)*abs(Ybus(m,n))*sin(theta(m)-theta(n)-angle(Ybus(m,n))); 343 | end 344 | end 345 | end 346 | % Get Asys 347 | Asys = A1-B1*inv(D1)*C1-(B2-B1*inv(D1)*D2)*inv(D4-D3*inv(D1)*D2-D5*inv(D7)*D6)*(C2-D3*inv(D1)*C1); 348 | % get B matrix for different setup 349 | Bsys= E_1; 350 | 351 | 352 | 353 | end 354 | 355 | -------------------------------------------------------------------------------- /loadflow.m: -------------------------------------------------------------------------------- 1 | function [Vg,thg,Pgen,Qgen,Pl,Ql,pv,pq,V,theta]=loadflow; 2 | % Newton Raphson method for loadflow 3 | % Detailed explanation goes here 4 | 5 | %% all variables 6 | global nbus sys_base Ybus bus line 7 | type = bus(:,8); 8 | V = bus(:,2); 9 | Pg = bus(:,4); 10 | Pl = bus(:,6); 11 | Ql = bus(:,7); 12 | % pre allocate variables 13 | theta = zeros(nbus,1); 14 | Qg = zeros(nbus,1); 15 | 16 | P = Pg-Pl; 17 | Q = Qg-Ql; 18 | Psp = P; 19 | Qsp = Q; 20 | G = real(Ybus); 21 | B = imag(Ybus); 22 | pv = find(type == 2 | type == 1); 23 | pq = find(type == 3); 24 | npv = length(pv); 25 | npq = length(pq); 26 | err = 1; % error 27 | Iter = 1; % iteration counter 28 | disp('Starting loadflow'); 29 | %% start the while loop 30 | while (err>1e-12) 31 | % calculate P and Q using V, theta, G and B 32 | P = zeros(nbus,1); 33 | Q = zeros(nbus,1); 34 | for i = 1:nbus 35 | for k = 1:nbus 36 | P(i)= P(i) + V(i)*V(k)*(G(i,k)*cos(theta(i)-theta(k))+B(i,k)*sin(theta(i)-theta(k))); 37 | Q(i)= Q(i) + V(i)*V(k)*(G(i,k)*sin(theta(i)-theta(k))-B(i,k)*cos(theta(i)-theta(k))); 38 | end 39 | end 40 | % calculat the change from specified value 41 | dPa = Psp-P; 42 | dQa = Qsp-Q; 43 | k = 1; % iterator for load bus 44 | dQ = zeros(npq,1); 45 | for i = 1:nbus 46 | if type(i) ==3 47 | dQ(k,1) = dQa(i); 48 | k = k+1; 49 | end 50 | end 51 | dP = dPa(type~=1); %dP for slack bus is 0... 52 | M = [dP; dQ]; %mismatch vector 53 | 54 | % Jacobian 55 | % J1 = dP/d theta 56 | J1 = zeros(nbus,nbus); 57 | for i=1:nbus 58 | for k=1:nbus 59 | if k== i 60 | for n=1:nbus 61 | J1(i,k)=J1(i,k)+V(i)*V(n)*(-G(i,n)*sin(theta(i)-theta(n))+B(i,n)*cos(theta(i)-theta(n))); 62 | end 63 | J1(i,k)=J1(i,k)-V(i)^2*B(i,i); 64 | else 65 | J1(i,k)= V(i)*V(k)*(G(i,k)*sin(theta(i)-theta(k))-B(i,k)*cos(theta(i)-theta(k))); 66 | end 67 | end 68 | end 69 | J1=J1(type~=1,type~=1); 70 | % J2 = dP/ dV , we only need PQ bus here because dP/dV for PV bus is 0 71 | J2 = zeros(nbus,npq); 72 | for i=1:nbus 73 | for k=1:npq 74 | n=pq(k); % get the index of pq bus 75 | if n == i 76 | for np=1:nbus % this n is inside this scope only 77 | J2(i,k)=J2(i,k)+V(np)*(G(i,np)*cos(theta(i)-theta(np))+B(i,np)*sin(theta(i)-theta(np))); 78 | end 79 | J2(i,k)=J2(i,k)+V(i)*G(i,i); 80 | else 81 | J2(i,k)=V(i)*(G(i,n)*cos(theta(i)-theta(n))+B(i,n)*sin(theta(i)-theta(n))); 82 | end 83 | end 84 | end 85 | J2 = J2(type~=1,:); 86 | % J3 = dQ/ d theta, we only need PQ bus here 87 | J3 = zeros(npq,nbus); 88 | for i = 1:npq 89 | m = pq(i);% get the index of pq bus 90 | for k = 1:nbus 91 | if k==m 92 | for n=1:nbus 93 | J3(i,k)=J3(i,k)+V(m)*V(n)*(G(m,n)*cos(theta(m)-theta(n))+B(m,n)*sin(theta(m)-theta(n))); 94 | end 95 | J3(i,k)=J3(i,k)-V(m)^2*G(m,m); 96 | else 97 | J3(i,k)= V(m)*V(k)*(-G(m,k)*cos(theta(m)-theta(k))-B(m,k)*sin(theta(m)-theta(k))); 98 | end 99 | end 100 | end 101 | J3 = J3(:,type~=1); 102 | % J4 = dQ/ dV 103 | J4 = zeros(npq,npq); 104 | for i= 1:npq 105 | m=pq(i); 106 | for k = 1:npq 107 | n=pq(k); 108 | if m==n 109 | for n = 1:nbus % this n is local scope 110 | J4(i,k)=J4(i,k)+V(n)*(G(m,n)*sin(theta(m)-theta(n))-B(m,n)*cos(theta(m)-theta(n))); 111 | end 112 | J4(i,k)=J4(i,k) - V(m)*B(m,m); 113 | else 114 | J4(i,k)=V(m)*(G(m,n)*sin(theta(m)-theta(n))-B(m,n)*cos(theta(m)-theta(n))); 115 | end 116 | end 117 | end 118 | J = [J1 J2;J3 J4]; 119 | % calculate mismatch 120 | X = J\M; % the correction term 121 | dtheta = X (1:nbus-1); 122 | dV = X(nbus:end); 123 | % update the state vector 124 | theta(type~=1) = dtheta + theta(type~=1); 125 | V(pq) = dV+V(pq); 126 | err= max(abs(M)); 127 | Iter = Iter+1; 128 | end 129 | fprintf('Finish! The number of iteration of loadflow program is %d.\n',Iter); 130 | disp('------------------------------------'); 131 | %% get all outputs 132 | Vg(1:npv,1)=V(pv); %terminal voltage of generator unchange 133 | thg(1:npv,1)=theta(pv); %angle of generator, this will change 134 | Pgen(1:npv,1) = P(pv)+Pl(pv); % P for generator 135 | Qgen(1:npv,1) = Q(pv)+Pl(pv); % Q for generator 136 | end 137 | 138 | -------------------------------------------------------------------------------- /ybus.m: -------------------------------------------------------------------------------- 1 | function Y = ybus 2 | % Calculate the system ybus 3 | % input data is line and bus data 4 | global line nbus 5 | i=sqrt(-1); 6 | %% read data 7 | FromIndex = line(:,1); 8 | ToIndex = line(:,2); 9 | R = line(:,3); 10 | X = line(:,4); 11 | B = line(:,5); % each end assign B/2 !!!\ 12 | tap = line(:,6); 13 | tap(tap == 0) = 1; 14 | Z = R + i*X; % impedance of that line 15 | y = 1./Z; % admintance of that line 16 | nline = length(FromIndex); % number of lines 17 | 18 | %% form Ybus 19 | Y=zeros(nbus,nbus); 20 | % off diagonal elements 21 | for k=1:nline 22 | Y(FromIndex(k),ToIndex(k))= Y(FromIndex(k),ToIndex(k))-y(k)/tap(k); 23 | Y(ToIndex(k),FromIndex(k))= Y(FromIndex(k),ToIndex(k)); 24 | end 25 | % diagonal elements 26 | for m=1:nbus 27 | for n=1:nline 28 | if FromIndex(n)==m 29 | Y(m,m)=Y(m,m)+y(n)/(tap(n)^2) + i*B(n)/2; 30 | elseif ToIndex(n)==m 31 | Y(m,m)=Y(m,m)+y(n)+i*B(n)/2; 32 | end 33 | end 34 | end 35 | 36 | 37 | end 38 | 39 | --------------------------------------------------------------------------------