femagtools 1.7.9__py3-none-any.whl → 1.8.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 (43) hide show
  1. femagtools/__init__.py +1 -1
  2. femagtools/amela.py +2 -2
  3. femagtools/dxfsl/area.py +130 -26
  4. femagtools/dxfsl/conv.py +2 -14
  5. femagtools/dxfsl/converter.py +69 -12
  6. femagtools/dxfsl/fslrenderer.py +15 -13
  7. femagtools/dxfsl/geom.py +153 -82
  8. femagtools/dxfsl/journal.py +2 -2
  9. femagtools/dxfsl/machine.py +19 -15
  10. femagtools/dxfsl/shape.py +3 -0
  11. femagtools/ecloss.py +386 -2
  12. femagtools/femag.py +82 -9
  13. femagtools/fsl.py +52 -56
  14. femagtools/machine/pm.py +1 -1
  15. femagtools/machine/sm.py +16 -8
  16. femagtools/mcv.py +128 -124
  17. femagtools/me.py +13 -13
  18. femagtools/model.py +8 -2
  19. femagtools/plot/fieldlines.py +1 -1
  20. femagtools/plot/mcv.py +18 -0
  21. femagtools/plot/wdg.py +2 -2
  22. femagtools/svgfsl/converter.py +1 -1
  23. femagtools/templates/afm_rotor.mako +4 -0
  24. femagtools/templates/gen_hairpin_winding.mako +36 -45
  25. femagtools/templates/magnetIron.mako +1 -1
  26. femagtools/templates/magnetIron2.mako +1 -1
  27. femagtools/templates/magnetIron3.mako +1 -1
  28. femagtools/templates/magnetIron4.mako +1 -1
  29. femagtools/templates/magnetIron5.mako +1 -1
  30. femagtools/templates/magnetIronV.mako +1 -1
  31. femagtools/templates/magnetSector.mako +1 -1
  32. femagtools/templates/mesh-airgap.mako +12 -6
  33. femagtools/templates/prepare_thermal.mako +199 -61
  34. femagtools/windings.py +25 -20
  35. {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/METADATA +20 -20
  36. {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/RECORD +42 -43
  37. {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/WHEEL +1 -1
  38. tests/test_mcv.py +106 -1
  39. tests/test_windings.py +5 -0
  40. tests/test_mcvwriter.py +0 -96
  41. {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/LICENSE +0 -0
  42. {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/entry_points.txt +0 -0
  43. {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/top_level.txt +0 -0
femagtools/dxfsl/geom.py CHANGED
@@ -811,6 +811,10 @@ class Geometry(object):
811
811
  def get_neighbors(self, n):
812
812
  return [nbr for nbr in self.g.neighbors(n)]
813
813
 
814
+ def num_of_neighbors(self, n):
815
+ nbrs = [nbr for nbr in self.g.neighbors(n)]
816
+ return len(nbrs)
817
+
814
818
  def angle_nodes(self, center, angle, rtol, atol):
815
819
  if np.isclose(abs(angle), np.pi, rtol, atol):
816
820
  angle_func = positive_angle
@@ -868,8 +872,8 @@ class Geometry(object):
868
872
  logger.debug("begin of dist_end_max_corner")
869
873
  logger.debug("end corners: %s", self.end_corners)
870
874
 
871
- #if self.is_mirrored():
872
- # return self.dist_start_max_corner()
875
+ if self.is_mirrored():
876
+ return self.dist_start_max_corner()
873
877
  d = distance(self.center, self.end_corners[-1])
874
878
  logger.debug("end of dist_end_max_corner: %s", d)
875
879
  return d
@@ -1845,14 +1849,22 @@ class Geometry(object):
1845
1849
  return []
1846
1850
 
1847
1851
  def reduce_winding_nodes(self, mindist=0.01):
1852
+ return self.reduce_element_nodes(mindist=mindist,
1853
+ area_types=(AREA.TYPE_WINDINGS,))
1854
+
1855
+ def reduce_element_nodes(self, mindist=0.01, area_types=()):
1856
+ timer = Timer(start_it=True)
1857
+ nodes_deleted = 0
1848
1858
  for area in self.list_of_areas():
1849
- if area.is_winding():
1850
- reduced_shapes = area.reduce_nodes(mindist)
1851
- if reduced_shapes:
1852
- area.remove_edges(self.g, ndec)
1853
- area.area = reduced_shapes
1854
- for r in reduced_shapes:
1855
- self.add_element(r, rtol=self.rtol, atol=self.atol)
1859
+ if not area_types or area.type in area_types:
1860
+ nodes_deleted += area.reduce_element_nodes(self, mindist)
1861
+
1862
+ t = timer.stop("-- {} nodes deleted in %0.4f seconds --".format(nodes_deleted))
1863
+ self.journal.put('time_deleting_nodes', t)
1864
+ if nodes_deleted:
1865
+ self.journal.put('nodes_deleted', nodes_deleted)
1866
+ self.area_list = []
1867
+ return nodes_deleted > 0
1856
1868
 
1857
1869
  def render_areagroups(self, renderer):
1858
1870
  if not self.areagroup_list:
@@ -2741,7 +2753,7 @@ class Geometry(object):
2741
2753
  intersection = False
2742
2754
  inner_gap_list = []
2743
2755
  for no_a in my_notouch:
2744
- if no_a.intersect_line(line):
2756
+ if no_a.intersect_area(line):
2745
2757
  intersection = True
2746
2758
  logger.debug(" --> intersection with %s",
2747
2759
  no_a.get_id())
@@ -2805,6 +2817,7 @@ class Geometry(object):
2805
2817
  pts = self.split_and_get_intersect_points(line)
2806
2818
  if len(pts) != 2:
2807
2819
  logger.error("ERROR in create_aux_lines()")
2820
+ self.journal.put("warning", "Error while creating auxiliary lines")
2808
2821
  logger.debug("Points: %s", pts)
2809
2822
  logger.debug("Line: %s", line)
2810
2823
 
@@ -3598,6 +3611,16 @@ class Geometry(object):
3598
3611
  return True
3599
3612
  return False
3600
3613
 
3614
+ def windings_in_the_middle(self, midangle):
3615
+ wdg_areas = [a for a in self.list_of_areas()
3616
+ if a.is_winding()]
3617
+ logger.info("%s windings in geom", len(wdg_areas))
3618
+ for a in wdg_areas:
3619
+ if greater(a.max_angle, midangle) and \
3620
+ less(a.min_angle, midangle):
3621
+ return True
3622
+ return False
3623
+
3601
3624
  def looking_for_corners(self):
3602
3625
  if self.is_inner:
3603
3626
  logger.debug("looking_for_corners: inner")
@@ -3613,16 +3636,21 @@ class Geometry(object):
3613
3636
  area.mark_airgap_corners(start_cp, end_cp)
3614
3637
  return
3615
3638
 
3616
- def num_areas_of_type(self, type):
3639
+ def num_areas_of_type(self, types=()):
3617
3640
  return len([area for area in self.list_of_areas()
3618
- if area.is_type(type)])
3641
+ if area.type in types])
3619
3642
 
3620
3643
  def area_size_of_type(self, type):
3621
3644
  return sum([area.surface for area in self.list_of_areas()
3622
3645
  if area.is_type(type)])*1e-3
3623
3646
 
3624
3647
  def num_of_windings(self):
3625
- return self.num_areas_of_type(AREA.TYPE_WINDINGS)
3648
+ return self.num_areas_of_type((AREA.TYPE_WINDINGS,))
3649
+
3650
+ def num_of_irons(self):
3651
+ return self.num_areas_of_type((AREA.TYPE_IRON,
3652
+ AREA.TYPE_YOKE,
3653
+ AREA.TYPE_TOOTH,))
3626
3654
 
3627
3655
  def area_close_to_endangle(self, type):
3628
3656
  return len([area for area in self.list_of_areas()
@@ -4184,9 +4212,9 @@ class Geometry(object):
4184
4212
  if not ok1: # fatal => ignore
4185
4213
  logger.debug("end repair_border_line: missing point %s", n1)
4186
4214
  return False
4187
- d1, n1, ok1 = nodes[-1]
4188
- if not ok1: # fatal => ignore
4189
- logger.debug("end repair_border_line: missing point %s", n1)
4215
+ d2, n2, ok2 = nodes[-1]
4216
+ if not ok2: # fatal => ignore
4217
+ logger.debug("end repair_border_line: missing point %s", n2)
4190
4218
  return False
4191
4219
 
4192
4220
  remove_n1 = None
@@ -4218,89 +4246,132 @@ class Geometry(object):
4218
4246
  logger.debug("end repair_border_line")
4219
4247
  return True
4220
4248
 
4221
- def create_boundery_nodes(self,
4249
+ def create_boundary_nodes(self,
4222
4250
  center,
4223
4251
  startangle,
4224
4252
  endangle,
4225
4253
  rtol=None, atol=None):
4254
+ logger.debug("begin of create_boundary_nodes")
4226
4255
  if not rtol:
4227
- rtol = 1e-4
4256
+ rtol = 1e-3
4228
4257
  if not atol:
4229
4258
  atol = 1e-3
4230
4259
 
4231
- start_nodes = [n for n in self.angle_nodes(center, startangle, rtol, atol)]
4232
- end_nodes = [n for n in self.angle_nodes(center, endangle, rtol, atol)]
4233
- alpha = alpha_angle(startangle, endangle)
4234
-
4235
- logger.debug("begin of create_boundery_nodes")
4236
- start_rot_nodes = self.rotate_nodes(alpha, start_nodes)
4237
- end_rot_nodes = self.rotate_nodes(-alpha, end_nodes)
4238
-
4239
- def miss_nodelist(src_nodelist, dest_nodelist):
4240
- nlist = []
4241
- for src_n in src_nodelist:
4242
- ok = False
4243
- for dest_n in dest_nodelist:
4244
- if points_are_close(src_n, dest_n, rtol=rtol, atol=atol):
4245
- ok = True
4246
- break
4247
- if not ok:
4248
- nlist.append(src_n)
4249
- return nlist
4250
-
4251
- logger.debug("Begin with Nodes Start=%s, End=%s", len(start_nodes), len(end_nodes))
4252
-
4253
- missing_end_nodes = miss_nodelist(start_rot_nodes, end_nodes)
4254
- missing_start_nodes = miss_nodelist(end_rot_nodes, start_nodes)
4255
-
4256
- if missing_start_nodes:
4257
- logger.debug("%s missing start nodes", len(missing_start_nodes))
4258
- start_nodes = [(distance(center, n), n, True) for n in start_nodes]
4259
- for n in missing_start_nodes:
4260
- start_nodes.append((distance(center, n), n, False))
4261
- start_nodes.sort()
4262
- if not self.repair_border_line(start_nodes):
4263
- logger.debug("end of create_boundery_nodes (failed)")
4264
- return
4265
- else:
4266
- start_nodes = [(distance(center, n), n, True) for n in start_nodes]
4267
- start_nodes.sort()
4268
-
4269
- if missing_end_nodes:
4270
- logger.debug("%s missing end nodes", len(missing_end_nodes))
4271
- end_nodes = [(distance(center, n), n, True) for n in end_nodes]
4272
- for n in missing_end_nodes:
4273
- end_nodes.append((distance(center, n), n, False))
4274
- end_nodes.sort()
4275
- if not self.repair_border_line(end_nodes):
4276
- logger.debug("end of create_boundery_nodes (failed)")
4277
- return
4278
- else:
4279
- end_nodes = [(distance(center, n), n, True) for n in end_nodes]
4280
- end_nodes.sort()
4260
+ def check_line(nlist):
4261
+ d, n1, b = nlist[0]
4262
+ for d, n2, b in nlist[1:]:
4263
+ if not self.get_edge_element(n1, n2):
4264
+ return False
4265
+ n1 = n2
4266
+ return True
4281
4267
 
4282
- start_nodes = [(distance(center, n), n)
4268
+ start_nodes = [(distance(center, n), n, True)
4283
4269
  for n in self.angle_nodes(center, startangle, rtol, atol)]
4284
4270
  start_nodes.sort()
4285
- end_nodes = [(distance(center, n), n)
4271
+ d_start1, n, b = start_nodes[0]
4272
+ if not points_are_close(self.start_corners[0], n):
4273
+ logger.warning("end of create_boundary_nodes: corner missing in start boundary")
4274
+ return False
4275
+ d_start2, n, b = start_nodes[-1]
4276
+ if not points_are_close(self.start_corners[-1], n):
4277
+ logger.warning("end of create_boundary_nodes: corner missing in start boundary")
4278
+ return False
4279
+ if not check_line(start_nodes):
4280
+ logger.warning("end of create_boundary_nodes: bad start boundary")
4281
+ return False
4282
+
4283
+ logger.debug("Start Nodes")
4284
+ [logger.debug(" --> %s", x) for x in start_nodes]
4285
+
4286
+ end_nodes = [(distance(center, n), n, True)
4286
4287
  for n in self.angle_nodes(center, endangle, rtol, atol)]
4287
4288
  end_nodes.sort()
4289
+ d_end1, n, b = end_nodes[0]
4290
+ if not points_are_close(self.end_corners[0], n):
4291
+ logger.warning("end of create_boundary_nodes: corner missing in end boundary")
4292
+ return False
4293
+ d_end2, n, b = end_nodes[-1]
4294
+ if not points_are_close(self.end_corners[-1], n):
4295
+ logger.warning("end of create_boundary_nodes: corner missing in end boundary")
4296
+ return False
4297
+ if not check_line(end_nodes):
4298
+ logger.warning("end of create_boundary_nodes: bad end boundary")
4299
+ return False
4288
4300
 
4289
- logger.debug("End with Nodes Start=%s, End=%s", len(start_nodes), len(end_nodes))
4301
+ logger.debug("End Nodes")
4302
+ [logger.debug(" --> %s", x) for x in end_nodes]
4290
4303
 
4291
- nodes = [n for d, n in start_nodes]
4292
- start_rot_nodes = self.rotate_nodes(alpha, nodes)
4304
+ logger.debug("Lower Corners: %s <> %s", d_start1, d_end1)
4305
+ if not np.isclose(d_start1, d_end1, rtol=self.rtol, atol=self.atol):
4306
+ logger.warning("end of create_boundary_nodes: corners dont match")
4307
+ return False
4293
4308
 
4294
- for d, node in start_nodes:
4295
- self.set_point_of_node(node, node)
4296
- i = 0
4297
- if len(end_nodes) == len(start_rot_nodes):
4298
- for d, node in end_nodes:
4299
- self.set_point_of_node(node, start_rot_nodes[i])
4300
- i += 1
4309
+ logger.debug("Upper Corners: %s <> %s", d_start2, d_end2)
4310
+ if not np.isclose(d_start2, d_end2, rtol=self.rtol, atol=self.atol):
4311
+ logger.warning("end of create_boundary_nodes: corners dont match")
4312
+ return False
4301
4313
 
4302
- logger.debug("end of create_boundery_nodes")
4303
- return
4314
+ if len(start_nodes) == 2 and len(end_nodes) == 2:
4315
+ logger.debug("end of create_boundary_nodes: only corners available")
4316
+ return False # ok
4317
+
4318
+ def node_distance_list(nodelist1, nodelist2):
4319
+ distlist = []
4320
+ i1 = 0
4321
+ i2 = 0
4322
+ while i1 < len(nodelist1) and i2 < len(nodelist2):
4323
+ d1, n1, b1 = nodelist1[i1]
4324
+ d2, n2, b2 = nodelist2[i2]
4325
+ if np.isclose(d1, d2, rtol=self.rtol, atol=self.atol):
4326
+ distlist.append((d1, True, True))
4327
+ i1 += 1
4328
+ i2 += 1
4329
+ elif d1 > d2:
4330
+ distlist.append((d2, False, True))
4331
+ i2 += 1
4332
+ else:
4333
+ distlist.append((d1, True, False))
4334
+ i1 += 1
4335
+ if not i1 == len(nodelist1) and i2 == len(nodelist2):
4336
+ return []
4337
+ return distlist
4338
+
4339
+ distance_list = node_distance_list(start_nodes, end_nodes)
4340
+ [logger.debug("distance: %s, (%s, %s)", d, b1, b2)
4341
+ for d, b1, b2 in distance_list]
4342
+
4343
+ diff = len(distance_list) - len(start_nodes)
4344
+ done = False
4345
+ if not diff == 0:
4346
+ logger.debug("%s missing start nodes", diff)
4347
+ done = True
4348
+ for d, in_start, in_end in distance_list:
4349
+ if not in_start:
4350
+ p = point(self.center, d, startangle)
4351
+ start_nodes.append((d, p, False))
4352
+ start_nodes.sort()
4353
+ assert(len(start_nodes) == len(distance_list))
4354
+ if not self.repair_border_line(start_nodes):
4355
+ logger.debug("end of create_boundary_nodes (failed)")
4356
+ return False
4357
+
4358
+ diff = len(distance_list) - len(end_nodes)
4359
+ if not diff == 0:
4360
+ logger.debug("%s missing end nodes", diff)
4361
+ done = True
4362
+ for d, in_start, in_end in distance_list:
4363
+ if not in_end:
4364
+ p = point(self.center, d, endangle)
4365
+ end_nodes.append((d, p, False))
4366
+ end_nodes.sort()
4367
+ assert(len(end_nodes) == len(distance_list))
4368
+
4369
+ if not self.repair_border_line(end_nodes):
4370
+ logger.debug("end of create_boundary_nodes (failed)")
4371
+ return False
4372
+
4373
+ logger.debug("end of create_boundary_nodes")
4374
+ return done
4304
4375
 
4305
4376
  def set_point_of_node(self, node, p):
4306
4377
  if isinstance(node, list):
@@ -121,8 +121,8 @@ class Journal(object):
121
121
  data_list.append(val)
122
122
  self.data[name] = data_list
123
123
 
124
- def put_filename(self, val):
125
- self.put('filename', val)
124
+ def set_filename(self, val):
125
+ self.set('filename', val)
126
126
 
127
127
  def put_areas(self, val):
128
128
  self.put('areas', val)
@@ -5,14 +5,16 @@
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, Shape
9
- from .corner import Corner
8
+ from femagtools.dxfsl.shape import Element, Circle, Arc, Line, Shape
9
+ from femagtools.dxfsl.corner import Corner
10
10
  from femagtools.dxfsl.symmetry import Symmetry
11
- from .functions import point, points_are_close, distance
12
- from .functions import alpha_angle, normalise_angle, middle_angle, third_angle
13
- from .functions import alpha_line, line_m, line_n, mirror_point
14
- from .functions import within_interval, part_of_circle
15
- from .functions import less, less_equal, greater, greater_equal
11
+ import femagtools.dxfsl.area as AREA
12
+ from femagtools.dxfsl.functions import point, points_are_close, distance
13
+ from femagtools.dxfsl.functions import alpha_angle, normalise_angle, middle_angle, third_angle
14
+ from femagtools.dxfsl.functions import alpha_line, line_m, line_n, mirror_point
15
+ from femagtools.dxfsl.functions import within_interval, part_of_circle
16
+ from femagtools.dxfsl.functions import less, less_equal, greater, greater_equal
17
+ from femagtools.dxfsl.journal import Journal, getJournal
16
18
  logger = logging.getLogger('femagtools.geom')
17
19
 
18
20
 
@@ -37,6 +39,7 @@ class Machine(object):
37
39
  self.airgap2_radius = 0.0
38
40
  self.airgap_second = None
39
41
  self.previous_machine = None
42
+ self.journal = getJournal()
40
43
 
41
44
  if not self.center:
42
45
  raise ValueError("FATAL ERROR: no center in Geometry")
@@ -283,11 +286,6 @@ class Machine(object):
283
286
  logger.debug("end of copy_mirror")
284
287
  return machine
285
288
 
286
- def has_mirrored_windings(self):
287
- if not self.is_mirrored():
288
- return False
289
- return self.geom.area_close_to_endangle(2) > 0
290
-
291
289
  def undo_mirror(self):
292
290
  assert(self.is_mirrored())
293
291
  assert(self.previous_machine)
@@ -533,7 +531,7 @@ class Machine(object):
533
531
  def repair_hull_geom(self, geom, startangle, endangle):
534
532
  logger.debug('begin repair_hull_geom (%s, %s)', startangle, endangle)
535
533
 
536
- rtol = 1e-4
534
+ rtol = 1e-3
537
535
  atol = 1e-4
538
536
  c_corner = Corner(self.center, self.center)
539
537
  start_c_added, start_corners = geom.get_corner_list(self.center, startangle,
@@ -558,8 +556,9 @@ class Machine(object):
558
556
  rtol=rtol, atol=atol)
559
557
  logger.debug('end of repair_hull_geom')
560
558
 
561
- def create_boundery_nodes(self):
562
- self.geom.create_boundery_nodes(self.center, self.startangle, self.endangle)
559
+ def create_boundary_nodes(self):
560
+ if self.geom.create_boundary_nodes(self.center, self.startangle, self.endangle):
561
+ logger.debug("___additional boundary nodes created___")
563
562
 
564
563
  def create_auxiliary_lines(self):
565
564
  logger.debug("create_auxiliary_lines")
@@ -1138,6 +1137,11 @@ class Machine(object):
1138
1137
 
1139
1138
  return 0.0
1140
1139
 
1140
+ def has_windings_in_the_middle(self):
1141
+ midangle = middle_angle(self.startangle,
1142
+ self.endangle)
1143
+ return self.geom.windings_in_the_middle(midangle)
1144
+
1141
1145
  def create_mirror_lines_outside_windings(self):
1142
1146
  logger.debug("create_mirror_lines_outside_windings")
1143
1147
 
femagtools/dxfsl/shape.py CHANGED
@@ -54,6 +54,9 @@ class Shape(object):
54
54
  def classname(self):
55
55
  return "Shape"
56
56
 
57
+ def set_my_color(self, color):
58
+ self.my_color = color
59
+
57
60
  def get_my_color(self):
58
61
  if hasattr(self, 'my_color'):
59
62
  return self.my_color