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 pypsa
import numpy as np
import pandas as pd
[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=.4)
network.add("Bus","LV2 bus",v_nom=.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")
network.add("Load", "LV load", bus="LV2 bus", p_set=0.1, q_set=0.05)
[3]:
def run_pf():
    network.lpf()
    network.pf(use_seed=True)
    return pd.DataFrame({'Voltage Angles': network.buses_t.v_ang.loc['now']*180./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 SubNetwork 0 for snapshot(s) Index(['now'], dtype='object')
INFO:pypsa.pf:Performing non-linear load-flow on AC sub-network SubNetwork 0 for snapshots Index(['now'], dtype='object')
INFO:pypsa.pf:Newton-Raphson solved in 3 iterations with error of 0.000000 in 0.026950 seconds
[4]:
Voltage Angles Volate Magnitude
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 SubNetwork 0 for snapshot(s) Index(['now'], dtype='object')
INFO:pypsa.pf:Performing non-linear load-flow on AC sub-network SubNetwork 0 for snapshots Index(['now'], dtype='object')
INFO:pypsa.pf:Newton-Raphson solved in 3 iterations with error of 0.000000 in 0.026923 seconds
[5]:
Voltage Angles Volate Magnitude
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 SubNetwork 0 for snapshot(s) Index(['now'], dtype='object')
INFO:pypsa.pf:Performing non-linear load-flow on AC sub-network SubNetwork 0 for snapshots Index(['now'], dtype='object')
INFO:pypsa.pf:Newton-Raphson solved in 3 iterations with error of 0.000000 in 0.026316 seconds
[6]:
Voltage Angles Volate Magnitude
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 = network.transformer_types.append(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 SubNetwork 0 for snapshot(s) Index(['now'], dtype='object')
INFO:pypsa.pf:Performing non-linear load-flow on AC sub-network SubNetwork 0 for snapshots Index(['now'], dtype='object')
INFO:pypsa.pf:Newton-Raphson solved in 3 iterations with error of 0.000000 in 0.025110 seconds
[8]:
Voltage Angles Volate Magnitude
MV bus 0.000000 1.020000
LV1 bus -150.755820 1.059317
LV2 bus -149.964875 1.017221
[9]:
network.transformers.T
[9]:
MV-LV trafo
attribute
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_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
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 SubNetwork 0 for snapshot(s) Index(['now'], dtype='object')
INFO:pypsa.pf:Performing non-linear load-flow on AC sub-network SubNetwork 0 for snapshots Index(['now'], dtype='object')
INFO:pypsa.pf:Newton-Raphson solved in 3 iterations with error of 0.000000 in 0.027012 seconds
[10]:
Voltage Angles Volate Magnitude
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.
network.lines.s_nom = 1.
network.lopf()
pd.DataFrame({'Voltage Angles': network.buses_t.v_ang.loc['now']*180./np.pi,
                        'Volate Magnitude': network.buses_t.v_mag_pu.loc['now']})
INFO:pypsa.opf:Performed preliminary steps
INFO:pypsa.opf:Building pyomo model using `kirchhoff` formulation
INFO:pypsa.opf:Solving model using glpk
WARNING:pyomo.solvers:Could not locate the 'glpsol' executable, which is required for solver 'glpk'
---------------------------------------------------------------------------
ApplicationError                          Traceback (most recent call last)
/tmp/ipykernel_870/2785965588.py in <module>
      1 network.generators.p_nom = 1.
      2 network.lines.s_nom = 1.
----> 3 network.lopf()
      4 pd.DataFrame({'Voltage Angles': network.buses_t.v_ang.loc['now']*180./np.pi,
      5                         'Volate Magnitude': network.buses_t.v_mag_pu.loc['now']})

~/checkouts/readthedocs.org/user_builds/pypsa-docs-staging/envs/latest/lib/python3.7/site-packages/pypsa/components.py in lopf(self, snapshots, pyomo, solver_name, solver_options, solver_logfile, formulation, keep_files, extra_functionality, multi_investment_periods, **kwargs)
    646
    647         if pyomo:
--> 648             return network_lopf(self, **args)
    649         else:
    650             return network_lopf_lowmem(self, **args)

~/checkouts/readthedocs.org/user_builds/pypsa-docs-staging/envs/latest/lib/python3.7/site-packages/pypsa/opf.py in network_lopf(network, snapshots, solver_name, solver_io, skip_pre, extra_functionality, multi_investment_periods, solver_logfile, solver_options, keep_files, formulation, ptdf_tolerance, free_memory, extra_postprocessing)
   1663                               solver_logfile=solver_logfile, solver_options=solver_options,
   1664                               keep_files=keep_files, free_memory=free_memory,
-> 1665                               extra_postprocessing=extra_postprocessing)

~/checkouts/readthedocs.org/user_builds/pypsa-docs-staging/envs/latest/lib/python3.7/site-packages/pypsa/opf.py in network_lopf_solve(network, snapshots, formulation, solver_options, solver_logfile, keep_files, free_memory, extra_postprocessing)
   1563             network.results = network.opt.solve(*args, suffixes=["dual"], keepfiles=keep_files, logfile=solver_logfile, options=solver_options)
   1564     else:
-> 1565         network.results = network.opt.solve(*args, suffixes=["dual"], keepfiles=keep_files, logfile=solver_logfile, options=solver_options)
   1566
   1567     if logger.isEnabledFor(logging.INFO):

~/checkouts/readthedocs.org/user_builds/pypsa-docs-staging/envs/latest/lib/python3.7/site-packages/pyomo/opt/base/solvers.py in solve(self, *args, **kwds)
    510         """ Solve the problem """
    511
--> 512         self.available(exception_flag=True)
    513         #
    514         # If the inputs are models, then validate that they have been

~/checkouts/readthedocs.org/user_builds/pypsa-docs-staging/envs/latest/lib/python3.7/site-packages/pyomo/opt/solver/shellcmd.py in available(self, exception_flag)
    123             if exception_flag:
    124                 msg = "No executable found for solver '%s'"
--> 125                 raise ApplicationError(msg % self.name)
    126             return False
    127         return True

ApplicationError: No executable found for solver 'glpk'