Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
197 commits
Select commit Hold shift + click to select a range
daa7e91
add the possibility to compute a contingency analysis even on grid sp…
BDonnot Jun 19, 2026
652b0b0
update CHANGELOG and docs + fix a segfault
BDonnot Jun 19, 2026
6b80116
add functions to properly set and compare a network between lightsim2…
BDonnot Jun 25, 2026
22bcdde
Merge branch 'refactoNR_2' into n1_full_compute
BDonnot Jun 25, 2026
bc832e4
add multithreaded security analysis
BDonnot Jun 25, 2026
2293913
support multiple version of pypowsybl in the parameters factory
BDonnot Jun 25, 2026
401e69b
fix thread configuration
BDonnot Jun 25, 2026
1990591
add possibility to 'bake' from an initial powerflow only the main con…
BDonnot Jun 25, 2026
f6a1814
add support for islanding grid in DC security analysis
BDonnot Jun 25, 2026
8aad093
add possibility to have slack and remote voltage control
BDonnot Jun 26, 2026
898614e
fix some issues to make lightsim2grid more realistic
BDonnot Jun 26, 2026
8fc9ed8
fix some issues to make lightsim2grid more realistic
BDonnot Jun 26, 2026
c915475
fix some tap changer cpp side
BDonnot Jun 26, 2026
62cf3bc
improve the contingency analysis - multi thread- handling
BDonnot Jun 26, 2026
fbe62a9
add features for easier extensions writing
BDonnot Jul 1, 2026
1564fca
improve script to init grid from pypowsybl
BDonnot Jul 1, 2026
96f976a
add a new serialization method, fix some HVDC import issues
BDonnot Jul 2, 2026
2b74bf6
fixing some issues with HVDC still
BDonnot Jul 2, 2026
94e3efc
still improving the baking script
BDonnot Jul 2, 2026
83887cd
fix another issue in the grid baking
BDonnot Jul 2, 2026
00d98c0
baking the 'pseudo off' generators -> remove them from PV in olf_bake
BDonnot Jul 2, 2026
72a598f
add handling of limit violation in contingency analysis, fix warnings…
BDonnot Jul 3, 2026
f141aca
fix some issues with the control of the algorithm in time series and …
BDonnot Jul 3, 2026
8acf1db
Add native from_matpower initializer for LSGrid
claude Jul 5, 2026
a369e31
Address PR review comments on the matpower loader
claude Jul 5, 2026
6289252
Merge pull request #141 from Grid2op/claude/lightsim2grid-matpower-pr…
BDonnot Jul 5, 2026
c8b5fee
Merge pull request #141 from Grid2op/claude/lightsim2grid-matpower-pr…
BDonnot Jul 5, 2026
2cc88c7
Add init_from_pf_delta loader for the PFΔ benchmark dataset
claude Jul 5, 2026
8a90a56
Add init_from_pf_delta loader for the PFΔ benchmark dataset
claude Jul 5, 2026
4239224
Adapt to matpower loader review changes; use pi trafo model for fixture
claude Jul 5, 2026
5de56a5
Adapt to matpower loader review changes; use pi trafo model for fixture
claude Jul 5, 2026
29b2766
Convert PowerModels dcline entries instead of rejecting them
claude Jul 5, 2026
21b72d4
Convert PowerModels dcline entries instead of rejecting them
claude Jul 5, 2026
98e85b2
Invert loader dependency: from_matpower now delegates to from_powermo…
claude Jul 6, 2026
9db8aa6
Invert loader dependency: from_matpower now delegates to from_powermo…
claude Jul 6, 2026
23e24f1
Merge pull request #142 from Grid2op/claude/pfdelta-lsgrid-loader-jvtivx
BDonnot Jul 6, 2026
97a3113
Merge pull request #142 from Grid2op/claude/pfdelta-lsgrid-loader-jvtivx
BDonnot Jul 6, 2026
36d2d2c
lots of improvements still
BDonnot Jul 6, 2026
40ef2f6
lots of improvements still
BDonnot Jul 6, 2026
2f201c5
add serializing of algorithm config
BDonnot Jul 6, 2026
80107b6
add serializing of algorithm config
BDonnot Jul 6, 2026
32eeef3
improve handling of real grid
BDonnot Jul 6, 2026
f5913d9
improve handling of real grid
BDonnot Jul 6, 2026
02ad707
forget changelog
BDonnot Jul 6, 2026
b4ece58
forget changelog
BDonnot Jul 6, 2026
6078e8e
fixing some other issues when reading real data
BDonnot Jul 7, 2026
ab1ab0e
fixing some other issues when reading real data
BDonnot Jul 7, 2026
cd2cdb8
fix some docstring
BDonnot Jul 7, 2026
74e70c0
fix some docstring
BDonnot Jul 7, 2026
29e1621
add some convenient accessors for internal NRLedger powerflow variables
BDonnot Jul 7, 2026
a674b2a
add some convenient accessors for internal NRLedger powerflow variables
BDonnot Jul 7, 2026
1919650
Merge branch 'n1_full_compute' of https://github.com/grid2op/lightsim…
BDonnot Jul 7, 2026
d43032c
Merge branch 'n1_full_compute' of https://github.com/grid2op/lightsim…
BDonnot Jul 7, 2026
0448c9e
fix voltage control for NR single slack
BDonnot Jul 7, 2026
f080fb8
fix voltage control for NR single slack
BDonnot Jul 7, 2026
107a483
fix an issue in batch solvers when line is half disconnected'
BDonnot Jul 8, 2026
8c6a724
fix an issue in batch solvers when line is half disconnected'
BDonnot Jul 8, 2026
bce5890
fix some other issues related to disconnected buses
BDonnot Jul 8, 2026
716c596
fix some other issues related to disconnected buses
BDonnot Jul 8, 2026
e8c9a61
improve the baking function to be closer to real grid
BDonnot Jul 10, 2026
9485747
improve the baking function to be closer to real grid
BDonnot Jul 10, 2026
752ca0e
fix some broken tests
BDonnot Jul 10, 2026
131aca7
fix some broken tests
BDonnot Jul 10, 2026
ca847c8
Fix out-of-bounds memory access from Python-exposed bindings
claude Jul 11, 2026
7be352c
Fix out-of-bounds memory access from Python-exposed bindings
claude Jul 11, 2026
18a60ea
Use make_unique for CKTSO/NICSLU index buffers; add CHANGELOG
claude Jul 11, 2026
4066f33
Use make_unique for CKTSO/NICSLU index buffers; add CHANGELOG
claude Jul 11, 2026
94b4ff9
Use unique_ptr with custom deleters for KLU solver handles
claude Jul 11, 2026
3b2eaee
Use unique_ptr with custom deleters for KLU solver handles
claude Jul 11, 2026
1beb45c
Add tests for out-of-bounds handling in Python-exposed methods
claude Jul 11, 2026
d3a2e15
Add tests for out-of-bounds handling in Python-exposed methods
claude Jul 11, 2026
51d8c2a
Merge pull request #143 from Grid2op/claude/cpp-memory-safety-binding…
BDonnot Jul 11, 2026
c1ba48b
Merge pull request #143 from Grid2op/claude/cpp-memory-safety-binding…
BDonnot Jul 11, 2026
6d83a38
Harden binary serialization against ill-formed input
claude Jul 11, 2026
1a35a27
Harden binary serialization against ill-formed input
claude Jul 11, 2026
9f4b77a
Address review: optional atomic save + serialized-enum value guard
claude Jul 12, 2026
d5127b4
Address review: optional atomic save + serialized-enum value guard
claude Jul 12, 2026
7a8b43c
Merge pull request #144 from Grid2op/claude/lsgrid-binary-robustness-…
BDonnot Jul 12, 2026
d130ea3
Merge pull request #144 from Grid2op/claude/lsgrid-binary-robustness-…
BDonnot Jul 12, 2026
4a0b4b8
Add memory-hardening CI: ASan+UBSan and debug-asserts jobs
claude Jul 11, 2026
dc25c4a
Add memory-hardening CI: ASan+UBSan and debug-asserts jobs
claude Jul 11, 2026
e0a49d2
Fix UB found by UBSan: Eigen::Map on &vec[0] of empty vectors
claude Jul 11, 2026
bf6a4c6
Fix UB found by UBSan: Eigen::Map on &vec[0] of empty vectors
claude Jul 11, 2026
6b1757b
Fix two reader bugs found by the corruption sweep under UBSan
claude Jul 11, 2026
87f1e56
Fix two reader bugs found by the corruption sweep under UBSan
claude Jul 11, 2026
f5e3338
Trigger sanitizer workflow on slashed branch names too
claude Jul 11, 2026
22e2ee3
Trigger sanitizer workflow on slashed branch names too
claude Jul 11, 2026
ea34568
Merge pull request #145 from Grid2op/claude/lsgrid-ci-sanitizers
BDonnot Jul 12, 2026
b0d8211
Merge pull request #145 from Grid2op/claude/lsgrid-ci-sanitizers
BDonnot Jul 12, 2026
f5eef8a
Validate powerflow inputs (ac_pf / dc_pf / every solver's compute_pf)
claude Jul 12, 2026
71f00ec
Validate powerflow inputs (ac_pf / dc_pf / every solver's compute_pf)
claude Jul 12, 2026
705caf6
Move powerflow input validation off the internal hot path
claude Jul 12, 2026
e6a0161
Move powerflow input validation off the internal hot path
claude Jul 12, 2026
538f2f1
Allow max_iter=0 in check_iter_tol (fixes test_jacobian.py CI failures)
claude Jul 12, 2026
b46eaf2
Allow max_iter=0 in check_iter_tol (fixes test_jacobian.py CI failures)
claude Jul 12, 2026
3c889a5
Merge pull request #146 from Grid2op/claude/lsgrid-pf-input-validation
BDonnot Jul 12, 2026
00bbaa3
Merge pull request #146 from Grid2op/claude/lsgrid-pf-input-validation
BDonnot Jul 12, 2026
4b49e37
fix reading from OLF with dist and remote voltage control at the same…
BDonnot Jul 13, 2026
df6a629
fix reading from OLF with dist and remote voltage control at the same…
BDonnot Jul 13, 2026
2c6c463
adding some missing tests data
BDonnot Jul 13, 2026
6121402
adding some missing tests data
BDonnot Jul 13, 2026
46b44d1
fix the 'remove outer loops' from OLF parameters
BDonnot Jul 13, 2026
a630497
fix the 'remove outer loops' from OLF parameters
BDonnot Jul 13, 2026
594a5fd
fix CI
BDonnot Jul 13, 2026
c4c1cff
fix CI
BDonnot Jul 13, 2026
41537bd
Add dedicated C++ unit tests (Catch2) for BinaryArchive, run under va…
claude Jul 13, 2026
018515f
Add C++ LSGrid API tests, standalone-library docs; fix uninitialized …
claude Jul 13, 2026
bd51cac
Address review comments on the C++ library docs
claude Jul 14, 2026
6423997
Address review comments: C++26 in the standard cascade, more LSGrid e…
claude Jul 14, 2026
48ff859
Address review comments: HVDC droop tests, unfeasible dual-controller…
claude Jul 14, 2026
f11ef3b
Merge pull request #147 from Grid2op/claude/cpp-unit-tests-catch2-lghkf5
BDonnot Jul 14, 2026
38356d7
Eliminate unnecessary Eigen copies on the powerflow hot path
claude Jul 14, 2026
b36547b
Eliminate unnecessary Eigen copies in the batch/time-series layer
claude Jul 14, 2026
f34e883
Fix dangling Eigen::Ref and NR extension slack_weights copies
claude Jul 14, 2026
81cc362
Fix dangling numpy arrays from get_ptdf/get_lodf/get_Bf* Python bindings
claude Jul 14, 2026
e86a5c7
DataConverter: take pandapower import vectors as Eigen::Ref
claude Jul 14, 2026
0ba9e92
[BREAKING] BaseAlgo::compute_pf/compute_pf_dc: Sbus/Pbus/slack_weight…
claude Jul 14, 2026
c191841
compute_one_powerflow: Sbus as Eigen::Ref, closing the batch-layer copy
claude Jul 14, 2026
f541a4d
Document the compute_amps_flows/compute_active_power_flows copy as a …
claude Jul 14, 2026
b897a81
init/init_full/init_osc_pq/init_bus: take vectors as Eigen::Ref
claude Jul 14, 2026
d1d925c
Add a report-only clang-tidy CI workflow (performance-*, readability-…
claude Jul 14, 2026
e908549
LSGrid::ac_pf/dc_pf/check_solution and the Vinit chain: Eigen::Ref
claude Jul 14, 2026
d69171c
Merge pull request #148 from Grid2op/claude/eigen-vector-copy-audit-x…
BDonnot Jul 14, 2026
fcb2b69
element_container: final on leaf classes, override on missed overrides
claude Jul 14, 2026
6b5a50b
powerflow_algorithm/batch_algorithm: final on leaves, override everyw…
claude Jul 14, 2026
960cc6d
const-correctness: getters, and Eigen::Ref<const ...> on read-only se…
claude Jul 14, 2026
4ca8292
Drop redundant virtual alongside override/final; enable modernize-use…
claude Jul 14, 2026
a7ef12d
LSGrid: [[nodiscard]] on public getters
claude Jul 14, 2026
8c7609c
Address review: Eigen::Ref<const T>& parameter style, drop redundant
claude Jul 15, 2026
b09ac44
get_status_droop_vect/get_status_droop_hvdc_vect: return Eigen::Ref<c…
claude Jul 15, 2026
fa604b6
Merge pull request #149 from Grid2op/claude/compiler-optimization-hin…
BDonnot Jul 15, 2026
0bdaaca
try to merge, we might abandon if too complicated
BDonnot Jul 15, 2026
36388e0
fix a bug introduced by fused branch in original grid
BDonnot Jul 15, 2026
ab72dfe
update CHANGELOG
BDonnot Jul 15, 2026
c943295
Merge pull request #150 from Grid2op/fused_branch_fix
BDonnot Jul 15, 2026
c20550a
improve handling of const Eigen::Ref
BDonnot Jul 15, 2026
756b287
Generalize RTE-specific grid references in from_pypowsybl and tests
BDonnot Jul 15, 2026
e7f1caf
Sharpen doc wording per PR #140 self-review
BDonnot Jul 15, 2026
2bee701
Misc PR #140 self-review items: debug ids + nb_thread benchmark
BDonnot Jul 15, 2026
470fb1f
_olf_params.py: robust version parsing + clarify remove_outer_loops i…
BDonnot Jul 15, 2026
cf80027
_from_pypowsybl.py: document the net-vs-net_pu split for dangling lin…
BDonnot Jul 15, 2026
3b87660
_result_network.py: align angle datum on the actual slack bus, not a …
BDonnot Jul 15, 2026
33ac4ba
ContingencyResult: add element_names alongside element_ids
BDonnot Jul 15, 2026
ae46417
LimitViolation.name: report the substation name for BUS violations
BDonnot Jul 15, 2026
7363e95
Document slack_ids[0]-must-be-reference invariant at point of use
BDonnot Jul 15, 2026
2040998
LightsimResultNetwork: document supported element types + per-method …
BDonnot Jul 15, 2026
9231e9c
Add shared exotic-elements test fixture; wire into HVDC/SVC round trips
BDonnot Jul 15, 2026
84e2020
Split _from_pypowsybl.py's 1083-line init() into per-element modules
BDonnot Jul 15, 2026
3d1c68f
attempt to merge n1_full_compute and fix CI
BDonnot Jul 15, 2026
8eeb893
add an example solver for distributing slack with outer loops
BDonnot Jul 16, 2026
5deda3d
add a way to generate a 'text fixture' : a case14 grid with some exot…
BDonnot Jul 16, 2026
631d5aa
fix a compilation issue
BDonnot Jul 16, 2026
0049fa3
synch with n1_full_compute
BDonnot Jul 16, 2026
6dea686
adding some other eigen ref in the codebase
BDonnot Jul 16, 2026
6a35f8f
improve the presence of Eigen::Ref everywhere
BDonnot Jul 16, 2026
ba136eb
fix a bug in benchmark_grid_size.py
BDonnot Jul 16, 2026
840a9f9
fix a bug when compiling with march=native flags
BDonnot Jul 16, 2026
e7c85b5
Add missing examples/cmake/MatchLightsim2gridBuildFlags.cmake
claude Jul 16, 2026
07b682a
Detect core/plugin and core/bindings Eigen ABI drift at load time
claude Jul 16, 2026
e5d4b01
Ls2gAbiTag: compare full Eigen version, document the runtime ABI check
claude Jul 17, 2026
a696a3e
before merge
BDonnot Jul 17, 2026
59a84f1
fix conflicts, ready to merge
BDonnot Jul 17, 2026
cd709b6
add possibility to extract detailed information about which generator…
BDonnot Jul 17, 2026
52608f2
fixing a KLU bug, present since beginning and rationalizing some inte…
BDonnot Jul 17, 2026
ebdb0f8
Add Levenberg-Marquardt Newton-Raphson as an out-of-tree example plugin
claude Jul 18, 2026
c30dbea
Merge pull request #152 from Grid2op/claude/levenberg-marquardt-nr-al…
BDonnot Jul 18, 2026
385d8a0
Merge pull request #151 from Grid2op/improve_const_ref
BDonnot Jul 21, 2026
a65beac
core: const-correctness and copy-elimination low-hanging fruit
claude Jul 21, 2026
0a33d4d
Make solver-plugin registration exception-safe at load time
claude Jul 22, 2026
10e56b6
examples: use available_algorithm_names() in the plugin smoke tests
claude Jul 23, 2026
a9d308d
Make the plugin-loading unittest actually run in CI (and fix it)
claude Jul 23, 2026
044fcea
Harden plugin error-buffer handling (PR review)
claude Jul 23, 2026
605a412
Merge pull request #154 from Grid2op/claude/lightsim2grid-plugin-regi…
BDonnot Jul 23, 2026
133e262
Add LSGrid::check_grid() whole-grid consistency validation
claude Jul 24, 2026
227b86c
Expose check_grid() to Python and call it from every grid loader
claude Jul 24, 2026
2e18a3e
Sanity-check solver output before consuming it (plugin seam)
claude Jul 24, 2026
2d653cf
Add C++ tests for check_grid() and the solver-output check
claude Jul 24, 2026
f9ea702
Add Python tests for check_grid() and run them under ASan/UBSan
claude Jul 24, 2026
6564101
Document the trust boundaries and check_grid() (docs + CHANGELOG)
claude Jul 24, 2026
39027ae
Run test_LSGrid_out_of_bounds under ASan/UBSan
claude Jul 24, 2026
e0daf36
Accept IndexError from check_grid on the binary corruption sweep
claude Jul 24, 2026
d324994
check_grid: drop input-finiteness checks (false positives on real grids)
claude Jul 24, 2026
0bafd6d
Address PR review: docs wording, subid tests, plugin-only output check
claude Jul 24, 2026
fec1f9e
Fix a SIGFPE reachable from the solver / newtonpf entry point
claude Jul 24, 2026
528719e
Serialize the algorithm by name so plugin grids round-trip
claude Jul 25, 2026
bf66552
Restrict solver names to a safe ASCII whitelist
claude Jul 25, 2026
0248125
Strengthen the plugin-solver copy test, and cover DC plugins
claude Jul 25, 2026
6377ae8
Merge pull request #153 from Grid2op/claude/const-correctness-optimiz…
BDonnot Jul 25, 2026
90b15c9
Merge pull request #155 from Grid2op/claude/n1-full-compute-security-…
BDonnot Jul 25, 2026
5b8bfd3
Fix memory-safety holes on the untrusted-input paths
claude Jul 26, 2026
acf2cf9
Enforce the per-substation nominal voltage invariant, and fix init_sub
claude Jul 26, 2026
cdda703
Express the per-substation voltage check as index arithmetic, TODO su…
claude Jul 26, 2026
abfd892
Address PR review: solver origin, vn_kv > 0, overflow, noexcept
claude Jul 27, 2026
df0516b
Merge pull request #156 from Grid2op/claude/lightsim2grid-security-au…
BDonnot Jul 28, 2026
cd7421f
Close five more memory-safety holes on the untrusted-input paths
claude Jul 28, 2026
a13ea8c
Validate the grid-wide per-unit scalars (sn_mva, init_vm_pu)
claude Jul 28, 2026
e80f615
Merge pull request #157 from Grid2op/claude/n1-full-compute-security-…
BDonnot Jul 28, 2026
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
51 changes: 51 additions & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Advisory only for now: see .github/workflows/clang-tidy.yml, which runs
# this report-only (it does not fail the job on findings). The performance-*
# family targets exactly the class of bug found in the Eigen unnecessary-copy
# audit (by-value Eigen/STL params, const-ref-to-value copies, ...);
# readability-const-return-type catches `const T foo()` return types that
# block move semantics on the caller side. misc-const-correctness covers the
# same ground as the manual const-correctness sweep (see the element_container
# / LSGrid commit it landed alongside): local variables that are never
# reassigned but aren't declared const. Runs in ~5 minutes over src/core as of
# this writing (own measurement, GCC 13 / clang-tidy 18) -- noticeably slower
# than the other checks here, but still well within the report-only job's
# budget.
#
# modernize-use-override: this codebase used to keep the `virtual` keyword on
# overrides alongside `override`/`final`, which this check flags as
# redundant on every single one of them -- ~80% pure noise against that
# style in an initial run. Rather than suppress the check, the redundant
# `virtual` was dropped codebase-wide (virtual is implied by `override`, and
# by `final` on an actual override) as part of the same final/override sweep,
# and every destructor overriding a base's virtual destructor was annotated
# `override` too, bringing this down to 2 residual warnings, both the same
# explainable case: `override final` used together for defensive
# compile-time checking (marks BOTH "this really overrides something" and
# "no further overrides") on a method in a class that ISN'T itself `final`
# (OneSideContainer::disconnect_if_not_in_main_component,
# TwoSidesContainer::nb_line_end) -- the check prefers `final` alone since it
# implies `override`, but the pair is intentional there and left as-is.
# (Classes that are themselves `final` don't repeat `final` on their
# methods -- redundant, since the class already can't be subclassed at all.)
#
# Known false-positive class: performance-unnecessary-value-param flags every
# `Eigen::Ref<...>` parameter passed by value (the idiom used throughout this
# codebase -- Ref is a thin pointer+size+stride wrapper, cheap to copy) as if
# it were an expensive-to-copy type. Confirmed while validating this config;
# left un-suppressed for now so the report-only phase shows the real noise
# level before anyone spends time tuning NOLINT / config exclusions for it.
Checks: >
-*,
performance-*,
readability-const-return-type,
misc-const-correctness,
modernize-use-override
WarningsAsErrors: ''
# Only report on our own headers (src/core, src/bindings) -- clang-tidy's
# default (empty) header filter would otherwise only ever look at the
# primary .cpp file and silently skip every inline-in-header function, which
# is most of this codebase's element_container / powerflow_algorithm classes.
# Vendored trees (eigen/, Catch2/, SuiteSparse/) live outside src/, so this
# regex excludes them without needing a separate exclude list.
HeaderFilterRegex: '.*/src/(core|bindings)/.*'
FormatStyle: none
83 changes: 83 additions & 0 deletions .github/workflows/clang-tidy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Static analysis: runs clang-tidy's performance-* / readability-const-return-type
# checks over src/core (the checks that would have caught the unnecessary Eigen
# copies found and fixed across several PRs). Report-only for now (see the
# "Summarize" step): findings are posted to the job summary and uploaded as an
# artifact, but do not fail the job. Once the baseline noise level is known,
# flip `continue-on-error` below (and drop the `|| true`) to make this a real
# gate -- e.g. restricted to the master / tag triggers already below, so a
# regression blocks a release without slowing down every topic-branch push.
#
# Triggers: on demand (Actions tab -> this workflow -> "Run workflow"), on
# every push to master, and on every version tag -- not on topic branches,
# since this is advisory / slower than the test suites that do run there.
name: clang-tidy

on:
workflow_dispatch:
push:
branches:
- master
tags:
- 'v*.*.*'

jobs:
clang-tidy:
name: performance / readability checks (src/core)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
# eigen (transitive include of the core headers), Catch2 (needed to
# configure src/tests, even though test files are not analyzed) and
# SuiteSparse (KLU headers)
submodules: true

- name: Install clang-tidy
run: |
sudo apt-get update
sudo apt-get install -y clang-tidy
clang-tidy --version

- name: Configure (generates compile_commands.json for src/core)
# standalone test project: no python / pybind11 involved, matching
# the C++ unit tests workflow. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON is
# the only addition -- clang-tidy needs it to see the real include
# paths / defines each translation unit was configured with.
run: cmake -S src/tests -B build_tidy -DCMAKE_EXPORT_COMPILE_COMMANDS=ON

- name: Run clang-tidy over src/core
# Not built: clang-tidy re-parses each translation unit itself via
# libTooling and does not need object files or a link step.
# `|| true`: see the report-only note above -- warnings must not fail
# this job yet, only errors in clang-tidy's own invocation would
# (caught separately by checking the report is non-empty below).
run: |
find src/core -name '*.cpp' | sort > /tmp/tidy_files.txt
wc -l < /tmp/tidy_files.txt
clang-tidy -p build_tidy $(cat /tmp/tidy_files.txt) > clang-tidy-report.txt 2>&1 || true

- name: Summarize
run: |
{
echo "## clang-tidy (performance-*, readability-const-return-type)"
echo
if [ ! -s clang-tidy-report.txt ]; then
echo "clang-tidy produced no output -- something upstream (configure/invocation) likely failed silently. Check the previous step's log."
else
n_warnings=$(grep -c 'warning:' clang-tidy-report.txt || true)
echo "**${n_warnings} finding(s)** across $(wc -l < /tmp/tidy_files.txt) files in \`src/core\`."
echo
echo "This workflow is report-only: it does not fail the job. See \`.github/workflows/clang-tidy.yml\` for how to promote it to a gate."
echo
echo '```'
head -c 60000 clang-tidy-report.txt
echo '```'
fi
} >> "$GITHUB_STEP_SUMMARY"

- name: Upload full report
uses: actions/upload-artifact@v4
with:
name: clang-tidy-report
path: clang-tidy-report.txt
retention-days: 30
50 changes: 50 additions & 0 deletions .github/workflows/cpp_unit_tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# C++ unit tests: builds the Catch2 suite under src/tests/ (the archive layer
# compiled straight into a small test binary -- no python, no pip, no solver
# deps) and runs it twice: once through ctest, once under valgrind. Being a
# plain binary makes valgrind practical here (--error-exitcode=1 turns any
# memory error into a CI failure), which it is not over the python test suite
# (10-50x slowdown plus CPython suppressions). Complements the Sanitizers
# workflow, which exercises the full python extension.

name: C++ unit tests

on:
push:
branches:
# '**' and not '*': a single '*' does not match '/' in GitHub Actions
# globs, so topic branches like 'foo/bar' would silently never run
- '**'
tags:
- 'v*.*.*'

jobs:
cpp_unit_tests:
name: Catch2 + valgrind
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
# eigen (transitive include of the core headers) and Catch2
submodules: true

- name: Install valgrind
run: |
sudo apt-get update
sudo apt-get install -y valgrind

- name: Configure
# standalone test project: no python, pybind11 or KLU involved.
# Debug keeps assert() live and gives valgrind full line info.
run: cmake -S src/tests -B build_tests -DCMAKE_BUILD_TYPE=Debug

- name: Build
run: cmake --build build_tests -j$(nproc)

- name: Run tests
run: ctest --test-dir build_tests --output-on-failure

- name: Run tests under valgrind
run: |
cd build_tests
valgrind --error-exitcode=1 --leak-check=full --track-origins=yes \
./lightsim2grid_unit_tests
64 changes: 64 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,20 @@ jobs:
- name: Run plugin test
run: python examples/external_algorithm/test_plugin.py

- name: Run plugin registration unittests (against the installed package)
shell: bash
# Run from the scratch dir so `import lightsim2grid` resolves to the
# pip-installed package, not the source tree (which has no built
# extension). LS2G_TEST_PLUGIN_DIR points the tests at the plugin built
# above; the finders pick the right per-platform file name themselves.
working-directory: _tmp_cmake_dir
env:
LS2G_TEST_PLUGIN_DIR: ${{ github.workspace }}/examples/external_algorithm/build
run: |
python -m unittest -v \
lightsim2grid.tests.test_solver_registry \
lightsim2grid.tests.test_plugin_registration

test_klu_strategies:
name: Test KLU detection strategies (Ubuntu)
runs-on: ubuntu-latest
Expand Down Expand Up @@ -802,6 +816,56 @@ jobs:
print('Strategy 1 OK: KLU available')
"

test_march_native:
# -march=native is a supported opt-in build flag (see benchmarks/env_compile_all.sh)
# that release wheels do not use, so plain CI builds never exercise it. It changes
# which SIMD ISA Eigen sees enabled (__AVX__, __AVX2__, ...) in each translation
# unit; lightsim2grid_core and lightsim2grid_cpp (the pybind11 bindings) are two
# separate shared libraries, so both must see the identical flag -- otherwise an
# Eigen object allocated in one and freed in the other computes a different
# alignment offset, corrupting the heap ("double free or corruption") the first
# time a function's return value crosses the module boundary (e.g. any pandapower
# -> LightSimBackend conversion, or a forecast-backend copy). Regression test for
# that class of bug: env creation reliably crashed within seconds before the fix.
name: Test -march=native build (Ubuntu)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true

- uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -r requirements_compile_ci.txt
python -m pip install grid2op pandapower lxml

- name: Build lightsim2grid with -march=native
run: __COMPILE_MARCHNATIVE=1 __O3_OPTIM=1 python -m pip install -v . --no-build-isolation

- name: Create + reset a LightSimBackend env (exercises the core<->bindings Eigen boundary)
run: |
mkdir -p _march_native_check
cd _march_native_check
python -c "
import warnings
from grid2op import make
from grid2op.Parameters import Parameters
from lightsim2grid import LightSimBackend

param = Parameters()
param.init_from_dict({'NO_OVERFLOW_DISCONNECTION': True, 'ENV_DC': True, 'FORECAST_DC': True})
with warnings.catch_warnings():
warnings.filterwarnings('ignore')
env = make('l2rpn_case14_sandbox', backend=LightSimBackend(), param=param, test=True)
env.reset()
print('OK: env created and reset under -march=native without crashing')
"

package:
name: Package wheels
runs-on: ubuntu-latest
Expand Down
106 changes: 106 additions & 0 deletions .github/workflows/sanitizers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Memory-hardening CI: builds the C++ core + bindings with instrumentation
# that the release wheels do not carry, and runs the test modules most likely
# to surface memory issues (out-of-bounds, use-after-free, UB, silenced
# assertions). Complements the functional suites on CircleCI, which run
# against plain optimized builds.

name: Sanitizers

on:
push:
branches:
# '**' and not '*': a single '*' does not match '/' in GitHub Actions
# globs, so topic branches like 'foo/bar' would silently never run
- '**'
tags:
- 'v*.*.*'

jobs:
asan_ubsan:
# AddressSanitizer + UndefinedBehaviorSanitizer over the untrusted-input
# path (binary serialization) and the heaviest C++ compute paths (solver
# control, time series, contingency analysis).
name: ASan + UBSan tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true

- uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Install python dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -r requirements_compile_ci.txt
python -m pip install grid2op scipy pandapower

- name: Build lightsim2grid with ASan + UBSan
# __SANITIZE=1 is picked up by src/core/CMakeLists.txt and
# src/bindings/python/CMakeLists.txt: -fsanitize=address,undefined
# on both lightsim2grid_core and lightsim2grid_cpp
run: __SANITIZE=1 python -m pip install -v . --no-build-isolation

- name: Run tests under ASan + UBSan
# The sanitized code lives in a python extension, so the ASan runtime
# must be the first thing loaded into the (uninstrumented) python
# process: hence LD_PRELOAD. libstdc++ must be preloaded along with
# it: python itself does not link it, and without it ASan's
# __cxa_throw interceptor cannot resolve the real function and every
# C++ exception aborts the process. Leak detection stays off:
# CPython's allocator keeps interned objects alive by design and
# would drown real reports in noise.
env:
ASAN_OPTIONS: detect_leaks=0
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
run: |
export LD_PRELOAD="$(gcc -print-file-name=libasan.so) $(gcc -print-file-name=libstdc++.so.6)"
cd lightsim2grid/tests
python -W ignore -m unittest -v \
test_binary_serialization \
test_solver_control \
test_TimeSerie \
test_time_series_dc \
test_SecurityAnlysis \
test_DCSecurityAnlysis \
test_SecurityAnlysis_cpp \
test_ContingencyAnalysis_limit_violations \
test_ContingencyAnalysis_split \
test_check_grid \
test_LSGrid_out_of_bounds

debug_asserts:
# Release wheels are compiled with NDEBUG, which silences every Eigen
# bounds assertion: logically-wrong-but-in-bounds indexing is invisible
# to ASan. This build re-enables them (plus the ABI-safe libstdc++
# container checks) and runs the solver-heavy modules.
name: Eigen/libstdc++ assertions tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true

- uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Install python dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -r requirements_compile_ci.txt
python -m pip install grid2op scipy pandapower

- name: Build lightsim2grid with assertions re-enabled
# __DEBUG_ASSERTS=1 -> -UNDEBUG -D_GLIBCXX_ASSERTIONS on both targets
run: __DEBUG_ASSERTS=1 python -m pip install -v . --no-build-isolation

- name: Run solver tests with assertions active
run: |
cd lightsim2grid/tests
python -W ignore -m unittest -v \
test_ACPF \
test_DCPF \
test_solver_control
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ __pycache__/
# Distribution / packaging
.Python
build/
build_tests/
develop-eggs/
dist/
downloads/
Expand Down
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@
path = eigen
url = https://gitlab.com/libeigen/eigen.git
ignore = dirty
[submodule "Catch2"]
path = Catch2
url = https://github.com/catchorg/Catch2.git
ignore = dirty
Loading
Loading