CHAPTER 6: Fast Decoupled Loadflow

FDLF is an improvement to NRLF. The Jacobian matrix is only one fourth in size, and iteration alternates between real power and reactive power.
FDLF_Eq. (1)
By setting J=N=0, the jacobian matrix can be decoupled, i.e., separated or divorced. The principle underlying is based on two observations: 1)Change in voltage angle at a node affects real power flow on a line and leaves the reactive power relatively unchanged. 2) Change in voltage magnitude at a node affects the reactive line power flow and leaves the real power flow relatively unaffected. We are then left with two separate system of equations. These 2 systems are decoupled in the sense that voltage angle corrections are calculated using delta-P and voltage magnitude with delta-Q. H and L are still interdependent with voltage angle and magnitude.
FDLF_Eq. (2) decoupled Newton-Raphson.
FDLF_Eq. (3) injected node-i real and reactive power
FDLF_Eq. (4) H-elements
FDLF_Eq. (5) Hii in terms of Qi
FDLF_Eq. (6) L-elements
FDLF_Eq. (7) Lii in terms of Qi

Equations 3,4,5,6 and 7 were already derived from the previous chapter and shown here as a summary. In Eq. (4), we add and subtract EiEiBii. The one we add inside the summation removes the restriction when i=j. This summation now becomes -Qi, as in Eq. (3). In order to equate Qi in Eq.(6), we move one part of -2EiEiBii inside the summation, thus remove the restriction when i=j. Qi is shown in Eq. (3). There is a purpose for doing this.

Then we introduce the following assumptions
FDLF_Eq. (8)

We can equate H=L so that there is only one matrix used in updating the voltage magnitude and angle. The drawback is that the Jacobian matrix need be replaced in every iteration due to a new set of voltages. It is desired to have H and L remain constant in all iterations. Eq. (9) is the matrix form of Eq. (8) for the H matrix.
FDLF_Eq. (9)

Let us rewrite Eq. (9) by factoring out the voltage.
FDLF_Eq. (10)

Then transfer the voltage outside the Jacobian as a divisor of delta-P and multiplier of delta-theta. All these equation manipulations did not alter the system of equations, only its look.
FDLF_Eq. (11)

We can write the decoupled sets as
FDLF_Eq. (12)
in here the Jacobian matrix remains constant in each iteration, because H and L is no longer a function of voltage magnitude and angle. For the delta-Q, E cancels.

Further simplifications are applied for delta-P.
1. omit shunt reactance like off-nominal tap and line capacitance-- it does not affect theta.
2. From delta theta.E, set E=1.0. Removing the influence of Mvar flows on theta since E affects Mvar and theta affects Mw.
3. neglect resistance, Bij prime=numerically negative reciprocal of line reactance (Xij)
For delta-Q, omit phase shifter, it does not affect E. Bij double prime = -Bij of the Ybus.

Program Listing_1: FAST DECOUPLED LOADFLOW



Code Explanation:

B' (prime) and B'' (double prime) represents the Jacobian matrix H and L. This time, it is computed only once and remains unchanged from iteration to iteration. They are computed as data is read from a file and factored using LU factorization. Forward and backward course is performed on delta-P with B' and delta-Q with B''. To include PV busses, just delete the row and column on B". Shown on the next textbox is the LU factorization with forward and backward course to simulate the row and column delete both for unsymmetric and symmetric matrices. For symmetric matrix, there is no need to store the lower half (L) of the matrix as its value can be taken from (U) and divide it by the diagonal. We are using only one subroutine to perform the said LU and forward/backward course. By passing a code=1 for B' there is no delete for PV. With code=2 for B", there is a need to test for PV. To do the test we use [if (code <2 || !type[k])]. The 2 vertical lines stands for "or". Computation will be done if code=1 for B' or if code=2 and type[k]=0. The first condition will be false because code is not less than 2. The second condition will be true only if type[k] is zero, for PQ. So if it is PV, the loop is not performed. We will utilize the symmetric LU for our sparsity programming. AT this point, you must be familiar now full matrix techniques. Go back and review because sparsity will be complex to comprehend.

Program Listing_2: Comparison of LU on symmetric and non-symmetric Matrix

Program Listing_3: FAST DECOUPLED LOADFLOW- Sparse Matrix Applied

This code is in C. There are limitations in this code to make it easier to comprehend.

1. Node numbering must be contiguous starting from 1.
2. There is only one linked list to cover B' and B".
3. Slack and PV busses may be located randomly. This will be taken cared in
     LU factorization and also in the forward and backward course.
4. There is no optimal ordering.
5. There can be no parallel branches.

Shown after the listing is the output.



Code Explanation:
The theory for sparsity can be read from chapter 7 of the companion eBOOK, "Part 1: Short Circuit Calculation". That chapter includes optimal ordering too. The solution to large simultaneous equations in the form of Ax=b is in chapter 3. We will apply all these theories in the code above.

Some subroutines are basically the same. Like flows(),deltaP((),deltaQ() and main(). We follow the notation from fdlfC1.cpp when rewriting lufact() and Solve(). Subroutine input() when forming the linked-list is the same as in gslifo.cpp.

New subroutines for this code is Get_RHSnodes() and BrnSrNsrt(). The first one will get all the right hand side nodes including its address. If you are looking for branch i-j and j is at right side of i, the address referred to is the address of branch i-j. The next function BrnSrNsrt() is to search for a branch to be modified. If that branch is not in the linked list, it will be inserted. An inserted branch is called a fill-in. Fill-ins tend to increase the non-zero off diagonal of a matrix. Optimal ordering will tend to make it at a minimum, although not necessarily the best minimum.

The snippet below is already a full blown factorizatioin with sparity technique. Because we are using only one linked list, there must be a code for B'=1, B"=2. Remember that in B", we delete the row and column for busses of type PV. Both B", B" deletes the row and column for Slack. We use type[] since the size of type[] is nb and the square matrix size of B' is also nb although stored linearly.

 
 171: //Solution of simultaneous equations Ax=b
 172: //by symmetric LU Factorization using lifo             
 173: void lufact(int code,float A[LMAX2], float Ad[BMAX])
 174: {int kk,i,j,ij,ki,kj,I,J,EndBus[20],Adr[20],counter;
 175: //All matrices had been reset (=zero)
 176:  for (kk=1;kk< nb;kk++) 
 177:   if (type[kk]!=2)                             //exclude Slack
 178:     {if (code< 2 ||!type[kk])                   //exclude PV
 179:        {counter=Get_RHSnodes(kk,EndBus,Adr);   //number of RHS elements
 180:           if (counter)    //perform finite change on upper triangle only
 181:             for (i=1;i<= counter;i++)
 182:               {I=EndBus[i];ki=Adr[i];  
 183:                Ad[I]-=A[ki]*A[ki]/Ad[kk];       // Diagonal part
 184:                if (i<counter)
 185:                  for (j=i+1;j<= counter;j++)    // Off-diagonal part
 186:                    {J=EndBus[j];kj=Adr[j];
 187:                     ij=BrnSrNsrt(I,J);          //branch search-insert J
 188:                     A[ij]-=A[kj]*A[ki]/Ad[kk];
 189:                    } /*for j*/
 190:               }  /*for i*/ 
 191:        }//if not PV  
 192:     }//if not Slack
 193:  }
 194: 
 195: 
 196:     
 197: void Solve(int code,float A[LMAX2],float Ad[BMAX]) 
 198: {int i,ki,kj,more,j,k;
 199: //forward course
 200:   for (k=1;k< nb; k++) 
 201:    if (type[k]!=2)                //exclude Slack
 202:      {if (code< 2 ||!type[k])      //exclude PV
 203:         {more=start[k];  
 204:          while (more)
 205:            {i=mbus[more];                  //for (i=k+1; i<=nb; i++) 
 206:             if (i>k)                          //check if rhs node
 207:               {ki=(more+1)/2;              //get the address         
 208:                x[i]=x[i]-A[ki]*x[k]/Ad[k];    //x[i]=x[i]-A[k][i]*x[k]/A[k][k];  
 209:               }        
 210:             more=next[more]; 
 211:            }  //while  
 212:         }   //if not PV
 213:      }  //if not Slack
 214: //backward course //the same as unsymmetric             
 215:   x[nb]/=Ad[nb];
 216:   for (k=nb-1;k>=1; k--)   
 217:     if (type[k]!=2)                 //exclude Slack
 218:       {if (code<2 ||!type[k])         //exclude PV
 219:          {more=start[k];                   //for (j=k+1;j<=nb;j++)  
 220:           while (more)
 221:            {j=mbus[more];  
 222:             if (j>k)                       //only rhs nodes 
 223:               {kj=(more+1)/2;   
 224:                if (type[j]!=2)                 //exclude Slack
 225:                  {if (code<2 ||!type[j])       //exclude PV
 226:                    x[k]=x[k]-A[kj]*x[j];      //x[k]=x[k]-A[k][j]*x[j]; 
 227:                  }
 228:               }//j is rhs of k      
 229:             more=next[more];       
 230:            }//while   
 231:           x[k]/=Ad[k];  
 232:          }//if not PV       
 233:       }//if not Slack                   
 234: }
 

Click this for a complete Fortran Listing.

i n n o v a t e   o r   s t a g n a t e  
Free Web Hosting