Skip to content

Commit

Permalink
Detect invalid element overrides (#203)
Browse files Browse the repository at this point in the history
Fixes #186
  • Loading branch information
alihamdan authored Mar 18, 2024
1 parent a2fd4e5 commit 7d02ca7
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 110 deletions.
2 changes: 2 additions & 0 deletions doc/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ myst:

## Unreleased

- {gh-pr}`203` {gh-issue}`186` Detect invalid element overrides when connecting a new element with the
same ID and type of an existing element.
- {gh-pr}`202` {gh-issue}`188` Explicitly prevent instantiation of abstract classes.
- {gh-pr}`201` {gh-issue}`185` Add `type` attribute to the load classes and rename branches `branch_type`
attribute to `type` for consistency. Please replace `branch.branch_type` by `branch.type` in your code.
Expand Down
7 changes: 4 additions & 3 deletions roseau/load_flow/models/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,10 @@ def _disconnect(self) -> None:
element._connected_elements.remove(self)
self._connected_elements = []
self._set_network(None)
self._cy_element.disconnect()
# The cpp element has been disconnected and can't be reconnected easily, it's safer to delete it
self._cy_element = None
if self._cy_element is not None:
self._cy_element.disconnect()
# The cpp element has been disconnected and can't be reconnected easily, it's safer to delete it
self._cy_element = None

def _invalidate_network_results(self) -> None:
"""Invalidate the network making the result"""
Expand Down
15 changes: 8 additions & 7 deletions roseau/load_flow/models/tests/test_line_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@


def test_line_parameters():
bus = Bus(id="junction", phases="abcn")
bus1 = Bus(id="junction1", phases="abcn")
bus2 = Bus(id="junction2", phases="abcn")
ground = Ground("ground")

# Real element off the diagonal (Z)
Expand Down Expand Up @@ -63,9 +64,9 @@ def test_line_parameters():
y_shunt = np.eye(3, dtype=complex)
lp = LineParameters("test", z_line=z_line, y_shunt=y_shunt)
with pytest.raises(RoseauLoadFlowException) as e:
Line("line", bus, bus, phases="abcn", ground=ground, parameters=lp, length=2.4)
Line("line1", bus1, bus2, phases="abcn", ground=ground, parameters=lp, length=2.4)
assert e.value.code == RoseauLoadFlowExceptionCode.BAD_Y_SHUNT_SHAPE
assert e.value.msg == "Incorrect y_shunt dimensions for line 'line': (3, 3) instead of (4, 4)"
assert e.value.msg == "Incorrect y_shunt dimensions for line 'line1': (3, 3) instead of (4, 4)"

# Bad shape (MV - Z)
z_line = np.eye(4, dtype=complex)[:, :2]
Expand All @@ -80,18 +81,18 @@ def test_line_parameters():
y_shunt = np.eye(6, dtype=complex)
lp = LineParameters("test", z_line=z_line, y_shunt=y_shunt)
with pytest.raises(RoseauLoadFlowException) as e:
Line("line", bus, bus, phases="abc", ground=ground, parameters=lp, length=2.4)
Line("line2", bus1, bus2, phases="abc", ground=ground, parameters=lp, length=2.4)
assert e.value.code == RoseauLoadFlowExceptionCode.BAD_Y_SHUNT_SHAPE
assert e.value.msg == "Incorrect y_shunt dimensions for line 'line': (6, 6) instead of (3, 3)"
assert e.value.msg == "Incorrect y_shunt dimensions for line 'line2': (6, 6) instead of (3, 3)"

# LV line with not zero shunt admittance
z_line = np.eye(3, dtype=complex)
y_shunt = np.eye(3, dtype=complex)
lp = LineParameters("test", z_line=z_line, y_shunt=y_shunt)
with pytest.raises(RoseauLoadFlowException) as e:
Line("line", bus, bus, phases="abcn", ground=ground, parameters=lp, length=2.4)
Line("line3", bus1, bus2, phases="abcn", ground=ground, parameters=lp, length=2.4)
assert e.value.code == RoseauLoadFlowExceptionCode.BAD_Z_LINE_SHAPE
assert e.value.msg == "Incorrect z_line dimensions for line 'line': (3, 3) instead of (4, 4)"
assert e.value.msg == "Incorrect z_line dimensions for line 'line3': (3, 3) instead of (4, 4)"

# Adding/Removing a shunt to a line is not allowed
mat = np.eye(3, dtype=complex)
Expand Down
26 changes: 13 additions & 13 deletions roseau/load_flow/models/tests/test_lines.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@

def test_lines_length():
bus1 = Bus("bus1", phases="abcn")
bus2 = Bus("bus1", phases="abcn")
bus2 = Bus("bus2", phases="abcn")
lp = LineParameters("lp", z_line=np.eye(4, dtype=complex))

# Negative value for length in the constructor
with pytest.raises(RoseauLoadFlowException) as e:
Line("line", bus1=bus1, bus2=bus2, parameters=lp, length=-5)
Line("line1", bus1=bus1, bus2=bus2, parameters=lp, length=-5)
assert "A line length must be greater than 0." in e.value.msg
assert e.value.args[1] == RoseauLoadFlowExceptionCode.BAD_LENGTH_VALUE

# The same with a unit
with pytest.raises(RoseauLoadFlowException) as e:
Line("line", bus1=bus1, bus2=bus2, parameters=lp, length=Q_(-5, "m"))
Line("line2", bus1=bus1, bus2=bus2, parameters=lp, length=Q_(-5, "m"))
assert "A line length must be greater than 0." in e.value.msg
assert e.value.args[1] == RoseauLoadFlowExceptionCode.BAD_LENGTH_VALUE

# Test on the length setter
line = Line("line", bus1=bus1, bus2=bus2, parameters=lp, length=Q_(5, "m"))
line = Line("line3", bus1=bus1, bus2=bus2, parameters=lp, length=Q_(5, "m"))
with pytest.raises(RoseauLoadFlowException) as e:
line.length = -6.5
assert "A line length must be greater than 0." in e.value.msg
Expand All @@ -40,40 +40,40 @@ def test_lines_length():

def test_lines_units():
bus1 = Bus("bus1", phases="abcn")
bus2 = Bus("bus1", phases="abcn")
bus2 = Bus("bus2", phases="abcn")
lp = LineParameters("lp", z_line=np.eye(4, dtype=complex))

# Good unit constructor
line = Line("line", bus1=bus1, bus2=bus2, parameters=lp, length=Q_(5, "km"))
line = Line("line1", bus1=bus1, bus2=bus2, parameters=lp, length=Q_(5, "km"))
assert np.isclose(line._length, 5)

# Good unit setter
line = Line("line", bus1=bus1, bus2=bus2, parameters=lp, length=5)
line = Line("line2", bus1=bus1, bus2=bus2, parameters=lp, length=5)
assert np.allclose(line._length, 5)
line.length = Q_(6.5, "m")
assert np.isclose(line._length, 6.5e-3)

# Bad unit constructor
with pytest.raises(DimensionalityError, match=r"Cannot convert from 'ampere' \(\[current\]\) to 'km'"):
Line("line", bus1=bus1, bus2=bus2, parameters=lp, length=Q_(5, "A"))
Line("line3", bus1=bus1, bus2=bus2, parameters=lp, length=Q_(5, "A"))

# Bad unit setter
line = Line("line", bus1=bus1, bus2=bus2, parameters=lp, length=5)
line = Line("line4", bus1=bus1, bus2=bus2, parameters=lp, length=5)
with pytest.raises(DimensionalityError, match=r"Cannot convert from 'ampere' \(\[current\]\) to 'km'"):
line.length = Q_(6.5, "A")


def test_line_parameters_shortcut():
bus1 = Bus("bus1", phases="abcn")
bus2 = Bus("bus1", phases="abcn")
bus2 = Bus("bus2", phases="abcn")

#
# Without shunt
#
lp = LineParameters("lp", z_line=np.eye(4, dtype=complex))

# Z
line = Line("line", bus1=bus1, bus2=bus2, parameters=lp, length=Q_(50, "m"))
line = Line("line1", bus1=bus1, bus2=bus2, parameters=lp, length=Q_(50, "m"))
assert np.allclose(line.z_line.m_as("ohm"), 0.05 * np.eye(4, dtype=complex))

# Y
Expand All @@ -89,7 +89,7 @@ def test_line_parameters_shortcut():

# Z
ground = Ground("ground")
line = Line("line", bus1=bus1, bus2=bus2, parameters=lp, length=Q_(50, "m"), ground=ground)
line = Line("line2", bus1=bus1, bus2=bus2, parameters=lp, length=Q_(50, "m"), ground=ground)
assert np.allclose(line.z_line.m_as("ohm"), 0.05 * z_line)

# Y
Expand All @@ -99,7 +99,7 @@ def test_line_parameters_shortcut():

def test_res_violated():
bus1 = Bus("bus1", phases="abc")
bus2 = Bus("bus1", phases="abc")
bus2 = Bus("bus2", phases="abc")
lp = LineParameters("lp", z_line=np.eye(3, dtype=complex))
line = Line("line", bus1=bus1, bus2=bus2, parameters=lp, length=Q_(50, "m"))
direct_seq = np.exp([0, -2 / 3 * np.pi * 1j, 2 / 3 * np.pi * 1j])
Expand Down
Loading

0 comments on commit 7d02ca7

Please sign in to comment.