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

Sign up to get free protection for your applications and to get access to all the features.
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()