Transformer with non-trivial phase shift and tap ratio

Note

You can download this example as a Jupyter notebook or start it in interactive mode.

Transformer with non-trivial phase shift and tap ratio#

This example is a copy of pandapower’s minimal example.

[1]:
import numpy as np
import pandas as pd

import pypsa
[2]:
network = pypsa.Network()

network.add("Bus", "MV bus", v_nom=20, v_mag_pu_set=1.02)
network.add("Bus", "LV1 bus", v_nom=0.4)
network.add("Bus", "LV2 bus", v_nom=0.4)

network.add(
    "Transformer",
    "MV-LV trafo",
    type="0.4 MVA 20/0.4 kV",
    bus0="MV bus",
    bus1="LV1 bus",
)
network.add(
    "Line", "LV cable", type="NAYY 4x50 SE", bus0="LV1 bus", bus1="LV2 bus", length=0.1
)
network.add(
    "Generator", "External Grid", bus="MV bus", control="Slack", marginal_cost=10
)
network.add("Load", "LV load", bus="LV2 bus", p_set=0.1, q_set=0.05)
[2]:
Index(['LV load'], dtype='object')
[3]:
def run_pf():
    network.lpf()
    network.pf(use_seed=True)
    return pd.DataFrame(
        {
            "Voltage Angles": network.buses_t.v_ang.loc["now"] * 180.0 / np.pi,
            "Volate Magnitude": network.buses_t.v_mag_pu.loc["now"],
        }
    )
[4]:
run_pf()
INFO:pypsa.pf:Performing linear load-flow on AC sub-network <pypsa.components.SubNetwork object at 0x7fae62153a70> for snapshot(s) Index(['now'], dtype='object', name='snapshot')
INFO:pypsa.pf:Performing non-linear load-flow on AC sub-network <pypsa.components.SubNetwork object at 0x7fae342d2cf0> for snapshots Index(['now'], dtype='object', name='snapshot')
[4]:
Voltage Angles Volate Magnitude
Bus
MV bus 0.000000 1.020000
LV1 bus -150.760126 1.008843
LV2 bus -149.884141 0.964431
[5]:
network.transformers.tap_position = 2
run_pf()
INFO:pypsa.pf:Performing linear load-flow on AC sub-network <pypsa.components.SubNetwork object at 0x7fae34342570> for snapshot(s) Index(['now'], dtype='object', name='snapshot')
INFO:pypsa.pf:Performing non-linear load-flow on AC sub-network <pypsa.components.SubNetwork object at 0x7fae3488a300> for snapshots Index(['now'], dtype='object', name='snapshot')
[5]:
Voltage Angles Volate Magnitude
Bus
MV bus 0.000000 1.020000
LV1 bus -150.843911 0.959655
LV2 bus -149.870837 0.912713
[6]:
network.transformers.tap_position = -2
run_pf()
INFO:pypsa.pf:Performing linear load-flow on AC sub-network <pypsa.components.SubNetwork object at 0x7fae6274eba0> for snapshot(s) Index(['now'], dtype='object', name='snapshot')
INFO:pypsa.pf:Performing non-linear load-flow on AC sub-network <pypsa.components.SubNetwork object at 0x7fae6274eba0> for snapshots Index(['now'], dtype='object', name='snapshot')
[6]:
Voltage Angles Volate Magnitude
Bus
MV bus 0.000000 1.020000
LV1 bus -150.681666 1.063133
LV2 bus -149.896634 1.021202

Now play with tap changer on LV side

[7]:
new_trafo_lv_tap = network.transformer_types.loc[["0.4 MVA 20/0.4 kV"]]
new_trafo_lv_tap.index = ["New trafo"]
new_trafo_lv_tap.tap_side = 1
new_trafo_lv_tap.T
[7]:
New trafo
f_nom 50.0
s_nom 0.4
v_nom_0 20.0
v_nom_1 0.4
vsc 6.0
vscr 1.425
pfe 1.35
i0 0.3375
phase_shift 150.0
tap_side 1
tap_neutral 0
tap_min -2
tap_max 2
tap_step 2.5
references pandapower;Oswald - Transformatoren - Vorlesun...
[8]:
network.transformer_types = pd.concat([network.transformer_types, new_trafo_lv_tap])
network.transformers.type = "New trafo"
network.transformers.tap_position = 2
run_pf()
INFO:pypsa.pf:Performing linear load-flow on AC sub-network <pypsa.components.SubNetwork object at 0x7fae34257a70> for snapshot(s) Index(['now'], dtype='object', name='snapshot')
INFO:pypsa.pf:Performing non-linear load-flow on AC sub-network <pypsa.components.SubNetwork object at 0x7fae34257a70> for snapshots Index(['now'], dtype='object', name='snapshot')
[8]:
Voltage Angles Volate Magnitude
Bus
MV bus 0.000000 1.020000
LV1 bus -150.755820 1.059317
LV2 bus -149.964875 1.017221
[9]:
network.transformers.T
[9]:
Transformer MV-LV trafo
bus0 MV bus
bus1 LV1 bus
type New trafo
model t
x 0.058283
r 0.01425
g 0.003375
b -0.0
s_nom 0.4
s_nom_mod 0.0
s_nom_extendable False
s_nom_min 0.0
s_nom_max inf
s_max_pu 1.0
capital_cost 0.0
num_parallel 1.0
tap_ratio 1.05
tap_side 1
tap_position 2
phase_shift 150.0
active True
build_year 0
lifetime inf
v_ang_min -inf
v_ang_max inf
sub_network 0
x_pu 0.145712
r_pu 0.035618
g_pu 0.00135
b_pu -0.0
x_pu_eff 0.152994
r_pu_eff 0.037406
s_nom_opt 0.0
[10]:
network.transformers.tap_position = -2
run_pf()
INFO:pypsa.pf:Performing linear load-flow on AC sub-network <pypsa.components.SubNetwork object at 0x7fae2ff201a0> for snapshot(s) Index(['now'], dtype='object', name='snapshot')
INFO:pypsa.pf:Performing non-linear load-flow on AC sub-network <pypsa.components.SubNetwork object at 0x7fae341cb590> for snapshots Index(['now'], dtype='object', name='snapshot')
[10]:
Voltage Angles Volate Magnitude
Bus
MV bus 0.000000 1.020000
LV1 bus -150.765232 0.958366
LV2 bus -149.789394 0.911353

Now make sure that the phase shift is also there in the LOPF

[11]:
network.generators.p_nom = 1.0
network.lines.s_nom = 1.0
network.optimize()
pd.DataFrame(
    {
        "Voltage Angles": network.buses_t.v_ang.loc["now"] * 180.0 / np.pi,
        "Volate Magnitude": network.buses_t.v_mag_pu.loc["now"],
    }
)
WARNING:pypsa.consistency:The following buses have carriers which are not defined:
Index(['MV bus', 'LV1 bus', 'LV2 bus'], dtype='object', name='Bus')
WARNING:pypsa.consistency:The following lines have carriers which are not defined:
Index(['LV cable'], dtype='object', name='Line')
WARNING:pypsa.consistency:The following sub_networks have carriers which are not defined:
Index(['0'], dtype='object', name='SubNetwork')
WARNING:pypsa.consistency:The following buses have carriers which are not defined:
Index(['MV bus', 'LV1 bus', 'LV2 bus'], dtype='object', name='Bus')
WARNING:pypsa.consistency:The following lines have carriers which are not defined:
Index(['LV cable'], dtype='object', name='Line')
WARNING:pypsa.consistency:The following sub_networks have carriers which are not defined:
Index(['0'], dtype='object', name='SubNetwork')
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/envs/v0.31.0/lib/python3.12/site-packages/linopy/common.py:147: UserWarning: coords for dimension(s) ['Generator'] is not aligned with the pandas object. Previously, the indexes of the pandas were ignored and overwritten in these cases. Now, the pandas object's coordinates are taken considered for alignment.
  warn(
INFO:linopy.model: Solve problem using Highs solver
INFO:linopy.io: Writing time: 0.04s
INFO:linopy.solvers:Log file at /tmp/highs.log
INFO:linopy.constants: Optimization successful:
Status: ok
Termination condition: optimal
Solution: 3 primals, 10 duals
Objective: 1.00e+00
Solver model: available
Solver message: optimal

INFO:pypsa.optimization.optimize:The shadow-prices of the constraints Generator-fix-p-lower, Generator-fix-p-upper, Line-fix-s-lower, Line-fix-s-upper, Transformer-fix-s-lower, Transformer-fix-s-upper were not assigned to the network.
Running HiGHS 1.7.2 (git hash: 184e327): Copyright (c) 2024 HiGHS under MIT licence terms
Coefficient ranges:
  Matrix [1e+00, 1e+00]
  Cost   [1e+01, 1e+01]
  Bound  [0e+00, 0e+00]
  RHS    [1e-01, 1e+00]
Presolving model
0 rows, 0 cols, 0 nonzeros  0s
0 rows, 0 cols, 0 nonzeros  0s
Presolve : Reductions: rows 0(-10); columns 0(-3); elements 0(-12) - Reduced to empty
Solving the original LP from the solution after postsolve
Model   status      : Optimal
Objective value     :  1.0000000000e+00
HiGHS run time      :          0.00
Writing the solution to /tmp/linopy-solve-i8k1c0v6.sol
[11]:
Voltage Angles Volate Magnitude
Bus
MV bus 0.627810 1.020000
LV1 bus -0.165294 0.958366
LV2 bus -0.462516 0.911353