[1]:
import numpy as np
from bokeh.io import output_notebook, show
from bokeh.plotting import figure
from bokeh.layouts import gridplot
from bokeh.models import ColumnDataSource, HoverTool, CustomJS
from bokeh.io import push_notebook
from ipywidgets import interact
from scipy.interpolate import Rbf
output_notebook()
[2]:
from pydgrid.pydgrid import grid
CIGRE LV European System¶
Contour plot for voltages using Bokeh¶
[3]:
sys1 = grid()
sys1.read('cigre_europe_residential.json') # Load data
sys1.pf()
sys1.get_v() # post process voltages
sys1.get_i() # post process currents
V_an = np.array([item['v_an']/item['U_kV']/1000*np.sqrt(3) for item in sys1.buses])
V_bn = np.array([item['v_bn']/item['U_kV']/1000*np.sqrt(3) for item in sys1.buses])
V_cn = np.array([item['v_cn']/item['U_kV']/1000*np.sqrt(3) for item in sys1.buses])
Pos_x = np.array([item['pos_x'] for item in sys1.buses])
Pos_y = np.array([item['pos_y'] for item in sys1.buses])
x_min = np.min(Pos_x)
x_max = np.max(Pos_x)
y_min = np.min(Pos_y)
y_max = np.max(Pos_y)
x_margin = 150
y_margin = 100
x_min2 = x_min-x_margin
x_max2 = x_max+x_margin
y_min2 = y_min-y_margin
y_max2 = y_max+y_margin
Pos_x_e = np.hstack((x_min2, x_min2, Pos_x, x_max2, x_max2))
Pos_y_e = np.hstack((y_min2, y_max2, Pos_y, y_max2, y_min2))
V_an_e = np.hstack((1,1, V_an, 1,1))
V_bn_e = np.hstack((1,1, V_bn, 1,1))
V_cn_e = np.hstack((1,1, V_cn, 1,1))
rbfi_a = Rbf(Pos_x_e, Pos_y_e, V_an_e, function='linear')
rbfi_b = Rbf(Pos_x_e, Pos_y_e, V_bn_e)
rbfi_c = Rbf(Pos_x_e, Pos_y_e, V_cn_e)
x = np.linspace(x_min2,x_max2, 500)
y = np.linspace(y_min2,y_max2, 500)
X, Y = np.meshgrid(x, y)
Z_a = rbfi_a(X, Y)
Z_b = rbfi_b(X, Y)
Z_c = rbfi_c(X, Y)
Graph with obtained results¶
[4]:
sys1.s_radio_scale = 0.1
sys1.s_radio_min = 5.0
sys1.bokeh_tools()
p = figure(width=600, height=800,
title='European LV Network (CIGRE)', x_range=[-150,150], y_range=[-350, 50])
p.image(image=[Z_a], x=x_min2, y=y_min2, dw=(x_max2-x_min2), dh=(y_max2-y_min2), palette="Spectral11")
# lines:
source = ColumnDataSource(sys1.line_data)
lin = p.multi_line(source=source, xs='x_s', ys='y_s', color="red", alpha=1, line_width=5)
# buses:
source = ColumnDataSource(sys1.bus_data)
cr = p.circle(source=source, x='x', y='y', size='s_radio', color='s_color', alpha=1)
p.add_tools(HoverTool(renderers=[lin], tooltips=sys1.line_tooltip))
p.add_tools(HoverTool(renderers=[cr], tooltips=sys1.bus_tooltip))
show(p)
Interaction with powers¶
[5]:
sys1.read('cigre_europe_residential.json') # Load data
sys1.pf()
sys1.get_v() # post process voltages
sys1.get_i() # post process currents
s_0_3pn = np.copy(sys1.pq_3pn) #
s_0_1p = np.copy(sys1.pq_1p) #
sys1.bokeh_tools()
p = figure(width=800, height=400,
title='Voltage vs load powers',
x_range = [40,-350], y_range = [180,250],
x_axis_label='Distance (m)',
y_axis_label='Voltage (V)')
source = ColumnDataSource(sys1.bus_data)
cr = p.circle(source=source, x='y', y='v_an', size=15, color="red", alpha=0.5)
p.circle(source=source, x='y', y='v_bn', size=15, color="green", alpha=0.5)
p.circle(source=source, x='y', y='v_cn', size=15, color="blue", alpha=0.5)
p.line([-400,300],[231*1.05,231*1.05], color='red', line_width=5)
p.line([-400,300],[231*0.90,231*0.90], color='blue', line_width=5)
#p.add_tools(HoverTool(renderers=[cr], tooltips=sys1.bus_tooltip))
def update_loads(load_factor=1.0):
sys1.pq_1p = load_factor*s_0_1p
sys1.pq_3pn = np.copy(load_factor*s_0_3pn)
sys1.set_pf()
sys1.pf()
sys1.get_v()
sys1.get_i()
#sys1.bokeh_tools()
v_an_m = np.abs(sys1.V_node[sys1.node_1_sorter])
v_bn_m = np.abs(sys1.V_node[sys1.node_2_sorter])
v_cn_m = np.abs(sys1.V_node[sys1.node_3_sorter])
sys1.bus_data['v_an'] = v_an_m
sys1.bus_data['v_bn'] = v_bn_m
sys1.bus_data['v_cn'] = v_cn_m
source.data = sys1.bus_data
push_notebook()
#p_grid = gridplot([[p], [p_2]])
show(p, notebook_handle=True)
[5]:
<Bokeh Notebook handle for In[5]>
[6]:
from ipywidgets import interact
interact(update_loads, load_factor=(-1,1.2, 0.1))
[6]:
<function __main__.update_loads(load_factor=1.0)>
Analysis using Pandas¶
[7]:
import pandas as pd
[8]:
df = pd.DataFrame()
df['nodes'] = sys1.nodes
df['I_node_m'] = np.abs(sys1.I_node)
df['V_node_m'] = np.abs(sys1.V_node)
#df['phi'] = np.angle(sys1.I_node, deg=True) - np.angle(sys1.V_node, deg=True)
s = np.conjugate(sys1.I_node)*sys1.V_node
df['p_kW'] = s.real/1000
df['q_kVA'] = s.imag/1000
df
[8]:
nodes | I_node_m | V_node_m | p_kW | q_kVA | |
---|---|---|---|---|---|
0 | R0.1 | 12.279686 | 11547.000000 | 133.228235 | 48.534983 |
1 | R0.2 | 12.194776 | 11547.000000 | 132.224879 | 48.424213 |
2 | R0.3 | 12.219433 | 11547.000000 | 132.822486 | 47.610666 |
3 | R1.1 | 294.305597 | 226.183736 | -63.206394 | -20.883865 |
4 | R1.2 | 294.318022 | 226.377454 | -63.338571 | -20.673117 |
5 | R1.3 | 294.268246 | 227.024469 | -63.455017 | -20.892937 |
6 | R1.4 | 0.129777 | 0.488038 | -0.000018 | -0.000061 |
7 | R11.1 | 22.619924 | 221.082177 | -4.751117 | -1.560611 |
8 | R11.2 | 22.542696 | 221.818706 | -4.749990 | -1.562532 |
9 | R11.3 | 22.431808 | 222.842141 | -4.748898 | -1.560605 |
10 | R11.4 | 0.111885 | 0.056907 | 0.000006 | -0.000001 |
11 | R15.1 | 82.678522 | 210.089330 | -16.512848 | -5.388732 |
12 | R15.2 | 82.063130 | 211.381109 | -16.463661 | -5.463720 |
13 | R15.3 | 81.216693 | 212.814945 | -16.424028 | -5.384451 |
14 | R15.4 | 0.869274 | 0.627272 | 0.000537 | -0.000093 |
15 | R16.1 | 85.643246 | 214.560691 | -17.470587 | -5.695963 |
16 | R16.2 | 84.972116 | 215.951166 | -17.414043 | -5.785090 |
17 | R16.3 | 84.050216 | 217.432385 | -17.366033 | -5.692562 |
18 | R16.4 | 0.947507 | 0.712773 | 0.000663 | -0.000129 |
19 | R17.1 | 55.050752 | 212.626217 | -11.132419 | -3.616867 |
20 | R17.2 | 54.506010 | 214.317220 | -11.080836 | -3.697878 |
21 | R17.3 | 53.767616 | 216.004660 | -11.037499 | -3.613848 |
22 | R17.4 | 0.762900 | 1.009420 | 0.000755 | -0.000153 |
23 | R18.1 | 74.293759 | 211.633036 | -14.954995 | -4.853998 |
24 | R18.2 | 73.514087 | 213.405120 | -14.879548 | -4.972049 |
25 | R18.3 | 72.461012 | 215.150835 | -14.816623 | -4.849461 |
26 | R18.4 | 1.089448 | 1.091264 | 0.001165 | -0.000237 |
27 | R2.1 | 0.000000 | 223.960103 | 0.000000 | -0.000000 |
28 | R2.2 | 0.000000 | 224.415535 | -0.000000 | 0.000000 |
29 | R2.3 | 0.000000 | 225.243290 | 0.000000 | 0.000000 |
... | ... | ... | ... | ... | ... |
45 | R6.3 | 0.000000 | 219.425766 | 0.000000 | 0.000000 |
46 | R6.4 | 0.000000 | 0.634712 | 0.000000 | -0.000000 |
47 | R7.1 | 0.000000 | 215.787875 | 0.000000 | -0.000000 |
48 | R7.2 | 0.000000 | 217.212013 | -0.000000 | 0.000000 |
49 | R7.3 | 0.000000 | 218.710282 | 0.000000 | 0.000000 |
50 | R7.4 | 0.000000 | 0.741778 | 0.000000 | -0.000000 |
51 | R8.1 | 0.000000 | 214.889967 | 0.000000 | -0.000000 |
52 | R8.2 | 0.000000 | 216.422120 | -0.000000 | 0.000000 |
53 | R8.3 | 0.000000 | 217.994913 | 0.000000 | 0.000000 |
54 | R8.4 | 0.000000 | 0.848844 | 0.000000 | -0.000000 |
55 | R9.1 | 0.000000 | 213.992505 | 0.000000 | -0.000000 |
56 | R9.2 | 0.000000 | 215.631806 | -0.000000 | 0.000000 |
57 | R9.3 | 0.000000 | 217.279749 | 0.000000 | 0.000000 |
58 | R9.4 | 0.000000 | 0.956068 | 0.000000 | -0.000000 |
59 | R10.1 | 0.000000 | 213.476942 | 0.000000 | -0.000000 |
60 | R10.2 | 0.000000 | 215.178180 | -0.000000 | 0.000000 |
61 | R10.3 | 0.000000 | 216.869265 | 0.000000 | 0.000000 |
62 | R10.4 | 0.000000 | 1.017707 | 0.000000 | -0.000000 |
63 | R12.1 | 0.000000 | 217.273533 | 0.000000 | -0.000000 |
64 | R12.2 | 0.000000 | 218.317615 | -0.000000 | 0.000000 |
65 | R12.3 | 0.000000 | 219.559931 | 0.000000 | 0.000000 |
66 | R12.4 | 0.000000 | 0.367154 | 0.000000 | -0.000000 |
67 | R13.1 | 0.000000 | 214.877482 | 0.000000 | -0.000000 |
68 | R13.2 | 0.000000 | 216.004358 | -0.000000 | 0.000000 |
69 | R13.3 | 0.000000 | 217.310579 | 0.000000 | 0.000000 |
70 | R13.4 | 0.000000 | 0.453609 | 0.000000 | -0.000000 |
71 | R14.1 | 0.000000 | 212.482806 | 0.000000 | -0.000000 |
72 | R14.2 | 0.000000 | 213.692088 | -0.000000 | 0.000000 |
73 | R14.3 | 0.000000 | 215.062258 | 0.000000 | 0.000000 |
74 | R14.4 | 0.000000 | 0.540432 | 0.000000 | -0.000000 |
75 rows × 5 columns