femagtools 1.6.7__py3-none-any.whl → 1.7.0__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.
Files changed (50) hide show
  1. femagtools/__init__.py +2 -2
  2. femagtools/bch.py +1 -1
  3. femagtools/dxfsl/area.py +334 -332
  4. femagtools/dxfsl/areabuilder.py +131 -10
  5. femagtools/dxfsl/conv.py +27 -9
  6. femagtools/dxfsl/converter.py +390 -125
  7. femagtools/dxfsl/corner.py +3 -0
  8. femagtools/dxfsl/femparser.py +1 -1
  9. femagtools/dxfsl/fslrenderer.py +290 -246
  10. femagtools/dxfsl/functions.py +4 -2
  11. femagtools/dxfsl/geom.py +1120 -886
  12. femagtools/dxfsl/journal.py +53 -22
  13. femagtools/dxfsl/machine.py +250 -74
  14. femagtools/dxfsl/plotrenderer.py +34 -3
  15. femagtools/dxfsl/shape.py +380 -103
  16. femagtools/dxfsl/symmetry.py +679 -110
  17. femagtools/femag.py +27 -2
  18. femagtools/forcedens.py +65 -40
  19. femagtools/fsl.py +71 -28
  20. femagtools/losscoeffs.py +46 -0
  21. femagtools/machine/effloss.py +8 -1
  22. femagtools/machine/im.py +3 -1
  23. femagtools/machine/pm.py +12 -11
  24. femagtools/machine/sizing.py +14 -11
  25. femagtools/machine/sm.py +114 -33
  26. femagtools/machine/utils.py +38 -34
  27. femagtools/model.py +12 -2
  28. femagtools/moo/population.py +1 -1
  29. femagtools/parstudy.py +17 -1
  30. femagtools/plot/__init__.py +1 -1
  31. femagtools/plot/char.py +24 -7
  32. femagtools/plot/forcedens.py +56 -29
  33. femagtools/plot/mcv.py +4 -1
  34. femagtools/plot/phasor.py +6 -1
  35. femagtools/poc.py +17 -10
  36. femagtools/templates/cogg_calc.mako +7 -1
  37. femagtools/templates/displ_stator_rotor.mako +33 -0
  38. femagtools/templates/fieldcalc.mako +10 -16
  39. femagtools/templates/pm_sym_f_cur.mako +1 -1
  40. femagtools/tks.py +3 -9
  41. {femagtools-1.6.7.dist-info → femagtools-1.7.0.dist-info}/LICENSE +1 -0
  42. {femagtools-1.6.7.dist-info → femagtools-1.7.0.dist-info}/METADATA +7 -4
  43. {femagtools-1.6.7.dist-info → femagtools-1.7.0.dist-info}/RECORD +50 -49
  44. tests/engines/__init__.py +0 -20
  45. tests/geom/__init__.py +0 -20
  46. tests/moo/__init__.py +0 -20
  47. tests/test_model.py +8 -1
  48. {femagtools-1.6.7.dist-info → femagtools-1.7.0.dist-info}/WHEEL +0 -0
  49. {femagtools-1.6.7.dist-info → femagtools-1.7.0.dist-info}/entry_points.txt +0 -0
  50. {femagtools-1.6.7.dist-info → femagtools-1.7.0.dist-info}/top_level.txt +0 -0
femagtools/plot/char.py CHANGED
@@ -3,15 +3,17 @@
3
3
  """
4
4
  import numpy as np
5
5
  import matplotlib.pyplot as plt
6
+ from ..machine.utils import iqd
6
7
  import logging
7
8
 
8
9
 
9
- def mtpa(pmrel, i1max, title='', projection='', ax=0):
10
+ def mtpa(pmrel, i1max, u1max=0, title='', projection='', ax=0):
10
11
  """create a line or surface plot with torque and mtpa curve
11
12
 
12
13
  Args:
13
14
  pmrel: pm machine object
14
15
  i1max: maximum phase current / A
16
+ u1max: maximum phase voltage / V (optional)
15
17
  title: plot title
16
18
  projection: projection to be used (surface if '3d')
17
19
  ax: axis to be used
@@ -46,19 +48,29 @@ def mtpa(pmrel, i1max, title='', projection='', ax=0):
46
48
 
47
49
  ax.set_aspect('equal')
48
50
  x, y = np.meshgrid(id, iq)
49
- CS = ax.contour(x, y, torque_iqd, 6, colors='k')
50
- ax.clabel(CS, fmt='%d', inline=1)
51
+ nlevels = 6
52
+ CST = ax.contour(x, y, torque_iqd, nlevels, colors='k')
53
+ ax.clabel(CST, fmt='%d Nm', inline=1)
54
+ if u1max > 0:
55
+ n_iqd = np.array([
56
+ [pmrel.w1_umax(u1max, iqx, idx)/np.pi/2/pmrel.p*60
57
+ for idx in id] for iqx in iq])
58
+ CSN = ax.contour(x, y, n_iqd, nlevels, colors='k',
59
+ linestyles='dotted') # linestyles='dashed')
60
+ ax.clabel(CSN, fmt='%d rpm', inline=1)
51
61
 
52
62
  ax.set_xlabel('Id/A')
53
63
  ax.set_ylabel('Iq/A')
54
64
  ax.plot(iopt[1], iopt[0],
55
- color='red', linewidth=2, label='MTPA: {0:5.0f} Nm'.format(
65
+ color='red', linewidth=2, label='MTPA: {0:.0f} Nm'.format(
56
66
  np.max(iopt[2][-1])))
67
+ iqx, idx = np.array([iqd(b, i1max) for b in np.linspace(-np.pi/2, 0)]).T
68
+ ax.plot(idx, iqx, color='blue', label='I1max: {0:.0f} A'.format(i1max))
57
69
  ax.grid()
58
70
 
59
71
  if title:
60
72
  ax.set_title(title)
61
- ax.legend()
73
+ ax.legend(loc='upper left', framealpha=1)
62
74
 
63
75
 
64
76
  def mtpv(pmrel, u1max, i1max, title='', projection='', ax=0):
@@ -176,7 +188,12 @@ def characteristics(char, title=''):
176
188
  axs[1, 0].set_xlabel("Speed / rpm")
177
189
  axs[1, 0].set_ylabel("Current / A")
178
190
  axs[1, 0].legend(loc='center left')
179
- if 'beta' in char:
191
+ if 'iex' in char:
192
+ ax3 = axs[1, 0].twinx()
193
+ ax3.plot(n, char['iex'], 'C3-', label='Iexc')
194
+ ax3.set_ylabel("Iexc / A")
195
+ ax3.legend(loc='center right')
196
+ elif 'beta' in char:
180
197
  ax3 = axs[1, 0].twinx()
181
198
  ax3.plot(n, char['beta'], 'C3-', label='Beta')
182
199
  ax3.set_ylabel("Beta / °")
@@ -337,7 +354,7 @@ def _plot_contour(speed, torque, z, ax, title='', levels=[],
337
354
  return contf, xscale, yscale
338
355
 
339
356
 
340
- def efficiency_map(rmap, ax=0, title='Efficiency Map', clabel=True,
357
+ def efficiency_map(rmap, ax=0, title='', clabel=True,
341
358
  cmap='YlOrRd', levels=None, cbar=False):
342
359
  if ax == 0:
343
360
  fig, ax = plt.subplots(figsize=(12, 12))
@@ -8,7 +8,7 @@
8
8
  """
9
9
  import numpy as np
10
10
  import matplotlib.pyplot as plt
11
- from matplotlib import cm
11
+ from matplotlib import colormaps
12
12
 
13
13
  def _create_3d_axis():
14
14
  """creates a subplot with 3d projection if one does not already exist"""
@@ -24,7 +24,7 @@ def _create_3d_axis():
24
24
  plt.subplot(111, projection='3d')
25
25
 
26
26
 
27
- def _plot_surface(ax, x, y, z, labels, azim=None):
27
+ def _plot_surface(ax, x, y, z, labels, azim=None, cmap=colormaps['viridis']):
28
28
  """helper function for surface plots"""
29
29
  # ax.tick_params(axis='both', which='major', pad=-3)
30
30
  assert np.size(x) > 1 and np.size(y) > 1 and np.size(z) > 1
@@ -34,7 +34,7 @@ def _plot_surface(ax, x, y, z, labels, azim=None):
34
34
  Z = np.ma.masked_invalid(z)
35
35
  ax.plot_surface(X, Y, Z,
36
36
  rstride=1, cstride=1,
37
- cmap=cm.viridis, alpha=0.85,
37
+ cmap=cmap,
38
38
  vmin=np.nanmin(z), vmax=np.nanmax(z),
39
39
  linewidth=0, antialiased=True)
40
40
  # edgecolor=(0, 0, 0, 0))
@@ -60,43 +60,70 @@ def forcedens(title, pos, fdens, ax=0):
60
60
  ax.set_ylabel('Force Density / kN/m²')
61
61
 
62
62
 
63
- def forcedens_surface(fdens, ax=0):
63
+ def forcedens_surface(fdens, attr='FN', ax=0, cmap=colormaps['jet']):
64
64
  if ax == 0:
65
65
  _create_3d_axis()
66
66
  ax = plt.gca()
67
- xpos = [p for p in fdens.positions[0]['X']]
68
- ypos = [p['position'] for p in fdens.positions]
69
- z = 1e-3*np.array([p['FN']
70
- for p in fdens.positions])
71
- _plot_surface(ax, xpos, ypos, z,
72
- ('Rotor pos/°', 'Pos/°', 'F N / kN/m²'))
73
-
74
-
75
- def forcedens_fft(title, fdens, nharm=40, ax=0):
67
+ z = 1e-3*np.array(getattr(fdens, attr))
68
+ n, m = z.shape
69
+ x = np.linspace(0, 360, m)
70
+ y = np.linspace(0, 360, n)
71
+ _plot_surface(ax, x, y, z,
72
+ ('Rotor pos/°', 'Pos/°', f'{attr} / kN/m²'),
73
+ cmap=cmap)
74
+
75
+ def forcedens_contour(fdens, attr='FN', ax=0, cmap=colormaps['jet']):
76
+ if ax == 0:
77
+ ax = plt.gca()
78
+ z = 1e-3*np.array(getattr(fdens, attr))
79
+ n, m = z.shape
80
+ x = np.linspace(0, 360, m)
81
+ y = np.linspace(0, 360, n)
82
+ cs = ax.contourf(x, y, z, cmap=cmap)
83
+ ax.set_xlabel('Rotor pos/°')
84
+ ax.set_ylabel('Pos/°')
85
+ if attr == 'FN':
86
+ ax.set_title('Radial Force Density')
87
+ elif attr == 'FT':
88
+ ax.set_title('Tangential Force Density')
89
+ cfig = ax.get_figure()
90
+ cbar = cfig.colorbar(cs, ax=ax)
91
+ cbar.ax.set_ylabel('kN/m²')
92
+
93
+ def forcedens_fft(title, fdens, harmmax=(), #(200, 40),
94
+ cmap=colormaps['YlOrBr'],
95
+ ax=0):
76
96
  """plot force densities FFT
77
97
  Args:
78
98
  title: plot title
79
99
  fdens: force density object
80
- nharm: (int) num harmonics
100
+ cmap: colormap
81
101
  """
82
102
  if ax == 0:
83
103
  ax = plt.axes(projection="3d")
84
104
 
85
- F = 1e-3*fdens.fft(nharm)['fn_harm']['amplitude']
86
- fmin = 0.2
87
- num_bars = F.shape[0] + 1
88
- _xx, _yy = np.meshgrid(np.arange(1, num_bars),
89
- np.arange(1, num_bars))
90
- z_size = F[F > fmin]
91
- x_pos, y_pos = _xx[F > fmin], _yy[F > fmin]
92
- z_pos = np.zeros_like(z_size)
93
- x_size = 2
94
- y_size = 2
95
-
96
- ax.bar3d(x_pos, y_pos, z_pos, x_size, y_size, z_size)
97
- #ax.view_init(azim=120)
98
- ax.set_xlim(0, num_bars+1)
99
- ax.set_ylim(0, num_bars+1)
105
+ FN = 1e-3*fdens.fft()['fn_harm']['amplitude']
106
+ if harmmax:
107
+ shape = np.min((harmmax, np.shape(FN)), axis=0)
108
+ else:
109
+ shape = np.shape(FN)
110
+
111
+ _x = np.arange(shape[0])+1
112
+ _y = np.arange(shape[1])+1
113
+ _xx, _yy = np.meshgrid(_x, _y)
114
+ x, y = _xx.ravel(), _yy.ravel()
115
+ top = np.ravel(FN[:shape[0],:shape[1]])
116
+ bottom = np.zeros_like(top)
117
+ maxy = max(x[-1], y[-1])
118
+ width, depth = 5*x[-1]/maxy, 5*y[-1]/maxy
119
+
120
+ min_height = np.min(top)
121
+ max_height = np.max(top)
122
+ rgba = [cmap((k-min_height)/max_height) for k in top]
123
+ ax.bar3d(x, y, bottom, width, depth, top, color=rgba)
124
+
125
+ ax.set_xlim(0, shape[0]+1)
126
+ ax.set_ylim(0, shape[1]+1)
100
127
  ax.set_title(title)
101
128
  ax.set_xlabel('M')
102
129
  ax.set_ylabel('N')
femagtools/plot/mcv.py CHANGED
@@ -70,7 +70,8 @@ def felosses(losses, coeffs, title='', log=True, ax=0):
70
70
  Args:
71
71
  losses: dict with f, B, pfe values
72
72
  coeffs: list with steinmetz (cw, alpha, beta) or
73
- jordan (cw, alpha, ch, beta, gamma) coeffs
73
+ jordan (cw, alpha, ch, beta, gamma) or
74
+ bertotti (cw, alpha, cw, ce) coeffs
74
75
  title: title string
75
76
  log: log scale for x and y axes if True
76
77
 
@@ -89,6 +90,8 @@ def felosses(losses, coeffs, title='', log=True, ax=0):
89
90
  if f > 0:
90
91
  if len(coeffs) == 5:
91
92
  ax.plot(B, lc.pfe_jordan(f, B, *coeffs, fo=fo, Bo=Bo))
93
+ if len(coeffs) == 4:
94
+ ax.plot(B, lc.pfe_bertotti(f, B, *coeffs))
92
95
  elif len(coeffs) == 3:
93
96
  ax.plot(B, lc.pfe_steinmetz(f, B, *coeffs, fo=fo, Bo=Bo))
94
97
  ax.plot(losses['B'][:len(pfe)], pfe,
femagtools/plot/phasor.py CHANGED
@@ -141,6 +141,11 @@ def phasor(bch, ax=0):
141
141
  xd = w1*bch.dqPar['ld'][-1]
142
142
  xq = w1*bch.dqPar['lq'][-1]
143
143
  r1 = bch.machine['r1']
144
- i1beta_phasor(bch.dqPar['up'][-1],
144
+ if np.isscalar(bch.dqPar['up']):
145
+ up = bch.dqPar['up']
146
+ else:
147
+ up = bch.dqPar['up'][-1]
148
+
149
+ i1beta_phasor(up,
145
150
  bch.dqPar['i1'][-1], bch.dqPar['beta'][-1],
146
151
  r1, xd, xq, ax)
femagtools/poc.py CHANGED
@@ -11,11 +11,12 @@
11
11
 
12
12
 
13
13
  class Poc:
14
- def __init__(self, arg, parameters=dict()):
14
+ def __init__(self, arg=999, parameters={}, current_angles=[]):
15
15
  """initialize this object from a set of parameters or a file
16
16
 
17
17
  Args:
18
- arg filename or pole_pitch
18
+ arg: filename or pole_pitch
19
+ current_angles: list of current angles
19
20
  """
20
21
  self.skew_angle = 0.0
21
22
  self.num_skew_steps = 0
@@ -33,15 +34,21 @@ class Poc:
33
34
  [str(i+1) for i in range(3)])
34
35
  b = parameters.get('offset', 0)
35
36
  num_winding = len(self.key_winding)
36
- self.phi_voltage_winding = parameters.get('phi_voltage_winding',
37
- [b+i*360/num_winding
38
- for i in range(num_winding)])
37
+ if current_angles:
38
+ self.phi_voltage_winding = current_angles
39
+ else:
40
+ self.phi_voltage_winding = parameters.get('phi_voltage_winding',
41
+ [b+i*360/num_winding
42
+ for i in range(num_winding)])
39
43
 
40
44
  def __setattr__(self, name, val):
41
45
  self.__dict__[name] = val # this will create the attribute name
42
46
 
43
- def filename(self):
44
- prefix = self.pocType
47
+ def filename(self, modelName=''):
48
+ if modelName:
49
+ prefix = modelName
50
+ else:
51
+ prefix = self.pocType
45
52
  if prefix == 'Function':
46
53
  prefix = self.shape_current
47
54
  return '{}_{}p.poc'.format(
@@ -125,7 +132,7 @@ class Poc:
125
132
  else:
126
133
  self.shape_current=self.pocType
127
134
  self.pocType='Function'
128
-
135
+
129
136
  try:
130
137
  self.skew_angle=float(pocfile.readline())
131
138
  self.num_skew_steps=int(pocfile.readline())
@@ -155,7 +162,7 @@ class HspPoc(Poc):
155
162
  pocType='hsp', harmonic_id=harm,
156
163
  func_current=amp, func_phi=phi))
157
164
 
158
-
165
+
159
166
  def curr_har(x, n, A, phi ):
160
167
  "return fourier sum"
161
168
  import numpy as np
@@ -169,7 +176,7 @@ def curr_fun(phi, A, phi_wdg ):
169
176
  "return curr"
170
177
  import numpy as np
171
178
  if np.asarray(A).shape == 1:
172
- return [[np.asarray(phi)+x, A] for x in phi_wdg]
179
+ return [[np.asarray(phi)+x, A] for x in phi_wdg]
173
180
  return [phi, A]
174
181
 
175
182
 
@@ -18,7 +18,6 @@ m.line = 0
18
18
  m.two_pole_wi = 2*m.pole_width
19
19
  m.range_x = m.two_pole_wi
20
20
  m.range_y = 0.0
21
-
22
21
  m.fc_force_points = 5
23
22
  m.fcpx_mm1 = m.npols_gen*m.pole_width +1.0
24
23
  m.fcpy_mm1 = -ag/2
@@ -39,7 +38,14 @@ m.fcpy_mm5 = m.fcpy_mm1
39
38
  % endif
40
39
 
41
40
  m.nu_skew_steps = ${model.get('num_skew_steps', 0)}
41
+ % if model.get('noload_ex_cur', 0):
42
+ m.nloa_ex_cur = ${model.get('noload_ex_cur',0)}
43
+ % endif
44
+ % if model.get("noload_ex_cur", 0):
45
+ m.magn_temp = 20 -- dummy parameter
46
+ % else:
42
47
  m.magn_temp = ${model.get('magn_temp')}
48
+ % endif
43
49
  m.fc_mult_move_type = 1.0 -- Type of move path in air gap
44
50
  m.nu_move_steps = ${model.get('num_move_steps', 49)}
45
51
 
@@ -0,0 +1,33 @@
1
+ -- calculate static or dynamic eccentricity
2
+ -- NOTE: requires full model
3
+ --
4
+ static = 0
5
+ dynamic = 1
6
+ m.disp_info = ${model.get('type', 'static')} -- Displace: Stator: 0, Rotor: 1
7
+
8
+ da1 = ${model.get('bore_diam',0)*1e3}
9
+ ag = ${model.get('airgap',0)*1e3}
10
+
11
+ if m.b_min == 0 then -- move inside: outer stator
12
+ if m.disp_info == static then
13
+ m.fc_radius = da1/2 - ag/6
14
+ else
15
+ m.fc_radius = da1/2 - 5*ag/6
16
+ end
17
+ else
18
+ if m.disp_info == static then
19
+ m.fc_radius = da1/2 + ag/6
20
+ else
21
+ m.fc_radius = da1/2 + 5*ag/6
22
+ end
23
+ end
24
+ m.disp_radius = ${model.get('ecc', 0)*1e3} -- Displacement: r [mm]
25
+ m.disp_phi = 0.0 -- Displacement: phi [Degr]
26
+
27
+ pre_models("Displ_Stat/Rot")
28
+ -- must correct fc_radius
29
+ if m.b_min == 0 then -- move inside: outer stator
30
+ m.fc_radius = da1/2 - ag/2
31
+ else
32
+ m.fc_radius = da1/2 + ag/2
33
+ end
@@ -6,29 +6,23 @@ du_u0=1e-3
6
6
 
7
7
  get_wdg_keys("wkeys")
8
8
 
9
- -- check the machine type PSM/ESM
10
- magn = get_dev_data("magn_remanence")
11
-
12
- if magn > 0 then -- IPM
13
- -- set cur to zero
14
- for i = 1, #wkeys do
15
- def_curr_wdg(wkeys[i],0, 0)
16
- end
17
- else -- ESM
18
- for i = 1, #wkeys - 1 do
19
- def_curr_wdg(wkeys[i],0, 0)
20
- end
9
+ -- set cur to zero
10
+ for i = 1, #wkeys do
11
+ def_curr_wdg(wkeys[i],0, 0)
21
12
  end
22
-
13
+ % if model.get('noload_ex_cur', 0):
14
+ def_curr_wdg(wkeys[#wkeys], ${model['noload_ex_cur']}, 0)
15
+ % endif
16
+
23
17
  calc_field_single(maxit, reset, du_u0)
24
18
 
25
- post_models("induct(x)","b") -- Calculate field distribution
19
+ post_models("induct(x)","b_airgap") -- Calculate field distribution
26
20
 
27
21
  data=io.open("bag.dat","w") -- Output in data file
28
- N = table.getn(b) -- Number of elements in array
22
+ N = table.getn(b_airgap) -- Number of elements in array
29
23
  i = 1
30
24
  repeat
31
- data:write(string.format("%g %g %g\n",b[i],b[i+1],b[i+2]))
25
+ data:write(string.format("%g %g %g\n",b_airgap[i],b_airgap[i+1],b_airgap[i+2]))
32
26
  i = i+3
33
27
  until i>=N
34
28
  io.close(data)
@@ -1,7 +1,7 @@
1
1
  --
2
2
  -- SM Simulation with excitation current
3
3
  --
4
- m.wdcon = ${model.get('wdgcon', 1)} -- Connection: 0=open, 1=star, 2=delta
4
+ m.wdcon = ${model.get('wdgcon', 0)} -- Connection: 0=open, 1=star, 2=delta
5
5
  m.move_action = ${model.get('move_action', 0)}
6
6
  m.speed = ${model.get('speed')*60}
7
7
  m.skew_angle = ${model.get('skew_angle',0)}
femagtools/tks.py CHANGED
@@ -56,7 +56,6 @@ class Reader(object):
56
56
  self.rho = 7.6
57
57
  self.losses = dict(f=[], B=[])
58
58
  pfe = []
59
- b_pfe = []
60
59
 
61
60
  # filecontent is used
62
61
  if filecontent:
@@ -92,7 +91,6 @@ class Reader(object):
92
91
  b, p = readlist(content[i+1:])
93
92
  self.losses['f'].append(fxref)
94
93
  self.losses['B'].append(b)
95
- b_pfe.append(b)
96
94
  pfe.append(p)
97
95
  logger.info("%s Bmax %3.2f", filename, max(self.curve[0]['bi']))
98
96
 
@@ -126,19 +124,15 @@ class Reader(object):
126
124
 
127
125
  self.losses['Bo'] = self.Bo
128
126
  self.losses['fo'] = self.fo
129
-
130
- z = lc.fit_bertotti0(self.losses['f'], b_pfe, pfe)
131
- if z.shape[0] == 4:
132
- self.bertotti = {'ch': z[0], 'alpha': z[1], 'cw': z[2], 'ce': z[3]}
133
- else:
134
- self.bertotti = {'ch': z[0], 'alpha': 2.0, 'cw': z[1], 'ce': z[2]}
127
+ z = lc.fit_bertotti(self.losses['f'],
128
+ self.losses['B'], pfe)
129
+ self.bertotti = {'ch': z[0], 'alpha': 2.0, 'cw': z[1], 'ce': z[2]}
135
130
  logger.info("Bertotti loss coeffs %s", z)
136
131
 
137
132
  # must normalize pfe matrix:
138
133
  (self.losses['B'],
139
134
  self.losses['pfe']) = femagtools.mcv.norm_pfe(
140
135
  self.losses['B'], pfe)
141
- self.b_pfe = b_pfe
142
136
  self.pfe = pfe
143
137
 
144
138
 
@@ -1,4 +1,5 @@
1
1
  Copyright (c) 2016-2023, Semafor Informatik & Energie AG, Basel
2
+ Copyright (c) 2023-2024, Gamma Technology LLC
2
3
  All rights reserved.
3
4
 
4
5
  Redistribution and use in source and binary forms, with or without
@@ -1,9 +1,10 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: femagtools
3
- Version: 1.6.7
3
+ Version: 1.7.0
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
7
+ Copyright (c) 2023-2024, Gamma Technology LLC
7
8
  All rights reserved.
8
9
 
9
10
  Redistribution and use in source and binary forms, with or without
@@ -42,6 +43,8 @@ Requires-Dist: mako
42
43
  Requires-Dist: six
43
44
  Requires-Dist: lmfit
44
45
  Requires-Dist: netCDF4 >=1.6.5
46
+ Provides-Extra: all
47
+ Requires-Dist: femagtools[dxfsl,meshio,mplot,svgfsl,test,vtk,zmq] ; extra == 'all'
45
48
  Provides-Extra: dxfsl
46
49
  Requires-Dist: dxfgrabber ; extra == 'dxfsl'
47
50
  Requires-Dist: networkx ; extra == 'dxfsl'
@@ -81,14 +84,14 @@ Femagtools is an Open-Source Python-API for FEMAG offering following features:
81
84
  * calculate machine characteristics by using analytic machine models
82
85
  * execute parameter studies and multi-objective optimization
83
86
 
84
- The package can be used with Python 3.x on Linux, MacOS or Windows and is hosted on github: <https://github.com/SEMAFORInformatik/femagtools/>` where also many examples can be found in the examples directory. Contributions and feedback to this project are highly welcome.
87
+ The package can be used with Python 3.x on Linux, MacOS or Windows and is hosted on github: <https://github.com/SEMAFORInformatik/femagtools/> where also many examples can be found in the examples directory. Contributions and feedback to this project are highly welcome.
85
88
 
86
89
  The installation can be done in the usual ways with pip:
87
90
 
88
91
  ```
89
- pip install femagtools[all]
92
+ pip install 'femagtools[all]'
90
93
  ```
91
- ([all] pulls in all optional dependencies.
94
+ `[all]` pulls in all optional dependencies. Up-to-date information about optional dependencies can be found in the [pyproject.toml](pyproject.toml) file under `[project.optional-dependencies]`.
92
95
 
93
96
  For details see the documentation <http://docs.semafor.ch/femagtools>
94
97