pydae 0.53.6__py3-none-any.whl → 0.54.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pydae/__init__.py CHANGED
@@ -7,5 +7,5 @@ Differential Algebraic Equations in Python
7
7
 
8
8
  """
9
9
 
10
- __version__ = "0.53.6"
10
+ __version__ = "0.54.0"
11
11
 
@@ -0,0 +1,8 @@
1
+ """
2
+ ===========================
3
+ SVG Tools
4
+ ===========================
5
+
6
+ """
7
+
8
+ from pydae.svg_tools.svg_tools import svg
@@ -0,0 +1,369 @@
1
+
2
+ from xml.etree.ElementTree import Element
3
+ import numpy as np
4
+
5
+
6
+
7
+ def set_tooltips_v2(self, output_file):
8
+
9
+ s = self
10
+ grid = self.grid
11
+
12
+ for bus in s.grid_data['buses']:
13
+ bus_id = bus['name']
14
+ bus_elm_list = s.root.findall(f".//*[@id='{bus_id}']")
15
+ if len(bus_elm_list) > 0:
16
+ bus_elm = bus_elm_list[0]
17
+ else:
18
+ print(f'SVG element {bus_id} not found')
19
+ continue
20
+
21
+ if f"V_{bus['name']}_3_r" in grid.y_ini_list:
22
+ v_n_r,v_n_i = grid.get_mvalue([f"V_{bus['name']}_3_r",f"V_{bus['name']}_3_i"])
23
+ v_n = v_n_r + 1j*v_n_i
24
+ else:
25
+ v_n = 0.0
26
+ for ph,da in zip(['0','1','2'],['data1','data2','data3']):
27
+ V_r_id,V_i_id = f"V_{bus['name']}_{ph}_r",f"V_{bus['name']}_{ph}_i"
28
+ if V_r_id in grid.y_ini_list:
29
+ v_r,v_i = grid.get_mvalue([V_r_id,V_i_id])
30
+ v = v_r + 1j*v_i
31
+ v_m = np.abs(v-v_n)
32
+ if 'acdc' in bus:
33
+ v_base = bus['U_kV']*1000/2
34
+ else:
35
+ v_base = bus['U_kV']*1000/np.sqrt(3)
36
+ bus_elm.attrib[da] =f"{v_m:20.1f} V / {v_m/v_base:9.2f} pu "
37
+ bus_elm.attrib['data4'] =f"{np.abs(v_n):20.1f} V"
38
+ bus_elm.attrib['data0'] = 'bus'
39
+
40
+ p_load_a,q_load_a = -0.001,-0.001
41
+ p_load_b,q_load_b = -0.001,-0.001
42
+ p_load_c,q_load_c = -0.001,-0.001
43
+ p_load = 0.0
44
+ q_load = 0.0
45
+ if f"p_load_{bus_id}_a" in grid.u_ini_list: # ac load
46
+ p_load_a = grid.get_value(f"p_load_{bus_id}_a")
47
+ q_load_a = grid.get_value(f"q_load_{bus_id}_a")
48
+ p_load_b = grid.get_value(f"p_load_{bus_id}_b")
49
+ q_load_b = grid.get_value(f"q_load_{bus_id}_b")
50
+ p_load_c = grid.get_value(f"p_load_{bus_id}_c")
51
+ q_load_c = grid.get_value(f"q_load_{bus_id}_c")
52
+ p_load = p_load_a + p_load_b + p_load_c
53
+ q_load = q_load_a + q_load_b + q_load_c
54
+ if f"p_load_{bus_id}" in grid.u_ini_list: # dc load
55
+ p_load = grid.get_value(f"p_load_{bus_id}")
56
+ q_load = 0.0
57
+
58
+ bus_elm.attrib['data5'] =f"{p_load/1e3:20.1f} kW"
59
+ bus_elm.attrib['data6'] =f"{q_load/1e3:20.1f} kvar"
60
+ bus_elm.attrib['data7'] ="xx"
61
+
62
+ bus_elm.attrib['class'] = 'tooltip-trigger'
63
+
64
+ for line in s.grid_data['lines']:
65
+
66
+ bus_j = line['bus_j']
67
+ bus_k = line['bus_k']
68
+
69
+ for ph in ['0','1','2','3']:
70
+
71
+ line_id = f'l_{bus_j}_{ph}_{bus_k}_{ph}'
72
+ line_svg = s.root.findall(f".//*[@id='{line_id}']")
73
+ if len(line_svg)>0:
74
+ line_elm = line_svg[0]
75
+ else:
76
+ continue
77
+ line_elm.attrib['data0'] = 'line'
78
+
79
+ for phi,da in zip(['0','1','2','3'],['data1','data2','data3','data4']):
80
+ meas_line_id = f'l_{bus_j}_{phi}_{bus_k}_{phi}'
81
+
82
+ i_m = 0.0
83
+
84
+ if f'i_{meas_line_id}_r' in grid.outputs_list:
85
+ i_r,i_i = grid.get_mvalue([f"i_{meas_line_id}_r",f"i_{meas_line_id}_i"])
86
+ i = i_r + 1j*i_i
87
+ i_m = np.abs(i)
88
+ v_base = 1.0
89
+ line_elm.attrib[da] =f"{i_m:20.1f} A / {i_m/v_base:9.2f} pu "
90
+
91
+ line_elm.attrib['class'] = 'tooltip-trigger'
92
+
93
+ if 'transformers' in s.grid_data:
94
+ for trafo in s.grid_data['transformers']:
95
+
96
+ bus_j = trafo['bus_j']
97
+ bus_k = trafo['bus_k']
98
+
99
+ for wind in [1,2]:
100
+ trafo_id = f'trafo_{bus_j}_{bus_k}_{wind}'
101
+
102
+ trafo_svg = s.root.findall(f".//*[@id='{trafo_id}']")
103
+ if len(trafo_svg)>0:
104
+ trafo_elm = trafo_svg[0]
105
+ else:
106
+ print(f'No trafo {trafo_id} found')
107
+ continue
108
+
109
+ trafo_elm.attrib['data0'] = 'trafo'
110
+
111
+
112
+ z2a = {'0':'a','1':'b','2':'c','3':'n'}
113
+ string_1 = ''
114
+ for ph in ['0','1','2']:
115
+ i_r_id = f'i_t_{bus_j}_{bus_k}_1_{ph}_r'
116
+ i_i_id = f'i_t_{bus_j}_{bus_k}_1_{ph}_i'
117
+ if i_r_id in grid.outputs_list:
118
+ i_r,i_i = grid.get_mvalue([i_r_id,i_i_id])
119
+ i = i_r + 1j*i_i
120
+ i_m = np.abs(i)
121
+ string_1 += f'{z2a[ph]}: {i_m:0.2f}\t '
122
+
123
+ string_2 = ''
124
+ for ph in ['0','1','2','3']:
125
+ i_r_id = f'i_t_{bus_j}_{bus_k}_2_{ph}_r'
126
+ i_i_id = f'i_t_{bus_j}_{bus_k}_2_{ph}_i'
127
+ if i_r_id in grid.outputs_list:
128
+ i_r,i_i = grid.get_mvalue([i_r_id,i_i_id])
129
+ i = i_r + 1j*i_i
130
+ i_m = np.abs(i)
131
+ string_2 += f'{z2a[ph]}: {i_m:0.2f} '
132
+
133
+ trafo_elm.attrib['data1'] = string_1 + ' A'
134
+ trafo_elm.attrib['data2'] = string_2 + ' A'
135
+ trafo_elm.attrib['data3'] = ''
136
+ trafo_elm.attrib['data4'] = ''
137
+ trafo_elm.attrib['class'] = 'tooltip-trigger'
138
+
139
+ if 'vscs' in self.grid_data:
140
+ vscs_list = self.grid_data['vscs']
141
+ else:
142
+ vscs_list = []
143
+
144
+ for vsc in vscs_list:
145
+
146
+ if not 'bus_ac' in vsc: continue
147
+
148
+ bus_ac = vsc['bus_ac']
149
+ bus_dc = vsc['bus_dc']
150
+ vsc_id = f'vsc_{bus_ac}_{bus_dc}'
151
+
152
+ vsc_svg = s.root.findall(f".//*[@id='{vsc_id}']")
153
+ if len(vsc_svg)>0:
154
+ vsc_elm = vsc_svg[0]
155
+ else:
156
+ print(f'No VSC {vsc_id} found')
157
+ continue
158
+ vsc_elm.attrib['data0'] = 'vsc'
159
+ p_dc = grid.get_value(f'p_vsc_{bus_dc}')
160
+ vsc_elm.attrib['data1'] = 'VSC'
161
+
162
+ p_ac = grid.get_value(f'p_vsc_{bus_ac}')
163
+ p_dc = grid.get_value(f'p_vsc_{bus_dc}')
164
+ vsc_elm.attrib['data2'] = f' Pac = {p_ac/1e3:0.1f} kW, Pdc = {p_dc/1e3:0.1f} kW'
165
+
166
+ p_loss = grid.get_value(f'p_vsc_loss_{bus_ac}')
167
+ vsc_elm.attrib['data3'] = f' Losses = {p_loss/1e3:0.1f} kW'
168
+
169
+ vsc_elm.attrib['class'] = 'tooltip-trigger'
170
+
171
+ script = '''
172
+ <![CDATA[
173
+ (function() {
174
+ var svg = document.getElementById('document_id');
175
+ var tooltip_1 = svg.getElementById('tooltip1');
176
+ var tooltipText_1_1 = tooltip_1.getElementsByTagName('text')[0];
177
+ var tooltipText_1_2 = tooltip_1.getElementsByTagName('text')[1];
178
+ var tooltipText_1_3 = tooltip_1.getElementsByTagName('text')[2];
179
+ var tooltipText_1_4 = tooltip_1.getElementsByTagName('text')[3];
180
+ var tooltipText_1_5 = tooltip_1.getElementsByTagName('text')[4];
181
+ var tooltipText_1_6 = tooltip_1.getElementsByTagName('text')[5];
182
+ var tooltip_2 = svg.getElementById('tooltip2');
183
+ var tooltipText_2_1 = tooltip_2.getElementsByTagName('text')[0];
184
+ var tooltipText_2_2 = tooltip_2.getElementsByTagName('text')[1];
185
+ var tooltipText_2_3 = tooltip_2.getElementsByTagName('text')[2];
186
+ var tooltipText_2_4 = tooltip_2.getElementsByTagName('text')[3];
187
+ var tooltipText_2_5 = tooltip_2.getElementsByTagName('text')[4];
188
+ var tooltipText_2_6 = tooltip_2.getElementsByTagName('text')[5];
189
+ var tooltip_3 = svg.getElementById('tooltip3');
190
+ var tooltipText_3_1 = tooltip_3.getElementsByTagName('text')[0];
191
+ var tooltipText_3_2 = tooltip_3.getElementsByTagName('text')[1];
192
+ var tooltipText_3_3 = tooltip_3.getElementsByTagName('text')[2];
193
+ var tooltipText_3_4 = tooltip_3.getElementsByTagName('text')[3];
194
+
195
+ var tooltipRects = tooltip_1.getElementsByTagName('rect');
196
+ var triggers = svg.getElementsByClassName('tooltip-trigger');
197
+ for (var i = 0; i < triggers.length; i++) {
198
+ triggers[i].addEventListener('mousemove', showTooltip);
199
+ triggers[i].addEventListener('mouseout', hideTooltip);
200
+ }
201
+ function showTooltip(evt) {
202
+ var CTM = svg.getScreenCTM();
203
+ var x_unsat = (evt.clientX - CTM.e) / CTM.a
204
+ var x = x_unsat;
205
+ if (x_unsat>x_max) {var x = x_max}
206
+ if (x_unsat<x_min) {var x = x_min}
207
+
208
+
209
+ var y_unsat = (evt.clientY - CTM.f) / CTM.d + 30;
210
+ var y = y_unsat;
211
+ if (y_unsat>y_max) {var y = y_max - y_height}
212
+
213
+
214
+ if (evt.target.getAttributeNS(null, "data0") == "bus") {
215
+ tooltip_1.setAttributeNS(null, "transform", "translate(" + x + " " + y + ")");
216
+ tooltip_1.setAttributeNS(null, "visibility", "visible")}
217
+
218
+ if (evt.target.getAttributeNS(null, "data0") == "line") {
219
+ tooltip_2.setAttributeNS(null, "transform", "translate(" + x + " " + y + ")");
220
+ tooltip_2.setAttributeNS(null, "visibility", "visible")}
221
+
222
+ if (evt.target.getAttributeNS(null, "data0") == "vsc") {
223
+ tooltip_3.setAttributeNS(null, "transform", "translate(" + x + " " + y + ")");
224
+ tooltip_3.setAttributeNS(null, "visibility", "visible")}
225
+
226
+ if (evt.target.getAttributeNS(null, "data0") == "trafo") {
227
+ tooltip_3.setAttributeNS(null, "transform", "translate(" + x + " " + y + ")");
228
+ tooltip_3.setAttributeNS(null, "visibility", "visible")}
229
+
230
+ tooltipText_1_1.firstChild.data = evt.target.getAttributeNS(null, "data1");
231
+ tooltipText_1_2.firstChild.data = evt.target.getAttributeNS(null, "data2");
232
+ tooltipText_1_3.firstChild.data = evt.target.getAttributeNS(null, "data3");
233
+ tooltipText_1_4.firstChild.data = evt.target.getAttributeNS(null, "data4");
234
+ tooltipText_1_5.firstChild.data = evt.target.getAttributeNS(null, "data5");
235
+ tooltipText_1_6.firstChild.data = evt.target.getAttributeNS(null, "data6");
236
+
237
+ tooltipText_2_1.firstChild.data = evt.target.getAttributeNS(null, "data1");
238
+ tooltipText_2_2.firstChild.data = evt.target.getAttributeNS(null, "data2");
239
+ tooltipText_2_3.firstChild.data = evt.target.getAttributeNS(null, "data3");
240
+ tooltipText_2_4.firstChild.data = evt.target.getAttributeNS(null, "data4");
241
+ tooltipText_2_5.firstChild.data = evt.target.getAttributeNS(null, "data5");
242
+ tooltipText_2_6.firstChild.data = evt.target.getAttributeNS(null, "data6");
243
+
244
+ tooltipText_3_1.firstChild.data = evt.target.getAttributeNS(null, "data1");
245
+ tooltipText_3_2.firstChild.data = evt.target.getAttributeNS(null, "data2");
246
+ tooltipText_3_3.firstChild.data = evt.target.getAttributeNS(null, "data3");
247
+ tooltipText_3_4.firstChild.data = evt.target.getAttributeNS(null, "data4");
248
+
249
+ var length = tooltipText_1_1.getComputedTextLength()+200;
250
+ for (var i = 0; i < tooltipRects.length; i++) {
251
+ tooltipRects[i].setAttributeNS(null, "width", length + 8);
252
+ }
253
+ }
254
+ function hideTooltip(evt) {
255
+ tooltip_1.setAttributeNS(null, "visibility", "hidden");
256
+ tooltip_2.setAttributeNS(null, "visibility", "hidden");
257
+ tooltip_3.setAttributeNS(null, "visibility", "hidden");
258
+ }
259
+ })()
260
+ ]]>'''
261
+
262
+
263
+
264
+ element = Element('script')
265
+ element.attrib['type'] ="text/ecmascript"
266
+ element.attrib['id'] = "script15"
267
+ element.text = 'scriptplace'
268
+ self.root.append(element)
269
+
270
+ set_lines_currents_v2(self)
271
+ set_buses_voltages_v2(self)
272
+
273
+ out = self.tostring().replace('scriptplace',script)
274
+ width = float(self.root.attrib['width'])
275
+ height = float(self.root.attrib['height'])
276
+ document_id = self.root.attrib['id']
277
+
278
+ tooltip_width = 320
279
+ tooltip_height = 100
280
+
281
+ out=out.replace('x_max',f'{width-tooltip_width/2}' )
282
+ out=out.replace('x_min',f'{tooltip_width/2}' )
283
+ out=out.replace('y_max',f'{height-tooltip_height}' )
284
+ out=out.replace('y_height',f'{tooltip_height}' )
285
+ out=out.replace('document_id', document_id)
286
+
287
+ with open(output_file,'w') as fobj:
288
+ fobj.write(out)
289
+
290
+ def set_lines_currents_v2(self):
291
+
292
+ for line in self.grid_data['lines']:
293
+ #if not 'monitor'in line or not 'vsc_line' in line: continue
294
+ if 'monitor' in line:
295
+ if not line['monitor']: continue
296
+ if 'vsc_line' in line:
297
+ if not line['vsc_line']: continue
298
+
299
+ bus_j = line['bus_j']
300
+ bus_k = line['bus_k']
301
+
302
+ z2a = {'0':'a','1':'b','2':'c','3':'n'}
303
+ for ph in ['0','1','2','3']:
304
+ line_id = f'l_{bus_j}_{ph}_{bus_k}_{ph}'
305
+ if f'i_{line_id}_r' in self.grid.outputs_list:
306
+ if 'code' in line:
307
+ I_max = self.grid_data["line_codes"][line['code']]['I_max']
308
+ else:
309
+ I_max = line['I_max']
310
+
311
+
312
+ i_r = self.grid.get_value(f'i_{line_id}_r')
313
+ i_i = self.grid.get_value(f'i_{line_id}_i')
314
+ i = i_r + 1j*i_i
315
+ i_abs = np.abs(i)
316
+ #print(f'l_{bus_j}_{bus_k}_{ph} = {i_abs:8.1f} A')
317
+ if i_abs < 1e-3: continue
318
+ i_sat = np.clip((i_abs/I_max)**2*255,0,255)
319
+ self.set_color('line',line_id,(int(i_sat),0,0))
320
+
321
+ def set_buses_voltages_v2(self):
322
+
323
+ v_ac_min = 20e6
324
+ min_dc_voltage = 20e6
325
+ min_n_ac_voltage = 20e6
326
+ min_n_dc_voltage = 20e6
327
+
328
+ v_ac_max = 0
329
+ max_dc_voltage = 0
330
+ max_n_ac_voltage = 0
331
+ max_n_dc_voltage = 0
332
+
333
+
334
+ for bus in self.grid_data['buses']:
335
+ v_r = self.grid.get_value(f'V_{bus["name"]}_0_r')
336
+ v_i = self.grid.get_value(f'V_{bus["name"]}_0_i')
337
+ v = v_r + 1j*v_i
338
+ v_abs = np.abs(v)
339
+ V_med_pu= 0.5*(self.V_max_pu + self.V_min_pu)
340
+ acdc = 'ac'
341
+ if 'acdc' in bus:
342
+ if bus['acdc'] == 'DC':
343
+ V_nom = bus['U_kV']*1000/2
344
+ acdc = 'dc'
345
+ if bus['acdc'] == 'AC':
346
+ V_nom = bus['U_kV']/np.sqrt(3)*1000
347
+ acdc = 'ac'
348
+ else:
349
+ V_nom = bus['U_kV']/np.sqrt(3)*1000
350
+ acdc = 'ac'
351
+
352
+ V_pu = v_abs/V_nom
353
+
354
+ # when V_pu = V_med_pu color = 0, when V_pu = V_max_pu color = 255 (red)
355
+ # when V_pu = V_med_pu color = 0, when V_pu = V_min_pu color = 255 (blue)
356
+ if V_pu < V_med_pu:
357
+ blue = np.clip(255*((V_pu - V_med_pu)/(self.V_min_pu - V_med_pu))**2,0,255)
358
+ self.set_color('rect',f'{bus["name"]}',(0,0,int(blue)))
359
+ if V_pu > V_med_pu:
360
+ red = np.clip(255*((V_pu - V_med_pu)/(self.V_max_pu - V_med_pu))**2,0,255)
361
+ self.set_color('rect',f'{bus["name"]}',(int(red),0,0))
362
+
363
+ if acdc == 'ac':
364
+ if V_pu < v_ac_min:
365
+ self.post_data.update({'v_ac_min':{'bus':bus['name'],'value':V_pu}})
366
+ v_ac_min = V_pu
367
+ if V_pu > v_ac_max:
368
+ self.post_data.update({'v_ac_max':{'bus':bus['name'],'value':V_pu}})
369
+ v_ac_max = V_pu