pydae 0.57.2__py3-none-any.whl → 0.57.3__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,525 @@
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
+
11
+
12
+ def DTR_Symbolic(self, line_name, bus_j, bus_k):
13
+ """
14
+ Symbolic implementation of the IEEE 738 Dynamic Thermal Rating model.
15
+ Designed for integration with PyDAE or other symbolic solvers.
16
+ """
17
+ name = line_name
18
+
19
+ # --- 1. Define State Variables and Inputs (Symbols) ---
20
+ # Algebraic State (Unknown to solve for) - Lowercase
21
+ self.t_conductor = sym.Symbol(f't_conductor_{name}', real=True)
22
+
23
+ # Inputs (Control or Disturbance) - Lowercase
24
+ I_j_k,I_k_j = sym.symbols(f"I_{bus_j}_{bus_k},I_{bus_k}_{bus_j}", real=True)
25
+ #I_j_k,I_k_j = sym.symbols(f"I_{bus_j}_{bus_k}_aux,I_{bus_k}_{bus_j}_aux", real=True)
26
+
27
+ self.K_dtr = sym.Symbol(f'K_dtr_{name}', real=True)
28
+
29
+ self.i_line = I_j_k*self.K_dtr
30
+ self.t_ambient = sym.Symbol(f't_ambient_{name}', real=True)
31
+ self.v_wind = sym.Symbol(f'v_wind_{name}', real=True)
32
+ self.angle_wind = sym.Symbol(f'angle_wind_{name}', real=True)
33
+ self.irradiance = sym.Symbol(f'irradiance_{name}', real=True)
34
+
35
+ # Physical Parameters (Fixed constants) - Initial Capital
36
+ self.D_conductor = sym.Symbol(f'D_conductor_{name}', real=True, positive=True)
37
+ self.D_core = sym.Symbol(f'D_core_{name}', real=True, positive=True)
38
+ self.Emissivity = sym.Symbol(f'Emissivity_{name}', real=True)
39
+ self.Absorptivity = sym.Symbol(f'Absorptivity_{name}', real=True)
40
+ self.Elevation = sym.Symbol(f'Elevation_{name}', real=True)
41
+ self.Mass_linear = sym.Symbol(f'Mass_linear_{name}', real=True, positive=True) # [kg/m]
42
+ self.Cp = sym.Symbol(f'Cp_{name}', real=True, positive=True) # [J/(kg*C)]
43
+
44
+ # Constants - Initial Capital
45
+ self.Sigma = 5.670373e-8 # Stefan-Boltzmann constant
46
+ self.Gravity = 9.81 # Gravity
47
+
48
+ # pydae
49
+ # self.f_list = []
50
+ # self.x_list = []
51
+ # self.dae['g'] = []
52
+ # self.dae['y_ini'] = []
53
+ # self.u_dict = {}
54
+
55
+
56
+ # Initialize Default Values
57
+ # Inputs
58
+ # self.dae['u_ini_dict'].update({str(self.i_line): 0.0})
59
+ # self.dae['u_run_dict'].update({str(self.i_line): 0.0})
60
+
61
+
62
+ self.dae['u_ini_dict'].update({str(self.t_ambient): 25.0})
63
+ self.dae['u_ini_dict'].update({str(self.v_wind): 1.0})
64
+ self.dae['u_ini_dict'].update({str(self.angle_wind): 90.0})
65
+ self.dae['u_ini_dict'].update({str(self.irradiance): 1000.0})
66
+
67
+
68
+ self.dae['u_run_dict'].update({str(self.t_ambient): 25.0})
69
+ self.dae['u_run_dict'].update({str(self.v_wind): 1.0})
70
+ self.dae['u_run_dict'].update({str(self.angle_wind): 90.0})
71
+ self.dae['u_run_dict'].update({str(self.irradiance): 1000.0})
72
+
73
+ # Parameters
74
+ self.dae['params_dict'].update({str(self.D_conductor): 0.0277})
75
+ self.dae['params_dict'].update({str(self.D_core): 0.00308})
76
+ self.dae['params_dict'].update({str(self.Emissivity): 0.8})
77
+ self.dae['params_dict'].update({str(self.Absorptivity): 0.8})
78
+ self.dae['params_dict'].update({str(self.Elevation): 0.0})
79
+ # Default Mass (Approx for ACSR 20mm) and Cp (Aluminum/Steel mix)
80
+ self.dae['params_dict'].update({str(self.Mass_linear): 1.62}) # kg/m
81
+ self.dae['params_dict'].update({str(self.Cp): 900.0}) # J/kg-C
82
+
83
+ self.dae['params_dict'].update({str(self.K_dtr): 0.0}) # J/kg-C
84
+
85
+ """
86
+ Constructs the symbolic heat balance equations.
87
+ Returns:
88
+ g_list: List of algebraic equations (g(y,u) = 0)
89
+ y_list: List of algebraic variables
90
+ """
91
+
92
+ y_list_considered = ['dens','reynolds','rayleigh','nu','p_s','p_c'] # t_conductor is always considered in y or in x, it doesn't work
93
+ #y_list_considered = [] # t_conductor is always considered in y, it works
94
+ #y_list_considered = ['p_s','p_c', 'p_j'] # t_conductor is always considered in y, it works
95
+ # y_list_considered = ['rayleigh','p_s','p_c', 'p_j'] # t_conductor is always considered in y, it works
96
+ # y_list_considered = ['reynolds','rayleigh','p_s','p_c', 'p_j'] # t_conductor is always considered in y, it works
97
+ # y_list_considered = ['reynolds','rayleigh','nu','p_s','p_c', 'p_j','R_ac'] # t_conductor is always considered in y, it works
98
+ # y_list_considered = ['dens','reynolds','rayleigh','nu','p_s','p_c', 'p_j','R_ac'] # t_conductor is always considered in y, it doesn't work
99
+ #y_list_considered = ['reynolds','rayleigh'] # t_conductor is always considered in y or in x, it doesn't work
100
+
101
+ # --- A. Film Temperature ---
102
+ t_film = 0.5 * (self.t_ambient + self.t_conductor)
103
+
104
+ # --- B. Air Properties ---
105
+ # Thermal conductivity (lmb)
106
+ lmb = 2.368e-2 + 7.23e-5*t_film - 2.763e-8*t_film**2
107
+
108
+ # Air Density (dens)
109
+ dens_num = 1.293 - 1.525e-4*self.Elevation + 6.379e-9*self.Elevation**2
110
+ self.dens = dens_num / (1 + 0.00367*t_film)
111
+
112
+ # Intermediate variable for PyDAE (lowercase)
113
+
114
+ if 'dens' in y_list_considered:
115
+ dens = sym.Symbol(f'dens_{line_name}', real=True)
116
+ self.dae['g'] += [self.dens - dens]
117
+ self.dae['y_ini'] += [dens]
118
+ self.dae['y_run'] += [dens]
119
+ else:
120
+ dens = self.dens
121
+
122
+
123
+ # Dynamic Viscosity (mu_f)
124
+ mu_f = (17.239 + 4.635e-2*t_film - 2.03e-5*t_film**2) * 1e-6
125
+
126
+ # Kinematic Viscosity (uf)
127
+ uf = mu_f / dens
128
+
129
+ # --- C. Convection (p_c) Calculation ---
130
+ # Reynolds Number
131
+ self.reynolds = self.v_wind * self.D_conductor / uf
132
+ if 'reynolds' in y_list_considered:
133
+ reynolds = sym.Symbol(f'reynolds_{line_name}', real=True)
134
+ self.dae['g'] += [self.reynolds - reynolds]
135
+ self.dae['y_ini'] += [reynolds]
136
+ self.dae['y_run'] += [reynolds]
137
+ else:
138
+ reynolds = self.reynolds
139
+
140
+ # Roughness factor
141
+ Rs = self.D_core / (2 * (self.D_conductor - self.D_core))
142
+
143
+ # Forced Convection Logic
144
+ cond_high_smooth = sym.And(reynolds > 2650, Rs <= 0.05)
145
+ cond_high_rough = reynolds > 2650
146
+
147
+ B = sym.Piecewise(
148
+ (0.178, cond_high_smooth),
149
+ (0.048, cond_high_rough),
150
+ (0.641, True)
151
+ )
152
+
153
+ n = sym.Piecewise(
154
+ (0.633, cond_high_smooth),
155
+ (0.800, cond_high_rough),
156
+ (0.471, True)
157
+ )
158
+
159
+ nu_90 = B * reynolds**n
160
+
161
+ # Wind Angle Correction
162
+ phi_rad = self.angle_wind/180*np.pi
163
+ seno = sym.Abs(sym.sin(phi_rad))
164
+ eff_angle = sym.Mod(self.angle_wind, 180)
165
+
166
+ delta = sym.Piecewise(
167
+ (0.42 + 0.68 * seno**1.08, eff_angle <= 24),
168
+ (0.42 + 0.58 * seno**0.9, True)
169
+ )
170
+
171
+ nu_forz = nu_90 * delta
172
+
173
+ # Natural Convection
174
+ Gr = (self.D_conductor**3 * (self.t_conductor - self.t_ambient) * self.Gravity) / ((t_film + 273.15) * uf**2)
175
+ Pr_num = (1.9327e-10*t_film**4 - 7.9999e-7*t_film**3 + 1.1407e-3*t_film**2 - 0.4489*t_film + 1057.5) * mu_f / lmb
176
+
177
+ self.rayleigh = Gr * Pr_num
178
+ if 'rayleigh' in y_list_considered:
179
+ rayleigh = sym.Symbol(f'rayleigh_{line_name}', real=True)
180
+ self.dae['g'] += [self.rayleigh - rayleigh]
181
+ self.dae['y_ini'] += [rayleigh]
182
+ self.dae['y_run'] += [rayleigh]
183
+ else:
184
+ rayleigh = self.rayleigh
185
+
186
+
187
+ A_nat = sym.Piecewise(
188
+ (1.02, sym.And(rayleigh > 0.1, rayleigh < 1e2)),
189
+ (0.85, sym.And(rayleigh >= 1e2, rayleigh < 1e4)),
190
+ (0.48, sym.And(rayleigh >= 1e4, rayleigh < 1e7)),
191
+ (0.125, sym.And(rayleigh >= 1e7, rayleigh < 1e12)),
192
+ (0.0, True)
193
+ )
194
+
195
+ m_nat = sym.Piecewise(
196
+ (0.148, sym.And(rayleigh > 0.1, rayleigh < 1e2)),
197
+ (0.188, sym.And(rayleigh >= 1e2, rayleigh < 1e4)),
198
+ (0.25, sym.And(rayleigh >= 1e4, rayleigh < 1e7)),
199
+ (0.333, sym.And(rayleigh >= 1e7, rayleigh < 1e12)),
200
+ (0.0, True)
201
+ )
202
+
203
+ nu_nat = A_nat * rayleigh**m_nat
204
+
205
+ # Total Cooling Nusselt
206
+ self.nu = sym.Max(nu_nat, nu_forz)
207
+ if 'nu' in y_list_considered:
208
+ nu = sym.Symbol(f'nu_{line_name}', real=True)
209
+ self.dae['g'] += [self.nu - nu]
210
+ self.dae['y_ini'] += [nu]
211
+ self.dae['y_run'] += [nu]
212
+ else:
213
+ nu = self.nu
214
+
215
+ # Heat Loss Terms
216
+ self.p_c = np.pi * lmb * (self.t_conductor - self.t_ambient) * nu
217
+ if 'p_c' in y_list_considered:
218
+ p_c = sym.Symbol(f'p_c_{line_name}', real=True)
219
+ self.dae['g'] += [self.p_c - p_c]
220
+ self.dae['y_ini'] += [p_c]
221
+ self.dae['y_run'] += [p_c]
222
+ else:
223
+ p_c = self.p_c
224
+
225
+ self.p_r = np.pi * self.D_conductor * self.Sigma * self.Emissivity * ((self.t_conductor + 273.15)**4 - (self.t_ambient + 273.15)**4)
226
+ if 'p_r' in y_list_considered:
227
+ p_r = sym.Symbol(f'p_r_{line_name}', real=True)
228
+ self.dae['g'] += [self.p_r - p_r]
229
+ self.dae['y_ini'] += [p_r]
230
+ self.dae['y_run'] += [p_r]
231
+ else:
232
+ p_r = self.p_r
233
+
234
+ self.p_s = self.Absorptivity * self.irradiance * self.D_conductor
235
+ if 'p_s' in y_list_considered:
236
+ p_s = sym.Symbol(f'p_s_{line_name}', real=True)
237
+ self.dae['g'] += [self.p_s - p_s]
238
+ self.dae['y_ini'] += [p_s]
239
+ self.dae['y_run'] += [p_s]
240
+ else:
241
+ p_s = self.p_s
242
+
243
+ # Joule Heating
244
+ R_ref_const = 1.04 * 0.000071873143
245
+ self.R_ac = R_ref_const * (1 + 0.000937474 * (self.t_conductor - 20))
246
+ if 'R_ac' in y_list_considered:
247
+ R_ac = sym.Symbol(f'R_ac_{line_name}', real=True)
248
+ self.dae['g'] += [self.R_ac - R_ac]
249
+ self.dae['y_ini'] += [R_ac]
250
+ self.dae['y_run'] += [R_ac]
251
+ else:
252
+ R_ac = self.R_ac
253
+
254
+ self.p_j = self.i_line**2 * self.R_ac
255
+ if 'p_j' in y_list_considered:
256
+ p_j = sym.Symbol(f'p_j_{line_name}', real=True)
257
+ self.dae['g'] += [self.p_j - p_j]
258
+ self.dae['y_ini'] += [p_j]
259
+ self.dae['y_run'] += [p_j]
260
+ else:
261
+ p_j = self.p_j
262
+
263
+ # --- G. Final Balance Equation ---
264
+ # 0 = Heat_In - Heat_Out
265
+ # Solve for t_conductor
266
+ self.balance = self.p_j + self.p_s - self.p_c - self.p_r
267
+ dt_conductor = 1/(self.Cp*self.Mass_linear)*self.balance
268
+
269
+ # Add main algebraic equation for t_conductor
270
+ self.dae['f'] += [ dt_conductor]
271
+ self.dae['x'] += [ self.t_conductor]
272
+
273
+
274
+ self.dae['xy_0_dict'].update({f"p_line_pu_{line_name}":1})
275
+ self.dae['xy_0_dict'].update({f'dens_{line_name}':1.16})
276
+ self.dae['xy_0_dict'].update({f'reynolds_{line_name}' : 1732.85})
277
+ self.dae['xy_0_dict'].update({f'rayleigh_{line_name}' : 20558.69})
278
+ self.dae['xy_0_dict'].update({f'nu_{line_name}' : 21.49})
279
+ self.dae['xy_0_dict'].update({f'p_c_{line_name}' : 17.69})
280
+ self.dae['xy_0_dict'].update({f'p_s_{line_name}' : 22.16})
281
+ self.dae['xy_0_dict'].update({f'R_ac_{line_name}' : 0.08})
282
+ self.dae['xy_0_dict'].update({f'p_j_{line_name}' : 0.1})
283
+ self.dae['xy_0_dict'].update({f't_conductor_{line_name}' : 35.14})
284
+
285
+
286
+ self.dae['h_dict'].update({f'dens_{line_name}':dens})
287
+ self.dae['h_dict'].update({f'reynolds_{line_name}' : reynolds})
288
+ self.dae['h_dict'].update({f'rayleigh_{line_name}' : rayleigh})
289
+ self.dae['h_dict'].update({f'nu_{line_name}' : nu})
290
+ self.dae['h_dict'].update({f'p_c_{line_name}' : p_c})
291
+ self.dae['h_dict'].update({f'p_s_{line_name}' : p_s})
292
+ self.dae['h_dict'].update({f'R_ac_{line_name}' : R_ac})
293
+ self.dae['h_dict'].update({f'p_j_{line_name}' : p_j})
294
+ self.dae['h_dict'].update({f't_conductor_{line_name}' : self.t_conductor})
295
+
296
+
297
+ return self.dae['g'], self.dae['y_ini'], self.dae['y_run']
298
+
299
+
300
+ def add_line_dtr(self, line):
301
+
302
+ sys = self.system
303
+
304
+ bus_j = line['bus_j']
305
+ bus_k = line['bus_k']
306
+
307
+ idx_j = self.buses_list.index(bus_j)
308
+ idx_k = self.buses_list.index(bus_k)
309
+
310
+ self.A[self.it,idx_j] = 1
311
+ self.A[self.it,idx_k] =-1
312
+ self.A[self.it+1,idx_j] = 1
313
+ self.A[self.it+2,idx_k] = 1
314
+
315
+ line_name = f"{bus_j}_{bus_k}"
316
+
317
+ DTR_Symbolic(self, line_name, bus_j, bus_k)
318
+
319
+
320
+ g_jk = sym.Symbol(f"g_{line_name}", real=True)
321
+ b_jk = sym.Symbol(f"b_{line_name}", real=True)
322
+ bs_jk = sym.Symbol(f"bs_{line_name}", real=True)
323
+ self.G_primitive[self.it,self.it] = g_jk
324
+ self.B_primitive[self.it,self.it] = b_jk
325
+ self.B_primitive[self.it+1,self.it+1] = bs_jk/2
326
+ self.B_primitive[self.it+2,self.it+2] = bs_jk/2
327
+
328
+ if not 'dtr' in line:
329
+ line.update({'dtr':False})
330
+
331
+ if 'X_pu' in line:
332
+ if 'S_mva' in line: S_line = 1e6*line['S_mva']
333
+ R = line['R_pu']*sys['S_base']/S_line # in pu of the system base
334
+ X = line['X_pu']*sys['S_base']/S_line # in pu of the system base
335
+ G = R/(R**2+X**2)
336
+ B = -X/(R**2+X**2)
337
+ self.dae['params_dict'].update({f"g_{line_name}":G})
338
+ self.dae['params_dict'].update({f'b_{line_name}':B})
339
+
340
+ if 'X' in line:
341
+ bus_idx = self.buses_list.index(line['bus_j'])
342
+ U_base = self.buses[bus_idx]['U_kV']*1000
343
+ Z_base = U_base**2/sys['S_base']
344
+ R = line['R']/Z_base # in pu of the system base
345
+ X = line['X']/Z_base # in pu of the system base
346
+ G = R/(R**2+X**2)
347
+ B = -X/(R**2+X**2)
348
+ self.dae['params_dict'].update({f"g_{line_name}":G})
349
+ self.dae['params_dict'].update({f'b_{line_name}':B})
350
+
351
+ if 'X_km' in line:
352
+ bus_idx = self.buses_list.index(line['bus_j'])
353
+ U_base = self.buses[bus_idx]['U_kV']*1000
354
+ Z_base = U_base**2/sys['S_base']
355
+ R = line['R_km']*line['km']/Z_base # in pu of the system base
356
+
357
+ X = line['X_km']*line['km']/Z_base # in pu of the system base
358
+ G = R/(R**2+X**2)
359
+ B = -X/(R**2+X**2)
360
+ self.dae['params_dict'].update({f"g_{line_name}":G})
361
+ self.dae['params_dict'].update({f'b_{line_name}':B})
362
+
363
+ self.dae['params_dict'].update({f'bs_{line_name}':0.0})
364
+ if 'Bs_pu' in line:
365
+ if 'S_mva' in line: S_line = 1e6*line['S_mva']
366
+ Bs = line['Bs_pu']*S_line/sys['S_base'] # in pu of the system base
367
+ bs = Bs
368
+ self.dae['params_dict'][f'bs_{line_name}'] = bs
369
+
370
+ if 'Bs_km' in line:
371
+ bus_idx = self.buses_list.index(line['bus_j'])
372
+ U_base = self.buses[bus_idx]['U_kV']*1000
373
+ Z_base = U_base**2/sys['S_base']
374
+ Y_base = 1.0/Z_base
375
+ Bs = line['Bs_km']*line['km']/Y_base # in pu of the system base
376
+ bs = Bs
377
+ self.dae['params_dict'][f'bs_{line_name}'] = bs
378
+
379
+ self.it += 3
380
+
381
+
382
+ def change_line(model,bus_j,bus_k, *args,**kwagrs):
383
+ line = kwagrs
384
+ S_base = model.get_value('S_base')
385
+
386
+ line_name = f"{bus_j}_{bus_k}"
387
+ if 'X_pu' in line:
388
+ if 'S_mva' in line: S_line = 1e6*line['S_mva']
389
+ R = line['R_pu']*S_base/S_line # in pu of the model base
390
+ X = line['X_pu']*S_base/S_line # in pu of the model base
391
+ if 'X' in line:
392
+ U_base = model.get_value(f'U_{bus_j}_n')
393
+ Z_base = U_base**2/S_base
394
+ R = line['R']/Z_base # in pu of the model base
395
+ X = line['X']/Z_base # in pu of the model base
396
+ if 'X_km' in line:
397
+ U_base = model.get_value(f'U_{bus_j}_n')
398
+ Z_base = U_base**2/S_base
399
+ R = line['R_km']*line['km']/Z_base # in pu of the model base
400
+ X = line['X_km']*line['km']/Z_base # in pu of the model base
401
+ if 'Bs_km' in line:
402
+ U_base = model.get_value(f'U_{bus_j}_n')
403
+ Z_base = U_base**2/S_base
404
+ Y_base = 1.0/Z_base
405
+ Bs = line['Bs_km']*line['km']/Y_base # in pu of the model base
406
+ bs = Bs
407
+ model.set_value(f'bs_{line_name}',bs)
408
+
409
+ G = R/(R**2+X**2)
410
+ B = -X/(R**2+X**2)
411
+ model.set_value(f"g_{line_name}",G)
412
+ model.set_value(f"b_{line_name}",B)
413
+
414
+ def get_line_current(model,bus_j,bus_k, units='A'):
415
+ V_j_m,theta_j = model.get_mvalue([f'V_{bus_j}',f'theta_{bus_j}'])
416
+ V_k_m,theta_k = model.get_mvalue([f'V_{bus_k}',f'theta_{bus_k}'])
417
+ name = f'b_{bus_j}_{bus_k}'
418
+ if name in model.params_list:
419
+ B_j_k,G_j_k = model.get_mvalue([f'b_{bus_j}_{bus_k}',f'g_{bus_j}_{bus_k}'])
420
+ Bs_j_k = model.get_value(f'bs_{bus_j}_{bus_k}')
421
+ elif f'b_{bus_k}_{bus_j}' in model.params_list:
422
+ B_j_k,G_j_k = model.get_mvalue([f'b_{bus_k}_{bus_j}',f'g_{bus_k}_{bus_j}'])
423
+ Bs_j_k = model.get_value(f'bs_{bus_k}_{bus_j}')
424
+
425
+
426
+ Y_j_k = G_j_k + 1j*B_j_k
427
+ V_j = V_j_m*np.exp(1j*theta_j)
428
+ V_k = V_k_m*np.exp(1j*theta_k)
429
+ I_j_k_pu = (V_j - V_k)*Y_j_k + 1j*V_j*Bs_j_k/2
430
+
431
+ if units == 'A':
432
+ S_b = model.get_value('S_base')
433
+ U_b = model.get_value(f'U_{bus_j}_n')
434
+ I_b = S_b/(np.sqrt(3)*U_b)
435
+ I_j_k = I_j_k_pu*I_b
436
+
437
+ return I_j_k
438
+
439
+
440
+ def test_line_pu_build():
441
+
442
+ from pydae.bmapu import bmapu_builder
443
+ from pydae.build_v2 import build_mkl,build_numba
444
+
445
+ data = {
446
+ "system":{"name":"temp","S_base":100e6, "K_p_agc":0.01,"K_i_agc":0.01, "K_xif":0.01},
447
+ "buses":[{"name":"1", "P_W":0.0,"Q_var":0.0,"U_kV":20.0},
448
+ {"name":"2", "P_W":0.0,"Q_var":0.0,"U_kV":20.0}],
449
+ "lines":[{"bus_j":"1", "bus_k":"2", "X_pu":0.15,"R_pu":0.0,"Bs_pu":0.5, "S_mva":900.0, "monitor":True}],
450
+ "sources":[{"bus":"1","type":"vsource","V_mag_pu":1.0,"V_ang_rad":0.0,"K_delta":0.1}]
451
+ }
452
+
453
+ grid = bmapu_builder.bmapu(data)
454
+ grid.uz_jacs = False
455
+ grid.verbose = True
456
+ grid.construct(f'temp')
457
+ build_numba(grid.sys_dict)
458
+
459
+ def test_line_pu_ini():
460
+
461
+ import temp
462
+
463
+ model = temp.model()
464
+ model.ini({'P_2':0e6, "K_xif":0.01},'xy_0.json')
465
+ print(f"V_1 = {model.get_value('V_1'):2.2f}, V_2 = {model.get_value('V_2'):2.2f}")
466
+
467
+ model.report_y()
468
+
469
+ def test_line_km_build():
470
+
471
+ from pydae.bmapu import bmapu_builder
472
+ from pydae.build_v2 import build_mkl,build_numba
473
+
474
+ R_km = 0.0268 # (Ω/km)
475
+ X_km = 0.2766 # (Ω/km)
476
+ B_km = 4.59e-6 # (℧-1/Km)
477
+
478
+ N_parallel = 44.0
479
+
480
+ Lenght_km = 22000.0/N_parallel
481
+
482
+ data = {
483
+ "system":{"name":"temp","S_base":100e6, "K_p_agc":0.01,"K_i_agc":0.01, "K_xif":0.01},
484
+ "buses":[{"name":"1", "P_W":0.0,"Q_var":0.0,"U_kV":400.0},
485
+ {"name":"2", "P_W":5000e6,"Q_var":0.0,"U_kV":400.0}],
486
+ "lines":[{"bus_j":"1", "bus_k":"2", 'X_km':X_km/44, 'R_km':R_km/44, 'Bs_km':B_km*44, "km":Lenght_km, "monitor":True}],
487
+ "sources":[{"bus":"1","type":"vsource","V_mag_pu":1.0,"V_ang_rad":0.0,"K_delta":0.1}]
488
+ }
489
+
490
+ grid = bmapu_builder.bmapu(data)
491
+ grid.uz_jacs = False
492
+ grid.verbose = True
493
+ grid.construct(f'temp')
494
+ build_numba(grid.sys_dict)
495
+
496
+ def test_line_km_ini():
497
+
498
+ import temp
499
+
500
+ model = temp.model()
501
+ model.ini({'P_2':5000e6,'Q_2':0, "K_xif":0.01},'xy_0.json')
502
+ print(f"V_1 = {model.get_value('V_1'):2.2f}, V_2 = {model.get_value('V_2'):2.2f}")
503
+
504
+ print("report_y:")
505
+ model.report_y()
506
+ print("-----------------------------------------------------------------------")
507
+ print("report_z:")
508
+ model.report_z()
509
+
510
+ U_1 = 400e3
511
+ U_2 = 400e3
512
+ Bs = 4.59e-6*22000
513
+ Q = U_1**2*Bs/2 + U_2**2*Bs/2
514
+ print(f"Q = {Q/1e6:2.2f} Mvar")
515
+
516
+
517
+ if __name__ == "__main__":
518
+
519
+ #test_line_pu_build()
520
+ #test_line_pu_ini()
521
+
522
+ test_line_km_build()
523
+ test_line_km_ini()
524
+
525
+