femagtools 1.5.7__py3-none-any.whl → 1.6.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.
- femagtools/__init__.py +1 -1
- femagtools/bch.py +38 -3
- femagtools/dxfsl/area.py +2 -3
- femagtools/dxfsl/conv.py +6 -1
- femagtools/dxfsl/converter.py +10 -2
- femagtools/dxfsl/fslrenderer.py +1 -2
- femagtools/dxfsl/functions.py +24 -27
- femagtools/dxfsl/geom.py +210 -89
- femagtools/dxfsl/machine.py +43 -16
- femagtools/dxfsl/plotrenderer.py +2 -2
- femagtools/dxfsl/shape.py +84 -19
- femagtools/femag.py +21 -3
- femagtools/fsl.py +14 -2
- femagtools/machine/__init__.py +13 -33
- femagtools/machine/afpm.py +22 -21
- femagtools/machine/pm.py +22 -21
- femagtools/machine/sm.py +1 -1
- femagtools/machine/utils.py +112 -58
- femagtools/mcv.py +27 -1
- femagtools/model.py +4 -2
- femagtools/nc.py +7 -0
- femagtools/opt.py +1 -1
- femagtools/parstudy.py +5 -2
- femagtools/plot/__init__.py +1 -0
- femagtools/plot/bch.py +2 -0
- femagtools/plot/fieldlines.py +37 -0
- femagtools/templates/basic_modpar.mako +8 -0
- femagtools/templates/bertotti.mako +40 -0
- femagtools/templates/modified_steinmetz.mako +39 -0
- femagtools/ts.py +1 -1
- femagtools/utils.py +9 -3
- {femagtools-1.5.7.dist-info → femagtools-1.6.1.dist-info}/METADATA +1 -1
- {femagtools-1.5.7.dist-info → femagtools-1.6.1.dist-info}/RECORD +40 -37
- tests/test_bchreader.py +12 -1
- tests/test_femag.py +1 -1
- tests/test_fsl.py +1 -1
- {femagtools-1.5.7.dist-info → femagtools-1.6.1.dist-info}/LICENSE +0 -0
- {femagtools-1.5.7.dist-info → femagtools-1.6.1.dist-info}/WHEEL +0 -0
- {femagtools-1.5.7.dist-info → femagtools-1.6.1.dist-info}/entry_points.txt +0 -0
- {femagtools-1.5.7.dist-info → femagtools-1.6.1.dist-info}/top_level.txt +0 -0
femagtools/__init__.py
CHANGED
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
|
@@ -266,6 +269,28 @@ class Reader:
|
|
266
269
|
self.weight['conductor'] = sum(w[1])
|
267
270
|
self.weight['magnet'] = sum(w[2])
|
268
271
|
self.weight['total'] = sum([sum(l) for l in w])
|
272
|
+
|
273
|
+
# check if cogging and fft
|
274
|
+
try:
|
275
|
+
if (self.type.startswith('Fast cogging')
|
276
|
+
and not self.torque_fft):
|
277
|
+
from .utils import fft
|
278
|
+
# calc frequency sepctrum (assume a full period)
|
279
|
+
f = fft(self.torque[0]['angle'],
|
280
|
+
self.torque[0]['torque'], pmod=2)
|
281
|
+
slots = self.machine['Q']
|
282
|
+
poles = 2*self.machine['p']
|
283
|
+
n = np.lcm(slots, poles)
|
284
|
+
nue = np.arange(0, 5*n).tolist()
|
285
|
+
order, tq = np.array(
|
286
|
+
[(n, b)
|
287
|
+
for n, b in zip(nue, f['nue'])]).T
|
288
|
+
self.torque_fft = [
|
289
|
+
{'order': order.tolist(),
|
290
|
+
'torque': tq.tolist()}]
|
291
|
+
except (KeyError, IndexError):
|
292
|
+
pass
|
293
|
+
|
269
294
|
return self
|
270
295
|
|
271
296
|
def __findNums(self, l):
|
@@ -1003,9 +1028,9 @@ class Reader:
|
|
1003
1028
|
e.g. : idList[-450, -350, -250, -150, -50, 0]
|
1004
1029
|
idList[-500, -400, -300, -200, -100, 0, 0]
|
1005
1030
|
'''
|
1031
|
+
diff = np.around(np.abs(np.diff(idList[1:]) - np.diff(idList)[:-1]), 1)
|
1006
1032
|
if idList[-1] == 0 and len(idList) > 2 and \
|
1007
|
-
|
1008
|
-
int(idList[-2] - idList[0]) / (len(idList)-2):
|
1033
|
+
not np.all(diff == diff[0]):
|
1009
1034
|
idList = idList[:-1]
|
1010
1035
|
return idList
|
1011
1036
|
|
@@ -1168,6 +1193,12 @@ class Reader:
|
|
1168
1193
|
for s in subregs[:-2] + ['rotor', 'magnet']:
|
1169
1194
|
cols += [s+'_hyst', s+'_eddy']
|
1170
1195
|
if m:
|
1196
|
+
# FEMAG-2024.2
|
1197
|
+
if len(m[0]) > len(subregs[:-1])*2+2:
|
1198
|
+
cols = []
|
1199
|
+
for s in subregs[:-2] + ['rotor', 'magnet']:
|
1200
|
+
cols += [s+'_hyst', s+'_eddy', s+'_excess']
|
1201
|
+
|
1171
1202
|
m = np.array(m).T
|
1172
1203
|
if self.ldq:
|
1173
1204
|
ls.update({k: np.reshape(v[:mlen],
|
@@ -1570,6 +1601,8 @@ class Reader:
|
|
1570
1601
|
x[0] = int(x[0])
|
1571
1602
|
if len(losses[part][k][0]) == 4:
|
1572
1603
|
cols = ('order_el', 'freq', 'hyst', 'eddy')
|
1604
|
+
if len(losses[part][k][0]) == 6:
|
1605
|
+
cols = ('order_mech', 'order_el', 'freq', 'hyst', 'eddy', 'excess')
|
1573
1606
|
if losses[part][k]:
|
1574
1607
|
self.losses[-1][part][k] = {
|
1575
1608
|
k1: l
|
@@ -1619,6 +1652,8 @@ class Reader:
|
|
1619
1652
|
elif len(rec) == 5: # FEMAG Rel 8.3 with el/mech order
|
1620
1653
|
losses[part][k].append([floatnan(x)
|
1621
1654
|
for i, x in enumerate(rec)])
|
1655
|
+
elif len(rec) == 6:
|
1656
|
+
losses[part][k].append([floatnan(x) for x in rec])
|
1622
1657
|
else:
|
1623
1658
|
part = 'fft'
|
1624
1659
|
|
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
|
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
|
134
|
+
except Exception:
|
136
135
|
return
|
137
136
|
|
138
137
|
def has_fsl(self):
|
femagtools/dxfsl/conv.py
CHANGED
@@ -119,9 +119,13 @@ def main():
|
|
119
119
|
dest='debug',
|
120
120
|
action="store_true")
|
121
121
|
argparser.add_argument('-l', '--log',
|
122
|
-
help='print information in logfile',
|
122
|
+
help='print information in logfile and set --debug',
|
123
123
|
dest='debug',
|
124
124
|
action="store_true")
|
125
|
+
argparser.add_argument('--logfile',
|
126
|
+
help='print information in logfile',
|
127
|
+
dest='logfile',
|
128
|
+
action="store_true")
|
125
129
|
argparser.add_argument('--version',
|
126
130
|
help='show version of some packages',
|
127
131
|
dest='version',
|
@@ -137,6 +141,7 @@ def main():
|
|
137
141
|
loglevel = logging.INFO
|
138
142
|
if args.debug:
|
139
143
|
loglevel = logging.DEBUG
|
144
|
+
if args.debug or args.logfile:
|
140
145
|
logfilename = 'debugger.log'
|
141
146
|
print("see log-messages in {}".format(logfilename))
|
142
147
|
|
femagtools/dxfsl/converter.py
CHANGED
@@ -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=
|
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=
|
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,
|
femagtools/dxfsl/fslrenderer.py
CHANGED
@@ -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(
|
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',
|
femagtools/dxfsl/functions.py
CHANGED
@@ -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
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
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,
|
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,
|
333
|
+
if np.isclose(mid, start, rtol=rtol, atol=atol):
|
340
334
|
return True
|
341
|
-
if np.isclose(mid, end,
|
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):
|