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 |