femagtools 1.7.5__py3-none-any.whl → 1.7.7__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/bch.py +11 -1
- femagtools/dxfsl/area.py +108 -7
- femagtools/dxfsl/conv.py +15 -0
- femagtools/dxfsl/converter.py +44 -20
- femagtools/dxfsl/fslrenderer.py +93 -42
- femagtools/dxfsl/functions.py +8 -0
- femagtools/dxfsl/geom.py +126 -18
- femagtools/dxfsl/machine.py +30 -9
- femagtools/femag.py +3 -3
- femagtools/fsl.py +73 -48
- femagtools/isa7.py +2 -2
- femagtools/machine/effloss.py +2 -0
- femagtools/machine/pm.py +198 -42
- femagtools/machine/sm.py +294 -253
- femagtools/machine/utils.py +5 -14
- femagtools/model.py +32 -2
- femagtools/moo/algorithm.py +6 -0
- femagtools/nc.py +2 -0
- femagtools/opt.py +2 -1
- femagtools/plot/bch.py +19 -5
- femagtools/plot/char.py +4 -4
- femagtools/plot/nc.py +21 -4
- femagtools/plot/wdg.py +38 -26
- femagtools/templates/gen_hairpin_winding.mako +209 -0
- femagtools/templates/gen_winding.mako +8 -9
- femagtools/templates/magnetIron.mako +32 -6
- femagtools/templates/mesh-airgap.mako +9 -0
- femagtools/templates/rotor_winding.mako +10 -6
- femagtools/templates/statorRotor3.mako +8 -5
- femagtools/windings.py +31 -18
- {femagtools-1.7.5.dist-info → femagtools-1.7.7.dist-info}/METADATA +1 -1
- {femagtools-1.7.5.dist-info → femagtools-1.7.7.dist-info}/RECORD +38 -37
- {femagtools-1.7.5.dist-info → femagtools-1.7.7.dist-info}/WHEEL +1 -1
- tests/test_windings.py +1 -1
- {femagtools-1.7.5.dist-info → femagtools-1.7.7.dist-info}/LICENSE +0 -0
- {femagtools-1.7.5.dist-info → femagtools-1.7.7.dist-info}/entry_points.txt +0 -0
- {femagtools-1.7.5.dist-info → femagtools-1.7.7.dist-info}/top_level.txt +0 -0
femagtools/machine/utils.py
CHANGED
@@ -14,7 +14,7 @@ logger = logging.getLogger(__name__)
|
|
14
14
|
|
15
15
|
def K(d):
|
16
16
|
"""space phasor transformation matrix
|
17
|
-
(Inverse Park Transformation) T-1 * dq
|
17
|
+
(Inverse Park Transformation) T-1 * dq --> abc
|
18
18
|
arguments:
|
19
19
|
d: rotation angle
|
20
20
|
|
@@ -28,7 +28,7 @@ def K(d):
|
|
28
28
|
|
29
29
|
def T(d):
|
30
30
|
"""space phasor transformation matrix
|
31
|
-
(Park Transformation) T * abc
|
31
|
+
(Park Transformation) T * abc --> dq
|
32
32
|
arguments:
|
33
33
|
d: rotation angle
|
34
34
|
|
@@ -390,21 +390,12 @@ def dqparident(workdir, engine, temp, machine,
|
|
390
390
|
fcu = 0.42
|
391
391
|
|
392
392
|
try: # calc basic dimensions if not fsl or dxf model
|
393
|
+
from ..model import MachineModel
|
393
394
|
wdg = create_wdg(machine)
|
394
395
|
Q1 = wdg.Q
|
395
|
-
|
396
|
-
machine['stator'][k], dict)][-1]
|
397
|
-
if slotmodel == 'stator1':
|
398
|
-
hs = machine['stator']['stator1']['slot_rf1'] - \
|
399
|
-
machine['stator']['stator1']['tip_rh1']
|
400
|
-
else:
|
401
|
-
da1 = machine['bore_diam']
|
402
|
-
dy1 = machine['outer_diam']
|
403
|
-
hs = machine['stator'][slotmodel].get(
|
404
|
-
'slot_height', 0.6*(dy1-da1)/2)
|
405
|
-
|
396
|
+
model = MachineModel(machine)
|
406
397
|
Jmax = 30e6 # max current density in A/m2
|
407
|
-
Acu = fcu*
|
398
|
+
Acu = fcu*model.slot_area() # approx. copper area of one slot
|
408
399
|
i1_max = round(g*Acu/wdg.l/N*Jmax/10)*10
|
409
400
|
except KeyError:
|
410
401
|
if kwargs.get('i1_max', 0) == 0:
|
femagtools/model.py
CHANGED
@@ -15,6 +15,12 @@ MODELNAME_CHARS = string.printable[:63] + "-_äöüéè"
|
|
15
15
|
# maximum name length
|
16
16
|
MAX_MODEL_NAME_LEN = 255
|
17
17
|
|
18
|
+
default_th_properties = {
|
19
|
+
"spmaweight": 8.96,
|
20
|
+
"tempcoef": 3.9e-3,
|
21
|
+
"thcond": 30,
|
22
|
+
"thcap": 480
|
23
|
+
}
|
18
24
|
|
19
25
|
def movesteps(nodes):
|
20
26
|
"""returns list of move steps
|
@@ -191,6 +197,28 @@ class MachineModel(Model):
|
|
191
197
|
except (KeyError, AttributeError):
|
192
198
|
pass
|
193
199
|
|
200
|
+
def slot_height(self):
|
201
|
+
if 'statorRotor3' in self.stator:
|
202
|
+
return self.stator['statorRotor3']['slot_height']
|
203
|
+
if 'stator1' in self.stator:
|
204
|
+
return self.stator['stator1']['slot_rf1'] - self.stator['stator1']['tip_rh1']
|
205
|
+
if 'stator4' in self.stator:
|
206
|
+
return self.stator['stator4']['slot_height']
|
207
|
+
da1 = self.bore_diam
|
208
|
+
if self.external_rotor:
|
209
|
+
yh = da1-self.inner_diam
|
210
|
+
else:
|
211
|
+
yh = da1+self.outer_diam
|
212
|
+
return 0.6*yh/2
|
213
|
+
|
214
|
+
def slot_area(self):
|
215
|
+
if 'slot_area' in self.stator:
|
216
|
+
return self.stator['slot_area']
|
217
|
+
da1 = self.bore_diam
|
218
|
+
Q1 = self.stator['num_slots']
|
219
|
+
hs = self.slot_height()
|
220
|
+
return np.pi*hs*(da1+hs)/Q1/2
|
221
|
+
|
194
222
|
def set_num_slots_gen(self):
|
195
223
|
if 'num_slots_gen' not in self.stator:
|
196
224
|
try:
|
@@ -392,6 +420,8 @@ class MachineModel(Model):
|
|
392
420
|
for k in self.rotor:
|
393
421
|
# anything that is a dict must represent the type
|
394
422
|
if isinstance(self.rotor[k], dict):
|
423
|
+
if k == 'rot_hsm':
|
424
|
+
return 'EESM'
|
395
425
|
return k
|
396
426
|
raise AttributeError("Missing rotor model in {}".format(self.magnet))
|
397
427
|
|
@@ -429,11 +459,11 @@ class MachineModel(Model):
|
|
429
459
|
def props(self):
|
430
460
|
"""returns dict of this model"""
|
431
461
|
keys = ('name', 'poles', 'outer_diam', 'airgap',
|
432
|
-
'bore_diam', 'external_rotor', 'agndst')
|
462
|
+
'bore_diam', 'inner_diam', 'external_rotor', 'agndst')
|
433
463
|
model = {k: getattr(self, k) for k in keys if hasattr(self, k)}
|
434
464
|
if hasattr(self, 'stator'):
|
435
465
|
model['stator'] = {k: self.stator[k]
|
436
|
-
for k in ('num_slots', 'num_slots_gen')
|
466
|
+
for k in ('num_slots', 'num_slots_gen', 'slot_area')
|
437
467
|
if k in self.stator}
|
438
468
|
return model
|
439
469
|
|
femagtools/moo/algorithm.py
CHANGED
@@ -71,6 +71,9 @@ class Nsga2:
|
|
71
71
|
rnd*alpha))**(1.0/(self.eta_c+1.0))
|
72
72
|
|
73
73
|
c1 = 0.5*((y1+y2)-betaq*(y2-y1))
|
74
|
+
if isinstance(c1, complex):
|
75
|
+
logger.warning(f"c1 {c1} is complex")
|
76
|
+
c1 = abs(c1)
|
74
77
|
|
75
78
|
beta = 1.0 + (2.0*(yu-y2)/(y2-y1))
|
76
79
|
alpha = 2.0 - beta**(-(self.eta_c+1.0))
|
@@ -81,6 +84,9 @@ class Nsga2:
|
|
81
84
|
rnd*alpha))**(1.0/(self.eta_c+1.0))
|
82
85
|
|
83
86
|
c2 = 0.5*((y1+y2)+betaq*(y2-y1))
|
87
|
+
if isinstance(c2, complex):
|
88
|
+
logger.warning(f"c2 {c2} is complex")
|
89
|
+
c2 = abs(c2)
|
84
90
|
|
85
91
|
if c1<yl : c1=yl
|
86
92
|
if c2<yl : c2=yl
|
femagtools/nc.py
CHANGED
@@ -191,6 +191,8 @@ class Reader(object):
|
|
191
191
|
self.speed = float(grp.variables['speed'].getValue().data)
|
192
192
|
self.FC_RADIUS = float(grp.variables['fc_radius'].getValue().data)
|
193
193
|
self.pole_pairs = int(grp.variables['pole_pairs'].getValue().data)
|
194
|
+
self.layers = int(grp.variables['num_layers'].getValue().data)
|
195
|
+
self.coil_span = int(grp.variables['coil_span'].getValue().data)
|
194
196
|
self.delta_node_angle = float( # rad
|
195
197
|
grp.variables['delta_node_angle'].getValue().data)
|
196
198
|
self.poles_sim = int(grp.variables['poles_sim'].getValue().data)
|
femagtools/opt.py
CHANGED
@@ -77,7 +77,8 @@ class Optimizer(object):
|
|
77
77
|
set_magnet_properties(self.model, self.fea, self.femag.magnets)
|
78
78
|
task.add_file('femag.fsl',
|
79
79
|
self.builder.create(self.model, self.fea,
|
80
|
-
self.femag.magnets
|
80
|
+
self.femag.magnets,
|
81
|
+
self.femag.condMat))
|
81
82
|
if 'poc' in self.fea:
|
82
83
|
task.add_file(self.fea['pocfilename'],
|
83
84
|
self.fea['poc'].content())
|
femagtools/plot/bch.py
CHANGED
@@ -508,19 +508,33 @@ def transientsc(bch, title=''):
|
|
508
508
|
row = 1
|
509
509
|
plt.subplot(rows, cols, row)
|
510
510
|
ax = plt.gca()
|
511
|
-
ax.set_title('Currents / A')
|
512
511
|
ax.grid(True)
|
513
|
-
|
514
|
-
|
512
|
+
istat = np.array([bch.scData[i]
|
513
|
+
for i in ('ia', 'ib', 'ic')])
|
514
|
+
if np.max(istat) > 4000:
|
515
|
+
istat *= 1e-3
|
516
|
+
ax.set_title('Currents / kA')
|
517
|
+
else:
|
518
|
+
ax.set_title('Currents / A')
|
519
|
+
|
520
|
+
for i, iph in zip(('ia', 'ib', 'ic'), istat):
|
521
|
+
ax.plot(bch.scData['time'], iph, label=i)
|
515
522
|
ax.set_xlabel('Time / s')
|
516
523
|
ax.legend()
|
517
524
|
|
518
525
|
row = 2
|
519
526
|
plt.subplot(rows, cols, row)
|
520
527
|
ax = plt.gca()
|
521
|
-
|
528
|
+
scale = 1
|
529
|
+
torque = np.array(bch.scData['torque'])
|
530
|
+
if np.max(torque) > 4000:
|
531
|
+
torque *= 1e-3
|
532
|
+
ax.set_title('Torque / kNm')
|
533
|
+
else:
|
534
|
+
ax.set_title('Torque / Nm')
|
535
|
+
|
522
536
|
ax.grid(True)
|
523
|
-
ax.plot(bch.scData['time'],
|
537
|
+
ax.plot(bch.scData['time'], torque)
|
524
538
|
ax.set_xlabel('Time / s')
|
525
539
|
|
526
540
|
fig.tight_layout(h_pad=2)
|
femagtools/plot/char.py
CHANGED
@@ -326,15 +326,15 @@ def _plot_contour(speed, torque, z, ax, title='', levels=[],
|
|
326
326
|
contf = ax.tricontourf(x, y, z,
|
327
327
|
levels=levels, cmap=cmap)
|
328
328
|
|
329
|
+
#ax.plot(x, y, "k.", ms=3)
|
330
|
+
if clabel:
|
331
|
+
ax.clabel(cont, inline=True, colors='k', fontsize=8, inline_spacing=0)
|
332
|
+
|
329
333
|
clippath = Path(_get_nT_boundary(x, y))
|
330
334
|
patch = PathPatch(clippath, facecolor='none')
|
331
335
|
ax.add_patch(patch)
|
332
336
|
for c in cont.collections:
|
333
337
|
c.set_clip_path(patch)
|
334
|
-
#ax.plot(x, y, "k.", ms=3)
|
335
|
-
if clabel:
|
336
|
-
ax.clabel(cont, inline=True, colors='k', fontsize=8, inline_spacing=0)
|
337
|
-
|
338
338
|
for c in contf.collections:
|
339
339
|
c.set_clip_path(patch)
|
340
340
|
|
femagtools/plot/nc.py
CHANGED
@@ -30,10 +30,27 @@ def spel(isa, superelements=[], with_axis=False, ax=0):
|
|
30
30
|
spels = isa.superelements
|
31
31
|
for se in spels:
|
32
32
|
ax.add_patch(Polygon([n.xy
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
for nc in se.nodechains
|
34
|
+
for n in nc.nodes],
|
35
|
+
color=isa.color[se.color], lw=0))
|
36
|
+
try:
|
37
|
+
# draw wire direction
|
38
|
+
if se.subregion:
|
39
|
+
if se.subregion.curdir != 0:
|
40
|
+
wkey = se.subregion.winding.key
|
41
|
+
if se.subregion.curdir < 0:
|
42
|
+
label = str(se.subregion.curdir*wkey)
|
43
|
+
else:
|
44
|
+
label = '+'+str(se.subregion.curdir*wkey)
|
45
|
+
|
46
|
+
xy = np.array([n.xy
|
47
|
+
for nc in se.nodechains
|
48
|
+
for n in nc.nodes])
|
49
|
+
cx, cy = np.mean(np.unique(xy[:, 0])), np.mean(np.unique(xy[:, -1]))
|
50
|
+
ax.text(cx, cy, label, rotation=np.arctan2(cy, cx)/np.pi*180-90,
|
51
|
+
horizontalalignment='center', verticalalignment='center')
|
52
|
+
except:
|
53
|
+
pass
|
37
54
|
ax.autoscale(enable=True)
|
38
55
|
if not with_axis:
|
39
56
|
ax.axis('off')
|
femagtools/plot/wdg.py
CHANGED
@@ -48,19 +48,28 @@ def mmf_fft(f, title='', mmfmin=1e-2, ax=0):
|
|
48
48
|
pass
|
49
49
|
|
50
50
|
|
51
|
-
def zoneplan(wdg, ax=0):
|
51
|
+
def zoneplan(wdg, write_title=True, max_slots=0, ax=0):
|
52
52
|
"""plot zone plan of winding wdg"""
|
53
53
|
from matplotlib.patches import Rectangle
|
54
54
|
upper, lower = wdg.zoneplan()
|
55
55
|
Qb = len([n for l in upper for n in l])
|
56
|
+
if max_slots:
|
57
|
+
Qb = max_slots
|
56
58
|
from femagtools.windings import coil_color
|
57
|
-
|
59
|
+
h = 0.5
|
60
|
+
w = 1
|
61
|
+
dx = -1.5, -1.5
|
62
|
+
dt = 0.5, 0.5
|
63
|
+
yl = 0, 0.
|
64
|
+
ymax = h
|
58
65
|
if lower:
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
66
|
+
if wdg.q < 1:
|
67
|
+
dx = -1, -1.5
|
68
|
+
dt = 0.2, 0.2
|
69
|
+
w = 0.5
|
70
|
+
else:
|
71
|
+
yl = h, 0
|
72
|
+
ymax = 2*h
|
64
73
|
if ax == 0:
|
65
74
|
ax = plt.gca()
|
66
75
|
ax.axis('off')
|
@@ -70,28 +79,31 @@ def zoneplan(wdg, ax=0):
|
|
70
79
|
|
71
80
|
for i, p in enumerate(upper):
|
72
81
|
for x in p:
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
82
|
+
if abs(x) < Qb+1:
|
83
|
+
ax.add_patch(Rectangle((abs(x)+dx[0], yl[0]), w, h,
|
84
|
+
facecolor=coil_color[i],
|
85
|
+
edgecolor='white', fill=True))
|
86
|
+
s = f'+{i+1}' if x > 0 else f'-{i+1}'
|
87
|
+
ax.text(abs(x)+dx[0]+dt[0], yl[0]+h/2, s, color='black',
|
88
|
+
ha="center", va="center")
|
79
89
|
for i, p in enumerate(lower):
|
80
90
|
for x in p:
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
91
|
+
if abs(x) < Qb+1:
|
92
|
+
ax.add_patch(Rectangle((abs(x)+dx[1], yl[1]), w, h,
|
93
|
+
facecolor=coil_color[i],
|
94
|
+
edgecolor='white', fill=True))
|
95
|
+
s = f'+{i+1}' if x > 0 else f'-{i+1}'
|
96
|
+
ax.text(abs(x)+dx[1]+dt[1], yl[1]+h/2, s, color='black',
|
97
|
+
ha="center", va="center")
|
98
|
+
|
99
|
+
yu = yl[0]+h
|
89
100
|
step = 1 if Qb < 25 else 2
|
90
|
-
|
91
|
-
yl -= rh
|
101
|
+
yl = min(yl)
|
92
102
|
margin = 0.05
|
93
|
-
|
94
|
-
|
103
|
+
if write_title:
|
104
|
+
ax.text(-0.5, yu+margin,
|
105
|
+
f'Q={wdg.Q}, p={wdg.p}, q={round(wdg.q,4)}, yd={wdg.yd}',
|
106
|
+
ha='left', va='bottom', size=15)
|
95
107
|
for i in range(0, Qb, step):
|
96
108
|
ax.text(i, yl-margin, f'{i+1}', ha="center", va="top")
|
97
109
|
|
@@ -99,7 +111,7 @@ def zoneplan(wdg, ax=0):
|
|
99
111
|
def winding_factors(wdg, n=8, ax=0):
|
100
112
|
"""plot winding factors"""
|
101
113
|
ax = plt.gca()
|
102
|
-
ax.set_title(f'Winding factors Q={wdg.Q}, p={wdg.p}, q={round(wdg.q,4)}')
|
114
|
+
ax.set_title(f'Winding factors Q={wdg.Q}, p={wdg.p}, q={round(wdg.q,4)}, yd={wdg.yd}')
|
103
115
|
ax.grid(True)
|
104
116
|
order, kwp, kwd, kw = np.array(
|
105
117
|
[(n, k1, k2, k3)
|
@@ -0,0 +1,209 @@
|
|
1
|
+
-- hairpin winding template
|
2
|
+
|
3
|
+
rcoil, phi_coil = c2pd(m.xcoil_1, m.ycoil_1)
|
4
|
+
|
5
|
+
slot_div_angle = 360/m.tot_num_slot
|
6
|
+
|
7
|
+
-- delete existing mesh in the slot
|
8
|
+
for i = 1, m.num_sl_gen do
|
9
|
+
xc, yc = pd2c(rcoil, phi_coil+(i-1)*slot_div_angle)
|
10
|
+
delete_mesh_se(xc, yc)
|
11
|
+
end
|
12
|
+
-- wire params
|
13
|
+
wire_height = ${model['wire']["wire_height"]*1e3}
|
14
|
+
wire_width = ${model['wire']["wire_width"]*1e3}
|
15
|
+
wire_corner_r = ${model['wire']["corner_radius"]*1e3}
|
16
|
+
wire_gap = ${model['wire']["wire_separation"]*1e3}
|
17
|
+
TH1 = ${model['wire']["wire_th1"]*1e3} -- distance to the bore radius
|
18
|
+
nwires = ${model['wire']["num_layers"]}
|
19
|
+
|
20
|
+
fml = require "fml"
|
21
|
+
|
22
|
+
function line_xy(pnt1, pnt2, nnodes)
|
23
|
+
-- create line
|
24
|
+
nc_line(pnt1.x, pnt1.y, pnt2.x, pnt2.y, nnodes)
|
25
|
+
end
|
26
|
+
|
27
|
+
function circle_xy(pnt1, pnt2, cx, cy, nnodes)
|
28
|
+
-- create circle
|
29
|
+
nc_circle_m(pnt1.x, pnt1.y, pnt2.x, pnt2.y, cx, cy, nnodes)
|
30
|
+
end
|
31
|
+
|
32
|
+
function draw_rectangle_wire(dx, dy, dphi, wire_height, wire_width, r0, agndst)
|
33
|
+
|
34
|
+
local x = {}
|
35
|
+
local y = {}
|
36
|
+
local x1 = {}
|
37
|
+
local y1 = {}
|
38
|
+
local hl = {}
|
39
|
+
local hi = {}
|
40
|
+
local hj = {}
|
41
|
+
local hk = {}
|
42
|
+
local xcp, ycp
|
43
|
+
local tmpx, tmpy, tmpr, tmpp
|
44
|
+
|
45
|
+
h1 = fml.Point:Create(dx, 0)
|
46
|
+
h2 = fml.Point:Create(dx, -wire_width/2+dy)
|
47
|
+
he = fml.Point:Create(dx+wire_height, 0)
|
48
|
+
|
49
|
+
hl[1] = fml.Line:Create(h1, 90)
|
50
|
+
hl[2] = fml.Line:Parallel(hl[1], wire_height)
|
51
|
+
hl[3] = fml.Line:Create(h2, 0)
|
52
|
+
hl[4] = fml.Line:Parallel(hl[3], -wire_width)
|
53
|
+
|
54
|
+
hi[1] = fml.Point:Intersection(hl[1], hl[3])
|
55
|
+
hi[2] = fml.Point:Intersection(hl[1], hl[4])
|
56
|
+
hi[3] = fml.Point:Intersection(hl[2], hl[4])
|
57
|
+
hi[4] = fml.Point:Intersection(hl[2], hl[3])
|
58
|
+
-- with corner
|
59
|
+
if r0 > 0 then
|
60
|
+
s1 = {1, 1, 2, 2}
|
61
|
+
s2 = {3, 4, 4, 3}
|
62
|
+
s3 = {1, 4, 3, 2}
|
63
|
+
ctr = 1
|
64
|
+
|
65
|
+
for i =1, 4 do
|
66
|
+
hj[ctr], hj[ctr+1], hj[ctr+2] = fml.Point:Rounding(hl[s1[i]], hl[s2[i]], r0, s3[i])
|
67
|
+
ctr = ctr + 3
|
68
|
+
end
|
69
|
+
|
70
|
+
for j = 1, #hj do
|
71
|
+
tmpr, tmpp = c2pd(hj[j].x, hj[j].y)
|
72
|
+
tmpx, tmpy = pd2c(tmpr, tmpp+dphi)
|
73
|
+
hk[j] = fml.Point:Create(tmpx, tmpy)
|
74
|
+
end
|
75
|
+
|
76
|
+
dst = agndst/2
|
77
|
+
ah1 = fml.Point:Create((hk[12].x+hk[8].x)/2 , (hk[12].y+hk[8].y)/2)
|
78
|
+
ah2 = fml.Point:Create((hk[6].x+hk[2].x)/2 , (hk[6].y+hk[2].y)/2)
|
79
|
+
|
80
|
+
line_xy(hk[12], ah1, 0)
|
81
|
+
line_xy(ah1, hk[8], 0)
|
82
|
+
line_xy(hk[9], hk[5], 0)
|
83
|
+
line_xy( hk[6], ah2, 0)
|
84
|
+
|
85
|
+
line_xy(ah2, hk[2], 0)
|
86
|
+
line_xy(hk[3], hk[11], 0)
|
87
|
+
|
88
|
+
circle_xy(hk[8], hk[9], hk[7].x, hk[7].y, 6)
|
89
|
+
circle_xy(hk[5], hk[6], hk[4].x, hk[4].y, 6)
|
90
|
+
circle_xy(hk[2], hk[3], hk[1].x, hk[1].y, 6)
|
91
|
+
circle_xy(hk[11], hk[12], hk[10].x, hk[10].y, 6)
|
92
|
+
xcp = (hk[12].x + hk[6].x)/2
|
93
|
+
ycp = (hk[12].y + hk[6].y)/2
|
94
|
+
|
95
|
+
else
|
96
|
+
xcp = 0
|
97
|
+
ycp = 0
|
98
|
+
|
99
|
+
for i = 1, 4 do
|
100
|
+
x[i], y[i] = hi[i].x, hi[i].y
|
101
|
+
tmpr, tmpp = c2pd(x[i], y[i])
|
102
|
+
tmpx, tmpy = pd2c(tmpr, tmpp+dphi)
|
103
|
+
x1[i], y1[i] = tmpx, tmpy
|
104
|
+
xcp = xcp + tmpx/4
|
105
|
+
ycp = ycp + tmpy/4
|
106
|
+
end
|
107
|
+
|
108
|
+
nc_line(x1[1], y1[1], x1[2], y1[2], 0)
|
109
|
+
nc_line_cont(x1[3], y1[3], 0)
|
110
|
+
nc_line_cont(x1[4], y1[4], 0)
|
111
|
+
nc_line_cont(x1[1], y1[1], 0)
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
return xcp, ycp, ah1, ah2
|
116
|
+
end
|
117
|
+
|
118
|
+
-- hairpin winding
|
119
|
+
wire_xy = {}
|
120
|
+
x0, y0 = da1/2+TH1, 0
|
121
|
+
auh1 = {}
|
122
|
+
auh2 = {}
|
123
|
+
|
124
|
+
for j = 1, m.num_sl_gen do
|
125
|
+
wire_xy[j] = {}
|
126
|
+
for k = 1, nwires do
|
127
|
+
wire_xy[j][k] = 0.0
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
ndt(agndst)
|
132
|
+
for j = 1, m.num_sl_gen do
|
133
|
+
for i = 1, nwires do
|
134
|
+
dx, dy = x0+(wire_gap+wire_height)*(i-1), y0
|
135
|
+
xcp, ycp, ah1, ah2 = draw_rectangle_wire(dx, dy, 360/m.tot_num_slot/2*(2*j-1), wire_height, wire_width, wire_corner_r, agndst)
|
136
|
+
wire_xy[j][nwires - (i-1)] = fml.Point:Create(xcp, ycp) -- large radius to smaller radius
|
137
|
+
create_mesh_se(xcp, ycp)
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
create_mesh()
|
142
|
+
|
143
|
+
-- create winding
|
144
|
+
|
145
|
+
widfile = io.open("wid.fsl", 'r')
|
146
|
+
|
147
|
+
nrows = 1
|
148
|
+
winding = {}
|
149
|
+
|
150
|
+
for i in widfile:lines() do
|
151
|
+
winding[nrows] = {}
|
152
|
+
ncols = 1
|
153
|
+
for j in string.gmatch(i, "[+-]?%d+") do
|
154
|
+
winding[nrows][ncols] = tonumber(j)
|
155
|
+
ncols = ncols + 1
|
156
|
+
end
|
157
|
+
nrows = nrows + 1
|
158
|
+
end
|
159
|
+
|
160
|
+
--[[
|
161
|
+
|
162
|
+
winding table
|
163
|
+
|
164
|
+
1 slot_go pos_in_slot slot_ret pos_in_slot
|
165
|
+
|
166
|
+
]]--
|
167
|
+
dir = 'wi'
|
168
|
+
cols = {"green", "yellow", "cyan"}
|
169
|
+
wk = 1
|
170
|
+
for i = 1, #winding do
|
171
|
+
idx = winding[i][2]
|
172
|
+
idxp = winding[i][3]
|
173
|
+
idy = winding[i][4]
|
174
|
+
idyp = winding[i][5]
|
175
|
+
|
176
|
+
if i == 1 then
|
177
|
+
if idx <= m.num_sl_gen then
|
178
|
+
wkey = def_new_wdg(wire_xy[idx][idxp].x, wire_xy[idx][idxp].y, cols[winding[i][1]], "Phase"..winding[i][1], 1, 0, 0, dir)
|
179
|
+
end
|
180
|
+
|
181
|
+
if math.abs(idy) <= m.num_sl_gen then
|
182
|
+
add_to_wdg (wire_xy[math.abs(idy)][idyp].x, wire_xy[math.abs(idy)][idyp].y, "wsamekey", "wo", "wser")
|
183
|
+
end
|
184
|
+
else
|
185
|
+
if winding[i][1] == winding[i-1][1] and winding[i][1] == wk then
|
186
|
+
if idx <= m.num_sl_gen then
|
187
|
+
add_to_wdg (wire_xy[idx][idxp].x, wire_xy[idx][idxp].y, "wsamekey", dir, "wser")
|
188
|
+
end
|
189
|
+
if math.abs(idy) <= m.num_sl_gen then
|
190
|
+
add_to_wdg (wire_xy[math.abs(idy)][idyp].x, wire_xy[math.abs(idy)][idyp].y, "wsamekey", "wo", "wser")
|
191
|
+
end
|
192
|
+
else
|
193
|
+
if idx <= m.num_sl_gen then
|
194
|
+
wkey = def_new_wdg(wire_xy[idx][idxp].x, wire_xy[idx][idxp].y, cols[winding[i][1]], "Phase"..winding[i][1], 1, 0, 0, dir)
|
195
|
+
wk = wk + 1
|
196
|
+
end
|
197
|
+
if math.abs(idy) <= m.num_sl_gen then
|
198
|
+
if wk == winding[i][1] then
|
199
|
+
add_to_wdg (wire_xy[math.abs(idy)][idyp].x, wire_xy[math.abs(idy)][idyp].y, "wsamekey", "wo", "wser")
|
200
|
+
else
|
201
|
+
wkey = def_new_wdg(wire_xy[math.abs(idy)][idyp].x, wire_xy[math.abs(idy)][idyp].y, cols[winding[i][1]], "Phase"..winding[i][1], 1, 0, 0, "wo")
|
202
|
+
wk = wk + 1
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
m.num_par_wdgs = ${model.get('num_par_wdgs', 1)}
|
@@ -99,20 +99,19 @@ if m.slot_height ~= nil then
|
|
99
99
|
elseif m.middle_line == 2 then
|
100
100
|
dr = 1
|
101
101
|
end
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
cap = capCu*da^2/(dCu^2*math.pi/4)
|
102
|
+
|
103
|
+
density = ${model.windings['spmaweight']*1e3}
|
104
|
+
lam = ${model.windings['thcond']}
|
105
|
+
cap = ${model.windings['thcap']}
|
106
|
+
|
108
107
|
for i=1,m.num_sl_gen do
|
109
108
|
a = (2*i-1)*math.pi/m.tot_num_sl + m.zeroangl/180*math.pi
|
110
109
|
xwl,ywl = pr2c(rw+dr,a+dw)
|
111
|
-
def_mat_therm(xwl,ywl,'yellow',
|
110
|
+
def_mat_therm(xwl,ywl,'yellow',density,lam,cap,1)
|
112
111
|
if m.middle_line > 0 then
|
113
112
|
xwr,ywr = pr2c(rw-dr,a-dw)
|
114
|
-
def_mat_therm(xwr,ywr,'yellow',
|
113
|
+
def_mat_therm(xwr,ywr,'yellow',density,lam,cap,1)
|
115
114
|
end
|
116
115
|
end
|
117
116
|
end
|
118
|
-
%endif
|
117
|
+
%endif
|
@@ -44,16 +44,25 @@ beta = math.pi/m.num_poles
|
|
44
44
|
xrb,yrb = pr2c(m.yoke_rad+0.1, beta) -- rotor lamination
|
45
45
|
thcond = ${model['thcond']}
|
46
46
|
thcap = ${model['thcap']}
|
47
|
-
|
48
|
-
def_mat_therm(
|
47
|
+
density = ${model.get('density')*1e3}
|
48
|
+
def_mat_therm(xrb,yrb,'blue',density,thcond,thcap,1)
|
49
49
|
|
50
|
+
%if model.get('thcond_shaft', 0) and model.get('thcap_shaft', 0):
|
51
|
+
if m.shaft_rad < m.yoke_rad then
|
52
|
+
thcond = ${model['thcond_shaft']}
|
53
|
+
thcap = ${model['thcap_shaft']}
|
54
|
+
density = ${model['spmaweight_shaft']*1e3}
|
55
|
+
def_mat_therm(m.yoke_rad/2,0.1,'blue',density,thcond,thcap,1) -- Shaft
|
56
|
+
end
|
57
|
+
%endif
|
50
58
|
rm = m.magn_rad*math.cos(beta)
|
51
|
-
|
52
|
-
|
59
|
+
density = ${model['spmaweight_magnet']*1e3}
|
60
|
+
thcond = ${model.get('thcond_magnet', 8)}
|
61
|
+
thcap = ${model.get('thcap_magnet', 440)}
|
53
62
|
for i = 1,m.npols_gen do -- Magnete
|
54
63
|
alfa = (2*i-1) * beta
|
55
64
|
xmx,ymx = pr2c(rm,alfa)
|
56
|
-
def_mat_therm(xmx,ymx,darkgreen-i%2,
|
65
|
+
def_mat_therm(xmx,ymx,darkgreen-i%2,density,thcond,thcap,1)
|
57
66
|
end
|
58
67
|
|
59
68
|
if m.air_triangle > 0 then
|
@@ -67,4 +76,21 @@ if m.air_triangle > 0 then
|
|
67
76
|
def_mat_therm(xsx,ysx,skyblue,1.12,0.026,1007,1)
|
68
77
|
end
|
69
78
|
end
|
70
|
-
|
79
|
+
|
80
|
+
|
81
|
+
-- add air layer (inside) for heat transfer
|
82
|
+
h = 3.8
|
83
|
+
beta = 360*m.npols_gen/m.num_poles
|
84
|
+
|
85
|
+
|
86
|
+
x0, y0 = pd2c(m.shaft_rad, m.zeroangl)
|
87
|
+
x1, y1 = pd2c(m.shaft_rad-h, m.zeroangl)
|
88
|
+
x2, y2 = pd2c(m.shaft_rad-h, beta+m.zeroangl)
|
89
|
+
x3, y3 = pd2c(m.shaft_rad, beta+m.zeroangl)
|
90
|
+
nc_line(x0, y0, x1, y1, 0)
|
91
|
+
nc_circle(x1, y1, x2, y2, 0)
|
92
|
+
nc_line(x2, y2, x3, y3, 0)
|
93
|
+
x0, y0 = pd2c(m.shaft_rad-h/2, beta/2+m.zeroangl)
|
94
|
+
create_mesh_se(x0, y0)
|
95
|
+
|
96
|
+
%endif
|
@@ -14,13 +14,22 @@ if not airgap_created then
|
|
14
14
|
end
|
15
15
|
% if hasattr(model, 'bore_diam'):
|
16
16
|
r1 = m.fc_radius - ag/6
|
17
|
+
if(m.npols_gen == m.num_poles) then
|
18
|
+
alfa = alfa / 2
|
19
|
+
end
|
17
20
|
x1, y1 = pr2c(r1, alfa)
|
18
21
|
n = math.floor(m.fc_radius*alfa/agndst + 1.5)
|
19
22
|
nc_circle_m(r1, 0, x1, y1, 0.0, 0.0, n)
|
23
|
+
if(m.npols_gen == m.num_poles) then
|
24
|
+
nc_circle_m(x1, y1, r1, 0, 0.0, 0.0, n)
|
25
|
+
end
|
20
26
|
|
21
27
|
r2 = m.fc_radius + ag/6
|
22
28
|
x2, y2 = pr2c(r2, alfa)
|
23
29
|
nc_circle_m(r2, 0, x2, y2, 0.0, 0.0, n)
|
30
|
+
if(m.npols_gen == m.num_poles) then
|
31
|
+
nc_circle_m(x2, y2, r2, 0, 0.0, 0.0, n)
|
32
|
+
end
|
24
33
|
|
25
34
|
if inner_da_start == nil then
|
26
35
|
inner_da_start = da2/2
|
@@ -1,12 +1,16 @@
|
|
1
|
-
-- Winding (ROT_HSM
|
1
|
+
-- Winding (ROT_HSM or dxf)
|
2
2
|
m.num_wires = ${model['num_wires']}
|
3
3
|
|
4
|
-
a = m.rotor_diam/2 - ag - m.pole_height - m.core_height/2
|
5
|
-
b = ((m.core_width1 + m.core_width2)/4 + m.pole_width/2)/2
|
6
|
-
r = math.sqrt(a^2 + b^2)
|
7
|
-
alpha = math.atan2(b, a)
|
8
|
-
|
9
4
|
phi = math.pi/m.num_poles
|
5
|
+
if m.xcoil_r == nil then -- ROT_HSM
|
6
|
+
a = m.rotor_diam/2 - ag - m.pole_height - m.core_height/2
|
7
|
+
b = ((m.core_width1 + m.core_width2)/4 + m.pole_width/2)/2
|
8
|
+
r = math.sqrt(a^2 + b^2)
|
9
|
+
alpha = math.atan2(b, a)
|
10
|
+
else
|
11
|
+
r,beta = c2pr(m.xcoil_r, m.ycoil_r)
|
12
|
+
alpha = phi - beta
|
13
|
+
end
|
10
14
|
dir = {'wi', 'wo'}
|
11
15
|
xcoil, ycoil = pr2c(r, phi - alpha)
|
12
16
|
def_new_wdg(xcoil, ycoil, yellow, "Exc", m.num_wires, 10.0, dir[1])
|