pydae 0.56.3__py3-none-any.whl → 0.56.4__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.
@@ -4,11 +4,5 @@
4
4
  "V_2": 1.0,
5
5
  "theta_2": 0.0,
6
6
  "omega_coi": 1.0,
7
- "omega_1": 1.0,
8
- "e1q_1": 1.0,
9
- "i_q_1": 0.5,
10
- "v_f_1": 1.5,
11
- "v_r_1": 1.0,
12
- "xi_v_1": 10000.0,
13
- "x_cb_1": 2.0
7
+ "omega_2": 1.0
14
8
  }
@@ -4,11 +4,5 @@
4
4
  "V_2": 1.0,
5
5
  "theta_2": 0.0,
6
6
  "omega_coi": 1.0,
7
- "omega_1": 1.0,
8
- "e1q_1": 1.0,
9
- "i_q_1": 0.5,
10
- "v_f_1": 1.5,
11
- "v_r_1": 1.0,
12
- "xi_v_1": 10000.0,
13
- "x_cb_1": 2.0
7
+ "omega_2": 1.0
14
8
  }
pydae/bmapu/pvs/pvs.py CHANGED
@@ -29,12 +29,15 @@ def add_pvs(grid):
29
29
  else:
30
30
  name = bus_name
31
31
 
32
+
33
+
32
34
  for gen_id in range(100):
33
35
  if name not in grid.generators_id_list:
34
36
  grid.generators_id_list += [name]
35
37
  break
36
38
  else:
37
39
  name = name + f'_{gen_id}'
40
+
38
41
 
39
42
  item['name'] = name
40
43
 
@@ -0,0 +1,325 @@
1
+ import numpy as np
2
+ import json,hjson
3
+ from pydae.utils import read_data
4
+
5
+
6
+ class Desing:
7
+
8
+ def __init__(self, data):
9
+
10
+ self.data = read_data(data)
11
+ self.z_decimals = 5
12
+ self.lines_impedance_format = 'Z_km' # 'Z_km', 'pu-s', 'Z'
13
+
14
+
15
+ self.S_base = self.data['S_base']
16
+ self.P_inv_max = self.data['P_inv_max']
17
+ self.S_inv_max = self.data['S_inv_max']
18
+ self.U_lv = self.data['U_lv']
19
+ self.U_mv = self.data['U_mv']
20
+ self.U_hv = self.data['U_hv']
21
+ self.F = self.data['F']
22
+ self.M = self.data['M']
23
+ self.N = self.data['N']
24
+ self.S_bess_mva = self.data['S_bess_mva']
25
+ self.S_bess_storage_kWh = self.data['S_bess_storage_kWh']
26
+ self.Irrad_max = self.data['Irrad_max']
27
+ self.Area_form_factor = self.data['Area_form_factor']
28
+ self.PV_efficiency = self.data['PV_efficiency']
29
+ self.Z_trafo_poi_pu = self.data['Z_trafo_poi_pu']
30
+ self.I_mp = data["I_mp"]
31
+ self.V_mp = data["V_mp"]
32
+ self.V_dc_n = data["V_dc_n"]
33
+
34
+ self.cables = [
35
+ {'name': '1X95', 'R_dc_km': 0.320, 'R_ac_km': 0.403, 'X_km': 0.128, 'muC_km': 0.187, 'R_0_km': 1.050, 'X_0_km': 0.391, 'muC_0_km': 0.187, 'I_max_aire': 255, 'I_max_direct': 205, 'I_max_tube': 190, 'I_cc_max': 8930, 'I_cc_0_max': 3140},
36
+ {'name': '1X150', 'R_dc_km': 0.206, 'R_ac_km': 0.262, 'X_km': 0.119, 'muC_km': 0.216, 'R_0_km': 0.890, 'X_0_km': 0.341, 'muC_0_km': 0.216, 'I_max_aire': 335, 'I_max_direct': 260, 'I_max_tube': 245, 'I_cc_max': 14100, 'I_cc_0_max': 3470},
37
+ {'name': '1X240', 'R_dc_km': 0.125, 'R_ac_km': 0.161, 'X_km': 0.109, 'muC_km': 0.260, 'R_0_km': 0.768, 'X_0_km': 0.297, 'muC_0_km': 0.260, 'I_max_aire': 455, 'I_max_direct': 345, 'I_max_tube': 320, 'I_cc_max': 22600, 'I_cc_0_max': 3810},
38
+ {'name': '1X400', 'R_dc_km':0.0778, 'R_ac_km': 0.102, 'X_km': 0.103, 'muC_km': 0.313, 'R_0_km': 0.650, 'X_0_km': 0.237, 'muC_0_km': 0.313, 'I_max_aire': 610, 'I_max_direct': 445, 'I_max_tube': 415, 'I_cc_max': 37600, 'I_cc_0_max': 4300},
39
+ {'name': '1X500', 'R_dc_km':0.0605, 'R_ac_km': 0.084, 'X_km': 0.099, 'muC_km': 0.329, 'R_0_km': 0.618, 'X_0_km': 0.225, 'muC_0_km': 0.329, 'I_max_aire': 715, 'I_max_direct': 505, 'I_max_tube': 480, 'I_cc_max': 47000, 'I_cc_0_max': 4810},
40
+ {'name': '1X630', 'R_dc_km':0.0469, 'R_ac_km':0.0636, 'X_km': 0.095, 'muC_km': 0.396, 'R_0_km': 0.561, 'X_0_km': 0.195, 'muC_0_km': 0.396, 'I_max_aire': 830, 'I_max_direct': 575, 'I_max_tube': 545, 'I_cc_max': 59200, 'I_cc_0_max': 5140}
41
+ ]
42
+
43
+
44
+ def design(self):
45
+
46
+ M = self.M
47
+ N = self.N
48
+ self.S_plant = self.S_inv_max*N*M + 1.2*self.S_bess_mva*1e6
49
+ S_base = self.S_base
50
+
51
+ self.LV_MV_trafo_X_pu = 0.05
52
+ self.LV_MV_trafo_R_pu = 0.01
53
+
54
+ S_trafo_poi = M*N*self.S_inv_max*1.1
55
+
56
+ # Area_inv = Long_n * Long_m
57
+ # Long_n = Area_form_factor * Long_m
58
+ # Area_inv = Area_form_factor * Long_m**2
59
+
60
+ Area_inv = self.P_inv_max/(self.Irrad_max*self.PV_efficiency)
61
+ self.Long_m = np.sqrt( Area_inv/self.Area_form_factor )
62
+ self.Long_n = self.Area_form_factor * self.Long_m
63
+
64
+ S_grid_line = self.S_plant*2.0
65
+
66
+ self.base_data = {
67
+ "system":{"name":f"pv_{M}_{N}","S_base":S_base,"K_p_agc":0.0,"K_i_agc":0.0,"K_xif":0.01},
68
+ "buses":[
69
+ {"name": "POIMV","P_W":0.0,"Q_var":0.0,"U_kV":self.U_mv/1e3},
70
+ {"name": "POI","P_W":0.0,"Q_var":0.0,"U_kV":self.U_hv/1e3},
71
+ {"name": "GRID","P_W":0.0,"Q_var":0.0,"U_kV":self.U_hv/1e3},
72
+ {"name": "BESS","P_W":0.0,"Q_var":0.0,"U_kV":self.U_lv/1e3},
73
+ ],
74
+ "lines":[
75
+ {"bus_j":"POI","bus_k":"GRID","X_pu":0.001*S_base/S_grid_line,"R_pu":0.0,"Bs_pu":0.0,"S_mva":S_base/1e6, 'sym':True, 'monitor':True},
76
+ {"bus_j":"BESS","bus_k": "POIMV","X_pu":0.01,"R_pu":0.0,"Bs_pu":0.0,"S_mva":S_base/1e6, 'sym':True, 'monitor':True},
77
+ ],
78
+ "transformers":[{"bus_j":"POIMV","bus_k": "POI","X_pu":0.1,"R_pu":0.0,"Bs_pu":0.0,"S_mva":self.S_plant/1e6}],
79
+ "pvs":[],
80
+ "sources":[{"type":"genape","bus":"GRID",
81
+ "S_n":1000e6,"F_n":50.0,"X_v":0.001,"R_v":0.0,
82
+ "K_delta":0.001,"K_alpha":1e-6}],
83
+ "vscs":[{"type":"bess_pq","bus":"BESS","E_kWh":self.S_bess_storage_kWh,"S_n":self.S_bess_mva*1e6,
84
+ "soc_ref":0.5,
85
+ "socs":[0.0, 0.1, 0.2, 0.8,0.9,1.0],
86
+ "es":[1, 1.08, 1.13, 1.17, 1.18,1.25]}
87
+ ],
88
+ }
89
+
90
+
91
+ Z_base_trafo_poi = self.U_mv**2/S_trafo_poi
92
+ Z_trafo_poi = Z_base_trafo_poi*self.Z_trafo_poi_pu
93
+ I_cc_max = self.U_mv/(np.sqrt(3)*Z_trafo_poi)
94
+
95
+ for it, item in enumerate(self.cables):
96
+ if item['I_cc_max'] > I_cc_max:
97
+ print(f"Short circuit designed cable ({I_cc_max/1e3:0.2f} kA): {item['name']}")
98
+ idx_cc = it
99
+ break
100
+
101
+ I_max = 1.0*N*self.S_inv_max/(np.sqrt(3)*self.U_mv)
102
+
103
+ for it, item in enumerate(self.cables):
104
+ if item['I_max_tube'] > I_max:
105
+ print(f"Nominal current designed cable ({I_max:0.2f} A): {item['name']}")
106
+ idx_n = it
107
+ break
108
+
109
+ if idx_cc > idx_n:
110
+ idx_cable = idx_cc
111
+ else:
112
+ idx_cable = idx_n
113
+
114
+ print(f"Cable: {self.cables[idx_cable]['name']}")
115
+
116
+ self.section_cable = float(self.cables[idx_cable]['name'].split('X')[-1])
117
+ self.R_km_cable = self.cables[idx_cable]['R_ac_km']
118
+ self.X_km_cable = self.cables[idx_cable]['X_km']
119
+ self.B_km_cable = 2*np.pi*50*self.cables[idx_cable]['muC_km']*1e-6
120
+
121
+
122
+
123
+
124
+ P_mp = self.I_mp*self.V_mp
125
+ N_pv_s = int(self.V_dc_n/self.V_mp)
126
+ N_pv_p = int(self.P_inv_max/(P_mp*N_pv_s))
127
+
128
+ S_feeder = N*self.S_inv_max
129
+ I_feeder = S_feeder/(np.sqrt(3)*self.U_mv)
130
+
131
+ pos_mv_poi_m_pu = 0.0
132
+ pos_mv_poi_m = pos_mv_poi_m_pu * (M-1)*self.Long_m
133
+ pos_mv_poi_n = 0.0
134
+
135
+ for i_m in range(1,M+1):
136
+ name_j = "POIMV"
137
+ monitor = True
138
+ pos_m = (i_m-1) * self.Long_m
139
+
140
+
141
+ for i_n in range(1,N+1):
142
+ name = f"{i_m}".zfill(2) + f"{i_n}".zfill(2)
143
+ name_k = 'MV' + name
144
+
145
+ self.base_data['buses'].append({"name":f"LV{name}","P_W":0.0,"Q_var":0.0,"U_kV":self.U_lv/1e3})
146
+ self.base_data['buses'].append({"name":f"MV{name}","P_W":0.0,"Q_var":0.0,"U_kV":self.U_mv/1e3})
147
+
148
+
149
+ if i_n == 1:
150
+ Long = np.abs(pos_mv_poi_m - pos_m) + self.Long_n*0.5
151
+ else:
152
+ Long = self.Long_n
153
+
154
+ pos_n = (i_n-1) * self.Long_n + self.Long_n/2
155
+ #print(f'pos_m = {pos_m:5.1f}, pos_n = {pos_n:5.1f}')
156
+
157
+ # LV-MV Trafos
158
+ S_trafo_n = 1.2*self.S_inv_max
159
+ X_pu = self.LV_MV_trafo_X_pu*self.S_base/S_trafo_n
160
+ R_pu = self.LV_MV_trafo_R_pu*self.S_base/S_trafo_n
161
+
162
+
163
+
164
+ self.base_data['lines'].append({"bus_j":f"LV{name}","bus_k":f"MV{name}","X_pu":np.round(X_pu,self.z_decimals),"R_pu":np.round(R_pu,self.z_decimals),"Bs_pu":0.0,"S_mva":S_base/1e6,"monitor":False})
165
+
166
+
167
+ # MV Cables:
168
+ S_b = self.S_base
169
+ Z_b = self.U_mv**2/S_b
170
+ R_cable_pu = self.R_km_cable*Long/1e3/Z_b
171
+ X_cable_pu = self.X_km_cable*Long/1e3/Z_b
172
+ B_cable_pu = self.B_km_cable*Long/1e3*Z_b
173
+
174
+ print(f"{name_k} - {name_j}, Cable: {self.cables[idx_cable]['name']}, R_km = {self.R_km_cable:3.4f}, X_km = {self.X_km_cable:3.4f}, B_km = {self.B_km_cable:3.4f}, Long_km = {Long/1000:2.5f}")
175
+
176
+ # LV/MV Transformers
177
+
178
+ # MV Feeders lines
179
+ if self.lines_impedance_format == 'pu-s':
180
+ self.base_data['lines'].append({"bus_j":f"{name_k}","bus_k":f"{name_j}","X_pu":X_cable_pu,"R_pu":R_cable_pu,"Bs_pu":B_cable_pu,"S_mva":S_base/1e6,"monitor":monitor})
181
+
182
+ if self.lines_impedance_format == 'Z_km':
183
+ X_km_cable = np.round(self.X_km_cable,self.z_decimals)
184
+ R_km_cable = np.round(self.R_km_cable,self.z_decimals)
185
+ B_km_cable = np.round(self.B_km_cable,self.z_decimals)
186
+
187
+ self.base_data['lines'].append({"bus_j":f"{name_k}","bus_k":f"{name_j}","X_km": X_km_cable,"R_km": R_km_cable,"Bs_km": B_km_cable,"km":np.round(Long/1e3,4),"monitor":monitor})
188
+
189
+
190
+ name_j = name_k
191
+ self.base_data['pvs'].append({"bus":f"LV{name}","type":"pv_dq_d","S_n":self.S_inv_max,"U_n":self.U_lv,"F_n":50.0,"X_s":0.1,"R_s":0.0001,"monitor":False,
192
+ "I_sc":8,"V_oc":42.1,"I_mp":self.I_mp,"V_mp":self.V_mp,"K_vt":-0.160,"K_it":0.065,"N_pv_s":N_pv_s,"N_pv_p":N_pv_p})
193
+
194
+ monitor = False
195
+
196
+ with open(f'pv_{M}_{N}.json','w') as fobj:
197
+ fobj.write(json.dumps(self.base_data, indent=2))
198
+
199
+ def report(self):
200
+
201
+ M = self.M
202
+ N = self.N
203
+
204
+ latex = r'''
205
+ \begin{table}
206
+ \centering
207
+ \caption{Nominal characteristics of PV inverters and transformers of the benchmark 2$\times$3 PV park.}
208
+ \begin{tabular}{lr}
209
+ \toprule
210
+ \multicolumn{2}{c}{PV inverters} \\ \midrule
211
+ Rated voltage & inverter_rated_voltage V \\ \hline
212
+ Rated power & inverter_rated_mva MVA \\ \hline
213
+ Rated power factor & inverter_pf (ind/cap)\\ \midrule
214
+ \multicolumn{2}{c}{MV/LV PV transformers} \\ \midrule
215
+ Rated voltages & U_mv_kV/U_lv_kV kV \\ \hline
216
+ Rated power & MV_LV_rated_mva MVA \\ \hline
217
+ Short-circuit impedance & 0.06 p.u. \\ \hline
218
+ $X_{sc}/R_{sc}$ & 10 \\ \midrule
219
+ \multicolumn{2}{c}{HV/MV POI transformer} \\ \midrule
220
+ Rated voltages & U_hv_kV/U_mv_kV kV \\ \hline
221
+ Rated power & poi_trafo_rated_power MVA \\ \hline
222
+ Short-circuit impedance & 0.13 p.u. \\ \hline
223
+ $X_{sc}/R_{sc}$ & 10\\ \midrule
224
+ \multicolumn{2}{c}{MV branches} \\
225
+ \midrule
226
+ first_feeder_segment_string
227
+ Length MV\#\# - MV\#\# & length_segments m \\ \hline
228
+ Cross section & section_cable mm$^2$\\ \hline
229
+ Resistance & R_km_cable $\Omega$/km \\ \hline
230
+ Reactance & X_km_cable $\Omega$/km \\ %\hline
231
+ % Susceptance & B_km_cable S/km \\
232
+ \bottomrule
233
+ \end{tabular}
234
+ \label{tab:PV_MxN}
235
+ \end{table}
236
+ '''
237
+
238
+ latex = latex.replace('inverter_rated_voltage', f'{self.U_lv:0.0f}')
239
+ latex = latex.replace('inverter_rated_mva', f'{self.S_inv_max/1e6:0.1f}')
240
+ latex = latex.replace('inverter_pf', f'{self.P_inv_max/self.S_inv_max:0.2f}')
241
+ latex = latex.replace('U_mv_kV', f'{self.U_mv/1e3:0.0f}').replace('U_lv_kV', f'{self.U_lv/1e3}')
242
+ latex = latex.replace('inverter_pf', f'{self.P_inv_max/self.S_inv_max:0.2f}')
243
+ latex = latex.replace('U_mv_kV', f'{self.U_mv/1e3:0.0f}').replace('U_hv_kV', f'{self.U_hv/1e3:0.0f}')
244
+ latex = latex.replace('poi_trafo_rated_power', f'{self.S_plant/1e6:0.0f}')
245
+
246
+
247
+ pos_mv_poi_m_pu = 0.0
248
+ pos_mv_poi_m = pos_mv_poi_m_pu * (M-1)*self.Long_m
249
+ pos_mv_poi_n = 0.0
250
+
251
+ first_feeder_segment_string = ''
252
+ for i_m in range(1,M+1):
253
+ name_j = "POIMV"
254
+ monitor = True
255
+ pos_m = (i_m-1) * self.Long_m
256
+
257
+
258
+ for i_n in range(1,N+1):
259
+ name = f"{i_m}".zfill(2) + f"{i_n}".zfill(2)
260
+ name_k = 'MV' + name
261
+
262
+ self.base_data['buses'].append({"name":f"LV{name}","P_W":0.0,"Q_var":0.0,"U_kV":self.U_lv/1e3})
263
+ self.base_data['buses'].append({"name":f"MV{name}","P_W":0.0,"Q_var":0.0,"U_kV":self.U_mv/1e3})
264
+
265
+
266
+ if i_n == 1:
267
+ Long = np.abs(pos_mv_poi_m - pos_m) + self.Long_n*0.5
268
+ else:
269
+ Long = self.Long_n
270
+
271
+ if i_n == 1:
272
+ first_feeder_segment_string += f' Length {name_k}-{name_j} & {Long:0.0f} m' + r'\\ \hline'
273
+ if i_m < M:
274
+ first_feeder_segment_string += '\n'
275
+ else:
276
+ self.length_segments = Long
277
+
278
+ latex = latex.replace('first_feeder_segment_string', first_feeder_segment_string)
279
+ latex = latex.replace('length_segments', f'{self.length_segments:0.0f}')
280
+
281
+ latex = latex.replace('length_segments', f'{self.length_segments:0.0f}')
282
+ latex = latex.replace('R_km_cable', f'{self.R_km_cable:0.4f}')
283
+ latex = latex.replace('X_km_cable', f'{self.X_km_cable:0.4f}')
284
+
285
+ if self.B_km_cable > 0.001:
286
+ latex = latex.replace('B_km_cable', f'{self.B_km_cable:0.4f}')
287
+ else:
288
+ latex = latex.replace('B_km_cable', '0')
289
+
290
+ latex = latex.replace('section_cable', f'{self.section_cable:0.0f}')
291
+ latex = latex.replace('PV_MxN', f'PV_{M}x{N}')
292
+
293
+ return latex
294
+
295
+
296
+ if __name__ == "__main__":
297
+
298
+ data = {
299
+ "M": 2,
300
+ "N": 3,
301
+ "S_base": 10e6,
302
+ "P_inv_max": 3e6, # W
303
+ "S_inv_max": 3e6/0.85,
304
+ "U_lv": 800,
305
+ "U_mv": 20e3,
306
+ "U_hv": 132e3,
307
+ "F": 50, #Nominal Frequency (Hz)
308
+ "S_bess_mva": 1,
309
+ "S_bess_storage_kWh": 250,
310
+ "Irrad_max": 1000, # W/m_2
311
+ "Area_form_factor": 1.0,
312
+ "PV_efficiency": 0.1,
313
+ "Z_trafo_poi_pu": 0.1,
314
+ "I_mp" : 3.56, # PV module current at MP
315
+ "V_mp" : 33.7, # PV module voltage at MP
316
+ "V_dc_n" : 1200 # DC nominal voltage
317
+ }
318
+
319
+ d = Desing(data)
320
+ d.design()
321
+ print(d.report())
322
+
323
+ #print(d.base_data)
324
+
325
+
pydae/tools.py CHANGED
@@ -8,7 +8,9 @@
8
8
 
9
9
  import numpy as np
10
10
  import json
11
-
11
+ import hjson
12
+ import requests
13
+ import os
12
14
 
13
15
  def save(json_file,dictionary, sort_keys=False, indent=4):
14
16
  '''
@@ -34,14 +36,14 @@ def save(json_file,dictionary, sort_keys=False, indent=4):
34
36
 
35
37
 
36
38
 
37
- def load(json_file):
39
+ def load(data_input):
38
40
  '''
39
- Read json file and convert it to dictionary.
41
+ Read json or hjson file and convert it to dictionary.
40
42
 
41
43
  Parameters
42
44
  ----------
43
- json_file : path
44
- Path of the json data file.
45
+ data_input : path
46
+ Path of the json or hjson data file.
45
47
 
46
48
  Returns
47
49
  -------
@@ -50,12 +52,21 @@ def load(json_file):
50
52
 
51
53
  '''
52
54
 
53
- with open(json_file, 'r') as fobj:
54
- json_data = fobj.read()
55
-
56
- json_data = json_data.replace("'",'"')
57
- data_dictionary = json.loads(json_data)
58
-
55
+ if type(data_input) == str:
56
+ if 'http' in data_input:
57
+ url = data_input
58
+ resp = requests.get(url)
59
+ data_dictionary = hjson.loads(resp.text)
60
+ else:
61
+ if os.path.splitext(data_input)[1] == '.json':
62
+ with open(data_input,'r') as fobj:
63
+ data_dictionary = json.loads(fobj.read().replace("'",'"'))
64
+ if os.path.splitext(data_input)[1] == '.hjson':
65
+ with open(data_input,'r') as fobj:
66
+ data_dictionary = hjson.loads(fobj.read().replace("'",'"'))
67
+ elif type(data_input) == dict:
68
+ data_dictionary = data_input
69
+
59
70
  return data_dictionary
60
71
 
61
72
 
@@ -127,28 +127,31 @@ def sofc_dcdcac_gf(grid,data,name,bus_name):
127
127
  Tau_h2 = sym.Symbol(f'Tau_h2_{name}', real=True) # ?? (units?)
128
128
  Tau_h2o = sym.Symbol(f'Tau_h2o_{name}', real=True) # ?? (units?)
129
129
  Tau_o2 = sym.Symbol(f'Tau_o2_{name}', real=True) # ?? (units?)
130
- N0 = sym.Symbol(f'N0_{name}', real=True) # ?? (units?)
130
+ N_s = sym.Symbol(f'N_s_{name}', real=True) # ?? (units?)
131
+ N_p = sym.Symbol(f'N_p_{name}', real=True) # ?? (units?)
131
132
  E0 = sym.Symbol(f'E0_{name}', real=True) # ?? (units?)
132
133
  R_ohm = sym.Symbol(f'R_ohm_{name}', real=True) # ?? (units?)
133
134
 
134
135
  F = 96487.3 # Faraday's constant (units?)
135
136
  R = 8.314 # Universal gas constant (units?)
136
137
  i_dc = i_dc_ref + Di_dc_ref + sym.Piecewise((1.0,i_l<1.0),(250.0,i_l>250.0),(i_l,True))
138
+ i_cell = i_dc/N_p
137
139
 
138
- #formulacion del sistema de ecuaciones del modelo
140
+ #formulacion del sistema de ecuaciones del modelo de una única celda
139
141
  # dynamic equations
140
- dq_h2 = (2*K_r/U_opt*i_dc - q_h2)/Tau_f
141
- dp_h2 = (-p_h2 + (-2*K_r*i_dc + q_h2)/K_h2)/Tau_h2
142
- dp_h2o = (2*K_r*i_dc/K_h2o - p_h2o)/Tau_h2o
143
- dp_o2 = ((q_h2/R_h01 - K_r*i_dc)/K_o2 - p_o2)/Tau_o2
142
+ dq_h2 = (2*K_r/U_opt*i_cell - q_h2)/Tau_f
143
+ dp_h2 = (-p_h2 + (-2*K_r*i_cell + q_h2)/K_h2)/Tau_h2
144
+ dp_h2o = (2*K_r*i_cell/K_h2o - p_h2o)/Tau_h2o
145
+ dp_o2 = ((q_h2/R_h01 - K_r*i_cell)/K_o2 - p_o2)/Tau_o2
144
146
 
145
147
  dDi_dc_ref = di_dc_ref - 1e-6*Di_dc_ref
146
148
 
147
- V_ernst = R*temp/(2*F)*sym.ln(p_h2*sym.sqrt(p_o2)/p_h2o)*N0
149
+ V_ernst = R*temp/(2*F)*sym.ln(p_h2*sym.sqrt(p_o2)/p_h2o)
148
150
  P_dc = v_fc_dc*i_dc
149
151
 
152
+
150
153
  # Algebraic equations
151
- g_v_fc_dc = V_ernst + E0*N0 - R_ohm*N0*i_dc - v_fc_dc
154
+ g_v_fc_dc = (V_ernst + E0 - R_ohm*i_cell)*N_s - v_fc_dc
152
155
 
153
156
 
154
157
  grid.dae['f'] += [dq_h2,dp_h2,dp_h2o,dp_o2,dDi_dc_ref]
@@ -181,7 +184,8 @@ def sofc_dcdcac_gf(grid,data,name,bus_name):
181
184
  grid.dae['params_dict'].update({f'Tau_h2_{name}':26.1})
182
185
  grid.dae['params_dict'].update({f'Tau_h2o_{name}':78.3})
183
186
  grid.dae['params_dict'].update({f'Tau_o2_{name}':2.91})
184
- grid.dae['params_dict'].update({f'N0_{name}':450})
187
+ grid.dae['params_dict'].update({f'N_s_{name}':450})
188
+ grid.dae['params_dict'].update({f'N_p_{name}':10})
185
189
  grid.dae['params_dict'].update({f'E0_{name}':1.18})
186
190
  grid.dae['params_dict'].update({f'R_ohm_{name}':3.2813e-004})
187
191
 
pydae/utils/svg2pdf.py ADDED
@@ -0,0 +1,56 @@
1
+ import os
2
+ import subprocess
3
+ import json
4
+ import time
5
+
6
+
7
+
8
+ def load_converted_data(json_path):
9
+ if os.path.exists(json_path):
10
+ with open(json_path, "r") as f:
11
+ return json.load(f)
12
+ return {}
13
+
14
+ def save_converted_data(json_path, data):
15
+ with open(json_path, "w") as f:
16
+ json.dump(data, f, indent=2)
17
+
18
+ def get_file_mod_time(path):
19
+ return os.path.getmtime(path)
20
+
21
+ def convert_all_svgs_to_pdf(input_dir, output_dir, json_path="converted_files.json", inkscape_path=r"C:\Program Files\Inkscape\bin\inkscape.exe"):
22
+ os.makedirs(output_dir, exist_ok=True)
23
+ converted_data = load_converted_data(json_path)
24
+ updated_data = {}
25
+
26
+ for filename in os.listdir(input_dir):
27
+ if filename.lower().endswith(".svg"):
28
+ input_svg = os.path.join(input_dir, filename)
29
+ output_pdf = os.path.join(output_dir, os.path.splitext(filename)[0] + ".pdf")
30
+ mod_time = get_file_mod_time(input_svg)
31
+
32
+ # Skip if unchanged
33
+ if filename in converted_data and converted_data[filename] == mod_time:
34
+ print(f"Skipping (unchanged): {filename}")
35
+ updated_data[filename] = mod_time
36
+ continue
37
+
38
+ # Convert
39
+ try:
40
+ subprocess.run([
41
+ inkscape_path,
42
+ input_svg,
43
+ "--export-type=pdf",
44
+ f"--export-filename={output_pdf}"
45
+ ], check=True)
46
+ print(f"Converted: {filename}")
47
+ updated_data[filename] = mod_time
48
+ except subprocess.CalledProcessError as e:
49
+ print(f"Failed to convert {filename}: {e}")
50
+
51
+ save_converted_data(json_path, updated_data)
52
+
53
+ def svg2pdf():
54
+ # Example usage
55
+ convert_all_svgs_to_pdf("svg", "figs")
56
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pydae
3
- Version: 0.56.3
3
+ Version: 0.56.4
4
4
  Summary: =====
5
5
  Keywords: engineering
6
6
  Author-email: Juan Manuel Mauricio <jmmauricio6@gmail.com>
@@ -1,5 +1,5 @@
1
1
  pydae/.gitignore,sha256=c1jUQV9WXX3PWrlOzHiKvUWFomLJUrfYogbU7nYwAwc,288
2
- pydae/__init__.py,sha256=WQV5HZES-dq8iqVUH5ysQUKQ576WJYMI2xCknHeBmEc,106
2
+ pydae/__init__.py,sha256=tC7ODVqBfv538NrCOaJBs4cHTgNvcGoqT4GXtmp5yfE,106
3
3
  pydae/b_pu.py,sha256=FdRRVieJLQDYPwYNWhbXJ0SXvf4jtPdbvIZTKWi16I0,6775
4
4
  pydae/bpu.py,sha256=FdRRVieJLQDYPwYNWhbXJ0SXvf4jtPdbvIZTKWi16I0,6775
5
5
  pydae/build.py,sha256=ECfc_doyK9PhrjEAlWJGLfirQmpT24XuYNxUgtrXI74,46151
@@ -41,13 +41,13 @@ pydae/temp.py,sha256=K_4SgF8_b6a9zkSCYM_1Ta9olJhpafuduiHSYCzLKQc,60271
41
41
  pydae/temp_ini_cffi.c,sha256=IOhBAj5NvJB7jtw7jhAlsbxWAyk4SXln_WbtQ-te_2k,42517
42
42
  pydae/temp_run_cffi.c,sha256=KXXwvj8Vco20aFVEGrXwv66w941e3Ko0kks4C3kI7nY,42511
43
43
  pydae/temp_trap_cffi.c,sha256=6TrwKnjjB1S_QDRMY57oz09trX0CjZSQHa0pOaWW88o,33135
44
- pydae/tools.py,sha256=MdmvKyKvbcRU3U4zKQ34Y_ksZXkuwT31EmGe5sWEWOc,4223
44
+ pydae/tools.py,sha256=f7VexbXpH0JOLFeH-l0o2vDG3faN7ai3OPlLldQqg9k,4765
45
45
  pydae/train_tools.py,sha256=8I-bKxIi0Ab0SXB_gKKUwk4n5wFipbDUdUjtFPl_rAE,6115
46
46
  pydae/transformers.py,sha256=tVei7P88EFJWx-68NjscVL8eYFJYECpQtRgS6BH_3B0,17289
47
47
  pydae/xy_0.json,sha256=uX-p5beHXjMDIkSTd5egfdq2UOq4n37oHpB8XJbpUts,240
48
48
  pydae/.ipynb_checkpoints/models-checkpoint.py,sha256=N8-m1Dk6HdmgpELHhEudVGup3ZO_b_DrJls7nanY4O8,58246
49
49
  pydae/bmapu/__init__.py,sha256=r7mgVYduCfuZ_pqaNXp_Y6Y-L3wcOKT4dzBLPsr8oak,105
50
- pydae/bmapu/bmapu_builder.py,sha256=JHMyJdW4eOR4WdSjYMyb5tuBbX_o0pOpU01E3Qap_i8,25832
50
+ pydae/bmapu/bmapu_builder.py,sha256=QwP2bEmLQAIO2aIG_1qaijipslW9kYDLtaqdBQ9qn3E,27450
51
51
  pydae/bmapu/avrs/__init__.py,sha256=JhpeBVii27qLqxJqimWLBYwjPgXrz3hYq7PQQf2ssGs,99
52
52
  pydae/bmapu/avrs/avr_antiw.py,sha256=WtezvBDcr82VEqEmbSMdfKS_jdeI-ZcBan5FWqTURd4,15589
53
53
  pydae/bmapu/avrs/avrs.py,sha256=sWz29mcLMPcK7N0NiCtkF7MszAkv-RNAvo8Vst81m2A,1104
@@ -99,20 +99,22 @@ pydae/bmapu/loads/xy_0.json,sha256=3S2kNH4SMSQdhG49UC_it-0iqZXOo_lXmf7QgLwXls8,2
99
99
  pydae/bmapu/loads/zip.hjson,sha256=fFe-SW6l4fy4zJ1RNjUhcgVORulc1KYLpZjo4CmUUBI,471
100
100
  pydae/bmapu/loads/zip.py,sha256=GPXNZZHZ5WSEd8GkPDhT0Y7Vi1sV0N33ZVNDCuvMrSA,2234
101
101
  pydae/bmapu/miscellaneous/__init__.py,sha256=JhpeBVii27qLqxJqimWLBYwjPgXrz3hYq7PQQf2ssGs,99
102
+ pydae/bmapu/miscellaneous/banks.hjson,sha256=RQr0Wb21BMTGjq63WSpNN7hPwOva8svcJJ-ljwBjRcc,534
103
+ pydae/bmapu/miscellaneous/banks.py,sha256=lBRiDVoEoyu3rDFDGlYGqIzNNTbi-gTZJLAvh08dcr4,2011
102
104
  pydae/bmapu/miscellaneous/fault.hjson,sha256=FLACfOsxsQ_u9gMUIqtIpu33RrfWJKVQ6jH3vaiw-8s,814
103
105
  pydae/bmapu/miscellaneous/fault.py,sha256=h9KH13K4_2v3I_GxNjUCIozw9poj37vZdlmVEM21GM8,3298
104
106
  pydae/bmapu/miscellaneous/fault.svg,sha256=HdUsQkL42e6PvBHzgKcoZErBsDljHn_16HgkdNxOuX8,32865
105
107
  pydae/bmapu/miscellaneous/miscellaneous.py,sha256=CH66pLjnbxiWWGkoObJNImiR6OiSiqKEHSkyyH_o43Q,649
106
108
  pydae/bmapu/miscellaneous/pll.hjson,sha256=juYnhVB4E6hugKoiYAm9CR6OTPsiU54AX0N_X09Xeyc,939
107
109
  pydae/bmapu/miscellaneous/pll.ipynb,sha256=94mo3h58QNo7vCGchz0gBNf8Vo_0Q6RXpeGchjfvm2E,100314
108
- pydae/bmapu/miscellaneous/pll.py,sha256=j9VZTv6sEnJqqSih2T898TsmbquchcnMUFG5q8uQlCE,3874
110
+ pydae/bmapu/miscellaneous/pll.py,sha256=232o6XqGcax1cVRwmR-PD3-hFWrWWn8f2cauKQrav-M,3943
109
111
  pydae/bmapu/miscellaneous/pll.svg,sha256=Q8Gmwk4moJv9sWA26bCL8sexCv28ZSUORWdZs_g9e3I,32748
110
112
  pydae/bmapu/miscellaneous/pll_omegas.svg,sha256=dygV8cT7DQk0JFpJbW9dzxgeywatyayqVdOE3nMwLlA,51621
111
113
  pydae/bmapu/miscellaneous/pll_pod.py,sha256=EH5WymAxEzRzVxl4Kv9rlcnlBLl-Tc8DEmVu5yl79YM,5739
112
- pydae/bmapu/miscellaneous/temp.py,sha256=v2TL7LdyazK0zKhHE-Un1yeb2y1zHnjQr7P6IjSxVIw,67153
113
- pydae/bmapu/miscellaneous/temp_cffi.c,sha256=yqbMWk_4s6L-OAqRt8HaGVgJdTfKbMAWOplQkpu-bvk,235891
114
- pydae/bmapu/miscellaneous/temp_xy_0.json,sha256=9UI6XGiyO3EHMx_VUVFzUNEJre1qg5rDlQ0t32MAljM,243
115
- pydae/bmapu/miscellaneous/xy_0.json,sha256=9UI6XGiyO3EHMx_VUVFzUNEJre1qg5rDlQ0t32MAljM,243
114
+ pydae/bmapu/miscellaneous/temp.py,sha256=2eODCi8JYFYPdaI5Z5UCygS6NW93BxH3wlExXT5thmU,65880
115
+ pydae/bmapu/miscellaneous/temp_cffi.c,sha256=8JgG-Uq0q4mO-rXWyl5j8LmmydMYvWXqBMu64mQa0vU,228005
116
+ pydae/bmapu/miscellaneous/temp_xy_0.json,sha256=3lR24ijoEGnQrtwvWuNW0zmc0yaybQeUeLzFjK0fI3c,123
117
+ pydae/bmapu/miscellaneous/xy_0.json,sha256=3lR24ijoEGnQrtwvWuNW0zmc0yaybQeUeLzFjK0fI3c,123
116
118
  pydae/bmapu/old/bpu.py,sha256=FdRRVieJLQDYPwYNWhbXJ0SXvf4jtPdbvIZTKWi16I0,6775
117
119
  pydae/bmapu/pods/__init__.py,sha256=JhpeBVii27qLqxJqimWLBYwjPgXrz3hYq7PQQf2ssGs,99
118
120
  pydae/bmapu/pods/pod_2wo_3ll.hjson,sha256=h2jdpkicUk_-vSrYkrLgAu7F4_KM_Dg89_aNqYXU9jk,1003
@@ -145,7 +147,7 @@ pydae/bmapu/pvs/pv_dq_ss_test.ipynb,sha256=sJevn6PnKK3OlPRwBpc1etGOPHdg2ikeD9uT5
145
147
  pydae/bmapu/pvs/pv_model_test.ipynb,sha256=UZMSZz5VcTCynyYP3E9CALz5kXrA9Kahi4kkFhJ2_1g,221714
146
148
  pydae/bmapu/pvs/pv_test.py,sha256=Ku2XC39nefqELSJC0u_gzRhJtBC5Pu7Y2n0M671u3nw,63880
147
149
  pydae/bmapu/pvs/pv_test_cffi.c,sha256=kfumVy9p7LgH7hu-bpFVHtIp0p5hgUh1yG0zEpoNx2E,111095
148
- pydae/bmapu/pvs/pvs.py,sha256=ihu1wZ98zz9rfeClnhofRSd32KmPO1neVAjiTVZj2co,1997
150
+ pydae/bmapu/pvs/pvs.py,sha256=TG39NflgJoEZY55BYQZnluc1Xn303iMH8QQ_roIY64o,2003
149
151
  pydae/bmapu/pvs/shaded.svg,sha256=w7aXKzb-uF6BgLGFt_-xMvtffi9MxJjwSbFR6WKmWtI,65005
150
152
  pydae/bmapu/pvs/shaded_cell.svg,sha256=DcMZJn71Mpkwzv5tplPukHrhVgi2By5t0BM7-rNUsnc,29942
151
153
  pydae/bmapu/pvs/temp.py,sha256=dGCBi7h2HNro_JvVOt3bl9Z4iAVbsrIGpUv1W1hRSLQ,67575
@@ -440,6 +442,7 @@ pydae/edashboards/wecs/sm_pmsm_iso/xy_0.json,sha256=Wr6xqWV2mI_jwSVWEzsCCtirQH2P
440
442
  pydae/edashboards/wecs/sm_pmsm_iso/xy_1.json,sha256=ytkz-xqgeht2MXatdvtyom44SYGvlce6KsqeivABarU,1319
441
443
  pydae/etools/__init__.py,sha256=ssmPnE4AIWaxmL7rUw7DnR3osNBd5qOhEY0hoZDMGqc,12
442
444
  pydae/etools/etools.py,sha256=DfketNK9TDTJ_rlIcrtJI_omlqzR2fNBT8OG8qZ5fu8,4534
445
+ pydae/etools/pv_designer.py,sha256=uPV4XnoRaD8hiunsspecXVqZcMmSht8jxGmua9gl85o,14470
443
446
  pydae/etools/solar.py,sha256=hudSW8GEH5bOjIWW0maxd9jr9lMJqO6p7hWey4xlbVQ,14016
444
447
  pydae/etools/vsc_losses.py,sha256=Momed_X7oa8Q_i3pqkHfV9-x-vj_m3Y-nKkcoads-to,22266
445
448
  pydae/models/__init__.py,sha256=p1f9JVQU3e7SjQZu2jnrxLHLMvhPi8gqrvkXvKc0Wtc,78
@@ -548,7 +551,7 @@ pydae/urisi/fcs/sofc_dcdc_gf.hjson,sha256=_Gg4GN7veQf8LrlFWzcgi_BOxzZihQI9pTJ_KZ
548
551
  pydae/urisi/fcs/sofc_dcdc_gf.ipynb,sha256=pJhhFKzwsrWaatLG2Iuq1L13pYZAWvGf_NR926n57_w,66820
549
552
  pydae/urisi/fcs/sofc_dcdc_gf.py,sha256=vXs8UhwohfM_s4keX9C2bIFzHgmdj8DAmr9nNhzizks,15340
550
553
  pydae/urisi/fcs/sofc_dcdc_gf_iso.hjson,sha256=oWNN0pq6Uvzo33BFExpa7PiYAgQ6JnzblSY6jmM5qvc,1056
551
- pydae/urisi/fcs/sofc_dcdcac_gf.py,sha256=OVjtmVkzkbREz194WTQqlysVHHWR70pk7xq1JG3TCbQ,9281
554
+ pydae/urisi/fcs/sofc_dcdcac_gf.py,sha256=JLNqALR8E03qeIXjj3XgVJ5nE0XhNUWqdNWfFDBTEis,9454
552
555
  pydae/urisi/fcs/sofc_dcdcac_gf_ib.hjson,sha256=0UHz1PDFEfkBWq8OahBj_XJj0RgZc76DfO7MWViNqXc,1707
553
556
  pydae/urisi/fcs/sofc_dcdcac_gf_ib.ipynb,sha256=-qDedoETT72I1_J7lKa3uVPcqkWWcfNHX2MQ2aeJrEM,271786
554
557
  pydae/urisi/fcs/sofc_dcdcac_gf_iso.hjson,sha256=4KB4SdUy-ZVj03hjglaueZrFZSPtS-F57t9k2j9yRIw,1613
@@ -715,12 +718,13 @@ pydae/urisi/vsgs/vsgs.py,sha256=v17sLm7EaaAyBVJk9-8DnLtxPDtXmkyizFlGhgqyFEE,644
715
718
  pydae/urisi/vsgs/xy_0.json,sha256=Q6qWPIqEP-w5Qu2twd3S4PX4zMggpNpG2W62e7ry70g,851
716
719
  pydae/utils/__init__.py,sha256=kwp76qeU2mnwrCexDSF15id9ih12Q0VRL3l-_c6omcQ,184
717
720
  pydae/utils/ss_num2sym.py,sha256=ZA-x01y1mEWk1HdlpNv9rNspFdH0RBlTq_JRDHmjlpU,3209
721
+ pydae/utils/svg2pdf.py,sha256=6tNORhlu_cMPDp264Kg3X_eBORfT9Q1cqAcWaWgDs7k,1861
718
722
  pydae/utils/tools.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
719
723
  pydae/utils/types_converter.py,sha256=3eAWwELgG1d6iFX8sn8iGPIp6NBaX4I-eyUriRDOFyE,7929
720
724
  pydae/utils/utils.py,sha256=AI0wZr4PJ3Td3vjfAW06FJdgcK01TpUAukhG37gZP5g,1079
721
725
  pydae/utils/emtp/readPL4.py,sha256=R59KhXTmFrqtdv-9nv5tkdHoTs9uoofGqEfBCF4fGEY,3088
722
- pydae-0.56.3.dist-info/COPYING,sha256=QWnWoslbTjQmtlFSRoGF3wxJEJuTJdlEMZ7lHtbGAeQ,1139
723
- pydae-0.56.3.dist-info/LICENSE,sha256=8hQe1oM4ySdliF3R-NEvR6HqrcGDKvsLFJC3gA1sNjY,1108
724
- pydae-0.56.3.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
725
- pydae-0.56.3.dist-info/METADATA,sha256=MMPp-f_zyzsr7q5hrTteWiyD5xacFUNWFrHNp_5oI2Y,1046
726
- pydae-0.56.3.dist-info/RECORD,,
726
+ pydae-0.56.4.dist-info/COPYING,sha256=QWnWoslbTjQmtlFSRoGF3wxJEJuTJdlEMZ7lHtbGAeQ,1139
727
+ pydae-0.56.4.dist-info/LICENSE,sha256=8hQe1oM4ySdliF3R-NEvR6HqrcGDKvsLFJC3gA1sNjY,1108
728
+ pydae-0.56.4.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
729
+ pydae-0.56.4.dist-info/METADATA,sha256=Dg71icY-yXGhkgv66E1lg0kNhDU1FxMOf7vTZgVypP0,1046
730
+ pydae-0.56.4.dist-info/RECORD,,
File without changes