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.
- femagtools/__init__.py +1 -1
- femagtools/airgap.py +11 -37
- femagtools/amela.py +148 -13
- femagtools/bch.py +19 -3
- femagtools/dxfsl/area.py +68 -15
- femagtools/dxfsl/converter.py +15 -6
- femagtools/dxfsl/fslrenderer.py +13 -8
- femagtools/dxfsl/functions.py +1 -1
- femagtools/dxfsl/geom.py +415 -62
- femagtools/dxfsl/machine.py +97 -5
- femagtools/dxfsl/shape.py +46 -2
- femagtools/ecloss.py +393 -0
- femagtools/femag.py +25 -1
- femagtools/fsl.py +3 -2
- femagtools/hxy.py +126 -0
- femagtools/isa7.py +37 -24
- femagtools/machine/__init__.py +14 -13
- femagtools/machine/effloss.py +153 -32
- femagtools/machine/im.py +137 -56
- femagtools/machine/pm.py +584 -202
- femagtools/machine/sm.py +218 -64
- femagtools/machine/utils.py +12 -8
- femagtools/mcv.py +6 -8
- femagtools/model.py +11 -1
- femagtools/parstudy.py +1 -1
- femagtools/plot.py +159 -35
- femagtools/templates/afm_rotor.mako +102 -0
- femagtools/templates/afm_stator.mako +141 -0
- femagtools/templates/airgapinduc.mako +3 -3
- femagtools/templates/basic_modpar.mako +23 -2
- femagtools/templates/cogg_calc.mako +28 -5
- femagtools/templates/cu_losses.mako +1 -1
- femagtools/templates/fieldcalc.mako +39 -0
- femagtools/templates/gen_winding.mako +52 -47
- femagtools/templates/mesh-airgap.mako +43 -0
- femagtools/templates/stator3Linear.mako +5 -4
- femagtools/templates/therm-dynamic.mako +12 -6
- femagtools/templates/therm-static.mako +12 -0
- femagtools/templates/torq_calc.mako +2 -4
- femagtools/utils.py +45 -0
- femagtools/windings.py +2 -1
- {femagtools-1.3.0.dist-info → femagtools-1.3.2.dist-info}/METADATA +1 -1
- {femagtools-1.3.0.dist-info → femagtools-1.3.2.dist-info}/RECORD +47 -41
- {femagtools-1.3.0.dist-info → femagtools-1.3.2.dist-info}/WHEEL +1 -1
- {femagtools-1.3.0.dist-info → femagtools-1.3.2.dist-info}/LICENSE +0 -0
- {femagtools-1.3.0.dist-info → femagtools-1.3.2.dist-info}/entry_points.txt +0 -0
- {femagtools-1.3.0.dist-info → femagtools-1.3.2.dist-info}/top_level.txt +0 -0
femagtools/__init__.py
CHANGED
femagtools/airgap.py
CHANGED
@@ -9,6 +9,7 @@
|
|
9
9
|
"""
|
10
10
|
import numpy as np
|
11
11
|
import logging
|
12
|
+
from . import utils
|
12
13
|
|
13
14
|
logger = logging.getLogger(__name__)
|
14
15
|
|
@@ -22,49 +23,22 @@ def fft(pos, b, pmod=0):
|
|
22
23
|
b: (list of floats) flux density values
|
23
24
|
pmod: number of poles in model (ignored if 0)
|
24
25
|
"""
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
negative_periodic = pmod % 2
|
30
|
-
else:
|
31
|
-
negative_periodic = np.abs(b[0] - b[-1])/np.max(b) > 1
|
32
|
-
|
33
|
-
if negative_periodic:
|
34
|
-
bx = np.append(
|
35
|
-
np.concatenate(
|
36
|
-
[n*b[:-1]
|
37
|
-
for n in [m % 2 or -1
|
38
|
-
for m in range(1, ntiles+1)]]),
|
39
|
-
b[0])
|
40
|
-
else:
|
41
|
-
bx = np.append(
|
42
|
-
np.tile(b[:-1], ntiles),
|
43
|
-
b[0])
|
44
|
-
|
45
|
-
N = len(bx)
|
46
|
-
# compute DFT from induction
|
47
|
-
Y = np.fft.fft(bx)
|
48
|
-
|
49
|
-
# find the peak (amplitude of base harmonic)
|
50
|
-
i = np.argmax(np.abs(Y[:N//2]))
|
51
|
-
a = 2*np.abs(Y[i])/N
|
52
|
-
freq = np.fft.fftfreq(N, d=pos[1]-pos[0])
|
53
|
-
T0 = np.abs(1/freq[i])
|
26
|
+
r = utils.fft(pos, b, pmod)
|
27
|
+
Bamp = r['a']
|
28
|
+
alfa0 = r['alfa0']
|
29
|
+
T0 = r['T0']
|
54
30
|
npoles = 2*int(np.ceil(360/T0))
|
55
31
|
logger.info("flux density: %s poles B amp %f ",
|
56
|
-
npoles, a)
|
57
|
-
|
58
|
-
alfa0 = np.angle(Y[i])
|
59
|
-
return dict(Bamp=a, npoles=npoles,
|
32
|
+
npoles, r['a'])
|
33
|
+
return dict(Bamp=Bamp, npoles=npoles,
|
60
34
|
phi0=alfa0,
|
61
35
|
pos=pos.tolist(),
|
62
36
|
B=b.tolist(),
|
63
37
|
nue=np.arange(0, 9*npoles).tolist(),
|
64
|
-
B_nue=
|
65
|
-
B_fft=(
|
66
|
-
Bi=
|
67
|
-
phi=np.linspace(pos[0], 360+pos[0], len(
|
38
|
+
B_nue=r['nue'],
|
39
|
+
B_fft=(Bamp*np.cos(2*np.pi*pos/T0+alfa0)).tolist(),
|
40
|
+
Bi=r['yi'],
|
41
|
+
phi=np.linspace(pos[0], 360+pos[0], len(r['yi'])).tolist())
|
68
42
|
|
69
43
|
|
70
44
|
def read(filename, pmod=0):
|
femagtools/amela.py
CHANGED
@@ -11,12 +11,110 @@ import logging
|
|
11
11
|
from pathlib import Path
|
12
12
|
import femagtools.nc
|
13
13
|
import numpy as np
|
14
|
-
from numpy import pi
|
14
|
+
from numpy import pi, sin, cos
|
15
15
|
import subprocess
|
16
16
|
|
17
17
|
# set logging
|
18
18
|
logger = logging.getLogger(__name__)
|
19
19
|
|
20
|
+
def geometry_id(bndx, bndy):
|
21
|
+
'''identify the magnet geometry'''
|
22
|
+
# caculate magnet area
|
23
|
+
xy = 0
|
24
|
+
yx = 0
|
25
|
+
for i in range(len(bndy)):
|
26
|
+
if i < (len(bndy)-1):
|
27
|
+
xy += bndx[i]*bndy[i+1]
|
28
|
+
yx += bndy[i]*bndx[i+1]
|
29
|
+
else:
|
30
|
+
xy += bndx[i]*bndy[0]
|
31
|
+
yx += bndy[i]*bndx[0]
|
32
|
+
area = np.abs(yx-xy)*0.5
|
33
|
+
|
34
|
+
x0, y0 = np.mean(bndx), np.mean(bndy)
|
35
|
+
distances = []
|
36
|
+
for i in range(len(bndx)):
|
37
|
+
for j in range(len(bndy)):
|
38
|
+
dist = np.sqrt((bndx[i] - bndx[j])**2 + (bndy[i] - bndy[j])**2)
|
39
|
+
distances.append([dist, bndx[i], bndx[j], bndy[i], bndy[j]])
|
40
|
+
|
41
|
+
distances.sort(reverse=True)
|
42
|
+
xe = [distances[0][2], distances[2][1], distances[0][1], distances[2][2]]
|
43
|
+
ye = [distances[0][4], distances[2][3], distances[0][3], distances[2][4]]
|
44
|
+
|
45
|
+
# dimension
|
46
|
+
dim = np.zeros((3, 5))
|
47
|
+
x1, y1 = xe[0], ye[0]
|
48
|
+
|
49
|
+
for i in range(3):
|
50
|
+
x2, y2 = xe[i+1], ye[i+1]
|
51
|
+
dim[i, 0] = np.sqrt((x2-x1)**2 + (y2-y1)**2)
|
52
|
+
dim[i, 1:3] = [x1, x2]
|
53
|
+
dim[i, 3:5] = [y1, y2]
|
54
|
+
|
55
|
+
dim = dim[np.lexsort((dim[:, 2], dim[:, 1], dim[:, 0]))]
|
56
|
+
dx12, dy12 = dim[1, 1] - dim[1, 2], dim[1, 3] - dim[1, 4]
|
57
|
+
dx14, dy14 = dim[0, 1] - dim[0, 2], dim[0, 3] - dim[0, 4]
|
58
|
+
|
59
|
+
alp1 = np.arctan2(dy12, dx12)
|
60
|
+
alp2 = np.arctan2(dy14, dx14)
|
61
|
+
|
62
|
+
if alp1 < 0: alp1 += 2*np.pi
|
63
|
+
if alp2 < 0: alp2 += 2*np.pi
|
64
|
+
if alp2 < alp1:
|
65
|
+
alp2 += np.pi
|
66
|
+
alpha = (alp1 + (alp2 - np.pi/2))/2
|
67
|
+
else:
|
68
|
+
alpha = (alp1 + (alp2 - np.pi/2))/2 + np.pi
|
69
|
+
|
70
|
+
wm = dim[1, 0]
|
71
|
+
hm = area/wm
|
72
|
+
|
73
|
+
return dict(wm=wm,
|
74
|
+
hm=hm,
|
75
|
+
x0=x0,
|
76
|
+
y0=y0,
|
77
|
+
area=area,
|
78
|
+
alpha=alpha)
|
79
|
+
|
80
|
+
def tf(b1, b2, alpha):
|
81
|
+
'''Tranformation Matrix'''
|
82
|
+
T = np.array([[cos(alpha), sin(alpha)],
|
83
|
+
[-sin(alpha), cos(alpha)]])
|
84
|
+
if b1.ndim > 1:
|
85
|
+
r = T.dot(((b1.ravel()), (b2.ravel())))
|
86
|
+
return [r[0, :].reshape(*b1.shape),
|
87
|
+
r[1, :].reshape(*b1.shape)]
|
88
|
+
else:
|
89
|
+
return T.dot(((b1), (b2)))
|
90
|
+
|
91
|
+
def transform_coord(geometry, xcp, ycp):
|
92
|
+
'''transform from global coord to local coord'''
|
93
|
+
# transformation
|
94
|
+
elcp = tf(b1=np.array(xcp)-geometry['x0'],
|
95
|
+
b2=np.array(ycp)-geometry['y0'],
|
96
|
+
alpha=geometry['alpha'])
|
97
|
+
return dict(excpl=elcp[0, :]+geometry['wm']/2,
|
98
|
+
eycpl=elcp[1, :]+geometry['hm']/2,
|
99
|
+
excp=np.array(xcp),
|
100
|
+
eycp=np.array(ycp))
|
101
|
+
|
102
|
+
def transform_flux_denstiy(geometry, bx, by):
|
103
|
+
'''transform the magnet flux density to local coordinate system'''
|
104
|
+
# transformation
|
105
|
+
bxy = tf(b1=bx,
|
106
|
+
b2=by,
|
107
|
+
alpha=geometry['alpha'])
|
108
|
+
|
109
|
+
# remove DC component
|
110
|
+
bxf = np.mean(bxy[0].T - np.mean(bxy[0],axis=1).T,axis=1)
|
111
|
+
byf = np.mean(bxy[1].T - np.mean(bxy[1],axis=1).T,axis=1)
|
112
|
+
|
113
|
+
return dict(bxl=bxy[0],
|
114
|
+
byl=bxy[1],
|
115
|
+
bxf=bxf,
|
116
|
+
byf=byf
|
117
|
+
)
|
20
118
|
|
21
119
|
class Amela():
|
22
120
|
'''Run Amela Calculation
|
@@ -66,7 +164,7 @@ class Amela():
|
|
66
164
|
if 'nseglen' in self.magn:
|
67
165
|
self.cmd.append(f"--nseglen {self.magn['nseglen']}")
|
68
166
|
|
69
|
-
def get_magnet_data(self):
|
167
|
+
def get_magnet_data(self, ibeta=None):
|
70
168
|
'''Extract magnet data from nc file
|
71
169
|
Parameters
|
72
170
|
----------
|
@@ -92,7 +190,15 @@ class Amela():
|
|
92
190
|
ycp = [[] for i in range(len(spel_key))]
|
93
191
|
bndx = [[] for i in range(len(spel_key))]
|
94
192
|
bndy = [[] for i in range(len(spel_key))]
|
95
|
-
|
193
|
+
# prepare data for ialh method
|
194
|
+
wm = []
|
195
|
+
hm = []
|
196
|
+
alpha = []
|
197
|
+
x0 = []
|
198
|
+
y0 = []
|
199
|
+
geometry = []
|
200
|
+
elcp = []
|
201
|
+
bl = []
|
96
202
|
# conductivity and permeability of the magnets
|
97
203
|
cond = 0
|
98
204
|
mur = 0
|
@@ -124,15 +230,26 @@ class Amela():
|
|
124
230
|
bndkey[k].pop(-1)
|
125
231
|
bndx[k].pop(-1)
|
126
232
|
bndy[k].pop(-1)
|
233
|
+
geo = geometry_id(bndx=bndx[k], bndy=bndy[k])
|
234
|
+
geometry.append(geo)
|
235
|
+
# necessary?
|
236
|
+
hm.append(geo['hm'])
|
237
|
+
wm.append(geo['wm'])
|
238
|
+
x0.append(geo['x0'])
|
239
|
+
y0.append(geo['y0'])
|
240
|
+
alpha.append(geo['alpha'])
|
127
241
|
|
128
242
|
# default load angle (input beta I vs Up)
|
129
|
-
|
130
|
-
|
131
|
-
indx = self.magn['loadcase'] - 1
|
243
|
+
if ibeta is not None:
|
244
|
+
indx = ibeta
|
132
245
|
else:
|
133
|
-
|
134
|
-
|
135
|
-
|
246
|
+
num_cases = r.el_fe_induction_1.shape[3] - 1
|
247
|
+
if 'loadcase' in self.magn:
|
248
|
+
indx = self.magn['loadcase'] - 1
|
249
|
+
else:
|
250
|
+
indx = num_cases
|
251
|
+
if indx == 3:
|
252
|
+
indx = num_cases # avoid error
|
136
253
|
|
137
254
|
# stationary case, no rotation
|
138
255
|
poles = 0
|
@@ -159,6 +276,10 @@ class Amela():
|
|
159
276
|
by[i][0][index, :] = fd['bx']*np.sin(theta) + \
|
160
277
|
fd['by']*np.cos(theta)
|
161
278
|
|
279
|
+
elcp.append(transform_coord(geometry[i], xcp[i], ycp[i]))
|
280
|
+
bl.append(transform_flux_denstiy(geometry[i], bx[i][0], by[i][0]))
|
281
|
+
|
282
|
+
|
162
283
|
if poles == 0:
|
163
284
|
freq = self.magn.get('f', r.speed)
|
164
285
|
time_vec = np.linspace(0, 1/freq, len(r.pos_el_fe_induction))
|
@@ -177,9 +298,10 @@ class Amela():
|
|
177
298
|
pm_data = []
|
178
299
|
for i in range(len(spel_key)):
|
179
300
|
pm_data.append(dict(name='pm_data_se' + str(spel_key[i]),
|
180
|
-
hm=self.magn.get('hm',
|
181
|
-
wm=self.magn.get('wm',
|
301
|
+
hm=self.magn.get('hm', hm[i]),
|
302
|
+
wm=self.magn.get('wm', wm[i]),
|
182
303
|
lm=self.magn.get('lm', r.arm_length*1e3),
|
304
|
+
alpha=alpha[i],
|
183
305
|
ls=r.arm_length*1e3,
|
184
306
|
sigma=float(self.magn.get('sigma', cond)),
|
185
307
|
mur=float(self.magn.get('mur', mur)),
|
@@ -190,7 +312,10 @@ class Amela():
|
|
190
312
|
bndkeys=bndkey[i],
|
191
313
|
bndx=[float(c) for c in bndx[i]],
|
192
314
|
bndy=[float(c) for c in bndy[i]],
|
193
|
-
|
315
|
+
bl=bl[i],
|
316
|
+
elcp=elcp[i],
|
317
|
+
area=spel_area[i],
|
318
|
+
spel_key=spel_key[i]))
|
194
319
|
pm_data[i].update(pos)
|
195
320
|
|
196
321
|
for k in range(len(pm_node_key)):
|
@@ -215,6 +340,14 @@ class Amela():
|
|
215
340
|
else:
|
216
341
|
return [pm_data[0]]
|
217
342
|
|
343
|
+
def get_magnet_data_all(self, num_op):
|
344
|
+
'''get all magnet data for all loadcases'''
|
345
|
+
pm_data = []
|
346
|
+
for i in num_op:
|
347
|
+
pmd = self.get_magnet_data(ibeta=i)
|
348
|
+
pm_data.append(pmd)
|
349
|
+
return pm_data
|
350
|
+
|
218
351
|
def export_json(self, pm_data):
|
219
352
|
'''Export magnet data to json files
|
220
353
|
Parameters
|
@@ -230,6 +363,9 @@ class Amela():
|
|
230
363
|
for i in pm_data:
|
231
364
|
filename = (pm_dir / i['name']).with_suffix('.json')
|
232
365
|
self.jsonfile.append(str(filename)) # for the future use
|
366
|
+
# pop out non necessary data
|
367
|
+
i.pop('bl')
|
368
|
+
i.pop('elcp')
|
233
369
|
with filename.open('w') as f:
|
234
370
|
json.dump(i, f)
|
235
371
|
logger.info('Exporting %s ...', i['name'])
|
@@ -279,4 +415,3 @@ class Amela():
|
|
279
415
|
with log_file.open('w') as output:
|
280
416
|
subprocess.run(cmd, stdout=output)
|
281
417
|
return self.read_loss(r)
|
282
|
-
|
femagtools/bch.py
CHANGED
@@ -170,6 +170,7 @@ class Reader:
|
|
170
170
|
self.dqPar = {}
|
171
171
|
self.ldq = {}
|
172
172
|
self.losses = []
|
173
|
+
self.magnet_loss_th = []
|
173
174
|
self.demag = []
|
174
175
|
self.weights = []
|
175
176
|
self.weight = {}
|
@@ -1497,11 +1498,12 @@ class Reader:
|
|
1497
1498
|
if l.find('Fe-Losses-Rotor') > -1:
|
1498
1499
|
rec = self.__findNums(content[i+3])
|
1499
1500
|
if len(rec) == 2:
|
1500
|
-
if content[i+1].find('Iron') > -1 and content[i+1].find('StJo') > 0
|
1501
|
+
if (content[i+1].find('Iron') > -1 and content[i+1].find('StJo') > 0 or
|
1502
|
+
content[i+1].split() == ['RoZa', 'RoJo']):
|
1501
1503
|
self.external_rotor = True
|
1502
1504
|
# TODO: there might be better places to check this
|
1503
|
-
losses['
|
1504
|
-
losses['
|
1505
|
+
losses['staza'] = floatnan(rec[0])
|
1506
|
+
losses['stajo'] = floatnan(rec[1])
|
1505
1507
|
losses['total'] += losses['staza']+losses['stajo']
|
1506
1508
|
else:
|
1507
1509
|
losses['rotfe'] = floatnan(rec[1])
|
@@ -1509,6 +1511,20 @@ class Reader:
|
|
1509
1511
|
i += 4
|
1510
1512
|
continue
|
1511
1513
|
|
1514
|
+
if l.find('Fe-Losses-Stator') > -1:
|
1515
|
+
rec = self.__findNums(content[i+3])
|
1516
|
+
if len(rec) == 2:
|
1517
|
+
if content[i+1].split() == ['StJo', 'StZa']:
|
1518
|
+
losses['stajo'] = floatnan(rec[0])
|
1519
|
+
losses['staza'] = floatnan(rec[1])
|
1520
|
+
losses['total'] += losses['staza']+losses['stajo']
|
1521
|
+
|
1522
|
+
if content[i+1].split() == ['rotf', '----']:
|
1523
|
+
losses['rotfe'] = sum([floatnan(x) for x in rec])
|
1524
|
+
losses['total'] += losses['rotfe']
|
1525
|
+
i += 4
|
1526
|
+
continue
|
1527
|
+
|
1512
1528
|
if l.find('Magnet-Losses') > -1:
|
1513
1529
|
rec = self.__findNums(content[i+1])
|
1514
1530
|
if len(rec) == 1:
|
femagtools/dxfsl/area.py
CHANGED
@@ -39,6 +39,8 @@ class Area(object):
|
|
39
39
|
self.min_air_angle = 0.0
|
40
40
|
self.max_air_angle = 0.0
|
41
41
|
self.close_to_ag = False
|
42
|
+
self.close_to_ag_startcorner = False
|
43
|
+
self.close_to_ag_endcorner = False
|
42
44
|
self.close_to_startangle = False
|
43
45
|
self.close_to_endangle = False
|
44
46
|
self.mag_rectangle = False
|
@@ -128,6 +130,18 @@ class Area(object):
|
|
128
130
|
except Exception as e:
|
129
131
|
return
|
130
132
|
|
133
|
+
def has_fsl(self):
|
134
|
+
try:
|
135
|
+
return self.fsl
|
136
|
+
except AttributeError:
|
137
|
+
return True
|
138
|
+
|
139
|
+
def list_of_equal_edges(self, a):
|
140
|
+
for e1 in self.area:
|
141
|
+
for e2 in a.area:
|
142
|
+
if e1.n1 == e2.n1 and e1.n2 == e2.n2:
|
143
|
+
yield e1
|
144
|
+
|
131
145
|
def virtual_nodes(self, render=False):
|
132
146
|
if len(self.area) < 2:
|
133
147
|
return
|
@@ -1044,6 +1058,12 @@ class Area(object):
|
|
1044
1058
|
return True
|
1045
1059
|
return False
|
1046
1060
|
|
1061
|
+
def is_touching_areas(self, areas):
|
1062
|
+
for a in areas:
|
1063
|
+
if self.is_touching(a):
|
1064
|
+
return True
|
1065
|
+
return False
|
1066
|
+
|
1047
1067
|
def mark_stator_subregions(self,
|
1048
1068
|
is_inner,
|
1049
1069
|
stator_size,
|
@@ -1143,18 +1163,37 @@ class Area(object):
|
|
1143
1163
|
logger.debug("***** air (part of a circle)\n")
|
1144
1164
|
return self.type
|
1145
1165
|
|
1166
|
+
def bad_winding_position():
|
1167
|
+
if is_inner:
|
1168
|
+
radius_third = airgap_radius - (airgap_radius - opposite_radius) * 0.33
|
1169
|
+
if self.max_dist < radius_third:
|
1170
|
+
return True
|
1171
|
+
else: # outer
|
1172
|
+
radius_third = airgap_radius + (opposite_radius - airgap_radius) * 0.33
|
1173
|
+
if self.min_dist > radius_third:
|
1174
|
+
return True
|
1175
|
+
return False
|
1176
|
+
|
1146
1177
|
if self.min_angle > 0.001:
|
1147
1178
|
if self.max_angle < alpha - 0.001:
|
1148
|
-
|
1149
|
-
|
1179
|
+
if bad_winding_position():
|
1180
|
+
self.type = 12 # windings or air
|
1181
|
+
logger.debug("***** windings or air #1\n")
|
1182
|
+
else:
|
1183
|
+
self.type = 2 # windings
|
1184
|
+
logger.debug("***** windings #1\n")
|
1150
1185
|
return self.type
|
1151
1186
|
if mirrored:
|
1152
|
-
|
1153
|
-
|
1187
|
+
if bad_winding_position():
|
1188
|
+
self.type = 12 # windings or air
|
1189
|
+
logger.debug("***** windings or air #2\n")
|
1190
|
+
else:
|
1191
|
+
self.type = 2 # windings
|
1192
|
+
logger.debug("***** windings #2\n")
|
1154
1193
|
return self.type
|
1155
1194
|
|
1156
1195
|
self.type = 0 # air
|
1157
|
-
logger.debug("***** air #
|
1196
|
+
logger.debug("***** air #3")
|
1158
1197
|
|
1159
1198
|
if self.close_to_startangle or self.close_to_endangle:
|
1160
1199
|
f = self.surface / stator_size
|
@@ -1167,7 +1206,7 @@ class Area(object):
|
|
1167
1206
|
logger.debug("***** air or iron close to border\n")
|
1168
1207
|
return self.type
|
1169
1208
|
|
1170
|
-
logger.debug("***** air #
|
1209
|
+
logger.debug("***** air #4\n")
|
1171
1210
|
return 0
|
1172
1211
|
|
1173
1212
|
def mark_rotor_subregions(self, is_inner, mirrored, alpha,
|
@@ -1319,6 +1358,15 @@ class Area(object):
|
|
1319
1358
|
logger.debug(">>> air remains")
|
1320
1359
|
return self.type
|
1321
1360
|
|
1361
|
+
def mark_airgap_corners(self, start_cp, end_cp):
|
1362
|
+
for n in self.list_of_nodes():
|
1363
|
+
if self.close_to_startangle:
|
1364
|
+
if points_are_close(n, start_cp):
|
1365
|
+
self.close_to_ag_startcorner = True
|
1366
|
+
if self.close_to_endangle:
|
1367
|
+
if points_are_close(n, end_cp):
|
1368
|
+
self.close_to_ag_endcorner = True
|
1369
|
+
|
1322
1370
|
def area_size(self):
|
1323
1371
|
nodes = [n for n in self.list_of_nodes()]
|
1324
1372
|
return area_size(nodes)
|
@@ -1455,14 +1503,19 @@ class Area(object):
|
|
1455
1503
|
|
1456
1504
|
def __str__(self):
|
1457
1505
|
return "Area {}\n".format(self.id) + \
|
1458
|
-
"distance
|
1506
|
+
"distance...............: from {} to {}\n".\
|
1459
1507
|
format(round(self.min_dist, 4), round(self.max_dist, 4)) + \
|
1460
|
-
"height
|
1461
|
-
"alpha
|
1462
|
-
"angle
|
1508
|
+
"height.................: {}\n".format(self.height) + \
|
1509
|
+
"alpha..................: {}\n".format(self.alpha) + \
|
1510
|
+
"angle..................: from {} to {}\n".\
|
1463
1511
|
format(round(self.min_angle, 6), round(self.max_angle, 6)) + \
|
1464
|
-
"delta
|
1465
|
-
"number
|
1466
|
-
"equal
|
1467
|
-
"symmetry
|
1468
|
-
"
|
1512
|
+
"delta..................: {}\n".format(self.delta) + \
|
1513
|
+
"number.................: {}\n".format(self.count) + \
|
1514
|
+
"equal areas............: {}\n".format(len(self.equal_areas)) + \
|
1515
|
+
"symmetry...............: {}\n".format(self.symmetry) + \
|
1516
|
+
"symmetry type..........: {}\n".format(self.sym_type) + \
|
1517
|
+
"close to airgap........: {}\n".format(self.close_to_ag) + \
|
1518
|
+
"close to startangle....: {}\n".format(self.close_to_startangle) + \
|
1519
|
+
"close to endangle......: {}\n".format(self.close_to_endangle) + \
|
1520
|
+
"close to ag startcorner: {}\n".format(self.close_to_ag_startcorner) + \
|
1521
|
+
"close to ag endcorner..: {}\n".format(self.close_to_ag_endcorner)
|
femagtools/dxfsl/converter.py
CHANGED
@@ -240,6 +240,7 @@ def convert(dxfile,
|
|
240
240
|
cols=2, # columns
|
241
241
|
num=3) # start num
|
242
242
|
machine_inner.set_inner()
|
243
|
+
machine_inner.check_and_correct_geom("Inner")
|
243
244
|
|
244
245
|
machine_outer = machine.copy(0.0, 2*np.pi, True, False)
|
245
246
|
machine_outer = symmetry_search(machine_outer,
|
@@ -251,6 +252,7 @@ def convert(dxfile,
|
|
251
252
|
rows=3, # rows
|
252
253
|
cols=2, # columns
|
253
254
|
num=4) # start num
|
255
|
+
machine_outer.check_and_correct_geom("Outer")
|
254
256
|
|
255
257
|
machine_inner.sync_with_counterpart(machine_outer)
|
256
258
|
|
@@ -273,22 +275,25 @@ def convert(dxfile,
|
|
273
275
|
|
274
276
|
machine_inner.delete_tiny_elements(mindist)
|
275
277
|
machine_outer.delete_tiny_elements(mindist)
|
278
|
+
machine_inner.geom.create_corner_areas()
|
276
279
|
logger.info("END of work: %s", basename)
|
277
280
|
|
278
281
|
if show_plots:
|
279
282
|
p.render_elements(machine_inner.geom, Shape,
|
280
283
|
draw_inside=True, title=inner_name,
|
281
284
|
rows=3, cols=2, num=5, show=False,
|
282
|
-
|
283
|
-
|
285
|
+
with_corners=False,
|
286
|
+
with_nodes=False,
|
287
|
+
neighbors=False,
|
284
288
|
write_id=write_id,
|
285
289
|
fill_areas=True)
|
286
290
|
|
287
291
|
p.render_elements(machine_outer.geom, Shape,
|
288
292
|
draw_inside=True, title=outer_name,
|
289
293
|
rows=3, cols=2, num=6, show=False,
|
290
|
-
|
291
|
-
|
294
|
+
with_corners=False,
|
295
|
+
with_nodes=False,
|
296
|
+
neighbors=False,
|
292
297
|
write_id=write_id,
|
293
298
|
fill_areas=True)
|
294
299
|
if write_png:
|
@@ -394,6 +399,7 @@ def convert(dxfile,
|
|
394
399
|
machine = machine.undo_mirror()
|
395
400
|
machine.geom.set_stator()
|
396
401
|
machine.geom.search_stator_subregions(part[1])
|
402
|
+
machine.geom.looking_for_corners()
|
397
403
|
machine.create_mirror_lines_outside_windings()
|
398
404
|
|
399
405
|
params = create_femag_parameters_stator(machine,
|
@@ -401,20 +407,23 @@ def convert(dxfile,
|
|
401
407
|
else:
|
402
408
|
machine.geom.set_rotor()
|
403
409
|
machine.geom.search_rotor_subregions(part[1])
|
410
|
+
machine.geom.looking_for_corners()
|
404
411
|
params = create_femag_parameters_rotor(machine,
|
405
412
|
part[1])
|
406
413
|
else:
|
407
414
|
machine.geom.search_subregions()
|
408
415
|
|
409
416
|
machine.delete_tiny_elements(mindist)
|
417
|
+
machine.geom.create_corner_areas()
|
410
418
|
logger.info("END of work: %s", basename)
|
411
419
|
|
412
420
|
if show_plots:
|
413
421
|
p.render_elements(machine.geom, Shape,
|
414
422
|
draw_inside=True, title=name,
|
415
423
|
rows=3, cols=2, num=5, show=False,
|
416
|
-
|
417
|
-
|
424
|
+
with_corners=False,
|
425
|
+
with_nodes=False,
|
426
|
+
neighbors=False,
|
418
427
|
write_id=write_id,
|
419
428
|
fill_areas=True)
|
420
429
|
if write_png:
|
femagtools/dxfsl/fslrenderer.py
CHANGED
@@ -110,14 +110,19 @@ class FslRenderer(object):
|
|
110
110
|
# if self.nodedist > 0:
|
111
111
|
# l = la.norm(np.asarray(p1)-p2)
|
112
112
|
# num = int(l/self.nodedist + 1)
|
113
|
-
if e is not None
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
113
|
+
if e is not None:
|
114
|
+
if e.has_attribute('no_fsl'):
|
115
|
+
logger.info("line with attr nofsl")
|
116
|
+
return
|
117
|
+
if e.has_attribute('auxline'):
|
118
|
+
self.content.append(
|
119
|
+
u"nc_line({}, {}, {}, {}, {}) -- auxiliary".format(
|
120
|
+
p1[0], p1[1], p2[0], p2[1], num))
|
121
|
+
return
|
122
|
+
|
123
|
+
self.content.append(
|
124
|
+
u"nc_line({}, {}, {}, {}, {})".format(
|
125
|
+
p1[0], p1[1], p2[0], p2[1], num))
|
121
126
|
|
122
127
|
def sorted_elements(self, geom, inner=False):
|
123
128
|
if inner:
|
femagtools/dxfsl/functions.py
CHANGED
@@ -288,7 +288,7 @@ def is_same_angle(angle1, angle2, atol=0.001):
|
|
288
288
|
np.isclose(np.sin(angle1), np.sin(angle2), atol=atol))
|
289
289
|
|
290
290
|
|
291
|
-
def part_of_circle(startangle, endangle, dec_place=
|
291
|
+
def part_of_circle(startangle, endangle, dec_place=2):
|
292
292
|
""" returns the number of segments included in the circle
|
293
293
|
if an integer number, 0 otherwise
|
294
294
|
"""
|