femagtools 1.5.0__py3-none-any.whl → 1.5.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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  """
4
4
  __title__ = 'femagtools'
5
- __version__ = '1.5.0'
5
+ __version__ = '1.5.2'
6
6
  __author__ = 'Ronald Tanner'
7
7
  __license__ = 'BSD'
8
8
  __copyright__ = 'Copyright 2016-2022 SEMAFOR Informatik & Energie AG'
femagtools/amela.py CHANGED
@@ -200,7 +200,11 @@ class Amela():
200
200
  for k, i in enumerate(mag_spels):
201
201
 
202
202
  cond = i.conduc
203
- mur = 1/i.elements[0].reluc[0]
203
+ if cond == 0:
204
+ cond = 625000
205
+ logger.info('Magnet conductivity equals 0, using 625000 S/m')
206
+
207
+ mur = np.abs(1/i.elements[0].reluc[0])
204
208
  logger.debug('Magnet: mur=%s, conductivity=%s', mur, cond)
205
209
 
206
210
  pm_elem_key.append([j.key for j in i.elements])
femagtools/femag.py CHANGED
@@ -41,7 +41,7 @@ def handle_process_output(filedes, outfile, log):
41
41
  """read from file descriptor and direct lines to logger and outfile"""
42
42
  with open(outfile, 'w') as fp:
43
43
  for line in filedes:
44
- fp.write(str(line))
44
+ fp.write(line.decode())
45
45
  if log:
46
46
  if (b'' == line or
47
47
  b'\x1b' in line or # ignore terminal escape seq
@@ -482,7 +482,7 @@ class Femag(BaseFemag):
482
482
  basename = pathlib.Path(filename).name
483
483
  outname = os.path.join(self.workdir, basename+'.out')
484
484
  errname = os.path.join(self.workdir, basename+'.err')
485
- with open(outname, 'w') as out, open(errname, 'w') as err:
485
+ with open(errname, 'w') as err:
486
486
  logger.info('invoking %s', ' '.join([str(a) for a in args]))
487
487
  proc = subprocess.Popen(
488
488
  args,
@@ -495,9 +495,15 @@ class Femag(BaseFemag):
495
495
  errs = []
496
496
  # print femag output
497
497
  with io.open(outname, encoding='latin1', errors='ignore') as outfile:
498
+ errLine = False
498
499
  for l in outfile:
499
500
  if l.find('ERROR') > -1:
500
501
  errs.append(l.strip())
502
+ errLine = True
503
+ elif errLine and l.startswith(' '): # additional error line
504
+ errs.append(l)
505
+ else:
506
+ errLine = False
501
507
 
502
508
  rc = proc.returncode
503
509
  logger.info("%s exited with returncode %d (num errs=%d)",
@@ -508,7 +514,7 @@ class Femag(BaseFemag):
508
514
  for l in errfile:
509
515
  errs.append(l.strip())
510
516
  errs.insert(0, 'Exit code {}'.format(rc))
511
- raise FemagError(errs)
517
+ raise FemagError("\n".join(errs))
512
518
 
513
519
  def cleanup(self):
514
520
  "removes all created files in workdir"
@@ -805,8 +811,8 @@ class ZmqFemag(BaseFemag):
805
811
  logger.error("send_fsl: %s", str(e))
806
812
  if timeout: # only first call raises zmq.error.Again
807
813
  return ['{"status":"error", "message":"Femag is not running"}', '{}']
808
- msg = str(e)
809
- return ['{"status":"error", "message":"'+msg+'"}', '{}']
814
+ msg = json.dumps(str(e))
815
+ return ['{"status":"error", "message":'+msg+'}', '{}']
810
816
 
811
817
  def run(self, options=['-b'], restart=False, procId=None,
812
818
  stateofproblem='mag_static'): # noqa: C901
@@ -1003,6 +1009,18 @@ class ZmqFemag(BaseFemag):
1003
1009
  logger.warning(response[0])
1004
1010
  return [s.decode('latin1') for s in response]
1005
1011
 
1012
+ def exportmesh(self, fslcmds, timeout=120000):
1013
+ """get svg format (with mesh) from fsl commands (if any graphic created)
1014
+ (since FEMAG v2024.1-17) """
1015
+ response = self.send_request(['SVG+Mesh', fslcmds], timeout=timeout)
1016
+ try:
1017
+ rc = json.loads(response[0].decode('latin1'))
1018
+ if rc['status'] == 'ok':
1019
+ return self.getfile(rc['result_file'][0])
1020
+ except json.decoder.JSONDecodeError:
1021
+ logger.warning(response[0])
1022
+ return [s.decode('latin1') for s in response]
1023
+
1006
1024
  def interrupt(self):
1007
1025
  """send push message to control port to stop current calculation"""
1008
1026
  context = zmq.Context.instance()
femagtools/fsl.py CHANGED
@@ -634,7 +634,7 @@ class Builder:
634
634
  def create_analysis(self, sim):
635
635
  pfefunc = sim.get('loss_funct', '')
636
636
  if pfefunc:
637
- sim['loss_funct'] = 2 # 3?
637
+ sim['loss_funct'] = 1 # 3?
638
638
  airgap_induc = (self.create_airgap_induc()
639
639
  if sim.get('airgap_induc', 0) else [])
640
640
  felosses = pfefunc.split('\n') + self.create_fe_losses(sim)
femagtools/hxy.py CHANGED
@@ -4,63 +4,95 @@
4
4
  ~~~~~~~~~~~~~~
5
5
 
6
6
  Reading HXY files (EXPERIMENTAL)
7
-
7
+ Build cluster of magnets
8
8
  """
9
9
 
10
10
  import numpy as np
11
- from collections import defaultdict
11
+ import logging
12
12
 
13
13
  # K-means clustering
14
+ # https://dev.to/sajal2692/coding-k-means-clustering-using-python-and-numpy-fg1
15
+ # Sajal Sharma
16
+ # with adaptions by Ronald Tanner
17
+ def initialize_random_centroids(K, X):
18
+ """Initializes and returns k random centroids"""
19
+ m, n = np.shape(X)
20
+ # a centroid should be of shape (1, n), so the centroids array will be of shape (K, n)
21
+ centroids = np.empty((K, n))
22
+ for i in range(K):
23
+ # pick a random data point from X as the centroid
24
+ centroids[i] = X[np.random.choice(range(m))]
25
+ return centroids
26
+
27
+
28
+ def initialize_centroids(K, X):
29
+ """Initializes and returns k centroids"""
30
+ c = np.mean(X, axis=0)
31
+ if K < 2:
32
+ return [c]
33
+ alfa = np.arctan2(c[1], c[0]) # angle of center axis
34
+ T = np.array([[np.cos(alfa), -np.sin(alfa)],
35
+ [np.sin(alfa), np.cos(alfa)]])
36
+ p = (np.asarray(X)-c).dot(T) # rotate X
37
+ d = np.linalg.norm(p, axis=1) # distance to center
38
+ a = np.arctan2(p[:, 1], p[:, 0]) # angle to center
39
+ h, b = np.histogram(a, bins=K)
40
+ return [np.mean(X[(a>r[0]) & (a<r[1])], axis=0)
41
+ for r in np.array((b[:-1], b[1:])).T]
42
+
43
+
44
+ def closest_centroid(x, centroids, K):
45
+ """Finds and returns the index of the closest centroid for a given vector x"""
46
+ distances = np.empty(K)
47
+ for i in range(K):
48
+ distances[i] = np.linalg.norm(centroids[i] - x)
49
+ return np.argmin(distances) # return the index of the lowest distance
50
+
51
+
52
+ def create_clusters(centroids, K, X):
53
+ """Returns an array of cluster indices for all the data samples"""
54
+ m, _ = np.shape(X)
55
+ cluster_idx = np.empty(m, dtype=int)
56
+ for i in range(m):
57
+ cluster_idx[i] = closest_centroid(X[i], centroids, K)
58
+ return cluster_idx
59
+
60
+
61
+ def compute_means(cluster_idx, K, X):
62
+ """Computes and returns the new centroids of the clusters"""
63
+ _, n = np.shape(X)
64
+ centroids = np.empty((K, n))
65
+ for i in range(K):
66
+ points = X[cluster_idx == i] # gather points for the cluster i
67
+ centroids[i] = np.mean(points, axis=0) # use axis=0 to compute means across points
68
+ return centroids
69
+
70
+
71
+ def run_Kmeans(K, X, max_iterations=500):
72
+ """Runs the K-means algorithm and computes the final clusters"""
73
+ # initialize centroids
74
+ centroids = initialize_centroids(K, X)
75
+ # loop till max_iterations or convergance
76
+ logging.debug(f"initial centroids: {centroids}")
77
+ for _ in range(max_iterations):
78
+ # create clusters by assigning the samples to the closet centroids
79
+ clusters = create_clusters(centroids, K, X)
80
+ previous_centroids = centroids
81
+ # compute means of the clusters and assign to centroids
82
+ centroids = compute_means(clusters, K, X)
83
+ # if the new_centroids are the same as the old centroids, return clusters
84
+ diff = previous_centroids - centroids
85
+ if not diff.any():
86
+ return clusters
87
+ return clusters
88
+
89
+ """references properties i to magnet k"""
14
90
  class point():
15
91
  def __init__(self, index, k, coord):
16
92
  self.index = index
17
93
  self.coord = coord
18
94
  self.k = k
19
95
 
20
- def make_k_mapping(points):
21
- region = defaultdict(list)
22
- for p in points:
23
- region[p.k] = region[p.k] + [p.coord]
24
- return region
25
-
26
- def calc_k_means(region):
27
- return [np.mean(region[k], axis=0) for k in region]
28
-
29
- def update_k(points, means):
30
- for p in points:
31
- dists = [np.linalg.norm(m - p.coord) for m in means]
32
- p.k = np.argmin(dists)
33
-
34
- def fit(points, epochs=10):
35
- for e in range(epochs):
36
- region = make_k_mapping(points)
37
- means = calc_k_means(region)
38
- update_k(points, means)
39
- return means, points
40
-
41
- def evaluate(points):
42
- region = make_k_mapping(points)
43
- means = calc_k_means(region)
44
- dists = [np.linalg.norm(means[p.k]-p.coord) for p in points]
45
- return np.mean(dists)
46
-
47
- def llf_(y, X, pr):
48
- # return maximized log likelihood
49
- nobs = float(X.shape[0])
50
- nobs2 = nobs / 2.0
51
- nobs = float(nobs)
52
- resid = y - pr
53
- ssr = np.sum((resid)**2)
54
- llf = -nobs2*np.log(2*np.pi) - nobs2*np.log(ssr / nobs) - nobs2
55
- return llf
56
-
57
-
58
- def aic(y, X, pr, p):
59
- # return aic metric
60
- llf = llf_(y, X, pr)
61
- return -2*llf+2*p
62
-
63
-
64
96
  def readSections(f):
65
97
  section = []
66
98
  movepos = False
@@ -83,44 +115,67 @@ def readSections(f):
83
115
 
84
116
 
85
117
  def read(filename, num_magnets):
86
- """read hxy file and return values grouped to magnets"""
118
+ """read hxy file and return values grouped to magnets
119
+ returns:
120
+ list of m=num_magnets dicts
121
+ pos: list of n positions in degree
122
+ e: n lists of center coordinates of elements in m
123
+ hxy: n lists of field strengths in kA/m
124
+ bxy: n lists of flux densities in T
125
+ mxy: n lists of magnetization in T
126
+ havg: average of field strengths kA/m
127
+ hmax: maximum of field strengths kA/m
128
+ """
87
129
  hxy = []
88
130
  with open(filename, encoding='latin1', errors='ignore') as f:
131
+ n = 0
132
+ k = 0
89
133
  for s in readSections(f):
90
134
  pos = float(s[0].split()[-1])
91
135
  num = np.array([[float(x) for x in l.split()] for l in s[5:] if l])
92
136
  hxy.append({'pos': pos, 'e': num[:, :2], 'hxy': num[:, 2:4],
93
137
  'bxy': num[:, 4:6], 'mxy':num[:, 6:]})
138
+ logging.info("HXY Section %d: pos %f shape %s", n, pos, num.shape)
139
+ n += 1
140
+ if k == 0:
141
+ k = num.shape[1]
94
142
  K = num_magnets
95
- points = [point(i, np.random.randint(0,K), xy)
96
- for i, xy in enumerate(hxy[0]['e'])]
97
- new_means, new_points = fit(points)
143
+ y_preds = run_Kmeans(num_magnets, np.array(hxy[0]['e']))
144
+ logging.info("Kmeans: %s",
145
+ [y_preds[y_preds==k].shape[0] for k in range(K)])
146
+ points = [point(i, k, hxy[0]['e'][i]) for i, k in enumerate(y_preds)]
98
147
  # move values to magnets:
99
- magnets = [{'e': [p.coord for p in new_points if p.k == k],
100
- 'pos': [], 'hxy': [], 'bxy': [], 'mxy': []}
148
+ magnets = [{'e': [[h['e'][p.index]*1e-3
149
+ for p in points if p.k == k]
150
+ for h in hxy]}
101
151
  for k in range(K)]
102
- hkeys = ['hxy', 'bxy', 'mxy']
103
- for i, h in enumerate(hxy): # all positions
104
- for mag in magnets:
105
- mag['pos'].append(h['pos'])
106
- m = [{k: [] for k in hkeys}
107
- for kk in range(K)]
108
- for p in new_points: # all elements
109
- for k in hkeys:
110
- m[p.k][k].append(h[k][p.k])
111
- for mk, magk in zip(m, magnets):
112
- for k in hkeys:
113
- magk[k].append(mk[k])
114
- for mag in magnets:
115
- for k in ['e'] + hkeys:
116
- mag[k] = np.array(mag[k])
117
- mag['havg'] = []
118
- mag['hmax'] = []
119
- for hpos in mag['hxy']:
120
- h = np.abs(np.linalg.norm(hpos, axis=1))
121
- mag['havg'].append(np.mean(h))
122
- mag['hmax'].append(np.max(h))
123
-
124
- # Note dimension of hkeys is (positions x elements x 2)
152
+
153
+ for k, mag in enumerate(magnets):
154
+ mag['pos'] = [h['pos'] for h in hxy]
155
+ for mk in ['hxy', 'bxy', 'mxy']:
156
+ mag[mk] = [[h[mk][p.index] for p in points if p.k == k]
157
+ for h in hxy]
158
+ hxyabs = [np.linalg.norm(hxy, axis=1)
159
+ for hxy in mag['hxy']]
160
+ mag['havg'] = [np.mean(a) for a in hxyabs]
161
+ mag['hmax'] = [np.max(a) for a in hxyabs]
125
162
 
126
163
  return magnets
164
+
165
+ if __name__ == '__main__':
166
+ import sys
167
+ import matplotlib.pyplot as plt
168
+ logging.basicConfig(level=logging.INFO,
169
+ format='%(asctime)s %(message)s')
170
+ magnets = read(sys.argv[1], int(sys.argv[2]))
171
+ for m in magnets:
172
+ print(f"{len(m['e'][0])}: Havg {m['havg']} Hmax {m['hmax']}")
173
+
174
+ fig, ax = plt.subplots()
175
+ for m in magnets:
176
+ b = np.array(m['e'][0])
177
+ ax.scatter(*b.T)
178
+ ax.set_aspect('equal')
179
+ ax.autoscale(enable=True)
180
+ ax.axis('off')
181
+ plt.show()
femagtools/isa7.py CHANGED
@@ -1357,13 +1357,15 @@ class Element(BaseEntity):
1357
1357
 
1358
1358
  def demagnetization(self, temperature=20):
1359
1359
  """return demagnetization Hx, Hy of this element"""
1360
- return self.demag_b(self.flux_density(cosys='cartes'), temperature)
1360
+ return self.demag_b(self.flux_density(cosys='polar'), temperature)
1361
1361
 
1362
1362
  def demag_b(self, b, temperature):
1363
1363
  """return demagnetization Hx, Hy of this element at flux density b
1364
1364
  and temperature"""
1365
1365
  if self.is_magnet():
1366
+ # assume polar coordinates of b
1366
1367
  pos = np.arctan2(self.center[1], self.center[0])
1368
+ #pos = 0 # cartesian
1367
1369
  br_temp_corr = 1. + self.br_temp_coef*(temperature - 20.)
1368
1370
  magn = np.sqrt(self.mag[0]**2 + self.mag[1]**2)*br_temp_corr
1369
1371
  alfa = np.arctan2(self.mag[1], self.mag[0]) - pos
@@ -4,13 +4,16 @@
4
4
  import logging
5
5
  import numpy as np
6
6
  from pathlib import Path
7
+ import shutil
7
8
  from .. import poc
8
9
  from .. import parstudy
9
10
  from .. import model
10
11
  from .. import utils
11
12
  from .. import windings
12
- from scipy.interpolate import RegularGridInterpolator, interp1d
13
+ from .. import femag
14
+ from scipy.interpolate import RegularGridInterpolator, interp1d, RectBivariateSpline
13
15
  from scipy.integrate import quad
16
+ import copy
14
17
 
15
18
  logger = logging.getLogger(__name__)
16
19
 
@@ -36,6 +39,50 @@ def _integrate1d(radius, val):
36
39
  return interp((x))
37
40
  return quad(func, radius[0], radius[-1])[0]
38
41
 
42
+ def ld_interpol(i1, beta, v):
43
+ '''interpolate Ld at beta angle 0°, -180°'''
44
+ # ld
45
+ cur = copy.deepcopy(i1)
46
+ betad = copy.deepcopy(beta)
47
+ if np.amin(beta) < -90 and \
48
+ np.amax(beta) > -90:
49
+ # motor and generator
50
+ v[0] = v[1]
51
+ v[-1] = v[-2]
52
+
53
+ dbeta = np.abs(beta[0][0] - beta[1][0])
54
+ bp = [[beta[0][0]-dbeta for i in range(len(np.unique(i1)))]] + beta[1:-1] + \
55
+ [[dbeta for i in range(len(np.unique(i1)))]]
56
+ else:
57
+ v[-1] = v[-2]
58
+ dbeta = np.abs(beta[0][0] - beta[1][0])
59
+ bp = beta[0:-1] + \
60
+ [[dbeta for i in range(len(np.unique(i1)))]]
61
+
62
+ return RectBivariateSpline(np.unique(bp), np.unique(cur), \
63
+ np.array(v)).ev(*[betad, i1]).tolist()
64
+
65
+ def lq_interpol(i1, beta, v):
66
+ '''interpolate Lq at beta -90°'''
67
+ if -90 not in np.unique(beta):
68
+ return v
69
+ # lq
70
+ betad = copy.deepcopy(beta)
71
+ if np.amin(beta) < -90 and \
72
+ np.amax(beta) > -90:
73
+ # motor and generator
74
+ inx = np.argwhere(np.array(beta) == -90).squeeze()
75
+ v.pop(inx[0, 0])
76
+ bp = beta[0:inx[0, 0]] + beta[inx[0, 0]+1:]
77
+ cp = i1[0:inx[0, 0]] + i1[inx[0, 0]+1:]
78
+ else:
79
+ v[0] = v[1]
80
+ dbeta = np.abs(beta[0][0] - beta[1][0])
81
+ bp = [[-90-dbeta for i in i1[0]]] + beta[1::]
82
+ cp = i1
83
+ cur = copy.deepcopy(cp)
84
+ return RectBivariateSpline(np.unique(bp), np.unique(cur), \
85
+ np.array(v)).ev(*[betad, i1]).tolist()
39
86
 
40
87
  def parident(workdir, engine, temp, machine,
41
88
  magnetizingCurves, magnetMat=[], condMat=[],
@@ -124,10 +171,6 @@ def parident(workdir, engine, temp, machine,
124
171
  ]
125
172
  }
126
173
 
127
- pstudy = parstudy.List(
128
- workdir, condMat=condMat, magnets=magnetMat,
129
- magnetizingCurves=magnetizingCurves,
130
- cmd=kwargs.get('cmd', None))
131
174
 
132
175
  ldq = []
133
176
  for magtemp in temp:
@@ -138,12 +181,37 @@ def parident(workdir, engine, temp, machine,
138
181
  poc=poc.Poc(999),
139
182
  speed=0)
140
183
  logging.info("Noload simulation")
141
- nlresults = pstudy(nlparvardef, machine, nlcalc, engine)
142
- if nlresults['status'].count('C') != len(nlresults['status']):
143
- raise ValueError('Noload simulation failed %s', nlresults['status'])
184
+ if kwargs.get('use_multiprocessing', True):
185
+ pstudy = parstudy.List(
186
+ workdir, condMat=condMat, magnets=magnetMat,
187
+ magnetizingCurves=magnetizingCurves,
188
+ cmd=kwargs.get('cmd', None))
189
+
190
+ nlresults = pstudy(nlparvardef, machine, nlcalc, engine)
191
+ if nlresults['status'].count('C') != len(nlresults['status']):
192
+ raise ValueError('Noload simulation failed %s', nlresults['status'])
193
+ else:
194
+ nlresults = {"x": [], "f": []}
195
+ i = 0
196
+ for pw, le, sp in zip(pole_width, lfe, linspeed):
197
+ nlmachine = {k: machine[k] for k in machine}
198
+ nlmachine['pole_width'] = pw
199
+ nlmachine['lfe'] = le
200
+ nlcalc.update({"speed": sp})
201
+ nlsubdir = f'{workdir}/{i}'
202
+ nlworkdir = Path(nlsubdir)
203
+ if nlworkdir.exists():
204
+ shutil.rmtree(nlworkdir)
205
+ nlworkdir.mkdir(exist_ok=True)
206
+ noloadsim = femag.Femag(nlworkdir, condMat=condMat, magnets=magnetMat,
207
+ magnetizingCurves=magnetizingCurves,
208
+ cmd=kwargs.get('cmd', None))
209
+ r = noloadsim(nlmachine, nlcalc)
210
+ nlresults['f'].append({k: v for k, v in r.items()})
211
+ i = i + 1
144
212
  nlresults.update(process(lfe, pole_width, machine, nlresults['f']))
145
- current_angles = nlresults['f'][0]['current_angles']
146
213
 
214
+ current_angles = nlresults['f'][0]['current_angles']
147
215
  results = []
148
216
  i = 0
149
217
  for l, pw in zip(lfe, pole_width):
@@ -152,17 +220,11 @@ def parident(workdir, engine, temp, machine,
152
220
  mpart['lfe'] = l
153
221
  subdir = f"{workdir}/{i}"
154
222
 
155
- gpstudy = parstudy.Grid(
156
- subdir, condMat=condMat, magnets=magnetMat,
157
- magnetizingCurves=magnetizingCurves,
158
- cmd=kwargs.get('cmd', None))
159
-
160
223
  simulation = dict(
161
224
  calculationMode="torq_calc",
162
225
  wind_temp=20.0,
163
226
  magn_temp=magtemp,
164
227
  angl_i_up=0.0,
165
- magnet_loss=True,
166
228
  magn_height=machine['magnet']['afm_rotor']['magn_height'],
167
229
  yoke_height=machine['magnet']['afm_rotor'].get(
168
230
  'yoke_height', 0),
@@ -173,8 +235,36 @@ def parident(workdir, engine, temp, machine,
173
235
  num_move_steps=60,
174
236
  speed=linspeed[i],
175
237
  num_par_wdgs=machine[wdgk].get('num_par_wdgs', 1))
176
-
177
- lresults = gpstudy(parvardef, mpart, simulation, engine)
238
+
239
+ if kwargs.get('use_multiprocessing', True):
240
+ gpstudy = parstudy.Grid(
241
+ subdir, condMat=condMat, magnets=magnetMat,
242
+ magnetizingCurves=magnetizingCurves,
243
+ cmd=kwargs.get('cmd', None))
244
+ lresults = gpstudy(parvardef, mpart, simulation, engine)
245
+
246
+ else:
247
+ lresults = {"x": [], "f": []}
248
+ domain_beta = np.linspace(beta_min, 0, num_beta_steps).tolist()
249
+ domain_cur = np.linspace(i1_max/num_cur_steps, i1_max, num_cur_steps).tolist()
250
+ dir_index = 0
251
+ for cur in domain_cur:
252
+ for be in domain_beta:
253
+ simulation['angl_i_up'] = be
254
+ simulation['current'] = cur
255
+ lresults['x'].append([be, cur])
256
+ subsubdir = subdir + f'/{dir_index}'
257
+ dir_index = dir_index + 1
258
+ lworkdir = Path(subsubdir)
259
+ if lworkdir.exists():
260
+ shutil.rmtree(lworkdir)
261
+ lworkdir.mkdir(exist_ok=True)
262
+ loadsim = femag.Femag(lworkdir, condMat=condMat, magnets=magnetMat,
263
+ magnetizingCurves=magnetizingCurves,
264
+ cmd=kwargs.get('cmd', None))
265
+ r = loadsim(mpart, simulation)
266
+ lresults['f'].append({k: v for k, v in r.items()})
267
+
178
268
  f = [{k: bch[k]
179
269
  for k in ('linearForce', 'flux', 'losses', 'lossPar')}
180
270
  for bch in lresults['f']]
@@ -198,6 +288,29 @@ def parident(workdir, engine, temp, machine,
198
288
  (-1, num_beta_steps)).T/np.sqrt(2)
199
289
  psiq = np.reshape([r['psiq'] for r in postp],
200
290
  (-1, num_beta_steps)).T/np.sqrt(2)
291
+
292
+ ld = np.reshape([r['Ld'] for r in postp],
293
+ (-1, num_beta_steps)).T.tolist()
294
+ lq = np.reshape([r['Lq'] for r in postp],
295
+ (-1, num_beta_steps)).T.tolist()
296
+ # interpolation ld, lq
297
+ curr, angl = [], []
298
+ for cr in range(len(beta)):
299
+ curr.append(i1)
300
+ for al in beta:
301
+ tmp = []
302
+ for cr in range(len(i1)):
303
+ tmp.append(al)
304
+ angl.append(tmp)
305
+ try:
306
+ xx, yy = copy.deepcopy(curr), copy.deepcopy(angl)
307
+ ld = ld_interpol(xx, yy, ld)
308
+ xx, yy = copy.deepcopy(curr), copy.deepcopy(angl)
309
+ lq = lq_interpol(xx, yy, lq)
310
+ except:
311
+ ld = np.zeros_like(psid).tolist()
312
+ lq = np.zeros_like(psid).tolist()
313
+
201
314
  torque = np.reshape([r['torque'] for r in postp],
202
315
  (-1, num_beta_steps)).T
203
316
  losses = {k: np.flip(np.reshape([r['plfe'][k] for r in postp],
@@ -214,6 +327,7 @@ def parident(workdir, engine, temp, machine,
214
327
  ldq.append({'temperature': magtemp,
215
328
  'i1':i1, 'beta':beta,
216
329
  'psid': psid.tolist(), 'psiq': psiq.tolist(),
330
+ 'ld': ld, 'lq': lq,
217
331
  'torque': torque.tolist(),
218
332
  'losses': losses})
219
333
  # T = 3/2 p (Psid iq - Psiq id)
@@ -736,8 +736,10 @@ def im(pnom: float, speed: float, p: int, **kwargs) -> dict:
736
736
  slots = []
737
737
  r = get_stator_dimensions(par, slots=slots)
738
738
  # rotor parameters
739
+ rtype = kwargs.get('rtype', 'rotorKs2')
739
740
  r['rotor'] = get_im_rotor_dimensions(
740
- par['cos_phi']*r['A'], r['Da2'], r['psi1'], r['lfe'], par)
741
+ par['cos_phi']*r['A'], r['Da2'], r['psi1'], r['lfe'],
742
+ par, rtype=rtype)
741
743
  _set_genpars(r, 2*par['p'])
742
744
  r['name'] = f"IM-{r['poles']}"
743
745
  return r
@@ -350,21 +350,27 @@ def dqparident(workdir, engine, temp, machine,
350
350
  """
351
351
  import pathlib
352
352
 
353
- da1 = machine['outer_diam']
353
+ wdgk = 'windings' if 'windings' in machine else 'winding'
354
+ da1 = machine['bore_diam']
354
355
  Q1 = machine['stator']['num_slots']
356
+ lfe = machine['lfe']
357
+ g = machine[wdgk].get('num_par_wdgs', 1)
355
358
  slotmodel = [k for k in machine['stator'] if isinstance(
356
359
  machine['stator'][k], dict)][-1]
357
360
  if slotmodel == 'stator1':
358
361
  hs = machine['stator']['stator1']['slot_rf1'] - \
359
362
  machine['stator']['stator1']['tip_rh1']
360
363
  else:
361
- hs = machine['stator'][slotmodel].get('slot_height', 0)
362
- wdgk = 'windings' if 'windings' in machine else 'winding'
364
+ dy1 = machine['outer_diam']
365
+ hs = machine['stator'][slotmodel].get(
366
+ 'slot_height', 0.6*(dy1-da1)/2)
367
+
363
368
  N = machine[wdgk]['num_wires']
364
- Jmax = 15 # max current density in A/mm2
369
+ Jmax = 20e6 # max current density in A/m2
370
+ f = machine[wdgk].get('fillfac', 0.42)
371
+ Acu = f*0.5*np.pi*(da1+hs)*hs
372
+ i1_max = round(Acu/Q1/N*Jmax/10)*10
365
373
 
366
- i1_max = round(0.28*np.pi*hs*(da1+hs)/Q1/N*Jmax*1e5)*10 * \
367
- machine[wdgk].get('num_par_wdgs', 1)
368
374
  period_frac = kwargs.get('period_frac', 6)
369
375
  if machine.get('external_rotor', False):
370
376
  period_frac = 1 # TODO: missing femag support
@@ -381,8 +387,6 @@ def dqparident(workdir, engine, temp, machine,
381
387
 
382
388
  wdg = windings.Winding(wpar)
383
389
 
384
- lfe = machine['lfe']
385
- g = machine[wdgk].get('num_par_wdgs', 1)
386
390
  if 'wire_gauge' in machine[wdgk]:
387
391
  aw = machine[wdgk]['wire_gauge']
388
392
  elif 'dia_wire' in machine[wdgk]:
femagtools/multiproc.py CHANGED
@@ -256,5 +256,5 @@ class Engine:
256
256
  try:
257
257
  self.pool.terminate()
258
258
  self.pool.close()
259
- except AttributeError:
259
+ except AttributeError as e:
260
260
  logger.warn("%s", e)
femagtools/plot/nc.py CHANGED
@@ -14,16 +14,21 @@ DEFAULT_CMAP='viridis'
14
14
  """default colormap (see https://matplotlib.org/stable/users/explain/colors/colormaps.html)"""
15
15
 
16
16
 
17
- def spel(isa, with_axis=False, ax=0):
17
+ def spel(isa, superelements=[], with_axis=False, ax=0):
18
18
  """plot super elements of I7/ISA7 model
19
19
  Args:
20
20
  isa: Isa7 object
21
+ superelements: list of super elements (all if empty)
21
22
  """
22
23
  from matplotlib.patches import Polygon
23
24
  if ax == 0:
24
25
  ax = plt.gca()
25
26
  ax.set_aspect('equal')
26
- for se in isa.superelements:
27
+ if superelements:
28
+ spels = superelements
29
+ else:
30
+ spels = isa.superelements
31
+ for se in spels:
27
32
  ax.add_patch(Polygon([n.xy
28
33
  for nc in se.nodechains
29
34
  for n in nc.nodes],
@@ -79,17 +84,16 @@ def _contour(ax, title, elements, values, label='',
79
84
  for n in nc.nodes],
80
85
  color='gray', alpha=0.1, lw=0))
81
86
  valid_values = np.logical_not(np.isnan(values))
82
- patches = np.array([Polygon([v.xy for v in e.vertices])
83
- for e in elements])[valid_values]
87
+ vertices = [[v.xy for v in e.vertices] for e in elements]
88
+ patches = np.array([Polygon(xy) for xy in vertices])[valid_values]
84
89
  p = PatchCollection(patches, match_original=False,
85
90
  cmap=cmap, alpha=alpha)
86
91
  p.set_array(np.asarray(values)[valid_values])
87
92
  ax.add_collection(p)
88
93
  cb = plt.colorbar(p, shrink=0.9)
89
94
 
90
- for patch in np.array([Polygon([v.xy for v in e.vertices],
91
- fc='white', alpha=1.0)
92
- for e in elements])[np.isnan(values)]:
95
+ for patch in np.array([Polygon(xy, fc='white', alpha=1.0)
96
+ for xy in vertices])[np.isnan(values)]:
93
97
  ax.add_patch(patch)
94
98
  if label:
95
99
  cb.set_label(label=label)
@@ -130,9 +134,10 @@ def demag_pos(isa, pos=-1, icur=-1, ibeta=-1, cmap=DEFAULT_CMAP, ax=0):
130
134
  x = isa.pos_el_fe_induction[i]
131
135
 
132
136
  hpol = demag[:, i]
137
+ hmax = np.max(hpol)
133
138
  hpol[hpol == 0] = np.nan
134
- _contour(ax, f'Demagnetization at pos. {round(x/np.pi*180):.1f}°,'
135
- f'{isa.MAGN_TEMPERATURE} °C (max -{np.max(hpol):.1f} kA/m)',
139
+ _contour(ax, f'Demagnetization at pos. {round(x/np.pi*180):.1f}°, '
140
+ f'{isa.MAGN_TEMPERATURE} °C (max -{hmax:.1f} kA/m)',
136
141
  emag, hpol, '-H / kA/m', cmap, isa)
137
142
  logger.info("Max demagnetization %f kA/m", np.nanmax(hpol))
138
143
 
@@ -232,7 +237,7 @@ def flux_density_pos(isa, ipos, subreg=[], icur=-1, ibeta=-1, cmap=DEFAULT_CMAP,
232
237
  for e in elements:
233
238
  fd = isa.flux_density(e, icur, ibeta)
234
239
  b.append(np.linalg.norm(
235
- (fd['bx'][ipos], fd['bx'][ipos])))
240
+ (fd['bx'][ipos], fd['by'][ipos])))
236
241
  fluxd = np.array(b)
237
242
  pos = isa.pos_el_fe_induction[ipos]*180/np.pi
238
243
  isa.rotate(isa.pos_el_fe_induction[ipos])
@@ -16,6 +16,15 @@ m.slot_r2 = ${model['slot_r2']*1e3} -- Slot radius [mm]
16
16
  m.mcvkey_yoke = mcvkey_yoke
17
17
  m.nodedist = ${model.get('m.nodedist', 1)} -- Node distance
18
18
 
19
+ -- overdeterminate slot_h2
20
+ if (math.abs(m.slot_h2 - m.slot_r1 - m.slot_h1) > 0) then
21
+ m.slot_h2 = m.slot_h1 + m.slot_r1
22
+ end
23
+ -- overdeterminate slot_open_width
24
+ if (m.slot_r1 > 0 and math.abs(m.slot_width - 2*m.slot_r1 - m.slot_open_width) > 0) then
25
+ m.slot_open_width = m.slot_width - 2*m.slot_r1
26
+ end
27
+
19
28
  if (m.model_type == "S1R2") or (m.model_type == "S1R2_all") then
20
29
  if (m.st_yoke_height > 0) then
21
30
  m.st_yoke_height = 0
@@ -68,7 +77,7 @@ m.nodedist = ${model.get('m.nodedist', 1)} -- Node distance
68
77
 
69
78
  if (m.slot_r1 > 0) then
70
79
  C1 = fml.Circle:Create(P33,m.slot_r1)
71
- P32 = fml.Point:Tangent(P52,C1,2)
80
+ P32 = fml.Point:Tangent(P52,C1,1)
72
81
  end
73
82
 
74
83
  model_size = m.pole_width*m.num_poles*m.num_slots/m.tot_num_slot
@@ -77,7 +86,7 @@ m.nodedist = ${model.get('m.nodedist', 1)} -- Node distance
77
86
 
78
87
  nc_line(P11.x,P11.y, P51.x,P51.y, 0)
79
88
  nc_line_cont(P52.x, P52.y, 0)
80
- if P32 ~= nil then
89
+ if P32 ~= nil and m.slot_r1 > 0 then
81
90
  nc_line_cont(P32.x, P32.y, 0)
82
91
  nc_circle_m(P23.x,P23.y, P32.x,P32.y, P33.x,P33.y, m.slot_r1, 0)
83
92
  else
@@ -33,7 +33,5 @@ post_models("induct(x)","b") -- Calculate field distribution
33
33
  until i>=N
34
34
  io.close(data)
35
35
 
36
- color_gradation(0,0,"tot","Babs",0,0,"")
37
36
  -- experimental (new femag-classic needed)
38
- -- without grf_clear, overlay fieldlines with color gradation
39
- add_field_lines("field.svg", 25)
37
+ export_calc_results('fieldcalc.vtu')
femagtools/vtu.py CHANGED
@@ -1,9 +1,11 @@
1
1
  """Read FEMAG vtu files
2
2
 
3
3
  """
4
- import vtk
4
+ import logging
5
5
  import pathlib
6
6
  import numpy as np
7
+ import vtk
8
+ from vtkmodules.util.numpy_support import vtk_to_numpy
7
9
 
8
10
 
9
11
  class Reader(object):
@@ -23,11 +25,13 @@ class Reader(object):
23
25
  self.field_data_names = []
24
26
  self.point_data_names = []
25
27
  self.cell_data_names = []
28
+ assert pathlib.Path(pathname).exists(), f"{pathname} not found"
26
29
  if pathlib.Path(pathname).suffix == '.vtu':
27
30
  self.filenames = [pathlib.Path(pathname)]
28
31
  else:
29
32
  self.filenames = sorted(pathlib.Path(pathname).glob(
30
33
  "*.vtu"))
34
+
31
35
  self.reader.SetFileName(str(self.filenames[0]))
32
36
  self.reader.Update()
33
37
  self.field_data_names = [
@@ -181,7 +185,7 @@ class Reader(object):
181
185
  point_vec.append(self.data[pnt_data][i].GetValue(pnt-1))
182
186
  return point_vec
183
187
 
184
- def get_cell_vector(self, cell_data, cell) -> list:
188
+ def get_cell_vector(self, cell_data, cell=0) -> list:
185
189
  '''Read cell data
186
190
 
187
191
  Args:
@@ -195,6 +199,9 @@ class Reader(object):
195
199
  if cell_data not in self.data:
196
200
  self.read_data([cell_data])
197
201
 
202
+ if cell<=0:
203
+ return vtk_to_numpy(
204
+ self.output.GetCellData().GetAbstractArray(cell_data))
198
205
  i = self.cell_data_names.index(cell_data)
199
206
  noc = self.output.GetCellData().GetAbstractArray(i).GetNumberOfComponents()
200
207
  if noc == 1:
@@ -228,12 +235,64 @@ class Reader(object):
228
235
  else:
229
236
  return [cell_vec_x, cell_vec_y, cell_vec_z]
230
237
 
238
+ def hrphi(self, scf, elements, magtemp):
239
+ """return H values for each element in polar coord system
240
+ (experimental)
241
+ Args:
242
+ elements: list of model elements
243
+ magtemp: magnet temperature in degree Celsius
244
+ scf: scale factor (poles/poles in model)
245
+ """
246
+ MUE0 = 4e-7*np.pi
247
+ b = vtk_to_numpy(
248
+ self.output.GetCellData().GetAbstractArray("b"))[:, :2]
249
+ e = elements[0]
250
+ x, y = np.mean(vtk_to_numpy(
251
+ self.output.GetCell(e.key-1).GetPoints().GetData()), axis=0)[:2]
252
+ rotpos = np.arctan2(y, x) - np.arctan2(e.center[1], e.center[0])
253
+ psign = 1 if rotpos / scf > 1 else -1
254
+
255
+ h = np.empty((len(elements), 2))
256
+ for i, e in enumerate(elements):
257
+ x, y = e.center
258
+ alfa = np.arctan2(y, x)
259
+ b1, b2 = b[e.key-1]
260
+ btempc = 1. + e.br_temp_coef*(magtemp - 20.)
261
+ m1 = e.mag[0]*np.cos(alfa) + e.mag[1]*np.sin(alfa)
262
+ m2 = -e.mag[0]*np.sin(alfa) + e.mag[1]*np.cos(alfa)
263
+ h[i] = abs(e.reluc[0])/MUE0*np.array((
264
+ (b1 - psign*btempc*m1), (b2 - psign*btempc*m2)))
265
+ logging.debug("H shape %s", h.shape)
266
+ return h
267
+
268
+
269
+ def demag(self, elements):
270
+ """return demag values for each element in kA/m
271
+ Args:
272
+ elements: list of model elements
273
+ Returns:
274
+ list of demags from each vtu file in set
275
+ """
276
+ dlist = []
277
+ for filename in self.filenames:
278
+ self.reader.SetFileName(str(filename))
279
+ self.reader.Update()
280
+ d = vtk_to_numpy(
281
+ self.output.GetCellData().GetAbstractArray("demagnetization"))
282
+ dm = np.empty((len(elements)))
283
+ for i, e in enumerate(elements):
284
+ dm[i] = d[e.key-1]
285
+ dlist.append(dm)
286
+ logging.debug("Demag shape %s", np.array(dlist).shape)
287
+ return dlist
288
+
289
+
231
290
  def get_data_vector(self, data_name, key=0) -> list:
232
291
  '''Read data of fiels, point or cell
233
292
 
234
293
  Args:
235
294
  data_name : str Name of data to read
236
- hey : int (optional) Key of point or cell
295
+ key : int (optional) Key of point or cell
237
296
 
238
297
  Returns:
239
298
  List of values within the time window
@@ -246,6 +305,16 @@ class Reader(object):
246
305
  return self.get_cell_vector(data_name, key)
247
306
  return []
248
307
 
308
+ def __repr__(self):
309
+ fmt = [f"N Cells {self.output.GetNumberOfCells()} N Points {self.output.GetNumberOfPoints()}"]
310
+ fmt += [
311
+ f"{self.output.GetPointData().GetAbstractArray(i).GetName()} Points"
312
+ for i in range(self.output.GetPointData().GetNumberOfArrays())]
313
+ fmt += [
314
+ f"{self.output.GetCellData().GetAbstractArray(i).GetName()} Cells"
315
+ for i in range(self.output.GetCellData().GetNumberOfArrays())]
316
+ return '\n'.join(fmt)
317
+
249
318
 
250
319
  def read(filename) -> Reader:
251
320
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: femagtools
3
- Version: 1.5.0
3
+ Version: 1.5.2
4
4
  Summary: Python API for FEMAG
5
5
  Author-email: Ronald Tanner <tar@semafor.ch>, Dapu Zhang <dzhang@gtisoft.com>, Beat Holm <hob@semafor.ch>, Günther Amsler <amg@semafor.ch>, Nicolas Mauchle <mau@semafor.ch>
6
6
  License: Copyright (c) 2016-2023, Semafor Informatik & Energie AG, Basel
@@ -1,7 +1,7 @@
1
- femagtools/__init__.py,sha256=eMGclaNbcY0JFMROit3E9gDgFcosrLZzcT5F3FYErwY,1615
1
+ femagtools/__init__.py,sha256=kGZSfjN0Y6_CwYhVU9ki2misQXnylS2nmIQNI60q1lk,1615
2
2
  femagtools/airgap.py,sha256=s8NoKFvBhkINxkMLG02RbLZA9PiSx9KMtPjByy1WwNc,1584
3
3
  femagtools/amazon.py,sha256=O1ICuv21XDAJi1qK1Sigs2TdS6hDZP19OzvmE2t76wU,12069
4
- femagtools/amela.py,sha256=m1iRPzZRGHXyHz06Po20bPIYm60nPXC3ATcCUXx5qm8,13731
4
+ femagtools/amela.py,sha256=pHjfXzpANI-7oz8MtrqNcyDZ6PxVM91vCJuvYhHy1rk,13891
5
5
  femagtools/asm.py,sha256=CiL0KWaF4P7O6-VwmGLdva_icwmPrPiI-TFQ19XYTKk,7660
6
6
  femagtools/bch.py,sha256=q6vMKFI0DSMQZDsOPAxMVPoxzz6aAUCApuwcW6c_oXM,70154
7
7
  femagtools/bchxml.py,sha256=KrRjAdrUPZXmiWvonu9HhpG_NvImMBpiXWTL4iSr4kE,3142
@@ -15,15 +15,15 @@ femagtools/dakotaout.py,sha256=6nn0PXsB40mPKiQLenqAtHy0KXCO7kvqqQ-aD2JhQvw,5573
15
15
  femagtools/docker.py,sha256=XDVmLBB0z4sZZpcrx7Wbm84xl4ksj7aqn5-ZOPxdxm4,7460
16
16
  femagtools/ecloss.py,sha256=boekPeuh3XlfdcEmtbg9IvmxeheX1PFm1ySv9QnY_90,12925
17
17
  femagtools/erg.py,sha256=IXKq76P9qLt_ssNOP78v8Qizk3J2Zg80yaKDSjzwoJE,1224
18
- femagtools/femag.py,sha256=kV0_iuEmCEUUXOaS2lNpCrxlmkQIKR4rS6TOvRCTE58,41522
18
+ femagtools/femag.py,sha256=0XfEiXkfv2MWW6qh3D25Za4Vq9uDP_UIEyHCIBL_wok,42305
19
19
  femagtools/forcedens.py,sha256=nEM1MHxtpLee2sGFsehzrWEdsCRe_RSRqyNfj6u_l8g,7415
20
- femagtools/fsl.py,sha256=ufZ1hhER1RywRu-GvopszGAfVTbtcu5Jltv2XYONIbY,31377
20
+ femagtools/fsl.py,sha256=3jbMaE63DMdm-2GxSFtTjMCfOI-Ql5xASe7L8IohRC8,31377
21
21
  femagtools/getset.py,sha256=yJ6Em35DeWK7WNZW0qjjS5s7LUkVh5mbgxF59HHm5FM,3017
22
22
  femagtools/gmsh.py,sha256=IKhNiviIBji4cMxAhxaYXNqBRMNAPSKsBGdnGyxkyQw,3903
23
23
  femagtools/google.py,sha256=ugRyHY1zBjHR4aNfbA7GeF-ZU_NgleuVTZaWpi_XLT4,17144
24
24
  femagtools/grid.py,sha256=s7LfKKLm2H4-cza2kSEANq6vwxq10Su3TJl3kHShHRA,1561
25
- femagtools/hxy.py,sha256=TU0GoHtStq3VBoc4nGLmtKquY8-tT0UWxLf5FzMBLjE,3738
26
- femagtools/isa7.py,sha256=2gre9mHYydA_uD0TxBkxsAU4phI9W3DK-QoZV9Us0A0,57297
25
+ femagtools/hxy.py,sha256=PkiZ_-CRhtvtpkmLAP8iMtwvzh7CjKGGcAbOhFb4Nls,6275
26
+ femagtools/isa7.py,sha256=KDZcakwRdlC8KECpQKoFzI-L2ZILJSaUp_MNOZNOfoE,57374
27
27
  femagtools/jhb.py,sha256=stJxkmzHpfUIBVcFw7jWbV5KN9_EFqzOCgacyhUqWvM,1779
28
28
  femagtools/job.py,sha256=dOatzr10nIda76CjVRSS0SfEWC8_BAw0kowli523qbY,11320
29
29
  femagtools/losscoeffs.py,sha256=dlSYDS13RqpPHLdv_EPWIA9liwhqjbxUiN7t7GFPZhw,5397
@@ -32,7 +32,7 @@ femagtools/mcv.py,sha256=Pll-r0YZh-wp9EQBTD4XEBlX4J5jy4oeVa22SYIM7q8,39744
32
32
  femagtools/me.py,sha256=XNK0l-aroNYfKyxV_uslE8q3vJb_KuntAYTWd-4FQaQ,1833
33
33
  femagtools/model.py,sha256=wcOZwKe8nd_vwe4SlLmWPe4ukvtVINUE8Qi5HEp2hkw,15018
34
34
  femagtools/moproblem.py,sha256=kOP8pRdD8YXz28_M2WKnFgl3eeJ7tqg49ohoazsmUOg,2825
35
- femagtools/multiproc.py,sha256=zzw2BECUw4oj_az3nT0py4S-zqyAl6IpMSccTLfr1_Y,8430
35
+ femagtools/multiproc.py,sha256=7mJF-VU1NrJkENyg8eHtDrDRNBwLPK43phZv3ehm9BU,8435
36
36
  femagtools/mxw2msh.py,sha256=CIIqAvfs8U-A0OfuOAoDaqNSmoMSHSI_tW1CPFRCP5E,2151
37
37
  femagtools/nc.py,sha256=VQKpA2ZLoyvkQmzmHGrG7oePfGvynNw-pwqfavSxJx8,14233
38
38
  femagtools/netlist.py,sha256=CSCl8setLZ_L8DCnNWaNA3-wLe1yo-fmzARZoVvYfaA,2052
@@ -44,7 +44,7 @@ femagtools/tks.py,sha256=FuEKiWcSnOW2Hp2NxCq1hBeQdRFkHutaJuctrhxh8Ws,6228
44
44
  femagtools/ts.py,sha256=JZbiXhss6f5J8gDhOMmfZe-fkroBA1BRcpGE5PGZjWU,47175
45
45
  femagtools/utils.py,sha256=Pi-FeM81Fm0m3GF1Mq9EYcTNeW_BI6qIXVGhbYcC1cY,1434
46
46
  femagtools/vbf.py,sha256=9XGfhftmD9carU8ByQ5DwqoR4daq5mJ39eMqruwml0Q,2444
47
- femagtools/vtu.py,sha256=NhbwGGGeRDhvNWA58z-Npm7nylvfOzZcaYtfHHWWjqE,8000
47
+ femagtools/vtu.py,sha256=Sf83dHIfCKY2km-MIUHKKoj-JKN4PDX7kkPLZXyIYY4,10723
48
48
  femagtools/windings.py,sha256=6ioABZRWQ3xA4kmEz2NUkXh-C-FmW9YYkjQKs5YakQs,22197
49
49
  femagtools/dxfsl/__init__.py,sha256=MywcCdpKPKs4qJBJJgeDsikJFJ2P48dbTuNk303f5pM,76
50
50
  femagtools/dxfsl/area.py,sha256=3YSa6tNW1vToZiUuo-0cghxtYG0jzIOU91dEibueltE,55787
@@ -59,13 +59,13 @@ femagtools/dxfsl/machine.py,sha256=E2w1vduaRn1yWfp6cQtvN4Rf0AeJWqbHNtOF5YofeEI,3
59
59
  femagtools/dxfsl/plotrenderer.py,sha256=lJFEH0Jdsph3atcABMS6IweKNPANxJA1aF0YlMdk_p0,12725
60
60
  femagtools/dxfsl/shape.py,sha256=BYIePcfpSPLgE5DjwTs5ofQbuIF4MdTvCitwrvNQiw4,46010
61
61
  femagtools/machine/__init__.py,sha256=m3DnYBP8Wxh-qDoFhkPVlXUGcA4fjDOVleqo3YQ4syA,7728
62
- femagtools/machine/afpm.py,sha256=uSXO0e0MX4Y2dIJotesdKO55S1nz3c1EZJ1ho5QokwA,20017
62
+ femagtools/machine/afpm.py,sha256=TRRGKZWpbXWPXMJQPXAjfOtmXm1XPCnwgzhgBjexfl8,24813
63
63
  femagtools/machine/effloss.py,sha256=aaSmmxKd_KWMasHUHipYDcZOw-fvTHNa38MWFnpVock,13130
64
64
  femagtools/machine/im.py,sha256=ScIOLrlc4CPLYFNx2MmJqkpmbky_HXxFGZbMWUNGBrk,37881
65
65
  femagtools/machine/pm.py,sha256=suVFbQ8E8winWaoSQOYnA3Qggn_8ObQVS7mjigwO3Ig,53319
66
- femagtools/machine/sizing.py,sha256=BNaYNmZpOz-Q8grCara_hTeen5rbRPqpNcnLr84W9o4,23031
66
+ femagtools/machine/sizing.py,sha256=aN_OahewjTTBHnpRNfLh1AGFhqnoeZVuMBeb_3MCIVI,23096
67
67
  femagtools/machine/sm.py,sha256=iiFBLmMliDvx3rdKscU7XZLu0TK66F__BA5S7JlbR-8,32958
68
- femagtools/machine/utils.py,sha256=oqGE_q1uDZYR6cqo2TPNBh6gw8wBT_TfUlv9QB1FVxo,16698
68
+ femagtools/machine/utils.py,sha256=i2nnwYLTrf_OZbSDgo6uhHpH8-7UaWlRbvgp_BL4JSE,16770
69
69
  femagtools/moo/__init__.py,sha256=zinmWEOrsEz6DmMX0Dbn4t6_1UR-p4bEGqyR1wUQk_Q,175
70
70
  femagtools/moo/algorithm.py,sha256=lNEf0Bur4yFpIJeLtAC3oIus8sOMWTb7jepFlD28YzE,5445
71
71
  femagtools/moo/population.py,sha256=gi8PSVUXkYY5vzgAwWvxfMbH_z51fN58O4-NKoarwzI,10100
@@ -79,12 +79,12 @@ femagtools/plot/char.py,sha256=pfmsoSbrE4QuWBaGV9X7s2hT4OSK5ZQ99drmE4y1TDw,11192
79
79
  femagtools/plot/fluxdens.py,sha256=NlexRJ3f_8CgKoWrV82ZIsAXPrLhwj98uOe8_fUks7A,1082
80
80
  femagtools/plot/forcedens.py,sha256=37FQLViGsjCh20tSlWlVfLTsvtjzdK_pEQGC2KcQ-xI,2996
81
81
  femagtools/plot/mcv.py,sha256=AKbWhJd20Kcec8Hv9dX32G5yTLPkcWorQS7-3P6m-mQ,2960
82
- femagtools/plot/nc.py,sha256=Y1C0FdZs_dOA5YMUf3Fuz0ZfTNV9dD9g5aztKZrRFow,9380
82
+ femagtools/plot/nc.py,sha256=CU-6420EYq6S4ZzyqxCOyxrbHIeJ8_aBVxDPM3E2oD4,9516
83
83
  femagtools/plot/phasor.py,sha256=5iqxCQi_idkdqYALJjQb6YFr_Zv5xsUayDoKL5HzsdE,4765
84
84
  femagtools/plot/wdg.py,sha256=UooR1K8JDoVjKWEox_AfkBY40L87jk2L9OdIFz4O-OY,8462
85
85
  femagtools/templates/FE-losses.mako,sha256=Rql5_8Q6_uthpr-uFXMUo7tdHehfZYND-7M-ohJXVU8,874
86
86
  femagtools/templates/afm_rotor.mako,sha256=fY-dlZvRLN9UAy5V6Q_inWghkSUe8pzrCYjJdNgfNXs,3112
87
- femagtools/templates/afm_stator.mako,sha256=LbsnLoXuF52qJHhqghj8jWJFRBiM3DGXqqQEtiGjhXI,5005
87
+ femagtools/templates/afm_stator.mako,sha256=l1xEwxffZ1jyx5wuJ3rhVbVlZirJzD2K8n4i5Dvbxuc,5344
88
88
  femagtools/templates/airgapinduc.mako,sha256=aCMLZ7P4vjeSGikIetkwymgDjESdftPN_aYx2LfjfsY,246
89
89
  femagtools/templates/asyn_motor.mako,sha256=vvZ0SIJj4ORaCbE1Hl5NeCU_j2CWdOltVpSKP7ESJTQ,2879
90
90
  femagtools/templates/basic_modpar.mako,sha256=7qXIYrqJqI3xRnxXKG5zSwBNsiQotc94Q37X4sbAXxQ,3036
@@ -98,7 +98,7 @@ femagtools/templates/connect_models.mako,sha256=8j1hzBMeoDJ7-GL5BH-S5p53Bu5jtqqs
98
98
  femagtools/templates/cu_losses.mako,sha256=EeNwINYuwBuhbo9LH3STdQOTxOyyWw_BANgh_BSV9TE,1339
99
99
  femagtools/templates/ec-rotorbar.mako,sha256=RbA1TVNczEEddTNjvGLPxILExxp4rIgoxXe1YT6a4Is,1672
100
100
  femagtools/templates/fe-contr.mako,sha256=NoP7FQ62ITxgNmwP6GmkCnGhjEn5gPLUFgdLdhkKylY,1983
101
- femagtools/templates/fieldcalc.mako,sha256=-KgomjTDoWIJH-9nMyfkIWvfSjHnYYeuL8eIGyvZnCs,905
101
+ femagtools/templates/fieldcalc.mako,sha256=yZ0_uAtdtzpv1uPjd92zyCbzTLhu2Rvvd5mRaOyesSU,806
102
102
  femagtools/templates/gen_winding.mako,sha256=yRe00f1L4_UuEOVwBkbEOL6rgG8NY43Jbpdud1nw4oo,3834
103
103
  femagtools/templates/inductances.mako,sha256=OpcW3E7LW09J8eoXylzfq2R16LKKxzJDr0PGCdHzixM,560
104
104
  femagtools/templates/ld_lq_fast.mako,sha256=BEQoplL7Ojqg5caldzAhMLKL-3E78wCSSbz5-KkDk2o,1359
@@ -162,6 +162,7 @@ tests/test_erg.py,sha256=kRVzpXa6JDdbxTss18HUWKny9Dx8IMx9uGTrbQCnHwg,523
162
162
  tests/test_femag.py,sha256=l7-av3eitLm7bwTuunEmVeTspi82ifPrlz7f1boGdVI,1934
163
163
  tests/test_forcedens.py,sha256=Yzl3SAmJNkZN9dA3aLxRvwY8fKsw077Fl0iJm6zJ5Sk,536
164
164
  tests/test_fsl.py,sha256=I2UqfZgvm5J2kc8sRlDiQY9MH6wIjBmLLx0i-fYqYYA,16623
165
+ tests/test_hxy.py,sha256=pVb6ZfDhBy5-DXa3gh7RQmLFG8p5cSYB8gdGLC8kjAk,640
165
166
  tests/test_im.py,sha256=55wfCoA8_PuogI_RsC3AjUQCpR84T-HddtHuU1NxfPc,662
166
167
  tests/test_isa7.py,sha256=GJhRj2nncrUpNTIlM4jvG4kKZS7cK19hhQg9KbM3b5Q,3001
167
168
  tests/test_jhb.py,sha256=aDzwr2ZaXlizrPnlLlcI_IT3OpSxuKu-FzBBkIALEDg,824
@@ -179,12 +180,12 @@ tests/test_nc.py,sha256=aQNHHDBnyr1mV8yfaBh728tjDkRn3DLUgEaYV5GtBYE,4205
179
180
  tests/test_parident.py,sha256=RiEEdRjR6SVebdxPMwkT0FMt7MlHXCfxChHpbAo5reI,1340
180
181
  tests/test_parstudy.py,sha256=wk7WfYQrx5dtv6MnmWCfNAEInvRKsbVXYEUIIR9zLbQ,3200
181
182
  tests/test_pocfile.py,sha256=eiMLBRQxDnHIGiqku6EXcQ3fb7wGIxhXmb20iyLlPRU,5816
182
- tests/test_sizing.py,sha256=UEZV0wLNQhzcXVO1ysfQNXdX-fNIEM98Ya8zFw6gFf8,1109
183
+ tests/test_sizing.py,sha256=8tIT8DG1c28aSwkPD4qPryKk3sU2JhXWLYYxhmDQMbM,1131
183
184
  tests/test_sm.py,sha256=FjcAbx4n7kLH00kjnKoGMk6t4_V9TJzIaxM21MkrOjE,83524
184
185
  tests/test_tksreader.py,sha256=8QtPAzxPJbkpxd1Nw2I7ggaTaKaL4WY55JJBHkZAzus,766
185
186
  tests/test_ts.py,sha256=tR2x5cKU9gw2fUprzaPgPbCvmDOHDO36JUPCCoTlY7Y,1833
186
187
  tests/test_vbfreader.py,sha256=-6oAhLJDb7K3Ui5O1mtHvbskawEfgyIH-Of5n-8u-fc,832
187
- tests/test_vtu.py,sha256=mZe-JDFUv0SDRofx8sH0R8mO2MGf1Evbvvd-Oc5DrRo,872
188
+ tests/test_vtu.py,sha256=pGpHuAcaCk5zDYTBBp_akOEenZOpq-IzGl_kaMtodyA,1469
188
189
  tests/test_windings.py,sha256=PerbhIvIeyTuHZbBCORUy9EINKEhVoyN6vshtsrs1xA,4912
189
190
  tests/engines/__init__.py,sha256=l8HD-AY8EwxOoo_VrG3HgEZb2MaHypvnhKCVSkR-DTA,808
190
191
  tests/engines/test_amazon.py,sha256=4uy36NIo0epi3CgjUm8vl4snLpr4NRvUoWi6Zew_zcE,2014
@@ -196,9 +197,9 @@ tests/moo/__init__.py,sha256=l8HD-AY8EwxOoo_VrG3HgEZb2MaHypvnhKCVSkR-DTA,808
196
197
  tests/moo/test_algorithm.py,sha256=Em8sFm2vzPmuIzRrBBnUQLU_TYuJHSf-kEeozw0XeX4,2563
197
198
  tests/moo/test_population.py,sha256=FvX9LRCxQx0_E2GxHQ5vKwOYFBQiNbT6Lmv5GmNWjTQ,5471
198
199
  tests/moo/test_problem.py,sha256=ALeP4u7g-dFhfwWL8vxivdrrYzVKPjHMCAXzzgyNZbs,467
199
- femagtools-1.5.0.dist-info/LICENSE,sha256=V5OED7AzEaOtvbfgNheKOSUeNtijvKQuo84FtSJNkJU,1316
200
- femagtools-1.5.0.dist-info/METADATA,sha256=JA6n507B4ZEi8wJjCA6QTIU99W-aBi10TJBmwV-VCBI,5685
201
- femagtools-1.5.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
202
- femagtools-1.5.0.dist-info/entry_points.txt,sha256=UXpu6KnrykN89sCUaFAIIzn_dYwuxizUS0GcPdoekro,195
203
- femagtools-1.5.0.dist-info/top_level.txt,sha256=Ri4YWtU8MZTzNje9IKyXhTakNbsrCynuWdon4Yq94Dc,17
204
- femagtools-1.5.0.dist-info/RECORD,,
200
+ femagtools-1.5.2.dist-info/LICENSE,sha256=V5OED7AzEaOtvbfgNheKOSUeNtijvKQuo84FtSJNkJU,1316
201
+ femagtools-1.5.2.dist-info/METADATA,sha256=M2C4o3QLWJgrRNDvT0hE7k3yKK1WTroS-lzvUuhdIh0,5685
202
+ femagtools-1.5.2.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
203
+ femagtools-1.5.2.dist-info/entry_points.txt,sha256=UXpu6KnrykN89sCUaFAIIzn_dYwuxizUS0GcPdoekro,195
204
+ femagtools-1.5.2.dist-info/top_level.txt,sha256=Ri4YWtU8MZTzNje9IKyXhTakNbsrCynuWdon4Yq94Dc,17
205
+ femagtools-1.5.2.dist-info/RECORD,,
tests/test_hxy.py ADDED
@@ -0,0 +1,19 @@
1
+ import femagtools.hxy
2
+ import pathlib
3
+ import pytest
4
+
5
+
6
+ @pytest.fixture
7
+ def data_dir():
8
+ return pathlib.Path(__file__).with_name('data') / 'hxy'
9
+
10
+
11
+ def test_read(data_dir):
12
+ num_magnets = 2
13
+ magnets = femagtools.hxy.read(data_dir / 'PM270L8_011.hxy',
14
+ num_magnets)
15
+ assert len(magnets) == num_magnets
16
+ assert set([len(m['e'][0]) for m in magnets]) == {169, 189}
17
+ assert [m['pos'][0] for m in magnets] == [0.0, 0.0]
18
+ assert sorted([m['havg'][0] for m in magnets]) == pytest.approx([156.3, 156.5], 0.1)
19
+ assert sorted([m['hmax'][0] for m in magnets]) == pytest.approx([195.6, 304.4], 0.1)
tests/test_sizing.py CHANGED
@@ -15,7 +15,7 @@ def test_im():
15
15
  r = femagtools.machine.sizing.im(P, n, p, udc=udc,
16
16
  sigmas=fs, Ba=0.77,
17
17
  cos_phi=0.8, eta=0.8,
18
- lda=0.9)
18
+ lda=0.9, rtype='statorRotor3')
19
19
  assert round(r['outer_diam'], 3) == 0.19
20
20
  assert r['stator']['num_slots'] == 36
21
21
 
tests/test_vtu.py CHANGED
@@ -1,14 +1,19 @@
1
1
  import pytest
2
+ import pathlib
2
3
  from femagtools import vtu
3
4
 
4
5
 
5
6
  @pytest.fixture
6
- def vtu_data():
7
- filename = 'src/tests/data/zzz_pm_model_ts_results_1/zzz_pm_model_ts_0000.vtu'
8
- return vtu.read(filename)
7
+ def ts_data_dir():
8
+ return pathlib.Path(__file__).with_name('data') / 'zzz_pm_model_ts_results_1/'
9
+
10
+ @pytest.fixture
11
+ def demag_data_dir():
12
+ return pathlib.Path(__file__).with_name('data') / 'demag-vtu/'
9
13
 
10
14
 
11
- def test_read(vtu_data):
15
+ def test_read(ts_data_dir):
16
+ vtu_data = vtu.read(ts_data_dir / 'zzz_pm_model_ts_0000.vtu')
12
17
  assert vtu_data.field_data_names == [
13
18
  'time [s]', 'angle [rad]',
14
19
  'speed [rad/s]', 'torque [Nm]',
@@ -23,3 +28,15 @@ def test_read(vtu_data):
23
28
  assert b[0] == pytest.approx([-0.003114], abs=1e-5)
24
29
  assert b[1] == pytest.approx([-0.00313], abs=1e-5)
25
30
  assert b[2] == [0.0]
31
+
32
+ def test_demag(demag_data_dir):
33
+ vtu_data = vtu.read(demag_data_dir / 'PM_130_L10_0000.vtu')
34
+ keys = [7412, 7413, 7414, 7415, 7416]
35
+ class Element:
36
+ def __init__(self, key):
37
+ self.key = key
38
+ elements = [Element(k) for k in keys]
39
+ expected = [241.5, 250.2, 262.3, 276.5, 390.5]
40
+ actual = vtu_data.demag(elements)
41
+ assert len(actual) == 1
42
+ assert actual[0] == pytest.approx(expected, abs=0.1)