Source code for pyleecan.Methods.Machine.Winding.comp_connection_mat
from numpy import zeros, swapaxes, sign
from ....Methods.Machine.Winding import WindingError
from swat_em import datamodel
[docs]def comp_connection_mat(self, Zs=None, p=None):
"""Compute the Winding Matrix for
Parameters
----------
self : Winding
A: Winding object
Zs : int
Number of Slot (Integer >0)
p : int
Number of pole pairs (Integer >0)
Returns
-------
wind_mat: numpy.ndarray
Winding Matrix (1, 1, Zs, qs)
Raises
------
WindingT2DefNtError
Zs/qs/2 must be an integer
"""
if Zs is None:
if not hasattr(self.parent, "slot") and not hasattr(self.parent, "slot_list"):
raise WindingError("The Winding object must be in a Lamination object.")
Zs = self.parent.get_Zs()
if p is None:
if self.parent is None:
raise WindingError("The Winding object must be in a Lamination object.")
p = self.parent.get_pole_pair_number()
assert Zs > 0, "Zs must be >0"
assert Zs % 1 == 0, "Zs must be an integer"
assert p > 0, "p must be >0"
assert p % 1 == 0, "p must be an integer"
qs = self.qs # Phase Number
Ntcoil = self.Ntcoil # number of turns per coils
Nlayer = self.Nlayer # number of layers
# Coil pitch (or coil span)
if self.coil_pitch in [0, None]:
# Number of slots per pole and per phase
spp = Zs / (2 * p * qs)
if spp > 0.5:
# distributed winding
self.coil_pitch = int(qs * spp)
else:
# tooth concentrated winding
self.coil_pitch = 1
# generate a datamodel for the winding
wdg = datamodel()
# generate winding from inputs
wdg.genwdg(Q=Zs, P=2 * p, m=qs, layers=Nlayer, turns=Ntcoil, w=self.coil_pitch)
# init connexion matrix
wind_mat = zeros((Nlayer, 1, Zs, qs))
# get connexion matrix from swat-em
wind_mat_swat = wdg.get_phases()
# perform checks
assert p == wdg.get_num_polepairs(), (
"number of pole pairs is not as requested (returned "
+ str(wdg.get_num_polepairs())
+ " expected "
+ str(p)
+ ")"
)
assert qs == wdg.get_num_phases(), (
"number of phases is not as requested (returned "
+ str(wdg.get_num_phases())
+ " expected "
+ str(qs)
+ ")"
)
# convert swat-em connexion matrix to pyleecan connexion matrix
for qq, phase in enumerate(wind_mat_swat):
for ll, layer in enumerate(phase):
if len(layer) > 0:
for cond in layer:
wind_mat[Nlayer - ll - 1, 0, abs(cond) - 1, qq] = (
sign(cond) * Ntcoil
)
# permute radial and tangential layers if coil span is 1
if wdg.get_coilspan() == 1:
wind_mat = swapaxes(wind_mat, 0, 1)
# check that requested number of parallel connections is feasible
Npcp_list = wdg.get_parallel_connections()
if self.Npcp is None:
self.Npcp = Npcp_list[0]
elif self.Npcp > 2 * p:
# self.Npcp = 2 * p
self.get_logger().warning(
"Number of parallel circuits per phase should be < 2*p, current value is: "
+ str(self.Npcp)
)
# if self.Npcp not in Npcp_list:
# if self.Npcp is not None:
# self.get_logger().warning(
# "Requested number of parallel circuits per phase is not feasible, assign it to: "
# + str(Npcp_list[0])
# )
# self.Npcp = Npcp_list[0]
# enforce the number of layers if it is not as requested
Nlayer_actual = wdg.get_num_layers()
if self.Nlayer != Nlayer_actual:
self.Nlayer = Nlayer_actual
self.get_logger().info(
"Requested number of layers is not feasible, assign it to: "
+ str(Nlayer_actual)
)
# get periodicities
# self.per_a = wdg.get_periodicity_t()
# self.is_aper_a = wdg.get_is_symmetric()
# To check periodicities swat-em / pyleecan definitions
self.per_a, self.is_aper_a = self.comp_periodicity(wind_mat=wind_mat)
# if is_aper_a: # Different def for Anti per
# per_a = per_a / 2
# if self.per_a != per_a or self.is_aper_a != is_aper_a:
# self.get_logger().warning(
# "(Anti-)periodicity calculated by pyleecan and SWAT_EM differs"
# )
# Set default values
if self.is_reverse_wind is None:
self.is_reverse_wind = False
if self.Nslot_shift_wind is None:
self.Nslot_shift_wind = 0
return wind_mat