-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathinductance.py
346 lines (269 loc) · 12.3 KB
/
inductance.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
"""
Ce programme permet de représenter une inductance sous FEMM
Adapté du programme "simulation_femm_inductance.py" de M. Javier OJEDA
"""
__author__ = "Javier OJEDA"
__license__ = "GPL"
__version__ = "1.0.0"
__maintainer__ = "Augustin GODINOT"
__email__ = "[email protected]"
__status__ = "Education"
###############################################################################
##
## Dimensionnement d'une inductance saturable
##
###############################################################################
import femm
import numpy as np
from scipy.interpolate import interp1d
class Inductance:
"""Classe définissant une inductance caractérisée par :
- Sa hauteur réelle (hauteur)
- Sa largeur réelle (largeur)
- Sa longueur active (l_active)
- Son entrefer (entrefer)
- La largeur d'une dent fer (l_dent)
- Son coefficient de bobinage (k_b)
- Sa densité de courant maximale (j_max)
- Son courant maximum (i_max)"""
def __init__(self, induct):
"""Les elements sont dans un dictionnaire rangé par ordre :
hauteur, largeur, l_active,
entrefer, l_dent, k_b, j_max"""
for key, value in induct.items():
if key == "hauteur":
self.hauteur = value
elif key == "largeur":
self.largeur = value
elif key == "l_active":
self.l_active = value
elif key == "entrefer":
self.entrefer = value
elif key == "l_dent":
self.l_dent = value
elif key == "k_b":
self.k_b = value
elif key == "j_max":
self.j_max = value
elif key == "i_max":
self.i_max = value
else:
print("Paramètres {0} non requis".format(key))
@property
def densite_courant(self):
""" Getter permettant d'obtenir la valeur de j_max """
return self.j_max
@densite_courant.setter
def densite_courant(self, j_max):
""" Setter permettant de modifier la valeur de j_max """
self.j_max = j_max
def creation_FEMM(self, display=False):
"""Méthode permettant de générer une simulation FEMM"""
# Permet de lancer le logiciel FEMM. (1 = pas d'affichage graphique)
femm.openfemm(int(not(display)))
# Création d'un problème de magnétostatique ( = 0 ).
femm.newdocument(0)
# Définition du problème. Magnetostatique, Unités mètres, Problème plan,
# Precision de 10^(-8), longueur active de 1m, angle de contraintes de 30deg
femm.mi_probdef(50,'meters','planar',1e-8,1,30)
def creation_geometrie(self):
"""Méthode permettant de générer la géométrie"""
# Dessin d'un rectangle (xmin,ymin,xmax,ymax)
femm.mi_drawrectangle(-self.largeur/2,
-self.hauteur/2,
self.largeur/2,
self.hauteur/2);
# Dessin de points (x,y)
femm.mi_addnode(self.l_dent/2, self.entrefer/2)
femm.mi_addnode(-self.l_dent/2, self.entrefer/2)
femm.mi_addnode(self.l_dent/2, -self.entrefer/2)
femm.mi_addnode(-self.l_dent/2, -self.entrefer/2)
femm.mi_addnode(self.l_dent/2, self.hauteur/2-self.l_dent/2)
femm.mi_addnode(-self.l_dent/2, self.hauteur/2-self.l_dent/2)
femm.mi_addnode(self.l_dent/2, -self.hauteur/2+self.l_dent/2)
femm.mi_addnode(-self.l_dent/2, -self.hauteur/2+self.l_dent/2)
femm.mi_addnode(self.largeur/2-self.l_dent/2,
self.hauteur/2-self.l_dent/2)
femm.mi_addnode(-self.largeur/2+self.l_dent/2,
self.hauteur/2-self.l_dent/2)
femm.mi_addnode(self.largeur/2-self.l_dent/2,
-self.hauteur/2+self.l_dent/2)
femm.mi_addnode(-self.largeur/2+self.l_dent/2,
-self.hauteur/2+self.l_dent/2)
# Dessin des lignes (x1,y1,x2,y2)
femm.mi_addsegment(self.l_dent/2, self.entrefer/2,
-self.l_dent/2, self.entrefer/2)
femm.mi_addsegment(self.l_dent/2, -self.entrefer/2,
-self.l_dent/2, -self.entrefer/2)
femm.mi_addsegment(self.l_dent/2, self.entrefer/2,
self.l_dent/2, self.hauteur/2-self.l_dent/2)
femm.mi_addsegment(-self.l_dent/2, self.entrefer/2,
-self.l_dent/2, self.hauteur/2-self.l_dent/2)
femm.mi_addsegment(self.l_dent/2, -self.entrefer/2,
self.l_dent/2, -self.hauteur/2+self.l_dent/2)
femm.mi_addsegment(-self.l_dent/2, -self.entrefer/2,
-self.l_dent/2, -self.hauteur/2+self.l_dent/2)
femm.mi_addsegment(self.l_dent/2, self.hauteur/2-self.l_dent/2,
self.largeur/2-self.l_dent/2,
self.hauteur/2-self.l_dent/2)
femm.mi_addsegment(-self.l_dent/2, self.hauteur/2-self.l_dent/2,
-self.largeur/2+self.l_dent/2,
self.hauteur/2-self.l_dent/2)
femm.mi_addsegment(self.l_dent/2, -self.hauteur/2+self.l_dent/2,
self.largeur/2-self.l_dent/2,
-self.hauteur/2+self.l_dent/2)
femm.mi_addsegment(-self.l_dent/2, -self.hauteur/2+self.l_dent/2,
-self.largeur/2+self.l_dent/2,
-self.hauteur/2+self.l_dent/2)
femm.mi_addsegment(self.largeur/2-self.l_dent/2,
self.hauteur/2-self.l_dent/2,
self.largeur/2-self.l_dent/2,
-self.hauteur/2+self.l_dent/2)
femm.mi_addsegment(-self.largeur/2+self.l_dent/2,
self.hauteur/2-self.l_dent/2,
-self.largeur/2+self.l_dent/2,
-self.hauteur/2+self.l_dent/2)
femm.mi_addsegment(self.l_dent/2, self.entrefer/2,
self.l_dent/2, -self.entrefer/2)
femm.mi_addsegment(-self.l_dent/2, self.entrefer/2,
-self.l_dent/2, -self.entrefer/2)
def affectation_materiaux(self):
"""Méthode permettant d'attribuer la propriété des matériaux"""
# Affectation de l'air (x,y)
femm.mi_addmaterial('Air', 1, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0)
femm.mi_addblocklabel(0, 0)
femm.mi_selectlabel(0, 0)
femm.mi_setblockprop('Air', 0, 1, '<None>', 0, 0, 0)
femm.mi_clearselected()
# Affectation du Cuivre (bobine positive) (Attention J en A/mm²)
femm.mi_addmaterial('Cuivre-', 1, 1, 0, -self.k_b*self.j_max*1.0e-6,
0, 0, 0, 0, 0, 0, 0)
femm.mi_addblocklabel(self.largeur/4, 0)
femm.mi_selectlabel(self.largeur/4, 0)
femm.mi_setblockprop('Cuivre-', 0, 1, 'incricuit', 0, 0, 0)
femm.mi_clearselected()
# Affectation du Cuivre (bobine négative)
femm.mi_addmaterial('Cuivre+', 1, 1, 0, self.k_b*self.j_max*1.0e-6,
0, 0, 0, 0, 0, 0, 0)
femm.mi_addblocklabel(-self.largeur/4, 0)
femm.mi_selectlabel(-self.largeur/4, 0)
femm.mi_setblockprop('Cuivre+', 0 ,1 ,'incircuit', 0, 0, 0)
femm.mi_clearselected()
# Matériau non linéaire
# Création d'un matériau linéaire
femm.mi_addmaterial('Iron', 2100, 2100, 0, 0, 0, 0, 0, 0, 0, 0, 0)
# Les points de la courbe BH
bdata = [
0.1, 0.2, 0.4, 0.7, 1., 1.2, 1.3, 1.4, 1.5, 1.55, 1.6, 1.65, 1.7
]
hdata = [
26.5, 37.8, 52.4, 71.9, 99.3, 136, 176, 279, 659, 1084, 1718, 2577,
3670
]
# Affectation des points de la courbe
for n in range(0,len(bdata)):
femm.mi_addbhpoint('Iron', bdata[n], hdata[n])
# Les points de la courbe Pertes fer = f(B)
pdata = [
0.0176, 0.0683, 0.240, 0.602, 1.09, 1.51, 1.79, 2.14, 2.56, 2.77,
2.96, 3.13, 3.29
]
self._interp_pertes_fer = interp1d(
bdata,
pdata,
bounds_error=False,
fill_value=(pdata[0], pdata[-1])
)
# Affectation du matériau
femm.mi_addblocklabel(self.largeur/2-self.l_dent/4, 0)
femm.mi_selectlabel(self.largeur/2-self.l_dent/4, 0)
femm.mi_setblockprop('Iron', 0, 1, '<None>', 0, 0, 0)
femm.mi_clearselected()
def conditions_limites(self):
"""Méthode permettant d'attribuer les conditions aux limites"""
femm.mi_addboundprop('lim',0,0,0,0,0,0,0,0,0)
femm.mi_selectsegment(0, self.hauteur/2)
femm.mi_selectsegment(0, -self.hauteur/2)
femm.mi_selectsegment(self.largeur/2, 0)
femm.mi_selectsegment(-self.largeur/2, 0)
femm.mi_setsegmentprop('lim', 0, 1, 0, 0)
femm.mi_clearselected();
def sauvegarde_simulation(self):
"""Sauvegarde de la simulation (à faire avant de simuler)"""
femm.mi_saveas('transfo.fem')
def maillage(self):
"""Maillage de la géométrie"""
femm.mi_createmesh()
def simulation(self):
"""Simulation du système"""
femm.mi_analyze()
femm.mi_loadsolution()
@property
def energie_stockee(self):
"""Calcul de l'energie dans l'entrefer et le fer"""
femm.mo_selectblock(0, 0) # On selectionne l'entrefer
femm.mo_selectblock(0, self.hauteur/4) # On selectionne le fer
energie = femm.mo_blockintegral(2)*self.l_active # 2 : Magnetic field energy
femm.mo_clearblock()
return energie
@property
def volume_externe(self):
"""Calcul du volume de l'inductance"""
return self.l_active*self.hauteur*self.largeur
@property
def volume_fer(self):
"""Calcul du volume de fer de l'inductance"""
v_fer = (self.volume_externe-
self.volume_cuivre-
self.entrefer*self.l_dent*self.l_active)
return v_fer
@property
def volume_cuivre(self):
"""Calcul du volume de cuivre de l'inductance"""
v_cuivre = 2*(self.hauteur/2-
self.l_dent)*(self.largeur/2-
self.l_dent)*self.l_active
return v_cuivre
@property
def masse_fer(self):
"""Calcul de la masse de fer de l'inductance"""
RHO_FER = 7874
m_fer = RHO_FER*self.volume_fer
return m_fer
@property
def masse_cuivre(self):
"""Calcul de la masse de cuivre de l'inductance"""
RHO_CUIVRE = 8960
m_cuivre = RHO_CUIVRE*self.volume_cuivre
return m_cuivre
@property
def masse_totale(self):
""" Calcul de la masse totale dans le transformateur """
return self.masse_cuivre + self.masse_fer
@property
def pertes_joule(self):
"""Calcul des pertes cuivre de l'inductance"""
SIGMA_CUIVRE = 59.6e6
pertes_joule = (1/SIGMA_CUIVRE*
self.k_b*
self.volume_cuivre*
self.j_max**2)
return pertes_joule
@property
def pertes_fer(self):
""" Calcul des pertes fer de l'inductance """
FREQUENCE = 50 # (en Hz)
# Mesure du Bx, By au milieu de la dent centrale
b_x, b_y = femm.mo_getb(0, self.hauteur/4)
b_moy = np.sqrt(b_x**2 + b_y**2)
# TODO : faire la moyenne de Bx et By sur tout le volume
# plutôt que juste dans la dent ?
return self._interp_pertes_fer(b_moy)
def fit_zoom(self):
"""Méthode permettant de générer la géométrie"""
# Zoom pour avoir une meilleur vue
femm.mi_zoomnatural()
def fermeture_simulation(self):
"""Fermeture de FEMM"""
femm.closefemm()