femagtools 1.8.3__py3-none-any.whl → 1.8.5__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 +10 -6
- femagtools/dxfsl/area.py +4 -1
- femagtools/dxfsl/conv.py +49 -17
- femagtools/dxfsl/converter.py +239 -80
- femagtools/dxfsl/fslrenderer.py +18 -22
- femagtools/dxfsl/functions.py +24 -2
- femagtools/dxfsl/geom.py +100 -23
- femagtools/dxfsl/machine.py +44 -7
- femagtools/dxfsl/shape.py +4 -0
- femagtools/dxfsl/symmetry.py +78 -25
- femagtools/fsl.py +0 -1
- femagtools/machine/afpm.py +277 -2
- femagtools/machine/effloss.py +2 -2
- femagtools/machine/im.py +6 -8
- femagtools/machine/sm.py +2 -2
- femagtools/machine/utils.py +2 -1
- femagtools/mcv.py +10 -11
- femagtools/plot/char.py +19 -8
- femagtools/templates/mesh-airgap.mako +6 -0
- femagtools/utils.py +1 -1
- femagtools/windings.py +11 -4
- femagtools/zmq.py +0 -1
- {femagtools-1.8.3.dist-info → femagtools-1.8.5.dist-info}/METADATA +1 -1
- {femagtools-1.8.3.dist-info → femagtools-1.8.5.dist-info}/RECORD +30 -30
- tests/test_parident.py +2 -1
- {femagtools-1.8.3.dist-info → femagtools-1.8.5.dist-info}/LICENSE +0 -0
- {femagtools-1.8.3.dist-info → femagtools-1.8.5.dist-info}/WHEEL +0 -0
- {femagtools-1.8.3.dist-info → femagtools-1.8.5.dist-info}/entry_points.txt +0 -0
- {femagtools-1.8.3.dist-info → femagtools-1.8.5.dist-info}/top_level.txt +0 -0
femagtools/machine/afpm.py
CHANGED
@@ -11,9 +11,10 @@ from .. import model
|
|
11
11
|
from .. import utils
|
12
12
|
from .. import windings
|
13
13
|
from .. import femag
|
14
|
-
from scipy.interpolate import
|
14
|
+
from scipy.interpolate import make_interp_spline, RegularGridInterpolator, RectBivariateSpline
|
15
15
|
from scipy.integrate import quad
|
16
16
|
import copy
|
17
|
+
from matplotlib.colors import to_rgb
|
17
18
|
|
18
19
|
logger = logging.getLogger(__name__)
|
19
20
|
|
@@ -58,7 +59,7 @@ def _integrate(radius, pos, val):
|
|
58
59
|
|
59
60
|
|
60
61
|
def _integrate1d(radius, val):
|
61
|
-
interp =
|
62
|
+
interp = make_interp_spline(radius, val, k=1)
|
62
63
|
def func(x):
|
63
64
|
return interp((x))
|
64
65
|
return quad(func, radius[0], radius[-1])[0]
|
@@ -598,6 +599,280 @@ def _get_copper_losses(scale_factor, bch):
|
|
598
599
|
return 0 # noload calc has no winding losses
|
599
600
|
|
600
601
|
|
602
|
+
def _set_plot_attributes(ax):
|
603
|
+
ax.set_aspect('equal')
|
604
|
+
for loc, spine in ax.spines.items():
|
605
|
+
spine.set_color('none') # don't draw spine
|
606
|
+
ax.yaxis.set_ticks([])
|
607
|
+
ax.xaxis.set_ticks([])
|
608
|
+
|
609
|
+
|
610
|
+
def _get_colors(colors, delta):
|
611
|
+
if delta == 0.0:
|
612
|
+
return colors
|
613
|
+
new_colors = []
|
614
|
+
for col in colors:
|
615
|
+
rgb = to_rgb(col)
|
616
|
+
r, g, b = rgb
|
617
|
+
col = (max(0.0, min(r+delta, 1.0)),
|
618
|
+
max(0.0, min(g+delta, 1.0)),
|
619
|
+
max(0.0, min(b+delta, 1.0)))
|
620
|
+
new_colors.append(col)
|
621
|
+
return new_colors
|
622
|
+
|
623
|
+
|
624
|
+
def _draw_vertical_magnets(ax,
|
625
|
+
poles,
|
626
|
+
xr, yr,
|
627
|
+
Rr,
|
628
|
+
xoff, yoff,
|
629
|
+
delta=0.0):
|
630
|
+
color = ['green', 'red']
|
631
|
+
color = _get_colors(color, delta)
|
632
|
+
for i in range(poles):
|
633
|
+
ax.fill(xr+xoff, yr+yoff,
|
634
|
+
facecolor=color[i%2], edgecolor=color[i%2])
|
635
|
+
xr, yr = np.dot(Rr, [xr, yr])
|
636
|
+
return
|
637
|
+
|
638
|
+
|
639
|
+
def _draw_vertical_slots(ax,
|
640
|
+
Q,
|
641
|
+
r,
|
642
|
+
alpha,
|
643
|
+
xoff, yoff,
|
644
|
+
delta=0.0):
|
645
|
+
color = ['skyblue', 'blue']
|
646
|
+
color = _get_colors(color, delta)
|
647
|
+
taus = 2*np.pi/Q
|
648
|
+
for n in range(Q):
|
649
|
+
beta = np.array([[n*taus+alpha[0], (n+1)*taus-alpha[0]],
|
650
|
+
[(n+1)*taus-alpha[1], n*taus+alpha[1]]])
|
651
|
+
ax.fill(np.hstack((r * np.cos(beta[0, 0]),
|
652
|
+
(r[::-1] * np.cos(beta[0, 1]))))+xoff,
|
653
|
+
np.hstack((r * np.sin(beta[0, 0]),
|
654
|
+
(r[::-1] * np.sin(beta[0, 1]))))+yoff,
|
655
|
+
facecolor=color[0], edgecolor=color[0])
|
656
|
+
|
657
|
+
|
658
|
+
def vertical_plot(machine, ax):
|
659
|
+
"""plots afpm stator and rotor (vertical section)
|
660
|
+
Args:
|
661
|
+
dy1, dy1: float outer, inner diameter
|
662
|
+
rel_magn_width: float rel magnet width 0..1
|
663
|
+
Q: number of stator slots
|
664
|
+
poles: number of poles
|
665
|
+
slot_width: width of stator slot
|
666
|
+
"""
|
667
|
+
logger.debug("begin of vertical_plot()")
|
668
|
+
|
669
|
+
model_type = machine['afmtype'][0:4]
|
670
|
+
dy1 = machine['outer_diam']*1e3
|
671
|
+
dy2 = machine['inner_diam']*1e3
|
672
|
+
rel_magn_width = machine['magnet']['afm_rotor']['rel_magn_width']
|
673
|
+
Q = machine['stator']['num_slots']
|
674
|
+
slot_width = machine['stator']['afm_stator']['slot_width']*1e3
|
675
|
+
poles = machine['poles']
|
676
|
+
|
677
|
+
# prepare Magnets
|
678
|
+
theta = np.linspace(np.pi/poles*(1-rel_magn_width),
|
679
|
+
np.pi/poles*(1+rel_magn_width),
|
680
|
+
10)
|
681
|
+
xr = np.concatenate((dy1/2 * np.cos(theta), dy2/2 * np.cos(theta[::-1])))
|
682
|
+
yr = np.concatenate((dy1/2 * np.sin(theta), dy2/2 * np.sin(theta[::-1])))
|
683
|
+
rtheta = 2*np.pi/poles
|
684
|
+
Rr = np.array([
|
685
|
+
[np.cos(rtheta), -np.sin(rtheta)],
|
686
|
+
[np.sin(rtheta), np.cos(rtheta)]
|
687
|
+
])
|
688
|
+
|
689
|
+
# prepare Slots
|
690
|
+
taus = 2*np.pi/Q
|
691
|
+
r = np.array([dy2/2, dy1/2])
|
692
|
+
alpha = np.arctan2(slot_width/2, r)
|
693
|
+
|
694
|
+
yoff = 0.0
|
695
|
+
xoff = 0.0
|
696
|
+
y_shift = -2
|
697
|
+
x_shift = dy1-dy2
|
698
|
+
ma_delta = 0.0 # color
|
699
|
+
sl_delta = 0.0 # color
|
700
|
+
|
701
|
+
# Draw
|
702
|
+
if model_type in ("S1R2"): # 2 rotor
|
703
|
+
_draw_vertical_magnets(ax, poles, xr, yr, Rr, xoff, yoff, delta=-0.1)
|
704
|
+
yoff += y_shift
|
705
|
+
xoff += x_shift
|
706
|
+
|
707
|
+
if model_type in ("S2R1"): # 2 stator
|
708
|
+
sl_delta = -0.1
|
709
|
+
|
710
|
+
_draw_vertical_slots(ax, Q, r, alpha, xoff, yoff, delta=sl_delta)
|
711
|
+
yoff += y_shift
|
712
|
+
xoff += x_shift
|
713
|
+
|
714
|
+
if model_type in ("S1R2"): # 2 rotor
|
715
|
+
ma_delta = 0.1
|
716
|
+
|
717
|
+
_draw_vertical_magnets(ax, poles, xr, yr, Rr, xoff, yoff, delta=ma_delta)
|
718
|
+
yoff += y_shift
|
719
|
+
xoff += x_shift
|
720
|
+
|
721
|
+
if model_type in ("S2R1"): # 2 stator
|
722
|
+
sl_delta = 0.0
|
723
|
+
_draw_vertical_slots(ax, Q, r, alpha, xoff, yoff, delta=sl_delta)
|
724
|
+
|
725
|
+
_set_plot_attributes(ax)
|
726
|
+
logger.debug("end of vertical_plot()")
|
727
|
+
|
728
|
+
|
729
|
+
IRON_NO = 0
|
730
|
+
IRON_UP = 1
|
731
|
+
IRON_DOWN = 2
|
732
|
+
|
733
|
+
def _draw_horizontal_magnets(ax,
|
734
|
+
poles,
|
735
|
+
magn_height,
|
736
|
+
magn_width,
|
737
|
+
yoke_height,
|
738
|
+
Q,
|
739
|
+
g,
|
740
|
+
taus,
|
741
|
+
dy2,
|
742
|
+
yoff=0.0,
|
743
|
+
iron=IRON_NO
|
744
|
+
):
|
745
|
+
color = ['green', 'red']
|
746
|
+
xy = (0, Q//g*taus, Q//g*taus, 0)
|
747
|
+
|
748
|
+
if iron == IRON_UP:
|
749
|
+
yy = (yoff-yoke_height,
|
750
|
+
yoff-yoke_height,
|
751
|
+
yoff,
|
752
|
+
yoff)
|
753
|
+
yoff -= yoke_height
|
754
|
+
ax.fill(xy, yy, color='skyblue')
|
755
|
+
|
756
|
+
taum = dy2*np.pi/poles
|
757
|
+
ym = np.array([yoff-magn_height,
|
758
|
+
yoff-magn_height,
|
759
|
+
yoff,
|
760
|
+
yoff])
|
761
|
+
yoff -= magn_height
|
762
|
+
|
763
|
+
for n in range(poles//g):
|
764
|
+
xl = taum*n + taum*(1 - magn_width)
|
765
|
+
xr = taum*(n + 1) - taum*(1 - magn_width)
|
766
|
+
xm = (xl, xr, xr, xl)
|
767
|
+
ax.fill(xm, ym, color=color[n%2])
|
768
|
+
|
769
|
+
if iron == IRON_DOWN:
|
770
|
+
yy = (yoff-yoke_height,
|
771
|
+
yoff-yoke_height,
|
772
|
+
yoff,
|
773
|
+
yoff)
|
774
|
+
yoff -= yoke_height
|
775
|
+
ax.fill(xy, yy, color='skyblue')
|
776
|
+
return yoff
|
777
|
+
|
778
|
+
|
779
|
+
TOOTH_UP = 0
|
780
|
+
TOOTH_DOWN = 1
|
781
|
+
TOOTH_ONLY = 2
|
782
|
+
|
783
|
+
|
784
|
+
def _draw_horizontal_slots(ax,
|
785
|
+
slot_height, slot_width, yoke_height,
|
786
|
+
Q, g, taus,
|
787
|
+
yoff=0.0,
|
788
|
+
tooth=TOOTH_DOWN):
|
789
|
+
if not tooth == TOOTH_ONLY:
|
790
|
+
xx = (0, Q//g*taus, Q//g*taus, 0)
|
791
|
+
if tooth == TOOTH_DOWN:
|
792
|
+
yy = (yoff-yoke_height,
|
793
|
+
yoff-yoke_height,
|
794
|
+
yoff,
|
795
|
+
yoff)
|
796
|
+
else:
|
797
|
+
yy = (yoff-slot_height,
|
798
|
+
yoff-slot_height,
|
799
|
+
yoff-slot_height-yoke_height,
|
800
|
+
yoff-slot_height-yoke_height)
|
801
|
+
ax.fill(xx, yy, color='skyblue')
|
802
|
+
|
803
|
+
yt = (yoff-slot_height-yoke_height,
|
804
|
+
yoff-slot_height-yoke_height,
|
805
|
+
yoff, yoff)
|
806
|
+
for n in range(Q//g):
|
807
|
+
xt = np.array((n*taus, n*taus+(taus-slot_width)/2,
|
808
|
+
n*taus+(taus-slot_width)/2, n*taus))
|
809
|
+
ax.fill(xt, yt, color='skyblue')
|
810
|
+
xt += slot_width + (taus-slot_width)/2
|
811
|
+
ax.fill(xt, yt, color='skyblue')
|
812
|
+
return yoff - slot_height - yoke_height
|
813
|
+
|
814
|
+
|
815
|
+
def horizontal_plot(machine, ax):
|
816
|
+
logger.debug("begin of horizontal_plot()")
|
817
|
+
|
818
|
+
model_type = machine['afmtype'][0:4]
|
819
|
+
dy1 = machine['outer_diam']*1e3
|
820
|
+
dy2 = machine['inner_diam']*1e3
|
821
|
+
rel_magn_width = machine['magnet']['afm_rotor']['rel_magn_width']
|
822
|
+
magn_height = machine['magnet']['afm_rotor']['magn_height']*1e3
|
823
|
+
magn_yoke_height = machine['magnet']['afm_rotor']['yoke_height']*1e3
|
824
|
+
|
825
|
+
Q = machine['stator']['num_slots']
|
826
|
+
slot_width = machine['stator']['afm_stator']['slot_width']*1e3
|
827
|
+
poles = machine['poles']
|
828
|
+
m = 3
|
829
|
+
slot_height = machine['stator']['afm_stator']['slot_height']*1e3
|
830
|
+
if model_type in ('S2R1', 'S2R1_all'):
|
831
|
+
slot_height /= 2
|
832
|
+
yoke_height = machine['stator']['afm_stator']['yoke_height']*1e3
|
833
|
+
ag = machine['airgap']*1e3
|
834
|
+
|
835
|
+
g = np.gcd(Q, m*poles)//m
|
836
|
+
taus = dy2*np.pi/Q
|
837
|
+
|
838
|
+
yoff = 0.0
|
839
|
+
if model_type in ('S1R2', 'S1R2_all'): # 2 rotor
|
840
|
+
yoff = _draw_horizontal_magnets(ax, poles,
|
841
|
+
magn_height, rel_magn_width,
|
842
|
+
magn_yoke_height,
|
843
|
+
Q, g, taus, dy2,
|
844
|
+
yoff=yoff,
|
845
|
+
iron=IRON_UP)
|
846
|
+
yoff -= ag
|
847
|
+
|
848
|
+
tooth = TOOTH_ONLY if model_type in ('S1R2', 'S1R2_all') else TOOTH_DOWN
|
849
|
+
yoff = _draw_horizontal_slots(ax,
|
850
|
+
slot_height, slot_width, yoke_height,
|
851
|
+
Q, g, taus,
|
852
|
+
yoff=yoff,
|
853
|
+
tooth=tooth)
|
854
|
+
yoff -= ag
|
855
|
+
|
856
|
+
iron = IRON_DOWN if model_type in ('S1R1', 'S1R2', 'S1R2_all') else IRON_NO
|
857
|
+
yoff = _draw_horizontal_magnets(ax, poles,
|
858
|
+
magn_height, rel_magn_width,
|
859
|
+
magn_yoke_height,
|
860
|
+
Q, g, taus, dy2,
|
861
|
+
yoff=yoff,
|
862
|
+
iron=iron)
|
863
|
+
yoff -= ag
|
864
|
+
|
865
|
+
if model_type in ('S2R1', 'S2R1_all'): # 2 rotor
|
866
|
+
yoff = _draw_horizontal_slots(ax,
|
867
|
+
slot_height, slot_width, yoke_height,
|
868
|
+
Q, g, taus,
|
869
|
+
yoff=yoff,
|
870
|
+
tooth=TOOTH_UP)
|
871
|
+
|
872
|
+
_set_plot_attributes(ax)
|
873
|
+
logger.debug("end of horizontal_plot()")
|
874
|
+
|
875
|
+
|
601
876
|
class AFPM:
|
602
877
|
"""Axial Flux PM
|
603
878
|
Arguments:
|
femagtools/machine/effloss.py
CHANGED
@@ -166,9 +166,9 @@ def _generate_mesh(n, T, nb, Tb, npoints):
|
|
166
166
|
nmax = max(n)
|
167
167
|
tmin, tmax = 0, max(T)
|
168
168
|
tnum = npoints[1]
|
169
|
-
tip = ip.
|
169
|
+
tip = ip.make_interp_spline(n, T, k=1)
|
170
170
|
if nb and Tb:
|
171
|
-
tbip = ip.
|
171
|
+
tbip = ip.make_interp_spline(nb, Tb, k=1)
|
172
172
|
else:
|
173
173
|
def tbip(x): return 0
|
174
174
|
|
femagtools/machine/im.py
CHANGED
@@ -35,6 +35,9 @@ def log_interp1d(x, y, kind='cubic'):
|
|
35
35
|
logy = np.log10(yy)
|
36
36
|
lin_interp = ip.interp1d(logx, logy, kind=kind, fill_value="extrapolate")
|
37
37
|
def log_interp(zz): return np.power(10.0, lin_interp(np.log10(zz)))
|
38
|
+
# TODO check replace interp1d
|
39
|
+
#lin_interp = ip.make_interp_spline(logx, logy, bc_type='not-a-knot')
|
40
|
+
#def log_interp(zz): return np.power(10.0, lin_interp(np.log10(zz), nu=1))
|
38
41
|
return log_interp
|
39
42
|
|
40
43
|
|
@@ -792,15 +795,10 @@ def parident(workdir, engine, f1, u1, wdgcon,
|
|
792
795
|
tend = time.time()
|
793
796
|
logger.info("Elapsed time %d s Status %s",
|
794
797
|
(tend-tstart), status)
|
798
|
+
if any([x != 'C' for x in status]):
|
799
|
+
raise ValueError("AC simulation failed")
|
795
800
|
# collect results
|
796
|
-
results = []
|
797
|
-
errors = []
|
798
|
-
for t in job.tasks:
|
799
|
-
if t.status == 'C':
|
800
|
-
results.append(t.get_results())
|
801
|
-
else:
|
802
|
-
logger.warning("Status %s", t.status)
|
803
|
-
results.append({})
|
801
|
+
results = [t.get_results() for t in job.tasks]
|
804
802
|
|
805
803
|
i1_0 = results[0]['i1_0'].tolist()
|
806
804
|
psi1_0 = results[0]['psi1_0'].tolist()
|
femagtools/machine/sm.py
CHANGED
@@ -187,7 +187,7 @@ def parident(workdir, engine, machine,
|
|
187
187
|
|
188
188
|
if simulation['calculationMode'] == 'ld_lq_fast':
|
189
189
|
dqpars = dict(m=3, p=b['machine']['p'],
|
190
|
-
r1=r1,
|
190
|
+
r1=float(r1),
|
191
191
|
r2=machine['rotor'].get('resistance', 1),
|
192
192
|
rotor_mass=rotor_mass, kfric_b=1,
|
193
193
|
ldq=[dict(
|
@@ -434,7 +434,7 @@ class SynchronousMachine(object):
|
|
434
434
|
def iqd_tmech(self, torque, n, disp=False, maxiter=500):
|
435
435
|
"""return currents for shaft torque with minimal losses"""
|
436
436
|
if torque > 0:
|
437
|
-
startvals = self.bounds[0][1], 0, self.bounds[-1][1]
|
437
|
+
startvals = self.bounds[0][1]/2, 0, self.bounds[-1][1]
|
438
438
|
else:
|
439
439
|
startvals = -self.bounds[0][1]/2, 0, self.bounds[-1][1]
|
440
440
|
|
femagtools/machine/utils.py
CHANGED
@@ -366,7 +366,8 @@ def dqparident(workdir, engine, temp, machine,
|
|
366
366
|
num_beta_steps: number of current steps (default 7 per quadrant)
|
367
367
|
speed: rotor speed in 1/s (default 160/p)
|
368
368
|
i1_max: maximum current in A rms (default approx 3*i1nom)
|
369
|
-
period_frac: fraction of rotating angle (default 6)
|
369
|
+
period_frac: (int) fraction of rotating angle (default 6)
|
370
|
+
dqtype: (str) type of identification: 'ldq' (default), 'psidq'
|
370
371
|
cmd: femag executable
|
371
372
|
"""
|
372
373
|
import pathlib
|
femagtools/mcv.py
CHANGED
@@ -12,7 +12,7 @@ import pathlib
|
|
12
12
|
import struct
|
13
13
|
import math
|
14
14
|
import numpy as np
|
15
|
-
|
15
|
+
from scipy.interpolate import make_interp_spline
|
16
16
|
from six import string_types
|
17
17
|
import femagtools.losscoeffs as lc
|
18
18
|
|
@@ -99,7 +99,7 @@ def norm_pfe(B, pfe):
|
|
99
99
|
b = list(b)
|
100
100
|
b[-1] = Bv[n]
|
101
101
|
n += 1
|
102
|
-
pfunc =
|
102
|
+
pfunc = make_interp_spline(b, pfe[i])
|
103
103
|
m.append([float(pfunc(x))
|
104
104
|
for x in Bv[:n]] + [None]*(len(Bv)-n))
|
105
105
|
return Bv.tolist(), m
|
@@ -168,8 +168,7 @@ def recalc_bsin(curve):
|
|
168
168
|
if bi[0] > 0:
|
169
169
|
bi.insert(0, 0)
|
170
170
|
hi.insert(0, 0)
|
171
|
-
bh =
|
172
|
-
kind='cubic', assume_sorted=True)
|
171
|
+
bh = make_interp_spline(bi, hi)
|
173
172
|
for bx in c['bi'][2:]:
|
174
173
|
bt = bx*np.sin(2*np.pi/4/ndel*x)
|
175
174
|
nue = np.sum(bh(bt)/bt)/ndel
|
@@ -196,8 +195,7 @@ def recalc_hsin(curve):
|
|
196
195
|
if hi[0] > 0:
|
197
196
|
hi.insert(0, 0)
|
198
197
|
bi.insert(0, 0)
|
199
|
-
hb =
|
200
|
-
kind='cubic', assume_sorted=True)
|
198
|
+
hb = make_interp_spline(hi, bi)
|
201
199
|
for hx in c['hi'][2:]:
|
202
200
|
ht = hx*np.sin(2*np.pi/4/ndel*x)
|
203
201
|
bt = hb(ht)*np.sin(2*np.pi/4/ndel*x)
|
@@ -243,11 +241,12 @@ def approx(db2, curve, ctype):
|
|
243
241
|
if ctype in (DEMCRV, MAG_AC_CRV):
|
244
242
|
dhdbn = 0
|
245
243
|
k = len(bi2)-1
|
246
|
-
if
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
244
|
+
if k < len(curve['bi']):
|
245
|
+
if curve['bi'][k] - curve['bi'][k-1] > 0:
|
246
|
+
dhdbn = ((curve['hi'][k] - curve['h'][k-1])
|
247
|
+
/(curve['bi'][k] - curve['bi'][k-1]))
|
248
|
+
a.append(MUE0*dhdbn)
|
249
|
+
b.append(MUE0*curve['hi'][k] - dhdbn*curve['bi'][k])
|
251
250
|
else:
|
252
251
|
a.append(1.0)
|
253
252
|
b.append(MUE0*curve['hi'][-1]-curve['bi'][-1])
|
femagtools/plot/char.py
CHANGED
@@ -333,10 +333,14 @@ def _plot_contour(speed, torque, z, ax, title='', levels=[],
|
|
333
333
|
clippath = Path(_get_nT_boundary(x, y))
|
334
334
|
patch = PathPatch(clippath, facecolor='none')
|
335
335
|
ax.add_patch(patch)
|
336
|
-
|
337
|
-
c.
|
338
|
-
|
339
|
-
c.
|
336
|
+
try:
|
337
|
+
for c in cont.collections:
|
338
|
+
c.set_clip_path(patch)
|
339
|
+
for c in contf.collections:
|
340
|
+
c.set_clip_path(patch)
|
341
|
+
except AttributeError: # matplotlib >= 3.10
|
342
|
+
cont.set_clip_path(patch)
|
343
|
+
contf.set_clip_path(patch)
|
340
344
|
|
341
345
|
if xscale > 1:
|
342
346
|
def format_fn(tick_val, tick_pos):
|
@@ -367,9 +371,16 @@ def efficiency_map(rmap, ax=0, title='', clabel=True,
|
|
367
371
|
|
368
372
|
|
369
373
|
def losses_map(rmap, ax=0, title='Losses Map / kW', clabel=True,
|
370
|
-
cmap='YlOrRd', cbar=False):
|
374
|
+
cmap='YlOrRd', cbar=False, key='losses'):
|
375
|
+
"""
|
376
|
+
plot losses map
|
377
|
+
Args:
|
378
|
+
rmap: (dict) result of efficiency_losses_map
|
379
|
+
key: (str) type of losses: 'plfe1', 'plfe2', 'plmag', 'plcu1', 'plcu2', 'plfric', 'losses';
|
380
|
+
"""
|
381
|
+
|
371
382
|
if ax == 0:
|
372
383
|
fig, ax = plt.subplots(figsize=(12, 12))
|
373
|
-
return _plot_contour(rmap['n'], rmap['T'], np.asarray(rmap[
|
374
|
-
|
375
|
-
|
384
|
+
return _plot_contour(rmap['n'], rmap['T'], np.asarray(rmap[key])/1e3, ax,
|
385
|
+
title=title, levels=14, clabel=clabel,
|
386
|
+
cmap=cmap, cbar=cbar)
|
@@ -44,10 +44,16 @@ if not airgap_created then
|
|
44
44
|
nc_line(r2, 0.0, x2, y2, 0.0)
|
45
45
|
|
46
46
|
if m.tot_num_slot > m.num_sl_gen then
|
47
|
+
if inner_da_end == nil then
|
48
|
+
inner_da_end = inner_da_start
|
49
|
+
end
|
47
50
|
x3, y3 = pr2c(inner_da_end, alfa)
|
48
51
|
x4, y4 = pr2c(r1, alfa)
|
49
52
|
nc_line(x3, y3, x4, y4, 0, 0)
|
50
53
|
|
54
|
+
if outer_da_end == nil then
|
55
|
+
outer_da_end = outer_da_start
|
56
|
+
end
|
51
57
|
x3, y3 = pr2c(outer_da_end, alfa)
|
52
58
|
x4, y4 = pr2c(r2, alfa)
|
53
59
|
nc_line(x3, y3, x4, y4, 0, 0)
|
femagtools/utils.py
CHANGED
@@ -17,7 +17,7 @@ def fft(pos, y, pmod=0):
|
|
17
17
|
else:
|
18
18
|
#negative_periodic = np.abs(y[0] - y[-1])/np.max(y) > 1
|
19
19
|
# count zero crossings
|
20
|
-
ypos = np.asarray(y
|
20
|
+
ypos = np.asarray(y)-np.mean(y) > 0
|
21
21
|
nypos = ~ypos
|
22
22
|
nzc = len(((ypos[:-1] & nypos[1:])
|
23
23
|
| (nypos[:-1] & ypos[1:])).nonzero()[0])
|
femagtools/windings.py
CHANGED
@@ -179,10 +179,10 @@ class Winding(object):
|
|
179
179
|
nue = n
|
180
180
|
else:
|
181
181
|
nue = self.kw_order(n)
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
182
|
+
if q1 == q2: # integral slot winding
|
183
|
+
q = self.Q/2/self.m/self.p
|
184
|
+
nuep = nue/self.p
|
185
|
+
return np.sin(nuep*np.pi/2/self.m)/q/np.sin(nuep*np.pi/2/self.m/q)
|
186
186
|
k = 2 if self.l == 1 else 1
|
187
187
|
a = nue*k*np.pi/self.Q*Yk
|
188
188
|
t = self.Q//Qb
|
@@ -416,6 +416,13 @@ class Winding(object):
|
|
416
416
|
[[d*s for s, d in zip(l, ld)] for l, ld in zip(lower, ldirs)])
|
417
417
|
# complete if not basic winding:
|
418
418
|
Qb = self.Q//num_basic_windings(self.Q, self.p, self.l)
|
419
|
+
|
420
|
+
if not np.asarray(upper).size or not np.asarray(lower).size:
|
421
|
+
layers = 1
|
422
|
+
if layers == 1 and z[1]:
|
423
|
+
z = ([[d*s for s, d in zip(l, ld)] for l, ld in zip(lower, ldirs)],
|
424
|
+
[[d*s for s, d in zip(u, ud)] for u, ud in zip(upper, udirs)])
|
425
|
+
|
419
426
|
if max([abs(n) for m in z[0] for n in m]) < Qb:
|
420
427
|
return [[k + [-n+Qb//2 if n < 0 else -(n+Qb//2) for n in k]
|
421
428
|
for k in m] for m in z]
|
femagtools/zmq.py
CHANGED
@@ -147,7 +147,6 @@ class SubscriberTask(threading.Thread):
|
|
147
147
|
def send_notify():
|
148
148
|
logger.debug(f"Send loop: {SubscriberTask.notify_send_loop}")
|
149
149
|
while SubscriberTask.notify_send_loop:
|
150
|
-
logger.debug(f"Send data: {SubscriberTask.notify_send_header}")
|
151
150
|
if 'progress_logger' in SubscriberTask.notify_send_header:
|
152
151
|
# collect data from different threads
|
153
152
|
SubscriberTask.notify_send_header.remove('progress_logger')
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: femagtools
|
3
|
-
Version: 1.8.
|
3
|
+
Version: 1.8.5
|
4
4
|
Summary: Python API for FEMAG
|
5
5
|
Author-email: Ronald Tanner <tar@semafor.ch>, Dapu Zhang <dzhang@gtisoft.com>, Beat Holm <hob@semafor.ch>, Günther Amsler <amg@semafor.ch>, Nicolas Mauchle <mau@semafor.ch>
|
6
6
|
License: Copyright (c) 2016-2023, Semafor Informatik & Energie AG, Basel
|