Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_compile_definitions(_USE_MATH_DEFINES)

if(MSVC)
add_compile_definitions(NOMINMAX WIN32_LEAN_AND_MEAN)
endif()

file(GLOB CMAKE_FILES "${CMAKE_SOURCE_DIR}/cmake/*.cmake")

foreach(CMAKE_FILE ${CMAKE_FILES})
Expand Down
6 changes: 3 additions & 3 deletions Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@ PROJECT_BRIEF =
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
# the logo to the output directory.

# PROJECT_LOGO = docs/deltaFlow.png
PROJECT_LOGO = docs/assets/deltaFlow.png

# With the PROJECT_ICON tag one can specify an icon that is included in the tabs
# when the HTML document is shown. Doxygen will copy the logo to the output
# directory.

PROJECT_ICON = docs/deltaFlow.svg
PROJECT_ICON = docs//assets/deltaFlow.svg

# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
Expand Down Expand Up @@ -1101,7 +1101,7 @@ EXAMPLE_RECURSIVE = NO
# that contain images that are to be included in the documentation (see the
# \image command).

IMAGE_PATH =
IMAGE_PATH = docs/assets

# The INPUT_FILTER tag can be used to specify a program that Doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
Expand Down
89 changes: 53 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,70 +1,87 @@
# deltaFlow

![deltaFlow](./docs/deltaFlow.png)
![deltaFlow](./docs/assets/deltaFlow.png)

**deltaFlow** is a command-line tool that solves steady-state power flow problems using numerical methods like Gauss-Seidel and Newton-Raphson. It reads input from CSV files for bus and branch data.
**deltaFlow** is a command-line power flow analysis tool for electrical power systems.
It solves the steady-state power flow equations using the Gauss-Seidel and Newton-Raphson
iterative methods, with automatic reactive power limit (Q-limit) enforcement for
voltage-controlled (PV) buses.

deltaFlow reads standard industry input formats — IEEE Common Data Format (`.cdf`, `.txt`)
and PSS/E Raw Format (`.raw`) — and produces bus voltage/power summaries and line flow reports.

---

## Build Instructions
## Features

Requires: A C++17-compatible compiler and CMake.
- **Solvers:** Gauss-Seidel (with relaxation) and Newton-Raphson
- **Q-limit enforcement:** Automatic PV-to-PQ bus type switching when reactive limits are violated
- **Input formats:** IEEE Common Data Format and PSS/E Raw Format (v32/v33)
- **Validated:** Tested against IEEE 14, 30, 57, 118, and 300-bus standard test cases
- **Cross-platform:** Builds on Linux (GCC) and Windows (MSVC)

Build the project with:
---

```sh
./bin/build.pl -t # Run build and tests
```
## Dependencies

Other options:
| Library | Version | Purpose |
|---------|---------|---------|
| [Eigen](https://eigen.tuxfamily.org/) | 3.4.0 | Linear algebra |
| [fmt](https://fmt.dev/) | 10.2.1 | Formatting and logging |
| [Catch2](https://github.com/catchorg/Catch2) | 3.5.4 | Unit testing |

* `-b`, `--build`: Build only (no tests)
* `-d`, `--doc`: Generate documentation (requires Doxygen)
Dependencies are managed automatically via [Conan](https://conan.io/).

---

## Usage
## Build Instructions

**Requirements:** C++17 compiler, CMake (>= 3.25), Conan 2, Perl

```sh
./deltaFlow [OPTIONS] <method>
./bin/build.pl -b # Build only
./bin/build.pl -t # Build and run tests
./bin/build.pl -d # Generate documentation (requires Doxygen)
```

### Required:

* `-b`, `--bus <file>`: Bus data CSV
* `-l`, `--branch <file>`: Branch data CSV
* `<method>`: Power flow method (`gauss-seidel` or `newton-raphson`)

### Optional:

* `-t`, `--tolerance <value>`: Convergence tolerance (default: `1E-8`)
* `-m`, `--max-iterations <int>`: Max iterations (default: `1024`)
* `-r`, `--relaxation <value>`: Relaxation factor (Gauss-Seidel only, default: `1.0`)
* `-h`, `--help`: Show help
* `-v`, `--version`: Show version

---

## Examples
## Usage

```sh
./deltaFlow -b data/bus.csv -l data/line.csv gauss-seidel
./deltaFlow --bus data/bus.csv --line data/line.csv newton-raphson
```
deltaFlow [OPTIONS] <input-file> <solver>
```

---
### Required arguments

## Notes
| Argument | Description |
|----------|-------------|
| `<input-file>` | Path to input file (`.cdf`, `.txt`, or `.raw`) |
| `<solver>` | Solver method: `GAUSS` or `NEWTON` |

* Both bus and branch files are required.
* `--relaxation` is ignored with Newton-Raphson.
### Options

| Option | Description | Default |
|--------|-------------|---------|
| `-j, --job <name>` | Job name (used for output labeling) | Input filename stem |
| `-t, --tolerance <value>` | Convergence tolerance | `1E-8` |
| `-m, --max-iterations <int>` | Maximum solver iterations | `1024` |
| `-r, --relaxation <value>` | Relaxation coefficient (Gauss-Seidel only) | `1.0` |
| `-h, --help` | Display help message | |
| `-v, --version` | Show version and exit | |

---

## Documentation

Generate with:
API documentation is generated with Doxygen:

```sh
./bin/build.pl -d
```

---

## License

deltaFlow is licensed under the [GNU General Public License v3.0](LICENSE).
File renamed without changes
Binary file removed docs/deltaFlow.png
Binary file not shown.
7 changes: 6 additions & 1 deletion src/core/model/Admittance.C
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
* <https://www.gnu.org/licenses/>.
*/

/**
* @file
* @brief Bus admittance matrix computation implementation.
*/

#include <complex>

#include "Admittance.H"
Expand Down Expand Up @@ -60,7 +65,7 @@ Eigen::MatrixXcd computeAdmittanceMatrix(const BusData& busData, const BranchDat
int busIndex = busData.ID(n) - 1; // Convert to 0-based

if (busIndex < 0 || busIndex >= Ybus.rows()) {
ERROR("Warning: Bus ID {} out of bounds in Ybus", busIndex + 1);
LOG_ERROR("Warning: Bus ID {} out of bounds in Ybus", busIndex + 1);
continue;
}

Expand Down
4 changes: 2 additions & 2 deletions src/core/model/Admittance.H
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@

#include <Eigen/Dense>

class BranchData;
class BusData;
struct BranchData;
struct BusData;

/**
* @brief Computes the complex bus admittance matrix ($$ Y_{bus} $$).
Expand Down
25 changes: 15 additions & 10 deletions src/core/solvers/GaussSeidel.C
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,19 @@
* <https://www.gnu.org/licenses/>.
*/

/**
* @file
* @brief Gauss-Seidel power flow solver implementation.
*/

#include <cmath>
#include <complex>
#include <iostream>
#include <limits>

#include "GaussSeidel.H"
#include "Logger.H"
#include "ProgressBar.H"
#include "Progress.H"

bool GaussSeidel(
const Eigen::MatrixXcd& Y,
Expand All @@ -52,22 +57,22 @@ bool GaussSeidel(
double error = std::numeric_limits<double>::infinity();

if (omega <= 0.0 || omega >= 2.0) {
WARN("Invalid input: Relaxation coefficient must be between 0 and 2.");
DEBUG("Setting Relaxation coefficient to 1.");
LOG_WARN("Invalid input: Relaxation coefficient must be between 0 and 2.");
LOG_DEBUG("Setting Relaxation coefficient to 1.");
omega = 1.0;
}

if (omega < 1.0) {
CRITICAL("Under-relaxation enabled (omega < 1), this will slow down convergence.");
LOG_CRITICAL("Under-relaxation enabled (omega < 1), this will slow down convergence.");
}
else if (omega == 1.0) {
DEBUG("Standard Gauss-Seidel enabled (omega = 1).");
LOG_DEBUG("Standard Gauss-Seidel enabled (omega = 1).");
}
else if (omega > 1.0) {
DEBUG("Over-relaxation enabled (omega > 1), this will accelerate convergence.");
LOG_DEBUG("Over-relaxation enabled (omega > 1), this will accelerate convergence.");
}

DEBUG("Relaxation Coefficient :: {}", omega);
LOG_DEBUG("Relaxation Coefficient :: {}", omega);

while (error >= tolerance && iteration < maxIter) {
Eigen::VectorXcd dV = Eigen::VectorXcd::Zero(N);
Expand Down Expand Up @@ -105,8 +110,8 @@ bool GaussSeidel(

if (iteration >= maxIter) {
printConvergenceStatus("Gauss-Seidel", false, iteration, maxIter, error, tolerance);
WARN("Gauss-Seidel did not converge within max iterations ({}).", maxIter);
DEBUG("Final error norm was {:.6e}, tolerance is {:.6e}.", error, tolerance);
LOG_WARN("Gauss-Seidel did not converge within max iterations ({}).", maxIter);
LOG_DEBUG("Final error norm was {:.6e}, tolerance is {:.6e}.", error, tolerance);
return false;
}

Expand All @@ -117,7 +122,7 @@ bool GaussSeidel(
}

printConvergenceStatus("Gauss-Seidel", true, iteration, maxIter, error, tolerance);
DEBUG("Gauss-Seidel converged in {} iterations with error norm {:.6e}.", iteration, error);
LOG_DEBUG("Gauss-Seidel converged in {} iterations with error norm {:.6e}.", iteration, error);

return true;
}
1 change: 1 addition & 0 deletions src/core/solvers/GaussSeidel.H
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
* @param maxIter Maximum number of iterations (default: 1024).
* @param tolerance Convergence tolerance for bus voltage updates (default: $$ 1 \times 10^{-8} $$).
* @param omega Relaxation parameter for the Successive Over-Relaxation (SOR) method (default: 1.0; SOR not applied).
* @param iterHistory Optional pointer to store iteration number and error at each step.
* @return true if the algorithm converged within the specified number of iterations, false otherwise.
*/
bool GaussSeidel(
Expand Down
5 changes: 5 additions & 0 deletions src/core/solvers/Jacobian.C
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
* <https://www.gnu.org/licenses/>.
*/

/**
* @file
* @brief Jacobian matrix computation implementation for Newton-Raphson solver.
*/

#include <cmath>

#include "Jacobian.H"
Expand Down
15 changes: 10 additions & 5 deletions src/core/solvers/NewtonRaphson.C
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
* <https://www.gnu.org/licenses/>.
*/

/**
* @file
* @brief Newton-Raphson power flow solver implementation.
*/

#include <cmath>
#include <limits>
#include <iostream>
Expand All @@ -27,7 +32,7 @@
#include "NewtonRaphson.H"
#include "Jacobian.H"
#include "PowerMismatch.H"
#include "ProgressBar.H"
#include "Progress.H"
#include "Data.H"
#include "Utils.H"

Expand Down Expand Up @@ -60,8 +65,8 @@ bool NewtonRaphson(
while (error >= tolerance) {
if (iter >= maxIter) {
printConvergenceStatus("Newton-Raphson", false, iter, maxIter, error, tolerance);
WARN("Newton-Raphson did not converge within {} iterations.", maxIter);
DEBUG("Final max mismatch was {:.6e}, tolerance is {:.6e}.", error, tolerance);
LOG_WARN("Newton-Raphson did not converge within {} iterations.", maxIter);
LOG_DEBUG("Final max mismatch was {:.6e}, tolerance is {:.6e}.", error, tolerance);
return false;
}
iter++;
Expand All @@ -88,10 +93,10 @@ bool NewtonRaphson(
error = mismatch.cwiseAbs().maxCoeff();
if (iterHistory) iterHistory->emplace_back(iter, error);
printIterationProgress("Newton-Raphson", iter, maxIter, error, tolerance);
DEBUG("NR iteration {}: max mismatch = {:.16e}", iter, error);
LOG_DEBUG("NR iteration {}: max mismatch = {:.16e}", iter, error);
}

printConvergenceStatus("Newton-Raphson", true, iter, maxIter, error, tolerance);
DEBUG("Newton-Raphson converged in {} iterations with max mismatch {:.6e}", iter, error);
LOG_DEBUG("Newton-Raphson converged in {} iterations with max mismatch {:.6e}", iter, error);
return true;
}
5 changes: 3 additions & 2 deletions src/core/solvers/NewtonRaphson.H
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@
#include <utility>
#include <vector>

class BranchData;
class BusData;
struct BranchData;
struct BusData;

/**
* @brief Solves the power flow equations using the Newton-Raphson iterative method.
Expand All @@ -101,6 +101,7 @@ class BusData;
* @param pq_bus_id 0-based indices of PQ buses.
* @param maxIter Maximum number of iterations (default: 1024).
* @param tolerance Convergence tolerance for power mismatches (default: $$ 1 \times 10^{-8} $$).
* @param iterHistory Optional pointer to store iteration number and error at each step.
* @return true if converged, false otherwise.
*/
bool NewtonRaphson(
Expand Down
5 changes: 5 additions & 0 deletions src/core/solvers/PowerMismatch.C
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
* <https://www.gnu.org/licenses/>.
*/

/**
* @file
* @brief Active and reactive power mismatch computation implementation.
*/

#include <cmath>

#include "PowerMismatch.H"
Expand Down
11 changes: 8 additions & 3 deletions src/core/solvers/Qlim.C
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
* <https://www.gnu.org/licenses/>.
*/

/**
* @file
* @brief Reactive power limit enforcement implementation.
*/

#include <cmath>
#include <limits>
#include <vector>
Expand Down Expand Up @@ -65,17 +70,17 @@ bool checkQlimits(
type_bus(idx) = 3; // PV to PQ
busData.Qg(idx) = Qmax(idx); // Fix Q at limit for next solver run
qlim_hit = true;
DEBUG("Q-limit (max) hit at bus {} : Qg = {:.4f} > Qmax = {:.4f}", idx + 1, Qg(idx), Qmax(idx));
LOG_DEBUG("Q-limit (max) hit at bus {} : Qg = {:.4f} > Qmax = {:.4f}", idx + 1, Qg(idx), Qmax(idx));
} else if (Qg(idx) < Qmin(idx)) {
type_bus(idx) = 3; // PV to PQ
busData.Qg(idx) = Qmin(idx); // Fix Q at limit for next solver run
qlim_hit = true;
DEBUG("Q-limit (min) hit at bus {} : Qg = {:.4f} < Qmin = {:.4f}", idx + 1, Qg(idx), Qmin(idx));
LOG_DEBUG("Q-limit (min) hit at bus {} : Qg = {:.4f} < Qmin = {:.4f}", idx + 1, Qg(idx), Qmin(idx));
}
}

if (!qlim_hit) {
DEBUG("Power flow converged without hitting Q-limits.");
LOG_DEBUG("Power flow converged without hitting Q-limits.");
}

return qlim_hit;
Expand Down
2 changes: 1 addition & 1 deletion src/core/solvers/Qlim.H
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

#include <Eigen/Dense>

class BusData;
struct BusData;

/**
* @brief Checks reactive power limits on PV buses after solver convergence.
Expand Down
Loading
Loading