femagtools 1.6.7__py3-none-any.whl → 1.7.0__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 (50) hide show
  1. femagtools/__init__.py +2 -2
  2. femagtools/bch.py +1 -1
  3. femagtools/dxfsl/area.py +334 -332
  4. femagtools/dxfsl/areabuilder.py +131 -10
  5. femagtools/dxfsl/conv.py +27 -9
  6. femagtools/dxfsl/converter.py +390 -125
  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 +1120 -886
  12. femagtools/dxfsl/journal.py +53 -22
  13. femagtools/dxfsl/machine.py +250 -74
  14. femagtools/dxfsl/plotrenderer.py +34 -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 +12 -11
  24. femagtools/machine/sizing.py +14 -11
  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.7.dist-info → femagtools-1.7.0.dist-info}/LICENSE +1 -0
  42. {femagtools-1.6.7.dist-info → femagtools-1.7.0.dist-info}/METADATA +7 -4
  43. {femagtools-1.6.7.dist-info → femagtools-1.7.0.dist-info}/RECORD +50 -49
  44. tests/engines/__init__.py +0 -20
  45. tests/geom/__init__.py +0 -20
  46. tests/moo/__init__.py +0 -20
  47. tests/test_model.py +8 -1
  48. {femagtools-1.6.7.dist-info → femagtools-1.7.0.dist-info}/WHEEL +0 -0
  49. {femagtools-1.6.7.dist-info → femagtools-1.7.0.dist-info}/entry_points.txt +0 -0
  50. {femagtools-1.6.7.dist-info → femagtools-1.7.0.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,42 +1006,67 @@ 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)
1055
+
1056
+ def search_stator_subregions(self, single=False):
1057
+ self.geom.search_stator_subregions(self.startangle, self.endangle, single=single)
955
1058
 
956
- def rebuild_subregions(self):
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
1072
  self.geom.delete_tiny_elements(mindist)
@@ -975,15 +1084,24 @@ class Machine(object):
975
1084
  # self.geom.add_edge(arc.node1(4), arc.node2(4), arc)
976
1085
  return False
977
1086
 
1087
+ n = self.geom.find_nodes(pts[0], pts[1])
1088
+ angle1 = alpha_line(self.center, pts[0])
1089
+ angle2 = alpha_line(self.center, pts[1])
1090
+ if np.isclose(angle1, self.startangle, atol=1e-03):
1091
+ startangle = angle1
1092
+ endangle = angle2
1093
+ else:
1094
+ startangle = angle2
1095
+ endangle = angle1
978
1096
  arc = Arc(Element(center=self.center,
979
1097
  radius=radius,
980
- start_angle=self.startangle*180/np.pi,
981
- end_angle=self.endangle*180/np.pi),
1098
+ start_angle=startangle*180/np.pi,
1099
+ end_angle=endangle*180/np.pi),
982
1100
  color=color,
983
1101
  linestyle=linestyle)
984
1102
  arc.set_attribute(attr)
985
- n = self.geom.find_nodes(pts[0], pts[1])
986
- self.geom.add_edge(n[0], n[1], arc)
1103
+
1104
+ self.geom.add_or_join_edge(n[0], n[1], arc)
987
1105
  return True
988
1106
 
989
1107
  def get_iron_separator(self, radius_list):
@@ -1036,11 +1154,6 @@ class Machine(object):
1036
1154
  if self.create_arc(r[1]):
1037
1155
  radius = r[1]
1038
1156
  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
1157
 
1045
1158
  # install line
1046
1159
  line = Line(
@@ -1054,10 +1167,73 @@ class Machine(object):
1054
1167
  self.geom.area_list = []
1055
1168
  logger.debug("create subregions again")
1056
1169
  self.geom.create_list_of_areas()
1057
- self.geom.search_subregions()
1170
+ self.geom.search_subregions(self.startangle, self.endangle)
1058
1171
 
1059
1172
  logger.debug("end create_mirror_lines_outside_windings")
1060
1173
 
1174
+ def create_inner_auxiliary_arcs(self):
1175
+ if not self.geom.is_inner:
1176
+ return False
1177
+
1178
+ ag_list = self.geom.detect_airgaps(self.center,
1179
+ self.startangle, self.endangle,
1180
+ atol=0.001,
1181
+ with_end=True)
1182
+ if not ag_list:
1183
+ return False
1184
+
1185
+ done = False
1186
+ radius_list = [(ag[0], (ag[0] + ag[1]) / 2, ag[1]) for ag in ag_list]
1187
+ min_mag, max_mag = self.geom.get_minmax_magnet()
1188
+ radius_list.sort()
1189
+ rmin, rmid, rmax = radius_list[0]
1190
+ start = 0
1191
+ for r in radius_list[1:]:
1192
+ if np.isclose(rmax, r[0]):
1193
+ # SHAFT
1194
+ rmin, rmid, rmax = r
1195
+ start = 1
1196
+ break
1197
+
1198
+ for r in radius_list[start:]:
1199
+ if (r[2] - r[0]) > 4:
1200
+ radius = (r[1] + r[2]) / 2
1201
+ elif (r[2] - r[1]) > 0.5:
1202
+ radius = r[1]
1203
+ else:
1204
+ radius = min_mag + 1
1205
+ if radius < min_mag:
1206
+ self.create_arc(radius, attr='iron_sep', color='black')
1207
+ done = True
1208
+ return done
1209
+
1210
+ def create_mirror_lines_outside_magnets(self):
1211
+ logger.debug("create_mirror_lines_outside_magnets")
1212
+
1213
+ rebuild = self.create_inner_auxiliary_arcs()
1214
+
1215
+ if not self.geom.has_areas_touching_both_sides():
1216
+ logger.debug("end create_mirror_lines_outside_magnets: not done")
1217
+ return rebuild
1218
+
1219
+ radius = self.radius+10
1220
+ midangle = middle_angle(self.startangle, self.endangle)
1221
+ line = Line(
1222
+ Element(start=self.center,
1223
+ end=point(self.center, radius, midangle)))
1224
+
1225
+ pts = self.geom.split_and_get_intersect_points(line)
1226
+ pts.sort()
1227
+
1228
+ if self.geom.create_lines_outside_magnets(pts):
1229
+ rebuild = True
1230
+
1231
+ logger.debug("end create_mirror_lines_outside_magnets")
1232
+ return rebuild
1233
+
1234
+ def create_inner_corner_areas(self):
1235
+ self.geom.create_inner_corner_areas(self.startangle, self.endangle)
1236
+
1061
1237
  def check_and_correct_geom(self, what):
1062
1238
  geom = self.geom.check_geom(what)
1063
1239
  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,11 @@ 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)
186
210
  fill_areas = kwargs.get('fill_areas', False)
187
211
  write_id = kwargs.get('write_id', False)
212
+ with_legend = kwargs.get('with_legend', True)
188
213
  title = kwargs.get('title', "")
189
214
  show = kwargs.get('show', True)
190
215
  write_png = kwargs.get('png', False)
@@ -256,7 +281,7 @@ class PlotRenderer(object):
256
281
 
257
282
  if fill_areas:
258
283
  handles = geom.render_area_fill(self)
259
- if handles:
284
+ if handles and with_legend:
260
285
  legend = pl.legend(handles=handles, loc='best',
261
286
  fancybox=True,
262
287
  framealpha=1.0,
@@ -269,6 +294,8 @@ class PlotRenderer(object):
269
294
  for e in geom.elements(type):
270
295
  e.render(self, 'blue', with_nodes)
271
296
 
297
+ if draw_groups:
298
+ geom.render_areagroups(self)
272
299
  geom.render_cut_lines(self)
273
300
  geom.render_airgaps(self)
274
301
  if neighbors:
@@ -278,6 +305,9 @@ class PlotRenderer(object):
278
305
  for p in points:
279
306
  self.point(p, 'o', color='red')
280
307
 
308
+ if draw_phi:
309
+ geom.render_magnet_phi(self)
310
+
281
311
  if with_center and geom.center:
282
312
  self.point(geom.center, 'o', color='darkgreen')
283
313
  x_min = min(x_min, geom.center[0]-5)
@@ -375,3 +405,4 @@ class PlotRenderer(object):
375
405
  filename = '{}.png'.format(name)
376
406
  fig = self.figure()
377
407
  fig.savefig(filename)
408
+ pl.close()