deltaFlow
NewtonRaphson.H File Reference

Declaration of the Newton-Raphson load flow solver for power system analysis. More...

#include <Eigen/Dense>
#include <utility>
#include <vector>
Include dependency graph for NewtonRaphson.H:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

bool NewtonRaphson (const Eigen::MatrixXd &G, const Eigen::MatrixXd &B, const Eigen::VectorXd &Ps, const Eigen::VectorXd &Qs, Eigen::VectorXd &V, Eigen::VectorXd &delta, int n_bus, int n_pq, const std::vector< int > &pq_bus_id, int maxIter=1024, double tolerance=1E-8, std::vector< std::pair< int, double > > *iterHistory=nullptr)
 Solves the power flow equations using the Newton-Raphson iterative method.
 

Detailed Description

Declaration of the Newton-Raphson load flow solver for power system analysis.

The Newton-Raphson method is a robust and widely-used iterative algorithm for solving the nonlinear power flow equations in electrical power systems.

It uses the bus admittance matrix $$Y_{bus}$$ and iteratively updates the bus voltages $$V$$ by solving the set of nonlinear equations:

$$\Delta x^{(k)} = -[J(x^{(k)})]^{-1} F(x^{(k)})$$

where:

  • $$x$$ is the state vector (bus voltage magnitudes and angles),
  • $$F(x)$$ is the vector of power mismatch equations,
  • $$J(x)$$ is the Jacobian matrix of partial derivatives with respect to $$x$$,
  • $$\Delta x$$ is the update to the state vector at iteration $$k$$.

The power injection equations at each bus are:

Active power (P):

$$P_i = \sum_{j=1}^{n} |V_i||V_j|(G_{ij}\cos(\theta_{ij}) + B_{ij}\sin(\theta_{ij}))$$

Reactive power (Q):

$$Q_i = \sum_{j=1}^{n} |V_i||V_j|(G_{ij}\sin(\theta_{ij}) - B_{ij}\cos(\theta_{ij}))$$

where:

  • $$G_{ij} + jB_{ij}$$ is the element of the admittance matrix $$Y_{bus}$$,
  • $$\theta_{ij} = \delta_i - \delta_j$$ is the voltage angle difference between buses $$i$$ and $$j$$,
  • $$V_i, V_j$$ are the voltage magnitudes at buses $$i$$ and $$j$$.

The Jacobian matrix has the general block structure:

$$J = \begin{bmatrix} \frac{\partial P}{\partial \delta} & \frac{\partial P}{\partial |V|} \\ \frac{\partial Q}{\partial \delta} & \frac{\partial Q}{\partial |V|} \end{bmatrix}$$

with submatrices defined as follows:

$$J_1(kn) = \frac{\partial P_k}{\partial \delta_n} = \begin{cases} -V_k \sum_{n=1}^N V_n |Y_{kn}| \sin(\delta_k - \delta_n - \theta_{kn}) & \text{if } k = n \ V_k V_n |Y_{kn}| \sin(\delta_k - \delta_n - \theta_{kn}) & \text{if } k \ne n \end{cases}$$

$$J_2(kn) = \frac{\partial P_k}{\partial |V_n|} = \begin{cases} V_k |Y_{kk}| \cos(\theta_{kk}) + \sum_{n \ne k} V_n |Y_{kn}| \cos(\delta_k - \delta_n - \theta_{kn}) & \text{if } k = n \ V_k |Y_{kn}| \cos(\delta_k - \delta_n - \theta_{kn}) & \text{if } k \ne n \end{cases}$$

$$J_3(kn) = \frac{\partial Q_k}{\partial \delta_n} = \begin{cases} V_k \sum_{n=1}^N V_n |Y_{kn}| \cos(\delta_k - \delta_n - \theta_{kn}) & \text{if } k = n \ -V_k V_n |Y_{kn}| \cos(\delta_k - \delta_n - \theta_{kn}) & \text{if } k \ne n \end{cases}$$

$$J_4(kn) = \frac{\partial Q_k}{\partial |V_n|} = \begin{cases} -V_k |Y_{kk}| \sin(\theta_{kk}) + \sum_{n \ne k} V_n |Y_{kn}| \sin(\delta_k - \delta_n - \theta_{kn}) & \text{if } k = n \ V_k |Y_{kn}| \sin(\delta_k - \delta_n - \theta_{kn}) & \text{if } k \ne n \end{cases}$$

The process continues until all mismatches are within a specified tolerance or the maximum number of iterations is reached.

Definition in file NewtonRaphson.H.

Function Documentation

◆ NewtonRaphson()

bool NewtonRaphson ( const Eigen::MatrixXd &  G,
const Eigen::MatrixXd &  B,
const Eigen::VectorXd &  Ps,
const Eigen::VectorXd &  Qs,
Eigen::VectorXd &  V,
Eigen::VectorXd &  delta,
int  n_bus,
int  n_pq,
const std::vector< int > &  pq_bus_id,
int  maxIter = 1024,
double  tolerance = 1E-8,
std::vector< std::pair< int, double > > *  iterHistory = nullptr 
)

Solves the power flow equations using the Newton-Raphson iterative method.

This is a pure solver function that takes G, B matrices, scheduled power, initial voltage/angle guesses, and bus classification. It modifies V and delta in-place.

Parameters
GConductance matrix (real part of $$ Y_{bus} $$).
BSusceptance matrix (imaginary part of $$ Y_{bus} $$).
PsScheduled active power injections (Pg - Pl) [p.u.].
QsScheduled reactive power injections (Qg - Ql) [p.u.].
V(in/out) Voltage magnitudes [p.u.].
delta(in/out) Voltage angles [rad].
n_busTotal number of buses.
n_pqNumber of PQ buses.
pq_bus_id0-based indices of PQ buses.
maxIterMaximum number of iterations (default: 1024).
toleranceConvergence tolerance for power mismatches (default: $$ 1 \times 10^{-8} $$).
iterHistoryOptional pointer to store iteration number and error at each step.
Returns
true if converged, false otherwise.

Definition at line 39 of file NewtonRaphson.C.

52 {
53 // Compute initial mismatch
54 Eigen::VectorXd P(n_bus), Q(n_bus);
55 Eigen::VectorXd mismatch = powerMismatch(Ps, Qs, G, B, V, delta, n_bus, pq_bus_id, P, Q);
56
57 double error = mismatch.cwiseAbs().maxCoeff();
58 int iter = 0;
59
60 if (iterHistory) {
61 iterHistory->clear();
62 iterHistory->emplace_back(0, error);
63 }
64
65 while (error >= tolerance) {
66 if (iter >= maxIter) {
67 printConvergenceStatus("Newton-Raphson", false, iter, maxIter, error, tolerance);
68 LOG_WARN("Newton-Raphson did not converge within {} iterations.", maxIter);
69 LOG_DEBUG("Final max mismatch was {:.6e}, tolerance is {:.6e}.", error, tolerance);
70 return false;
71 }
72 iter++;
73
74 // Build Jacobian
75 Eigen::MatrixXd J = computeJacobian(V, delta, n_bus, n_pq, pq_bus_id, G, B, P, Q);
76
77 // Solve J * correction = mismatch
78 Eigen::VectorXd correction = J.colPivHouseholderQr().solve(mismatch);
79
80 // Update delta for non-slack buses (indices 1..N-1)
81 for (int i = 1; i < n_bus; ++i) {
82 delta(i) += correction(i - 1);
83 }
84
85 // Update V for PQ buses only
86 for (int k = 0; k < n_pq; ++k) {
87 V(pq_bus_id[k]) += correction(n_bus - 1 + k);
88 }
89
90 // Recompute mismatch
91 mismatch = powerMismatch(Ps, Qs, G, B, V, delta, n_bus, pq_bus_id, P, Q);
92
93 error = mismatch.cwiseAbs().maxCoeff();
94 if (iterHistory) iterHistory->emplace_back(iter, error);
95 printIterationProgress("Newton-Raphson", iter, maxIter, error, tolerance);
96 LOG_DEBUG("NR iteration {}: max mismatch = {:.16e}", iter, error);
97 }
98
99 printConvergenceStatus("Newton-Raphson", true, iter, maxIter, error, tolerance);
100 LOG_DEBUG("Newton-Raphson converged in {} iterations with max mismatch {:.6e}", iter, error);
101 return true;
102}
Eigen::MatrixXd computeJacobian(const Eigen::VectorXd &V, const Eigen::VectorXd &delta, int n_bus, int n_pq, const std::vector< int > &pq_bus_id, const Eigen::MatrixXd &G, const Eigen::MatrixXd &B, const Eigen::VectorXd &P, const Eigen::VectorXd &Q)
Computes the Jacobian matrix for the Newton-Raphson power flow solver.
Definition Jacobian.C:30
#define LOG_WARN(msg,...)
Macro for logging a warning-level message.
Definition Logger.H:87
#define LOG_DEBUG(msg,...)
Macro for logging a debug-level message.
Definition Logger.H:85
Eigen::VectorXd powerMismatch(const Eigen::VectorXd &Ps, const Eigen::VectorXd &Qs, const Eigen::MatrixXd &G, const Eigen::MatrixXd &B, const Eigen::VectorXd &V, const Eigen::VectorXd &delta, int n_bus, const std::vector< int > &pq_bus_id, Eigen::VectorXd &P, Eigen::VectorXd &Q)
Computes the power mismatch vector for use in Newton-Raphson iterations.
void printIterationProgress(const std::string &solver, int iter, int maxIter, double error, double tol, int barWidth=50)
Print an iteration progress line for a solver.
Definition Progress.H:50
void printConvergenceStatus(const std::string &solver, bool converged, int iter, int maxIter, double error, double tol, int barWidth=50)
Print the final convergence status line.
Definition Progress.H:100

References computeJacobian(), LOG_DEBUG, LOG_WARN, powerMismatch(), printConvergenceStatus(), and printIterationProgress().

Here is the call graph for this function: