femagtools 1.8.2__py3-none-any.whl → 1.8.4__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.
Files changed (49) hide show
  1. femagtools/__init__.py +1 -1
  2. femagtools/bch.py +10 -6
  3. femagtools/dxfsl/area.py +69 -1
  4. femagtools/dxfsl/conv.py +53 -16
  5. femagtools/dxfsl/converter.py +273 -76
  6. femagtools/dxfsl/fslrenderer.py +18 -22
  7. femagtools/dxfsl/functions.py +38 -8
  8. femagtools/dxfsl/geom.py +112 -35
  9. femagtools/dxfsl/journal.py +1 -1
  10. femagtools/dxfsl/machine.py +44 -7
  11. femagtools/dxfsl/shape.py +4 -0
  12. femagtools/dxfsl/symmetry.py +105 -32
  13. femagtools/femag.py +64 -61
  14. femagtools/fsl.py +4 -2
  15. femagtools/isa7.py +3 -2
  16. femagtools/machine/afpm.py +45 -25
  17. femagtools/machine/effloss.py +31 -20
  18. femagtools/machine/im.py +6 -8
  19. femagtools/machine/sizing.py +4 -3
  20. femagtools/machine/sm.py +35 -37
  21. femagtools/mcv.py +66 -37
  22. femagtools/multiproc.py +79 -80
  23. femagtools/parstudy.py +10 -4
  24. femagtools/semi_fea.py +108 -0
  25. femagtools/templates/basic_modpar.mako +0 -3
  26. femagtools/templates/fe-contr.mako +18 -18
  27. femagtools/templates/ld_lq_fast.mako +3 -0
  28. femagtools/templates/mesh-airgap.mako +6 -0
  29. femagtools/templates/mult_cal_fast.mako +3 -0
  30. femagtools/templates/pm_sym_f_cur.mako +4 -1
  31. femagtools/templates/pm_sym_fast.mako +3 -0
  32. femagtools/templates/pm_sym_loss.mako +3 -0
  33. femagtools/templates/psd_psq_fast.mako +3 -0
  34. femagtools/templates/torq_calc.mako +3 -0
  35. femagtools/tks.py +23 -20
  36. femagtools/utils.py +1 -1
  37. femagtools/windings.py +11 -4
  38. femagtools/zmq.py +213 -0
  39. {femagtools-1.8.2.dist-info → femagtools-1.8.4.dist-info}/METADATA +3 -3
  40. {femagtools-1.8.2.dist-info → femagtools-1.8.4.dist-info}/RECORD +49 -47
  41. {femagtools-1.8.2.dist-info → femagtools-1.8.4.dist-info}/WHEEL +1 -1
  42. tests/test_afpm.py +15 -6
  43. tests/test_femag.py +1 -1
  44. tests/test_fsl.py +4 -4
  45. tests/test_mcv.py +20 -14
  46. tests/test_parident.py +2 -1
  47. {femagtools-1.8.2.dist-info → femagtools-1.8.4.dist-info}/LICENSE +0 -0
  48. {femagtools-1.8.2.dist-info → femagtools-1.8.4.dist-info}/entry_points.txt +0 -0
  49. {femagtools-1.8.2.dist-info → femagtools-1.8.4.dist-info}/top_level.txt +0 -0
@@ -10,20 +10,22 @@ 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, middle_angle
13
+ from femagtools.dxfsl.functions import Timer, SimpleProcess, middle_angle
14
14
  from femagtools.dxfsl.journal import Journal, getJournal
15
15
  from femagtools.dxfsl.area import TYPE_WINDINGS
16
+ from femagtools.dxfsl.areabuilder import disable_logging, enable_logging
16
17
  import logging
17
18
  import logging.config
18
19
  import numpy as np
19
20
  import sys
21
+ import multiprocessing
20
22
 
21
23
  logger = logging.getLogger(__name__)
22
24
  journal = None
23
25
 
24
26
 
25
27
  def plot_geom(doit, plt, geom, title="Plot", areas=True):
26
- if not doit:
28
+ if not doit or not plt:
27
29
  return
28
30
 
29
31
  logger.info("Prepare Plot %s", title)
@@ -42,9 +44,121 @@ def plot_geom(doit, plt, geom, title="Plot", areas=True):
42
44
  fill_areas=areas)
43
45
 
44
46
 
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
+
45
158
  def symmetry_search(machine,
46
- plt, # plotter
47
- kind,
159
+ plt=None, # plotter
160
+ kind="single",
161
+ mindist=0.01,
48
162
  symtol=0.0,
49
163
  sympart=0,
50
164
  is_inner=False,
@@ -56,11 +170,13 @@ def symmetry_search(machine,
56
170
  num=1):
57
171
  logger.info("*** Begin symmetry search for %s ***", kind)
58
172
 
59
- if is_inner:
60
- machine.set_inner()
61
- elif is_outer:
62
- machine.set_outer()
173
+ def return_machine(machine, kind):
174
+ machine.set_attributes(kind=kind, inner=is_inner, outer=is_outer)
175
+ machine.check_and_correct_geom(kind)
176
+ machine.delete_tiny_elements(mindist)
177
+ return machine
63
178
 
179
+ machine.set_attributes(kind=kind, inner=is_inner, outer=is_outer)
64
180
  machine.clear_cut_lines()
65
181
  if show_plots and debug_mode:
66
182
  plt.render_elements(machine.geom, Shape,
@@ -71,9 +187,8 @@ def symmetry_search(machine,
71
187
  logger.error("force symmetry failed")
72
188
  sys.exit(1)
73
189
  machine_ok = machine.get_forced_symmetry(sympart)
74
- machine_ok.set_kind(kind)
75
190
  logger.info("*** End of symmetry search for %s ***", kind)
76
- return machine_ok
191
+ return return_machine(machine_ok, kind)
77
192
 
78
193
  plot_geom(False, # for developer
79
194
  plt, machine.geom,
@@ -92,9 +207,8 @@ def symmetry_search(machine,
92
207
  rows=rows, cols=cols, num=num, show=False)
93
208
  machine_slice = machine.get_symmetry_slice()
94
209
  if machine_slice is None:
95
- machine.kind = kind
96
210
  logger.info(" - no slice extracted ?!?")
97
- return machine
211
+ return return_machine(machine, kind)
98
212
 
99
213
  plot_geom(False, # for developer
100
214
  plt, machine_slice.geom,
@@ -104,13 +218,11 @@ def symmetry_search(machine,
104
218
  machine_mirror = machine_slice.get_symmetry_mirror(no_third=True)
105
219
 
106
220
  if machine_mirror is not None:
107
- machine_mirror.set_kind(kind)
108
221
  logger.info("*** End of symmetry search for %s (symmetry and mirror) ***", kind)
109
- return machine_mirror
222
+ return return_machine(machine_mirror, kind)
110
223
 
111
- machine_slice.set_kind(kind)
112
224
  logger.info("*** End of symmetry search for %s (symmetry) ***", kind)
113
- return machine_slice
225
+ return return_machine(machine_slice, kind)
114
226
 
115
227
  # --- no symmetry slice found ---
116
228
  logger.info(" - {}: no symmetry axis found".format(kind))
@@ -129,6 +241,10 @@ def symmetry_search(machine,
129
241
  machine.rotate_to(0.0)
130
242
  machine.set_alfa_and_corners()
131
243
 
244
+ plot_geom(False, # for developer
245
+ plt, machine.geom,
246
+ title="Before Mirror ({})".format(kind))
247
+
132
248
  machine_mirror = machine.get_symmetry_mirror()
133
249
  machine_slice = machine
134
250
  machine_slice.set_alfa_and_corners()
@@ -146,6 +262,9 @@ def symmetry_search(machine,
146
262
  while machine_next_mirror is not None:
147
263
  logger.info(" - another mirror found")
148
264
  machine_mirror = machine_next_mirror
265
+ plot_geom(False, # for developer
266
+ plt, machine_mirror.geom,
267
+ title="Next Mirror ({})".format(kind))
149
268
  machine_next_mirror = machine_mirror.get_symmetry_mirror()
150
269
 
151
270
  machine_ok = machine_mirror
@@ -155,10 +274,8 @@ def symmetry_search(machine,
155
274
  machine_ok.rotate_to(0.0)
156
275
  machine_ok.set_alfa_and_corners()
157
276
 
158
- machine_ok.set_kind(kind)
159
-
160
277
  logger.info("*** End of symmetry search for %s ***", kind)
161
- return machine_ok
278
+ return return_machine(machine_ok, kind)
162
279
 
163
280
 
164
281
  def build_machine_rotor(machine, inner, mindist, plt, EESM=False, single=False):
@@ -313,6 +430,58 @@ def build_machine_stator(machine, inner, mindist, plt, EESM=False, single=False)
313
430
  return machine_temp
314
431
 
315
432
 
433
+ def build_inner_machine(machine,
434
+ mindist=0.01,
435
+ plt=None,
436
+ EESM=False):
437
+ logger.info("Begin of build_inner_machine")
438
+ machine.search_subregions(EESM)
439
+
440
+ if machine.geom.is_rotor(): # Inner mirrored rotor
441
+ machine = build_machine_rotor(machine,
442
+ True, # is inner
443
+ mindist,
444
+ plt,
445
+ EESM=EESM)
446
+
447
+ if machine.geom.is_stator() or machine.has_windings():
448
+ machine = build_machine_stator(machine,
449
+ True,
450
+ mindist,
451
+ plt,
452
+ EESM=EESM)
453
+
454
+ machine.search_critical_elements(mindist)
455
+ logger.info("End of build_inner_machine")
456
+ return machine
457
+
458
+
459
+ def build_outer_machine(machine,
460
+ mindist=0.01,
461
+ plt=None,
462
+ EESM=False):
463
+ logger.info("Begin of build_outer_machine")
464
+ machine.search_subregions(EESM)
465
+
466
+ if machine.geom.is_rotor(): # Outer mirrored rotor
467
+ machine = build_machine_rotor(machine,
468
+ False, # is outer
469
+ mindist,
470
+ plt,
471
+ EESM=EESM)
472
+
473
+ if machine.geom.is_stator() or machine.has_windings():
474
+ machine = build_machine_stator(machine,
475
+ False,
476
+ mindist,
477
+ plt,
478
+ EESM=EESM)
479
+
480
+ machine.search_critical_elements(mindist)
481
+ logger.info("End of build_outer_machine")
482
+ return machine
483
+
484
+
316
485
  def convert(dxfile,
317
486
  EESM=False,
318
487
  rtol=1e-04,
@@ -335,11 +504,13 @@ def convert(dxfile,
335
504
  show_areas=False,
336
505
  small_plots=False,
337
506
  write_fsl=True,
507
+ write_fsl_single=False,
338
508
  write_png=False,
339
509
  write_id=False,
340
510
  full_model=False,
341
511
  debug_mode=False,
342
- write_journal=False):
512
+ write_journal=False,
513
+ no_processing=False):
343
514
  global journal
344
515
  layers = ()
345
516
  conv = {}
@@ -360,6 +531,7 @@ def convert(dxfile,
360
531
  basename,
361
532
  __version__)
362
533
  timer = Timer(start_it=True)
534
+ start_timer = Timer(start_it=True)
363
535
 
364
536
  journal = getJournal(name='converter_journal', aktiv=write_journal)
365
537
  journal.get_journal(input_file.name)
@@ -388,6 +560,11 @@ def convert(dxfile,
388
560
  split_ini = False
389
561
  split_cpy = split
390
562
 
563
+ if write_fsl_single:
564
+ write_fsl = True
565
+ if small_plots:
566
+ show_plots = False
567
+
391
568
  try:
392
569
  if input_file.suffix in ['.fem', '.FEM']:
393
570
  from .femparser import femshapes
@@ -434,8 +611,6 @@ def convert(dxfile,
434
611
  logger.info("total elements %s", len(basegeom.g.edges()))
435
612
 
436
613
  p = PlotRenderer()
437
- if small_plots:
438
- show_plots = False
439
614
 
440
615
  if view_only:
441
616
  logger.info("View only")
@@ -462,6 +637,7 @@ def convert(dxfile,
462
637
 
463
638
  if not (machine_base.part > 0):
464
639
  # machine shape is unclear
640
+ logger.warn("machine shape is unclear")
465
641
  machine_base.set_center(0.0, 0.0)
466
642
  machine_base.set_radius(9999999)
467
643
 
@@ -552,72 +728,63 @@ def convert(dxfile,
552
728
  connect=True)
553
729
  machine_outer.set_outer()
554
730
 
731
+ start_timer.stop("-- first part in %0.4f seconds --", info=True)
732
+ process_timer = Timer(start_it=True)
555
733
  # inner part
556
- machine_inner = symmetry_search(machine_inner,
557
- p, # plot
558
- inner_name,
559
- is_inner=True,
560
- symtol=symtol,
561
- show_plots=show_plots,
562
- rows=3, # rows
563
- cols=2, # columns
564
- num=3) # start num
565
- machine_inner.set_inner()
566
- machine_inner.check_and_correct_geom("Inner")
567
- machine_inner.delete_tiny_elements(mindist)
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()
568
749
 
569
750
  # outer part
570
751
  machine_outer = symmetry_search(machine_outer,
571
- p, # plot
572
- outer_name,
752
+ plt=p, # plot
753
+ kind=outer_name,
573
754
  is_outer=True,
755
+ mindist=mindist,
574
756
  symtol=symtol,
575
757
  show_plots=show_plots,
576
758
  rows=3, # rows
577
759
  cols=2, # columns
578
760
  num=4) # start num
579
- machine_outer.check_and_correct_geom("Outer")
580
- machine_outer.delete_tiny_elements(mindist)
581
-
582
- machine_inner.sync_with_counterpart(machine_outer)
583
761
 
584
- machine_inner.search_subregions(EESM)
585
- machine_outer.search_subregions(EESM)
762
+ machine_inner = inner_queue.get()
763
+ inner_proc.wait()
764
+ process_timer.stop("-- symmetry search in %0.4f seconds --", info=True)
586
765
 
587
- # Inner mirrored rotor
588
- if machine_inner.geom.is_rotor():
589
- machine_inner = build_machine_rotor(machine_inner,
590
- True, # is inner
591
- mindist,
592
- p,
593
- EESM=EESM)
594
-
595
- # Outer mirrored rotor
596
- if machine_outer.geom.is_rotor():
597
- machine_outer = build_machine_rotor(machine_outer,
598
- False, # is outer
599
- mindist,
600
- p,
601
- EESM=EESM)
602
-
603
- if machine_inner.geom.is_stator() or machine_inner.has_windings():
604
- machine_inner = build_machine_stator(machine_inner,
605
- True,
606
- mindist,
607
- p,
608
- EESM=EESM)
609
-
610
- if machine_outer.geom.is_stator() or machine_outer.has_windings():
611
- machine_outer = build_machine_stator(machine_outer,
612
- False,
613
- mindist,
614
- p,
615
- EESM=EESM)
616
766
  machine_inner.sync_with_counterpart(machine_outer)
617
767
 
618
- machine_inner.search_critical_elements(mindist)
619
- machine_outer.search_critical_elements(mindist)
768
+ 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()
778
+
779
+ machine_outer = build_outer_machine(machine_outer,
780
+ mindist,
781
+ p,
782
+ EESM=EESM)
783
+ machine_inner = inner_queue.get()
784
+ inner_proc.wait()
785
+ final_timer.stop("-- final part in %0.4f seconds --", info=True)
620
786
 
787
+ machine_inner.sync_with_counterpart(machine_outer)
621
788
  logger.info("***** END of work: %s *****", basename)
622
789
 
623
790
  if machine_inner.geom.is_rotor():
@@ -719,6 +886,14 @@ def convert(dxfile,
719
886
  fslrenderer = FslRenderer(basename, mtype)
720
887
  inner = fslrenderer.render(machine_inner, inner=True)
721
888
  outer = fslrenderer.render(machine_outer, outer=True)
889
+ if write_fsl_single:
890
+ inner_single = fslrenderer.render(machine_inner, inner=True,
891
+ standalone=True)
892
+ outer_single = fslrenderer.render(machine_outer, outer=True,
893
+ standalone=True)
894
+ else:
895
+ inner_single = None
896
+ outer_single = None
722
897
  if full_model:
723
898
  params['num_sl_gen'] = params.get('tot_num_slot', 0)
724
899
  params['agndst'] = agndst(params.get('da1'),
@@ -729,10 +904,18 @@ def convert(dxfile,
729
904
 
730
905
  if params['external_rotor']:
731
906
  conv['fsl_rotor'] = outer
907
+ if outer_single:
908
+ conv['fsl_rotor_single'] = outer_single
732
909
  conv['fsl_stator'] = inner
910
+ if inner_single:
911
+ conv['fsl_stator_single'] = inner_single
733
912
  else:
734
913
  conv['fsl_rotor'] = inner
914
+ if inner_single:
915
+ conv['fsl_rotor_single'] = inner_single
735
916
  conv['fsl_stator'] = outer
917
+ if outer_single:
918
+ conv['fsl_stator_single'] = outer_single
736
919
 
737
920
  conv['fsl'] = fslrenderer.render_main(
738
921
  machine_inner, machine_outer,
@@ -756,10 +939,11 @@ def convert(dxfile,
756
939
  outer = True
757
940
 
758
941
  machine = symmetry_search(machine,
759
- p, # plot
760
- name,
942
+ plt=p, # plot
943
+ kind=name,
761
944
  is_inner=inner,
762
945
  is_outer=outer,
946
+ mindist=mindist,
763
947
  symtol=symtol,
764
948
  sympart=sympart,
765
949
  show_plots=show_plots,
@@ -875,11 +1059,24 @@ def convert(dxfile,
875
1059
  if write_fsl:
876
1060
  logger.debug("Write fsl")
877
1061
  if conv and conv['fsl']:
878
- with io.open(basename + '.fsl', 'w', encoding='utf-8') as f:
1062
+ with io.open(basename + '.fsl', 'w',
1063
+ encoding='utf-8') as f:
879
1064
  f.write('\n'.join(conv['fsl']))
880
1065
  else:
881
1066
  logger.warning("No fsl data available")
882
1067
 
1068
+ if conv:
1069
+ if conv.get('fsl_rotor_single', None):
1070
+ with io.open(basename + '_ROTOR.fsl', 'w',
1071
+ encoding='utf-8') as f:
1072
+ f.write('\n'.join(conv['fsl_rotor_single']))
1073
+ del conv['fsl_rotor_single']
1074
+ if conv.get('fsl_stator_single', None):
1075
+ with io.open(basename + '_STATOR.fsl', 'w',
1076
+ encoding='utf-8') as f:
1077
+ f.write('\n'.join(conv['fsl_stator_single']))
1078
+ del conv['fsl_stator_single']
1079
+
883
1080
  conv['name'] = basename
884
1081
  t = timer.stop("-- all done in %0.4f seconds --", info=True)
885
1082
  journal.put('time_total', t)
@@ -26,28 +26,18 @@ def agndst(da1, da2, Q, p, nodedist=1):
26
26
  """
27
27
  r = (da1 + da2)/4
28
28
  ag = abs(da1 - da2)/6
29
- num_nodes = [30, 48, 60, 96, 120, 144, 180, 240, 288, 336, 360,
30
- 432, 480]
31
- dagset = [2*np.pi/p/i for i in num_nodes]
32
- i = max(np.argmin(np.abs(np.array(dagset) - np.arctan2(ag, r))), 1)
33
- if p*num_nodes[i-1] % Q:
34
- lcm = np.lcm(Q, p)//p
35
- nmin, nmax = num_nodes[0]//lcm, num_nodes[-1]//lcm
36
- num_nodes = [i*lcm for i in range(nmin, nmax) if i*lcm%6==0]
37
- dagset = [2*np.pi/p/i for i in num_nodes]
38
- i = max(np.argmin(np.abs(np.array(dagset) - np.arctan2(ag, r))), 1)
39
- # nodedist 0.5, 2, 4, 6
40
- nd = min(round(nodedist), i)
41
- try:
42
- logger.info("Num nodes/p %d Num nodes/slot %g nodedist %g",
43
- num_nodes[i-1], p*num_nodes[i-1]/Q, nodedist)
44
- if nodedist > 1:
45
- return dagset[i-nd]*r
46
- if nodedist < 1 or i == 0:
47
- return dagset[i]*r
48
- except IndexError:
49
- pass
50
- return dagset[i-1]*r
29
+ lcm = np.lcm(Q, p)//p
30
+ taup = 2*np.pi*r/p
31
+ nmin, nmax = max(1, 18//lcm), 480//lcm
32
+ num_nodes = [i*lcm for i in range(nmin, nmax)
33
+ if i*lcm % 6 == 0 and i*lcm*p//Q % 2 == 0]
34
+ dagset = np.array([taup/i for i in num_nodes])
35
+ i = np.argmin(np.abs(dagset - ag*nodedist))
36
+ if i > 0 and dagset[i]*nodedist < ag:
37
+ i -= 1
38
+ logger.info("%d Num nodes/p %d Num nodes/slot %g nodedist %g",
39
+ i, num_nodes[i], p*num_nodes[i]/Q, nodedist)
40
+ return dagset[i]
51
41
 
52
42
 
53
43
  class FslRenderer(object):
@@ -629,9 +619,15 @@ class FslRenderer(object):
629
619
  'x2, y2 = pr2c(outer_da_start, 0.0)',
630
620
  'nc_line(r2, 0.0, x2, y2, 0.0)\n',
631
621
  'if m.tot_num_slot > m.num_sl_gen then',
622
+ ' if inner_da_end == nil then',
623
+ ' inner_da_end = inner_da_start',
624
+ ' end',
632
625
  ' x3, y3 = pr2c(inner_da_end, alfa)',
633
626
  ' x4, y4 = pr2c(r1, alfa)',
634
627
  ' nc_line(x3, y3, x4, y4, 0, 0)\n',
628
+ ' if outer_da_end == nil then',
629
+ ' outer_da_end = outer_da_start',
630
+ ' end',
635
631
  ' x3, y3 = pr2c(outer_da_end, alfa)',
636
632
  ' x4, y4 = pr2c(r2, alfa)',
637
633
  ' nc_line(x3, y3, x4, y4, 0, 0)',
@@ -12,6 +12,7 @@ import logging
12
12
  import numpy as np
13
13
  import copy
14
14
  import time
15
+ import multiprocessing
15
16
 
16
17
  logger = logging.getLogger('femagtools.functions')
17
18
 
@@ -76,8 +77,8 @@ def alpha_triangle(a, b, c):
76
77
  return rslt
77
78
 
78
79
 
79
- def alpha_angle(startangle, endangle):
80
- if less_equal(endangle, startangle):
80
+ def alpha_angle(startangle, endangle, rtol=1e-3, atol=1e-8):
81
+ if less_equal(endangle, startangle, rtol=rtol, atol=atol):
81
82
  endangle += 2.0*np.pi
82
83
  angle = endangle - startangle
83
84
  if less_equal(angle, 2.0*np.pi):
@@ -85,16 +86,24 @@ def alpha_angle(startangle, endangle):
85
86
  return angle - 2.0*np.pi
86
87
 
87
88
 
88
- def max_angle(alpha1, alpha2):
89
+ def less_angle(alpha1, alpha2):
89
90
  angle = alpha_angle(alpha1, alpha2)
90
- if angle < np.pi or angle > 2.0*np.pi:
91
- return alpha2
92
- return alpha1
91
+ return (angle < np.pi or angle > 2.0*np.pi)
93
92
 
94
93
 
95
- def min_angle(alpha1, alpha2):
94
+ def greater_angle(alpha1, alpha2):
96
95
  angle = alpha_angle(alpha1, alpha2)
97
- if angle < np.pi or angle > 2.0*np.pi:
96
+ return not (angle < np.pi or angle > 2.0*np.pi)
97
+
98
+
99
+ def max_angle(alpha1, alpha2):
100
+ if greater_angle(alpha1, alpha2):
101
+ return alpha1
102
+ return alpha2
103
+
104
+
105
+ def min_angle(alpha1, alpha2):
106
+ if less_angle(alpha1, alpha2):
98
107
  return alpha1
99
108
  return alpha2
100
109
 
@@ -472,3 +481,24 @@ class Timer(object):
472
481
  else:
473
482
  logger.debug(fmt, sec)
474
483
  return sec
484
+
485
+
486
+ class SimpleProcess(multiprocessing.Process):
487
+ def __init__(self, name=None, no_processing=False):
488
+ super(SimpleProcess, self).__init__()
489
+ self._no_processing = no_processing
490
+ self.name = name
491
+
492
+ def without_processing(self):
493
+ return self._no_processing
494
+
495
+ def wait(self):
496
+ if not self._no_processing:
497
+ logger.debug("%s Waiting for Process", self.name)
498
+ self.join()
499
+
500
+ def start_task(self):
501
+ if self._no_processing:
502
+ self.run()
503
+ return
504
+ self.start()