femagtools 1.6.8__py3-none-any.whl → 1.7.1__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 (51) hide show
  1. femagtools/__init__.py +2 -2
  2. femagtools/bch.py +1 -1
  3. femagtools/dxfsl/area.py +343 -406
  4. femagtools/dxfsl/areabuilder.py +139 -12
  5. femagtools/dxfsl/conv.py +27 -9
  6. femagtools/dxfsl/converter.py +406 -127
  7. femagtools/dxfsl/corner.py +3 -0
  8. femagtools/dxfsl/femparser.py +1 -1
  9. femagtools/dxfsl/fslrenderer.py +290 -246
  10. femagtools/dxfsl/functions.py +4 -2
  11. femagtools/dxfsl/geom.py +1204 -893
  12. femagtools/dxfsl/journal.py +58 -22
  13. femagtools/dxfsl/machine.py +254 -75
  14. femagtools/dxfsl/plotrenderer.py +38 -3
  15. femagtools/dxfsl/shape.py +380 -103
  16. femagtools/dxfsl/symmetry.py +679 -110
  17. femagtools/femag.py +27 -2
  18. femagtools/forcedens.py +65 -40
  19. femagtools/fsl.py +71 -28
  20. femagtools/losscoeffs.py +46 -0
  21. femagtools/machine/effloss.py +8 -1
  22. femagtools/machine/im.py +3 -1
  23. femagtools/machine/pm.py +11 -7
  24. femagtools/machine/sizing.py +15 -12
  25. femagtools/machine/sm.py +114 -33
  26. femagtools/machine/utils.py +38 -34
  27. femagtools/model.py +12 -2
  28. femagtools/moo/population.py +1 -1
  29. femagtools/parstudy.py +17 -1
  30. femagtools/plot/__init__.py +1 -1
  31. femagtools/plot/char.py +24 -7
  32. femagtools/plot/forcedens.py +56 -29
  33. femagtools/plot/mcv.py +4 -1
  34. femagtools/plot/phasor.py +6 -1
  35. femagtools/poc.py +17 -10
  36. femagtools/templates/cogg_calc.mako +7 -1
  37. femagtools/templates/displ_stator_rotor.mako +33 -0
  38. femagtools/templates/fieldcalc.mako +10 -16
  39. femagtools/templates/pm_sym_f_cur.mako +1 -1
  40. femagtools/tks.py +3 -9
  41. {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/LICENSE +1 -0
  42. {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/METADATA +7 -4
  43. {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/RECORD +51 -50
  44. {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/WHEEL +1 -1
  45. tests/engines/__init__.py +0 -20
  46. tests/geom/__init__.py +0 -20
  47. tests/moo/__init__.py +0 -20
  48. tests/test_model.py +8 -1
  49. tests/test_sizing.py +2 -2
  50. {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/entry_points.txt +0 -0
  51. {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/top_level.txt +0 -0
@@ -5,7 +5,7 @@
5
5
  from __future__ import print_function
6
6
  import numpy as np
7
7
  import logging
8
- from .shape import Element, Circle, Arc, Line
8
+ from .shape import Element, Circle, Arc, Line, Shape
9
9
  from .corner import Corner
10
10
  from femagtools.dxfsl.symmetry import Symmetry
11
11
  from .functions import point, points_are_close, distance
@@ -35,7 +35,9 @@ class Machine(object):
35
35
  self.airgaps = []
36
36
  self.airgap_radius = 0.0
37
37
  self.airgap2_radius = 0.0
38
+ self.airgap_second = None
38
39
  self.previous_machine = None
40
+
39
41
  if not self.center:
40
42
  raise ValueError("FATAL ERROR: no center in Geometry")
41
43
 
@@ -116,11 +118,19 @@ class Machine(object):
116
118
  def set_kind(self, kind):
117
119
  self.geom.kind = kind
118
120
 
121
+ def set_inner_or_outer(self, place=''):
122
+ if place == 'in':
123
+ self.set_inner()
124
+ elif place == 'out':
125
+ self.set_outer()
126
+
119
127
  def set_inner(self):
120
128
  self.geom.is_inner = True
129
+ self.geom.is_outer = False
121
130
 
122
131
  def set_outer(self):
123
132
  self.geom.is_outer = True
133
+ self.geom.is_inner = False
124
134
 
125
135
  def clear_cut_lines(self):
126
136
  self.geom.clear_cut_lines()
@@ -173,7 +183,8 @@ class Machine(object):
173
183
  def copy(self, startangle, endangle,
174
184
  airgap=False, inside=True, split=False,
175
185
  delete_appendices=False,
176
- concatenate_tiny_el=False):
186
+ concatenate=False,
187
+ connect=False):
177
188
  if airgap and self.airgap_radius > 0.0:
178
189
  if inside:
179
190
  if self.airgap2_radius > 0.0:
@@ -185,7 +196,8 @@ class Machine(object):
185
196
  0.0, new_radius,
186
197
  split=split,
187
198
  delete_appendices=delete_appendices,
188
- concatenate_tiny_el=concatenate_tiny_el)
199
+ concatenate=concatenate,
200
+ connect=connect)
189
201
  else:
190
202
  new_radius = self.radius
191
203
  gap_radius = max(self.airgap_radius, self.airgap2_radius)
@@ -194,7 +206,8 @@ class Machine(object):
194
206
  gap_radius, self.radius+9999,
195
207
  split=split,
196
208
  delete_appendices=delete_appendices,
197
- concatenate_tiny_el=concatenate_tiny_el)
209
+ concatenate=concatenate,
210
+ connect=connect)
198
211
 
199
212
  circ = Circle(Element(center=self.center,
200
213
  radius=self.airgap_radius))
@@ -206,7 +219,8 @@ class Machine(object):
206
219
  self.radius+9999,
207
220
  split=split,
208
221
  delete_appendices=delete_appendices,
209
- concatenate_tiny_el=concatenate_tiny_el)
222
+ concatenate=concatenate,
223
+ connect=connect)
210
224
 
211
225
  if not np.isclose(normalise_angle(startangle),
212
226
  normalise_angle(endangle), 0.0):
@@ -230,11 +244,16 @@ class Machine(object):
230
244
  startangle=self.startangle,
231
245
  endangle=self.endangle)
232
246
 
233
- def full_copy(self):
247
+ def full_copy(self, concatenate_matching_el=False):
234
248
  clone = self.geom.copy_shape(self.radius,
235
249
  0.0, 2*np.pi,
236
- 0.0, self.radius+9999)
237
- return clone.get_machine()
250
+ 0.0, self.radius+9999,
251
+ concatenate_matching_el=concatenate_matching_el)
252
+ clone.kind = self.geom.kind
253
+ clone.sym_part = self.geom.sym_part
254
+ clone.sym_counterpart = self.geom.sym_counterpart
255
+ clone.alfa = self.geom.alfa
256
+ self.geom = clone
238
257
 
239
258
  def copy_mirror(self, startangle, midangle, endangle):
240
259
  logger.debug("begin of copy_mirror")
@@ -290,6 +309,7 @@ class Machine(object):
290
309
 
291
310
  if points_are_close(self.center, [0.0, 0.0]):
292
311
  angle = new_startangle - self.startangle
312
+ self.geom.area_list = []
293
313
  self.geom.rotate(angle)
294
314
  self.startangle = new_startangle
295
315
  self.endangle += angle
@@ -437,11 +457,14 @@ class Machine(object):
437
457
  pos_list.append([pos, d, c])
438
458
  elif prv_dist_percent <= 1:
439
459
  pos_list.append([prv_dist_percent, d, c])
460
+
440
461
  if get_one:
441
462
  if pos_list:
442
463
  dist_list = [[d, c] for pos, d, c in pos_list]
443
464
  dist_list.sort()
444
465
  circle = dist_list[0][1]
466
+ if len(dist_list) > 1:
467
+ self.airgap_second = dist_list[1][1]
445
468
 
446
469
  logger.info("airgap {} prefered".format(circle.radius))
447
470
  return circle.radius
@@ -449,6 +472,19 @@ class Machine(object):
449
472
  print("Use options --airgap/--airgap2 <float> to specify")
450
473
  return None
451
474
 
475
+ def check_airgap(self):
476
+ return self.geom.check_airgap(self.startangle, self.endangle)
477
+
478
+ def install_alternative_airgap(self):
479
+ if self.airgap_second is None:
480
+ return False
481
+ circle = self.airgap_second
482
+ self.airgap_radius = circle.radius
483
+ return True
484
+
485
+ def has_alternative_airgap(self):
486
+ return self.airgap_second is not None
487
+
452
488
  def has_airgap(self):
453
489
  return self.airgap_radius > 0.0
454
490
 
@@ -522,46 +558,12 @@ class Machine(object):
522
558
  rtol=rtol, atol=atol)
523
559
  logger.debug('end of repair_hull_geom')
524
560
 
525
- def create_stator_auxiliary_lines(self):
526
- logger.debug("create_stator_auxiliary_lines")
527
- return self.geom.create_auxiliary_lines(self.startangle, self.endangle)
561
+ def create_boundery_nodes(self):
562
+ self.geom.create_boundery_nodes(self.center, self.startangle, self.endangle)
528
563
 
529
- def create_rotor_auxiliary_lines(self):
530
- logger.debug("create_rotor_auxiliary_lines")
531
- done = False
532
- ag_list = self.geom.detect_airgaps(self.center,
533
- self.startangle, self.endangle,
534
- atol=0.001,
535
- with_end=True)
536
- if ag_list:
537
- radius_list = [(ag[0], (ag[0] + ag[1]) / 2, ag[1]) for ag in ag_list]
538
-
539
- min_mag, max_mag = self.geom.get_minmax_magnet()
540
- if self.geom.is_inner:
541
- radius_list.sort()
542
- rmin, rmid, rmax = radius_list[0]
543
- start = 0
544
- for r in radius_list[1:]:
545
- if np.isclose(rmax, r[0]):
546
- # SHAFT
547
- rmin, rmid, rmax = r
548
- start = 1
549
- break
550
-
551
- for r in radius_list[start:]:
552
- if (r[2] - r[0]) > 4:
553
- radius = (r[1] + r[2]) / 2
554
- elif (r[2] - r[1]) > 1:
555
- radius = r[1]
556
- else:
557
- radius = min_mag + 1
558
- if radius < min_mag:
559
- if self.create_arc(radius, attr='iron_sep'):
560
- done = True
561
-
562
- if self.geom.create_auxiliary_lines(self.startangle, self.endangle):
563
- done = True
564
- return done
564
+ def create_auxiliary_lines(self):
565
+ logger.debug("create_auxiliary_lines")
566
+ return self.geom.create_auxiliary_lines(self.startangle, self.endangle)
565
567
 
566
568
  def set_alfa_and_corners(self):
567
569
  self.geom.start_corners = self.geom.get_corner_nodes(self.center,
@@ -588,7 +590,7 @@ class Machine(object):
588
590
  return w*2
589
591
  return w
590
592
 
591
- def find_symmetry(self, sym_tolerance, is_inner, is_outer):
593
+ def find_symmetry(self, sym_tolerance, is_inner, is_outer, plt):
592
594
  logger.debug("begin of find_symmetry")
593
595
  if self.radius <= 0.0:
594
596
  return False
@@ -603,7 +605,8 @@ class Machine(object):
603
605
  found = True
604
606
  else:
605
607
  found = self.geom.find_symmetry(self.radius,
606
- self.startangle, self.endangle,
608
+ self.startangle,
609
+ self.endangle,
607
610
  sym_tolerance)
608
611
  if not found and len(self.geom.area_list) < 5:
609
612
  if is_inner:
@@ -614,7 +617,8 @@ class Machine(object):
614
617
  if self.part != 1: # not full
615
618
  logger.debug("end of find_symmetry: not full")
616
619
  return found
617
-
620
+ return found
621
+ # ENDE
618
622
  if found:
619
623
  angle = self.geom.sym_slice_angle
620
624
  logger.debug(" - #1: %s slices with angle %s",
@@ -623,9 +627,33 @@ class Machine(object):
623
627
  else:
624
628
  logger.debug(" - #1: no symmetry found")
625
629
  angle = np.pi/2
630
+
631
+ if plt:
632
+ plt.render_elements(self.geom, Shape,
633
+ draw_inside=False,
634
+ title="Before Copy",
635
+ show=True,
636
+ with_corners=False,
637
+ with_nodes=False,
638
+ neighbors=True,
639
+ write_id=True)
640
+
641
+ logger.debug("1: ### create a new clone to find symmetry ###")
626
642
  elist = self.geom.copy_all_elements(-angle)
627
643
  logger.debug(" - %s elements copied", len(elist))
628
- clone = self.geom.new_clone(elist)
644
+ clone = self.geom.new_clone(elist,
645
+ concatenate=False,
646
+ connect=False)
647
+
648
+ if plt:
649
+ plt.render_elements(clone, Shape,
650
+ draw_inside=False,
651
+ title="After Copy",
652
+ show=True,
653
+ with_corners=False,
654
+ with_nodes=False,
655
+ neighbors=True,
656
+ write_id=True)
629
657
 
630
658
  f = clone.find_symmetry(self.radius,
631
659
  self.startangle,
@@ -651,9 +679,21 @@ class Machine(object):
651
679
  self.geom.sym_slices)
652
680
  return True
653
681
 
682
+ logger.debug("2: ### create a new clone to find symmetry ###")
654
683
  elist = clone.copy_all_elements(-angle)
655
684
  logger.debug(" - %s elements copied", len(elist))
656
- clone = clone.new_clone(elist)
685
+ clone = clone.new_clone(elist,
686
+ concatenate=False,
687
+ connect=False)
688
+ if plt:
689
+ plt.render_elements(clone, Shape,
690
+ draw_inside=False,
691
+ title="After Clone",
692
+ show=True,
693
+ with_corners=False,
694
+ with_nodes=False,
695
+ neighbors=True,
696
+ write_id=True)
657
697
 
658
698
  f = clone.find_symmetry(self.radius,
659
699
  self.startangle,
@@ -685,7 +725,7 @@ class Machine(object):
685
725
  elist = [Circle(Element(center=self.center,
686
726
  radius=radius))]
687
727
  elist += self.geom.copy_all_elements(0.0)
688
- clone = self.geom.new_clone(elist, split=True)
728
+ clone = self.geom.new_clone(elist, split=False)
689
729
  found = clone.find_symmetry(self.radius,
690
730
  self.startangle,
691
731
  self.endangle,
@@ -707,7 +747,8 @@ class Machine(object):
707
747
 
708
748
  machine_slice = self.copy(self.geom.symmetry_startangle(),
709
749
  self.geom.symmetry_endangle(),
710
- concatenate_tiny_el=True)
750
+ concatenate=True,
751
+ connect=True)
711
752
  machine_slice.clear_cut_lines()
712
753
  machine_slice.repair_hull()
713
754
  machine_slice.rotate_to(0.0)
@@ -732,7 +773,7 @@ class Machine(object):
732
773
  logger.debug("end get_forced_symmetry")
733
774
  return machine
734
775
 
735
- def get_third_symmetry_mirror(self):
776
+ def get_third_symmetry_mirror(self, plt):
736
777
  logger.debug("begin get_third_symmetry_mirror")
737
778
  first_thirdangle = third_angle(self.startangle, self.endangle)
738
779
  second_thirdangle = middle_angle(first_thirdangle, self.endangle)
@@ -741,12 +782,28 @@ class Machine(object):
741
782
  first_thirdangle,
742
783
  second_thirdangle)
743
784
  machine_mirror_1.clear_cut_lines()
785
+
744
786
  machine_mirror_1.repair_hull()
745
787
  machine_mirror_1.set_alfa_and_corners()
746
788
  if not machine_mirror_1.check_symmetry_graph(0.001, 0.05):
747
789
  logger.debug("end get_third_symmetry_mirror: no mirror first third")
748
790
  return None
749
791
 
792
+ if plt:
793
+ plt.render_elements(machine_mirror_1.geom, Shape,
794
+ title="Part",
795
+ show=True,
796
+ with_corners=False,
797
+ with_nodes=False,
798
+ neighbors=True)
799
+
800
+ plt.render_elements(machine_mirror_1.mirror_geom, Shape,
801
+ title="Counterpart",
802
+ show=True,
803
+ with_corners=False,
804
+ with_nodes=False,
805
+ neighbors=True)
806
+
750
807
  machine_mirror_2 = self.copy_mirror(first_thirdangle,
751
808
  second_thirdangle,
752
809
  self.endangle)
@@ -761,7 +818,7 @@ class Machine(object):
761
818
  logger.debug("end get_third_symmetry_mirror: ok")
762
819
  return machine_mirror_1
763
820
 
764
- def get_symmetry_mirror(self):
821
+ def get_symmetry_mirror(self, no_third=False, plt=None):
765
822
  logger.debug("begin get_symmetry_mirror")
766
823
  if self.part == 1:
767
824
  # a complete machine
@@ -772,7 +829,10 @@ class Machine(object):
772
829
  startangle = self.startangle
773
830
  endangle = self.endangle
774
831
  midangle = middle_angle(self.startangle, self.endangle)
775
- machine_mirror = self.get_third_symmetry_mirror()
832
+ if no_third:
833
+ machine_mirror = None
834
+ else:
835
+ machine_mirror = self.get_third_symmetry_mirror(plt)
776
836
  if machine_mirror:
777
837
  logger.debug("end get_symmetry_mirror: third found")
778
838
  return machine_mirror
@@ -781,8 +841,32 @@ class Machine(object):
781
841
  .format(startangle, midangle, endangle))
782
842
  machine_mirror = self.copy_mirror(startangle, midangle, endangle)
783
843
  machine_mirror.clear_cut_lines()
844
+
845
+ if plt:
846
+ plt.render_elements(machine_mirror.geom, Shape,
847
+ title="Before Repair Hull",
848
+ show=True,
849
+ with_corners=False,
850
+ with_nodes=False,
851
+ neighbors=True)
852
+
784
853
  machine_mirror.repair_hull()
785
854
  machine_mirror.set_alfa_and_corners()
855
+ if False:
856
+ plt.render_elements(machine_mirror.geom, Shape,
857
+ title="Part",
858
+ show=True,
859
+ with_corners=False,
860
+ with_nodes=False,
861
+ neighbors=True)
862
+
863
+ plt.render_elements(machine_mirror.mirror_geom, Shape,
864
+ title="Counterpart",
865
+ show=True,
866
+ with_corners=False,
867
+ with_nodes=False,
868
+ neighbors=True)
869
+
786
870
  if machine_mirror.check_symmetry_graph(0.001, 0.05):
787
871
  machine_mirror.previous_machine = self
788
872
  machine_mirror.rotate_to(0.0)
@@ -922,45 +1006,73 @@ class Machine(object):
922
1006
  logger.debug("end get_hit_factor => %s", factor)
923
1007
  return factor
924
1008
 
1009
+ symmetry = Symmetry(geom=self.geom,
1010
+ startangle=self.startangle,
1011
+ endangle=self.endangle)
1012
+ if symmetry.check_symmetry_of_mirror(self.mirror_geom,
1013
+ self.mirror_startangle):
1014
+ logger.debug("NEW SYMMETRY FOUND")
1015
+ return True
1016
+ return False
1017
+
925
1018
  hit_factor1 = get_hit_factor(self.geom,
926
1019
  self.mirror_geom)
927
1020
  logger.debug("=> hit_factor1 = {}".format(hit_factor1))
928
1021
  if hit_factor1 < 0.9:
929
- logger.debug("end get_hit_factor: hit_factor1 < 0.9")
1022
+ logger.debug("end check_symmetry_graph: hit_factor1 < 0.9")
930
1023
  return False # not ok
931
1024
 
932
1025
  hit_factor2 = get_hit_factor(self.mirror_geom,
933
1026
  self.geom)
934
1027
  logger.debug("=> hit_factor2 = {}".format(hit_factor2))
935
1028
  if hit_factor2 < 0.9:
936
- logger.debug("end get_hit_factor: hit_factor2 < 0.9")
1029
+ logger.debug("end check_symmetry_graph: hit_factor2 < 0.9")
937
1030
  return False # not ok
938
1031
 
939
1032
  if hit_factor1 < 0.93 and hit_factor2 < 0.93:
940
- logger.debug("end get_hit_factor: hit_factors < 0.93")
1033
+ logger.debug("end check_symmetry_graph: hit_factors < 0.93")
941
1034
  return False # not ok
942
1035
 
943
1036
  logger.debug("end check_symmetry_graph: ok")
944
1037
  return True
945
1038
 
946
1039
  def sync_with_counterpart(self, cp_machine):
1040
+ logger.debug("sync_with_counterpart")
947
1041
  self.geom.sym_counterpart = cp_machine.get_symmetry_part()
948
1042
  self.geom.sym_part = self.get_symmetry_part()
1043
+ logger.debug("part/sym-part: self=%s/%s, cp=%s/%s",
1044
+ self.part, self.geom.sym_part,
1045
+ cp_machine.part, self.geom.sym_counterpart)
949
1046
  cp_machine.geom.sym_counterpart = self.get_symmetry_part()
950
1047
  cp_machine.geom.sym_part = cp_machine.get_symmetry_part()
951
1048
 
952
- def search_subregions(self):
1049
+ def search_subregions(self, single=False):
953
1050
  logger.debug("Search subregions")
954
- self.geom.search_subregions()
1051
+ self.geom.search_subregions(self.startangle, self.endangle, single=single)
1052
+
1053
+ def search_rotor_subregions(self, single=False):
1054
+ self.geom.search_rotor_subregions(self.startangle, self.endangle, single=single)
955
1055
 
956
- def rebuild_subregions(self):
1056
+ def search_stator_subregions(self, single=False):
1057
+ self.geom.search_stator_subregions(self.startangle, self.endangle, single=single)
1058
+
1059
+ def rebuild_subregions(self, single=False):
957
1060
  logger.debug("Rebuild subregions")
958
1061
  self.geom.set_edge_attributes()
959
1062
  self.geom.area_list = []
960
- self.geom.search_subregions()
1063
+ self.geom.search_subregions(self.startangle, self.endangle, single=single)
1064
+
1065
+ def has_windings(self):
1066
+ return self.geom.has_windings
1067
+
1068
+ def has_magnets(self):
1069
+ return self.geom.has_magnets
961
1070
 
962
1071
  def delete_tiny_elements(self, mindist):
963
- self.geom.delete_tiny_elements(mindist)
1072
+ return self.geom.delete_tiny_elements(mindist)
1073
+
1074
+ def search_critical_elements(self, mindist):
1075
+ self.geom.search_critical_elements(mindist)
964
1076
 
965
1077
  def create_arc(self, radius,
966
1078
  color='red', linestyle='dotted',
@@ -975,15 +1087,24 @@ class Machine(object):
975
1087
  # self.geom.add_edge(arc.node1(4), arc.node2(4), arc)
976
1088
  return False
977
1089
 
1090
+ n = self.geom.find_nodes(pts[0], pts[1])
1091
+ angle1 = alpha_line(self.center, pts[0])
1092
+ angle2 = alpha_line(self.center, pts[1])
1093
+ if np.isclose(angle1, self.startangle, atol=1e-03):
1094
+ startangle = angle1
1095
+ endangle = angle2
1096
+ else:
1097
+ startangle = angle2
1098
+ endangle = angle1
978
1099
  arc = Arc(Element(center=self.center,
979
1100
  radius=radius,
980
- start_angle=self.startangle*180/np.pi,
981
- end_angle=self.endangle*180/np.pi),
1101
+ start_angle=startangle*180/np.pi,
1102
+ end_angle=endangle*180/np.pi),
982
1103
  color=color,
983
1104
  linestyle=linestyle)
984
1105
  arc.set_attribute(attr)
985
- n = self.geom.find_nodes(pts[0], pts[1])
986
- self.geom.add_edge(n[0], n[1], arc)
1106
+
1107
+ self.geom.add_or_join_edge(n[0], n[1], arc)
987
1108
  return True
988
1109
 
989
1110
  def get_iron_separator(self, radius_list):
@@ -1036,11 +1157,6 @@ class Machine(object):
1036
1157
  if self.create_arc(r[1]):
1037
1158
  radius = r[1]
1038
1159
  break
1039
- # else:
1040
- # sep_radius = self.get_iron_separator(radius_list)
1041
- # if sep_radius > 0.0:
1042
- # logger.debug("Iron Separator found: %s", sep_radius)
1043
- # radius = sep_radius
1044
1160
 
1045
1161
  # install line
1046
1162
  line = Line(
@@ -1054,10 +1170,73 @@ class Machine(object):
1054
1170
  self.geom.area_list = []
1055
1171
  logger.debug("create subregions again")
1056
1172
  self.geom.create_list_of_areas()
1057
- self.geom.search_subregions()
1173
+ self.geom.search_subregions(self.startangle, self.endangle)
1058
1174
 
1059
1175
  logger.debug("end create_mirror_lines_outside_windings")
1060
1176
 
1177
+ def create_inner_auxiliary_arcs(self):
1178
+ if not self.geom.is_inner:
1179
+ return False
1180
+
1181
+ ag_list = self.geom.detect_airgaps(self.center,
1182
+ self.startangle, self.endangle,
1183
+ atol=0.001,
1184
+ with_end=True)
1185
+ if not ag_list:
1186
+ return False
1187
+
1188
+ done = False
1189
+ radius_list = [(ag[0], (ag[0] + ag[1]) / 2, ag[1]) for ag in ag_list]
1190
+ min_mag, max_mag = self.geom.get_minmax_magnet()
1191
+ radius_list.sort()
1192
+ rmin, rmid, rmax = radius_list[0]
1193
+ start = 0
1194
+ for r in radius_list[1:]:
1195
+ if np.isclose(rmax, r[0]):
1196
+ # SHAFT
1197
+ rmin, rmid, rmax = r
1198
+ start = 1
1199
+ break
1200
+
1201
+ for r in radius_list[start:]:
1202
+ if (r[2] - r[0]) > 4:
1203
+ radius = (r[1] + r[2]) / 2
1204
+ elif (r[2] - r[1]) > 0.5:
1205
+ radius = r[1]
1206
+ else:
1207
+ radius = min_mag + 1
1208
+ if radius < min_mag:
1209
+ self.create_arc(radius, attr='iron_sep', color='black')
1210
+ done = True
1211
+ return done
1212
+
1213
+ def create_mirror_lines_outside_magnets(self):
1214
+ logger.debug("create_mirror_lines_outside_magnets")
1215
+
1216
+ rebuild = self.create_inner_auxiliary_arcs()
1217
+
1218
+ if not self.geom.has_areas_touching_both_sides():
1219
+ logger.debug("end create_mirror_lines_outside_magnets: not done")
1220
+ return rebuild
1221
+
1222
+ radius = self.radius+10
1223
+ midangle = middle_angle(self.startangle, self.endangle)
1224
+ line = Line(
1225
+ Element(start=self.center,
1226
+ end=point(self.center, radius, midangle)))
1227
+
1228
+ pts = self.geom.split_and_get_intersect_points(line)
1229
+ pts.sort()
1230
+
1231
+ if self.geom.create_lines_outside_magnets(pts):
1232
+ rebuild = True
1233
+
1234
+ logger.debug("end create_mirror_lines_outside_magnets")
1235
+ return rebuild
1236
+
1237
+ def create_inner_corner_areas(self):
1238
+ self.geom.create_inner_corner_areas(self.startangle, self.endangle)
1239
+
1061
1240
  def check_and_correct_geom(self, what):
1062
1241
  geom = self.geom.check_geom(what)
1063
1242
  if geom:
@@ -8,6 +8,7 @@
8
8
  """
9
9
  import numpy as np
10
10
  from .geom import convex_hull
11
+ from .functions import distance
11
12
  import logging
12
13
  try:
13
14
  import matplotlib
@@ -32,9 +33,9 @@ class PlotRenderer(object):
32
33
  import matplotlib # throws exception
33
34
  pass
34
35
 
35
- def figure(self):
36
+ def figure(self, figsize=(9, 10)):
36
37
  if self.fig is None:
37
- self.fig = pl.figure(figsize=(9, 10))
38
+ self.fig = pl.figure(figsize=figsize)
38
39
  # facecolor='lightblue'
39
40
  if matplotlibversion > 2:
40
41
  pl.tight_layout(h_pad=0.2, w_pad=0.2)
@@ -97,6 +98,26 @@ class PlotRenderer(object):
97
98
  color=color,
98
99
  linestyle=linestyle))
99
100
 
101
+ def arrow(self, start, end,
102
+ color='black',
103
+ shape='full',
104
+ linewidth=2):
105
+ x0, y0 = start
106
+ x1, y1 = end
107
+ length = distance(start, end)
108
+ xd = x1 - x0
109
+ yd = y1 - y0
110
+ head_width = length * 0.25
111
+ head_length = length * 0.2
112
+ pl.arrow(x0, y0, xd, yd,
113
+ head_width=head_width,
114
+ head_length=head_length,
115
+ color=color,
116
+ shape=shape,
117
+ overhang=head_length/5,
118
+ length_includes_head=True,
119
+ linewidth=linewidth)
120
+
100
121
  def point(self, p, marker, color='blue'):
101
122
  pl.plot([p[0]], [p[1]], marker, color=color)
102
123
 
@@ -151,6 +172,7 @@ class PlotRenderer(object):
151
172
  self.ax.set_aspect('equal')
152
173
  if filename:
153
174
  pl.savefig(filename)
175
+ pl.close()
154
176
  else:
155
177
  pl.show()
156
178
 
@@ -183,8 +205,12 @@ class PlotRenderer(object):
183
205
  neighbors = kwargs.get('neighbors', False)
184
206
  draw_center = kwargs.get('draw_center', False)
185
207
  draw_inside = kwargs.get('draw_inside', False)
208
+ draw_groups = kwargs.get('draw_groups', False)
209
+ draw_phi = kwargs.get('draw_phi', False)
210
+ critical = kwargs.get('critical', False)
186
211
  fill_areas = kwargs.get('fill_areas', False)
187
212
  write_id = kwargs.get('write_id', False)
213
+ with_legend = kwargs.get('with_legend', True)
188
214
  title = kwargs.get('title', "")
189
215
  show = kwargs.get('show', True)
190
216
  write_png = kwargs.get('png', False)
@@ -256,7 +282,7 @@ class PlotRenderer(object):
256
282
 
257
283
  if fill_areas:
258
284
  handles = geom.render_area_fill(self)
259
- if handles:
285
+ if handles and with_legend:
260
286
  legend = pl.legend(handles=handles, loc='best',
261
287
  fancybox=True,
262
288
  framealpha=1.0,
@@ -269,6 +295,8 @@ class PlotRenderer(object):
269
295
  for e in geom.elements(type):
270
296
  e.render(self, 'blue', with_nodes)
271
297
 
298
+ if draw_groups:
299
+ geom.render_areagroups(self)
272
300
  geom.render_cut_lines(self)
273
301
  geom.render_airgaps(self)
274
302
  if neighbors:
@@ -278,6 +306,12 @@ class PlotRenderer(object):
278
306
  for p in points:
279
307
  self.point(p, 'o', color='red')
280
308
 
309
+ if draw_phi:
310
+ geom.render_magnet_phi(self)
311
+
312
+ if critical:
313
+ geom.render_critical(self)
314
+
281
315
  if with_center and geom.center:
282
316
  self.point(geom.center, 'o', color='darkgreen')
283
317
  x_min = min(x_min, geom.center[0]-5)
@@ -375,3 +409,4 @@ class PlotRenderer(object):
375
409
  filename = '{}.png'.format(name)
376
410
  fig = self.figure()
377
411
  fig.savefig(filename)
412
+ pl.close()