femagtools 1.7.9__py3-none-any.whl → 1.8.1__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.
Files changed (43) hide show
  1. femagtools/__init__.py +1 -1
  2. femagtools/amela.py +2 -2
  3. femagtools/dxfsl/area.py +130 -26
  4. femagtools/dxfsl/conv.py +2 -14
  5. femagtools/dxfsl/converter.py +69 -12
  6. femagtools/dxfsl/fslrenderer.py +15 -13
  7. femagtools/dxfsl/geom.py +153 -82
  8. femagtools/dxfsl/journal.py +2 -2
  9. femagtools/dxfsl/machine.py +19 -15
  10. femagtools/dxfsl/shape.py +3 -0
  11. femagtools/ecloss.py +386 -2
  12. femagtools/femag.py +82 -9
  13. femagtools/fsl.py +52 -56
  14. femagtools/machine/pm.py +1 -1
  15. femagtools/machine/sm.py +16 -8
  16. femagtools/mcv.py +128 -124
  17. femagtools/me.py +13 -13
  18. femagtools/model.py +8 -2
  19. femagtools/plot/fieldlines.py +1 -1
  20. femagtools/plot/mcv.py +18 -0
  21. femagtools/plot/wdg.py +2 -2
  22. femagtools/svgfsl/converter.py +1 -1
  23. femagtools/templates/afm_rotor.mako +4 -0
  24. femagtools/templates/gen_hairpin_winding.mako +36 -45
  25. femagtools/templates/magnetIron.mako +1 -1
  26. femagtools/templates/magnetIron2.mako +1 -1
  27. femagtools/templates/magnetIron3.mako +1 -1
  28. femagtools/templates/magnetIron4.mako +1 -1
  29. femagtools/templates/magnetIron5.mako +1 -1
  30. femagtools/templates/magnetIronV.mako +1 -1
  31. femagtools/templates/magnetSector.mako +1 -1
  32. femagtools/templates/mesh-airgap.mako +12 -6
  33. femagtools/templates/prepare_thermal.mako +199 -61
  34. femagtools/windings.py +25 -20
  35. {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/METADATA +20 -20
  36. {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/RECORD +42 -43
  37. {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/WHEEL +1 -1
  38. tests/test_mcv.py +106 -1
  39. tests/test_windings.py +5 -0
  40. tests/test_mcvwriter.py +0 -96
  41. {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/LICENSE +0 -0
  42. {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/entry_points.txt +0 -0
  43. {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,7 @@
1
1
  -- prepare thermal model
2
2
 
3
3
  save_model('cont')
4
-
4
+ state_of_problem("therm_static")
5
5
  function get_xy(elkey)
6
6
  -- get element xy
7
7
  local x, y
@@ -40,12 +40,13 @@ shaft_spel = {} ---- lightgrey, 16
40
40
  magnet_spel = {} -- black, 8
41
41
  outer_air = {} -- darkred, 10
42
42
  inner_air = {} -- lightgrey, 16
43
- rotor_air = {}
43
+ rotor_air = {}
44
44
  stator_air = {} -- black, 8
45
45
  airgap = {} -- white, 8
46
46
  magnet_pocket_spel = {} -- red, 1
47
47
  non_uniform_airgap = {} -- white, 8
48
-
48
+ slot_opening = {}
49
+ slot_sreg_exist = 0
49
50
  -- search all components
50
51
  for i =1, #spel_keys do
51
52
  -- loop over all spel keys
@@ -73,7 +74,7 @@ for i =1, #spel_keys do
73
74
  %if model.get('htc_outer', 0):
74
75
  def_heat_transfer(xc,yc,yellow,${model['htc_outer']}, 1.0)
75
76
  %endif
76
- color_spel(spel_keys[i], 10)
77
+ color_spel(spel_keys[i], 10)
77
78
 
78
79
  elseif rc > dy2/2 and rc < da2/2 then
79
80
  -- rotor air
@@ -86,11 +87,18 @@ for i =1, #spel_keys do
86
87
  -- stator air
87
88
  table.insert(stator_air, spel_keys[i])
88
89
  def_mat_therm(xc, yc, 'yellow', 1.19,0.15,1007, 1)
89
- color_spel(spel_keys[i], 8)
90
-
90
+ color_spel(spel_keys[i], 8)
91
+ key_exist_sl = get_sreg_key(xc, yc)
92
+ if key_exist_sl <= 0 and slot_sreg_exist == 0 then
93
+ def_new_sreg(xc, yc, 'Slot', 'yellow')
94
+ slot_sreg_exist = 1
95
+ else
96
+ add_to_sreg(xc, yc, 'Slot')
97
+ end
91
98
  elseif rc > da2/2 and rc < da1/2 then
92
99
  table.insert(airgap, spel_keys[i])
93
- def_mat_therm(xc, yc, 'yellow', 1.19,0.063,1007, 1)
100
+ def_mat_therm(xc, yc, 'yellow', 1.19,0.15,1007, 1)
101
+ add_to_sreg(xc, yc, 'Slot')
94
102
  color_spel(spel_keys[i], 7) -- white air
95
103
 
96
104
  -- elseif rc > dy2/2 then
@@ -104,14 +112,6 @@ for i =1, #spel_keys do
104
112
  if x0_shaft ~= nil and x0_shaft ~= 0.0 then
105
113
  table.insert(shaft_spel, spel_keys[i])
106
114
  def_mat_therm(xc, yc, 'lightgrey', shaft_density, shaft_thcond, shaft_thcap, 1)
107
- else
108
- -- is inner air
109
- table.insert(inner_air, spel_keys[i])
110
- %if model.get('htc_inner', 0):
111
- def_heat_transfer(xc,yc,yellow,${model['htc_inner']}, 1.0)
112
- %endif
113
- def_new_sreg(xc,yc, 'INAR', 'yellow')
114
- color_spel(spel_keys[i], 16) -- light grey inner air
115
115
  end
116
116
  end
117
117
  end
@@ -139,81 +139,219 @@ end
139
139
 
140
140
  function is_exist(arr, val)
141
141
  local i
142
- if #arr == 0 then
143
- return false
144
- end
145
- for i = 1, #arr do
146
- if arr[i] == val then
142
+ if #arr == 0 then
143
+ return false
144
+ end
145
+ for i = 1, #arr do
146
+ if arr[i] == val then
147
147
  return true
148
- end
149
- end
148
+ end
149
+ end
150
150
  return false
151
- end
152
- -- identify magnet air pocket
151
+ end
152
+ -- identify magnet air pocket
153
153
 
154
- for i = 1, #magnet_spel do
154
+ for i = 1, #magnet_spel do
155
155
  bkeys = get_spel_data ( "bndkeys", magnet_spel[i])
156
- for j = 1, #bkeys do
156
+ for j = 1, #bkeys do
157
157
  elks = get_node_data ( "elkeys", bkeys[j] )
158
- for k = 1, #elks do
158
+ for k = 1, #elks do
159
159
  p1, p2 = get_elem_data("perm", elks[k])
160
160
  sek = get_elem_data("sekey", elks[k])
161
- if p1 == 1.0 then
162
- if (not is_exist(magnet_pocket_spel, sek)) and (not is_exist(airgap, sek)) then
161
+ if p1 == 1.0 then
162
+ if (not is_exist(magnet_pocket_spel, sek)) and (not is_exist(airgap, sek)) then
163
163
  table.insert(magnet_pocket_spel, sek)
164
164
  els = get_spel_data('elkeys', sek)
165
165
  xc, yc = get_xy(els[1])
166
166
  def_mat_therm(xc, yc, 'red', 1.12,0.026,1007, 1)
167
167
  --table.remove(rotor_air, sek)
168
168
  color_spel(sek, 1)
169
- end
170
- end
171
- end
172
- end
173
- end
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
174
174
 
175
175
 
176
176
 
177
- for i = 1, #rotor_air do
178
- if rotor_air[i] ~= nil then
177
+ for i = 1, #rotor_air do
178
+ if rotor_air[i] ~= nil then
179
179
  bkeys = get_spel_data ( "bndkeys", rotor_air[i])
180
- for j = 1, #bkeys do
180
+ for j = 1, #bkeys do
181
181
  x, y = get_node_data ( "xy", bkeys[j] )
182
- r, phi = c2pd(x, y)
183
- if math.abs(r - da2/2) < 1e-5 then
184
- if not is_exist(non_uniform_airgap,rotor_air[i]) then
182
+ r, phi = c2pd(x, y)
183
+ if math.abs(r - da2/2) < 1e-5 then
184
+ if not is_exist(non_uniform_airgap,rotor_air[i]) then
185
185
  table.insert(non_uniform_airgap, rotor_air[i])
186
186
  els = get_spel_data('elkeys', rotor_air[i])
187
187
  xc, yc = get_xy(els[1])
188
- def_mat_therm(xc, yc, 'yellow', 1.19,0.063,1007, 1)
188
+ def_mat_therm(xc, yc, 'yellow', 1.19,1.15,1007, 1)
189
+ add_to_sreg(xc, yc, 'Slot')
189
190
  color_spel(rotor_air[i], 7)
190
- end
191
- end
192
- end
193
- end
194
- end
191
+ end
192
+ end
193
+ end
194
+ end
195
+ end
195
196
 
196
- for i = 1, #rotor_air do
197
- if rotor_air[i] ~= nil then
198
- if is_exist(non_uniform_airgap, rotor_air[i]) then
197
+ for i = 1, #rotor_air do
198
+ if rotor_air[i] ~= nil then
199
+ if is_exist(non_uniform_airgap, rotor_air[i]) then
199
200
  rotor_air[i] = nil
200
- end
201
- end
202
- end
201
+ end
202
+ end
203
+ end
203
204
 
204
- for i = 1, #rotor_air do
205
- if is_exist(magnet_pocket_spel, rotor_air[i]) then
205
+ for i = 1, #rotor_air do
206
+ if is_exist(magnet_pocket_spel, rotor_air[i]) then
206
207
  rotor_air[i] = nil
207
- end
208
- end
209
-
208
+ end
209
+ end
210
+
210
211
 
211
- for i = 1, #rotor_air do
212
- if rotor_air[i] ~= nil then
212
+ for i = 1, #rotor_air do
213
+ if rotor_air[i] ~= nil then
213
214
  els = get_spel_data('elkeys', rotor_air[i])
214
215
  xc, yc = get_xy(els[1])
215
216
  def_mat_therm(xc, yc, 'red', 1.12,0.026,1007, 1)
216
- end
217
- end
217
+ end
218
+ end
219
+
218
220
 
219
221
  save_metafile(model..'.ps')
222
+
223
+
224
+
225
+ ---------------------------------------------
226
+ -- material slot insulation
227
+ ---------------------------------------------
228
+
229
+ function get_boundary_node(num_slots)
230
+
231
+ local ctr
232
+ -- get the number of winding
233
+ get_wdg_keys("wkeys")
234
+ -- search subregions
235
+ local srkey_sl = {}
236
+ ctr = 1
237
+ for i = 1, #wkeys do
238
+ tmpksl = get_wdg_data("srkeys", wkeys[i])
239
+ for j = 1, #tmpksl do
240
+ srkey_sl[ctr] = tmpksl[j]
241
+ ctr = ctr + 1
242
+ end
243
+ end
244
+ -- search superelements
245
+ local sekey_sl = {}
246
+ ctr = 1
247
+ for k = 1, #srkey_sl do
248
+ sl_se = get_sreg_data("sekeys", srkey_sl[k])
249
+ for kk =1, #sl_se do
250
+ sl_nd = get_spel_data("bndkeys", sl_se[kk])
251
+ x, y = get_node_data("xy", sl_nd[1])
252
+ r, phi = c2pd(x, y)
253
+ if phi < 360/num_slots then
254
+ sekey_sl[ctr] = sl_se[kk]
255
+ ctr = ctr + 1
256
+ end
257
+ end
258
+ end
259
+
260
+ local xn = {}
261
+ local yn = {}
262
+ local node = {}
263
+ local bndnodes = {}
264
+ local bnd_unique = {}
265
+
266
+ ctr = 1
267
+
268
+ for i = 1, #sekey_sl do
269
+ bnd = get_spel_data("bndkeys", sekey_sl[i])
270
+
271
+ for j = 1, #bnd do
272
+ bndnodes[ctr] = bnd[j]
273
+ ctr = ctr + 1
274
+ if bnd_unique[bnd[j]] == true then
275
+ bnd_unique[bnd[j]] = false
276
+ else
277
+ bnd_unique[bnd[j]] = true
278
+ end
279
+ end
280
+ end
281
+
282
+ ctr = 1
283
+ for j = 1, #bndnodes do
284
+ x, y = get_node_data("xy", bndnodes[j])
285
+
286
+ r, phi = c2pd(x, y)
287
+ if (phi < 360/num_slots/2 - 0.05) and (bnd_unique[bndnodes[j]] == true) then
288
+
289
+ node[ctr] = bndnodes[j]
290
+ xn[ctr] = x
291
+ yn[ctr] = y
292
+ ctr = ctr + 1
293
+ end
294
+ end
295
+
296
+
297
+ local indx = {1, math.floor(#node/4), math.floor(#node/2), math.floor(#node/4*3), #node}
298
+
299
+ local x_new = {}
300
+ local y_new = {}
301
+
302
+ for i = 1, 10 do
303
+ x_new[i] = 0
304
+ y_new[i] = 0
305
+ end
306
+
307
+ for i = 1, #indx do
308
+ x_new[i] = xn[indx[i]]
309
+ y_new[i] = yn[indx[i]]
310
+ r, phi = c2pd(x_new[i], y_new[i])
311
+ x_new[10 - (i-1)], y_new[10 - (i-1)] = pd2c(r, 360/num_slots - phi)
312
+ end
313
+
314
+ local rn = {}
315
+ local phin = {}
316
+
317
+ for i = 1, #x_new do
318
+ rn[i], phin[i] = c2pd(x_new[i], y_new[i])
319
+ end
320
+ return rn, phin
321
+ end
322
+
323
+
324
+ rn, phin = get_boundary_node(m.tot_num_slot)
325
+ thickness = ${model.windings.get('slot_insulation_thickness', 0.15e-3)*1e3}
326
+ if thickness == 0.0 then
327
+ thickness = 0.15
328
+ end
329
+ conductivity = ${model.get('slot_insul_cond', 0.31)}
330
+
331
+ for i = 1,m.num_sl_gen do
332
+ x = {}
333
+ y = {}
334
+
335
+ for j = 1, #rn do
336
+ x[j], y[j] = pd2c(rn[j], phin[j] + (i-1)*360/m.tot_num_slot)
337
+ point(x[j], y[j],"black","x")
338
+ end
339
+
340
+ def_insulation_by_nodechain(thickness,conductivity,
341
+ x[1],y[1],
342
+ x[2],y[2],
343
+ x[3],y[3],
344
+ x[4],y[4],
345
+ x[5],y[5],
346
+ x[6],y[6],
347
+ x[7],y[7],
348
+ x[8],y[8],
349
+ x[9],y[9],
350
+ x[10],y[10],
351
+ x[1], y[1]
352
+ )
353
+
354
+ end
355
+ save_metafile('insulation.ps')
356
+
357
+ state_of_problem("mag_static")
femagtools/windings.py CHANGED
@@ -32,18 +32,18 @@ def q1q2yk(Q, p, m, l=1):
32
32
  """returns q1, q2, Yk, Qb"""
33
33
  t = num_basic_windings(Q, p, l)
34
34
  Qb = Q//t
35
- qqb = Qb if l == 2 else Qb//2
35
+ qbb = Qb if l==2 else Qb//2
36
36
  pb = p//t
37
- if qqb//m % 2: # odd
38
- q2 = (qqb + m)//(2*m) - 1
37
+ if qbb//m % 2: # odd
38
+ q2 = (qbb + m)//(2*m) - 1
39
39
  q1 = q2 + 1
40
40
  else:
41
- q2 = (qqb)//(2*m)
41
+ q2 = (qbb)//(2*m)
42
42
  q1 = q2
43
43
  n = 1
44
- while (n*qqb + 1) % pb:
44
+ while (n*qbb + 1) % pb:
45
45
  n += 1
46
- Yk = (n*qqb + 1)//pb
46
+ Yk = (n*qbb + 1)//pb
47
47
  return q1, q2, Yk, Qb
48
48
 
49
49
 
@@ -118,22 +118,22 @@ class Winding(object):
118
118
  self.yd = coilwidth
119
119
 
120
120
  q1, q2, Yk, Qb = q1q2yk(self.Q, self.p, self.m, self.l)
121
+ j = 2 if layers == 1 else 1
121
122
  k1 = [(q1 + q2)*i for i in range(self.m)]
122
123
  k2 = (q1*(self.m+1) + q2*(self.m-1))//2
123
- j = 2 if layers == 1 else 1
124
124
  pos = [[(j*Yk*(k + n)) % Qb
125
125
  for n in range(q1)] for k in k1]
126
126
  neg = [[j*Yk*(k + n + k2) % Qb
127
127
  for n in range(q2)] for k in k1]
128
- if layers > 1:
128
+ if self.l > 1:
129
129
  slots = [sorted([(k, 1, 1)
130
130
  for k in p] + [(k, -1, 1)
131
131
  for k in n])
132
132
  for n, p in zip(neg, pos)]
133
133
  for i, p in enumerate(slots):
134
134
  slots[i] = sorted(slots[i] +
135
- [((k[0]+coilwidth) % Qb, -k[1], 0)
136
- for k in slots[i]], key=lambda s: s[0])
135
+ [((k[0]+self.yd) % Qb, -k[1], 0)
136
+ for k in slots[i]])
137
137
  else:
138
138
  if (coilwidth + 1) % 2:
139
139
  coilwidth += 1
@@ -147,10 +147,6 @@ class Winding(object):
147
147
  slots = [sorted([(k, 1, 1) for k in p] + [(k, -1, 1) for k in n])
148
148
  for n, p in zip(xneg, xpos)]
149
149
 
150
- if self.m > 3: # TODO: check this hack
151
- slots = slots[:self.m//2] + [[((k[0]+1) % self.Q, k[1], k[2])
152
- for k in s]
153
- for s in slots[:self.m//2]]
154
150
  taus = 360/self.Q
155
151
  self.windings = {
156
152
  i+1: dict(dir=[k[1] for k in s],
@@ -183,6 +179,10 @@ class Winding(object):
183
179
  nue = n
184
180
  else:
185
181
  nue = self.kw_order(n)
182
+ #if q1 == q2: # integral slot winding
183
+ # q = self.Q/2/self.m/self.p
184
+ # nuep = nue/self.p
185
+ # return np.sin(nuep*np.pi/2/self.m)/q/np.sin(nuep*np.pi/2/self.m/q)
186
186
  k = 2 if self.l == 1 else 1
187
187
  a = nue*k*np.pi/self.Q*Yk
188
188
  t = self.Q//Qb
@@ -244,14 +244,19 @@ class Winding(object):
244
244
 
245
245
  def slots(self, key):
246
246
  """returns slot indexes of winding key"""
247
- ngen = self.m*self.Q//np.gcd(self.Q, self.m*2*self.p)
248
247
  taus = 360/self.Q
249
-
250
- dim = int(self.l*ngen/self.m)
251
- slots = [(round((x-taus/2)/taus) + ngen*n) % self.Q + 1
252
- for n in range(self.Q//ngen)
248
+ t = num_basic_windings(self.Q, self.p, self.l)
249
+ Qb = self.Q//t
250
+ dim = self.l*Qb//self.m
251
+ ngen = t
252
+ qgen = Qb
253
+ if dim > len(self.windings[key]['PHI']):
254
+ qgen = qgen//2
255
+ ngen = 2*t
256
+ slots = [(round((x-taus/2)/taus) + qgen*n) % self.Q + 1
257
+ for n in range(ngen)
253
258
  for x in self.windings[key]['PHI'][:dim]]
254
- return np.array(slots).reshape((np.gcd(self.Q, self.p), -1))
259
+ return np.array(slots).reshape(t, -1)
255
260
 
256
261
  def axis(self, k=1):
257
262
  """returns axis angle of winding 1 in mechanical system"""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: femagtools
3
- Version: 1.7.9
3
+ Version: 1.8.1
4
4
  Summary: Python API for FEMAG
5
5
  Author-email: Ronald Tanner <tar@semafor.ch>, Dapu Zhang <dzhang@gtisoft.com>, Beat Holm <hob@semafor.ch>, Günther Amsler <amg@semafor.ch>, Nicolas Mauchle <mau@semafor.ch>
6
6
  License: Copyright (c) 2016-2023, Semafor Informatik & Energie AG, Basel
@@ -37,33 +37,33 @@ Classifier: Topic :: Scientific/Engineering
37
37
  Requires-Python: >=3.7
38
38
  Description-Content-Type: text/markdown
39
39
  License-File: LICENSE
40
- Requires-Dist: numpy <=1.26.4
40
+ Requires-Dist: numpy<=1.26.4
41
41
  Requires-Dist: scipy
42
42
  Requires-Dist: mako
43
43
  Requires-Dist: six
44
44
  Requires-Dist: lmfit
45
- Requires-Dist: netCDF4 >=1.6.5
46
- Provides-Extra: all
47
- Requires-Dist: femagtools[dxfsl,meshio,mplot,svgfsl,test,vtk,zmq] ; extra == 'all'
45
+ Requires-Dist: netCDF4>=1.6.5
46
+ Provides-Extra: rdp
47
+ Requires-Dist: rdp; extra == "rdp"
48
48
  Provides-Extra: dxfsl
49
- Requires-Dist: dxfgrabber ; extra == 'dxfsl'
50
- Requires-Dist: networkx ; extra == 'dxfsl'
51
- Requires-Dist: rdp ; extra == 'dxfsl'
52
- Provides-Extra: meshio
53
- Requires-Dist: meshio ; extra == 'meshio'
54
- Provides-Extra: mplot
55
- Requires-Dist: matplotlib ; extra == 'mplot'
49
+ Requires-Dist: dxfgrabber; extra == "dxfsl"
50
+ Requires-Dist: networkx; extra == "dxfsl"
56
51
  Provides-Extra: svgfsl
57
- Requires-Dist: dxfgrabber ; extra == 'svgfsl'
58
- Requires-Dist: networkx ; extra == 'svgfsl'
59
- Requires-Dist: lxml ; extra == 'svgfsl'
60
- Requires-Dist: rdp ; extra == 'svgfsl'
61
- Provides-Extra: test
62
- Requires-Dist: pytest ; extra == 'test'
52
+ Requires-Dist: dxfgrabber; extra == "svgfsl"
53
+ Requires-Dist: networkx; extra == "svgfsl"
54
+ Requires-Dist: lxml; extra == "svgfsl"
55
+ Provides-Extra: mplot
56
+ Requires-Dist: matplotlib; extra == "mplot"
57
+ Provides-Extra: meshio
58
+ Requires-Dist: meshio; extra == "meshio"
63
59
  Provides-Extra: vtk
64
- Requires-Dist: vtk ; extra == 'vtk'
60
+ Requires-Dist: vtk; extra == "vtk"
65
61
  Provides-Extra: zmq
66
- Requires-Dist: pyzmq ; extra == 'zmq'
62
+ Requires-Dist: pyzmq; extra == "zmq"
63
+ Provides-Extra: test
64
+ Requires-Dist: pytest; extra == "test"
65
+ Provides-Extra: all
66
+ Requires-Dist: femagtools[dxfsl,meshio,mplot,svgfsl,test,vtk,zmq]; extra == "all"
67
67
 
68
68
 
69
69
  # Introduction to Femagtools