femagtools 1.8.4__py3-none-any.whl → 1.8.6__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 +5 -2
- femagtools/dxfsl/area.py +3 -0
- femagtools/dxfsl/conv.py +1 -8
- femagtools/dxfsl/converter.py +60 -147
- femagtools/dxfsl/geom.py +49 -0
- femagtools/femag.py +5 -2
- femagtools/machine/afpm.py +339 -12
- femagtools/machine/utils.py +2 -1
- femagtools/multiproc.py +2 -1
- femagtools/plot/__init__.py +1 -0
- femagtools/plot/bch.py +57 -3
- femagtools/plot/char.py +19 -8
- femagtools/plot/machine.py +100 -0
- femagtools/poc.py +10 -0
- femagtools/utils.py +3 -1
- femagtools/zmq.py +22 -5
- {femagtools-1.8.4.dist-info → femagtools-1.8.6.dist-info}/METADATA +1 -1
- {femagtools-1.8.4.dist-info → femagtools-1.8.6.dist-info}/RECORD +23 -22
- {femagtools-1.8.4.dist-info → femagtools-1.8.6.dist-info}/LICENSE +0 -0
- {femagtools-1.8.4.dist-info → femagtools-1.8.6.dist-info}/WHEEL +0 -0
- {femagtools-1.8.4.dist-info → femagtools-1.8.6.dist-info}/entry_points.txt +0 -0
- {femagtools-1.8.4.dist-info → femagtools-1.8.6.dist-info}/top_level.txt +0 -0
femagtools/__init__.py
CHANGED
femagtools/bch.py
CHANGED
@@ -618,8 +618,8 @@ class Reader:
|
|
618
618
|
|
619
619
|
def __read_peak_winding_currents(self, content):
|
620
620
|
self.scData['peakWindingCurrents'] = [float(x)
|
621
|
-
for x in
|
622
|
-
|
621
|
+
for x in self._numPattern.findall(
|
622
|
+
''.join(content))]
|
623
623
|
|
624
624
|
def __read_general_machine_data(self, content):
|
625
625
|
mcfiles = []
|
@@ -1771,6 +1771,9 @@ class Reader:
|
|
1771
1771
|
def __getattr__(self, k):
|
1772
1772
|
return self.__dict__[k]
|
1773
1773
|
|
1774
|
+
def asdict(self):
|
1775
|
+
return {k[0]: k[1] for k in self.items()}
|
1776
|
+
|
1774
1777
|
def items(self):
|
1775
1778
|
return [(k, self.get(k)) for k in ('version',
|
1776
1779
|
'type',
|
femagtools/dxfsl/area.py
CHANGED
@@ -435,6 +435,9 @@ class Area(object):
|
|
435
435
|
self.type == TYPE_WINDINGS or \
|
436
436
|
self.type == TYPE_FD_WINDINGS
|
437
437
|
|
438
|
+
def is_field_winding(self):
|
439
|
+
return self.type == TYPE_FD_WINDINGS
|
440
|
+
|
438
441
|
def is_magnet(self):
|
439
442
|
return self.type == TYPE_MAGNET_AIRGAP or self.type == TYPE_MAGNET_RECT
|
440
443
|
|
femagtools/dxfsl/conv.py
CHANGED
@@ -180,12 +180,6 @@ def main():
|
|
180
180
|
help='create full model (fsl only)',
|
181
181
|
dest='full_model',
|
182
182
|
action="store_true")
|
183
|
-
argparser.add_argument('--no_processing',
|
184
|
-
help=(argparse.SUPPRESS if not super_help else
|
185
|
-
"omit multiprocessing"),
|
186
|
-
dest='no_processing',
|
187
|
-
action="store_true",
|
188
|
-
default=False)
|
189
183
|
|
190
184
|
args = argparser.parse_args()
|
191
185
|
|
@@ -282,8 +276,7 @@ def main():
|
|
282
276
|
write_id=args.write_id,
|
283
277
|
debug_mode=args.debugger,
|
284
278
|
full_model=args.full_model,
|
285
|
-
write_journal=args.journal
|
286
|
-
no_processing=args.no_processing)
|
279
|
+
write_journal=args.journal)
|
287
280
|
keys = ('tot_num_slot', 'num_sl_gen', 'num_poles', 'nodedist',
|
288
281
|
'dy1', 'da1', 'da2', 'dy2', 'agndst', 'name')
|
289
282
|
logger.info("%s", {k: res[k] for k in keys if k in res})
|
femagtools/dxfsl/converter.py
CHANGED
@@ -10,7 +10,7 @@ from femagtools.dxfsl.shape import Shape
|
|
10
10
|
from femagtools.dxfsl.fslrenderer import FslRenderer, agndst
|
11
11
|
from femagtools.dxfsl.plotrenderer import PlotRenderer
|
12
12
|
from femagtools.dxfsl.concat import Concatenation
|
13
|
-
from femagtools.dxfsl.functions import Timer,
|
13
|
+
from femagtools.dxfsl.functions import Timer, middle_angle
|
14
14
|
from femagtools.dxfsl.journal import Journal, getJournal
|
15
15
|
from femagtools.dxfsl.area import TYPE_WINDINGS
|
16
16
|
from femagtools.dxfsl.areabuilder import disable_logging, enable_logging
|
@@ -18,10 +18,8 @@ import logging
|
|
18
18
|
import logging.config
|
19
19
|
import numpy as np
|
20
20
|
import sys
|
21
|
-
import multiprocessing
|
22
21
|
|
23
22
|
logger = logging.getLogger(__name__)
|
24
|
-
journal = None
|
25
23
|
|
26
24
|
|
27
25
|
def plot_geom(doit, plt, geom, title="Plot", areas=True):
|
@@ -44,117 +42,6 @@ def plot_geom(doit, plt, geom, title="Plot", areas=True):
|
|
44
42
|
fill_areas=areas)
|
45
43
|
|
46
44
|
|
47
|
-
class SymSearchProcess(SimpleProcess):
|
48
|
-
def __init__(self,
|
49
|
-
name=None,
|
50
|
-
queue=None,
|
51
|
-
machine=None,
|
52
|
-
plt=None, # plotter
|
53
|
-
kind="",
|
54
|
-
mindist=0.01,
|
55
|
-
symtol=0.0,
|
56
|
-
sympart=0,
|
57
|
-
is_inner=False,
|
58
|
-
is_outer=False,
|
59
|
-
show_plots=True,
|
60
|
-
debug_mode=False,
|
61
|
-
rows=1,
|
62
|
-
cols=1,
|
63
|
-
num=1,
|
64
|
-
no_processing=False):
|
65
|
-
SimpleProcess.__init__(self,
|
66
|
-
name=name,
|
67
|
-
no_processing=no_processing)
|
68
|
-
self.queue = queue
|
69
|
-
self.mach_in = machine
|
70
|
-
self.mach_out = None
|
71
|
-
self.plt = plt
|
72
|
-
self.kind = kind
|
73
|
-
self.mindist = mindist
|
74
|
-
self.symtol = symtol
|
75
|
-
self.sympart = sympart
|
76
|
-
self.is_inner = is_inner
|
77
|
-
self.is_outer = is_outer
|
78
|
-
self.show_plots = show_plots
|
79
|
-
self.debug_mode = debug_mode
|
80
|
-
self.rows = rows
|
81
|
-
self.cols = cols
|
82
|
-
self.num = num
|
83
|
-
pass
|
84
|
-
|
85
|
-
def run(self):
|
86
|
-
if not self.without_processing():
|
87
|
-
logger.info("Process is running")
|
88
|
-
self.plt = None
|
89
|
-
self.show_plots = False
|
90
|
-
else:
|
91
|
-
logger.info("without multiprocessing")
|
92
|
-
|
93
|
-
try:
|
94
|
-
self.mach_out = symmetry_search(
|
95
|
-
self.mach_in,
|
96
|
-
plt=self.plt,
|
97
|
-
kind=self.kind,
|
98
|
-
mindist=self.mindist,
|
99
|
-
symtol=self.symtol,
|
100
|
-
sympart=self.sympart,
|
101
|
-
is_inner=self.is_inner,
|
102
|
-
is_outer=self.is_outer,
|
103
|
-
show_plots=self.show_plots,
|
104
|
-
debug_mode=self.debug_mode,
|
105
|
-
rows=self.rows,
|
106
|
-
cols=self.cols,
|
107
|
-
num=self.num)
|
108
|
-
except Exception as e:
|
109
|
-
logger.warning("Exception in symmetry_search: %s", e)
|
110
|
-
if not self.mach_out:
|
111
|
-
logger.error("NO MACHINE AFTER PROCESS")
|
112
|
-
self.queue.put(self.mach_out)
|
113
|
-
if not self.without_processing():
|
114
|
-
logger.info("Process is finished")
|
115
|
-
|
116
|
-
|
117
|
-
class BuildInnerProcess(SimpleProcess):
|
118
|
-
def __init__(self,
|
119
|
-
name=None,
|
120
|
-
queue=None,
|
121
|
-
machine=None,
|
122
|
-
mindist=0.01,
|
123
|
-
plt=None, # plotter
|
124
|
-
EESM=False,
|
125
|
-
no_processing=False):
|
126
|
-
SimpleProcess.__init__(self,
|
127
|
-
name=name,
|
128
|
-
no_processing=no_processing)
|
129
|
-
self.queue = queue
|
130
|
-
self.mach_in = machine
|
131
|
-
self.mach_out = None
|
132
|
-
self.plt = plt
|
133
|
-
self.mindist = mindist
|
134
|
-
self.EESM = EESM
|
135
|
-
pass
|
136
|
-
|
137
|
-
def run(self):
|
138
|
-
if not self.without_processing():
|
139
|
-
logger.info("Process is running")
|
140
|
-
self.plt = None
|
141
|
-
else:
|
142
|
-
logger.info("without multiprocessing")
|
143
|
-
|
144
|
-
try:
|
145
|
-
self.mach_out = build_inner_machine(
|
146
|
-
self.mach_in,
|
147
|
-
mindist=self.mindist,
|
148
|
-
plt=self.plt,
|
149
|
-
EESM=self.EESM)
|
150
|
-
except Exception as e:
|
151
|
-
logger.warning("Exception in symmetry_search: %s", e)
|
152
|
-
|
153
|
-
self.queue.put(self.mach_out)
|
154
|
-
if not self.without_processing():
|
155
|
-
logger.info("Process is finished")
|
156
|
-
|
157
|
-
|
158
45
|
def symmetry_search(machine,
|
159
46
|
plt=None, # plotter
|
160
47
|
kind="single",
|
@@ -279,7 +166,6 @@ def symmetry_search(machine,
|
|
279
166
|
|
280
167
|
|
281
168
|
def build_machine_rotor(machine, inner, mindist, plt, EESM=False, single=False):
|
282
|
-
global journal
|
283
169
|
logger.debug("Begin of build_machine_rotor")
|
284
170
|
|
285
171
|
if machine.has_windings():
|
@@ -357,7 +243,6 @@ def build_machine_rotor(machine, inner, mindist, plt, EESM=False, single=False):
|
|
357
243
|
|
358
244
|
|
359
245
|
def build_machine_stator(machine, inner, mindist, plt, EESM=False, single=False):
|
360
|
-
global journal
|
361
246
|
logger.debug("Begin of build_machine_stator")
|
362
247
|
timer = Timer(start_it=True)
|
363
248
|
|
@@ -509,8 +394,7 @@ def convert(dxfile,
|
|
509
394
|
write_id=False,
|
510
395
|
full_model=False,
|
511
396
|
debug_mode=False,
|
512
|
-
write_journal=False
|
513
|
-
no_processing=False):
|
397
|
+
write_journal=False):
|
514
398
|
global journal
|
515
399
|
layers = ()
|
516
400
|
conv = {}
|
@@ -729,23 +613,19 @@ def convert(dxfile,
|
|
729
613
|
machine_outer.set_outer()
|
730
614
|
|
731
615
|
start_timer.stop("-- first part in %0.4f seconds --", info=True)
|
616
|
+
|
732
617
|
process_timer = Timer(start_it=True)
|
733
618
|
# inner part
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
rows=3, # rows
|
745
|
-
cols=2, # columns
|
746
|
-
num=3, # start num
|
747
|
-
no_processing=no_processing)
|
748
|
-
inner_proc.start_task()
|
619
|
+
machine_inner = symmetry_search(machine=machine_inner,
|
620
|
+
plt=p, # plot
|
621
|
+
kind=inner_name,
|
622
|
+
is_inner=True,
|
623
|
+
mindist=mindist,
|
624
|
+
symtol=symtol,
|
625
|
+
show_plots=show_plots,
|
626
|
+
rows=3, # rows
|
627
|
+
cols=2, # columns
|
628
|
+
num=3) # start num
|
749
629
|
|
750
630
|
# outer part
|
751
631
|
machine_outer = symmetry_search(machine_outer,
|
@@ -759,29 +639,20 @@ def convert(dxfile,
|
|
759
639
|
cols=2, # columns
|
760
640
|
num=4) # start num
|
761
641
|
|
762
|
-
machine_inner = inner_queue.get()
|
763
|
-
inner_proc.wait()
|
764
642
|
process_timer.stop("-- symmetry search in %0.4f seconds --", info=True)
|
765
643
|
|
766
644
|
machine_inner.sync_with_counterpart(machine_outer)
|
767
645
|
|
768
646
|
final_timer = Timer(start_it=True)
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
mindist=mindist,
|
774
|
-
plt=p,
|
775
|
-
EESM=EESM,
|
776
|
-
no_processing=no_processing)
|
777
|
-
inner_proc.start_task()
|
647
|
+
machine_inner = build_inner_machine(machine_inner,
|
648
|
+
mindist=mindist,
|
649
|
+
plt=p,
|
650
|
+
EESM=EESM)
|
778
651
|
|
779
652
|
machine_outer = build_outer_machine(machine_outer,
|
780
653
|
mindist,
|
781
654
|
p,
|
782
655
|
EESM=EESM)
|
783
|
-
machine_inner = inner_queue.get()
|
784
|
-
inner_proc.wait()
|
785
656
|
final_timer.stop("-- final part in %0.4f seconds --", info=True)
|
786
657
|
|
787
658
|
machine_inner.sync_with_counterpart(machine_outer)
|
@@ -963,7 +834,7 @@ def convert(dxfile,
|
|
963
834
|
r_out = 0.0
|
964
835
|
r_in = 0.0
|
965
836
|
if machine.cut_is_possible(r_in, r_out):
|
966
|
-
logger.
|
837
|
+
logger.debug("make a cut")
|
967
838
|
machine = machine.cut(r_in, r_out)
|
968
839
|
|
969
840
|
if part:
|
@@ -1085,6 +956,37 @@ def convert(dxfile,
|
|
1085
956
|
return conv
|
1086
957
|
|
1087
958
|
|
959
|
+
def _create_rotor_parameters(machine):
|
960
|
+
rotor = {
|
961
|
+
'min_radius': machine.geom.min_radius,
|
962
|
+
'max_radius': machine.geom.max_radius,
|
963
|
+
'mags': machine.geom.magnets_minmax_list(),
|
964
|
+
'fd_wnds': machine.geom.fd_windings_minmax_list()
|
965
|
+
}
|
966
|
+
shaft_min, shaft_max = machine.geom.shaft_minmax()
|
967
|
+
if shaft_max > 0.0:
|
968
|
+
rotor['shaft_min'] = shaft_min
|
969
|
+
rotor['shaft_max'] = shaft_max
|
970
|
+
if shaft_max > rotor['min_radius']:
|
971
|
+
rotor['min_radius'] = shaft_max
|
972
|
+
return rotor
|
973
|
+
|
974
|
+
|
975
|
+
def _create_stator_parameters(machine):
|
976
|
+
stator = {
|
977
|
+
'min_radius': machine.geom.min_radius,
|
978
|
+
'max_radius': machine.geom.max_radius,
|
979
|
+
'wnds': machine.geom.windings_minmax_list()
|
980
|
+
}
|
981
|
+
shaft_min, shaft_max = machine.geom.shaft_minmax()
|
982
|
+
if shaft_max > 0.0:
|
983
|
+
stator['shaft_min'] = shaft_min
|
984
|
+
stator['shaft_max'] = shaft_max
|
985
|
+
if shaft_max > stator['min_radius']:
|
986
|
+
stator['min_radius'] = shaft_max
|
987
|
+
return stator
|
988
|
+
|
989
|
+
|
1088
990
|
def create_femag_parameters(m_inner, m_outer, nodedist=1):
|
1089
991
|
if not (m_inner and m_outer):
|
1090
992
|
logger.warning("inner %s outer %s", m_inner, m_outer)
|
@@ -1127,6 +1029,13 @@ def create_femag_parameters(m_inner, m_outer, nodedist=1):
|
|
1127
1029
|
params['alfa_slot'] = alfa_slot
|
1128
1030
|
params['alfa_pole'] = alfa_pole
|
1129
1031
|
|
1032
|
+
if m_inner.geom.is_rotor():
|
1033
|
+
params['rotor'] = _create_rotor_parameters(m_inner)
|
1034
|
+
params['stator'] = _create_stator_parameters(m_outer)
|
1035
|
+
else:
|
1036
|
+
params['rotor'] = _create_rotor_parameters(m_outer)
|
1037
|
+
params['stator'] = _create_stator_parameters(m_inner)
|
1038
|
+
|
1130
1039
|
if num_slots == 0 or num_poles == 0:
|
1131
1040
|
if num_slots == 0:
|
1132
1041
|
logger.warning("No slots found")
|
@@ -1154,6 +1063,8 @@ def create_femag_parameters_stator(motor, position):
|
|
1154
1063
|
params['dy1'] = 2*motor.geom.max_radius
|
1155
1064
|
params['da1'] = 2*motor.geom.min_radius
|
1156
1065
|
params['slot_area'] = motor.slot_area()
|
1066
|
+
params['stator'] = _create_stator_parameters(motor)
|
1067
|
+
params['machine'] = motor
|
1157
1068
|
return params
|
1158
1069
|
|
1159
1070
|
|
@@ -1168,4 +1079,6 @@ def create_femag_parameters_rotor(motor, position):
|
|
1168
1079
|
params['dy1'] = 2*motor.geom.max_radius
|
1169
1080
|
params['da1'] = 2*motor.geom.min_radius
|
1170
1081
|
params['slot_area'] = motor.slot_area()
|
1082
|
+
params['rotor'] = _create_rotor_parameters(motor)
|
1083
|
+
params['machine'] = motor
|
1171
1084
|
return params
|
femagtools/dxfsl/geom.py
CHANGED
@@ -4528,6 +4528,55 @@ class Geometry(object):
|
|
4528
4528
|
add_element(e)
|
4529
4529
|
self.area_list += area_list
|
4530
4530
|
|
4531
|
+
def areas_minmax_list(self, area_list):
|
4532
|
+
if not area_list:
|
4533
|
+
return []
|
4534
|
+
|
4535
|
+
dist_list = []
|
4536
|
+
for n, a in enumerate(area_list):
|
4537
|
+
dist_list.append((a.min_dist, a.max_dist, n))
|
4538
|
+
dist_list.sort()
|
4539
|
+
|
4540
|
+
minmax_list = []
|
4541
|
+
d1_this, d2_this, n = dist_list [0]
|
4542
|
+
for d1_next, d2_next, n in dist_list[1:]:
|
4543
|
+
if d1_next > d2_this:
|
4544
|
+
minmax_list.append((d1_this, d2_this))
|
4545
|
+
d1_this = d1_next
|
4546
|
+
d2_this = d2_next
|
4547
|
+
else:
|
4548
|
+
d2_this = max(d2_this, d2_next)
|
4549
|
+
minmax_list.append((d1_this, d2_this))
|
4550
|
+
return minmax_list
|
4551
|
+
|
4552
|
+
def magnets_minmax_list(self):
|
4553
|
+
magnets = [a for a in self.list_of_areas()
|
4554
|
+
if a.is_magnet()]
|
4555
|
+
return self.areas_minmax_list(magnets)
|
4556
|
+
|
4557
|
+
def windings_minmax_list(self):
|
4558
|
+
windings = [a for a in self.list_of_areas()
|
4559
|
+
if a.is_winding()]
|
4560
|
+
return self.areas_minmax_list(windings)
|
4561
|
+
|
4562
|
+
def fd_windings_minmax_list(self):
|
4563
|
+
windings = [a for a in self.list_of_areas()
|
4564
|
+
if a.is_field_winding()]
|
4565
|
+
return self.areas_minmax_list(windings)
|
4566
|
+
|
4567
|
+
def shaft_minmax(self):
|
4568
|
+
shafts = [a for a in self.list_of_areas()
|
4569
|
+
if a.is_shaft()]
|
4570
|
+
if not shafts:
|
4571
|
+
return (0.0, 0.0)
|
4572
|
+
|
4573
|
+
dmin = shafts[0].min_dist
|
4574
|
+
dmax = shafts[0].max_dist
|
4575
|
+
for s in shafts[1:]:
|
4576
|
+
dmin = min(dmin, s.min_dist)
|
4577
|
+
dmax = max(dmax, s.max_dist)
|
4578
|
+
return (dmin, dmax)
|
4579
|
+
|
4531
4580
|
def check_airgap_connecting_nodes(self, geom, startangle, endangle):
|
4532
4581
|
logger.info("check_airgap_connecting_nodes")
|
4533
4582
|
|
femagtools/femag.py
CHANGED
@@ -802,8 +802,10 @@ class ZmqFemag(BaseFemag):
|
|
802
802
|
"""attaches a notify function"""
|
803
803
|
logger.info("Subscribe on '%s' port %d", self.femaghost, self.port+1)
|
804
804
|
if self.subscriber is None:
|
805
|
+
# progress/xyplot at a configured timestep published
|
806
|
+
header = [b'progress', b'xyplot', b'license']
|
805
807
|
self.subscriber = femagtools.zmq.SubscriberTask(
|
806
|
-
port=self.port+1, host=self.femaghost, notify=notify)
|
808
|
+
port=self.port+1, host=self.femaghost, notify=notify, header=header)
|
807
809
|
self.subscriber.start()
|
808
810
|
else:
|
809
811
|
# reattach?
|
@@ -1087,7 +1089,7 @@ class ZmqFemag(BaseFemag):
|
|
1087
1089
|
response = self.send_request(
|
1088
1090
|
['CONTROL', f'getfile = {filename}'], timeout=1000)
|
1089
1091
|
return [response[0].decode('latin1'),
|
1090
|
-
response[1] if len(response) else b'']
|
1092
|
+
response[1] if len(response) > 1 else b'']
|
1091
1093
|
|
1092
1094
|
def exportsvg(self, fslcmds, timeout=10000):
|
1093
1095
|
"""get svg format from fsl commands (if any graphic created)
|
@@ -1156,6 +1158,7 @@ class ZmqFemag(BaseFemag):
|
|
1156
1158
|
logger.info("Interrupt %s", self.femaghost)
|
1157
1159
|
ctrl.send_string('interrupt')
|
1158
1160
|
ctrl.close()
|
1161
|
+
femagtools.zmq.SubscriberTask.clear()
|
1159
1162
|
|
1160
1163
|
def copy_winding_file(self, name, wdg):
|
1161
1164
|
wdg.write(name, self.workdir)
|