pydae 0.56.4__py3-none-any.whl → 0.57__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/build_v2.py CHANGED
@@ -30,7 +30,7 @@ from cffi import FFI
30
30
 
31
31
  class builder():
32
32
 
33
- def __init__(self,sys,verbose=False):
33
+ def __init__(self,sys,verbose=False,API=False):
34
34
 
35
35
  logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO)
36
36
 
@@ -40,11 +40,12 @@ class builder():
40
40
  self.name = self.sys['name']
41
41
  self.save_sources = False
42
42
  self.string_u2z = ''
43
- self.u2z = '\#'
43
+ self.u2z = r'#'
44
44
  self.inirun = True
45
45
  self.sparse = False
46
46
  self.mkl = False
47
47
  self.platform = 'Windows'
48
+ self.API = API
48
49
 
49
50
 
50
51
  if not os.path.exists('build'):
@@ -118,7 +119,8 @@ class builder():
118
119
  x = sym.Matrix(sys['x_list']).T
119
120
  y_ini = sym.Matrix(sys['y_ini_list']).T
120
121
  y_run = sym.Matrix(sys['y_run_list']).T
121
- u_ini = sym.Matrix(list(sys['u_ini_dict'].keys()), real=True)
122
+ u_ini_list = [sym.Symbol(item,real=True) for item in list(sys['u_ini_dict'].keys())]
123
+ u_ini = sym.Matrix(u_ini_list).T
122
124
  u_run_list = [sym.Symbol(item,real=True) for item in list(sys['u_run_dict'].keys())]
123
125
  u_run = sym.Matrix(u_run_list).T
124
126
  h = sym.Matrix(list(sys['h_dict'].values())).T
@@ -802,7 +804,10 @@ class builder():
802
804
  if self.mkl:
803
805
  class_template = pkgutil.get_data(__name__, "templates/class_dae_template_v2_mkl.py").decode().replace('\r\n','\n')
804
806
  else:
805
- class_template = pkgutil.get_data(__name__, "templates/class_dae_template_v2.py").decode().replace('\r\n','\n')
807
+ if self.API:
808
+ class_template = pkgutil.get_data(__name__, "templates/class_dae_template_api.py").decode().replace('\r\n','\n')
809
+ else:
810
+ class_template = pkgutil.get_data(__name__, "templates/class_dae_template_v2.py").decode().replace('\r\n','\n')
806
811
  if self.uz_jacs:
807
812
  uz_jacs_template = pkgutil.get_data(__name__, "templates/uz_jacs_v2.py").decode().replace('\r\n','\n')
808
813
  class_template += uz_jacs_template
@@ -1341,9 +1346,11 @@ def sym2xyup_mp(sys,full_list,inirun):
1341
1346
  logging.debug('end full_list update with xyup and tipo')
1342
1347
 
1343
1348
 
1344
- def build_numba(sys_dict,verbose=False):
1349
+ def build_numba(sys_dict,verbose=False, API=False):
1350
+
1351
+ from pydae.build_v2 import builder
1345
1352
 
1346
- b = builder(sys_dict,verbose=verbose)
1353
+ b = builder(sys_dict,verbose=True,API=API)
1347
1354
  b.sparse = False
1348
1355
  b.mkl = False
1349
1356
  b.uz_jacs = False
@@ -1354,6 +1361,8 @@ def build_numba(sys_dict,verbose=False):
1354
1361
  b.template()
1355
1362
  b.compile()
1356
1363
 
1364
+
1365
+
1357
1366
  def build_mkl(sys_dict,verbose=False,platform='Windows'):
1358
1367
  '''
1359
1368
 
@@ -1376,20 +1385,22 @@ def build_mkl(sys_dict,verbose=False,platform='Windows'):
1376
1385
  def test_numba():
1377
1386
 
1378
1387
  from pydae.models.pendulum.dae import dae
1379
- from pydae.build_v2 import builder
1388
+ from pydae.build_v2 import builder,build_numba
1380
1389
 
1381
1390
  sys_dict = dae('temp')
1382
1391
 
1383
- b = builder(sys_dict,verbose=True)
1384
- b.sparse = False
1385
- b.mkl = False
1386
- b.uz_jacs = False
1387
- b.dict2system()
1388
- b.functions()
1389
- b.jacobians()
1390
- b.cwrite()
1391
- b.template()
1392
- b.compile()
1392
+ build_numba(sys_dict,verbose=True)
1393
+
1394
+ # b = builder(sys_dict,verbose=True)
1395
+ # b.sparse = False
1396
+ # b.mkl = False
1397
+ # b.uz_jacs = False
1398
+ # b.dict2system()
1399
+ # b.functions()
1400
+ # b.jacobians()
1401
+ # b.cwrite()
1402
+ # b.template()
1403
+ # b.compile()
1393
1404
 
1394
1405
  import temp
1395
1406
 
@@ -1471,4 +1482,4 @@ def test_mkl():
1471
1482
 
1472
1483
  if __name__ == "__main__":
1473
1484
 
1474
- test_mkl()
1485
+ test_numba()
@@ -0,0 +1,106 @@
1
+ ### GET measures. Devuelve todas las medidas del POI y de los inversores
2
+ GET http://127.100.0.1:8000/measurements
3
+ Content-Type: application/json
4
+
5
+ ### GET measures. Devuelve todas las medidas del POI y de los inversores
6
+ GET http://10.20.0.2:5500/ppc_measurements
7
+ Content-Type: application/json
8
+
9
+ ### GET measures. Devuelve todas las medidas del POI y de los inversores
10
+ GET http://10.20.0.4:5500/ppc_measurements
11
+ Content-Type: application/json
12
+
13
+
14
+ ### POST setpoints. POST request to change PPC references.
15
+ POST http://127.0.0.1:5500/ppc_setpoints
16
+ Content-Type: application/json
17
+
18
+ {
19
+ "p_ol_ref":0.0,
20
+ "q_ol_ref":0.0,
21
+ "p_s_ref_BESS":0.0
22
+ }
23
+
24
+
25
+
26
+ ### POST false measurement liner transformations parameters .
27
+ POST http://127.100.0.1:8000/meas_pert
28
+ Content-Type: application/json
29
+
30
+ {
31
+ "U_SS1":{"m":0.5,"b":0}
32
+ }
33
+
34
+
35
+
36
+ ### POST setpoints. POST request to change active and reactive power references at POI.
37
+ POST http://10.20.0.2:8000/setpoints
38
+ Content-Type: application/json
39
+
40
+ {
41
+ "p_ol_ref":0.5,
42
+ "q_ol_ref":0.5,
43
+ "p_s_ref_BESS":0.0
44
+ }
45
+
46
+
47
+ ### POST setpoints. POST request to change active and reactive power references at POI.
48
+ POST http://10.20.0.2:8000/setpoints
49
+ Content-Type: application/json
50
+
51
+ {
52
+ "p_s_ppc_LV0101":1.5e6,
53
+ "p_s_ppc_LV0102":01.5e6,
54
+ "p_s_ref_BESS":0.0
55
+ }
56
+
57
+
58
+
59
+
60
+ ### POST setpoints. POST request to change PPC references.
61
+ POST http://127.0.0.1:5500/ppc_setpoints
62
+ Content-Type: application/json
63
+
64
+ {
65
+ "record":true
66
+ }
67
+
68
+
69
+
70
+ ### POST setpoints. POST request to change PPC references.
71
+ POST http://127.0.0.1:5500/ppc_setpoints
72
+ Content-Type: application/json
73
+
74
+ {
75
+ "P_POI_ref":0.5,
76
+ "Q_POI_ref":-0.9
77
+ }
78
+
79
+ ### POST setpoints. POST request to change PPC references.
80
+ POST http://127.0.0.1:5500/ppc_setpoints
81
+ Content-Type: application/json
82
+
83
+ {
84
+ "record":false
85
+ }
86
+
87
+
88
+ ### POST setpoints. POST request to change PPC references.
89
+ POST http://127.0.0.1:5500/ppc_setpoints
90
+ Content-Type: application/json
91
+
92
+ {
93
+ "stop_ppc":true
94
+ }
95
+
96
+
97
+ ### POST setpoints. POST request to change PPC references.
98
+ POST http://127.0.0.1:5500/ppc_params
99
+ Content-Type: application/json
100
+
101
+ {
102
+ "K_pp":0.5,
103
+ "K_pi":5.0,
104
+ "K_qp":0.5,
105
+ "K_qi":5.0
106
+ }
@@ -0,0 +1,107 @@
1
+ import numpy as np
2
+ import sympy as sym
3
+
4
+
5
+ def dae(model_name):
6
+ L,G,M,K_d = sym.symbols('L,G,M,K_d', real=True)
7
+ p_x,p_y,v_x,v_y = sym.symbols('p_x,p_y,v_x,v_y', real=True)
8
+ lam,f_x,theta,u_dummy = sym.symbols('lam,f_x,theta,u_dummy', real=True)
9
+
10
+ dp_x = v_x
11
+ dp_y = v_y
12
+ dv_x = (-2*p_x*lam + f_x - K_d*v_x)/M
13
+ dv_y = (-M*G - 2*p_y*lam - K_d*v_y)/M
14
+
15
+ g_1 = p_x**2 + p_y**2 - L**2 -lam*1e-6
16
+ g_2 = -theta + sym.atan2(p_x,-p_y) + u_dummy
17
+
18
+ params_dict = {'L':5.21,'G':9.81,'M':10.0,'K_d':1e-3} # parameters with default values
19
+
20
+ u_ini_dict = {'theta':np.deg2rad(5.0),'u_dummy':0.0} # input for the initialization problem
21
+ u_run_dict = {'f_x':0,'u_dummy':0.0} # input for the running problem, its value is updated
22
+
23
+ sys_dict = {'name':model_name,
24
+ 'params_dict':params_dict,
25
+ 'f_list':[dp_x,dp_y,dv_x,dv_y],
26
+ 'g_list':[g_1,g_2],
27
+ 'x_list':[ p_x, p_y, v_x, v_y],
28
+ 'y_ini_list':[lam,f_x],
29
+ 'y_run_list':[lam,theta],
30
+ 'u_ini_dict':u_ini_dict,
31
+ 'u_run_dict':u_run_dict,
32
+ 'h_dict':{'E_p':M*G*(p_y+L),'E_k':0.5*M*(v_x**2+v_y**2),
33
+ 'theta':theta,'f_x':f_x,'lam':lam},
34
+ 'xy_0':{'theta':sym.atan2(p_x,-p_y)}}
35
+
36
+ return sys_dict
37
+
38
+
39
+ def test_build():
40
+ import pydae.build_v2 as db
41
+ sys_dict = dae('temp')
42
+
43
+
44
+ b = db.builder(sys_dict,verbose=True,API=True)
45
+ b.sparse = False
46
+ b.mkl = False
47
+ b.platform = 'Windows'
48
+ b.dict2system()
49
+ b.functions()
50
+ b.jacobians()
51
+ b.cwrite()
52
+ b.template()
53
+ b.compile()
54
+
55
+
56
+ def test_ini():
57
+
58
+ import temp
59
+
60
+ model = temp.model()
61
+
62
+ M = 30.0 # mass of the bob (kg)
63
+ L = 5.21 # length of the pendulum (m)
64
+ model.ini({'M':M,'L':L, # parameters setting
65
+ 'theta':np.deg2rad(0) # initial desired angle = 0º
66
+ },-1) # here -1 means that -1 is considered as initial gess for
67
+ # dynamic and algebraic states
68
+
69
+ model.report_x() # obtained dynamic states
70
+ model.report_y() # obtained algebraic states
71
+ model.report_z() # obtained outputs
72
+ model.report_u() # obtained algebraic states (theta is both state and output; f_x is both input and output)
73
+ model.report_params() # considered parameters
74
+
75
+ def test_api():
76
+
77
+ import temp
78
+
79
+ model = temp.model()
80
+
81
+ M = 30.0 # mass of the bob (kg)
82
+ L = 5.21 # length of the pendulum (m)
83
+ model.ini({'M':M,'L':L, # parameters setting
84
+ 'theta':np.deg2rad(5) # initial desired angle = 0º
85
+ },-1) # here -1 means that -1 is considered as initial gess for
86
+ # dynamic and algebraic states
87
+
88
+ model.report_x() # obtained dynamic states
89
+ model.report_y() # obtained algebraic states
90
+ model.report_z() # obtained outputs
91
+ model.report_u() # obtained algebraic states (theta is both state and output; f_x is both input and output)
92
+ model.report_params() # considered parameters
93
+
94
+
95
+ # model.run(1.0,{})
96
+ model.run_api()
97
+ #model.step(0.000000001,{})
98
+
99
+ if __name__ == '__main__':
100
+
101
+ test_build()
102
+ test_ini()
103
+ test_api()
104
+
105
+
106
+
107
+
@@ -0,0 +1,211 @@
1
+ import panel as pn
2
+ import datetime
3
+ import param
4
+ import asyncio
5
+ import re
6
+ from pydae.svg_tools import svg
7
+ import requests
8
+ import json
9
+ import time
10
+ import matplotlib.pyplot as plt
11
+ import numpy as np
12
+ pn.extension('katex','matplotlib')
13
+
14
+ t_0 = time.time()
15
+ plot_pane = pn.pane.Matplotlib(sizing_mode='stretch_width')
16
+
17
+ # A function to generate a new plot
18
+
19
+ # with open('cuerva_emec_db.svg', 'r') as fobj:
20
+ # svg_file_content = fobj.read()
21
+
22
+ # Generate the new SVG
23
+ #s = svg('cuerva_emec_db.svg')
24
+ # s.set_tspan('U_SS1', f"{meas_dict['V_SS1']:5.3f} pu")
25
+ # s.set_tspan('U_SS2', f"{meas_dict['V_SS2']:5.3f} pu")
26
+ # s.set_tspan('U_POI', f"{slider_val:5.3f} pu")
27
+ # s.set_title('GRID_title', f"V = {meas_dict['V_GRID']:5.3f} pu\nP = {meas_dict['p_line_POIHV_GRID'] / 1e6:5.3f} MW\nQ = {meas_dict['q_line_POIHV_GRID'] / 1e6:5.3f} Mvar")
28
+ # s.set_tspan('P_POI', f"{meas_dict['p_line_POI_POIHV'] / 1e6:5.1f} MW")
29
+ # s.set_tspan('Q_POI', f"{meas_dict['q_line_POI_POIHV'] / 1e6:5.1f} Mvar")
30
+
31
+ # html_code = """
32
+ # <div>
33
+ # <svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
34
+ # <circle id="interactive_circle" cx="100" cy="100" r="50" fill="skyblue">
35
+ # <title>This is a circle\nHola</title>
36
+ # </circle>
37
+ # <text id="time_label" x="50" y="50" font-family="Arial" font-size="24" text-anchor="middle" fill="#333">
38
+ # Time: 00:00:00
39
+ # </text>
40
+ # </svg>
41
+ # </div>
42
+ # """
43
+
44
+ N_t = 300
45
+ charts_data = {'Times':np.zeros(N_t),
46
+ 'theta':np.zeros(N_t),
47
+ 'f_x':np.zeros(N_t),
48
+ 'k':0, 'N_t':N_t, 't_0':t_0
49
+ }
50
+
51
+ # html_code = f"""
52
+ # <div>
53
+ # {s.tostring()}
54
+ # </div>
55
+ # """
56
+
57
+
58
+ #svg_pane = pn.pane.HTML(html_code, width=200, height=200)
59
+ # panel.servable()
60
+
61
+
62
+ # Create other widgets
63
+ button1 = pn.widgets.Button(name='Set to Red', button_type='success')
64
+ button2 = pn.widgets.Button(name='Set to Green', button_type='primary')
65
+ slider1 = pn.widgets.IntSlider(name='Circle Radius', start=20, end=100, value=80)
66
+ color_picker = pn.widgets.ColorPicker(name='Circle Color', value='#FF0000')
67
+
68
+
69
+ sld_f_x_label = pn.pane.LaTeX(r'$\mathsf {f_{x}}$ (Nm):', width=80)
70
+ sld_f_x = pn.widgets.FloatSlider(start=-200.0, end=200.0, value=0.0, step=0.01)
71
+
72
+ # Crear pestañas con Panel
73
+ tabs_monitor = pn.Tabs(
74
+ # ('Plant', svg_pane),
75
+ ('Charts', plot_pane)
76
+ )
77
+ tabs_ctrl = pn.Tabs(
78
+ ('Enviroment', pn.Column(
79
+ sld_f_x_label,sld_f_x))
80
+ # ('POI', pn.widgets.Button(name='Set to 2', button_type='success')),
81
+ )
82
+
83
+ # # A reusable function to update the SVG (for buttons and sliders)
84
+ # def update_svg(event=None):
85
+ # current_svg = svg_pane.object
86
+
87
+ # new_radius = slider1.value
88
+ # new_color = color_picker.value
89
+
90
+ # if event and event.obj is button1:
91
+ # new_color = '#FF0000'
92
+ # elif event and event.obj is button2:
93
+ # new_color = '#00FF00'
94
+
95
+ # # Use regular expressions for more reliable attribute updates
96
+ # updated_svg = re.sub(
97
+ # r'(<circle id="interactive_circle".*?)\sfill=".*?"',
98
+ # r'\1 fill="{}"'.format(new_color),
99
+ # current_svg
100
+ # )
101
+ # updated_svg = re.sub(
102
+ # r'(<circle id="interactive_circle".*?)\sr=".*?"',
103
+ # r'\1 r="{}"'.format(new_radius),
104
+ # updated_svg
105
+ # )
106
+
107
+ # # s.set_tspan('U_SS1', f"{meas_dict['V_SS1']:5.3f} pu")
108
+ # # s.set_tspan('U_SS2', f"{meas_dict['V_SS2']:5.3f} pu")
109
+ # # s.set_tspan('U_POI', f"{slider_val:5.3f} pu")
110
+ # # s.set_title('GRID_title', f"V = {meas_dict['V_GRID']:5.3f} pu\nP = {meas_dict['p_line_POIHV_GRID'] / 1e6:5.3f} MW\nQ = {meas_dict['q_line_POIHV_GRID'] / 1e6:5.3f} Mvar")
111
+ # # s.set_tspan('P_POI', f"{meas_dict['p_line_POI_POIHV'] / 1e6:5.1f} MW")
112
+ # # s.set_tspan('Q_POI', f"{meas_dict['q_line_POI_POIHV'] / 1e6:5.1f} Mvar")
113
+
114
+
115
+ # svg_pane.object = updated_svg
116
+
117
+ # The asynchronous function to be called periodically
118
+ async def update_time_label():
119
+ """
120
+ Asynchronously updates the time label in the SVG.
121
+ """
122
+ current_time = datetime.datetime.now().strftime("%H:%M:%S")
123
+ # current_svg = svg_pane.object
124
+
125
+ # # Use a regular expression to update the content of the text element
126
+ # new_svg = re.sub(
127
+ # r'(<tspan id="P_POI".*?>)(.*?)(</tspan>)',
128
+ # r'\1Time: {}\3'.format(current_time),
129
+ # current_svg,
130
+ # flags=re.DOTALL
131
+ # )
132
+
133
+ url = "http://localhost:8000/measurements"
134
+
135
+ ppc_ip = '10.30.0.4'
136
+
137
+ # http://10.30.0.4:5500/ppc_measurements
138
+
139
+ ##############################################################################
140
+ url = "http://localhost:8000/measurements"
141
+ #url = f"http://{ppc_ip}:5500/ppc_measurements"
142
+ response = requests.get(url, headers={"Content-Type": "application/json"}, timeout=0.5) # Added a timeout
143
+ response.raise_for_status()
144
+ meas_dict = response.json()
145
+ time.sleep(0.05)
146
+
147
+ ###############################################################################
148
+ url = "http://localhost:8000/setpoints"
149
+ #url = f"http://{ppc_ip}:5500/ppc_setpoints"
150
+ headers = {"Content-Type": "application/json"}
151
+ data = {
152
+ "f_x":float(sld_f_x.value)
153
+ }
154
+
155
+ response = requests.post(url, headers=headers, data=json.dumps(data))
156
+
157
+ # # This is the line that's failing
158
+ # response.raise_for_status()
159
+
160
+ #response = requests.post(url, headers=headers, data=json.dumps(data))
161
+
162
+
163
+
164
+ # time.sleep(1.0)
165
+
166
+ # # Generate the new SVG
167
+ # s = svg('cuerva_emec_db.svg')
168
+ # s.set_tspan('U_SS1', f"{meas_dict['U_SS1']/20e3:5.3f} pu")
169
+ # s.set_tspan('U_SS2', f"{meas_dict['U_SS2']/20e3:5.3f} pu")
170
+ # s.set_tspan('U_POI', f"{meas_dict['U_POI']/20e3:5.3f} pu")
171
+ # #s.set_title('GRID_title', f"V = {meas_dict['V_GRID']:5.3f} pu\nP = {meas_dict['p_line_POIHV_GRID'] / 1e6:5.3f} MW\nQ = {meas_dict['q_line_POIHV_GRID'] / 1e6:5.3f} Mvar")
172
+ # s.set_tspan('P_POI', f"{meas_dict['p_line_POI_POIHV'] / 1e6:5.2f} MW")
173
+ # s.set_tspan('Q_POI', f"{meas_dict['q_line_POI_POIHV'] / 1e6:5.2f} Mvar")
174
+
175
+ charts_data['Times'][-1] = time.time() - t_0
176
+ charts_data['theta'][-1] = meas_dict['theta']
177
+ charts_data['f_x'][-1] = meas_dict['f_x']
178
+
179
+ charts_data['Times'][0:-1] = charts_data['Times'][1:]
180
+ charts_data['theta'][0:-1] = charts_data['theta'][1:]
181
+ charts_data['f_x'][0:-1] = charts_data['f_x'][1:]
182
+
183
+ charts_data['k'] += 1
184
+
185
+ plt.close('all') # Clear previous plot
186
+ fig, ax = plt.subplots(figsize=(6, 4))
187
+ ax.plot(charts_data['Times'], charts_data['theta'], color='blue') # Plot new random data
188
+ ax.plot(charts_data['Times'], charts_data['f_x'], color='red') # Plot new random data
189
+
190
+ plot_pane.object = fig # Assign the new figure to the pane
191
+
192
+
193
+ # # Link widgets to the update function
194
+ # button1.on_click(update_svg)
195
+ # button2.on_click(update_svg)
196
+ # slider1.param.watch(update_svg, 'value')
197
+ # color_picker.param.watch(update_svg, 'value')
198
+
199
+ # Combine all components into a Panel layout
200
+ dashboard = pn.Column(
201
+ tabs_monitor,
202
+ tabs_ctrl
203
+ )
204
+
205
+ # Use pn.io.periodic_async to run the update_time_label function every 1000ms (1 second)
206
+ # The `dashboard.servable()` is required to use periodic functions in a standalone app.
207
+ # In a Jupyter notebook, `dashboard` will automatically display the periodic updates.
208
+ pn.state.add_periodic_callback(update_time_label, period=100)
209
+
210
+ # Display the dashboard
211
+ dashboard.show()