femagtools 1.8.6__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 +11 -7
- femagtools/femag.py +8 -70
- femagtools/fsl.py +6 -3
- femagtools/isa7.py +47 -3
- femagtools/losscoeffs.py +29 -3
- femagtools/machine/afpm.py +15 -6
- femagtools/mcv.py +162 -7
- femagtools/parstudy.py +3 -1
- femagtools/plot/bch.py +126 -44
- femagtools/plot/nc.py +13 -0
- femagtools/shortcircuit.py +378 -0
- femagtools/templates/psi-torq-rem-rot.mako +127 -0
- {femagtools-1.8.6.dist-info → femagtools-1.8.7.dist-info}/METADATA +1 -1
- {femagtools-1.8.6.dist-info → femagtools-1.8.7.dist-info}/RECORD +20 -18
- tests/test_nc.py +11 -0
- {femagtools-1.8.6.dist-info → femagtools-1.8.7.dist-info}/LICENSE +0 -0
- {femagtools-1.8.6.dist-info → femagtools-1.8.7.dist-info}/WHEEL +0 -0
- {femagtools-1.8.6.dist-info → femagtools-1.8.7.dist-info}/entry_points.txt +0 -0
- {femagtools-1.8.6.dist-info → femagtools-1.8.7.dist-info}/top_level.txt +0 -0
femagtools/__init__.py
CHANGED
femagtools/bch.py
CHANGED
@@ -1057,10 +1057,11 @@ class Reader:
|
|
1057
1057
|
e.g. : idList[-450, -350, -250, -150, -50, 0]
|
1058
1058
|
idList[-500, -400, -300, -200, -100, 0, 0]
|
1059
1059
|
'''
|
1060
|
-
|
1061
|
-
if idList[-1] == 0 and len(idList) > 2 and \
|
1062
|
-
diff[-1] == 0:
|
1060
|
+
if list(idList).count(0) > 1: # femag writes duplicate id==0 values
|
1063
1061
|
idList = idList[:-1]
|
1062
|
+
diff = np.floor(np.abs(np.diff(idList)))
|
1063
|
+
if n := np.trim_zeros(np.diff(diff)).size:
|
1064
|
+
idList = idList[:-n]
|
1064
1065
|
return idList
|
1065
1066
|
|
1066
1067
|
def __read_psidq(self, content):
|
@@ -1085,8 +1086,7 @@ class Reader:
|
|
1085
1086
|
ncols = ncols-1
|
1086
1087
|
|
1087
1088
|
id = np.reshape(m[0], (-1, ncols)).T[0]
|
1088
|
-
|
1089
|
-
id = self.__removeTrailingZero(id)
|
1089
|
+
id = self.__removeTrailingZero(id)
|
1090
1090
|
nrows = len(id)
|
1091
1091
|
if nrows > 1 and id[nrows-1] < id[nrows-2]:
|
1092
1092
|
nrows = nrows-1
|
@@ -1121,8 +1121,7 @@ class Reader:
|
|
1121
1121
|
ncols = ncols-1
|
1122
1122
|
|
1123
1123
|
id = np.reshape(m[0], (-1, ncols)).T[0]
|
1124
|
-
|
1125
|
-
id = self.__removeTrailingZero(id)
|
1124
|
+
id = self.__removeTrailingZero(id)
|
1126
1125
|
nrows = len(id)
|
1127
1126
|
if nrows > 1 and id[nrows-1] < id[nrows-2]:
|
1128
1127
|
nrows = nrows-1
|
@@ -1610,6 +1609,11 @@ class Reader:
|
|
1610
1609
|
losses['staza'] = floatnan(rec[0])
|
1611
1610
|
losses['stajo'] = floatnan(rec[1])
|
1612
1611
|
losses['total'] += losses['staza']+losses['stajo']
|
1612
|
+
|
1613
|
+
elif content[i+1].split() == ['Iron', '----']:
|
1614
|
+
losses['rotfe'] = sum([floatnan(x) for x in rec])
|
1615
|
+
losses['total'] += losses['rotfe']
|
1616
|
+
|
1613
1617
|
else:
|
1614
1618
|
losses['rotfe'] = floatnan(rec[1])
|
1615
1619
|
losses['total'] += losses['rotfe']
|
femagtools/femag.py
CHANGED
@@ -61,43 +61,6 @@ def handle_process_output(filedes, outfile, log):
|
|
61
61
|
pass
|
62
62
|
|
63
63
|
|
64
|
-
def get_shortCircuit_parameters(bch, nload):
|
65
|
-
try:
|
66
|
-
if nload < 0:
|
67
|
-
nload = 0
|
68
|
-
if nload > 2:
|
69
|
-
nload = 2
|
70
|
-
if nload > 0:
|
71
|
-
dqld = bch.dqPar['ld']
|
72
|
-
dqlq = bch.dqPar['lq']
|
73
|
-
dqpsim = bch.dqPar['psim']
|
74
|
-
if len(dqld) <= nload or len(dqlq) <= nload or len(dqpsim) <= nload:
|
75
|
-
ld = dqld[-1]/bch.armatureLength
|
76
|
-
lq = dqlq[-1]/bch.armatureLength
|
77
|
-
psim = dqpsim[-1]/bch.armatureLength
|
78
|
-
else:
|
79
|
-
ld = dqld[nload-1]/bch.armatureLength
|
80
|
-
lq = dqlq[nload-1]/bch.armatureLength
|
81
|
-
psim = dqpsim[nload-1]/bch.armatureLength
|
82
|
-
else:
|
83
|
-
ld = bch.machine['ld']/bch.armatureLength
|
84
|
-
lq = bch.machine['lq']/bch.armatureLength
|
85
|
-
psim = bch.machine['psim']/bch.armatureLength
|
86
|
-
return dict(
|
87
|
-
r1=bch.machine['r1'],
|
88
|
-
ld=ld,
|
89
|
-
lq=lq,
|
90
|
-
psim=psim,
|
91
|
-
num_pol_pair=bch.machine['p'],
|
92
|
-
fc_radius=bch.machine['fc_radius'],
|
93
|
-
lfe=bch.armatureLength/1e3,
|
94
|
-
pocfilename=bch.machine['pocfile'],
|
95
|
-
num_par_wdgs=bch.machine.get('num_par_wdgs', 0),
|
96
|
-
calculationMode='shortcircuit')
|
97
|
-
except (KeyError, AttributeError, IndexError):
|
98
|
-
raise FemagError("missing pm/Rel-Sim results")
|
99
|
-
|
100
|
-
|
101
64
|
def set_magnet_properties(model, simulation, magnets):
|
102
65
|
"""set temperature adapted magnet properties"""
|
103
66
|
if not hasattr(model, 'magnet'):
|
@@ -449,7 +412,7 @@ class BaseFemag(object):
|
|
449
412
|
|
450
413
|
return list(pathlib.Path(self.workdir).glob('*.PROT'))[0].stem
|
451
414
|
|
452
|
-
def readResult(self, simulation, bch=None):
|
415
|
+
def readResult(self, machine, simulation, bch=None):
|
453
416
|
if simulation:
|
454
417
|
if simulation['calculationMode'] == "fieldcalc":
|
455
418
|
nc = self.read_nc()
|
@@ -495,38 +458,11 @@ class BaseFemag(object):
|
|
495
458
|
if simulation['calculationMode'] == 'pm_sym_fast' or \
|
496
459
|
simulation['calculationMode'] == 'torq_calc':
|
497
460
|
if simulation.get('shortCircuit', False):
|
498
|
-
|
499
|
-
simulation.update(
|
500
|
-
get_shortCircuit_parameters(bch,
|
501
|
-
simulation.get('initial', 2)))
|
502
|
-
|
503
|
-
builder = femagtools.fsl.Builder(self.templatedirs)
|
461
|
+
from .shortcircuit import shortcircuit
|
504
462
|
set_magnet_properties(self.model, simulation, self.magnets)
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
with open(os.path.join(self.workdir, fslfile), 'w') as f:
|
509
|
-
f.write('\n'.join(fslcmds))
|
510
|
-
self.run(fslfile) #, options?
|
511
|
-
bchfile = self.get_bch_file(self.modelname)
|
512
|
-
if bchfile:
|
513
|
-
bchsc = femagtools.bch.Reader()
|
514
|
-
logger.info("Read BCH {}".format(bchfile))
|
515
|
-
with io.open(bchfile, encoding='latin1',
|
516
|
-
errors='ignore') as f:
|
517
|
-
bchsc.read(f)
|
518
|
-
bch.scData = bchsc.scData
|
519
|
-
for w in bch.flux:
|
520
|
-
try:
|
521
|
-
bch.flux[w] += bchsc.flux[w]
|
522
|
-
bch.flux_fft[w] += bchsc.flux_fft[w]
|
523
|
-
except (KeyError, IndexError):
|
524
|
-
logging.debug(
|
525
|
-
"No additional flux data in sc simulation")
|
526
|
-
break
|
527
|
-
|
528
|
-
bch.torque += bchsc.torque
|
529
|
-
bch.demag += bchsc.demag
|
463
|
+
bch.scData = shortcircuit(self, machine, bch, simulation)
|
464
|
+
#bch.torque += bchsc.torque
|
465
|
+
#bch.demag += bchsc.demag
|
530
466
|
|
531
467
|
if 'airgap_induc' in simulation:
|
532
468
|
try:
|
@@ -699,8 +635,9 @@ class Femag(BaseFemag):
|
|
699
635
|
setattr(self, "dy2", machine['stator']['dy2'])
|
700
636
|
except:
|
701
637
|
pass
|
638
|
+
|
702
639
|
if simulation:
|
703
|
-
return self.readResult(simulation)
|
640
|
+
return self.readResult(machine, simulation)
|
704
641
|
|
705
642
|
return {'status': 'ok', 'message': self.modelname,
|
706
643
|
'model': self.model.props()}
|
@@ -801,6 +738,7 @@ class ZmqFemag(BaseFemag):
|
|
801
738
|
def subscribe(self, notify):
|
802
739
|
"""attaches a notify function"""
|
803
740
|
logger.info("Subscribe on '%s' port %d", self.femaghost, self.port+1)
|
741
|
+
femagtools.zmq.SubscriberTask.clear()
|
804
742
|
if self.subscriber is None:
|
805
743
|
# progress/xyplot at a configured timestep published
|
806
744
|
header = [b'progress', b'xyplot', b'license']
|
femagtools/fsl.py
CHANGED
@@ -227,7 +227,7 @@ class Builder:
|
|
227
227
|
# obsolete
|
228
228
|
th_props = [' ']
|
229
229
|
try:
|
230
|
-
logger.
|
230
|
+
logger.debug(model.magnet)
|
231
231
|
th_props = [f'rotor_density = {model["magnet"]["density"]}',
|
232
232
|
f'rotor_thcond = {model["magnet"]["thcond"]}',
|
233
233
|
f'rotor_thcap = {model["magnet"]["thcap"]}'
|
@@ -750,8 +750,11 @@ class Builder:
|
|
750
750
|
sim['eccentricity'])
|
751
751
|
|
752
752
|
if sim.get('calculationMode') == 'pm_sym_f_cur':
|
753
|
-
if 'nload_ex_cur'
|
754
|
-
sim
|
753
|
+
if sim.get('nload_ex_cur', ''): # convert obsolete key
|
754
|
+
if isinstance(sim, dict):
|
755
|
+
sim['noload_ex_cur'] = sim.pop('nload_ex_cur')
|
756
|
+
else:
|
757
|
+
sim.noload_ex_cur = sim.get('nload_ex_cur')
|
755
758
|
felosses = custom_fefunc + self.create_fe_losses(sim)
|
756
759
|
fslcalc = (displ_stator_rotor
|
757
760
|
+ self.__render(sim, sim.get('calculationMode'))
|
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
@@ -687,9 +687,9 @@ def _draw_vertical_slots(ax,
|
|
687
687
|
beta0 = np.linspace(n*taus + taus/2+alpha[0], (n+1)*taus, 5)
|
688
688
|
beta1 = np.linspace(n*taus + taus/2+alpha[1], (n+1)*taus, 5)
|
689
689
|
xr = np.concatenate((
|
690
|
-
r[0]*np.cos(beta0), r[1]*np.cos(beta1[::-1])))
|
690
|
+
r[0]*np.cos(beta0), r[1]*np.cos(beta1[::-1])))+xoff
|
691
691
|
yr = np.concatenate((
|
692
|
-
r[0]*np.sin(beta0), r[1]*np.sin(beta1[::-1])))
|
692
|
+
r[0]*np.sin(beta0), r[1]*np.sin(beta1[::-1])))+yoff
|
693
693
|
ax.fill(xr, yr, color=color[0])
|
694
694
|
|
695
695
|
|
@@ -707,7 +707,10 @@ def vertical_plot(machine, ax):
|
|
707
707
|
model_type = machine['afmtype'][0:4]
|
708
708
|
dy1 = machine['outer_diam']*1e3
|
709
709
|
dy2 = machine['inner_diam']*1e3
|
710
|
-
|
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']
|
711
714
|
Q = machine['stator']['num_slots']
|
712
715
|
slot_width = machine['stator']['afm_stator']['slot_width']*1e3
|
713
716
|
poles = machine['poles']
|
@@ -856,7 +859,10 @@ def horizontal_plot(machine, ax):
|
|
856
859
|
model_type = machine['afmtype'][0:4]
|
857
860
|
dy1 = machine['outer_diam']*1e3
|
858
861
|
dy2 = machine['inner_diam']*1e3
|
859
|
-
|
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']
|
860
866
|
magn_height = machine['magnet']['afm_rotor']['magn_height']*1e3
|
861
867
|
magn_yoke_height = machine['magnet']['afm_rotor']['yoke_height']*1e3
|
862
868
|
|
@@ -988,8 +994,11 @@ class AFPM:
|
|
988
994
|
|
989
995
|
machine['pole_width'] = np.pi * machine['inner_diam']/machine['poles']
|
990
996
|
machine['lfe'] = machine['outer_diam'] - machine['inner_diam']
|
991
|
-
|
992
|
-
machine['magnet']['afm_rotor']['rel_magn_width']
|
997
|
+
try:
|
998
|
+
machine['magnet']['afm_rotor']['rel_magn_width'] = max(
|
999
|
+
machine['magnet']['afm_rotor']['rel_magn_width'])
|
1000
|
+
except TypeError:
|
1001
|
+
pass
|
993
1002
|
|
994
1003
|
simulation['skew_displ'] = (simulation.get('skew_angle', 0)/180 * np.pi
|
995
1004
|
* machine['inner_diam'])
|
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/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):
|