public static void Jacobian(List <int> BusNO, List <int> BusType, List <double> VolAng, List <double> VolMag, List <double> Pi, List <double> Qi, double[,] Gbus, double[,] Bbus, out double[,] Jacobian, out List <double> dPQ) { // return the Jacobian matrix from Gbus and Bbus matrix. // find the bus type index. List <int> PQ, PV, PVPQ, slack; FindBusType(BusNO, BusType, out PQ, out PV, out PVPQ, out slack); // initialize. Jacobian = new double[PVPQ.Count + PQ.Count, PVPQ.Count + PQ.Count]; List <double> dP = new List <double>(); List <double> dQ = new List <double>(); dPQ = new List <double>(); double[,] J11 = new double[PVPQ.Count, PVPQ.Count]; double[,] J12 = new double[PVPQ.Count, PQ.Count]; double[,] J21 = new double[PQ.Count, PVPQ.Count]; double[,] J22 = new double[PQ.Count, PQ.Count]; // deltaP & Jacobian J11 i/i foreach (int i in PVPQ) { double sigema = 0.0, sigemaJ = 0.0; for (int j = 0; j < BusNO.Count; ++j) { sigema = sigema + VolMag[j] * (Gbus[i, j] * (Math.Cos(VolAng[i] - VolAng[j])) + Bbus[i, j] * (Math.Sin(VolAng[i] - VolAng[j]))); sigemaJ = sigemaJ + VolMag[j] * (Gbus[i, j] * ((-1) * Math.Sin(VolAng[i] - VolAng[j])) + Bbus[i, j] * (Math.Cos(VolAng[i] - VolAng[j]))); } dP.Add(Pi[i] - VolMag[i] * sigema); dPQ.Add(Pi[i] - VolMag[i] * sigema); J11[i - 1, i - 1] = VolMag[i] * sigemaJ - VolMag[i] * VolMag[i] * Bbus[i, i]; Jacobian[i - 1, i - 1] = J11[i - 1, i - 1]; } // Jacobian J11 i/j foreach (int i in PVPQ) { foreach (int j in PVPQ) { if (i != j) { int indexi = PVPQ.FindIndex(x => x == i); int indexj = PVPQ.FindIndex(x => x == j); J11[indexi, indexj] = VolMag[i] * VolMag[j] * (Gbus[i, j] * (Math.Sin(VolAng[i] - VolAng[j])) - Bbus[i, j] * (Math.Cos(VolAng[i] - VolAng[j]))); Jacobian[indexi, indexj] = J11[indexi, indexj]; } } } // Jacobian J12 i/i & J21 i/i foreach (int i in PQ) { double sigemaJ = 0.0; for (int j = 0; j < BusNO.Count; ++j) { sigemaJ = sigemaJ + VolMag[j] * (Gbus[i, j] * (Math.Cos(VolAng[i] - VolAng[j])) + Bbus[i, j] * (Math.Sin(VolAng[i] - VolAng[j]))); } int indexi = PVPQ.FindIndex(x => x == i); int indexj = PQ.FindIndex(x => x == i); J12[indexi, indexj] = sigemaJ + VolMag[i] * Gbus[i, i]; J21[indexj, indexi] = VolMag[i] * sigemaJ - (VolMag[i] * VolMag[i]) * Gbus[i, i]; Jacobian[indexi, indexj + PVPQ.Count] = J12[indexi, indexj]; Jacobian[indexj + PVPQ.Count, indexi] = J21[indexj, indexi]; } // Jacobian J12 i/j foreach (int i in PVPQ) { foreach (int j in PQ) { if (i != j) { int indexi = PVPQ.FindIndex(x => x == i); int indexj = PQ.FindIndex(x => x == j); J12[indexi, indexj] = VolMag[i] * (Gbus[i, j] * (Math.Cos(VolAng[i] - VolAng[j])) + Bbus[i, j] * (Math.Sin(VolAng[i] - VolAng[j]))); Jacobian[indexi, indexj + PVPQ.Count] = J12[indexi, indexj]; } } } // Jacobian J21 i/j foreach (int i in PQ) { foreach (int j in PVPQ) { if (i != j) { int indexi = PQ.FindIndex(x => x == i); int indexj = PVPQ.FindIndex(x => x == j); J21[indexi, indexj] = VolMag[i] * VolMag[j] * (-Gbus[i, j] * (Math.Cos(VolAng[i] - VolAng[j])) - Bbus[i, j] * (Math.Sin(VolAng[i] - VolAng[j]))); Jacobian[indexi + PVPQ.Count, indexj] = J21[indexi, indexj]; } } } // deltaQ & Jacobian J22 i/i foreach (int i in PQ) { double sigema = 0.0; for (int j = 0; j < BusNO.Count; ++j) { sigema = sigema + VolMag[j] * (Gbus[i, j] * (Math.Sin(VolAng[i] - VolAng[j])) - Bbus[i, j] * (Math.Cos(VolAng[i] - VolAng[j]))); } dQ.Add(Qi[i] - VolMag[i] * sigema); dPQ.Add(Qi[i] - VolMag[i] * sigema); int indexi = PQ.FindIndex(x => x == i); J22[indexi, indexi] = sigema - VolMag[i] * Bbus[i, i]; Jacobian[indexi + PVPQ.Count, indexi + PVPQ.Count] = J22[indexi, indexi]; } // Jacobian J22 i/j foreach (int i in PQ) { foreach (int j in PQ) { if (i != j) { int indexi = PQ.FindIndex(x => x == i); int indexj = PQ.FindIndex(x => x == j); J22[indexi, indexj] = VolMag[i] * (Gbus[i, j] * (Math.Sin(VolAng[i] - VolAng[j])) - Bbus[i, j] * (Math.Cos(VolAng[i] - VolAng[j]))); Jacobian[indexi + PVPQ.Count, indexj + PVPQ.Count] = J22[indexi, indexj]; } } } }
private void NewtonRaphson_Click(object sender, EventArgs e) { // start Newton-Raphson power flow calculation when user clicks the button. try { #region Useful infomation from bus and branch List <int> BusNO = bus[0].ToList().Select(int.Parse).ToList(); List <int> BusType = bus[6].ToList().Select(int.Parse).ToList(); List <double> VolMag = bus[7].ToList().Select(double.Parse).ToList(); List <double> VolAng = bus[8].ToList().Select(double.Parse).ToList(); List <double> LoadMW = bus[9].ToList().Select(double.Parse).ToList(); List <double> LoadMVAR = bus[10].ToList().Select(double.Parse).ToList(); List <double> GenMW = bus[11].ToList().Select(double.Parse).ToList(); List <double> GenMVAR = bus[12].ToList().Select(double.Parse).ToList(); List <double> busG = bus[17].ToList().Select(double.Parse).ToList(); List <double> busB = bus[18].ToList().Select(double.Parse).ToList(); List <int> fromBus = branch[0].ToList().Select(int.Parse).ToList(); List <int> toBus = branch[1].ToList().Select(int.Parse).ToList(); List <double> LineR = branch[6].ToList().Select(double.Parse).ToList(); List <double> LineX = branch[7].ToList().Select(double.Parse).ToList(); List <double> LineB = branch[8].ToList().Select(double.Parse).ToList(); #endregion // generate the Gbus and Bbus matrix. double[,] Gbus, Bbus; CommonFunctions.Ybus(bus, branch, out Gbus, out Bbus); // find the PQ, PV, PVPQ, slack bus index. List <int> PQ, PV, PVPQ, slack; CommonFunctions.FindBusType(BusNO, BusType, out PQ, out PV, out PVPQ, out slack); // initialize Pi, Qi, VolMag, VolAng according to bus type. List <double> Pi = new List <double>(); List <double> Qi = new List <double>(); for (int i = 0; i < BusNO.Count; ++i) { if (BusType[i] == 3) { // slack bus, set GenMW = 0, GenMVAR = 0; GenMW[i] = 0; GenMVAR[i] = 0; } if (BusType[i] == 2) { // PV bus, set GenMVAR = 0, VolAng = 0; GenMVAR[i] = 0; VolAng[i] = 0; } if (BusType[i] == 1 || BusType[i] == 0) { // PQ bus, set VolMag = 1, VolAng = 0; VolMag[i] = 1; VolAng[i] = 0; } // Pinjection = Pgen - Pload, must convert to p.u.! Pi.Add((GenMW[i] - LoadMW[i]) / 100); Qi.Add((GenMVAR[i] - LoadMVAR[i]) / 100); } // initialize the iteration count and error. int iter = 0; double error = 1.0; // Newton Raphson iteration. while (error > stoppingError) { // generate Jacobian matrix and mismatch deltaP and deltaQ. double[,] Jacobian; List <double> dPQ; CommonFunctions.Jacobian(BusNO, BusType, VolAng, VolMag, Pi, Qi, Gbus, Bbus, out Jacobian, out dPQ); // compute [dVol] by inverse of Jacobian multiply [dPQ]. List <double> dVol; CommonFunctions.LUFact(Jacobian, dPQ, out dVol); // update the VolAng and VolMag, // start another iteration until stopping error is satisfied. foreach (int i in PVPQ) { int index = PVPQ.FindIndex(x => x == i); VolAng[i] = VolAng[i] + dVol[index]; } foreach (int i in PQ) { int index = PQ.FindIndex(x => x == i) + PVPQ.Count; VolMag[i] = VolMag[i] + dVol[index]; } iter++; // update the error. CommonFunctions.FindMaxAbs(dPQ, out error); } // display the power flow results. UpdateResults(VolAng, VolMag, iter); // results save to a txt file. SaveResults(VolAng, VolMag); } catch (Exception ex) { MessageBox.Show("Please check data format! " + ex.Message); } }