femagtools 1.8.5__py3-none-any.whl → 1.8.7__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- 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):
|