femagtools 1.5.7__py3-none-any.whl → 1.6.0__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 (38) hide show
  1. femagtools/__init__.py +1 -1
  2. femagtools/bch.py +14 -1
  3. femagtools/dxfsl/area.py +2 -3
  4. femagtools/dxfsl/converter.py +10 -2
  5. femagtools/dxfsl/fslrenderer.py +1 -2
  6. femagtools/dxfsl/functions.py +24 -27
  7. femagtools/dxfsl/geom.py +116 -80
  8. femagtools/dxfsl/machine.py +16 -7
  9. femagtools/dxfsl/plotrenderer.py +2 -2
  10. femagtools/dxfsl/shape.py +68 -17
  11. femagtools/femag.py +21 -3
  12. femagtools/fsl.py +14 -2
  13. femagtools/machine/__init__.py +13 -33
  14. femagtools/machine/afpm.py +22 -21
  15. femagtools/machine/pm.py +22 -21
  16. femagtools/machine/utils.py +112 -58
  17. femagtools/mcv.py +27 -1
  18. femagtools/model.py +4 -2
  19. femagtools/nc.py +7 -0
  20. femagtools/opt.py +1 -1
  21. femagtools/parstudy.py +5 -2
  22. femagtools/plot/__init__.py +1 -0
  23. femagtools/plot/bch.py +2 -0
  24. femagtools/plot/fieldlines.py +37 -0
  25. femagtools/templates/basic_modpar.mako +8 -0
  26. femagtools/templates/bertotti.mako +40 -0
  27. femagtools/templates/modified_steinmetz.mako +39 -0
  28. femagtools/ts.py +1 -1
  29. femagtools/utils.py +7 -1
  30. {femagtools-1.5.7.dist-info → femagtools-1.6.0.dist-info}/METADATA +1 -1
  31. {femagtools-1.5.7.dist-info → femagtools-1.6.0.dist-info}/RECORD +38 -35
  32. tests/test_bchreader.py +12 -1
  33. tests/test_femag.py +1 -1
  34. tests/test_fsl.py +1 -1
  35. {femagtools-1.5.7.dist-info → femagtools-1.6.0.dist-info}/LICENSE +0 -0
  36. {femagtools-1.5.7.dist-info → femagtools-1.6.0.dist-info}/WHEEL +0 -0
  37. {femagtools-1.5.7.dist-info → femagtools-1.6.0.dist-info}/entry_points.txt +0 -0
  38. {femagtools-1.5.7.dist-info → femagtools-1.6.0.dist-info}/top_level.txt +0 -0
femagtools/__init__.py CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  """
4
4
  __title__ = 'femagtools'
5
- __version__ = '1.5.7'
5
+ __version__ = '1.6.0'
6
6
  __author__ = 'Ronald Tanner'
7
7
  __license__ = 'BSD'
8
8
  __copyright__ = 'Copyright 2016-2022 SEMAFOR Informatik & Energie AG'
femagtools/bch.py CHANGED
@@ -53,7 +53,7 @@ def sttylosses(losses):
53
53
  """map losses of stator subregions to stteeth and styoke"""
54
54
  # extract stator subregion names
55
55
  sregs = set([k for k in losses.keys()
56
- if k.split('_')[-1] not in {'hyst', 'eddy'} and
56
+ if k.split('_')[-1] not in {'hyst', 'eddy', 'excess'} and
57
57
  k not in {'rotor', 'magnet', 'speed'}])
58
58
 
59
59
  def hysteddy(yoke, teeth, losses):
@@ -65,6 +65,8 @@ def sttylosses(losses):
65
65
  d['stteeth_hyst'] = losses[teeth+'_hyst']
66
66
  d['styoke_eddy'] = losses[yoke+'_eddy']
67
67
  d['stteeth_eddy'] = losses[teeth+'_eddy']
68
+ d['styoke_excess'] = losses[yoke+'_excess']
69
+ d['stteeth_excess'] = losses[teeth+'_excess']
68
70
  except KeyError:
69
71
  pass
70
72
  return d
@@ -87,6 +89,7 @@ def sttylosses(losses):
87
89
  try:
88
90
  l['stteeth_eddy'] += losses['STTP_eddy']
89
91
  l['stteeth_hyst'] += losses['STTP_hyst']
92
+ l['stteeth_excess'] += losses['STTP_excess']
90
93
  except KeyError:
91
94
  pass
92
95
  return l
@@ -1168,6 +1171,12 @@ class Reader:
1168
1171
  for s in subregs[:-2] + ['rotor', 'magnet']:
1169
1172
  cols += [s+'_hyst', s+'_eddy']
1170
1173
  if m:
1174
+ # FEMAG-2024.2
1175
+ if len(m[0]) > len(subregs[:-1])*2+2:
1176
+ cols = []
1177
+ for s in subregs[:-2] + ['rotor', 'magnet']:
1178
+ cols += [s+'_hyst', s+'_eddy', s+'_excess']
1179
+
1171
1180
  m = np.array(m).T
1172
1181
  if self.ldq:
1173
1182
  ls.update({k: np.reshape(v[:mlen],
@@ -1570,6 +1579,8 @@ class Reader:
1570
1579
  x[0] = int(x[0])
1571
1580
  if len(losses[part][k][0]) == 4:
1572
1581
  cols = ('order_el', 'freq', 'hyst', 'eddy')
1582
+ if len(losses[part][k][0]) == 6:
1583
+ cols = ('order_mech', 'order_el', 'freq', 'hyst', 'eddy', 'excess')
1573
1584
  if losses[part][k]:
1574
1585
  self.losses[-1][part][k] = {
1575
1586
  k1: l
@@ -1619,6 +1630,8 @@ class Reader:
1619
1630
  elif len(rec) == 5: # FEMAG Rel 8.3 with el/mech order
1620
1631
  losses[part][k].append([floatnan(x)
1621
1632
  for i, x in enumerate(rec)])
1633
+ elif len(rec) == 6:
1634
+ losses[part][k].append([floatnan(x) for x in rec])
1622
1635
  else:
1623
1636
  part = 'fft'
1624
1637
 
femagtools/dxfsl/area.py CHANGED
@@ -8,7 +8,6 @@
8
8
  Authors: Ronald Tanner, beat Holm
9
9
  """
10
10
  from __future__ import print_function
11
- import sys
12
11
  import numpy as np
13
12
  import networkx as nx
14
13
  import logging
@@ -103,7 +102,7 @@ class Area(object):
103
102
  except ValueError as e:
104
103
  logger.error("list_of_nodes(): FATAL ERROR: %s", e)
105
104
  return
106
- except Exception as e:
105
+ except Exception:
107
106
  return
108
107
 
109
108
  def list_of_elements(self):
@@ -132,7 +131,7 @@ class Area(object):
132
131
  except ValueError as e:
133
132
  logger.error("list_of_elements(): FATAL ERROR: %s", e)
134
133
  return
135
- except Exception as e:
134
+ except Exception:
136
135
  return
137
136
 
138
137
  def has_fsl(self):
@@ -142,19 +142,25 @@ def convert(dxfile,
142
142
  logger.warn("distance yoke (dy) ignored")
143
143
  dy = 0.0
144
144
 
145
+ split_ini = split
146
+ split_cpy = False
147
+ if not (part or view_only):
148
+ split_ini = False
149
+ split_cpy = split
150
+
145
151
  try:
146
152
  if dxfile.split('.')[-1] == 'fem':
147
153
  basegeom = Geometry(femshapes(dxfile),
148
154
  rtol=rtol,
149
155
  atol=atol,
150
- split=split)
156
+ split=split_ini)
151
157
  else:
152
158
  basegeom = Geometry(dxfshapes(dxfile,
153
159
  mindist=mindist,
154
160
  layers=layers),
155
161
  rtol=rtol,
156
162
  atol=atol,
157
- split=split)
163
+ split=split_ini)
158
164
  except FileNotFoundError as ex:
159
165
  logger.error(ex)
160
166
  return dict()
@@ -230,6 +236,7 @@ def convert(dxfile,
230
236
  endangle=2*np.pi,
231
237
  airgap=True,
232
238
  inside=True,
239
+ split=split_cpy,
233
240
  delete_appendices=True)
234
241
 
235
242
  machine_inner = symmetry_search(machine_inner,
@@ -248,6 +255,7 @@ def convert(dxfile,
248
255
  endangle=2*np.pi,
249
256
  airgap=True,
250
257
  inside=False,
258
+ split=split_cpy,
251
259
  delete_appendices=True)
252
260
 
253
261
  machine_outer = symmetry_search(machine_outer,
@@ -151,7 +151,7 @@ class FslRenderer(object):
151
151
 
152
152
  n = 0
153
153
  for d, e in el_sorted:
154
- d_percent = min( 1.0, d / dist)
154
+ d_percent = min(1.0, d / dist)
155
155
  if ndt_list[n][0] < d_percent:
156
156
  self.agndst = ndt_list[n][1] * self.agndst
157
157
  self.content.append(u'\nndt({}*agndst)\n'.
@@ -356,7 +356,6 @@ class FslRenderer(object):
356
356
  geom.end_corners[0][0],
357
357
  geom.end_corners[0][1])] # min xy4
358
358
 
359
-
360
359
  self.content.append(u'if parts_gen > 1 then')
361
360
  if geom.corners_dont_match():
362
361
  txt = [u' -- Warning: corners dont match',
@@ -148,6 +148,10 @@ def area_size(points):
148
148
  def middle_point_of_arc(center, radius, p1, p2, rtol=1e-3, atol=1e-8):
149
149
  alpha_p1 = alpha_line(center, p1)
150
150
  alpha_p2 = alpha_line(center, p2)
151
+ if alpha_p1 < 0.0:
152
+ alpha_p1 += np.pi * 2.0
153
+ if alpha_p2 < 0.0:
154
+ alpha_p2 += np.pi * 2.0
151
155
 
152
156
  if np.isclose(alpha_p1, alpha_p2, rtol, atol):
153
157
  return p1
@@ -167,23 +171,13 @@ def middle_point_of_arc(center, radius, p1, p2, rtol=1e-3, atol=1e-8):
167
171
 
168
172
 
169
173
  def middle_angle(alpha1, alpha2):
170
- a1 = normalise_angle(alpha1)
171
- a2 = normalise_angle(alpha2)
172
-
173
- if np.isclose(a1, a2):
174
- return a1
175
-
176
- if greater_equal(a1, 0.0):
177
- if a2 < a1:
178
- a2 += 2.0*np.pi
179
- else:
180
- if less_equal(a2, a1):
181
- a1 += 2.0*np.pi
182
-
183
- if np.isclose(a1, a2):
184
- return copy.copy(a1)
185
-
186
- return (a1+a2)/2.0
174
+ if alpha1 < 0.0:
175
+ alpha1 += np.pi * 2.0
176
+ if alpha2 < 0.0:
177
+ alpha2 += np.pi * 2.0
178
+ if alpha2 < alpha1:
179
+ alpha2 += np.pi * 2.0
180
+ return normalise_angle((alpha1 + alpha2) / 2.0)
187
181
 
188
182
 
189
183
  def third_angle(alpha1, alpha2):
@@ -203,7 +197,7 @@ def third_angle(alpha1, alpha2):
203
197
  if np.isclose(a1, a2):
204
198
  return copy.copy(a1)
205
199
 
206
- return (a1+a2)/3.0
200
+ return normalise_angle((a1+a2)/3.0)
207
201
 
208
202
 
209
203
  def middle_point_of_line(p1, p2):
@@ -324,21 +318,21 @@ def gcd(x, y):
324
318
  return x+y
325
319
 
326
320
 
327
- def is_angle_outside(startangle, endangle, alpha):
328
- return not is_angle_inside(startangle, endangle, alpha)
321
+ def is_angle_outside(startangle, endangle, alpha, rtol=1e-08, atol=1e-08):
322
+ return not is_angle_inside(startangle, endangle, alpha, rtol=rtol, atol=atol)
329
323
 
330
324
 
331
- def is_angle_inside(startangle, endangle, alpha):
325
+ def is_angle_inside(startangle, endangle, alpha, rtol=1e-08, atol=1e-08):
332
326
  start = normalise_angle(startangle)
333
327
  end = normalise_angle(endangle)
334
328
  mid = normalise_angle(alpha)
335
329
 
336
- if np.isclose(start, end, 1e-08):
330
+ if np.isclose(start, end, rtol=rtol, atol=atol):
337
331
  # In diesem Fall ist alles 'inside'
338
332
  return True
339
- if np.isclose(mid, start, 1e-08):
333
+ if np.isclose(mid, start, rtol=rtol, atol=atol):
340
334
  return True
341
- if np.isclose(mid, end, 1e-08):
335
+ if np.isclose(mid, end, rtol=rtol, atol=atol):
342
336
  return True
343
337
 
344
338
  if end < start:
@@ -352,7 +346,8 @@ def is_angle_inside(startangle, endangle, alpha):
352
346
 
353
347
 
354
348
  def is_point_outside_region(p, center, inner_radius, outer_radius,
355
- startangle, endangle):
349
+ startangle, endangle,
350
+ rtol=1e-08, atol=1e-08):
356
351
  alpha = alpha_line(center, p)
357
352
  if is_angle_outside(startangle, endangle, alpha):
358
353
  return True
@@ -362,10 +357,12 @@ def is_point_outside_region(p, center, inner_radius, outer_radius,
362
357
 
363
358
  def is_point_inside_region(p, center,
364
359
  inner_radius, outer_radius,
365
- startangle, endangle):
360
+ startangle, endangle,
361
+ rtol=1e-08, atol=1e-08):
366
362
  return not is_point_outside_region(p, center,
367
363
  inner_radius, outer_radius,
368
- startangle, endangle)
364
+ startangle, endangle,
365
+ rtol=rtol, atol=atol)
369
366
 
370
367
 
371
368
  def get_angle_of_arc(startangle, endangle):