Minimal three node network

Note

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

Minimal three node network#

Here, we are going to create a network with three nodes, three lines and one generator. We then solve the non-linear power flow using a Newton-Raphson.

[1]:
import numpy as np

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

Add three buses

[3]:
n_buses = 3

for i in range(n_buses):
    network.add("Bus", f"My bus {i}", v_nom=20.0)

network.buses
[3]:
v_nom type x y carrier unit v_mag_pu_set v_mag_pu_min v_mag_pu_max control generator sub_network
Bus
My bus 0 20.0 0.0 0.0 AC 1.0 0.0 inf PQ
My bus 1 20.0 0.0 0.0 AC 1.0 0.0 inf PQ
My bus 2 20.0 0.0 0.0 AC 1.0 0.0 inf PQ

Add three lines in a ring

[4]:
for i in range(n_buses):
    network.add(
        "Line",
        f"My line {i}",
        bus0=f"My bus {i}",
        bus1=f"My bus {(i + 1) % n_buses}",
        x=0.1,
        r=0.01,
    )

network.lines
[4]:
bus0 bus1 type x r g b s_nom s_nom_mod s_nom_extendable ... v_ang_min v_ang_max sub_network x_pu r_pu g_pu b_pu x_pu_eff r_pu_eff s_nom_opt
Line
My line 0 My bus 0 My bus 1 0.1 0.01 0.0 0.0 0.0 0.0 False ... -inf inf 0.0 0.0 0.0 0.0 0.0 0.0 0.0
My line 1 My bus 1 My bus 2 0.1 0.01 0.0 0.0 0.0 0.0 False ... -inf inf 0.0 0.0 0.0 0.0 0.0 0.0 0.0
My line 2 My bus 2 My bus 0 0.1 0.01 0.0 0.0 0.0 0.0 False ... -inf inf 0.0 0.0 0.0 0.0 0.0 0.0 0.0

3 rows × 31 columns

Add a generator at bus 0

[5]:
network.add("Generator", "My gen", bus="My bus 0", p_set=100, control="PQ")

network.generators
[5]:
bus control type p_nom p_nom_mod p_nom_extendable p_nom_min p_nom_max p_min_pu p_max_pu ... min_up_time min_down_time up_time_before down_time_before ramp_limit_up ramp_limit_down ramp_limit_start_up ramp_limit_shut_down weight p_nom_opt
Generator
My gen My bus 0 PQ 0.0 0.0 False 0.0 inf 0.0 1.0 ... 0 0 1 0 NaN NaN 1.0 1.0 1.0 0.0

1 rows × 37 columns

[6]:
network.generators.p_set
[6]:
Generator
My gen    100.0
Name: p_set, dtype: float64

Add a load at bus 1

[7]:
network.add("Load", "My load", bus="My bus 1", p_set=100)

network.loads
[7]:
bus carrier type p_set q_set sign active
Load
My load My bus 1 100.0 0.0 -1.0 True
[8]:
network.loads.p_set
[8]:
Load
My load    100.0
Name: p_set, dtype: float64

Fix the reactive power of the load

[9]:
network.loads.q_set = 100.0

Do a Newton-Raphson power flow

[10]:
network.pf()
INFO:pypsa.pf:Performing non-linear load-flow on AC sub-network <pypsa.networks.SubNetwork object at 0x7f3e7692fcb0> for snapshots Index(['now'], dtype='object', name='snapshot')
[10]:
{'n_iter': SubNetwork  0
 snapshot
 now         3,
 'error': SubNetwork             0
 snapshot
 now         4.753531e-10,
 'converged': SubNetwork     0
 snapshot
 now         True}

Alright, it converged! Now, what is the active power flow on the lines?

[11]:
network.lines_t.p0
[11]:
My line 0 My line 1 My line 2
snapshot
now 66.897487 -33.333333 -33.391038

…and what are the voltage angles on the buses?

[12]:
network.buses_t.v_ang * 180 / np.pi
[12]:
Bus My bus 0 My bus 1 My bus 2
snapshot
now 0.0 -0.875939 -0.433813

…and their mangitudes?

[13]:
network.buses_t.v_mag_pu
[13]:
Bus My bus 0 My bus 1 My bus 2
snapshot
now 1.0 0.981199 0.99057