femagtools 1.7.8__py3-none-any.whl → 1.7.9__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/dxfsl/area.py +38 -9
- femagtools/dxfsl/converter.py +2 -1
- femagtools/dxfsl/fslrenderer.py +8 -1
- femagtools/dxfsl/geom.py +19 -8
- femagtools/dxfsl/svgparser.py +31 -4
- femagtools/femag.py +14 -0
- femagtools/fsl.py +74 -28
- femagtools/isa7.py +41 -0
- femagtools/job.py +2 -2
- femagtools/machine/afpm.py +5 -1
- femagtools/machine/utils.py +4 -3
- femagtools/model.py +7 -0
- femagtools/moo/population.py +9 -7
- femagtools/nc.py +12 -0
- femagtools/plot/__init__.py +1 -1
- femagtools/plot/nc.py +22 -5
- femagtools/plot/wdg.py +38 -5
- femagtools/svgfsl/converter.py +6 -0
- femagtools/templates/gen_winding.mako +7 -0
- femagtools/templates/magnetIron.mako +30 -46
- femagtools/templates/magnetIron2.mako +39 -0
- femagtools/templates/magnetIron3.mako +39 -0
- femagtools/templates/magnetIron4.mako +39 -0
- femagtools/templates/magnetIron5.mako +39 -0
- femagtools/templates/magnetIronV.mako +34 -54
- femagtools/templates/magnetSector.mako +32 -47
- femagtools/templates/prepare_thermal.mako +219 -0
- femagtools/templates/statorRotor3.mako +3 -22
- femagtools/windings.py +67 -39
- {femagtools-1.7.8.dist-info → femagtools-1.7.9.dist-info}/METADATA +3 -1
- {femagtools-1.7.8.dist-info → femagtools-1.7.9.dist-info}/RECORD +38 -37
- {femagtools-1.7.8.dist-info → femagtools-1.7.9.dist-info}/WHEEL +1 -1
- tests/test_fsl.py +1 -1
- tests/test_windings.py +13 -2
- {femagtools-1.7.8.dist-info → femagtools-1.7.9.dist-info}/LICENSE +0 -0
- {femagtools-1.7.8.dist-info → femagtools-1.7.9.dist-info}/entry_points.txt +0 -0
- {femagtools-1.7.8.dist-info → femagtools-1.7.9.dist-info}/top_level.txt +0 -0
femagtools/__init__.py
CHANGED
femagtools/dxfsl/area.py
CHANGED
@@ -171,6 +171,38 @@ class Area(object):
|
|
171
171
|
if e1.n1 == e2.n1 and e1.n2 == e2.n2:
|
172
172
|
yield e1
|
173
173
|
|
174
|
+
def reduce_nodes(self, mindist=0.01):
|
175
|
+
"""reduces number of nodes (lines only)
|
176
|
+
https://rdp.readthedocs.io/en/latest
|
177
|
+
"""
|
178
|
+
import rdp
|
179
|
+
def reduce_nodes_(lines, mindist):
|
180
|
+
nodes = [le.get_nodes()[0] for le in lines]
|
181
|
+
r = rdp.rdp(nodes,
|
182
|
+
epsilon=mindist)
|
183
|
+
if len(r) < len(nodes):
|
184
|
+
return [Line(Element(start=n1, end=n2))
|
185
|
+
for n1, n2 in zip(r, r[1:])]
|
186
|
+
return lines
|
187
|
+
|
188
|
+
lines = []
|
189
|
+
reduced = []
|
190
|
+
for e in self.area:
|
191
|
+
if isinstance(e, Line):
|
192
|
+
lines.append(e)
|
193
|
+
else:
|
194
|
+
reduced.append(e)
|
195
|
+
reduced += reduce_nodes_(lines, mindist)
|
196
|
+
lines = []
|
197
|
+
if lines:
|
198
|
+
reduced += reduce_nodes_(lines, mindist)
|
199
|
+
|
200
|
+
if len(self.area) > len(reduced):
|
201
|
+
logger.info("reduced areas %d -> %d",
|
202
|
+
len(self.area), len(reduced))
|
203
|
+
return reduced
|
204
|
+
return []
|
205
|
+
|
174
206
|
def virtual_nodes(self, render=False, parts=64):
|
175
207
|
if len(self.area) < 2:
|
176
208
|
return
|
@@ -337,15 +369,9 @@ class Area(object):
|
|
337
369
|
return False
|
338
370
|
|
339
371
|
def minmax_dist_from_center(self, center):
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
r = np.linalg.norm(np.array(n)-center)
|
344
|
-
if r < rmin:
|
345
|
-
rmin = r
|
346
|
-
if r > rmax:
|
347
|
-
rmax = r
|
348
|
-
return rmin, rmax
|
372
|
+
nodes = np.array([n for e in self.area for n in e.get_nodes()])
|
373
|
+
return (np.min(np.linalg.norm(nodes-center, axis=1)),
|
374
|
+
np.max(np.linalg.norm(nodes-center, axis=1)))
|
349
375
|
|
350
376
|
def minmax_angle_dist_from_center(self, center, dist):
|
351
377
|
circ = Circle(Element(center=center, radius=dist))
|
@@ -959,11 +985,14 @@ class Area(object):
|
|
959
985
|
self.legend())
|
960
986
|
|
961
987
|
def remove_edges(self, g, ndec):
|
988
|
+
r = 0
|
962
989
|
for e in self.area:
|
963
990
|
try:
|
964
991
|
g.remove_edge(e.node1(ndec), e.node2(ndec))
|
992
|
+
r+=1
|
965
993
|
except Exception:
|
966
994
|
continue
|
995
|
+
return r
|
967
996
|
|
968
997
|
def is_circle(self):
|
969
998
|
e = self.area[0]
|
femagtools/dxfsl/converter.py
CHANGED
@@ -533,6 +533,7 @@ def convert(dxfile,
|
|
533
533
|
EESM=EESM)
|
534
534
|
|
535
535
|
if machine_outer.geom.is_stator() or machine_outer.has_windings():
|
536
|
+
machine_outer.geom.reduce_winding_nodes()
|
536
537
|
machine_outer = build_machine_stator(machine_outer,
|
537
538
|
False,
|
538
539
|
mindist,
|
@@ -718,7 +719,7 @@ def convert(dxfile,
|
|
718
719
|
p,
|
719
720
|
EESM=EESM,
|
720
721
|
single=True)
|
721
|
-
|
722
|
+
machine.geom.reduce_winding_nodes()
|
722
723
|
params = create_femag_parameters_stator(machine,
|
723
724
|
part[1])
|
724
725
|
else:
|
femagtools/dxfsl/fslrenderer.py
CHANGED
@@ -162,6 +162,8 @@ class FslRenderer(object):
|
|
162
162
|
geom.split_all_lines_longer_than(split_len)
|
163
163
|
self.content = []
|
164
164
|
|
165
|
+
MAXDST=4.0
|
166
|
+
NUMLEVELS=10
|
165
167
|
ndt_list = [(0.00, 1.1),
|
166
168
|
(0.05, 1.5),
|
167
169
|
(0.10, 1.7),
|
@@ -173,6 +175,9 @@ class FslRenderer(object):
|
|
173
175
|
(0.70, 4.5),
|
174
176
|
(0.85, 5.5),
|
175
177
|
(1.10, 5.5)]
|
178
|
+
ndt_list = [(1.1*nl/NUMLEVELS, nl/NUMLEVELS*(MAXDST-1.1)+1.1)
|
179
|
+
for nl in range(NUMLEVELS+1)]
|
180
|
+
|
176
181
|
dist = geom.max_radius - geom.min_radius
|
177
182
|
el_sorted = self.sorted_elements(geom, inner)
|
178
183
|
|
@@ -182,7 +187,7 @@ class FslRenderer(object):
|
|
182
187
|
if ndt_list[n][0] < d_percent:
|
183
188
|
self.agndst = ndt_list[n][1] * self.agndst
|
184
189
|
self.content.append('\nndt({}*agndst)\n'.
|
185
|
-
format(ndt_list[n][1]))
|
190
|
+
format(round(ndt_list[n][1], 1)))
|
186
191
|
while ndt_list[n][0] < d_percent:
|
187
192
|
n += 1
|
188
193
|
e.render(self)
|
@@ -233,6 +238,8 @@ class FslRenderer(object):
|
|
233
238
|
'r, phi = c2pr(x0, y0)',
|
234
239
|
'x1, y1 = pr2c(r1, phi)',
|
235
240
|
'x2, y2 = pr2c(r1, {}*math.pi/parts)'.format(slice),
|
241
|
+
f'-- end max corner {geom.end_corners[-1]}',
|
242
|
+
f'-- center {geom.center}',
|
236
243
|
f'r = {geom.dist_end_max_corner()}',
|
237
244
|
'x3, y3 = pr2c(r, {}*math.pi/parts)'.format(slice),
|
238
245
|
'nc_line(x0, y0, x1, y1, 0)',
|
femagtools/dxfsl/geom.py
CHANGED
@@ -91,11 +91,12 @@ def create_geometry(new_elements, split=False):
|
|
91
91
|
|
92
92
|
|
93
93
|
def intersect_and_split(inp_elements, rtol, atol):
|
94
|
-
logger.info("Load input elements ... ")
|
94
|
+
logger.info("Load input elements ... %s", len(inp_elements))
|
95
95
|
out_elements = []
|
96
96
|
for e in inp_elements:
|
97
97
|
out_size = len(out_elements)
|
98
98
|
intersect_and_split_element(e, out_elements, 0, out_size, rtol, atol)
|
99
|
+
logger.debug(" done", e)
|
99
100
|
return out_elements
|
100
101
|
|
101
102
|
|
@@ -650,9 +651,9 @@ class Geometry(object):
|
|
650
651
|
return True
|
651
652
|
return False
|
652
653
|
|
653
|
-
def get_edge(self,
|
654
|
+
def get_edge(self, obj):
|
654
655
|
return [[e[0], e[1], e[2]['object']] for e in self.g.edges(data=True)
|
655
|
-
if e[2]['object'] is
|
656
|
+
if e[2]['object'] is obj]
|
656
657
|
|
657
658
|
def get_edge_element(self, n1, n2):
|
658
659
|
e_dict = self.g.get_edge_data(n1, n2)
|
@@ -679,9 +680,9 @@ class Geometry(object):
|
|
679
680
|
assert(len(e) == 1)
|
680
681
|
self._remove_edge(e[0][0], e[0][1])
|
681
682
|
|
682
|
-
def remove_edges(self,
|
683
|
-
for
|
684
|
-
self.remove_edge(
|
683
|
+
def remove_edges(self, objs):
|
684
|
+
for o in objs:
|
685
|
+
self.remove_edge(o)
|
685
686
|
|
686
687
|
def _remove_node(self, n):
|
687
688
|
for nbr in self.g.neighbors(n):
|
@@ -867,8 +868,8 @@ class Geometry(object):
|
|
867
868
|
logger.debug("begin of dist_end_max_corner")
|
868
869
|
logger.debug("end corners: %s", self.end_corners)
|
869
870
|
|
870
|
-
if self.is_mirrored():
|
871
|
-
|
871
|
+
#if self.is_mirrored():
|
872
|
+
# return self.dist_start_max_corner()
|
872
873
|
d = distance(self.center, self.end_corners[-1])
|
873
874
|
logger.debug("end of dist_end_max_corner: %s", d)
|
874
875
|
return d
|
@@ -1843,6 +1844,16 @@ class Geometry(object):
|
|
1843
1844
|
return [h for (k, h) in legend.items()]
|
1844
1845
|
return []
|
1845
1846
|
|
1847
|
+
def reduce_winding_nodes(self, mindist=0.01):
|
1848
|
+
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)
|
1856
|
+
|
1846
1857
|
def render_areagroups(self, renderer):
|
1847
1858
|
if not self.areagroup_list:
|
1848
1859
|
return
|
femagtools/dxfsl/svgparser.py
CHANGED
@@ -37,10 +37,17 @@ def get_angles(sweep, center, p1, p2):
|
|
37
37
|
def get_shapes(path):
|
38
38
|
"""return list of node elements (A, L)"""
|
39
39
|
state = ''
|
40
|
+
prevstate = ''
|
40
41
|
p = []
|
41
|
-
for s in [s for s in re.split('([
|
42
|
+
for s in [s for s in re.split('([AMLHV])|,|\\s+', path) if s]:
|
42
43
|
if state == '':
|
43
|
-
|
44
|
+
s = s.upper()
|
45
|
+
if s in ('A','M','L','H','V'):
|
46
|
+
state = s
|
47
|
+
prevstate = s
|
48
|
+
else: # wild guess
|
49
|
+
p.append(float(s))
|
50
|
+
state = prevstate
|
44
51
|
elif state == 'M':
|
45
52
|
p.append(float(s))
|
46
53
|
if len(p) == 2:
|
@@ -52,7 +59,7 @@ def get_shapes(path):
|
|
52
59
|
if len(p) == 2:
|
53
60
|
p2 = np.array(p)
|
54
61
|
logger.debug("Line %s -> %s",
|
55
|
-
|
62
|
+
p1, p2)
|
56
63
|
yield Line(Element(start=p1, end=p2))
|
57
64
|
p1 = p2.copy()
|
58
65
|
p = []
|
@@ -66,7 +73,7 @@ def get_shapes(path):
|
|
66
73
|
center = get_center(r, p1, p2, sweep)
|
67
74
|
start, end = get_angles(sweep, center, p1, p2)
|
68
75
|
logger.debug("Arc center %s r %f %f -> %f",
|
69
|
-
|
76
|
+
center, r, start, end)
|
70
77
|
yield Arc(Element(center=center,
|
71
78
|
radius=r,
|
72
79
|
start_angle=start*180/np.pi,
|
@@ -74,14 +81,34 @@ def get_shapes(path):
|
|
74
81
|
p1 = p2.copy()
|
75
82
|
p = []
|
76
83
|
state = ''
|
84
|
+
elif state == 'H':
|
85
|
+
logger.debug("h %s", s)
|
86
|
+
p2 = np.array((float(s), 0))
|
87
|
+
yield Line(Element(start=p1, end=p2))
|
88
|
+
p1 = p2.copy()
|
89
|
+
p = []
|
90
|
+
state = ''
|
91
|
+
elif state == 'V':
|
92
|
+
logger.debug("V %s", s)
|
93
|
+
p2 = np.array((0, float(s)))
|
94
|
+
yield Line(Element(start=p1, end=p2))
|
95
|
+
p1 = p2.copy()
|
96
|
+
p = []
|
97
|
+
state = ''
|
77
98
|
else:
|
78
99
|
raise ValueError(f"unsupported path {state}")
|
79
100
|
|
80
101
|
|
81
102
|
def svgshapes(svgfile):
|
82
103
|
svg = ET.parse(svgfile)
|
104
|
+
bcolor = re.compile('fill:([^;]+)')
|
105
|
+
sr = 0
|
83
106
|
for p in svg.findall(".//{http://www.w3.org/2000/svg}path"):
|
107
|
+
m = bcolor.search(p.get('style'))
|
108
|
+
if m:
|
109
|
+
logger.info("subregion %d: %s", sr, m.groups()[0])
|
84
110
|
yield from get_shapes(p.get('d'))
|
111
|
+
sr += 1
|
85
112
|
for p in svg.findall(".//{http://www.w3.org/2000/svg}line"):
|
86
113
|
yield Line(Element(start=[float(p.get('x1')), float(p.get('y1'))],
|
87
114
|
end=[float(p.get('x2')), float(p.get('y2'))]))
|
femagtools/femag.py
CHANGED
@@ -401,6 +401,10 @@ class BaseFemag(object):
|
|
401
401
|
ttemp = list(zip(*temp))
|
402
402
|
return {'t': ttemp[0], 'temperature': ttemp[1]}
|
403
403
|
|
404
|
+
if simulation['calculationMode'] == 'hsn':
|
405
|
+
model = self.read_nc()
|
406
|
+
return model.get_minmax_temp()
|
407
|
+
|
404
408
|
if not bch:
|
405
409
|
bch = self.read_bch(self.modelname)
|
406
410
|
if simulation['calculationMode'] == 'pm_sym_fast' or \
|
@@ -468,6 +472,11 @@ class BaseFemag(object):
|
|
468
472
|
bch.magnet_loss_th = m.th_loss
|
469
473
|
except:
|
470
474
|
pass
|
475
|
+
try:
|
476
|
+
if hasattr(self, 'dy2'):
|
477
|
+
setattr(bch, 'dy2', self.dy2)
|
478
|
+
except:
|
479
|
+
pass
|
471
480
|
return bch
|
472
481
|
|
473
482
|
|
@@ -599,6 +608,11 @@ class Femag(BaseFemag):
|
|
599
608
|
stateofproblem = 'mag_static'
|
600
609
|
|
601
610
|
self.run(fslfile, options, fsl_args, stateofproblem=stateofproblem)
|
611
|
+
|
612
|
+
try:
|
613
|
+
setattr(self, "dy2", machine['stator']['dy2'])
|
614
|
+
except:
|
615
|
+
pass
|
602
616
|
if simulation:
|
603
617
|
return self.readResult(simulation)
|
604
618
|
|
femagtools/fsl.py
CHANGED
@@ -356,25 +356,18 @@ class Builder:
|
|
356
356
|
if 'thcond' in model.stator:
|
357
357
|
fslcmds += [
|
358
358
|
'-- thermal properties in airgap',
|
359
|
-
'if m.zeroangl
|
360
|
-
'
|
361
|
-
' thcap = 1007',
|
362
|
-
' beta = math.pi*m.npols_gen/m.num_poles + m.zeroangl/180*math.pi',
|
363
|
-
' xai, yai = pr2c((da1+da2)/4, beta)',
|
364
|
-
' def_mat_therm(xai,yai,"cyan",1.19,ag_cond,thcap,1)',
|
365
|
-
' xai, yai = pr2c((da1+da2)/4-ag/4, beta)',
|
366
|
-
' def_mat_therm(xai,yai,"cyan",1.19,ag_cond,thcap,1)',
|
367
|
-
' xai, yai = pr2c((da1+da2)/4+ag/4, beta)',
|
368
|
-
' def_mat_therm(xai,yai,"cyan",1.19,ag_cond,thcap,1)',
|
369
|
-
'',
|
370
|
-
' state_of_problem("therm_static") -- thermic boundary conditions',
|
371
|
-
' x1,y1 = pd2c(dy2/2,m.zeroangl)',
|
372
|
-
' x2,y2 = pd2c(dy1/2,m.zeroangl)',
|
373
|
-
' beta = 360*m.npols_gen/m.num_poles',
|
374
|
-
' x3,y3 = pd2c(dy1/2,beta+m.zeroangl)',
|
375
|
-
' x4,y4 = pd2c(dy2/2,beta+m.zeroangl)',
|
376
|
-
' def_bcond_tp(x1,y1,x2,y2,x3,y3,x4,y4, 4)',
|
359
|
+
'if m.zeroangl == nil then',
|
360
|
+
' m.zeroangl = 0.0',
|
377
361
|
'end',
|
362
|
+
'beta = math.pi*m.npols_gen/m.num_poles + m.zeroangl/180*math.pi',
|
363
|
+
'',
|
364
|
+
'state_of_problem("therm_static") -- thermic boundary conditions',
|
365
|
+
'x1,y1 = pd2c(dy2/2,m.zeroangl)',
|
366
|
+
'x2,y2 = pd2c(dy1/2,m.zeroangl)',
|
367
|
+
'beta = 360*m.npols_gen/m.num_poles',
|
368
|
+
'x3,y3 = pd2c(dy1/2,beta+m.zeroangl)',
|
369
|
+
'x4,y4 = pd2c(dy2/2,beta+m.zeroangl)',
|
370
|
+
'def_bcond_tp(x1,y1,x2,y2,x3,y3,x4,y4, 4)',
|
378
371
|
'state_of_problem("mag_static")']
|
379
372
|
return fslcmds
|
380
373
|
return []
|
@@ -440,14 +433,14 @@ class Builder:
|
|
440
433
|
return []
|
441
434
|
|
442
435
|
def create_gen_winding(self, model):
|
443
|
-
try:
|
444
|
-
|
445
|
-
model.winding[
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
except KeyError: # not hairpin_winding
|
436
|
+
try:
|
437
|
+
model.winding['wire'].update(
|
438
|
+
{"num_layers": model.winding["num_layers"]})
|
439
|
+
genwdg = self.__render(model.winding,
|
440
|
+
'gen_' + model.winding['wire'].get('name'))
|
441
|
+
except:
|
450
442
|
genwdg = self.__render(model, 'gen_winding')
|
443
|
+
|
451
444
|
k = list({'leak_dist_wind',
|
452
445
|
'leak_evol_wind',
|
453
446
|
'leak_tooth_wind'}.intersection(model.winding))
|
@@ -510,6 +503,9 @@ class Builder:
|
|
510
503
|
setattr(model, 'stator', {})
|
511
504
|
model.stator['num_slots'] = conv.get('tot_num_slot')
|
512
505
|
model.stator['slot_area'] = conv.get('slot_area')
|
506
|
+
model.stator['dy1'] = conv.get('dy1')*1e-3
|
507
|
+
model.stator['dy2'] = conv.get('dy2')*1e-3
|
508
|
+
|
513
509
|
if model.get('num_agnodes', 0) == 0:
|
514
510
|
model.set_value('agndst', conv['agndst']*1e-3)
|
515
511
|
logger.info("num poles %d num slots %d outer diameter %.4f m agndst %.4f mm",
|
@@ -526,19 +522,39 @@ class Builder:
|
|
526
522
|
|
527
523
|
if 'fsl_stator' in conv:
|
528
524
|
self.fsl_stator = True
|
529
|
-
|
525
|
+
th_props = [' ']
|
526
|
+
if model.stator.get('thcond', 0):
|
527
|
+
th_props = [f'stator_density = {1e3*model.stator["density"]}',
|
528
|
+
f'stator_thcond = {model.stator["thcond"]}',
|
529
|
+
f'stator_thcap = {model.stator["thcap"]}',
|
530
|
+
]
|
531
|
+
model.stator['dxf'] = dict(fsl=conv['fsl_stator'] + th_props)
|
530
532
|
if not (hasattr(model, 'magnet') or hasattr(model, 'rotor')):
|
531
533
|
if params['EESM']:
|
532
534
|
setattr(model, 'rotor', {})
|
533
535
|
else:
|
534
536
|
setattr(model, 'magnet', {})
|
537
|
+
|
535
538
|
if 'fsl_rotor' in conv:
|
536
539
|
self.fsl_rotor = True
|
540
|
+
th_props = ['']
|
537
541
|
if hasattr(model, 'magnet'):
|
538
|
-
model
|
542
|
+
if model['magnet'].get('thcond', 0):
|
543
|
+
logger.info(model['magnet'])
|
544
|
+
th_props = [f'rotor_density = {1e3*model["magnet"]["density"]}',
|
545
|
+
f'rotor_thcond = {model["magnet"]["thcond"]}',
|
546
|
+
f'rotor_thcap = {model["magnet"]["thcap"]}'
|
547
|
+
]
|
548
|
+
model.magnet['dxf'] = dict(fsl=conv['fsl_rotor'] + th_props)
|
539
549
|
if hasattr(model, 'rotor'):
|
540
550
|
model.rotor['dxf'] = dict(fsl=conv['fsl_rotor'])
|
541
551
|
|
552
|
+
def create_thermal_properties(self, model):
|
553
|
+
if model.stator.get('thcond') and model.stator.get('thcap') and \
|
554
|
+
model.stator.get('density'):
|
555
|
+
return self.__render(model, 'prepare_thermal')
|
556
|
+
return ['']
|
557
|
+
|
542
558
|
def create_model(self, model, magnets=[], condMat=[], ignore_material=False):
|
543
559
|
magnetMat = {}
|
544
560
|
material = ''
|
@@ -594,6 +610,35 @@ class Builder:
|
|
594
610
|
self.create_magnet_model(model))
|
595
611
|
if magnetMat:
|
596
612
|
rotor += self.create_magnet(model, magnetMat)
|
613
|
+
|
614
|
+
if model['magnet'].get('thcond_magnet', 0):
|
615
|
+
th_props = [f'magn_density = {1e3*model["magnet"]["spmaweight_magnet"]}',
|
616
|
+
f'magn_thcond = {model["magnet"]["thcond_magnet"]}',
|
617
|
+
f'magn_thcap = {model["magnet"]["thcap_magnet"]}'
|
618
|
+
]
|
619
|
+
rotor += th_props
|
620
|
+
if model.is_dxffile() or 'dxf' in model['magnet']:
|
621
|
+
rotor += ['if x0_shaft == 0.0 then',
|
622
|
+
'-- add air layer (inside) for heat transfer',
|
623
|
+
' h = dy2/2/3',
|
624
|
+
' if h > 5 then',
|
625
|
+
' h = 3.8',
|
626
|
+
' end ',
|
627
|
+
' if m.zeroangl == nil then ',
|
628
|
+
' m.zeroangl = 0.0',
|
629
|
+
' end',
|
630
|
+
' beta = 360*m.npols_gen/m.num_poles',
|
631
|
+
' x0, y0 = pd2c(dy2/2, m.zeroangl)',
|
632
|
+
' x1, y1 = pd2c(dy2/2-h, m.zeroangl)',
|
633
|
+
' x2, y2 = pd2c(dy2/2-h, beta+m.zeroangl)',
|
634
|
+
' x3, y3 = pd2c(dy2/2, beta+m.zeroangl)',
|
635
|
+
' nc_line(x0, y0, x1, y1, 0)',
|
636
|
+
' nc_circle(x1, y1, x2, y2, 0)',
|
637
|
+
' nc_line(x2, y2, x3, y3, 0)',
|
638
|
+
' x0, y0 = pd2c(dy2/2-h/2, beta/2+m.zeroangl)',
|
639
|
+
' create_mesh_se(x0, y0)',
|
640
|
+
'end'
|
641
|
+
]
|
597
642
|
else:
|
598
643
|
rotor = self.create_rotor_model(
|
599
644
|
model, condMat, ignore_material)
|
@@ -635,7 +680,8 @@ class Builder:
|
|
635
680
|
rotor +
|
636
681
|
self.mesh_airgap(model) +
|
637
682
|
self.create_connect_models(model) +
|
638
|
-
self.create_rotor_winding(model))
|
683
|
+
self.create_rotor_winding(model)) + \
|
684
|
+
self.create_thermal_properties(model)
|
639
685
|
|
640
686
|
return (self.open_model(model) +
|
641
687
|
self.create_fe_losses(model) +
|
femagtools/isa7.py
CHANGED
@@ -544,6 +544,10 @@ class Isa7(object):
|
|
544
544
|
16: [0.8274509803921568, 0.8274509803921568, 0.8274509803921568]} # LIGHGREY
|
545
545
|
|
546
546
|
def __init__(self, reader):
|
547
|
+
try:
|
548
|
+
self.state_of_problem = reader.state_of_problem
|
549
|
+
except:
|
550
|
+
pass
|
547
551
|
self.points = [Point(x, y)
|
548
552
|
for x, y in zip(reader.POINT_ISA_POINT_REC_PT_CO_X,
|
549
553
|
reader.POINT_ISA_POINT_REC_PT_CO_Y)]
|
@@ -1139,6 +1143,43 @@ class Isa7(object):
|
|
1139
1143
|
sreg[sr.name] = [0,0,0]
|
1140
1144
|
return sreg
|
1141
1145
|
|
1146
|
+
def get_minmax_temp(self):
|
1147
|
+
def node_subregion(subregion_name):
|
1148
|
+
node_temperature = []
|
1149
|
+
for i in self.subregions:
|
1150
|
+
if i.name.lower() == subregion_name:
|
1151
|
+
for j in i.elements():
|
1152
|
+
for k in j.vertices:
|
1153
|
+
node_temperature.append(k.vpot[-1])
|
1154
|
+
ndtemp = np.unique(node_temperature)
|
1155
|
+
return [np.amax(ndtemp), np.amin(ndtemp), np.mean(ndtemp)]
|
1156
|
+
|
1157
|
+
zero_temp = [0.0, 0.0, 0.0]
|
1158
|
+
component_temperature = dict(styoke=zero_temp, stteeth=zero_temp,
|
1159
|
+
magnet=zero_temp, winding=zero_temp)
|
1160
|
+
for i in self.subregions:
|
1161
|
+
if i.name:
|
1162
|
+
sreg_name = i.name.lower()
|
1163
|
+
if sreg_name in ('stza', 'stth', 'stteeth'):
|
1164
|
+
component_temperature['stteeth'] = node_subregion(sreg_name)
|
1165
|
+
elif sreg_name in ('styk', 'styoke', 'stjo'):
|
1166
|
+
component_temperature['styoke'] = node_subregion(sreg_name)
|
1167
|
+
elif sreg_name == 'iron':
|
1168
|
+
component_temperature['iron'] = node_subregion(sreg_name)
|
1169
|
+
elif sreg_name == 'pmag':
|
1170
|
+
component_temperature['magnet'] = node_subregion(sreg_name)
|
1171
|
+
else:
|
1172
|
+
pass
|
1173
|
+
|
1174
|
+
wdg_temps = []
|
1175
|
+
for j in self.wdg_elements():
|
1176
|
+
for k in j.vertices:
|
1177
|
+
wdg_temps.append(k.vpot[-1])
|
1178
|
+
wdg_temp = np.unique(wdg_temps)
|
1179
|
+
component_temperature['winding'] = [np.amax(wdg_temp),
|
1180
|
+
np.amin(wdg_temp),
|
1181
|
+
np.mean(wdg_temp)]
|
1182
|
+
return component_temperature
|
1142
1183
|
|
1143
1184
|
def flux_dens(self, x, y, icur, ibeta):
|
1144
1185
|
el = self.get_element(x, y)
|
femagtools/job.py
CHANGED
@@ -112,7 +112,7 @@ class Task(object):
|
|
112
112
|
if bchfile_list:
|
113
113
|
result = femagtools.bch.Reader()
|
114
114
|
with open(bchfile_list[-1]) as f:
|
115
|
-
logger.
|
115
|
+
logger.debug("Reading %s",
|
116
116
|
bchfile_list[-1])
|
117
117
|
result.read(f)
|
118
118
|
if bagdat.exists():
|
@@ -127,7 +127,7 @@ class Task(object):
|
|
127
127
|
asm_list = sorted(basedir.glob(
|
128
128
|
'*_[0-9][0-9][0-9].ASM'))
|
129
129
|
if asm_list:
|
130
|
-
logger.
|
130
|
+
logger.debug("Reading %s",
|
131
131
|
asm_list[-1])
|
132
132
|
result = femagtools.asm.read(asm_list[-1])
|
133
133
|
if bagdat.exists():
|
femagtools/machine/afpm.py
CHANGED
@@ -645,6 +645,9 @@ class AFPM:
|
|
645
645
|
parameters={
|
646
646
|
'phi_voltage_winding': current_angles})
|
647
647
|
logger.info("Current angles: %s", current_angles)
|
648
|
+
elif (simulation['calculationMode'] == 'cogg_calc' and
|
649
|
+
'poc' not in simulation):
|
650
|
+
simulation['poc'] = poc.Poc(machine['pole_width'])
|
648
651
|
|
649
652
|
lresults = self.parstudy(
|
650
653
|
parvardef,
|
@@ -652,5 +655,6 @@ class AFPM:
|
|
652
655
|
simulation, engine) # Note: imcomplete machine prevents rebuild
|
653
656
|
|
654
657
|
results = process(lfe, pole_width, machine, lresults['f'])
|
655
|
-
|
658
|
+
if nlresults:
|
659
|
+
results.update(_psidq_ldq(results, nlresults))
|
656
660
|
return results
|
femagtools/machine/utils.py
CHANGED
@@ -411,6 +411,7 @@ def dqparident(workdir, engine, temp, machine,
|
|
411
411
|
elif ('wire_width' in machine[wdgk]) and ('wire_height' in machine[wdgk]):
|
412
412
|
aw = machine[wdgk]['wire_width']*machine[wdgk]['wire_height']
|
413
413
|
else: # wire diameter from slot area
|
414
|
+
da1 = machine['bore_diam']
|
414
415
|
aw = 0.75 * fcu * np.pi*da1*hs/Q1/wdg.l/N
|
415
416
|
r1 = wdg_resistance(wdg, N, g, aw, da1, hs, lfe)
|
416
417
|
except (NameError, KeyError):
|
@@ -489,6 +490,8 @@ def dqparident(workdir, engine, temp, machine,
|
|
489
490
|
machine['poles'] = 2*results['f'][0]['machine']['p']
|
490
491
|
da1 = 2*results['f'][0]['machine']['fc_radius']
|
491
492
|
wdg = create_wdg(machine)
|
493
|
+
if 'bore_diam' in machine:
|
494
|
+
da1 = machine['bore_diam']
|
492
495
|
ls1 = 0
|
493
496
|
try:
|
494
497
|
leakages = [float(x)
|
@@ -569,14 +572,12 @@ def dqparident(workdir, engine, temp, machine,
|
|
569
572
|
if r1:
|
570
573
|
dqpars['r1'] = r1
|
571
574
|
else:
|
572
|
-
|
573
|
-
model = nc.read(str(pathlib.Path(workdir) / machine['name']))
|
575
|
+
model = parvar.femag.read_nc()
|
574
576
|
try:
|
575
577
|
nlayers = wdg.l
|
576
578
|
except UnboundLocalError:
|
577
579
|
wdg = create_wdg(machine)
|
578
580
|
nlayers = wdg.l
|
579
|
-
da1 = machine['outer_diam']
|
580
581
|
Q1 = wdg.Q
|
581
582
|
istat = 0 if model.get_areas()[0]['slots'] else 1
|
582
583
|
asl = model.get_areas()[istat]['slots']
|
femagtools/model.py
CHANGED
@@ -386,6 +386,13 @@ class MachineModel(Model):
|
|
386
386
|
if mcv:
|
387
387
|
logger.debug('shaft mcv %s', mcv)
|
388
388
|
rotor['mcvkey_shaft'] = magcurves.fix_name(mcv)
|
389
|
+
mshaft = magcurves.find_by_name(mcv)
|
390
|
+
thkeys_shaft = ['thcond', 'thcap', 'rho']
|
391
|
+
if mshaft and set(thkeys_shaft).issubset(mshaft.keys()):
|
392
|
+
for k in thkeys_shaft:
|
393
|
+
rotor[k+'_shaft'] = mshaft[k]
|
394
|
+
rotor['spmaweight_shaft'] = rotor['rho_shaft']
|
395
|
+
|
389
396
|
self.stator['mcvkey_shaft_name'] = mcv
|
390
397
|
names.append((mcv, 1.0))
|
391
398
|
else:
|
femagtools/moo/population.py
CHANGED
@@ -198,21 +198,23 @@ class Population:
|
|
198
198
|
self.update_pareto_information()
|
199
199
|
retval = [[] for s in range(max(self.pareto_rank)+1)]
|
200
200
|
for i, j in enumerate(self.individuals):
|
201
|
-
retval[self.pareto_rank[i]].append(
|
201
|
+
retval[self.pareto_rank[i]].append(j)
|
202
202
|
return retval
|
203
203
|
|
204
204
|
def compute_ideal(self):
|
205
|
-
return [min(x)
|
205
|
+
return [np.min(np.array(x)[np.isfinite(x)])
|
206
206
|
for x in zip(*[i.cur_f
|
207
|
-
for i in self.individuals
|
207
|
+
for i in self.individuals
|
208
|
+
if i.rank == 0])]
|
208
209
|
|
209
210
|
def compute_nadir(self):
|
210
|
-
return [max(x)
|
211
|
+
return [np.max(np.array(x)[np.isfinite(x)])
|
211
212
|
for x in zip(*[i.cur_f
|
212
|
-
for i in self.individuals
|
213
|
+
for i in self.individuals
|
214
|
+
if i.rank == 0])]
|
213
215
|
|
214
216
|
def compute_worst(self):
|
215
|
-
return [max(x)
|
217
|
+
return [np.max(np.array(x)[np.isfinite(x)])
|
216
218
|
for x in zip(*[i.cur_f
|
217
219
|
for i in self.individuals])]
|
218
220
|
|
@@ -252,7 +254,7 @@ class Population:
|
|
252
254
|
raise ValueError(
|
253
255
|
'Invalid components of the objective function selected for plot')
|
254
256
|
|
255
|
-
p_dim = self.problem.
|
257
|
+
p_dim = self.problem.f_dim
|
256
258
|
|
257
259
|
if p_dim == 1:
|
258
260
|
raise ValueError(
|