Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
2 changes: 1 addition & 1 deletion roseau/load_flow/io/dgs.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ def network_from_dgs( # noqa: C901

# Generate transformer parameters
transformers_params_dict[idx] = TransformerParameters(
id=name, windings=windings, uhv=uhv, ulv=ulv, sn=sn, p0=p0, i0=i0, psc=psc, vsc=vsc
id=name, type=windings, uhv=uhv, ulv=ulv, sn=sn, p0=p0, i0=i0, psc=psc, vsc=vsc
)
transformers_tap[idx] = typ_tr.at[idx, "dutap"]

Expand Down
3 changes: 1 addition & 2 deletions roseau/load_flow/io/dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
VoltageSource,
)
from roseau.load_flow.typing import Id, JsonDict
from roseau.load_flow.utils import TransformerType

if TYPE_CHECKING:
from roseau.load_flow.network import ElectricalNetwork
Expand Down Expand Up @@ -347,7 +346,7 @@ def v0_to_v1_converter(data: JsonDict) -> JsonDict: # noqa: C901
branch["tap"] = old_branch["tap"]
branch["type"] = branch_type
# Transformers have no phases information, we need to infer it from the windings
w1, w2, _ = TransformerType.extract_windings(transformers_params[params_id]["type"])
w1, w2, _ = TransformerParameters.extract_windings(transformers_params[params_id]["type"])
phases1 = "abcn" if ("y" in w1.lower() or "z" in w1.lower()) else "abc"
phases2 = "abcn" if ("y" in w2.lower() or "z" in w2.lower()) else "abc"
# Determine the "special element" connected to bus2 of the transformer
Expand Down
30 changes: 15 additions & 15 deletions roseau/load_flow/io/tests/test_dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ def test_to_dict():

# Same id, different transformer parameters -> fail
tp1 = TransformerParameters(
"t", windings="Dyn11", uhv=20000, ulv=400, sn=160 * 1e3, p0=460, i0=2.3 / 100, psc=2350, vsc=4 / 100
"t", type="Dyn11", uhv=20000, ulv=400, sn=160 * 1e3, p0=460, i0=2.3 / 100, psc=2350, vsc=4 / 100
)
tp2 = TransformerParameters(
"t", windings="Dyn11", uhv=20000, ulv=400, sn=200 * 1e3, p0=460, i0=2.3 / 100, psc=2350, vsc=4 / 100
"t", type="Dyn11", uhv=20000, ulv=400, sn=200 * 1e3, p0=460, i0=2.3 / 100, psc=2350, vsc=4 / 100
)
transformer1 = Transformer(id="Transformer1", bus1=source_bus, bus2=load_bus, parameters=tp1)
transformer2 = Transformer(id="Transformer2", bus1=source_bus, bus2=load_bus, parameters=tp2)
Expand All @@ -88,7 +88,7 @@ def test_to_dict():

# Same id, same transformer parameters -> ok
tp2 = TransformerParameters(
"t", windings="Dyn11", uhv=20000, ulv=400, sn=160 * 1e3, p0=460, i0=2.3 / 100, psc=2350, vsc=4 / 100
"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()
Expand Down Expand Up @@ -719,7 +719,7 @@ def test_v0_to_v1_converter(monkeypatch):
tp = {
"160kVA_Dd0": TransformerParameters(
id="160kVA_Dd0",
windings="dd0",
type="dd0",
sn=160000.0,
uhv=20000.0,
ulv=400.0,
Expand All @@ -730,7 +730,7 @@ def test_v0_to_v1_converter(monkeypatch):
),
"160kVA_Dd6": TransformerParameters(
id="160kVA_Dd6",
windings="dd6",
type="dd6",
sn=160000.0,
uhv=20000.0,
ulv=400.0,
Expand All @@ -741,7 +741,7 @@ def test_v0_to_v1_converter(monkeypatch):
),
"160kVA_Dyn11": TransformerParameters(
id="160kVA_Dyn11",
windings="dyn11",
type="dyn11",
sn=160000.0,
uhv=20000.0,
ulv=400.0,
Expand All @@ -752,7 +752,7 @@ def test_v0_to_v1_converter(monkeypatch):
),
"160kVA_Dyn5": TransformerParameters(
id="160kVA_Dyn5",
windings="dyn5",
type="dyn5",
sn=160000.0,
uhv=20000.0,
ulv=400.0,
Expand All @@ -763,7 +763,7 @@ def test_v0_to_v1_converter(monkeypatch):
),
"160kVA_Dzn0": TransformerParameters(
id="160kVA_Dzn0",
windings="dzn0",
type="dzn0",
sn=160000.0,
uhv=20000.0,
ulv=400.0,
Expand All @@ -774,7 +774,7 @@ def test_v0_to_v1_converter(monkeypatch):
),
"160kVA_Dzn6": TransformerParameters(
id="160kVA_Dzn6",
windings="dzn6",
type="dzn6",
sn=160000.0,
uhv=20000.0,
ulv=400.0,
Expand All @@ -785,7 +785,7 @@ def test_v0_to_v1_converter(monkeypatch):
),
"160kVA_Yd11": TransformerParameters(
id="160kVA_Yd11",
windings="yd11",
type="yd11",
sn=160000.0,
uhv=20000.0,
ulv=400.0,
Expand All @@ -796,7 +796,7 @@ def test_v0_to_v1_converter(monkeypatch):
),
"160kVA_Yd5": TransformerParameters(
id="160kVA_Yd5",
windings="yd5",
type="yd5",
sn=160000.0,
uhv=20000.0,
ulv=400.0,
Expand All @@ -807,7 +807,7 @@ def test_v0_to_v1_converter(monkeypatch):
),
"160kVA_Yyn0": TransformerParameters(
id="160kVA_Yyn0",
windings="yyn0",
type="yyn0",
sn=160000.0,
uhv=20000.0,
ulv=400.0,
Expand All @@ -818,7 +818,7 @@ def test_v0_to_v1_converter(monkeypatch):
),
"160kVA_Yyn6": TransformerParameters(
id="160kVA_Yyn6",
windings="yyn6",
type="yyn6",
sn=160000.0,
uhv=20000.0,
ulv=400.0,
Expand All @@ -829,7 +829,7 @@ def test_v0_to_v1_converter(monkeypatch):
),
"160kVA_Yzn11": TransformerParameters(
id="160kVA_Yzn11",
windings="yzn11",
type="yzn11",
sn=160000.0,
uhv=20000.0,
ulv=400.0,
Expand All @@ -840,7 +840,7 @@ def test_v0_to_v1_converter(monkeypatch):
),
"160kVA_Yzn5": TransformerParameters(
id="160kVA_Yzn5",
windings="yzn5",
type="yzn5",
sn=160000.0,
uhv=20000.0,
ulv=400.0,
Expand Down
8 changes: 5 additions & 3 deletions roseau/load_flow/models/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,14 @@ def network(self) -> Optional["ElectricalNetwork"]:
return self._network

@classmethod
def _check_phases(cls, id: Id, **kwargs: str) -> None:
def _check_phases(cls, id: Id, allowed_phases: Optional[frozenset[str]] = None, **kwargs: str) -> None:
if allowed_phases is None:
allowed_phases = cls.allowed_phases
name, phases = kwargs.popitem() # phases, phases1 or phases2
if phases not in cls.allowed_phases:
if phases not in allowed_phases:
msg = (
f"{cls.__name__} of id {id!r} got invalid {name} {phases!r}, allowed values are: "
f"{sorted(cls.allowed_phases)}"
f"{sorted(allowed_phases)}"
)
logger.error(msg)
raise RoseauLoadFlowException(msg, RoseauLoadFlowExceptionCode.BAD_PHASE)
Expand Down
167 changes: 163 additions & 4 deletions roseau/load_flow/models/tests/test_phases.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,11 +217,11 @@ def test_switches_phases():
assert switch.phases == switch.phases1 == switch.phases2 == "ca"


def test_transformer_phases():
def test_transformer_tri_phases():
Comment thread
Saelyos marked this conversation as resolved.
Outdated
bus1 = Bus("bus-1", phases="abcn")
bus2 = Bus("bus-2", phases="abcn")

assert Transformer.allowed_phases == {"abc", "abcn"}
assert Transformer.allowed_phases == Bus.allowed_phases

# Not allowed
tp = TransformerParameters.from_name("H61_50kVA", "Dyn11")
Expand Down Expand Up @@ -252,18 +252,177 @@ def test_transformer_phases():
# Default
bus1.phases = "abc"
bus2.phases = "abcn"
transformer = Transformer(id="tr1", bus1=bus1, bus2=bus2, parameters=tp, length=10)
transformer = Transformer(id="tr1", bus1=bus1, bus2=bus2, parameters=tp)
assert transformer.phases1 == "abc"
assert transformer.phases2 == "abcn"

# Intersection
bus1.phases = "abcn"
bus2.phases = "abcn"
transformer = Transformer(id="tr1", bus1=bus1, bus2=bus2, parameters=tp, length=10)
transformer = Transformer(id="tr1", bus1=bus1, bus2=bus2, parameters=tp)
assert transformer.phases1 == "abc"
assert transformer.phases2 == "abcn"


def test_transformer_single_phases():
bus1 = Bus("bus-1", phases="an")
bus2 = Bus("bus-2", phases="an")

# Not allowed
tp = TransformerParameters.from_name("160kVA", "single")
for ph in ("ba", "nc", "anb", "nabc", "acb"):
with pytest.raises(RoseauLoadFlowException) as e:
Transformer("tr1", bus1, bus2, phases1=ph, phases2=ph, parameters=tp)
assert e.value.code == RoseauLoadFlowExceptionCode.BAD_PHASE
assert e.value.msg.startswith(f"Transformer of id 'tr1' got invalid phases1 '{ph}', allowed values are")

# Allowed
Transformer("tr1", bus1, bus2, phases1="an", phases2="an", parameters=tp)

# Not in bus
bus2.phases = "ab"
with pytest.raises(RoseauLoadFlowException) as e:
Transformer("tr1", bus1, bus2, phases1="an", phases2="an", parameters=tp)
assert e.value.code == RoseauLoadFlowExceptionCode.BAD_PHASE
assert e.value.msg == "Phases (2) ['n'] of transformer 'tr1' are not in phases 'ab' of bus 'bus-2'."

# Default
bus1.phases = "ab"
bus2.phases = "ab"
transformer = Transformer(id="tr1", bus1=bus1, bus2=bus2, parameters=tp)
assert transformer.phases1 == "ab"
assert transformer.phases2 == "ab"

# Intersection
bus1.phases = "abcn"
bus2.phases = "ab"
transformer = Transformer(id="tr1", bus1=bus1, bus2=bus2, parameters=tp)
assert transformer.phases1 == "ab"
assert transformer.phases2 == "ab"

bus1.phases = "abc"
bus2.phases = "bcn"
transformer = Transformer(id="tr1", bus1=bus1, bus2=bus2, parameters=tp)
assert transformer.phases1 == "bc"
assert transformer.phases2 == "bc"

bus1.phases = "abc"
bus2.phases = "ca"
transformer = Transformer(id="tr1", bus1=bus1, bus2=bus2, parameters=tp)
assert transformer.phases1 == "ca"
assert transformer.phases2 == "ca"

# Can not be deduced
bus1.phases = "abc"
bus2.phases = "abc"
with pytest.raises(RoseauLoadFlowException) as e:
Transformer(id="tr1", bus1=bus1, bus2=bus2, parameters=tp)
assert e.value.code == RoseauLoadFlowExceptionCode.BAD_PHASE
assert (
e.value.msg == "Phases (1) of transformer 'tr1' can not be deduced from the buses, they need to be specified."
)

bus1.phases = "abcn"
bus2.phases = "abn"
with pytest.raises(RoseauLoadFlowException) as e:
Transformer(id="tr1", bus1=bus1, bus2=bus2, parameters=tp)
assert e.value.code == RoseauLoadFlowExceptionCode.BAD_PHASE
assert (
e.value.msg == "Phases (1) of transformer 'tr1' can not be deduced from the buses, they need to be specified."
)

bus1.phases = "abcn"
bus2.phases = "a"
with pytest.raises(RoseauLoadFlowException) as e:
Transformer(id="tr1", bus1=bus1, bus2=bus2, parameters=tp)
assert e.value.code == RoseauLoadFlowExceptionCode.BAD_PHASE
assert (
e.value.msg == "Phases (1) of transformer 'tr1' can not be deduced from the buses, they need to be specified."
)


def test_transformer_split_phases():
bus1 = Bus("bus-1", phases="ab")
bus2 = Bus("bus-2", phases="abn")

# Not allowed
tp = TransformerParameters.from_name("160kVA", "split")
for ph in ("ba", "nc", "anb", "nabc", "acb"):
with pytest.raises(RoseauLoadFlowException) as e:
Transformer("tr1", bus1, bus2, phases1=ph, phases2=ph, parameters=tp)
assert e.value.code == RoseauLoadFlowExceptionCode.BAD_PHASE
assert e.value.msg.startswith(f"Transformer of id 'tr1' got invalid phases1 '{ph}', allowed values are")

# Allowed
Transformer("tr1", bus1, bus2, phases1="ab", phases2="abn", parameters=tp)

# Not in bus 1
bus1.phases = "acn"
with pytest.raises(RoseauLoadFlowException) as e:
Transformer("tr1", bus1, bus2, phases1="ab", phases2="abn", parameters=tp)
assert e.value.code == RoseauLoadFlowExceptionCode.BAD_PHASE
assert e.value.msg == "Phases (1) ['b'] of transformer 'tr1' are not in phases 'acn' of bus 'bus-1'."

# Not in bus 2
bus1.phases = "abc"
bus2.phases = "acn"
with pytest.raises(RoseauLoadFlowException) as e:
Transformer("tr1", bus1, bus2, phases1="ab", phases2="abn", parameters=tp)
assert e.value.code == RoseauLoadFlowExceptionCode.BAD_PHASE
assert e.value.msg == "Phases (2) ['b'] of transformer 'tr1' are not in phases 'acn' of bus 'bus-2'."

# Default
bus1.phases = "ab"
bus2.phases = "abn"
transformer = Transformer(id="tr1", bus1=bus1, bus2=bus2, parameters=tp)
assert transformer.phases1 == "ab"
assert transformer.phases2 == "abn"

# Intersection
bus1.phases = "abcn"
bus2.phases = "can"
transformer = Transformer(id="tr1", bus1=bus1, bus2=bus2, parameters=tp)
assert transformer.phases1 == "ca"
assert transformer.phases2 == "can"

# Can not be deduced
bus1.phases = "abc"
bus2.phases = "abcn"
with pytest.raises(RoseauLoadFlowException) as e:
Transformer(id="tr1", bus1=bus1, bus2=bus2, parameters=tp)
assert e.value.code == RoseauLoadFlowExceptionCode.BAD_PHASE
assert (
e.value.msg == "Phases (1) of transformer 'tr1' can not be deduced from the buses, they need to be specified."
)

bus1.phases = "a"
bus2.phases = "abn"
with pytest.raises(RoseauLoadFlowException) as e:
Transformer(id="tr1", bus1=bus1, bus2=bus2, parameters=tp)
assert e.value.code == RoseauLoadFlowExceptionCode.BAD_PHASE
assert (
e.value.msg == "Phases (1) of transformer 'tr1' can not be deduced from the buses, they need to be specified."
)

bus1.phases = "ab"
bus2.phases = "ab"
with pytest.raises(RoseauLoadFlowException) as e:
Transformer(id="tr1", bus1=bus1, bus2=bus2, parameters=tp)
assert e.value.code == RoseauLoadFlowExceptionCode.BAD_PHASE
assert (
e.value.msg == "Phases (2) of transformer 'tr1' can not be deduced from the buses, they need to be specified."
)

bus1.phases = "ab"
bus2.phases = "abc"
with pytest.raises(RoseauLoadFlowException) as e:
Transformer(id="tr1", bus1=bus1, bus2=bus2, parameters=tp)
assert e.value.code == RoseauLoadFlowExceptionCode.BAD_PHASE
assert (
e.value.msg == "Phases (2) of transformer 'tr1' can not be deduced from the buses, they need to be specified."
)


def test_voltage_phases():
# Bus
bus = Bus("bus", phases="abcn")
Expand Down
Loading