femagtools 1.3.0__py3-none-any.whl → 1.3.2__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 (47) hide show
  1. femagtools/__init__.py +1 -1
  2. femagtools/airgap.py +11 -37
  3. femagtools/amela.py +148 -13
  4. femagtools/bch.py +19 -3
  5. femagtools/dxfsl/area.py +68 -15
  6. femagtools/dxfsl/converter.py +15 -6
  7. femagtools/dxfsl/fslrenderer.py +13 -8
  8. femagtools/dxfsl/functions.py +1 -1
  9. femagtools/dxfsl/geom.py +415 -62
  10. femagtools/dxfsl/machine.py +97 -5
  11. femagtools/dxfsl/shape.py +46 -2
  12. femagtools/ecloss.py +393 -0
  13. femagtools/femag.py +25 -1
  14. femagtools/fsl.py +3 -2
  15. femagtools/hxy.py +126 -0
  16. femagtools/isa7.py +37 -24
  17. femagtools/machine/__init__.py +14 -13
  18. femagtools/machine/effloss.py +153 -32
  19. femagtools/machine/im.py +137 -56
  20. femagtools/machine/pm.py +584 -202
  21. femagtools/machine/sm.py +218 -64
  22. femagtools/machine/utils.py +12 -8
  23. femagtools/mcv.py +6 -8
  24. femagtools/model.py +11 -1
  25. femagtools/parstudy.py +1 -1
  26. femagtools/plot.py +159 -35
  27. femagtools/templates/afm_rotor.mako +102 -0
  28. femagtools/templates/afm_stator.mako +141 -0
  29. femagtools/templates/airgapinduc.mako +3 -3
  30. femagtools/templates/basic_modpar.mako +23 -2
  31. femagtools/templates/cogg_calc.mako +28 -5
  32. femagtools/templates/cu_losses.mako +1 -1
  33. femagtools/templates/fieldcalc.mako +39 -0
  34. femagtools/templates/gen_winding.mako +52 -47
  35. femagtools/templates/mesh-airgap.mako +43 -0
  36. femagtools/templates/stator3Linear.mako +5 -4
  37. femagtools/templates/therm-dynamic.mako +12 -6
  38. femagtools/templates/therm-static.mako +12 -0
  39. femagtools/templates/torq_calc.mako +2 -4
  40. femagtools/utils.py +45 -0
  41. femagtools/windings.py +2 -1
  42. {femagtools-1.3.0.dist-info → femagtools-1.3.2.dist-info}/METADATA +1 -1
  43. {femagtools-1.3.0.dist-info → femagtools-1.3.2.dist-info}/RECORD +47 -41
  44. {femagtools-1.3.0.dist-info → femagtools-1.3.2.dist-info}/WHEEL +1 -1
  45. {femagtools-1.3.0.dist-info → femagtools-1.3.2.dist-info}/LICENSE +0 -0
  46. {femagtools-1.3.0.dist-info → femagtools-1.3.2.dist-info}/entry_points.txt +0 -0
  47. {femagtools-1.3.0.dist-info → femagtools-1.3.2.dist-info}/top_level.txt +0 -0
femagtools/dxfsl/geom.py CHANGED
@@ -276,6 +276,32 @@ def lw_polyline(entity, lf, xoff=0.0, yoff=0.0, rotation=0.0):
276
276
  xoff=xoff, yoff=yoff,
277
277
  rotation=rotation)
278
278
 
279
+ def ellipse(entity, lf, xoff=0.0, yoff=0.0, rotation=0.0):
280
+ w = np.linalg.norm(entity.major_axis) * 2
281
+ h = entity.ratio * w
282
+ theta = np.arctan2(entity.major_axis[1], entity.major_axis[0])
283
+ start_angle = entity.start_param
284
+ end_angle = entity.end_param
285
+ if end_angle < start_angle:
286
+ end_angle += 2*np.pi
287
+ alfa = np.linspace(start_angle, end_angle, 20)
288
+ x = 0.5 * w * np.cos(alfa)
289
+ y = 0.5 * h * np.sin(alfa)
290
+ R = np.array([
291
+ [np.cos(theta), -np.sin(theta)],
292
+ [np.sin(theta), np.cos(theta)]
293
+ ])
294
+ x, y = np.dot(R, [x, y])
295
+ x += entity.center[0]
296
+ y += entity.center[1]
297
+ points = np.array((x,y)).T
298
+ p1 = points[0]
299
+ for p2 in points[1:]:
300
+ yield Line(Element(start=p1, end=p2), lf,
301
+ xoff=xoff, yoff=yoff,
302
+ rotation=rotation)
303
+ p1 = p2
304
+
279
305
 
280
306
  def spline(entity, lf, min_dist=0.001, xoff=0.0, yoff=0.0, rotation=0.0):
281
307
  if False:
@@ -493,22 +519,26 @@ def dxfshapes(dxffile, mindist=0.01, layers=[]):
493
519
  for l in insert_block(dwg, e, lf, rf, block, min_dist=mindist):
494
520
  yield l
495
521
  elif e.dxftype == 'ELLIPSE':
496
- w = np.linalg.norm(e.major_axis) * 2
497
- h = e.ratio * w
498
- rtheta = np.arctan2(e.major_axis[1], e.major_axis[0])
499
- angle = rtheta*180/np.pi
500
- start_angle = e.start_param*180/np.pi + angle
501
- end_angle = e.end_param*180/np.pi + angle
502
- arc = Arc(Element(center=e.center,
503
- radius=w/2,
504
- start_angle=start_angle,
505
- end_angle=end_angle,
506
- width=w,
507
- height=h,
508
- rtheta=rtheta,
509
- start_param=e.start_param,
510
- end_param=e.end_param))
511
- yield arc
522
+ for l in ellipse(e, lf):
523
+ yield l
524
+ #w = np.linalg.norm(e.major_axis) * 2
525
+ #h = e.ratio * w
526
+ #rtheta = np.arctan2(e.major_axis[1], e.major_axis[0])
527
+ #angle = rtheta*180/np.pi
528
+ #start_angle = e.start_param*180/np.pi + angle
529
+ #end_angle = e.end_param*180/np.pi + angle
530
+ #if end_angle < start_angle:
531
+ # end_angle += 360
532
+ #arc = Arc(Element(center=e.center,
533
+ # radius=w/2,
534
+ # start_angle=start_angle,
535
+ # end_angle=end_angle,
536
+ # width=w,
537
+ # height=h,
538
+ # rtheta=rtheta,
539
+ # start_param=e.start_param,
540
+ # end_param=e.end_param))
541
+ #yield arc
512
542
 
513
543
  elif e.dxftype == 'POINT':
514
544
  logger.debug("Id %d4: type %s ignored", id, e.dxftype)
@@ -817,6 +847,46 @@ class Geometry(object):
817
847
  for n, r in zip(self.g.nodes(), rotnodes)}
818
848
  nx.relabel_nodes(self.g, mapping, copy=False)
819
849
 
850
+ def check_geom(self, what):
851
+ logger.debug("check geometry of %s", what)
852
+ parts = int(round(np.pi * 2 / self.alfa, 1))
853
+ logger.debug(" --parts......: %s", parts)
854
+ logger.debug(" --ist alpha..: %s", self.alfa)
855
+ real_alfa = np.pi * 2 / parts
856
+ logger.debug(" --soll alpha.: %s", real_alfa)
857
+ if not np.isclose(self.alfa, real_alfa):
858
+ logger.debug(" --BAD angle ==> get corrected machine")
859
+ return self.correct_geom(real_alfa)
860
+ return None
861
+
862
+ def correct_geom(self, correct_alpha):
863
+ elements = []
864
+ for e in self.g.edges(data=True):
865
+ o = e[2]['object'].correct(self.alfa, correct_alpha, ndec)
866
+ elements.append(o)
867
+ geom = Geometry(elements, self.rtol, self.atol)
868
+ geom.center = self.center
869
+ geom.alfa = correct_alpha
870
+ geom.min_radius = self.min_radius
871
+ geom.max_radius = self.max_radius
872
+ geom.is_inner = self.is_inner
873
+ geom.kind = self.kind
874
+ geom.sym_part = self.sym_part
875
+ return geom
876
+
877
+ def log_geom(self):
878
+ logger.info("Kind............: %s", self.kind)
879
+ logger.info("Center..........: %s", self.center)
880
+ logger.info("Alpha...........: %s", self.alfa)
881
+ logger.info("Is Inner........: %s", self.is_inner)
882
+ logger.info("Is Outer........: %s", self.is_outer)
883
+ logger.info("Min Radius......: %s", self.min_radius)
884
+ logger.info("Max Radius......: %s", self.max_radius)
885
+ logger.info("Mirror Corners..: %s", self.mirror_corners)
886
+ logger.info("Start Corners...: %s", self.start_corners)
887
+ logger.info("End Corners.....: %s", self.end_corners)
888
+ logger.info("Edges...........: %s", self.num_edges)
889
+
820
890
  def scale(self, factor):
821
891
  """scales all objects"""
822
892
  for e in self.g.edges(data=True):
@@ -951,15 +1021,31 @@ class Geometry(object):
951
1021
  for e in edges:
952
1022
  self.remove_edge(e)
953
1023
 
954
- def add_line(self, n1, n2):
955
- line = Line(Element(start=n1, end=n2))
1024
+ def add_line(self, n1, n2, color=None):
1025
+ line = Line(Element(start=n1, end=n2), color=color)
956
1026
  add_or_join(self,
957
- line.node1(ndec),
958
- line.node2(ndec),
1027
+ n1,
1028
+ n2,
959
1029
  line,
960
1030
  self.rtol,
961
1031
  self.atol)
962
1032
 
1033
+ def add_arc(self, n1, n2, center, radius, color=None):
1034
+ angle_n1 = alpha_line(center, n1)
1035
+ angle_n2 = alpha_line(center, n2)
1036
+ arc = Arc(Element(center=center,
1037
+ radius=radius,
1038
+ start_angle=angle_n1*180/np.pi,
1039
+ end_angle=angle_n2*180/np.pi),
1040
+ color=color)
1041
+ add_or_join(self,
1042
+ n1,
1043
+ n2,
1044
+ arc,
1045
+ self.rtol,
1046
+ self.atol)
1047
+
1048
+
963
1049
  def elements(self, type):
964
1050
  """return lists of objects"""
965
1051
  return [e[2]['object'] for e in self.g.edges(data=True)
@@ -1077,6 +1163,36 @@ class Geometry(object):
1077
1163
  logger.debug("end of dist_end_min_corner: %s", d)
1078
1164
  return d
1079
1165
 
1166
+ def get_start_airgap_corner(self):
1167
+ if self.is_inner:
1168
+ p = (self.max_radius, 0.0)
1169
+ cp = self.start_corners[-1]
1170
+ else:
1171
+ p = (self.min_radius, 0.0)
1172
+ cp = self.start_corners[0]
1173
+ if points_are_close(p, cp, atol=0.5):
1174
+ return cp, True
1175
+ return p, False
1176
+
1177
+ def get_end_airgap_corner(self):
1178
+ if self.is_inner:
1179
+ p = point(self.center, self.max_radius, self.alfa, ndec)
1180
+ cp = self.end_corners[-1]
1181
+ else:
1182
+ p = point(self.center, self.min_radius, self.alfa, ndec)
1183
+ cp = self.end_corners[0]
1184
+ if points_are_close(p, cp, atol=0.5):
1185
+ return cp, True
1186
+ return p, False
1187
+
1188
+ def get_start_airgap_corner_point(self):
1189
+ p, b = self.get_start_airgap_corner()
1190
+ return Point(p)
1191
+
1192
+ def get_end_airgap_corner_point(self):
1193
+ p, b = self.get_end_airgap_corner()
1194
+ return Point(p)
1195
+
1080
1196
  def area_size(self):
1081
1197
  pts = [p for p in self.start_corners]
1082
1198
  end_pts = [p for p in reversed(self.end_corners)]
@@ -1357,7 +1473,7 @@ class Geometry(object):
1357
1473
 
1358
1474
  for n_angle, n_c, n_info_next in nbrs[1:]:
1359
1475
  n_info_next['angle'] = n_angle
1360
- if np.isclose(f_angle, n_angle):
1476
+ if np.isclose(f_angle, n_angle, 0.01, 0.01):
1361
1477
  logger.debug(" SAME DIRECTION")
1362
1478
  # ACHTUNG
1363
1479
  if self.is_lefthand_edge(alpha, f_info_next, n_info_next):
@@ -1401,7 +1517,7 @@ class Geometry(object):
1401
1517
  'alpha_n1': alpha_n1,
1402
1518
  'alpha_n2': e.get_alpha(n2),
1403
1519
  'alpha_start': normalise_angle(alpha_n1 + np.pi),
1404
- 'tracked': e_dict[x],
1520
+ 'tracked': e_dict.get(x, False),
1405
1521
  'reverse': False}
1406
1522
  return info
1407
1523
 
@@ -1427,9 +1543,9 @@ class Geometry(object):
1427
1543
  logger.debug(' node2 = %s', info['n2'])
1428
1544
  logger.debug(' x = %s', info['x'])
1429
1545
  logger.debug(' lock = (%s, %s, %s)',
1430
- info['data'][0],
1431
- info['data'][1],
1432
- info['data'][2])
1546
+ info['data'].get(0, False),
1547
+ info['data'].get(1, False),
1548
+ info['data'].get(2, False))
1433
1549
 
1434
1550
  def set_edge_tracked(self, info):
1435
1551
  x = info['x']
@@ -1540,6 +1656,16 @@ class Geometry(object):
1540
1656
  result['ok'] = True
1541
1657
  return result
1542
1658
 
1659
+ def set_edge_attributes(self):
1660
+ if nxversion == 1:
1661
+ nx.set_edge_attributes(self.g, 0, True)
1662
+ nx.set_edge_attributes(self.g, 1, False)
1663
+ nx.set_edge_attributes(self.g, 2, False)
1664
+ else:
1665
+ nx.set_edge_attributes(self.g, True, 0)
1666
+ nx.set_edge_attributes(self.g, False, 1)
1667
+ nx.set_edge_attributes(self.g, False, 2)
1668
+
1543
1669
  def create_list_of_areas(self, crunch=False):
1544
1670
  """ return list of areas for each node and their neighbors
1545
1671
  """
@@ -1554,15 +1680,7 @@ class Geometry(object):
1554
1680
  area_list.append(a)
1555
1681
 
1556
1682
  logger.debug("create new area list")
1557
-
1558
- if nxversion == 1:
1559
- nx.set_edge_attributes(self.g, 0, True)
1560
- nx.set_edge_attributes(self.g, 1, False)
1561
- nx.set_edge_attributes(self.g, 2, False)
1562
- else:
1563
- nx.set_edge_attributes(self.g, True, 0)
1564
- nx.set_edge_attributes(self.g, False, 1)
1565
- nx.set_edge_attributes(self.g, False, 2)
1683
+ self.set_edge_attributes()
1566
1684
 
1567
1685
  crunched = 0
1568
1686
  for n in self.g.nodes():
@@ -2081,11 +2199,20 @@ class Geometry(object):
2081
2199
  return self.alfa
2082
2200
 
2083
2201
  def __str__(self):
2202
+ real_alfa = 0
2203
+ if self.sym_part > 0:
2204
+ if self.is_mirrored():
2205
+ real_alfa = np.pi / self.sym_part
2206
+ else:
2207
+ real_alfa = 2*np.pi / self.sym_part
2084
2208
  return "name...........: {}\n".format(self._name) + \
2085
2209
  "kind...........: {}\n".format(self.kind) + \
2086
2210
  "sym_part.......: {}\n".format(self.sym_part) + \
2087
2211
  "sym_counterpart: {}\n".format(self.sym_counterpart) + \
2088
2212
  "alpha..........: {}\n".format(self.alfa) + \
2213
+ "alpha real.....: {}\n".format(real_alfa) + \
2214
+ "circle.........: {}\n".format(self.alfa * self.sym_part) + \
2215
+ "mirrored.......: {}\n".format(self.is_mirrored()) + \
2089
2216
  "radius.........: {} -- {}\n".format(self.min_radius,
2090
2217
  self.max_radius)
2091
2218
 
@@ -2550,7 +2677,7 @@ class Geometry(object):
2550
2677
  dist_max = max(dist_max, g[1])
2551
2678
  return airgaps
2552
2679
 
2553
- def detect_airgaps(self, center, startangle, endangle, atol):
2680
+ def detect_airgaps(self, center, startangle, endangle, atol=0.1, with_end=False):
2554
2681
  """ Die Funktion sucht Luftspalt-Kandidaten und liefert eine Liste
2555
2682
  von Möglichkeiten mit jeweils einem minimalen und einem maximalen
2556
2683
  Radius als Begrenzung des Luftspalts.
@@ -2570,6 +2697,8 @@ class Geometry(object):
2570
2697
  min_radius = self.min_radius + 1.0
2571
2698
  cur_radius = gaplist[0][1]
2572
2699
  max_radius = self.max_radius - 1.0
2700
+ if with_end:
2701
+ max_radius = self.max_radius + 1.0
2573
2702
 
2574
2703
  for g in gaplist:
2575
2704
  if greater(g[0], cur_radius) and \
@@ -2930,29 +3059,59 @@ class Geometry(object):
2930
3059
  shaft.type = 6 # iron shaft (Zahn)
2931
3060
  return
2932
3061
 
3062
+ def mark_connecting_edges(self, windings):
3063
+ logger.debug("begin of mark_connecting_edges")
3064
+ for a in windings:
3065
+ logger.debug("- id of winding: %s", a.identifier())
3066
+ for w in windings:
3067
+ if a.id != w.id:
3068
+ elist = [e for e in a.list_of_equal_edges(w)]
3069
+ logger.debug(" --> %s equal egdes", len(elist))
3070
+ for e in elist:
3071
+ e.init_attributes('lightblue', 'no_fsl')
3072
+
2933
3073
  def search_subregions(self):
2934
3074
  if self.is_stator():
2935
- return self.search_stator_subregions()
3075
+ self.search_stator_subregions()
3076
+ elif self.is_rotor():
3077
+ self.search_rotor_subregions()
3078
+ else:
3079
+ logger.warning("no stator or rotor assigned")
3080
+ self.search_unknown_subregions()
3081
+ self.looking_for_corners()
2936
3082
 
2937
- if self.is_rotor():
2938
- return self.search_rotor_subregions()
3083
+ def collect_windings(self):
3084
+ found = True
3085
+ while found:
3086
+ windings = [a for a in self.list_of_areas()
3087
+ if a.type == 2]
3088
+ bad_windings = [a for a in self.list_of_areas()
3089
+ if a.type == 12]
3090
+ if not bad_windings:
3091
+ return windings
2939
3092
 
2940
- logger.warning("no stator or rotor assigned")
2941
- return self.search_unknown_subregions()
3093
+ found = False
3094
+ for a in bad_windings:
3095
+ if a.is_touching_areas(windings):
3096
+ a.type = 2
3097
+ found = True
3098
+
3099
+ return [a for a in self.list_of_areas() if a.type == 2]
2942
3100
 
2943
3101
  def search_stator_subregions(self, place=''):
2944
- is_inner = self.is_inner
3102
+ logger.debug("Begin of search_stator_subregions")
3103
+
2945
3104
  if place == 'in':
2946
- is_inner = True
3105
+ self.is_inner = True
2947
3106
  elif place == 'out':
2948
- is_inner = False
3107
+ self.is_inner = False
2949
3108
 
2950
3109
  if self.alfa == 0.0:
2951
3110
  self.alfa = np.pi * 2.0
2952
3111
 
2953
3112
  stator_size = self.area_size()
2954
3113
  for area in self.list_of_areas():
2955
- area.mark_stator_subregions(is_inner,
3114
+ area.mark_stator_subregions(self.is_inner,
2956
3115
  stator_size,
2957
3116
  self.is_mirrored(),
2958
3117
  self.alfa,
@@ -2960,8 +3119,8 @@ class Geometry(object):
2960
3119
  self.min_radius,
2961
3120
  self.max_radius)
2962
3121
 
2963
- windings = [a for a in self.list_of_areas()
2964
- if a.type == 2]
3122
+ windings = self.collect_windings()
3123
+ [a.set_type(0) for a in self.list_of_areas() if a.type == 12]
2965
3124
  windings_found = len(windings)
2966
3125
  logger.info("%d windings found", windings_found)
2967
3126
 
@@ -2970,18 +3129,23 @@ class Geometry(object):
2970
3129
  windings_surface.sort(reverse=True)
2971
3130
  max_size = windings_surface[0][0]
2972
3131
  for sz, w in windings_surface:
3132
+ logger.debug("winding size = %s", sz)
2973
3133
  if sz / max_size < 0.95:
2974
3134
  w.set_type(0)
2975
-
3135
+ if sz / max_size < 0.2:
3136
+ windings_found -= 1
2976
3137
  windings = [a for a in self.list_of_areas()
2977
3138
  if a.is_winding()]
2978
3139
  if windings_found > 2 and len(windings) == 1:
3140
+ logger.info("no windings remaining")
2979
3141
  # no windings
2980
3142
  [w.set_type(0) for w in windings]
2981
3143
  [a.set_type(1) for a in self.list_of_areas() if a.is_iron()]
2982
3144
  windings = []
2983
3145
  elif len(windings) < windings_found:
2984
3146
  logger.info("%d windings remaining", len(windings))
3147
+ if len(windings) > 2:
3148
+ self.mark_connecting_edges(windings)
2985
3149
 
2986
3150
  wdg_min_angle = 99999
2987
3151
  wdg_max_angle = 0
@@ -3088,19 +3252,19 @@ class Geometry(object):
3088
3252
  self.check_shaft_area(shaft_areas[0])
3089
3253
 
3090
3254
  def search_rotor_subregions(self, place=''):
3091
- logger.debug("begin of search_rotor_subregions")
3092
- is_inner = self.is_inner
3255
+ logger.debug("Begin of search_rotor_subregions")
3256
+
3093
3257
  if place == 'in':
3094
- is_inner = True
3258
+ self.is_inner = True
3095
3259
  elif place == 'out':
3096
- is_inner = False
3260
+ self.is_inner = False
3097
3261
 
3098
3262
  if self.alfa == 0.0:
3099
3263
  self.alfa = np.pi * 2.0
3100
3264
 
3101
3265
  types = {}
3102
3266
  for area in self.list_of_areas():
3103
- t = area.mark_rotor_subregions(is_inner,
3267
+ t = area.mark_rotor_subregions(self.is_inner,
3104
3268
  self.is_mirrored(),
3105
3269
  self.alfa,
3106
3270
  self.center,
@@ -3230,7 +3394,21 @@ class Geometry(object):
3230
3394
  if a.surface < max_surface * 0.20: # too small
3231
3395
  a.set_type(0) # air
3232
3396
 
3233
- logger.debug("begin of search_unknown_subregions")
3397
+ logger.debug("end of search_unknown_subregions")
3398
+
3399
+ def looking_for_corners(self):
3400
+ if self.is_inner:
3401
+ logger.debug("looking_for_corners: inner")
3402
+ start_cp = self.start_corners[-1]
3403
+ end_cp = self.end_corners[-1]
3404
+ else:
3405
+ logger.debug("looking_for_corners: outer")
3406
+ start_cp = self.start_corners[0]
3407
+ end_cp = self.end_corners[0]
3408
+ logger.debug("looking_for_corners: start=%s, end=%s",
3409
+ start_cp, end_cp)
3410
+ for area in self.list_of_areas():
3411
+ area.mark_airgap_corners(start_cp, end_cp)
3234
3412
  return
3235
3413
 
3236
3414
  def num_areas_of_type(self, type):
@@ -3483,19 +3661,16 @@ class Geometry(object):
3483
3661
  c += self.remove_appendix(n2, nbrs[0], incr_text + '.')
3484
3662
  return c
3485
3663
 
3486
- def split_and_get_intersect_points(self, center, outer_radius, angle):
3664
+ def split_and_get_intersect_points(self, el, aktion=True):
3487
3665
  logger.debug("begin of split_and_get_intersect_points")
3488
3666
  rtol = 1e-03
3489
3667
  atol = 1e-03
3490
- line = Line(
3491
- Element(start=center,
3492
- end=point(center, outer_radius+1, angle)))
3493
3668
  points = []
3494
3669
  for e in self.elements(Shape):
3495
- pts = e.intersect_line(line,
3496
- rtol=rtol,
3497
- atol=atol,
3498
- include_end=True)
3670
+ pts = e.intersect_shape(el,
3671
+ rtol=rtol,
3672
+ atol=atol,
3673
+ include_end=True)
3499
3674
  if pts:
3500
3675
  pts_inside = []
3501
3676
  pts_real = []
@@ -3510,7 +3685,7 @@ class Geometry(object):
3510
3685
  pts_real.append(p)
3511
3686
  pts_inside.append(p)
3512
3687
 
3513
- if pts_inside:
3688
+ if pts_inside and aktion:
3514
3689
  self.remove_edge(e)
3515
3690
  elements = e.split(pts_inside, rtol, atol)
3516
3691
  for e in elements:
@@ -3533,6 +3708,31 @@ class Geometry(object):
3533
3708
  return True
3534
3709
  return False
3535
3710
 
3711
+ def inside_area_list(self, p):
3712
+ for area in self.list_of_areas():
3713
+ if area.is_point_inside(p):
3714
+ yield area
3715
+
3716
+ def critical_touch_point(self, points):
3717
+ logger.debug("looking for critical touch-point")
3718
+ winding_touched = False
3719
+ for p in points[1:]:
3720
+ d = distance(self.center, p)
3721
+ logger.debug("-- p = %s, dist = %s", p, d)
3722
+ for a in self.inside_area_list(p):
3723
+ logger.debug("-- Area type = %s", a.type)
3724
+ logger.debug(" min=%s, max= %s", a.min_dist, a.max_dist)
3725
+ logger.debug(" close to start = %s", a.close_to_startangle)
3726
+ logger.debug(" close to end = %s", a.close_to_endangle)
3727
+ if a.is_winding():
3728
+ winding_touched = True
3729
+ else:
3730
+ if winding_touched and greater(a.max_dist, d, atol=0.001):
3731
+ if not (a.close_to_startangle and a.close_to_endangle):
3732
+ logger.debug("-- return %s", p)
3733
+ return p
3734
+ return None
3735
+
3536
3736
  def create_lines_outside_windings(self, points):
3537
3737
  if not points:
3538
3738
  return False
@@ -3562,6 +3762,159 @@ class Geometry(object):
3562
3762
  return True
3563
3763
  return False
3564
3764
 
3765
+ def get_inner_airgap_line(self):
3766
+ logger.debug("begin of get_inner_airgap_line")
3767
+
3768
+ if not self.is_inner:
3769
+ logger.debug("end of get_inner_airgap_line: not inner")
3770
+ return []
3771
+ for a in self.area_list:
3772
+ logger.debug("%s", a)
3773
+ area = [a for a in self.area_list if a.close_to_ag_endcorner]
3774
+ if len(area) != 1:
3775
+ logger.debug("end of get_inner_airgap_line: %s areas found", len(area))
3776
+ return []
3777
+
3778
+ end_corner = self.end_corners[-1]
3779
+ logger.debug("END CORNER %s", end_corner)
3780
+ nodes = [n for n in area[0].list_of_nodes()]
3781
+ if not nodes:
3782
+ logger.debug("end of get_inner_airgap_line: no nodes found")
3783
+ return []
3784
+ n1 = nodes[0]
3785
+ if points_are_close(end_corner, n1):
3786
+ n2 = nodes[-1]
3787
+ else:
3788
+ n2 = n1
3789
+ for n1 in nodes[1:]:
3790
+ if points_are_close(end_corner, n1):
3791
+ break
3792
+ n2 = n1
3793
+
3794
+ if not points_are_close(end_corner, n1):
3795
+ logger.debug("end of get_inner_airgap_line: not close to endcorner")
3796
+ return []
3797
+
3798
+ start_corner = self.start_corners[-1]
3799
+
3800
+ logger.debug("EDGE FOUND: %s - %s", n1, n2)
3801
+ nodes = [n1, n2]
3802
+ info = self.get_edge_info(n1, n2)
3803
+ while not points_are_close(start_corner, n2):
3804
+ info = self.next_edge_lefthand_side(info)
3805
+ if not info:
3806
+ return []
3807
+ n2 = info['n2']
3808
+ nodes.append(n2)
3809
+
3810
+ logger.debug("end of get_inner_airgap_line #%s", len(nodes))
3811
+ return nodes
3812
+
3813
+ def create_corner_areas(self):
3814
+ self.set_edge_attributes()
3815
+ self.create_inner_corner_areas()
3816
+
3817
+ def create_and_append_area(self, n1, n2):
3818
+ rslt = self.get_new_area(n1, n2, False)
3819
+ logger.debug("create_and_append_area: %s", rslt)
3820
+ if rslt.get('ok', False):
3821
+ area = rslt['area']
3822
+ a = Area(area, self.center, 0.0)
3823
+ a.type = 0 # air
3824
+ self.area_list.append(a)
3825
+ return True
3826
+ logger.error("No area for air near airgap!!")
3827
+ return False
3828
+
3829
+ def create_inner_corner_areas(self):
3830
+ start_cp, start_exists = self.get_start_airgap_corner()
3831
+ end_cp, end_exists = self.get_end_airgap_corner()
3832
+ if start_exists and end_exists:
3833
+ return
3834
+ logger.info("*** Corner correction ***")
3835
+ airgap_line = self.get_inner_airgap_line()
3836
+ if not airgap_line:
3837
+ logger.debug("no airgapline found")
3838
+ return
3839
+
3840
+ logger.debug("airgapline found !!")
3841
+ airgap_nodes = [n for n in airgap_line[1:]]
3842
+ del airgap_nodes[-1]
3843
+ if not airgap_nodes:
3844
+ return # strange
3845
+
3846
+ if not start_exists:
3847
+ cp = self.start_corners[-1]
3848
+ logger.debug("Start Corner: %s -- %s", cp, start_cp)
3849
+ start_line = Line(Element(start=cp, end=start_cp), color='red')
3850
+ start_cp = start_line.node2(ndec)
3851
+ i = 0
3852
+ for n in airgap_nodes:
3853
+ i += 1
3854
+ if not self.search_intersection(i, self.max_radius,
3855
+ n, start_cp,
3856
+ airgap_nodes):
3857
+ d = distance(self.center, n)
3858
+ if np.isclose(d, self.max_radius):
3859
+ self.add_arc(start_cp, n, self.center, self.max_radius, color='red')
3860
+ else:
3861
+ self.add_line(start_cp, n, color='red')
3862
+ self.add_edge(cp, start_cp, start_line)
3863
+ self.create_and_append_area(start_cp, n)
3864
+ self.start_corners = self.get_corner_nodes(self.center,
3865
+ 0.0)
3866
+ break
3867
+
3868
+ if not end_exists:
3869
+ cp = self.end_corners[-1]
3870
+ logger.debug("End Corner: %s -- %s", cp, end_cp)
3871
+ end_line = Line(Element(start=cp, end=end_cp), color='red')
3872
+ end_cp = end_line.node2(ndec)
3873
+ airgap_nodes.reverse()
3874
+ i = 0
3875
+ for n in airgap_nodes:
3876
+ i += 1
3877
+ if not self.search_intersection(i, self.max_radius,
3878
+ n, end_cp,
3879
+ airgap_nodes):
3880
+ d = distance(self.center, n)
3881
+ if np.isclose(d, self.max_radius):
3882
+ self.add_arc(n, end_cp, self.center, self.max_radius, color='red')
3883
+ else:
3884
+ self.add_line(end_cp, n, color='red')
3885
+ self.add_edge(cp, end_cp, end_line)
3886
+ self.create_and_append_area(n, end_cp)
3887
+ self.end_corners = self.get_corner_nodes(self.center,
3888
+ self.alfa)
3889
+ break
3890
+
3891
+ def search_intersection(self, start_i, r, n1, n2, airgap_nodes):
3892
+ logger.debug("begin of search_intersection")
3893
+
3894
+ ag_line = Line(Element(start=n1, end=n2))
3895
+ for i in range(start_i, len(airgap_nodes)):
3896
+ n = airgap_nodes[i]
3897
+ alfa = alpha_line(self.center, n)
3898
+ dist_n = distance(self.center, n)
3899
+ p = point(self.center, r, alfa)
3900
+ line = Line(Element(start=self.center, end=p))
3901
+ pts = line.intersect_line(ag_line, include_end=True)
3902
+ if not pts:
3903
+ # no intersection
3904
+ return # ok
3905
+ if len(pts) != 1:
3906
+ logger.error("-- no intersection found ?!? %s", pts)
3907
+ logger.debug("end of search_intersection: bad")
3908
+ return True # fatal
3909
+ dist_p = distance(self.center, pts[0])
3910
+ logger.debug("-- check point %s[%s] -- %s[%s]", n, dist_n, pts[0], dist_p)
3911
+ if not less(dist_n, dist_p):
3912
+ logger.debug("end of search_intersection: found")
3913
+ return True # intersection
3914
+ logger.debug("-- dist %s <= %s", dist_n, dist_p)
3915
+ logger.debug("end of search_intersection: ok")
3916
+ return False # ok
3917
+
3565
3918
  def print_nodes(self):
3566
3919
  print("=== List of Nodes ({}) ===".format(self.number_of_nodes()))
3567
3920
  for n in self.g.nodes():