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.
- femagtools/__init__.py +1 -1
- femagtools/amela.py +2 -2
- femagtools/dxfsl/area.py +130 -26
- femagtools/dxfsl/conv.py +2 -14
- femagtools/dxfsl/converter.py +69 -12
- femagtools/dxfsl/fslrenderer.py +15 -13
- femagtools/dxfsl/geom.py +153 -82
- femagtools/dxfsl/journal.py +2 -2
- femagtools/dxfsl/machine.py +19 -15
- femagtools/dxfsl/shape.py +3 -0
- femagtools/ecloss.py +386 -2
- femagtools/femag.py +82 -9
- femagtools/fsl.py +52 -56
- femagtools/machine/pm.py +1 -1
- femagtools/machine/sm.py +16 -8
- femagtools/mcv.py +128 -124
- femagtools/me.py +13 -13
- femagtools/model.py +8 -2
- femagtools/plot/fieldlines.py +1 -1
- femagtools/plot/mcv.py +18 -0
- femagtools/plot/wdg.py +2 -2
- femagtools/svgfsl/converter.py +1 -1
- femagtools/templates/afm_rotor.mako +4 -0
- femagtools/templates/gen_hairpin_winding.mako +36 -45
- femagtools/templates/magnetIron.mako +1 -1
- femagtools/templates/magnetIron2.mako +1 -1
- femagtools/templates/magnetIron3.mako +1 -1
- femagtools/templates/magnetIron4.mako +1 -1
- femagtools/templates/magnetIron5.mako +1 -1
- femagtools/templates/magnetIronV.mako +1 -1
- femagtools/templates/magnetSector.mako +1 -1
- femagtools/templates/mesh-airgap.mako +12 -6
- femagtools/templates/prepare_thermal.mako +199 -61
- femagtools/windings.py +25 -20
- {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/METADATA +20 -20
- {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/RECORD +42 -43
- {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/WHEEL +1 -1
- tests/test_mcv.py +106 -1
- tests/test_windings.py +5 -0
- tests/test_mcvwriter.py +0 -96
- {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/LICENSE +0 -0
- {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/entry_points.txt +0 -0
- {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
|
-
|
872
|
-
|
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.
|
1850
|
-
|
1851
|
-
|
1852
|
-
|
1853
|
-
|
1854
|
-
|
1855
|
-
|
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.
|
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,
|
3639
|
+
def num_areas_of_type(self, types=()):
|
3617
3640
|
return len([area for area in self.list_of_areas()
|
3618
|
-
if area.
|
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
|
-
|
4188
|
-
if not
|
4189
|
-
logger.debug("end repair_border_line: missing point %s",
|
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
|
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-
|
4256
|
+
rtol = 1e-3
|
4228
4257
|
if not atol:
|
4229
4258
|
atol = 1e-3
|
4230
4259
|
|
4231
|
-
|
4232
|
-
|
4233
|
-
|
4234
|
-
|
4235
|
-
|
4236
|
-
|
4237
|
-
|
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
|
-
|
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
|
4301
|
+
logger.debug("End Nodes")
|
4302
|
+
[logger.debug(" --> %s", x) for x in end_nodes]
|
4290
4303
|
|
4291
|
-
|
4292
|
-
|
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
|
-
|
4295
|
-
|
4296
|
-
|
4297
|
-
|
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
|
-
|
4303
|
-
|
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):
|
femagtools/dxfsl/journal.py
CHANGED
@@ -121,8 +121,8 @@ class Journal(object):
|
|
121
121
|
data_list.append(val)
|
122
122
|
self.data[name] = data_list
|
123
123
|
|
124
|
-
def
|
125
|
-
self.
|
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)
|
femagtools/dxfsl/machine.py
CHANGED
@@ -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
|
-
|
12
|
-
from .functions import
|
13
|
-
from .functions import
|
14
|
-
from .functions import
|
15
|
-
from .functions import
|
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-
|
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
|
562
|
-
self.geom.
|
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
|
|