femagtools 1.8.4__py3-none-any.whl → 1.8.6__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
femagtools/__init__.py CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  """
4
4
  __title__ = 'femagtools'
5
- __version__ = '1.8.4'
5
+ __version__ = '1.8.6'
6
6
  __author__ = 'Ronald Tanner'
7
7
  __license__ = 'BSD'
8
8
  __copyright__ = 'Copyright 2023-2024 Gamma Technology'
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 re.findall(r'[-0-9.]+',
622
- ''.join(content))]
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})
@@ -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, SimpleProcess, middle_angle
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
- inner_queue = multiprocessing.Queue()
735
- inner_proc = SymSearchProcess(name="Inner", # for logger
736
- queue=inner_queue,
737
- machine=machine_inner,
738
- plt=None, # plot
739
- kind=inner_name,
740
- is_inner=True,
741
- mindist=mindist,
742
- symtol=symtol,
743
- show_plots=show_plots,
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
- inner_queue = multiprocessing.Queue()
770
- inner_proc = BuildInnerProcess(name="Inner", # for logger
771
- queue=inner_queue,
772
- machine=machine_inner,
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.info("make a cut")
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)