Skip to content

Documentation: update meshed observability test diagram and README#1330

Closed
Jerry-Jinfeng-Guo wants to merge 13 commits intomainfrom
feature/meshed-observability-pass-through-test-diagram
Closed

Documentation: update meshed observability test diagram and README#1330
Jerry-Jinfeng-Guo wants to merge 13 commits intomainfrom
feature/meshed-observability-pass-through-test-diagram

Conversation

@Jerry-Jinfeng-Guo
Copy link
Member

  • Test diagram
  • README

Copilot AI and others added 13 commits January 29, 2026 14:05
Co-authored-by: Jerry-Jinfeng-Guo <6221579+Jerry-Jinfeng-Guo@users.noreply.github.com>
Co-authored-by: Jerry-Jinfeng-Guo <6221579+Jerry-Jinfeng-Guo@users.noreply.github.com>
Co-authored-by: Jerry-Jinfeng-Guo <6221579+Jerry-Jinfeng-Guo@users.noreply.github.com>
Co-authored-by: Jerry-Jinfeng-Guo <6221579+Jerry-Jinfeng-Guo@users.noreply.github.com>
Co-authored-by: Jerry-Jinfeng-Guo <6221579+Jerry-Jinfeng-Guo@users.noreply.github.com>
Co-authored-by: Jerry-Jinfeng-Guo <6221579+Jerry-Jinfeng-Guo@users.noreply.github.com>
…lexity issues

Co-authored-by: Jerry-Jinfeng-Guo <6221579+Jerry-Jinfeng-Guo@users.noreply.github.com>
Co-authored-by: Jerry-Jinfeng-Guo <6221579+Jerry-Jinfeng-Guo@users.noreply.github.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
@Jerry-Jinfeng-Guo Jerry-Jinfeng-Guo self-assigned this Mar 13, 2026
@Jerry-Jinfeng-Guo Jerry-Jinfeng-Guo added the documentation Improvements or additions to documentation label Mar 13, 2026
@Jerry-Jinfeng-Guo
Copy link
Member Author

Git history had issues. Re-opening.

@Jerry-Jinfeng-Guo Jerry-Jinfeng-Guo deleted the feature/meshed-observability-pass-through-test-diagram branch March 13, 2026 10:46
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new topology validation for transformer tap regulator control_side (to mirror the C++ tap position optimizer behavior), adds unit tests for it, and updates a few README/docs files.

Changes:

  • Add validate_tap_regulator_control_side_topology() and integrate it into validate_transformer_tap_regulator().
  • Introduce InvalidTapRegulatorControlSideError and add a comprehensive unit test module for the new validation.
  • Update documentation for meshed-network observability test data and VS Code settings.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/power_grid_model/validation/_validation.py Adds graph-based reachability validation for tap regulator control-side topology and hooks it into existing validation.
src/power_grid_model/validation/errors.py Adds a new InvalidTapRegulatorControlSideError.
tests/unit/validation/test_tap_regulator_topology.py Adds new unit tests covering valid/invalid control-side topology scenarios.
tests/data/state_estimation/meshed-network-observability/README.md Updates the README text describing observability test scenarios.
.vscode/README.md Adds a short heading and clarifies the purpose of the directory.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +188 to +189
"""Test invalid control in cascaded transformers: T2 controlling from downstream towards upstream"""
# Setup: source at node 0, T1 from 0 to 1, T2 from 1 to 2, but T2 controls from to_side (wrong direction)
Comment on lines +13 to +26
1. **01-observable-with-branch-measurement**:
2. Observable system with branch measurement.
3. **02-unobservable-with-branch-measurement**:
4. Unobservable system with branch measurement.
5. **03-observable-without-branch-measurement**:
6. Observable system without branch measurement (using only nodal measurements).
7. **04-observable-without-branch-measurement**:
8. Another scenario of observable system without branch measurement.
9. **05-observable-with-branch-measurement-disconnected**:
10. Observable system with disconnected components (multiple islands) and branch measurements.
11. **06-unobservable-with-branch-measurement-disconnected**:
12. Unobservable system with disconnected components (multiple islands) and branch measurements.
13. **07-observable-2-voltage-sensors**:
14. Observable system with 2 voltage sensors.
Comment on lines +6 to +9
# Observability check cases for meshed networks

This module provides test cases for an N-node system with N-1 measurements.
The grids in tests are illustrated in the `test_network_diagrams.svg`
This module provides test cases for various meshed network observability scenarios.
The grids in tests are illustrated in the `test_network_diagrams.svg`.
Comment on lines +1357 to +1381
# Determine which node is the tap side and which is the control side
tap_node_idx = [node_1_idx, node_2_idx, node_3_idx][tap_side]
control_node_idx = [node_1_idx, node_2_idx, node_3_idx][control_side]
non_control_nodes = [idx for i, idx in enumerate([node_1_idx, node_2_idx, node_3_idx]) if i != control_side]

if tap_side == control_side:
# Tap at control side: edges from both non-control sides to control side
for non_control_idx in non_control_nodes:
graph[non_control_idx].append((control_node_idx, "regulated"))
# Bidirectional edge between non-control sides
graph[non_control_nodes[0]].append((non_control_nodes[1], "unregulated"))
graph[non_control_nodes[1]].append((non_control_nodes[0], "unregulated"))
else:
# Tap at non-control side: edges from non-tap sides to their respective sides
for i, idx in enumerate([node_1_idx, node_2_idx, node_3_idx]):
if i == tap_side:
# From tap side to control side
graph[tap_node_idx].append((control_node_idx, "regulated"))
elif i != control_side:
# From other non-tap, non-control side to control side
graph[idx].append((control_node_idx, "regulated"))
# Bidirectional edge between tap and the other non-control side
other_non_control = next(idx for idx in non_control_nodes if idx != tap_node_idx)
graph[tap_node_idx].append((other_non_control, "unregulated"))
graph[other_non_control].append((tap_node_idx, "unregulated"))
Comment on lines +1356 to +1360
# Branch3Side: side_1=0, side_2=1, side_3=2
# Determine which node is the tap side and which is the control side
tap_node_idx = [node_1_idx, node_2_idx, node_3_idx][tap_side]
control_node_idx = [node_1_idx, node_2_idx, node_3_idx][control_side]
non_control_nodes = [idx for i, idx in enumerate([node_1_idx, node_2_idx, node_3_idx]) if i != control_side]
Comment on lines +1440 to +1444
for source_idx in source_nodes:
# Use Dijkstra's algorithm
pq: list[tuple[float, int]] = [(0, source_idx)]
local_distances = [float("inf")] * num_nodes
local_distances[source_idx] = 0
if dist > local_distances[u]:
continue

for v, _ in graph[u]:
Comment on lines +73 to +74
"""Test invalid control side: controlling from non-source side (to_side) towards source side (from_side)"""
# Setup: source at node 0, transformer from 0 to 1, but control from to_side (1) - INVALID
@sonarqubecloud
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants