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 |