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
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ repos:
hooks:
- id: prettier
args: ["--print-width", "120"]
exclude: ^.vscode/
13 changes: 5 additions & 8 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,21 @@
"jupyter.notebookFileRoot": "${workspaceFolder}",
"notebook.formatOnSave.enabled": true,
"notebook.codeActionsOnSave": {
"source.organizeImports.ruff": true
"source.organizeImports.ruff": "explicit",
},

// Python
"python.analysis.diagnosticSeverityOverrides": {
"reportInvalidStringEscapeSequence": "warning",
"reportImportCycles": "warning",
"reportUnusedImport": "warning"
"reportUnusedImport": "warning",
},
"python.formatting.provider": "none",
"python.testing.pytestArgs": [],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports.ruff": true
}
}
"source.organizeImports.ruff": "explicit",
},
},
}
8 changes: 8 additions & 0 deletions doc/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@

**In development**

- {gh-pr}`138` Add network constraints for analysis of the results.
- Buses can define minimum and maximum voltages. Use `bus.res_violated` to see if the bus has
over- or under-voltage.
- Lines can define a maximum current. Use `line.res_violated` to see if the loading of any of the
line's cables is too high.
- Transformers can define a maximum power. Use `transformer.res_violated` to see if the transformer
loading is too high.
- The new fields also appear in the data frames of the network.
- {gh-pr}`133` {gh-issue}`126` Add Qmin and Qmax limits of flexible parameters.
- {gh-pr}`132` {gh-issue}`101` Document extra utilities including converters and constants.
- {gh-pr}`131` {gh-issue}`127` Improve the documentation of the flexible loads.
Expand Down
190 changes: 130 additions & 60 deletions doc/usage/Getting_Started.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions roseau/load_flow/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class RoseauLoadFlowExceptionCode(Enum):
BAD_BUS_ID = auto()
BAD_BUS_TYPE = auto()
BAD_POTENTIALS_SIZE = auto()
BAD_VOLTAGES = auto()
BAD_VOLTAGES_SIZE = auto()
BAD_SHORT_CIRCUIT = auto()

Expand Down
14 changes: 7 additions & 7 deletions roseau/load_flow/io/dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,15 @@ def network_from_dict(
return buses, branches_dict, loads, sources, grounds, potential_refs


def network_to_dict(en: "ElectricalNetwork", include_geometry: bool) -> JsonDict:
def network_to_dict(en: "ElectricalNetwork", *, _lf_only: bool) -> JsonDict:
"""Return a dictionary of the current network data.

Args:
en:
The electrical network.

include_geometry:
If False, the geometry will not be added to the network dictionary.
_lf_only:
Internal argument, please do not use.

Returns:
The created dictionary.
Expand All @@ -155,7 +155,7 @@ def network_to_dict(en: "ElectricalNetwork", include_geometry: bool) -> JsonDict
sources: list[JsonDict] = []
short_circuits: list[JsonDict] = []
for bus in en.buses.values():
buses.append(bus.to_dict(include_geometry=include_geometry))
buses.append(bus.to_dict(_lf_only=_lf_only))
for element in bus._connected_elements:
if isinstance(element, AbstractLoad):
assert element.bus is bus
Expand All @@ -171,7 +171,7 @@ def network_to_dict(en: "ElectricalNetwork", include_geometry: bool) -> JsonDict
lines_params_dict: dict[Id, LineParameters] = {}
transformers_params_dict: dict[Id, TransformerParameters] = {}
for branch in en.branches.values():
branches.append(branch.to_dict(include_geometry=include_geometry))
branches.append(branch.to_dict(_lf_only=_lf_only))
if isinstance(branch, Line):
params_id = branch.parameters.id
if params_id in lines_params_dict and branch.parameters != lines_params_dict[params_id]:
Expand All @@ -192,13 +192,13 @@ def network_to_dict(en: "ElectricalNetwork", include_geometry: bool) -> JsonDict
# Line parameters
line_params: list[JsonDict] = []
for lp in lines_params_dict.values():
line_params.append(lp.to_dict())
line_params.append(lp.to_dict(_lf_only=_lf_only))
line_params.sort(key=lambda x: x["id"]) # Always keep the same order

# Transformer parameters
transformer_params: list[JsonDict] = []
for tp in transformers_params_dict.values():
transformer_params.append(tp.to_dict())
transformer_params.append(tp.to_dict(_lf_only=_lf_only))
transformer_params.sort(key=lambda x: x["id"]) # Always keep the same order

res = {
Expand Down
30 changes: 26 additions & 4 deletions roseau/load_flow/io/tests/test_dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ def test_to_dict():
ground = Ground("ground")
vn = 400 / np.sqrt(3)
voltages = [vn, vn * np.exp(-2 / 3 * np.pi * 1j), vn * np.exp(2 / 3 * np.pi * 1j)]
source_bus = Bus(id="source", phases="abcn", geometry=Point(0.0, 0.0))
load_bus = Bus(id="load bus", phases="abcn", geometry=Point(0.0, 1.0))
source_bus = Bus(id="source", phases="abcn", geometry=Point(0.0, 0.0), min_voltage=0.9 * vn)
load_bus = Bus(id="load bus", phases="abcn", geometry=Point(0.0, 1.0), max_voltage=1.1 * vn)
ground.connect(load_bus)
p_ref = PotentialRef("pref", element=ground)
vs = VoltageSource("vs", source_bus, phases="abcn", voltages=voltages)
Expand All @@ -44,6 +44,8 @@ def test_to_dict():
grounds=[ground],
potential_refs=[p_ref],
)

# Same id, different line parameters -> fail
with pytest.raises(RoseauLoadFlowException) as e:
en.to_dict()
assert "There are multiple line parameters with id 'test'" in e.value.msg
Expand All @@ -52,17 +54,28 @@ def test_to_dict():
# Same id, same line parameters -> ok
lp2 = LineParameters("test", z_line=np.eye(4, dtype=complex), y_shunt=np.eye(4, dtype=complex))
line2.parameters = lp2
en.to_dict()

# Dict content
line2.parameters = lp1
lp1.max_current = 1000
res = en.to_dict()
assert "geometry" in res["buses"][0]
assert "geometry" in res["buses"][1]
assert "geometry" in res["branches"][0]
assert "geometry" in res["branches"][1]
assert np.isclose(res["buses"][0]["min_voltage"], 0.9 * vn)
assert np.isclose(res["buses"][1]["max_voltage"], 1.1 * vn)
assert np.isclose(res["lines_params"][0]["max_current"], 1000)

res = en.to_dict(include_geometry=False)
res = en.to_dict(_lf_only=True)
assert "geometry" not in res["buses"][0]
assert "geometry" not in res["buses"][1]
assert "geometry" not in res["branches"][0]
assert "geometry" not in res["branches"][1]
assert "min_voltage" not in res["buses"][0]
assert "max_voltage" not in res["buses"][1]
assert "max_current" not in res["lines_params"][0]

# Same id, different transformer parameters -> fail
ground = Ground("ground")
Expand Down Expand Up @@ -93,6 +106,8 @@ def test_to_dict():
grounds=[ground],
potential_refs=[p_ref],
)

# Same id, different transformer parameters -> fail
with pytest.raises(RoseauLoadFlowException) as e:
en.to_dict()
assert "There are multiple transformer parameters with id 't'" in e.value.msg
Expand All @@ -103,17 +118,24 @@ def test_to_dict():
"t", type="Dyn11", uhv=20000, ulv=400, sn=160 * 1e3, p0=460, i0=2.3 / 100, psc=2350, vsc=4 / 100
)
transformer2.parameters = tp2
en.to_dict()

# Dict content
transformer2.parameters = tp1
tp1.max_power = 180_000
res = en.to_dict()
assert "geometry" in res["buses"][0]
assert "geometry" in res["buses"][1]
assert "geometry" in res["branches"][0]
assert "geometry" in res["branches"][1]
assert np.isclose(res["transformers_params"][0]["max_power"], 180_000)

res = en.to_dict(include_geometry=False)
res = en.to_dict(_lf_only=True)
assert "geometry" not in res["buses"][0]
assert "geometry" not in res["buses"][1]
assert "geometry" not in res["branches"][0]
assert "geometry" not in res["branches"][1]
assert "max_power" not in res["transformers_params"][0]


def test_v0_to_v1_converter(monkeypatch):
Expand Down
4 changes: 2 additions & 2 deletions roseau/load_flow/models/branches.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def res_voltages(self) -> tuple[Q_[np.ndarray], Q_[np.ndarray]]:
def from_dict(cls, data: JsonDict) -> Self:
return cls(**data) # not used anymore

def to_dict(self, include_geometry: bool = True) -> JsonDict:
def to_dict(self, *, _lf_only: bool = False) -> JsonDict:
res = {
"id": self.id,
"type": self.branch_type,
Expand All @@ -135,7 +135,7 @@ def to_dict(self, include_geometry: bool = True) -> JsonDict:
"bus1": self.bus1.id,
"bus2": self.bus2.id,
}
if self.geometry is not None and include_geometry:
if not _lf_only and self.geometry is not None:
res["geometry"] = self.geometry.__geo_interface__
return res

Expand Down
Loading