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.
- femagtools/__init__.py +2 -2
- femagtools/bch.py +1 -1
- femagtools/dxfsl/area.py +343 -406
- femagtools/dxfsl/areabuilder.py +139 -12
- femagtools/dxfsl/conv.py +27 -9
- femagtools/dxfsl/converter.py +406 -127
- femagtools/dxfsl/corner.py +3 -0
- femagtools/dxfsl/femparser.py +1 -1
- femagtools/dxfsl/fslrenderer.py +290 -246
- femagtools/dxfsl/functions.py +4 -2
- femagtools/dxfsl/geom.py +1204 -893
- femagtools/dxfsl/journal.py +58 -22
- femagtools/dxfsl/machine.py +254 -75
- femagtools/dxfsl/plotrenderer.py +38 -3
- femagtools/dxfsl/shape.py +380 -103
- femagtools/dxfsl/symmetry.py +679 -110
- femagtools/femag.py +27 -2
- femagtools/forcedens.py +65 -40
- femagtools/fsl.py +71 -28
- femagtools/losscoeffs.py +46 -0
- femagtools/machine/effloss.py +8 -1
- femagtools/machine/im.py +3 -1
- femagtools/machine/pm.py +11 -7
- femagtools/machine/sizing.py +15 -12
- femagtools/machine/sm.py +114 -33
- femagtools/machine/utils.py +38 -34
- femagtools/model.py +12 -2
- femagtools/moo/population.py +1 -1
- femagtools/parstudy.py +17 -1
- femagtools/plot/__init__.py +1 -1
- femagtools/plot/char.py +24 -7
- femagtools/plot/forcedens.py +56 -29
- femagtools/plot/mcv.py +4 -1
- femagtools/plot/phasor.py +6 -1
- femagtools/poc.py +17 -10
- femagtools/templates/cogg_calc.mako +7 -1
- femagtools/templates/displ_stator_rotor.mako +33 -0
- femagtools/templates/fieldcalc.mako +10 -16
- femagtools/templates/pm_sym_f_cur.mako +1 -1
- femagtools/tks.py +3 -9
- {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/LICENSE +1 -0
- {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/METADATA +7 -4
- {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/RECORD +51 -50
- {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/WHEEL +1 -1
- tests/engines/__init__.py +0 -20
- tests/geom/__init__.py +0 -20
- tests/moo/__init__.py +0 -20
- tests/test_model.py +8 -1
- tests/test_sizing.py +2 -2
- {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/entry_points.txt +0 -0
- {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/top_level.txt +0 -0
femagtools/dxfsl/machine.py
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
526
|
-
|
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
|
530
|
-
logger.debug("
|
531
|
-
|
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,
|
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=
|
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
|
-
|
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
|
-
|
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
|
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
|
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
|
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
|
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=
|
981
|
-
end_angle=
|
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
|
-
|
986
|
-
self.geom.
|
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:
|
femagtools/dxfsl/plotrenderer.py
CHANGED
@@ -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=
|
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()
|