femagtools 1.8.5__py3-none-any.whl → 1.8.7__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 +16 -9
- femagtools/dxfsl/area.py +3 -0
- femagtools/dxfsl/conv.py +1 -8
- femagtools/dxfsl/converter.py +62 -144
- femagtools/dxfsl/geom.py +49 -0
- femagtools/femag.py +13 -72
- femagtools/fsl.py +6 -3
- femagtools/isa7.py +47 -3
- femagtools/losscoeffs.py +29 -3
- femagtools/machine/afpm.py +82 -21
- femagtools/mcv.py +162 -7
- femagtools/multiproc.py +2 -1
- femagtools/parstudy.py +3 -1
- femagtools/plot/__init__.py +1 -0
- femagtools/plot/bch.py +172 -36
- femagtools/plot/machine.py +100 -0
- femagtools/plot/nc.py +13 -0
- femagtools/poc.py +10 -0
- femagtools/shortcircuit.py +378 -0
- femagtools/templates/psi-torq-rem-rot.mako +127 -0
- femagtools/utils.py +2 -0
- femagtools/zmq.py +22 -4
- {femagtools-1.8.5.dist-info → femagtools-1.8.7.dist-info}/METADATA +1 -1
- {femagtools-1.8.5.dist-info → femagtools-1.8.7.dist-info}/RECORD +30 -27
- tests/test_nc.py +11 -0
- {femagtools-1.8.5.dist-info → femagtools-1.8.7.dist-info}/LICENSE +0 -0
- {femagtools-1.8.5.dist-info → femagtools-1.8.7.dist-info}/WHEEL +0 -0
- {femagtools-1.8.5.dist-info → femagtools-1.8.7.dist-info}/entry_points.txt +0 -0
- {femagtools-1.8.5.dist-info → femagtools-1.8.7.dist-info}/top_level.txt +0 -0
femagtools/isa7.py
CHANGED
@@ -1418,6 +1418,13 @@ class Element(BaseEntity):
|
|
1418
1418
|
"""return True if the element has lamination properties"""
|
1419
1419
|
return self.reluc != (1.0, 1.0) and self.mag == (0.0, 0.0)
|
1420
1420
|
|
1421
|
+
def remanence(self, temperature=20):
|
1422
|
+
"""return remanence Brx, Bry at element
|
1423
|
+
Arguments:
|
1424
|
+
temperature: (float) temperature in °C"""
|
1425
|
+
br_temp_corr = 1. + self.br_temp_coef*(temperature - 20.)
|
1426
|
+
return self.mag[0]*br_temp_corr, self.mag[1]*br_temp_corr
|
1427
|
+
|
1421
1428
|
def demagnetization(self, temperature=20):
|
1422
1429
|
"""return demagnetization Hx, Hy of this element"""
|
1423
1430
|
return self.demag_b(self.flux_density(cosys='polar'), temperature)
|
@@ -1429,9 +1436,9 @@ class Element(BaseEntity):
|
|
1429
1436
|
# assume polar coordinates of b
|
1430
1437
|
pos = np.arctan2(self.center[1], self.center[0])
|
1431
1438
|
#pos = 0 # cartesian
|
1432
|
-
|
1433
|
-
magn = np.sqrt(
|
1434
|
-
alfa = np.arctan2(
|
1439
|
+
mag = self.remanence(temperature)
|
1440
|
+
magn = np.sqrt(mag[0]**2 + mag[1]**2)
|
1441
|
+
alfa = np.arctan2(mag[1], mag[0]) - pos
|
1435
1442
|
b1, b2 = b
|
1436
1443
|
bpol = b1 * np.cos(alfa) + b2 * np.sin(alfa)
|
1437
1444
|
reluc = abs(self.reluc[0]) / (4*np.pi*1e-7 * 1000)
|
@@ -1505,6 +1512,43 @@ class SuperElement(BaseEntity):
|
|
1505
1512
|
"""return area of this superelement"""
|
1506
1513
|
return sum([e.area for e in self.elements])
|
1507
1514
|
|
1515
|
+
def get_rect_geom(self):
|
1516
|
+
"""return rectangle parameters of superelement:
|
1517
|
+
x0, y0: center coordinates
|
1518
|
+
w, h: width and height
|
1519
|
+
alpha: angle of main axis"""
|
1520
|
+
bxy = np.array([n.xy for b in self.nodechains
|
1521
|
+
for n in b.nodes[:-1]])
|
1522
|
+
# center
|
1523
|
+
cxy = np.mean(bxy, axis=0)
|
1524
|
+
# corner points: calculate angles
|
1525
|
+
b = np.vstack((bxy[-1], bxy, bxy[0]))
|
1526
|
+
a = np.arctan2(b[1:, 1]-b[:-1, 1],
|
1527
|
+
b[1:, 0]- b[:-1, 0])
|
1528
|
+
peaks = np.where(np.abs(np.diff(a)) > 1)[0]
|
1529
|
+
c = bxy[peaks]
|
1530
|
+
# width and height
|
1531
|
+
dxy = np.linalg.norm(np.vstack(
|
1532
|
+
(bxy[:-1, :] - bxy[1:, :],
|
1533
|
+
bxy[-1, :] - bxy[0, :])), axis=1)
|
1534
|
+
dc = (np.sum(dxy[peaks[0]:peaks[1]]),
|
1535
|
+
np.sum(dxy[peaks[1]:peaks[2]]),
|
1536
|
+
np.sum(dxy[peaks[2]:peaks[3]]),
|
1537
|
+
np.sum(np.hstack(
|
1538
|
+
(dxy[peaks[3]:], dxy[:peaks[0]]))))
|
1539
|
+
w = np.mean(np.sort(dc)[-2:])
|
1540
|
+
area = self.area()
|
1541
|
+
h = area/w
|
1542
|
+
# angle of main axis
|
1543
|
+
i = np.argmax(dc)
|
1544
|
+
c = np.vstack((c, c[0]))
|
1545
|
+
alpha = np.arctan2(c[i+1, 1]-c[i, 1], c[i+1, 0]-c[i, 0])
|
1546
|
+
if alpha < 0:
|
1547
|
+
alpha += np.pi
|
1548
|
+
return {'w': w, 'h': h, 'x0': cxy[0], 'y0': cxy[1],
|
1549
|
+
'area': area, 'alpha': alpha}
|
1550
|
+
|
1551
|
+
|
1508
1552
|
class SubRegion(BaseEntity):
|
1509
1553
|
def __init__(self, key, sr_type, color, name, nturns, curdir, wb_key,
|
1510
1554
|
superelements, nodechains):
|
femagtools/losscoeffs.py
CHANGED
@@ -20,6 +20,11 @@ def pfe_jordan(f, B, ch, fh, cw, fw, fb, fo, Bo):
|
|
20
20
|
def pfe_steinmetz(f, B, cw, fw, fb, fo, Bo):
|
21
21
|
return cw*(f/fo)**fw * (B/Bo)**fb
|
22
22
|
|
23
|
+
def pfe_modified_steinmetz(f, B, ch, cw, alpha, beta, fo, Bo):
|
24
|
+
return ch*(f/fo)*(B/Bo)**(alpha + B*beta) + cw*(f/fo)**2*(B/Bo)**2
|
25
|
+
|
26
|
+
def wbert(f, b, ch, cw, cx):
|
27
|
+
return (ch + cw*f)*b**2 + cx*f**0.5*b**1.5
|
23
28
|
|
24
29
|
def fitsteinmetz(f, B, losses, Bo, fo, alpha0=1.0):
|
25
30
|
"""fit coeffs of
|
@@ -56,6 +61,30 @@ def fitsteinmetz(f, B, losses, Bo, fo, alpha0=1.0):
|
|
56
61
|
fbx, y, (1.0, 1.0, 2.0))
|
57
62
|
return fitp
|
58
63
|
|
64
|
+
def fit_modified_steinmetz(f, B, losses, Bo, fo):
|
65
|
+
"""fit coeffs of modifeld steinmetz
|
66
|
+
losses(f,B)=ch*(f/fo)*(B/Bo)**(alpha + B*beta) + cw*(f/fo)**2*(B/Bo)**2
|
67
|
+
returns (ch, cw, alpha, beta)
|
68
|
+
"""
|
69
|
+
pfe = losses
|
70
|
+
z = []
|
71
|
+
for i, fx in enumerate(f):
|
72
|
+
if fx:
|
73
|
+
if isinstance(B[0], float):
|
74
|
+
z += [(fx, bx, y)
|
75
|
+
for bx, y in zip(B, pfe[i])
|
76
|
+
if y]
|
77
|
+
else:
|
78
|
+
z += [(fx, bx, y)
|
79
|
+
for bx, y in zip(B[i], pfe[i])
|
80
|
+
if y]
|
81
|
+
|
82
|
+
fbx = np.array(z).T[0:2]
|
83
|
+
y = np.array(z).T[2]
|
84
|
+
fitp, cov = so.curve_fit(lambda x, ch, cw, alpha, beta: pfe_modified_steinmetz(
|
85
|
+
x[0], x[1], ch, cw, alpha, beta, fo, Bo),
|
86
|
+
fbx, y, (1.0, 1.0, 1.0, 1.0))
|
87
|
+
return fitp
|
59
88
|
|
60
89
|
def fitjordan(f, B, losses, Bo, fo):
|
61
90
|
"""fit coeffs of
|
@@ -115,9 +144,6 @@ def fit_bertotti(f, B, losses):
|
|
115
144
|
if j > 2:
|
116
145
|
v.append(np.array((f[i0:j+i0], bb, y)).T.tolist())
|
117
146
|
|
118
|
-
def wbert(f, b, ch, cw, cx):
|
119
|
-
return (ch + cw*f)*b**2 + cx*f**0.5*b**1.5
|
120
|
-
|
121
147
|
z = np.array([b for a in v for b in a]).T
|
122
148
|
fbx = z[0:2]
|
123
149
|
y = z[2]
|
femagtools/machine/afpm.py
CHANGED
@@ -15,6 +15,7 @@ from scipy.interpolate import make_interp_spline, RegularGridInterpolator, RectB
|
|
15
15
|
from scipy.integrate import quad
|
16
16
|
import copy
|
17
17
|
from matplotlib.colors import to_rgb
|
18
|
+
from multiprocessing import Pool
|
18
19
|
|
19
20
|
logger = logging.getLogger(__name__)
|
20
21
|
|
@@ -54,7 +55,8 @@ def _integrate(radius, pos, val):
|
|
54
55
|
interp = RegularGridInterpolator((radius, pos), val)
|
55
56
|
def func(x, y):
|
56
57
|
return interp((x, y))
|
57
|
-
return [quad(func, radius[0], radius[-1],
|
58
|
+
return [quad(func, radius[0], radius[-1],
|
59
|
+
args=(p,), limit=200)[0]
|
58
60
|
for p in pos]
|
59
61
|
|
60
62
|
|
@@ -62,7 +64,7 @@ def _integrate1d(radius, val):
|
|
62
64
|
interp = make_interp_spline(radius, val, k=1)
|
63
65
|
def func(x):
|
64
66
|
return interp((x))
|
65
|
-
return quad(func, radius[0], radius[-1])[0]
|
67
|
+
return quad(func, radius[0], radius[-1], limit=100)[0]
|
66
68
|
|
67
69
|
def ld_interpol(i1, beta, v):
|
68
70
|
'''interpolate Ld at beta angle 0°, -180°'''
|
@@ -152,7 +154,17 @@ def parident(workdir, engine, temp, machine,
|
|
152
154
|
machine[wdgk].get('num_par_wdgs', 1))
|
153
155
|
|
154
156
|
p = machine['poles']
|
155
|
-
|
157
|
+
if np.isscalar(machine['magnet']['afm_rotor']['rel_magn_width']):
|
158
|
+
num_slices = kwargs.get('num_slices', 3)
|
159
|
+
rmagw = num_slices*[machine['magnet']['afm_rotor']['rel_magn_width']]
|
160
|
+
else:
|
161
|
+
rmagw = machine['magnet']['afm_rotor']['rel_magn_width']
|
162
|
+
if len(rmagw) == 1:
|
163
|
+
num_slices = kwargs.get('num_slices', 3)
|
164
|
+
rmagw = num_slices*list(rmagw)
|
165
|
+
else:
|
166
|
+
num_slices = len(rmagw)
|
167
|
+
|
156
168
|
lfe = get_arm_lengths(machine['outer_diam'],
|
157
169
|
machine['inner_diam'],
|
158
170
|
num_slices)
|
@@ -172,6 +184,8 @@ def parident(workdir, engine, temp, machine,
|
|
172
184
|
"decision_vars": [
|
173
185
|
{"values": pole_width,
|
174
186
|
"name": "pole_width"},
|
187
|
+
{"values": rmagw,
|
188
|
+
"name": "magnet.afm_rotor.rel_magn_width"},
|
175
189
|
{"values": lfe,
|
176
190
|
"name": "lfe"},
|
177
191
|
{"values": linspeed, "name": "speed"}
|
@@ -216,9 +230,11 @@ def parident(workdir, engine, temp, machine,
|
|
216
230
|
else:
|
217
231
|
nlresults = {"x": [], "f": []}
|
218
232
|
i = 0
|
219
|
-
|
233
|
+
|
234
|
+
for pw, le, sp, rmw in zip(pole_width, lfe, linspeed, rmagw):
|
220
235
|
nlmachine = {k: machine[k] for k in machine}
|
221
236
|
nlmachine['pole_width'] = pw
|
237
|
+
nlmachine['magnet']['afm_rotor']['rel_magn_width'] = rmw
|
222
238
|
nlmachine['lfe'] = le
|
223
239
|
nlcalc.update({"speed": sp})
|
224
240
|
nlsubdir = f'{workdir}/{i}'
|
@@ -237,10 +253,11 @@ def parident(workdir, engine, temp, machine,
|
|
237
253
|
current_angles = nlresults['f'][0]['current_angles']
|
238
254
|
results = []
|
239
255
|
i = 0
|
240
|
-
for l, pw in zip(lfe, pole_width):
|
256
|
+
for l, pw, rmw in zip(lfe, pole_width, rmagw):
|
241
257
|
mpart = {k: machine[k] for k in machine if k != 'afm_rotor'}
|
242
258
|
mpart['pole_width'] = pw
|
243
259
|
mpart['lfe'] = l
|
260
|
+
mpart['magnet']['afm_rotor']['rel_magn_width'] = rmw
|
244
261
|
subdir = f"{workdir}/{i}"
|
245
262
|
|
246
263
|
simulation = dict(
|
@@ -296,12 +313,23 @@ def parident(workdir, engine, temp, machine,
|
|
296
313
|
i += 1
|
297
314
|
|
298
315
|
postp = []
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
316
|
+
if kwargs.get('use_multiprocessing', True):
|
317
|
+
with Pool() as p:
|
318
|
+
for r in p.starmap(process,
|
319
|
+
[(lfe, pole_width, machine, bch)
|
320
|
+
for bch in zip(*[r['f']
|
321
|
+
for r in results])]):
|
322
|
+
torque = np.mean(r.pop('torque'))
|
323
|
+
r['torque'] = torque
|
324
|
+
r.update(_psidq_ldq(r, nlresults))
|
325
|
+
postp.append(r)
|
326
|
+
else:
|
327
|
+
for r in [process(lfe, pole_width, machine, bch)
|
328
|
+
for bch in zip(*[r['f'] for r in results])]:
|
329
|
+
torque = np.mean(r.pop('torque'))
|
330
|
+
r['torque'] = torque
|
331
|
+
r.update(_psidq_ldq(r, nlresults))
|
332
|
+
postp.append(r)
|
305
333
|
|
306
334
|
r1 = postp[0]['r1']
|
307
335
|
i1 = [r['i1'] for r in postp][::num_beta_steps]
|
@@ -396,6 +424,7 @@ def process(lfe, pole_width, machine, bch):
|
|
396
424
|
n = len(rotpos[0])
|
397
425
|
currents = [bch[0]['flux'][k][0]['current_k'][:n]
|
398
426
|
for k in bch[0]['flux']]
|
427
|
+
|
399
428
|
if len(pole_width) > 1:
|
400
429
|
# check homogenity:
|
401
430
|
if np.diff([len(d) for d in displ]).any():
|
@@ -427,6 +456,9 @@ def process(lfe, pole_width, machine, bch):
|
|
427
456
|
for ux in bch[0]['flux'][k][0]['voltage_dpsi'][:-1]]
|
428
457
|
for k in bch[0]['flux']}
|
429
458
|
emf = [voltage[k][:n] for k in voltage]
|
459
|
+
fluxxy = {k: [scale_factor * np.array(flx)
|
460
|
+
for flx in bch[0]['flux'][k][0]['flux_k']]
|
461
|
+
for k in bch[0]['flux']}
|
430
462
|
flux = [fluxxy[k][:n] for k in fluxxy]
|
431
463
|
|
432
464
|
pos = (rotpos[0]/np.pi*180)
|
@@ -485,7 +517,6 @@ def process(lfe, pole_width, machine, bch):
|
|
485
517
|
except KeyError as exc:
|
486
518
|
#logger.warning("missing key %s", exc)
|
487
519
|
pass
|
488
|
-
|
489
520
|
return {
|
490
521
|
'weights': weights.tolist(),
|
491
522
|
'pos': pos.tolist(), 'r1': r1,
|
@@ -646,13 +677,20 @@ def _draw_vertical_slots(ax,
|
|
646
677
|
color = _get_colors(color, delta)
|
647
678
|
taus = 2*np.pi/Q
|
648
679
|
for n in range(Q):
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
680
|
+
beta0 = np.linspace(n*taus, n*taus + taus/2-alpha[0], 5)
|
681
|
+
beta1 = np.linspace(n*taus, n*taus + taus/2-alpha[1], 5)
|
682
|
+
xr = np.concatenate((
|
683
|
+
r[0]*np.cos(beta0), r[1]*np.cos(beta1[::-1])))+xoff
|
684
|
+
yr = np.concatenate((
|
685
|
+
r[0]*np.sin(beta0), r[1]*np.sin(beta1[::-1])))+yoff
|
686
|
+
ax.fill(xr, yr, color=color[0])
|
687
|
+
beta0 = np.linspace(n*taus + taus/2+alpha[0], (n+1)*taus, 5)
|
688
|
+
beta1 = np.linspace(n*taus + taus/2+alpha[1], (n+1)*taus, 5)
|
689
|
+
xr = np.concatenate((
|
690
|
+
r[0]*np.cos(beta0), r[1]*np.cos(beta1[::-1])))+xoff
|
691
|
+
yr = np.concatenate((
|
692
|
+
r[0]*np.sin(beta0), r[1]*np.sin(beta1[::-1])))+yoff
|
693
|
+
ax.fill(xr, yr, color=color[0])
|
656
694
|
|
657
695
|
|
658
696
|
def vertical_plot(machine, ax):
|
@@ -669,7 +707,10 @@ def vertical_plot(machine, ax):
|
|
669
707
|
model_type = machine['afmtype'][0:4]
|
670
708
|
dy1 = machine['outer_diam']*1e3
|
671
709
|
dy2 = machine['inner_diam']*1e3
|
672
|
-
|
710
|
+
try:
|
711
|
+
rel_magn_width = max(machine['magnet']['afm_rotor']['rel_magn_width'])
|
712
|
+
except TypeError:
|
713
|
+
rel_magn_width = machine['magnet']['afm_rotor']['rel_magn_width']
|
673
714
|
Q = machine['stator']['num_slots']
|
674
715
|
slot_width = machine['stator']['afm_stator']['slot_width']*1e3
|
675
716
|
poles = machine['poles']
|
@@ -818,7 +859,10 @@ def horizontal_plot(machine, ax):
|
|
818
859
|
model_type = machine['afmtype'][0:4]
|
819
860
|
dy1 = machine['outer_diam']*1e3
|
820
861
|
dy2 = machine['inner_diam']*1e3
|
821
|
-
|
862
|
+
try:
|
863
|
+
rel_magn_width = max(machine['magnet']['afm_rotor']['rel_magn_width'])
|
864
|
+
except TypeError:
|
865
|
+
rel_magn_width = machine['magnet']['afm_rotor']['rel_magn_width']
|
822
866
|
magn_height = machine['magnet']['afm_rotor']['magn_height']*1e3
|
823
867
|
magn_yoke_height = machine['magnet']['afm_rotor']['yoke_height']*1e3
|
824
868
|
|
@@ -911,6 +955,14 @@ class AFPM:
|
|
911
955
|
except KeyError:
|
912
956
|
raise ValueError("missing key afmtype")
|
913
957
|
|
958
|
+
if np.isscalar(machine['magnet']['afm_rotor']['rel_magn_width']):
|
959
|
+
rmagw = num_slices*[machine['magnet']['afm_rotor']['rel_magn_width']]
|
960
|
+
else:
|
961
|
+
rmagw = machine['magnet']['afm_rotor']['rel_magn_width']
|
962
|
+
if len(rmagw) == 1:
|
963
|
+
rmagw = num_slices*list(rmagw)
|
964
|
+
elif num_slices != len(rmagw):
|
965
|
+
num_slices = len(rmagw)
|
914
966
|
lfe = get_arm_lengths(machine['outer_diam'],
|
915
967
|
machine['inner_diam'],
|
916
968
|
num_slices)
|
@@ -934,11 +986,20 @@ class AFPM:
|
|
934
986
|
"name": "pole_width"},
|
935
987
|
{"values": lfe,
|
936
988
|
"name": "lfe"},
|
989
|
+
{"values": rmagw,
|
990
|
+
"name": "magnet.afm_rotor.rel_magn_width"},
|
937
991
|
{"values": linspeed, "name": "speed"}
|
938
992
|
]
|
939
993
|
}
|
994
|
+
|
940
995
|
machine['pole_width'] = np.pi * machine['inner_diam']/machine['poles']
|
941
996
|
machine['lfe'] = machine['outer_diam'] - machine['inner_diam']
|
997
|
+
try:
|
998
|
+
machine['magnet']['afm_rotor']['rel_magn_width'] = max(
|
999
|
+
machine['magnet']['afm_rotor']['rel_magn_width'])
|
1000
|
+
except TypeError:
|
1001
|
+
pass
|
1002
|
+
|
942
1003
|
simulation['skew_displ'] = (simulation.get('skew_angle', 0)/180 * np.pi
|
943
1004
|
* machine['inner_diam'])
|
944
1005
|
nlresults = {}
|
femagtools/mcv.py
CHANGED
@@ -298,6 +298,8 @@ class Mcv(object):
|
|
298
298
|
# {'ch': 0, 'cw': 0, 'ch_freq':0, 'cw_freq':0}
|
299
299
|
self.bertotti = {}
|
300
300
|
# {'ch': 0, 'cw': 0, 'ce':0, 'ch_freq':0, 'cw_freq':0}
|
301
|
+
self.steinmetz_modified = {}
|
302
|
+
# {'ch': 0, 'cw': 0, 'ch_freq': 1, 'b_beta_coeff': 0, 'cw_freq': 2, 'b_coeff': 2}
|
301
303
|
self.MC1_FE_SPEZ_WEIGTH = 7.65
|
302
304
|
self.MC1_FE_SAT_MAGNETIZATION = 2.15
|
303
305
|
|
@@ -359,7 +361,7 @@ class Mcv(object):
|
|
359
361
|
for k in wtrans:
|
360
362
|
if wtrans[k] in data.keys():
|
361
363
|
self.__setattr__(k, data[wtrans[k]])
|
362
|
-
for k in ('bertotti', 'jordan', 'steinmetz'):
|
364
|
+
for k in ('bertotti', 'jordan', 'steinmetz', 'steinmetz_modified'):
|
363
365
|
if k in data:
|
364
366
|
self.__setattr__(k, data[k])
|
365
367
|
self.curve = data['curve']
|
@@ -374,6 +376,13 @@ class Mcv(object):
|
|
374
376
|
# assume jordan iron loss parameters
|
375
377
|
for k in self.jordan:
|
376
378
|
self.jordan[k] = getattr(self, transl[k])
|
379
|
+
# set loss coeffs when existing
|
380
|
+
try:
|
381
|
+
for k in ('bertotti', 'jordan', 'steinmetz', 'steinmetz_modified'):
|
382
|
+
if k in data:
|
383
|
+
self.__setattr__(k, data[k])
|
384
|
+
except:
|
385
|
+
pass
|
377
386
|
return
|
378
387
|
|
379
388
|
def rtrimValueList(self, vlist):
|
@@ -489,14 +498,24 @@ class Writer(Mcv):
|
|
489
498
|
feloss: (str) iron loss method (bertotti, jordan)
|
490
499
|
"""
|
491
500
|
curve = self._prepare(fillfac, recsin)
|
501
|
+
write_losses = True
|
492
502
|
try:
|
493
503
|
if feloss.lower() == 'bertotti':
|
494
504
|
for k in self.bertotti:
|
495
505
|
setattr(self, transl[k], self.bertotti[k])
|
496
|
-
|
497
|
-
|
506
|
+
write_losses = False
|
507
|
+
elif feloss.lower() == 'jordan':
|
498
508
|
for k in self.jordan:
|
499
509
|
setattr(self, transl[k], self.jordan[k])
|
510
|
+
write_losses = False
|
511
|
+
elif feloss.lower() == 'steinmetz':
|
512
|
+
for k in self.steinmetz:
|
513
|
+
setattr(self, transl[k], self.steinmetz[k])
|
514
|
+
write_losses = False
|
515
|
+
elif feloss.lower() == 'modified steinmetz':
|
516
|
+
for k in self.steinmetz_modified:
|
517
|
+
setattr(self, transl[k], self.steinmetz_modified[k])
|
518
|
+
write_losses = False
|
500
519
|
except AttributeError as e:
|
501
520
|
logger.warning("%s", e)
|
502
521
|
pass
|
@@ -578,7 +597,7 @@ class Writer(Mcv):
|
|
578
597
|
self.writeBlock([self.mc1_angle[K], self.mc1_db2[K]])
|
579
598
|
|
580
599
|
try:
|
581
|
-
if not (self.mc1_ch_factor or self.mc1_cw_factor) and self.losses:
|
600
|
+
if not (self.mc1_ch_factor or self.mc1_cw_factor) and self.losses and write_losses:
|
582
601
|
# fit loss parameters
|
583
602
|
pfe = self.losses['pfe']
|
584
603
|
f = self.losses['f']
|
@@ -611,12 +630,24 @@ class Writer(Mcv):
|
|
611
630
|
float(self.mc1_fe_spez_weigth),
|
612
631
|
float(self.mc1_fe_sat_magnetization)])
|
613
632
|
|
633
|
+
logger.info(f"fo = {float(self.mc1_base_frequency)}")
|
634
|
+
logger.info(f"Bo = {float(self.mc1_base_induction)}")
|
635
|
+
logger.info(f"ch = {float(self.mc1_ch_factor)}")
|
636
|
+
logger.info(f"cw = {float(self.mc1_cw_factor)}")
|
637
|
+
logger.info(f"ch_freq = {float(self.mc1_ch_freq_factor)}")
|
638
|
+
logger.info(f"cw_freq = {float(self.mc1_cw_freq_factor)}")
|
639
|
+
logger.info(f"b_coeff = {float(self.mc1_induction_factor)}")
|
640
|
+
logger.info(f"fr_spez_weight = {float(self.mc1_fe_spez_weigth)}")
|
641
|
+
logger.info(f"fe_sat_magnetization = {float(self.mc1_fe_sat_magnetization)}")
|
642
|
+
|
614
643
|
if not hasattr(self, 'losses') or not self.losses:
|
615
644
|
# new variables: ce factor for bertotti losses
|
616
645
|
# b_beta_coeff for modified steinmetz
|
617
646
|
try:
|
618
647
|
self.writeBlock([float(self.mc1_ce_factor),
|
619
648
|
float(self.mc1_induction_beta_factor)])
|
649
|
+
logger.info(f"ce = {float(self.mc1_ce_factor)}")
|
650
|
+
logger.info(f"b_beta_coeff = {float(self.mc1_induction_beta_factor)}")
|
620
651
|
except:
|
621
652
|
pass
|
622
653
|
return
|
@@ -677,13 +708,18 @@ class Writer(Mcv):
|
|
677
708
|
[0.0]*(M_LOSS_INDUCT - len(pl)))
|
678
709
|
self.writeBlock(float(f))
|
679
710
|
nrec += 1
|
680
|
-
|
681
|
-
|
682
|
-
|
711
|
+
|
712
|
+
if write_losses:
|
713
|
+
for m in range(M_LOSS_FREQ - nrec):
|
714
|
+
self.writeBlock([0.0]*M_LOSS_INDUCT)
|
715
|
+
self.writeBlock(0.0)
|
683
716
|
|
684
717
|
self.writeBlock([self.losses['cw'], self.losses['cw_freq'],
|
685
718
|
self.losses['b_coeff'], self.losses['fo'],
|
686
719
|
self.losses['Bo']])
|
720
|
+
logger.info("losses_cw = %f, losses_cw_freq = %f, losses_b_coeff = %f, losses_fo = %f, losses_Bo = %f",
|
721
|
+
self.losses['cw'], self.losses['cw_freq'],
|
722
|
+
self.losses['b_coeff'], self.losses['fo'], self.losses['Bo'])
|
687
723
|
self.writeBlock([1])
|
688
724
|
logger.info('Losses n freq %d n ind %d', nfreq, nind)
|
689
725
|
except Exception as e:
|
@@ -1175,6 +1211,125 @@ class MagnetizingCurve(object):
|
|
1175
1211
|
losses['fo'] = self.mcv[m]['fo']
|
1176
1212
|
|
1177
1213
|
|
1214
|
+
class MCVconvert:
|
1215
|
+
def __init__(self, bhdata):
|
1216
|
+
self.steinmetz = dict(cw=0, cw_freq=0, b_coeff=0)
|
1217
|
+
self.jordan = dict(ch=0, ch_freq=0, cw=0, cw_freq=0, b_coeff=0)
|
1218
|
+
self.bertotti = dict(ch=0, cw=0, ce=0)
|
1219
|
+
self.steinmetz_modified = dict(ch=0, cw=0, ch_freq=1, b_beta_coeff=0, cw_freq=2, b_coeff=2)
|
1220
|
+
self.losscalc = None
|
1221
|
+
|
1222
|
+
B = []
|
1223
|
+
f = [50.0, 100.0, 200.0, 400.0, 1000.0, 2000.0]
|
1224
|
+
pfe = []
|
1225
|
+
jordan = False
|
1226
|
+
bertotti = False
|
1227
|
+
modified_steinmetz = False
|
1228
|
+
flag = False
|
1229
|
+
|
1230
|
+
if "losses" in bhdata:
|
1231
|
+
# test if any nan in data
|
1232
|
+
for i in ("B", "f"):
|
1233
|
+
if np.any(np.isnan(bhdata["losses"][i])) or \
|
1234
|
+
np.any(np.isnan(bhdata["losses"][i])):
|
1235
|
+
flag = True
|
1236
|
+
for i in bhdata["losses"]['pfe']:
|
1237
|
+
if np.any(np.isnan(i)):
|
1238
|
+
flag = True
|
1239
|
+
|
1240
|
+
if 'losses' not in bhdata or flag:
|
1241
|
+
# check steinmetz or jordan
|
1242
|
+
bhdata.update({"losses": {"pfe": [], "f":[], "B": []}})
|
1243
|
+
B = bhdata["curve"][-1]["bi"]
|
1244
|
+
if "ch" in bhdata:
|
1245
|
+
|
1246
|
+
if "ce" in bhdata:
|
1247
|
+
if bhdata['ce'] > 1e-15:
|
1248
|
+
bertotti = True
|
1249
|
+
|
1250
|
+
if bhdata["ch"] > 1e-15 and bhdata['ce'] < 1e-15:
|
1251
|
+
jordan = True
|
1252
|
+
|
1253
|
+
else:
|
1254
|
+
jordan = True
|
1255
|
+
|
1256
|
+
#if (conditions for modified steinmetz):
|
1257
|
+
# modified_steinmetz = True
|
1258
|
+
|
1259
|
+
if jordan:
|
1260
|
+
self.losscalc = 'jordan'
|
1261
|
+
logger.info("calculating based on jordan...")
|
1262
|
+
for i in f:
|
1263
|
+
pfe.append(lc.pfe_jordan(i, np.array(B), bhdata['ch'], bhdata['ch_freq'], bhdata['cw'],
|
1264
|
+
bhdata['cw_freq'], bhdata['b_coeff'], 50, 1.5))
|
1265
|
+
|
1266
|
+
elif bertotti:
|
1267
|
+
self.losscalc = 'bertotti'
|
1268
|
+
logger.info("calculating based on bertotti")
|
1269
|
+
for i in f:
|
1270
|
+
pfe.append(lc.wbert(i, np.array(B), bhdata['ch'], bhdata['cw'], bhdata['ce']))
|
1271
|
+
|
1272
|
+
elif modified_steinmetz:
|
1273
|
+
self.losscalc = 'modified steinmetz'
|
1274
|
+
logger.info("calculating based on modified steinmetz...")
|
1275
|
+
for i in f:
|
1276
|
+
pfe.append(lc.pfe_modified_steinmetz(i, np.array(B), bhdata['ch'], bhdata['cw'], bhdata['b_coeff'], bhdata['b_beta_coeff'], 1, 1))
|
1277
|
+
|
1278
|
+
else: # steinmetz
|
1279
|
+
self.losscalc = 'steinmetz'
|
1280
|
+
logger.info("calculating based on steinmetz...")
|
1281
|
+
for i in f:
|
1282
|
+
pfe.append(lc.pfe_steinmetz(i, np.array(B), bhdata['cw'],
|
1283
|
+
bhdata['cw_freq'], bhdata['b_coeff'], 50, 1.5))
|
1284
|
+
bhdata['losses']['pfe'] = pfe
|
1285
|
+
bhdata['losses']['B'] = B
|
1286
|
+
bhdata['losses']['f'] = f
|
1287
|
+
|
1288
|
+
idx = 0
|
1289
|
+
for i, j in enumerate(bhdata['losses']['f']):
|
1290
|
+
if j == 0:
|
1291
|
+
idx = i
|
1292
|
+
break
|
1293
|
+
idx = idx - 1
|
1294
|
+
z = lc.fitsteinmetz(bhdata['losses']['f'][0:idx],
|
1295
|
+
bhdata['losses']['B'],
|
1296
|
+
bhdata['losses']['pfe'][0:idx],
|
1297
|
+
1.5,
|
1298
|
+
50)
|
1299
|
+
|
1300
|
+
for i, j in enumerate(self.steinmetz):
|
1301
|
+
self.steinmetz[j] = z[i]
|
1302
|
+
self.steinmetz.update({"Bo": 1.5, "fo": 50})
|
1303
|
+
|
1304
|
+
z = lc.fitjordan(bhdata['losses']['f'][0:idx],
|
1305
|
+
bhdata['losses']['B'],
|
1306
|
+
bhdata['losses']['pfe'][0:idx],
|
1307
|
+
1.5,
|
1308
|
+
50)
|
1309
|
+
|
1310
|
+
for i, j in enumerate(self.jordan):
|
1311
|
+
self.jordan[j] = z[i]
|
1312
|
+
self.jordan.update({"Bo": 1.5, "fo": 50})
|
1313
|
+
|
1314
|
+
z = lc.fit_bertotti(bhdata['losses']['f'][0:idx],
|
1315
|
+
bhdata['losses']['B'],
|
1316
|
+
bhdata['losses']['pfe'][0:idx])
|
1317
|
+
|
1318
|
+
for i, j in enumerate(self.bertotti):
|
1319
|
+
self.bertotti[j] = z[i]
|
1320
|
+
self.bertotti.update({"Bo": 1, "fo": 1, "alpha": 2.0, "ch_freq": 1.0, "cw_freq": 2.0, "b_coeff": 2.0})
|
1321
|
+
|
1322
|
+
z = lc.fit_modified_steinmetz(bhdata['losses']['f'][0:idx],
|
1323
|
+
bhdata['losses']['B'],
|
1324
|
+
bhdata['losses']['pfe'][0:idx], 1, 1)
|
1325
|
+
|
1326
|
+
for i,j in enumerate(self.steinmetz_modified):
|
1327
|
+
self.steinmetz_modified[j] = z[i]
|
1328
|
+
self.steinmetz_modified.update({"Bo": 1, "fo": 1})
|
1329
|
+
|
1330
|
+
bhdata['losses']['pfe'] = np.transpose(bhdata['losses']['pfe']).tolist() #len(B) rows and len(f) columns
|
1331
|
+
|
1332
|
+
|
1178
1333
|
def read(filename):
|
1179
1334
|
"""read MC/MCV file and return mc dict"""
|
1180
1335
|
mcv = Reader()
|
femagtools/multiproc.py
CHANGED
@@ -56,7 +56,8 @@ class ProgressLogger(threading.Thread):
|
|
56
56
|
["progress_logger",
|
57
57
|
f"{self.numTot}:{numOf}:{percent}:{' '.join(summary)}"])
|
58
58
|
else:
|
59
|
-
|
59
|
+
# TODO: log message might be misleading
|
60
|
+
logger.debug('collecting FE losses ...')
|
60
61
|
return
|
61
62
|
|
62
63
|
def stop(self):
|
femagtools/parstudy.py
CHANGED
@@ -6,6 +6,7 @@ import scipy as sc
|
|
6
6
|
import logging
|
7
7
|
import glob
|
8
8
|
import os
|
9
|
+
import re
|
9
10
|
import time
|
10
11
|
import shutil
|
11
12
|
import functools
|
@@ -172,7 +173,8 @@ class ParameterStudy(object):
|
|
172
173
|
else:
|
173
174
|
workdir = pathlib.Path(self.femag.workdir)
|
174
175
|
for d in workdir.glob('[0-9]*'):
|
175
|
-
|
176
|
+
if re.search(r'^\d+$', d.name):
|
177
|
+
shutil.rmtree(d)
|
176
178
|
|
177
179
|
extra_result_files = []
|
178
180
|
if simulation.get('airgap_induc', False):
|