femagtools 1.8.17__py3-none-any.whl → 1.8.19__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/airgap.py +5 -1
- femagtools/bch.py +23 -6
- femagtools/dxfsl/area.py +35 -23
- femagtools/dxfsl/areabuilder.py +97 -58
- femagtools/dxfsl/converter.py +11 -1
- femagtools/dxfsl/fslrenderer.py +3 -0
- femagtools/dxfsl/geom.py +265 -63
- femagtools/dxfsl/machine.py +128 -9
- femagtools/dxfsl/symmetry.py +20 -5
- femagtools/femag.py +27 -16
- femagtools/isa7.py +25 -22
- femagtools/machine/__init__.py +3 -1
- femagtools/machine/effloss.py +18 -4
- femagtools/machine/pm.py +88 -74
- femagtools/machine/sm.py +32 -21
- femagtools/mcv.py +4 -1
- femagtools/plot/bch.py +3 -1
- femagtools/plot/char.py +5 -16
- femagtools/plot/nc.py +67 -34
- femagtools/shortcircuit.py +18 -10
- femagtools/templates/psi-torq-rem.mako +4 -4
- femagtools/templates/statorKS1.mako +43 -0
- femagtools/utils.py +5 -4
- {femagtools-1.8.17.dist-info → femagtools-1.8.19.dist-info}/METADATA +2 -2
- {femagtools-1.8.17.dist-info → femagtools-1.8.19.dist-info}/RECORD +31 -30
- tests/test_machine.py +1 -2
- {femagtools-1.8.17.dist-info → femagtools-1.8.19.dist-info}/WHEEL +0 -0
- {femagtools-1.8.17.dist-info → femagtools-1.8.19.dist-info}/entry_points.txt +0 -0
- {femagtools-1.8.17.dist-info → femagtools-1.8.19.dist-info}/licenses/LICENSE +0 -0
- {femagtools-1.8.17.dist-info → femagtools-1.8.19.dist-info}/top_level.txt +0 -0
femagtools/machine/pm.py
CHANGED
@@ -97,7 +97,7 @@ class PmRelMachine(object):
|
|
97
97
|
self.zeta1 = 0.2
|
98
98
|
self.gam = 0.7
|
99
99
|
self.kh = 2
|
100
|
-
self.kpfe = 1 # iron loss factor
|
100
|
+
self.kpfe = 1 # common iron loss factor
|
101
101
|
self.kpmag = 1 # magnet loss factor
|
102
102
|
self.kfric_b = 1
|
103
103
|
self.rotor_mass = 0
|
@@ -182,6 +182,8 @@ class PmRelMachine(object):
|
|
182
182
|
return (0, 0)
|
183
183
|
if np.isscalar(iqd0):
|
184
184
|
i0 = self.io
|
185
|
+
if torque<0:
|
186
|
+
i0[0] = -i0[0]
|
185
187
|
else:
|
186
188
|
i0 = iqd0
|
187
189
|
if with_mtpa:
|
@@ -193,10 +195,14 @@ class PmRelMachine(object):
|
|
193
195
|
if res.success:
|
194
196
|
#raise ValueError(f'Torque {torque}, io {i0}: {res.message}')
|
195
197
|
return res.x
|
198
|
+
# should not happen
|
196
199
|
def func(i1):
|
197
200
|
return torque - self.mtpa(i1)[2]
|
201
|
+
# with warnings.catch_warnings():
|
202
|
+
# warnings.simplefilter("error")
|
198
203
|
i1 = so.fsolve(func, res.x[0])[0]
|
199
204
|
return self.mtpa(i1)[:2]
|
205
|
+
|
200
206
|
def func(iq):
|
201
207
|
return torque - self.torque_iqd(iq, 0)
|
202
208
|
return so.fsolve(func, 0)[0]
|
@@ -220,7 +226,7 @@ class PmRelMachine(object):
|
|
220
226
|
else:
|
221
227
|
i0 = (iq0, 0)
|
222
228
|
logger.debug("initial guess i0 %f -> %s tx %f torque %f",
|
223
|
-
|
229
|
+
self.io[0], i0, tx, torque)
|
224
230
|
else:
|
225
231
|
i0 = iqd0
|
226
232
|
|
@@ -237,7 +243,7 @@ class PmRelMachine(object):
|
|
237
243
|
# make new initial guess:
|
238
244
|
tx = self.tmech_iqd(*i0, n)
|
239
245
|
logger.debug("k %d new guess i0 %s tx %f torque %f",
|
240
|
-
|
246
|
+
k, i0, tx, torque)
|
241
247
|
i0=(min(0.9*self.i1range[1]/np.sqrt(2), torque/tx*i0[0]), 0)
|
242
248
|
k += 1
|
243
249
|
raise ValueError(
|
@@ -247,45 +253,18 @@ class PmRelMachine(object):
|
|
247
253
|
iq = so.fsolve(tqiq, (i0[0],))[0]
|
248
254
|
return iq, 0, self.tmech_iqd(iq, 0, n)
|
249
255
|
|
250
|
-
def iqd_tmech0(self, torque, n, iqd0=0, with_mtpa=True):
|
251
|
-
"""return minimum d-q-current for shaft torque"""
|
252
|
-
if np.abs(torque) < 1e-2:
|
253
|
-
return (0, 0)
|
254
|
-
if np.isscalar(iqd0):
|
255
|
-
i0 = self.io
|
256
|
-
else:
|
257
|
-
i0 = iqd0
|
258
|
-
|
259
|
-
if with_mtpa:
|
260
|
-
res = so.minimize(
|
261
|
-
lambda iqd: la.norm(iqd), i0, method='SLSQP',
|
262
|
-
constraints=({'type': 'eq',
|
263
|
-
'fun': lambda iqd:
|
264
|
-
self.tmech_iqd(*iqd, n) - torque}))
|
265
|
-
if res.success:
|
266
|
-
return res.x
|
267
|
-
|
268
|
-
#logger.warning("n: %s, torque %s: %s %s",
|
269
|
-
# 60*n, torque, res.message, i0)
|
270
|
-
# try a different approach:
|
271
|
-
#raise ValueError(
|
272
|
-
# f'Torque {torque:.1f} speed {60*n:.1f} {res.message}')
|
273
|
-
def func(i1):
|
274
|
-
return torque - self.mtpa_tmech(i1, n)[2]
|
275
|
-
i1 = so.fsolve(func, res.x[0])[0]
|
276
|
-
return self.mtpa_tmech(i1, n)[:2]
|
277
|
-
|
278
|
-
def tqiq(iq):
|
279
|
-
return torque - self.tmech_iqd(float(iq), 0, n)
|
280
|
-
iq = so.fsolve(tqiq, (i0[0],))[0]
|
281
|
-
return iq, 0, self.tmech_iqd(iq, 0, n)
|
282
|
-
|
283
256
|
def tloss_iqd(self, iq, id, n):
|
284
257
|
"""return loss torque of d-q current, iron loss correction factor
|
285
258
|
and friction windage losses"""
|
286
259
|
if n > 1e-3:
|
287
260
|
f1 = self.p*n
|
288
|
-
|
261
|
+
plfe1 = self.kpfe * self.iqd_plfe1(iq, id, f1)
|
262
|
+
plfe2 = self.kpfe * self.iqd_plfe2(iq, id, f1)
|
263
|
+
if hasattr(self, 'kpfe_s'):
|
264
|
+
plfe1 = self.kpfe_s * self.iqd_plfe1(iq, id, f1)
|
265
|
+
if hasattr(self, 'kpfe_r'):
|
266
|
+
plfe2 = self.kpfe_r * self.iqd_plfe2(iq, id, f1)
|
267
|
+
plfe = plfe1 + plfe2
|
289
268
|
pmag = self.kpmag * self.iqd_plmag(iq, id, f1)
|
290
269
|
return (plfe + pmag + self.pfric(n))/(2*np.pi*n)
|
291
270
|
return 0
|
@@ -350,12 +329,12 @@ class PmRelMachine(object):
|
|
350
329
|
sign = -1 if i1max > 0 else 1
|
351
330
|
res = so.minimize(
|
352
331
|
lambda n: sign*self.tmech_iqd(iq, id, n),
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
332
|
+
n0,
|
333
|
+
constraints={
|
334
|
+
'type': 'eq',
|
335
|
+
'fun': lambda n:
|
336
|
+
np.sqrt(2)*u1max - np.linalg.norm(
|
337
|
+
self.uqd(2*np.pi*n*self.p, iq, id))})
|
359
338
|
return 2*np.pi*res.x[0]*self.p, self.tmech_iqd(iq, id, res.x[0])
|
360
339
|
|
361
340
|
return so.fsolve(lambda x: np.linalg.norm(
|
@@ -453,22 +432,26 @@ class PmRelMachine(object):
|
|
453
432
|
i1 = self.i1_tmech(torque, 0, n)
|
454
433
|
i0 = iqd(0, i1)
|
455
434
|
|
435
|
+
logger.debug("i0 %s", i0)
|
456
436
|
if np.linalg.norm(self.uqd(w1, *i0))/np.sqrt(2) > u1max:
|
457
437
|
beta, i1 = betai1(*i0)
|
458
438
|
with warnings.catch_warnings():
|
459
439
|
warnings.simplefilter("ignore")
|
460
|
-
|
461
|
-
self.uqd(w1, *iqd(b, i1)))/np.sqrt(2),
|
462
|
-
|
440
|
+
bx, _, ier, msg = so.fsolve(lambda b: u1max - np.linalg.norm(
|
441
|
+
self.uqd(w1, *iqd(b, i1)))/np.sqrt(2), beta,
|
442
|
+
full_output=True)
|
443
|
+
i0 = iqd(bx[0], i1)
|
444
|
+
logger.debug("i0 %s ier %d %s", i0, ier, msg)
|
463
445
|
|
464
|
-
res = so.minimize(
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
446
|
+
res = so.minimize(
|
447
|
+
lambda iqd: np.linalg.norm(iqd), i0, method='SLSQP',
|
448
|
+
constraints=(
|
449
|
+
{'type': 'eq',
|
450
|
+
'fun': lambda iqd:
|
451
|
+
self.tmech_iqd(*iqd, n) - torque},
|
452
|
+
{'type': 'ineq',
|
453
|
+
'fun': lambda iqd:
|
454
|
+
np.sqrt(2)*u1max - la.norm(self.uqd(w1, *iqd))}))
|
472
455
|
iq, id = res.x
|
473
456
|
else:
|
474
457
|
iq, id = i0
|
@@ -587,18 +570,19 @@ class PmRelMachine(object):
|
|
587
570
|
log((iq, id, tq))
|
588
571
|
return iq, id, tq
|
589
572
|
|
590
|
-
def iqd_imax_umax(self, i1max, w1, u1max, torque, with_mtpv=True,
|
573
|
+
def iqd_imax_umax(self, i1max, w1, u1max, torque, with_mtpv=True,
|
574
|
+
with_tmech=True, with_mtpa=True):
|
591
575
|
"""return d-q current and shaft torque at stator frequency and max voltage
|
592
576
|
and max current (for motor operation if maxtorque else generator operation)"""
|
593
577
|
if torque > 0:
|
594
|
-
sign
|
578
|
+
sign = -1
|
595
579
|
# -pi/2 --> 0
|
596
580
|
b0, b1 = max(-np.pi/2, self.betarange[0]), 0
|
597
581
|
if max(self.betarange) < b1:
|
598
582
|
raise ValueError(
|
599
583
|
f"invalid betarange for maxtorque>0: {self.betarange}")
|
600
584
|
else:
|
601
|
-
sign=1
|
585
|
+
sign = 1
|
602
586
|
# -pi/2 --> -pi
|
603
587
|
b0, b1 = -np.pi/2, max(-np.pi, self.betarange[0])
|
604
588
|
if min(self.betarange) > b0:
|
@@ -608,6 +592,7 @@ class PmRelMachine(object):
|
|
608
592
|
iq, id, _ = self.mtpa(i1max)
|
609
593
|
else:
|
610
594
|
iq, id = iqd(0, i1max)
|
595
|
+
|
611
596
|
deps = 1e-6
|
612
597
|
kmax = 100
|
613
598
|
|
@@ -622,8 +607,10 @@ class PmRelMachine(object):
|
|
622
607
|
else:
|
623
608
|
iq, id, tq = self.iqd_torque_umax(torque, w1, u1max)
|
624
609
|
if not with_mtpv:
|
610
|
+
logging.debug("not mtpv iq %f id %f tq %f",
|
611
|
+
iq, id, tq)
|
625
612
|
return iq, id, tq
|
626
|
-
beta, i1 = betai1(iq, id)
|
613
|
+
#beta, i1 = betai1(iq, id)
|
627
614
|
else:
|
628
615
|
for k in range(kmax):
|
629
616
|
bx = b0 + (b1-b0)/2
|
@@ -642,9 +629,9 @@ class PmRelMachine(object):
|
|
642
629
|
if abs(du) > 0.1:
|
643
630
|
logger.debug('oops? iqd_imax_umax one more torque reduction')
|
644
631
|
if with_tmech:
|
645
|
-
iq, id = self.iqd_tmech_umax(torque, w1, u1max)
|
632
|
+
iq, id, tq = self.iqd_tmech_umax(torque, w1, u1max)
|
646
633
|
else:
|
647
|
-
iq, id = self.iqd_torque_umax(torque, w1, u1max)
|
634
|
+
iq, id, tq = self.iqd_torque_umax(torque, w1, u1max)
|
648
635
|
if with_mtpv:
|
649
636
|
try:
|
650
637
|
if with_tmech:
|
@@ -656,9 +643,26 @@ class PmRelMachine(object):
|
|
656
643
|
iq, id, tq = self.mtpv(w1, u1max, iqd0=(iq, id),
|
657
644
|
maxtorque=torque>0,
|
658
645
|
i1max=i1max)
|
646
|
+
logging.debug("mtpv iq %f id %f tq %f",
|
647
|
+
iq, id, tq)
|
659
648
|
return iq, id, tq
|
660
649
|
except ValueError as e:
|
661
|
-
|
650
|
+
n = w1/2/np.pi/self.p
|
651
|
+
logger.debug(" i1max %f iq %f id %f", i1max, iq, id)
|
652
|
+
#
|
653
|
+
res = so.minimize(
|
654
|
+
lambda iqd: sign*self.tmech_iqd(*iqd, n),
|
655
|
+
(iq, id),
|
656
|
+
constraints=[{
|
657
|
+
'type': 'eq',
|
658
|
+
'fun': lambda iqd:
|
659
|
+
np.sqrt(2)*u1max - np.linalg.norm(
|
660
|
+
self.uqd(w1, *iqd))}])
|
661
|
+
logger.debug(" n %f i1max %f %f iq %f id %f tq %f",
|
662
|
+
60*n, i1max, np.linalg.norm(res.x)/np.sqrt(2),
|
663
|
+
iq, id, sign*res.fun)
|
664
|
+
if res['success'] and abs(i1max*np.sqrt(2)) >= np.linalg.norm(res.x):
|
665
|
+
return *res.x, sign*res.fun
|
662
666
|
|
663
667
|
if with_tmech:
|
664
668
|
tq = self.tmech_iqd(iq, id, w1/2/np.pi/self.p)
|
@@ -723,6 +727,8 @@ class PmRelMachine(object):
|
|
723
727
|
else:
|
724
728
|
i0 = iqd0
|
725
729
|
n = w1/2/np.pi/self.p
|
730
|
+
logger.debug("w1 %f u1 %f iqd0 %s maxtorque %s %f",
|
731
|
+
w1, u1, iqd0, maxtorque, i1max)
|
726
732
|
constraints=[{'type': 'eq',
|
727
733
|
'fun': lambda iqd:
|
728
734
|
np.sqrt(2)*u1 - la.norm(
|
@@ -734,6 +740,7 @@ class PmRelMachine(object):
|
|
734
740
|
res = so.minimize(lambda iqd: sign*self.tmech_iqd(*iqd, n), i0,
|
735
741
|
method='SLSQP',
|
736
742
|
constraints=constraints)
|
743
|
+
logger.debug("iq %f id %f w1 %f success %s", res.x[0], res.x[1], w1, res['success'])
|
737
744
|
if res['success']:
|
738
745
|
return res.x[0], res.x[1], sign*res.fun
|
739
746
|
#logger.warning("w1=%.1f u1=%.1f maxtorque=%s %s: %s", w1, u1, maxtorque, res.x, res.message)
|
@@ -814,7 +821,7 @@ class PmRelMachine(object):
|
|
814
821
|
if (abs(i1max) >= i1
|
815
822
|
and round(u1max, 1) >= round(np.linalg.norm(
|
816
823
|
self.uqd(w1max, iq, id)/np.sqrt(2)), 1)):
|
817
|
-
return [w1type/2/np.pi/self.p, speedmax]
|
824
|
+
return [float(w1type/2/np.pi/self.p), float(speedmax)]
|
818
825
|
wl, wu = [w1type, min(4*w1type, w1max)]
|
819
826
|
if with_mtpv:
|
820
827
|
kmax = 6
|
@@ -835,6 +842,7 @@ class PmRelMachine(object):
|
|
835
842
|
T, with_mtpa=with_mtpa,
|
836
843
|
with_mtpv=False)[:2]
|
837
844
|
i1 = betai1(iq, id)[1]
|
845
|
+
logger.debug("iq %f id %f i1 %f", iq, id, i1)
|
838
846
|
try:
|
839
847
|
if with_tmech:
|
840
848
|
def voltw1(wx):
|
@@ -851,7 +859,7 @@ class PmRelMachine(object):
|
|
851
859
|
if ier == 1: #in (1, 4, 5):
|
852
860
|
if abs(w[0]) <= wx:
|
853
861
|
self.check_extrapolation = True
|
854
|
-
return [w/2/np.pi/self.p
|
862
|
+
return [float(w/2/np.pi/self.p)
|
855
863
|
for w in (w1type, w[0], w1max)] # ['MTPA', 'MTPV']
|
856
864
|
if w[0] > wu:
|
857
865
|
wl += (wu-wl)/4
|
@@ -873,7 +881,7 @@ class PmRelMachine(object):
|
|
873
881
|
self.check_extrapolation = True
|
874
882
|
w1max = min(w1max, np.floor(self.w1_umax(
|
875
883
|
u1max, *iqd(-np.pi/2, abs(i1max)))))
|
876
|
-
return [w/2/np.pi/self.p for w in (w1type, w1max)] # ['MTPA']
|
884
|
+
return [float(w/2/np.pi/self.p) for w in (w1type, w1max)] # ['MTPA']
|
877
885
|
|
878
886
|
|
879
887
|
def operating_point(self, T, n, u1max, with_mtpa=True):
|
@@ -925,10 +933,10 @@ class PmRelMachine(object):
|
|
925
933
|
plfe1 = self.iqd_plfe1(iq, id, f1)
|
926
934
|
plfe2 = self.iqd_plfe2(iq, id, f1)
|
927
935
|
plmag = self.iqd_plmag(iq, id, f1)
|
928
|
-
plfe = plfe1 + plfe2
|
936
|
+
plfe = plfe1 + plfe2
|
929
937
|
plfric = self.pfric(n)
|
930
938
|
plcu = self.betai1_plcu(i1, 2 * np.pi * f1)
|
931
|
-
pltotal = plfe + plcu + plfric
|
939
|
+
pltotal = plfe + plcu + plfric + plmag
|
932
940
|
p1 = pmech + pltotal
|
933
941
|
if np.abs(pmech) < 1e-12:
|
934
942
|
eta = 0 # power to low for eta calculation
|
@@ -990,8 +998,8 @@ class PmRelMachine(object):
|
|
990
998
|
if kwargs.get('i1max', 0):
|
991
999
|
i1max = kwargs['i1max']
|
992
1000
|
w1, Tf = self.w1_imax_umax(i1max, u1max,
|
993
|
-
|
994
|
-
|
1001
|
+
with_mtpa=with_mtpa,
|
1002
|
+
with_tmech=with_tmech)
|
995
1003
|
if with_mtpa:
|
996
1004
|
iq, id, T = self.mtpa(i1max)
|
997
1005
|
else:
|
@@ -1026,7 +1034,8 @@ class PmRelMachine(object):
|
|
1026
1034
|
iq, id = iqd(0, i1max)
|
1027
1035
|
|
1028
1036
|
if with_tmech:
|
1029
|
-
w1, Tf = self.w1_imax_umax(i1max, u1max,
|
1037
|
+
w1, Tf = self.w1_imax_umax(i1max, u1max,
|
1038
|
+
with_mtpa=with_mtpa,
|
1030
1039
|
with_tmech=with_tmech)
|
1031
1040
|
else:
|
1032
1041
|
iq, id = self.iqd_torque(T)
|
@@ -1100,14 +1109,15 @@ class PmRelMachine(object):
|
|
1100
1109
|
iq, id, tq = self.iqd_imax_umax(
|
1101
1110
|
i1max, w1, u1max,
|
1102
1111
|
tq, with_tmech=with_tmech,
|
1103
|
-
with_mtpv=with_mtpv,
|
1104
1112
|
with_mtpa=with_mtpa)
|
1105
1113
|
else:
|
1106
1114
|
if with_tmech:
|
1107
1115
|
iq, id, tq = self.mtpv_tmech(w1, u1max,
|
1116
|
+
iqd0=(iq, id),
|
1108
1117
|
maxtorque=T > 0)
|
1109
1118
|
else:
|
1110
1119
|
iq, id, tq = self.mtpv(w1, u1max,
|
1120
|
+
iqd0=(iq, id),
|
1111
1121
|
maxtorque=T > 0)
|
1112
1122
|
if (T > 0 and tq > 0) or (T < 0 and tq < 0):
|
1113
1123
|
r['id'].append(id)
|
@@ -1115,8 +1125,8 @@ class PmRelMachine(object):
|
|
1115
1125
|
r['n'].append(nn)
|
1116
1126
|
r['T'].append(tq)
|
1117
1127
|
else:
|
1118
|
-
logger.
|
1119
|
-
|
1128
|
+
logger.debug("fieldweakening: n %g T %g tq %g i1max %g w1 %g u1 %g",
|
1129
|
+
nn*60, T, tq, i1max, w1, u1max)
|
1120
1130
|
except ValueError as e:
|
1121
1131
|
nmax = r['n'][-1]
|
1122
1132
|
logger.warning("%s: adjusted nmax %f T %f", e, nmax, r['T'][-1])
|
@@ -1149,11 +1159,15 @@ class PmRelMachine(object):
|
|
1149
1159
|
f1 = np.array(r['n'])*self.p
|
1150
1160
|
plfe1 = self.kpfe*self.iqd_plfe1(np.array(r['iq']), np.array(r['id']), f1)
|
1151
1161
|
plfe2 = self.kpfe*self.iqd_plfe2(np.array(r['iq']), np.array(r['id']), f1)
|
1162
|
+
if hasattr(self, 'kpfe_s'):
|
1163
|
+
plfe1 = self.kpfe_s*self.iqd_plfe1(np.array(r['iq']), np.array(r['id']), f1)
|
1164
|
+
if hasattr(self, 'kpfe_r'):
|
1165
|
+
plfe2 = self.kpfe_r*self.iqd_plfe2(np.array(r['iq']), np.array(r['id']), f1)
|
1152
1166
|
plmag = self.kpmag*self.iqd_plmag(np.array(r['iq']), np.array(r['id']), f1)
|
1153
|
-
plfe = plfe1 + plfe2
|
1167
|
+
plfe = plfe1 + plfe2
|
1154
1168
|
plcu = self.betai1_plcu(np.array(r['i1']), 2*np.pi*f1)
|
1155
1169
|
plfw = self.pfric(2*np.pi*f1)
|
1156
|
-
pltotal = plfe + plcu + plfw
|
1170
|
+
pltotal = plfe + plcu + plfw + plmag
|
1157
1171
|
r['pmech'] = pmech.tolist()
|
1158
1172
|
r['plfe'] = plfe.tolist()
|
1159
1173
|
r['plcu'] = plcu.tolist()
|
femagtools/machine/sm.py
CHANGED
@@ -22,7 +22,7 @@ eecdefaults = {
|
|
22
22
|
'tcu2': 20,
|
23
23
|
'rotor_mass': 0,
|
24
24
|
'kfric_b': 1,
|
25
|
-
'kpfe': 1 # iron loss factor
|
25
|
+
'kpfe': 1 # common iron loss factor
|
26
26
|
}
|
27
27
|
|
28
28
|
logger = logging.getLogger('sm')
|
@@ -76,7 +76,13 @@ def parident(workdir, engine, machine,
|
|
76
76
|
raise ValueError('i1_max missing')
|
77
77
|
i1_max = kwargs['i1_max']
|
78
78
|
|
79
|
-
|
79
|
+
|
80
|
+
if "magnetFsl" in machine["magnet"]:
|
81
|
+
rotorkey = "magnet"
|
82
|
+
else:
|
83
|
+
rotorkey = "rotor"
|
84
|
+
|
85
|
+
ifnom = machine[rotorkey]['ifnom']
|
80
86
|
exc_logspace = True
|
81
87
|
ifmin, ifmax = ifnom/4, 1.4*ifnom
|
82
88
|
if exc_logspace:
|
@@ -126,7 +132,7 @@ def parident(workdir, engine, machine,
|
|
126
132
|
period_frac=kwargs.get('period_frac', 6),
|
127
133
|
speed=kwargs.get('speed', 50))
|
128
134
|
|
129
|
-
if kwargs.get("feloss", 0):
|
135
|
+
if kwargs.get("feloss", 0):
|
130
136
|
simulation["feloss"] = kwargs["feloss"]
|
131
137
|
machine["calc_fe_loss"] = loss_models[kwargs["feloss"].lower()]
|
132
138
|
###self.cleanup() # remove previously created files in workdir
|
@@ -197,7 +203,7 @@ def parident(workdir, engine, machine,
|
|
197
203
|
if simulation['calculationMode'] == 'ld_lq_fast':
|
198
204
|
dqpars = dict(m=3, p=b['machine']['p'],
|
199
205
|
r1=float(r1),
|
200
|
-
r2=machine[
|
206
|
+
r2=machine[rotorkey].get('resistance', 1),
|
201
207
|
rotor_mass=rotor_mass, kfric_b=1,
|
202
208
|
ldq=[dict(
|
203
209
|
ex_current=b['machine']['ex_current'],
|
@@ -214,7 +220,7 @@ def parident(workdir, engine, machine,
|
|
214
220
|
else:
|
215
221
|
dqpars = dict(m=3, p=b['machine']['p'],
|
216
222
|
r1=r1,
|
217
|
-
r2=machine[
|
223
|
+
r2=machine[rotorkey].get('resistance', 1),
|
218
224
|
rotor_mass=rotor_mass, kfric_b=1,
|
219
225
|
psidq=[dict(
|
220
226
|
ex_current=b['machine']['ex_current'],
|
@@ -387,8 +393,13 @@ class SynchronousMachine(object):
|
|
387
393
|
and friction windage losses"""
|
388
394
|
if n > 1e-3:
|
389
395
|
f1 = self.p*n
|
390
|
-
|
391
|
-
|
396
|
+
plfe1 = self.kpfe * self.iqd_plfe1(iq, id, iex, f1)
|
397
|
+
plfe2 = self.kpfe * self.iqd_plfe2(iq, id, iex, f1)
|
398
|
+
if hasattr(self, 'kpfe_s'):
|
399
|
+
plfe1 = self.kpfe_s * self.iqd_plfe1(iq, id, iex, f1)
|
400
|
+
if hasattr(self, 'kpfe_r'):
|
401
|
+
plfe2 = self.kpfe_r * self.iqd_plfe2(iq, id, iex, f1)
|
402
|
+
plfe = plfe1 + plfe2
|
392
403
|
return (plfe + self.pfric(n))/(2*np.pi*n)
|
393
404
|
return 0
|
394
405
|
|
@@ -413,8 +424,8 @@ class SynchronousMachine(object):
|
|
413
424
|
def uqd(self, w1, iq, id, iex):
|
414
425
|
"""return uq, ud of frequency w1 and d-q current"""
|
415
426
|
psid, psiq = self.psi(iq, id, iex)
|
416
|
-
r1 = self.rstat(w1)
|
417
|
-
return r1*iq + w1*psid, r1*id - w1*psiq
|
427
|
+
# r1 = self.rstat(w1)
|
428
|
+
return self.r1*iq + w1*(self.ls*id + psid), self.r1*id - w1*(self.ls*iq + psiq)
|
418
429
|
|
419
430
|
def plcu1(self, iqde, w1):
|
420
431
|
r1 = self.rstat(w1)
|
@@ -458,9 +469,9 @@ class SynchronousMachine(object):
|
|
458
469
|
#options={'disp': disp, 'maxiter': maxiter})
|
459
470
|
if res['success']:
|
460
471
|
return res.x
|
461
|
-
else:
|
472
|
+
else:
|
462
473
|
res = so.minimize(
|
463
|
-
lambda cur: (self.tmech_iqd(*cur, n) - torque)**2, res.x, method='SLSQP',
|
474
|
+
lambda cur: (self.tmech_iqd(*cur, n) - torque)**2, res.x, method='SLSQP',
|
464
475
|
bounds=self.bounds,
|
465
476
|
)
|
466
477
|
if res['success']:
|
@@ -548,10 +559,10 @@ class SynchronousMachine(object):
|
|
548
559
|
log(res.x)
|
549
560
|
if res["success"]:
|
550
561
|
return *res.x, self.tmech_iqd(*res.x, n)
|
551
|
-
else:
|
562
|
+
else:
|
552
563
|
# didn't converge, fullfill voltage and torque demand
|
553
564
|
res = so.minimize(
|
554
|
-
lambda cur: (self.tmech_iqd(*cur, n) - torque)**2, io, method='SLSQP',
|
565
|
+
lambda cur: (self.tmech_iqd(*cur, n) - torque)**2, io, method='SLSQP',
|
555
566
|
bounds=self.bounds,
|
556
567
|
constraints=[
|
557
568
|
{'type': 'eq',
|
@@ -562,8 +573,8 @@ class SynchronousMachine(object):
|
|
562
573
|
return *res.x, self.tmech_iqd(*res.x, n)
|
563
574
|
else:
|
564
575
|
res = so.minimize(
|
565
|
-
lambda cur: (self.tmech_iqd(*cur, n) - torque)**2 +
|
566
|
-
(np.linalg.norm(self.uqd(w1, *cur)) - u1max*np.sqrt(2))**2, io, method='SLSQP',
|
576
|
+
lambda cur: (self.tmech_iqd(*cur, n) - torque)**2 +
|
577
|
+
(np.linalg.norm(self.uqd(w1, *cur)) - u1max*np.sqrt(2))**2, io, method='SLSQP',
|
567
578
|
bounds=self.bounds,
|
568
579
|
)
|
569
580
|
return *res.x, self.tmech_iqd(*res.x, n)
|
@@ -680,7 +691,7 @@ class SynchronousMachine(object):
|
|
680
691
|
Tf = T
|
681
692
|
w1type = self.w1_umax(u1max, iq, id, iex)
|
682
693
|
logger.debug("w1type %f", w1type)
|
683
|
-
wmType = w1type/self.p
|
694
|
+
wmType = float(w1type/self.p)
|
684
695
|
pmax = Tf*wmType
|
685
696
|
|
686
697
|
def tload(wm):
|
@@ -723,7 +734,7 @@ class SynchronousMachine(object):
|
|
723
734
|
iq, id, iex, tqx = self.iqd_torque_umax(
|
724
735
|
tq, w1, u1max)
|
725
736
|
tqx -= self.tfric
|
726
|
-
else:
|
737
|
+
else:
|
727
738
|
tqx = Tf
|
728
739
|
|
729
740
|
uq, ud = self.uqd(w1, iq, id, iex)
|
@@ -857,9 +868,9 @@ class SynchronousMachinePsidq(SynchronousMachine):
|
|
857
868
|
'rotor_hyst', 'rotor_eddy')}
|
858
869
|
|
859
870
|
def set_max_iex(self, iexc):
|
860
|
-
self.bounds[-1] = (self.bounds[-1][0], iexc)
|
871
|
+
self.bounds[-1] = (self.bounds[-1][0], iexc)
|
861
872
|
self.exc_max = iexc
|
862
|
-
|
873
|
+
|
863
874
|
def psi(self, iq, id, iex):
|
864
875
|
"""return psid, psiq of currents iq, id"""
|
865
876
|
try:
|
@@ -980,9 +991,9 @@ class SynchronousMachineLdq(SynchronousMachine):
|
|
980
991
|
'styoke_eddy', 'stteeth_eddy',
|
981
992
|
'rotor_hyst', 'rotor_eddy')}
|
982
993
|
pass
|
983
|
-
|
994
|
+
|
984
995
|
def set_max_iex(self, iexc):
|
985
|
-
self.bounds[-1] = (self.bounds[-1][0], iexc)
|
996
|
+
self.bounds[-1] = (self.bounds[-1][0], iexc)
|
986
997
|
self.exc_max = iexc
|
987
998
|
|
988
999
|
def psi(self, iq, id, iex):
|
femagtools/mcv.py
CHANGED
@@ -1173,7 +1173,10 @@ class MagnetizingCurve(object):
|
|
1173
1173
|
mcv = self.find_by_name(name)
|
1174
1174
|
if not mcv:
|
1175
1175
|
bname = name
|
1176
|
-
filename =
|
1176
|
+
filename = name if pathlib.Path(name).suffix.upper() == ext \
|
1177
|
+
else ''.join((name, ext))
|
1178
|
+
if name == 'dummy':
|
1179
|
+
return filename
|
1177
1180
|
# check fillfac and readmcv
|
1178
1181
|
if not fillfac or fillfac == 1.0:
|
1179
1182
|
try:
|
femagtools/plot/bch.py
CHANGED
@@ -515,10 +515,12 @@ def cogging(bch, title=''):
|
|
515
515
|
fig.subplots_adjust(top=0.92)
|
516
516
|
|
517
517
|
|
518
|
-
def demagnetization(demag, ax=0):
|
518
|
+
def demagnetization(demag, title='', ax=0):
|
519
519
|
"""plot rel. remanence vs. current"""
|
520
520
|
if ax == 0:
|
521
521
|
ax = plt.gca()
|
522
|
+
if title:
|
523
|
+
ax.set_title(title)
|
522
524
|
scale = 1
|
523
525
|
unit = 'A'
|
524
526
|
if np.max(demag['i1']) > 25e3:
|
femagtools/plot/char.py
CHANGED
@@ -304,23 +304,12 @@ def _plot_contour(speed, torque, z, ax, title='', levels=[],
|
|
304
304
|
y, yscale = _normalize10(y, **kwargs)
|
305
305
|
|
306
306
|
if not levels:
|
307
|
+
levels = [0.5, 0.7, 0.8]
|
307
308
|
if max(z) <= 1:
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
levels = np.round(levels, 2)
|
313
|
-
levels = list(levels)
|
314
|
-
|
315
|
-
else:
|
316
|
-
#levels = [0.25, 0.5, 0.75, 0.8, 0.84,
|
317
|
-
#0.88, 0.9, 0.92, 0.94, 0.96]
|
318
|
-
levels = np.linspace(min(z),max(z),9)
|
319
|
-
levels = np.round(levels, 2)
|
320
|
-
levels = list(levels)
|
321
|
-
|
322
|
-
if max(z) > levels[-1]:
|
323
|
-
levels.append(np.ceil(max(z)*100)/100)
|
309
|
+
a = np.array(z)
|
310
|
+
zmax = np.ceil(100*np.max(z))/100
|
311
|
+
levels += [zmax - x for x in
|
312
|
+
[0.07, 0.05, 0.03, 0.02, 0.01, 0]]
|
324
313
|
else:
|
325
314
|
levels = 14
|
326
315
|
#
|