6. SPM Rotor Structural Analyzer

This analyzer determines the stress in a surface-mounted permanent magnet (SPM) rotor with a retaining sleeve.

6.1. Model Background

The analyzer models the SPM rotor as a series of concentric cylinders, shown in the figure below. The rotor is assumed to have four regions of varying material: a shaft, rotor back iron, magnets, and a sleeve. The sleeve is designed with an undersized fit in order to provide the compressive force on the rotor. In addition to the compressive force from the sleeve, loading due to thermal expansion is also considered.

Trial1
Trial1

All materials except for the sleeve are assumed to be isotropic. The sleeve is modeled as anisotropic, which allows consideration of high performance materials such as carbon fiber. The analyzer implements the rotor model developed in this paper:

  • M Johnson, K. Hanson and E. L. Severson, “Normalized Analytical Model of Stresses in a Surface Mounted Permanent Magnet Rotor,” 2021 IEEE Energy Conversion Congress and Exposition (ECCE), 2021, pp. 3928-3935.

6.2. Inputs from User

The structural analyzer problem requires a material dictionary (mat_dict) and dimensions of the shaft, rotor core, magnet, and sleeve as defined in the diagrams above. The structural analyzer problem also takes in deltaT which represents the rotor temperature rise to account for thermal expansion. The deltaT values should be thought of as the temperature rise from rest, so if when the rotor is not in use it rests at 20C, then the temperature rise would be relative to that temperature.

mat_dict input to SPM structural problem

Variable/key_value name

Description

Units

shaft_material_density

Shaft material density

kg/m3

shaft_youngs_modulus

Shaft youngs modulus

Pa

shaft_poission_ratio

Shaft poission ratio

alpha_sh

Shaft temperature coefficient

1/K

core_material_density

Rotor core material density

kg/m3

core_youngs_modulus

Rotor core youngs modulus

Pa

core_poission_ratio

Rotor core poission ratio

alpha_rc

Rotor core temperature coefficient

1/K

magnet_material_density

Magnet material density

kg/m3

magnet_youngs_modulus

Magnet youngs modulus

Pa

magnet_poission_ratio

Magnet poission ratio

alpha_pm

Magnet temperature coefficient

1/K

sleeve_material_density

Sleeve material density

kg/m3

sleeve_youngs_th_direction

Sleeve youngs thread direction

Pa

sleeve_youngs_p_direction

Sleeve youngs plane direction

Pa

sleeve_poission_ratio_p

Sleeve poission ratio plane

sleeve_poission_ratio_tp

Sleeve poission ratio thread x plane

alpha_sl_t

Temperature coefficient (Thread)

1/K

alpha_sl_r

Temperature coefficient (plane)

1/K

sleeve_max_rad_stress

Maximum radial stress of sleeve

Pa

sleeve_max_tan_stress

Maximum tangential stress of sleeve

Pa

Additional inputs for SPM structural problem

Variable/key_value name

Description

Units

r_sh

Shaft radius

m

d_m

Magnet thickness

m

d_sl

Sleeve thickness

m

delta_sl

Sleeve undersize

m

r_ro

Rotor outer radius

m

deltaT

Rotor temperature rise

K

N

Rotor speed

RPM

The following code demonstrates how to initialize the SPM_RotorStructuralProblem and SPM_RotorStructuralAnalyzer. The values used by the mat_dict are representative of typical values used by this analyzer assuming 1045 carbon steel for the shaft, M19 29-gauge laminated steel for the rotor core, N40 neodymium magnets, and carbon fiber for the sleeve.

import numpy as np
from matplotlib import pyplot as plt
import eMach.mach_eval.analyzers.mechanical.rotor_structural as sta
######################################################
# Creating the required Material Dictionary
######################################################
mat_dict = {
    'core_material_density': 7650,  # kg/m3
    'core_youngs_modulus': 185E9,  # Pa
    'core_poission_ratio': .3,
    'alpha_rc' : 1.2E-5,

    'magnet_material_density'    : 7450, # kg/m3
    'magnet_youngs_modulus'      : 160E9, # Pa
    'magnet_poission_ratio'      :.24,
    'alpha_pm'                   :5E-6,

    'sleeve_material_density'    : 1800, # kg/m3
    'sleeve_youngs_th_direction' : 125E9,  #Pa
    'sleeve_youngs_p_direction'  : 8.8E9,  #Pa
    'sleeve_poission_ratio_p'    :.015,
    'sleeve_poission_ratio_tp'   :.28,
    'alpha_sl_t'                :-4.7E-7,
    'alpha_sl_r'                :0.3E-6,

    'sleeve_max_tan_stress': 1950E6,  # Pa
    'sleeve_max_rad_stress': -100E6,  # Pa

    'shaft_material_density': 7870,  # kg/m3
    'shaft_youngs_modulus': 206E9,  # Pa
    'shaft_poission_ratio': .3,  # []
    'alpha_sh' : 1.2E-5
}
######################################################
#Setting the machine geometry and operating conditions
######################################################
r_sh = 5E-3 # [m]
d_m = 2E-3 # [m]
r_ro = 12.5E-3 # [m]
deltaT = 0 # [K]
N = 100E3 # [RPM]
d_sl=1E-3 # [m]
delta_sl=-2.4E-5 # [m]

######################################################
#Creating problem and analyzer class
######################################################
problem = sta.SPM_RotorStructuralProblem(r_sh, d_m, r_ro, d_sl, delta_sl, deltaT, N,mat_dict)
analyzer=sta.SPM_RotorStructuralAnalyzer()

6.2.1. Example with No Rotor Sleeve

To analyze a rotor with no sleeve, simple set d_sl, delta_sl, and deltaT to zero when creating the problem as shown in the following code:

######################################################
#Setting the machine geometry and operating conditions
######################################################
r_sh = 5E-3 # [m]
d_m = 2E-3 # [m]
r_ro = 12.5E-3 # [m]
deltaT = 0 # [K]
N = 50E3 # [RPM]
d_sl=0 # [m]
delta_sl=0 # [m]

######################################################
#Creating problem and analyzer class
######################################################
problem = sta.SPM_RotorStructuralProblem(r_sh, d_m, r_ro, d_sl, delta_sl, deltaT, N,mat_dict)
analyzer=sta.SPM_RotorStructuralAnalyzer()

6.3. Outputs to User

The SPM structural analyzer returns a list of sigma objects (referred to as sigmas). Each sigma object contains the analytic solution for radial and tangential stress in a single rotor components, as follows:

  • sigmas[0]: Shaft

  • sigmas[1]: Rotor Core

  • sigmas[2]: Magnets

  • sigmas[3]: Sleeve

The user can obtain the stress (in units of Pa) at any radius in a rotor component using the sigma.radial() and sigma.tangential() methods. For example, sigmas[2].radial(r_ro) would return the radial stress at the outer edge of the magnets (radius of r_ro in units of m), and sigmas[2].tangential(r_ro) would return the tangential stress. If the user attempts to pass a radius which is outside of the range of the rotor component, then the sigma object will raise a ValueError. Note that the sigma objects determine the stress by solving equation (4) in the supporting paper.

Example code to calculate the stress distribution in the rotor:

######################################################
#Analyzing Problem
######################################################
sigmas=analyzer.analyze(problem)

######################################################
#Creating vectors of radius used for plotting
######################################################
r_vect_sh=np.linspace(r_sh/10000,r_sh,100)
r_vect_rc=np.linspace(r_sh,r_ro-d_m,100)
r_vect_pm=np.linspace(r_ro-d_m,r_ro,100)
r_vect_sl=np.linspace(r_ro,r_ro+d_sl,100)

######################################################
#Plotting Stress distribution in rotor
######################################################
fig,ax=plt.subplots(2,1)
ax[0].plot(r_vect_sh,sigmas[0].radial(r_vect_sh))
ax[0].plot(r_vect_rc,sigmas[1].radial(r_vect_rc))
ax[0].plot(r_vect_pm,sigmas[2].radial(r_vect_pm))
ax[0].plot(r_vect_sl,sigmas[3].radial(r_vect_sl))
ax[0].set_xticks([])
ax[0].set_ylabel('Radial Stress [Pa]')
ax[1].plot(r_vect_sh,sigmas[0].tangential(r_vect_sh))
ax[1].plot(r_vect_rc,sigmas[1].tangential(r_vect_rc))
ax[1].plot(r_vect_pm,sigmas[2].tangential(r_vect_pm))
ax[1].plot(r_vect_sl,sigmas[3].tangential(r_vect_sl))
ax[1].set_ylabel('Tangential Stress [Pa]')
ax[1].set_xlabel('Radial Position [m]')
Trial1

6.3.1. Example with No Rotor Sleeve

The following code will calculate the stress distribution for a rotor which is not utilizing a rotor sleeve:

######################################################
#Analyzing Problem
######################################################
sigmas=analyzer.analyze(problem)

######################################################
#Creating vectors of radius used for plotting
######################################################
r_vect_sh=np.linspace(r_sh/10000,r_sh,100)
r_vect_rc=np.linspace(r_sh,r_ro-d_m,100)
r_vect_pm=np.linspace(r_ro-d_m,r_ro,100)
r_vect_sl=np.linspace(r_ro,r_ro+d_sl,100)

######################################################
#Plotting Stress distribution in rotor
######################################################
fig,ax=plt.subplots(2,1)
ax[0].plot(r_vect_sh,sigmas[0].radial(r_vect_sh))
ax[0].plot(r_vect_rc,sigmas[1].radial(r_vect_rc))
ax[0].plot(r_vect_pm,sigmas[2].radial(r_vect_pm))
ax[0].set_xticks([])
ax[0].set_ylabel('Radial Stress [Pa]')
ax[1].plot(r_vect_sh,sigmas[0].tangential(r_vect_sh))
ax[1].plot(r_vect_rc,sigmas[1].tangential(r_vect_rc))
ax[1].plot(r_vect_pm,sigmas[2].tangential(r_vect_pm))
ax[1].set_ylabel('Tangential Stress [Pa]')
ax[1].set_xlabel('Radial Position [m]')
Trial1