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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "V_1": 1.0,
3
+ "theta_1": 0.0,
4
+ "V_2": 1.0,
5
+ "theta_2": 0.0,
6
+ "omega_coi": 1.0
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "V_1": 1.0,
3
+ "theta_1": 0.0,
4
+ "V_2": 1.0,
5
+ "theta_2": 0.0,
6
+ "omega_coi": 1.0
7
+ }
@@ -0,0 +1,647 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Created on Thu August 10 23:52:55 2022
4
+
5
+ @author: jmmauricio
6
+ """
7
+
8
+ import numpy as np
9
+ import sympy as sym
10
+ from pydae.utils.ss_num2sym import ss_num2sym
11
+
12
+ def pv_dq_ss(grid,name,bus_name,data_dict):
13
+ '''
14
+
15
+ A substation with a LV to MV transformer
16
+ N_vsc converters connected radially to the substation
17
+ N_eq number of considered VSC
18
+
19
+
20
+ VSC VSC
21
+ SS
22
+ VSC VSC
23
+
24
+
25
+
26
+ VSC model with L filter coupling and purely algebraic.
27
+ PQ control is implemented.
28
+
29
+ parameters
30
+ ----------
31
+
32
+ S_n: nominal power in VA
33
+ U_n: nominal rms phase to phase voltage in V
34
+ F_n: nominal frequency in Hz
35
+ X_s: coupling reactance in pu (base machine S_n)
36
+ R_s: coupling resistance in pu (base machine S_n)
37
+
38
+ inputs
39
+ ------
40
+
41
+ p_s_ref: active power reference (pu, S_n base)
42
+ q_s_ref: reactive power reference (pu, S_n base)
43
+ v_dc: dc voltage in pu (when v_dc = 1 and m = 1, v_ac = 1)
44
+
45
+ example
46
+ -------
47
+
48
+ "vscs": [{"bus":bus_name,"type":"pv_pq",
49
+ "S_n":1e6,"U_n":400.0,"F_n":50.0,
50
+ "X_s":0.1,"R_s":0.01,"monitor":True,
51
+ "I_sc":3.87,"V_oc":42.1,"I_mp":3.56,"V_mp":33.7,
52
+ "K_vt":-0.160,"K_it":0.065,
53
+ "N_pv_s":25,"N_pv_p":250}]
54
+
55
+ '''
56
+
57
+ sin = sym.sin
58
+ cos = sym.cos
59
+
60
+ ## Common
61
+ ### inputs
62
+ V_s = sym.Symbol(f"V_{bus_name}", real=True)
63
+ p_s = sym.Symbol(f"p_s_{name}", real=True)
64
+ theta_s = sym.Symbol(f"theta_{bus_name}", real=True)
65
+ v_dc = sym.Symbol(f"v_dc_{name}", real=True)
66
+ p_s_ppc = sym.Symbol(f"p_s_ppc_{name}", real=True)
67
+ q_s_ppc = sym.Symbol(f"q_s_ppc_{name}", real=True)
68
+
69
+ ### parameters
70
+ S_n = sym.Symbol(f"S_n_{name}", real=True)
71
+ U_n = sym.Symbol(f"U_n_{name}", real=True)
72
+ V_dc_b = U_n*np.sqrt(2)
73
+ X_s = sym.Symbol(f"X_s_{name}", real=True)
74
+ R_s = sym.Symbol(f"R_s_{name}", real=True)
75
+
76
+ ## PV
77
+ K_vt,K_it = sym.symbols(f"K_vt_{name},K_it_{name}", real=True)
78
+ V_oc,V_mp,I_sc,I_mp = sym.symbols(f"V_oc_{name},V_mp_{name},I_sc_{name},I_mp_{name}", real=True)
79
+ temp_deg,irrad = sym.symbols(f"temp_deg_{name},irrad_{name}", real=True)
80
+ T_stc_k,i,v = sym.symbols(f"T_stc_k_{name},i_{name},v_{name}", real=True)
81
+ v_dc,v_dc_v,K_it = sym.symbols(f"v_dc_{name},v_dc_v_{name},K_it_{name}", real=True)
82
+ N_pv_s,N_pv_p = sym.symbols(f"N_pv_s_{name},N_pv_p_{name}", real=True)
83
+
84
+ T_stc_deg = 25.0
85
+
86
+ V_oc_t = N_pv_s*V_oc * (1 + K_vt/100.0*(temp_deg - T_stc_deg))
87
+ V_mp_t = N_pv_s*V_mp * (1 + K_vt/100.0*(temp_deg - T_stc_deg))
88
+ I_sc_t = N_pv_p*I_sc * (1 + K_it/100.0*(temp_deg - T_stc_deg))
89
+ I_mp_t = N_pv_p*I_mp * (1 + K_it/100.0*(temp_deg - T_stc_deg))
90
+ I_mp_i = I_mp_t*irrad/1000.0
91
+
92
+ v_1,i_1 = V_mp_t,I_mp_i
93
+ v_2,i_2 = V_oc_t,0
94
+
95
+ # (v_1 - v)/(v_1 - v_2) = (i_1 - i)/(i_1 - i_2)
96
+ i_pv = p_s*S_n/(v_dc*V_dc_b)
97
+ p_mp = (V_mp_t*I_mp_i)/S_n
98
+ #v_dc_v = v_1 - (i_1 - i_pv)*(v_1 - v_2)/(i_1 - i_2)
99
+ v_dc_v = v_1 - (i_1 - i_pv)*(v_1 - v_2)/(i_1 - i_2)
100
+ g_v_dc = -v_dc + v_dc_v/V_dc_b
101
+
102
+ grid.dae['g'] += [g_v_dc]
103
+ grid.dae['y_ini'] += [ v_dc]
104
+ grid.dae['y_run'] += [ v_dc]
105
+
106
+ grid.dae['u_ini_dict'].update({f'{str(irrad)}':1000.0})
107
+ grid.dae['u_run_dict'].update({f'{str(irrad)}':1000.0})
108
+
109
+ grid.dae['u_ini_dict'].update({f'{str(temp_deg)}':25.0})
110
+ grid.dae['u_run_dict'].update({f'{str(temp_deg)}':25.0})
111
+
112
+ grid.dae['params_dict'].update({
113
+ str(I_sc):data_dict['I_sc'],
114
+ str(I_mp):data_dict['I_mp'],
115
+ str(V_mp):data_dict['V_mp'],
116
+ str(V_oc):data_dict['V_oc'],
117
+ str(N_pv_s):data_dict['N_pv_s'],
118
+ str(N_pv_p):data_dict['N_pv_p'],
119
+ str(K_vt):data_dict['K_vt'],
120
+ str(K_it):data_dict['K_it']
121
+ })
122
+
123
+
124
+
125
+ #grid.dae['xy_0_dict'].update({f"v_dc_v_{name}":data_dict['V_mp']*data_dict['N_pv_s']})
126
+ grid.dae['xy_0_dict'].update({f"v_dc_{name}":1.5})
127
+
128
+ ## VSC control
129
+ ### inputs
130
+ p_s_ref = sym.Symbol(f"p_s_ref_{name}", real=True)
131
+ q_s_ref = sym.Symbol(f"q_s_ref_{name}", real=True)
132
+ i_sa_ref = sym.Symbol(f"i_sa_ref_{name}", real=True)
133
+ i_sr_ref = sym.Symbol(f"i_sr_ref_{name}", real=True)
134
+
135
+ ### dynamic states
136
+
137
+ ### algebraic states
138
+ i_sd_pq_ref,i_sq_pq_ref = sym.symbols(f'i_sd_pq_ref_{name},i_sq_pq_ref_{name}', real=True)
139
+ i_sd_ar_ref,i_sq_ar_ref = sym.symbols(f'i_sd_ar_ref_{name},i_sq_ar_ref_{name}', real=True)
140
+ i_sd_ref,i_sq_ref = sym.symbols(f'i_sd_ref_{name},i_sq_ref_{name}', real=True)
141
+ i_sd_ref,i_sq_ref = sym.symbols(f'i_sd_ref_{name},i_sq_ref_{name}', real=True)
142
+
143
+ v_td_ref,v_tq_ref = sym.symbols(f'v_td_ref_{name},v_tq_ref_{name}', real=True)
144
+ v_lvrt,lvrt_ext = sym.symbols(f"v_lvrt_{name},lvrt_ext_{name}", real=True)
145
+
146
+ x_p_1, x_p_2 = sym.symbols(f"x_p_1_{name},x_p_2_{name}", real=True)
147
+ A_11p,A_12p,A_21p,A_22p = sym.symbols(f"A_11p_{name},A_12p_{name},A_21p_{name},A_22p_{name}", real=True)
148
+ B_11p,B_21p = sym.symbols(f"B_11p_{name},B_21p_{name}", real=True)
149
+ C_11p,C_12p = sym.symbols(f"C_11p_{name},C_12p_{name}", real=True)
150
+ D_11p = sym.symbols(f"D_11p_{name}", real=True)
151
+
152
+ x_q_1, x_q_2 = sym.symbols(f"x_q_1_{name},x_q_2_{name}", real=True)
153
+ A_11q,A_12q,A_21q,A_22q = sym.symbols(f"A_11q_{name},A_12q_{name},A_21q_{name},A_22q_{name}", real=True)
154
+ B_11q,B_21q = sym.symbols(f"B_11q_{name},B_12q_{name}", real=True)
155
+ C_11q,C_12q = sym.symbols(f"C_11q_{name},C_12q_{name}", real=True)
156
+ D_11q = sym.symbols(f"D_11q_{name}", real=True)
157
+
158
+
159
+ ### parameters
160
+
161
+ ### auxiliar
162
+ delta = theta_s # ideal PLL
163
+ v_sD = V_s*sin(theta_s) # v_si e^(-j)
164
+ v_sQ = V_s*cos(theta_s) # v_sr
165
+ v_sd = v_sD * cos(delta) - v_sQ * sin(delta)
166
+ v_sq = v_sD * sin(delta) + v_sQ * cos(delta)
167
+
168
+ v_m = sym.sqrt(v_sd**2 + v_sq**2)
169
+ lvrt = sym.Piecewise((0.0,v_m>=v_lvrt),(1.0,v_m<v_lvrt)) + lvrt_ext
170
+
171
+ A_p = A_q = np.array([[-10.0]])
172
+ B_p = B_q = np.array([[-10.0]])
173
+ C_p = C_q = np.array([[1.0]])
174
+ D_p = D_q = np.array([[0.0]])
175
+
176
+ if 'A_p' in data_dict:
177
+ A_p = np.array(data_dict['A_p'])
178
+ B_p = np.array(data_dict['B_p'])
179
+ C_p = np.array(data_dict['C_p'])
180
+ D_p = np.array(data_dict['D_p'])
181
+
182
+ sys_p = ss_num2sym(f'p_{name}',A_p,B_p,C_p,D_p)
183
+ sys_p['dx']= sys_p['dx'].replace(sys_p['u'][0],p_s_ppc)
184
+ sys_p['z_evaluated']= sys_p['z_evaluated'].replace(sys_p['u'][0],p_s_ppc)
185
+
186
+ ### dynamic equations
187
+ grid.dae['f'] += list(sys_p['dx'])
188
+ grid.dae['x'] += list(sys_p['x'])
189
+
190
+ p_s_ppc_d = sys_p['z_evaluated'][0,0]
191
+
192
+ grid.dae['params_dict'].update(sys_p['params_dict'])
193
+
194
+ if 'A_q' in data_dict:
195
+ A_q = np.array(data_dict['A_q'])
196
+ B_q = np.array(data_dict['B_q'])
197
+ C_q = np.array(data_dict['C_q'])
198
+ D_q = np.array(data_dict['D_q'])
199
+
200
+ sys_q = ss_num2sym(f'q_{name}',A_q,B_q,C_q,D_q)
201
+ sys_q['dx']= sys_q['dx'].replace(sys_q['u'][0],q_s_ppc)
202
+ sys_q['z_evaluated']= sys_q['z_evaluated'].replace(sys_q['u'][0],q_s_ppc)
203
+
204
+ ### dynamic equations
205
+ grid.dae['f'] += list(sys_q['dx'])
206
+ grid.dae['x'] += list(sys_q['x'])
207
+
208
+ q_s_ppc_d = sys_q['z_evaluated'][0,0]
209
+
210
+ grid.dae['params_dict'].update(sys_q['params_dict'])
211
+
212
+ if 'A_pq' in data_dict:
213
+ A_pq = np.array(data_dict['A_pq'])
214
+ B_pq = np.array(data_dict['B_pq'])
215
+ C_pq = np.array(data_dict['C_pq'])
216
+ D_pq = np.array(data_dict['D_pq'])
217
+
218
+
219
+ sys_pq = ss_num2sym(f'pq_{name}',A_pq,B_pq,C_pq,D_pq)
220
+
221
+
222
+ sys_pq['dx']= sys_pq['dx'].replace(sys_pq['u'][0],p_s_ppc)
223
+ sys_pq['dx']= sys_pq['dx'].replace(sys_pq['u'][1],q_s_ppc)
224
+ sys_pq['z_evaluated']= sys_pq['z_evaluated'].replace(sys_pq['u'][0],p_s_ppc)
225
+ sys_pq['z_evaluated']= sys_pq['z_evaluated'].replace(sys_pq['u'][1],q_s_ppc)
226
+
227
+ ### dynamic equations
228
+ grid.dae['f'] += list(sys_pq['dx'])
229
+ grid.dae['x'] += list(sys_pq['x'])
230
+
231
+ p_s_ppc_d = sys_pq['z_evaluated'][0,0]
232
+ q_s_ppc_d = sys_pq['z_evaluated'][1,0]
233
+
234
+ grid.dae['params_dict'].update(sys_pq['params_dict'])
235
+
236
+
237
+
238
+
239
+
240
+ p_s_ref = sym.Piecewise((p_s_ppc_d,p_s_ppc_d<p_mp),(p_mp,p_s_ppc_d>=p_mp))
241
+ q_s_ref = q_s_ppc_d
242
+
243
+
244
+
245
+ ### algebraic equations
246
+ #g_i_sd_pq_ref = i_sd_pq_ref*v_sd + i_sq_pq_ref*v_sq - p_s_ref
247
+ #g_i_sq_pq_ref =-i_sq_pq_ref*v_sd + i_sd_pq_ref*v_sq - q_s_ref
248
+ #g_i_sd_ar_ref = i_sd_ar_ref*v_sd/v_m + i_sq_ar_ref*v_sq/v_m - i_sa_ref
249
+ #g_i_sq_ar_ref =-i_sq_ar_ref*v_sd/v_m + i_sd_ar_ref*v_sq/v_m - i_sr_ref
250
+ #g_v_td_ref = v_td_ref - R_s*i_sd_ref + X_s*i_sq_ref - v_sd
251
+ #g_v_tq_ref = v_tq_ref - R_s*i_sq_ref - X_s*i_sd_ref - v_sq
252
+
253
+ i_sd_ar_ref = i_sa_ref*v_sd/sym.sqrt(v_sd**2 + v_sq**2) + i_sr_ref*v_sq/sym.sqrt(v_sd**2 + v_sq**2)
254
+ i_sq_ar_ref = i_sa_ref*v_sq/sym.sqrt(v_sd**2 + v_sq**2) - i_sr_ref*v_sd/sym.sqrt(v_sd**2 + v_sq**2)
255
+
256
+ i_sd_pq_ref = (p_s_ref*v_sd + q_s_ref*v_sq)/(v_sd**2 + v_sq**2)
257
+ i_sq_pq_ref = (p_s_ref*v_sq - q_s_ref*v_sd)/(v_sd**2 + v_sq**2)
258
+ i_sd_ref_nosat = (1.0-lvrt)*i_sd_pq_ref + lvrt*i_sd_ar_ref
259
+ i_sq_ref_nosat = (1.0-lvrt)*i_sq_pq_ref + lvrt*i_sq_ar_ref
260
+ g_i_sd_ref = -i_sd_ref + sym.Piecewise((-1.2,i_sd_ref_nosat<-1.2),(1.2,i_sd_ref_nosat>1.2),(i_sd_ref_nosat,True))
261
+ g_i_sq_ref = -i_sq_ref + sym.Piecewise((-1.2,i_sq_ref_nosat<-1.2),(1.2,i_sq_ref_nosat>1.2),(i_sq_ref_nosat,True))
262
+
263
+ v_td_ref = R_s*i_sd_ref - X_s*i_sq_ref + v_sd
264
+ v_tq_ref = R_s*i_sq_ref + X_s*i_sd_ref + v_sq
265
+
266
+ v_tD_ref = v_td_ref * cos(delta) + v_tq_ref * sin(delta)
267
+ v_tQ_ref =-v_td_ref * sin(delta) + v_tq_ref * cos(delta)
268
+ v_ti_ref = v_tD_ref
269
+ v_tr_ref = v_tQ_ref
270
+ m_ref = sym.sqrt(v_tr_ref**2 + v_ti_ref**2)/v_dc
271
+ theta_t_ref = sym.atan2(v_ti_ref,v_tr_ref)
272
+
273
+
274
+ ### dae
275
+ grid.dae['g'] += [g_i_sd_ref, g_i_sq_ref]
276
+ grid.dae['y_ini'] += [i_sq_ref, i_sd_ref]
277
+ grid.dae['y_run'] += [i_sq_ref, i_sd_ref]
278
+
279
+ grid.dae['u_ini_dict'].update({f'lvrt_ext_{name}':0.0})
280
+ grid.dae['u_run_dict'].update({f'lvrt_ext_{name}':0.0})
281
+
282
+ grid.dae['u_ini_dict'].update({f'p_s_ppc_{name}':1.5})
283
+ grid.dae['u_run_dict'].update({f'p_s_ppc_{name}':1.5})
284
+
285
+ grid.dae['u_ini_dict'].update({f'q_s_ppc_{name}':0.0})
286
+ grid.dae['u_run_dict'].update({f'q_s_ppc_{name}':0.0})
287
+
288
+ grid.dae['u_ini_dict'].update({f'{str(i_sa_ref)}':0.0})
289
+ grid.dae['u_run_dict'].update({f'{str(i_sa_ref)}':0.0})
290
+
291
+ grid.dae['u_ini_dict'].update({f'{str(i_sr_ref)}':0.0})
292
+ grid.dae['u_run_dict'].update({f'{str(i_sr_ref)}':0.0})
293
+
294
+ grid.dae['params_dict'].update({f'{str(v_lvrt)}':0.8})
295
+ # grid.dae['params_dict'].update({f'{str(T_lp1p)}':0.1,f'{str(T_lp2p)}':0.1})
296
+ # grid.dae['params_dict'].update({f'{str(T_lp1q)}':0.1,f'{str(T_lp2q)}':0.1})
297
+ # grid.dae['params_dict'].update({f'{str(PRampUp)}':2.5,f'{str(PRampDown)}':-2.5})
298
+ # grid.dae['params_dict'].update({f'{str(QRampUp)}':2.5,f'{str(QRampDown)}':-2.5})
299
+
300
+
301
+
302
+
303
+ ### outputs
304
+ grid.dae['h_dict'].update({f"m_ref_{name}":m_ref})
305
+ grid.dae['h_dict'].update({f"v_sd_{name}":v_sd})
306
+ grid.dae['h_dict'].update({f"v_sq_{name}":v_sq})
307
+ grid.dae['h_dict'].update({f"lvrt_{name}":lvrt})
308
+ grid.dae['h_dict'].update({f'p_s_ppc_{name}':p_s_ppc})
309
+ grid.dae['h_dict'].update({f'q_s_ppc_{name}':q_s_ppc})
310
+
311
+ ## VSC model
312
+ # m = sym.Symbol(f"m_{name}", real=True)
313
+ # theta_t = sym.Symbol(f"theta_t_{name}", real=True)
314
+
315
+ ### dynamic states
316
+ #m_f = sym.Symbol(f"m_f_{name}", real=True)
317
+
318
+ ### algebraic states
319
+ i_si = sym.Symbol(f"i_si_{name}", real=True)
320
+ i_sr = sym.Symbol(f"i_sr_{name}", real=True)
321
+ p_s = sym.Symbol(f"p_s_{name}", real=True)
322
+ q_s = sym.Symbol(f"q_s_{name}", real=True)
323
+
324
+ ### parameters
325
+ F_n = sym.Symbol(f"F_n_{name}", real=True)
326
+
327
+
328
+ params_list = ['S_n','F_n','U_n','X_s','R_s']
329
+
330
+ ### auxiliar
331
+ v_si = V_s*sin(theta_s) # v_D, e^(-j)
332
+ v_sr = V_s*cos(theta_s) # v_Q
333
+ Omega_b = 2*np.pi*F_n
334
+ m = m_ref
335
+ theta_t = theta_t_ref
336
+ v_t_m = m*v_dc
337
+ v_tr = v_t_m*cos(theta_t)
338
+ v_ti = v_t_m*sin(theta_t)
339
+
340
+
341
+
342
+ ### dynamic equations
343
+
344
+ ### algebraic equations
345
+ v_ti = v_ti_ref
346
+ v_tr = v_tr_ref
347
+ g_i_si = v_ti - R_s*i_si + X_s*i_sr - v_si
348
+ g_i_sr = v_tr - R_s*i_sr - X_s*i_si - v_sr
349
+ # i_sr = (-R_s*v_sr + R_s*v_tr + X_s*v_si - X_s*v_ti)/(R_s**2 + X_s**2)
350
+ # i_si = (-R_s*v_si + R_s*v_ti - X_s*v_sr + X_s*v_tr)/(R_s**2 + X_s**2)
351
+ g_p_s = i_si*v_si + i_sr*v_sr - p_s
352
+ g_q_s = i_si*v_sr - i_sr*v_si - q_s
353
+
354
+ ### dae
355
+ f_vsg = []
356
+ x_vsg = []
357
+ g_vsg = [g_i_si,g_i_sr,g_p_s,g_q_s]
358
+ y_vsg = [ i_sr, i_si, p_s, q_s]
359
+
360
+ grid.dae['f'] += f_vsg
361
+ grid.dae['x'] += x_vsg
362
+ grid.dae['g'] += g_vsg
363
+ grid.dae['y_ini'] += y_vsg
364
+ grid.dae['y_run'] += y_vsg
365
+
366
+ # grid.dae['u_ini_dict'].update({f'{m}':1.0})
367
+ # grid.dae['u_run_dict'].update({f'{m}':1.0})
368
+
369
+ # grid.dae['u_ini_dict'].update({f'{theta_t}':0.0})
370
+ # grid.dae['u_run_dict'].update({f'{theta_t}':0.0})
371
+
372
+ # grid.dae['u_ini_dict'].update({f'{v_dc}':1.2})
373
+ # grid.dae['u_run_dict'].update({f'{v_dc}':1.2})
374
+
375
+ grid.dae['xy_0_dict'].update({str(p_s):0.5})
376
+
377
+ ### outputs
378
+
379
+
380
+
381
+ for item in params_list:
382
+ grid.dae['params_dict'].update({f"{item}_{name}":data_dict[item]})
383
+
384
+ if 'monitor' in data_dict:
385
+ if data_dict['monitor'] == True:
386
+
387
+ grid.dae['h_dict'].update({f"v_dc_v_{name}":v_dc*V_dc_b})
388
+ grid.dae['h_dict'].update({f"v_ac_v_{name}":v_t_m*U_n})
389
+ grid.dae['h_dict'].update({f"v_dc_v_{name}":v_dc_v})
390
+ grid.dae['h_dict'].update({f"p_mp_{name}":p_mp})
391
+ grid.dae['h_dict'].update({f"i_pv_{name}":i_pv})
392
+ grid.dae['h_dict'].update({f"v_dc_{name}":v_dc})
393
+ grid.dae['h_dict'].update({f"p_s_{name}":p_s})
394
+ grid.dae['h_dict'].update({f"q_s_{name}":q_s})
395
+ grid.dae['h_dict'].update({f"v_ti_{name}":v_ti})
396
+ grid.dae['h_dict'].update({f"v_tr_{name}":v_tr})
397
+ grid.dae['h_dict'].update({f"i_si_{name}":i_si})
398
+ grid.dae['h_dict'].update({f"i_sr_{name}":i_sr})
399
+ i_s = sym.sqrt(i_sr**2 + i_si**2)
400
+ grid.dae['h_dict'].update({f"i_s_{name}":i_s})
401
+
402
+ p_W = p_s * S_n
403
+ q_var = q_s * S_n
404
+
405
+ return p_W,q_var
406
+
407
+ def sym2model():
408
+ v_sd = sym.Symbol(f"v_sd", real=True)
409
+ v_sq = sym.Symbol(f"v_sq", real=True)
410
+ p_s_ref = sym.Symbol(f"p_s_ref", real=True)
411
+ q_s_ref = sym.Symbol(f"q_s_ref", real=True)
412
+ i_sa_ref = sym.Symbol(f"i_sa_ref", real=True)
413
+ i_sr_ref = sym.Symbol(f"i_sr_ref", real=True)
414
+ i_sd_pq_ref,i_sq_pq_ref = sym.symbols(f'i_sd_pq_ref,i_sq_pq_ref', real=True)
415
+ i_sd_ar_ref,i_sq_ar_ref = sym.symbols(f'i_sd_ar_ref,i_sq_ar_ref', real=True)
416
+
417
+
418
+ g_i_sd_pq_ref = i_sd_pq_ref*v_sd + i_sq_pq_ref*v_sq - p_s_ref
419
+ g_i_sq_pq_ref =-i_sq_pq_ref*v_sd + i_sd_pq_ref*v_sq - q_s_ref
420
+
421
+ sol = sym.solve([g_i_sd_pq_ref,g_i_sq_pq_ref],[i_sd_pq_ref,i_sq_pq_ref])
422
+
423
+ for item in sol:
424
+ print(f"{item} = {sol[item]}")
425
+
426
+ v_m = sym.sqrt(v_sd**2 + v_sq**2)
427
+ g_i_sd_ar_ref = i_sd_ar_ref*v_sd/v_m + i_sq_ar_ref*v_sq/v_m - i_sa_ref
428
+ g_i_sq_ar_ref =-i_sq_ar_ref*v_sd/v_m + i_sd_ar_ref*v_sq/v_m - i_sr_ref
429
+
430
+ sol = sym.solve([g_i_sd_ar_ref,g_i_sq_ar_ref],[i_sd_ar_ref,i_sq_ar_ref])
431
+
432
+ for item in sol:
433
+ print(f"{item} = {sol[item]}")
434
+
435
+ # coupling filter:
436
+ v_tr,v_ti = sym.symbols(f"v_tr,v_ti", real=True)
437
+ i_sr,i_si = sym.symbols(f"i_sr,i_si", real=True)
438
+ v_sr,v_si = sym.symbols(f"v_sr,v_si", real=True)
439
+ R_s,X_s = sym.symbols(f"R_s,X_s", real=True)
440
+
441
+ g_i_si = v_ti - R_s*i_si + X_s*i_sr - v_si
442
+ g_i_sr = v_tr - R_s*i_sr - X_s*i_si - v_sr
443
+ sol = sym.solve([g_i_sr,g_i_si],[i_sr,i_si])
444
+
445
+ for item in sol:
446
+ print(f"{item} = {sol[item]}")
447
+
448
+ # simplified PV module
449
+
450
+
451
+ def change_ss(model,A,B,C,D):
452
+ pass
453
+
454
+
455
+
456
+ def test_build():
457
+ from pydae.bmapu import bmapu_builder
458
+
459
+ data = {
460
+ "system":{"name":"test_model","S_base":100e6, "K_p_agc":0.0,"K_i_agc":0.0,"K_xif":0.01},
461
+ "buses":[{"name":"1", "P_W":0.0,"Q_var":0.0,"U_kV":20.0},
462
+ {"name":"2", "P_W":0.0,"Q_var":0.0,"U_kV":20.0}
463
+ ],
464
+ "lines":[{"bus_j":"1", "bus_k":"2", "X_pu":0.05,"R_pu":0.0,"Bs_pu":0.0,"S_mva":10000.0}],
465
+ "sources":[{"bus":"2","type":"genape", "S_n":10000e6,"F_n":50.0,"X_v":0.001,"R_v":0.0,"K_delta":0.001,"K_alpha":1e-6}],
466
+ "pvs":[{
467
+ "bus": "1",
468
+ "type": "pv_dq_ss",
469
+ "S_n": 3000000.0,
470
+ "U_n": 400.0,
471
+ "F_n": 50.0,
472
+ "X_s": 0.1,
473
+ "R_s": 0.0001,
474
+ "monitor": False,
475
+ "I_sc": 8,
476
+ "V_oc": 42.1,
477
+ "I_mp": 3.56,
478
+ "V_mp": 33.7,
479
+ "K_vt": -0.16,
480
+ "K_it": 0.065,
481
+ "N_pv_s": 23,
482
+ "N_pv_p": 1087,
483
+ # # Close loop
484
+ # "A_p": [[ 2.22745959, 2.89134367],[-5.98640302, -5.13853719]],
485
+ # "B_p":[[-2.62892537],[-3.35747765]],
486
+ # "C_p":[[-0.53183608 ,-0.28013641]],
487
+ # "D_p":[[0.]],
488
+ # "A_q": [[ 2.22745959, 2.89134367],[-5.98640302, -5.13853719]],
489
+ # "B_q":[[-2.62892537],[-3.35747765]],
490
+ # "C_q":[[-0.53183608 ,-0.28013641]],
491
+ # "D_q":[[0.]],
492
+ # Close loop pq coupled
493
+ "A_pq": [[ 2.22745959, 2.89134367, 0.0, 0.0],
494
+ [-5.98640302, -5.13853719, 0.0, 0.0],
495
+ [ 0.0, 0.0, 2.22745959, 2.89134367],
496
+ [ 0.0, 0.0,-5.98640302,-5.13853719]],
497
+ "B_pq":[[-2.62892537, 0.0],
498
+ [-3.35747765, 0.0],
499
+ [ 0.0,-2.62892537],
500
+ [ 0.0,-3.35747765]],
501
+ "C_pq":[[-0.53183608 ,-0.28013641, 0.0, 0.0],
502
+ [ 0.0, 0.0,-0.53183608 ,-0.28013641]],
503
+ "D_pq":[[0.,0.],[0.,0.]],
504
+ # Open loop
505
+ # "A_p":[[ 0.33137699, 2.1000962 ], [-9.11825055, -6.20455623]],
506
+ # "B_p":[[-3.44429742], [-5.67395313]],
507
+ # "C_p":[[-0.53651084, -0.02498652]],
508
+ # "D_p":[[0.]],
509
+ # "A_q":[[ 0.33137699, 2.1000962 ], [-9.11825055, -6.20455623]],
510
+ # "B_q":[[-3.44429742], [-5.67395313]],
511
+ # "C_q":[[-0.53651084, -0.02498652]],
512
+ # "D_q":[[0.]],
513
+ # Open loop high order
514
+ # "A_p":[[ 8.38271015, -1.7571524 , 1.73425499, -1.30126187, -0.65661779, 0.19946719, -0.27419108],
515
+ # [ 9.21838154, 4.00099853, -7.81509434, 4.35694934, 1.93722067,-0.5469874 , 0.71654726],
516
+ # [-2.40905211, 2.06691677, 1.45133758, -4.4215498 , -1.4626006 , 0.3642175 , -0.44442714],
517
+ # [ 1.49417659, -0.95112217, 3.64830378, -0.65345492, 2.62637562,-0.48697018, 0.52522081],
518
+ # [ 1.76580717, -0.98874696, 2.81999399, -6.13573245, -2.77497888,-1.4733826 , 1.18610772],
519
+ # [-3.98772761, 2.0720406 , -5.20922579, 8.4373616 , 10.92677635,-5.37878648, -6.41515444],
520
+ # [ 2.15679302, -1.06505127, 2.48988235, -3.55911887, -3.43500894, 2.50096692, -9.87800368]],
521
+ # "B_p":[[ 0.76019693],[-1.61641228],[ 0.79263982],[-0.70153677],[-1.0642704 ],[ 2.92345721],[-1.86444729]],
522
+ # "C_p":[[ 0.53471062, -0.22393912, 0.43508347, -0.49268284, -0.34211526,0.13852951, -0.2621668 ]],
523
+ # "D_p":[[0.]],
524
+ # "A_q":[[ 8.38271015, -1.7571524 , 1.73425499, -1.30126187, -0.65661779, 0.19946719, -0.27419108],
525
+ # [ 9.21838154, 4.00099853, -7.81509434, 4.35694934, 1.93722067,-0.5469874 , 0.71654726],
526
+ # [-2.40905211, 2.06691677, 1.45133758, -4.4215498 , -1.4626006 , 0.3642175 , -0.44442714],
527
+ # [ 1.49417659, -0.95112217, 3.64830378, -0.65345492, 2.62637562,-0.48697018, 0.52522081],
528
+ # [ 1.76580717, -0.98874696, 2.81999399, -6.13573245, -2.77497888,-1.4733826 , 1.18610772],
529
+ # [-3.98772761, 2.0720406 , -5.20922579, 8.4373616 , 10.92677635,-5.37878648, -6.41515444],
530
+ # [ 2.15679302, -1.06505127, 2.48988235, -3.55911887, -3.43500894, 2.50096692, -9.87800368]],
531
+ # "B_q":[[ 0.76019693],[-1.61641228],[ 0.79263982],[-0.70153677],[-1.0642704 ],[ 2.92345721],[-1.86444729]],
532
+ # "C_q":[[ 0.53471062, -0.22393912, 0.43508347, -0.49268284, -0.34211526,0.13852951, -0.2621668 ]],
533
+ # "D_q":[[0.]],
534
+ }]
535
+ }
536
+
537
+
538
+
539
+ grid = bmapu_builder.bmapu(data)
540
+ #grid.checker()
541
+ grid.verbose = False
542
+ grid.build('temp')
543
+
544
+ def test_run():
545
+ import temp
546
+
547
+ model = temp.model()
548
+ #model.ini({},'xy_0.json')
549
+ model.ini({},1)
550
+
551
+ model.report_x()
552
+ model.report_y()
553
+ model.report_z()
554
+
555
+ if __name__=='__main__':
556
+
557
+ test_build()
558
+ test_run()
559
+
560
+ # def test():
561
+
562
+ # from pydae.bmapu import bmapu_builder
563
+ # import pytest
564
+
565
+ # grid = bmapu_builder.bmapu('bess_pq_Hithium.hjson')
566
+ # #grid.checker()
567
+ # grid.verbose = False
568
+ # grid.build('temp')
569
+
570
+ # import temp
571
+
572
+ # model = temp.model()
573
+ # soc_ref = 0.5
574
+ # model.ini({'soc_ref_1':soc_ref},'xy_0.json')
575
+
576
+ # assert model.get_value('soc_1') == pytest.approx(soc_ref, rel=0.001)
577
+ # assert model.get_value('p_dc_1') == pytest.approx(0.0)
578
+
579
+
580
+ # ### run:
581
+ # model.Dt = 1.0
582
+ # model.run(1.0,{})
583
+ # model.run(0.5*3600,{'p_s_ref_1': 1.0}) # half an hour discharging
584
+
585
+ # assert model.get_value('soc_1') == pytest.approx(0.25, rel=0.05)
586
+
587
+ # model.run(1.0*3600,{'p_s_ref_1':-1.0}) # half an hour discharging
588
+ # model.post()
589
+
590
+ # assert model.get_value('soc_1') == pytest.approx(0.5, rel=0.05)
591
+
592
+
593
+
594
+
595
+
596
+
597
+
598
+
599
+
600
+ # #sym2model()
601
+ # if __name__ == "__main__":
602
+
603
+
604
+
605
+ # grid = bmapu_builder.bmapu(data)
606
+ # #grid.checker()
607
+ # grid.uz_jacs = True
608
+ # grid.verbose = False
609
+ # grid.construct('test_model')
610
+
611
+ # bus_name = "1"
612
+ # data_dict = {"bus":bus_name,"type":"pv_pq",
613
+ # "S_n":1e6,"U_n":400.0,"F_n":50.0,
614
+ # "X_s":0.1,"R_s":0.01,"monitor":True,
615
+ # "I_sc":8,"V_oc":42.1,"I_mp":3.56,"V_mp":33.7,
616
+ # "K_vt":-0.160,"K_it":0.065,
617
+ # "N_pv_s":25,"N_pv_p":250}
618
+
619
+ # p_W,q_var = pv_dq(grid,'1','1',data_dict)
620
+
621
+ # # grid power injection
622
+ # idx_bus = [bus['name'] for bus in grid.data['buses']].index(bus_name) # get the number of the bus where the syn is connected
623
+
624
+ # S_base = sym.Symbol('S_base', real = True)
625
+ # grid.dae['g'][idx_bus*2] += -p_W/S_base
626
+ # grid.dae['g'][idx_bus*2+1] += -q_var/S_base
627
+
628
+ # grid.compile()
629
+
630
+ # import test_model
631
+
632
+ # xy_0 = {
633
+ # "V_1": 1.0,
634
+ # "theta_1": 0.0,
635
+ # "V_2": 1.0,
636
+ # "theta_2": 0.0,
637
+ # "omega_coi": 1.0,
638
+ # "omega_2": 1.0,
639
+ # "v_dc_v_1":800
640
+ # }
641
+ # model = test_model.model()
642
+ # model.ini({'p_s_ppc_1':0.9,'q_s_ppc_1':0.2,'irrad_1':100,'temp_deg_1':75,
643
+ # 'v_ref_2':1.0},xy_0)
644
+
645
+ # #model.report_y()
646
+ # model.report_z()
647
+ # #model.report_u()
pydae/build_cffi.py CHANGED
@@ -1083,7 +1083,7 @@ class builder():
1083
1083
  ffi.compile()
1084
1084
  print(f'Compilation time: {time.time()-t_0:0.2f} s')
1085
1085
 
1086
- def build(self):
1086
+ def build(self, API=False):
1087
1087
 
1088
1088
  sys = self.sys
1089
1089
  name = self.name