Source code for pyleecan.Methods.Machine.Winding.comp_periodicity

```from numpy import squeeze, abs as np_abs, mod, where, all as np_all, gcd
from numpy.fft import fft

[docs]def comp_periodicity(self, wind_mat=None):
"""Computes the winding matrix (anti-)periodicity

Parameters
----------
self : Winding
A Winding object
wind_mat : ndarray
Winding connection matrix

Returns
-------
per_a: int
Number of spatial periods of the winding
is_aper_a: bool
True if the winding is anti-periodic over space

"""

if wind_mat is None:
wind_mat = self.get_connection_mat()

assert wind_mat.ndim == 4, "dim 4 expected for wind_mat"

Zs = wind_mat.shape[2]  # Number of Slot
qs = wind_mat.shape[3]  # Number of phase

# Summing on all the layers (Nlay_r and Nlay_theta)
wind_mat2 = wind_mat
# Avoid to squeeze qs=1 (WRSM)
if wind_mat.shape[1] == 1:
wind_mat2 = squeeze(wind_mat2, 1)
if wind_mat.shape[0] == 1:
wind_mat2 = squeeze(wind_mat2, 0)

if wind_mat2.ndim == 4:  # rad and tan > 2
Nlay = wind_mat2.shape[0] * wind_mat2.shape[1]
wind_mat2 = wind_mat2.reshape((Nlay, Zs, qs))
elif wind_mat2.ndim == 2:
Nlay = 1
wind_mat2 = wind_mat2[None, :, :]
else:
Nlay = wind_mat2.shape[0]

Nperw = Zs  # Number of electrical period of the winding
is_aper = True  # True if winding pattern is anti-periodic

# Looking for the periodicity of each phase
for q in range(qs):
# Looking for the periodicity of each layer
for l in range(Nlay):
# FFT of connectivity array for the given layer and phase
wind_mat_ql_fft = fft(wind_mat2[l, :, q])
# Find indices of nonzero amplitudes
I0 = where(np_abs(wind_mat_ql_fft) > 1e-3)[0]
if len(I0) == 0:  # This phase is not present in this layer
pass  # No impact on symmetry
else:
# Periodicity is given by the non zero lowest order
Nperw_ql = I0[0] if I0[0] != 0 else I0[1]
Nperw = gcd(Nperw, Nperw_ql)
if I0[0] == 0:
# Anti-periodicity is necessary false if there is a constant component
is_aper = False
else:
# Anti-periodicity is true if all non-zero components are odd multiple of periodicity
is_aper = is_aper and np_all(mod(I0 / Nperw_ql, 2) == 1)

if Nperw == 1 and not is_aper:
# No need to further continue if there is no anti-periodicity
break

# Multiply periodicity number by two in case of anti-periodicity
Nperw = Nperw * 2 if is_aper else Nperw

return int(Nperw), bool(is_aper)
```