Download LM example

Assumptions

This case study simulates the back electromotive force (bEMF) in a linear electromagnetic machine using Nabla's transient 2D solver. The simulation assumes a 2D planar geometry representing a cross-section of the linear machine. The machine consists of a moving permanent magnet assembly and a stationary conductive coil assembly.

Geometry

The sketch of the geometry used in this case study is shown below:

Geometry of Linear Machine

Simulation

The simulation was performed using Python API script to define the model, mesh, materials, boundary conditions, and solver settings.

Python Script


import matplotlib.pyplot as plt
from nabla_api import Nabla

model = Nabla("Linear_Machine")

model.start()

model.createNewModel("Linear_Machine")

# Create model geometry
model.line(-50.0, 0.0, 50.0, 0.0)
model.line(50.0, 0.0, 50.0, 50.0)
model.line(50.0, 50.0, -50.0, 50.0)
model.line(-50.0, 50.0, -50.0, 0.0)

model.line(-75.0, -27.0, -65.0, -27.0)
model.line(-65.0, -27.0, -65.0, -2.0)
model.line(-65.0, -2.0, -75.0, -2.0)
model.line(-75.0, -2.0, -75.0, -27.0)

model.line(-35.0, -27.0, -15.0, -27.0)
model.line(-15.0, -27.0, -15.0, -2.0)
model.line(-15.0, -2.0, -35.0, -2.0)
model.line(-35.0, -2.0, -35.0, -27.0)

model.line(15.0, -27.0, 35.0, -27.0)
model.line(35.0, -27.0, 35.0, -2.0)
model.line(35.0, -2.0, 15.0, -2.0)
model.line(15.0, -2.0, 15.0, -27.0)

model.line(65.0, -27.0, 75.0, -27.0)
model.line(75.0, -27.0, 75.0, -2.0)
model.line(75.0, -2.0, 65.0, -2.0)
model.line(65.0, -2.0, 65.0, -27.0)

model.line(-65.0, -2.0, -35.0, -2.0)
model.line(-15.0, -2.0, 15.0, -2.0)
model.line(35.0, -2.0, 65.0, -2.0)

model.line(75.0, -27.0, 75.0, -52.0)
model.line(75.0, -52.0, -75.0, -52.0)
model.line(-75.0, -52.0, -75.0, -27.0)

model.line(75.0, -2.0, 75.0, -1.5)
model.line(75.0, -1.5, -75.0, -1.5)
model.line(-75.0, -1.5, -75.0, -2.0)

model.line(75.0, -1.0, 75.0, 50.0)
model.line(75.0, 50.0, 75.0, 74.0)
model.line(75.0, 74.0, -75.0, 74.0)
model.line(-75.0, 74.0, -75.0, 50.0)
model.line(-75.0, 50.0, -75.0, -1.0)

model.line(-75.0, 50.0, -50.0, 50.0)
model.line(75.0, 50.0, 50.0, 50.0)

model.line(75.0, -1.0, -75.0, -1.0)

model.line(75.0, 74.0, 75.0, 84.0)
model.line(75.0, 84.0, -75.0, 84.0)
model.line(-75.0, 84.0, -75.0, 74.0)

model.line(75.0, -52.0, 75.0, -62.0)
model.line(75.0, -62.0, -75.0, -62.0)
model.line(-75.0, -62.0, -75.0, -52.0)

# Define regions and assign properties

mesh_size_1 = 5
mesh_size_2 = 10.0
mesh_size_3 = 6.0

model.createRegion(0.0, 60.0, mesh_size_1, "Rotor_Core")
model.setRegionMaterial("Rotor_Core", "M-36_steel")
model.createRegion(0.0, 25.0, mesh_size_1, "PM")
model.assignRegionProperties("PM", "M", 750.0)
model.assignRegionProperties("PM", "DOM", 90.0)
model.createRegion(0.0, -57.0, mesh_size_2, "Air_Stator")
model.assignRegionProperties("Air_Stator", "mu", 1.0)
model.createRegion(0.0, 79.0, mesh_size_2, "Air_Rotor")
model.assignRegionProperties("Air_Rotor", "mu", 1.0)
model.createRegion(-62.0, 25.0, mesh_size_2, "Rotor_Air")
model.assignRegionProperties("Rotor_Air", "mu", 1.0)
model.createRegion(0.0, -38.0, mesh_size_1, "Stator_Core")
model.setRegionMaterial("Stator_Core", "M-36_steel")
model.createRegion(0.0, -1.75, mesh_size_2, "Air_Aux")
model.assignRegionProperties("Air_Aux", "mu", 1.0)
model.createRegion(-25.0, -15, mesh_size_3, "PhA")
model.assignRegionProperties("PhA", "mu", 1.0)
model.assignRegionProperties("PhA", "sigma", 5.7e7)
model.createRegion(25.0, -15, mesh_size_3, "PhB")
model.assignRegionProperties("PhB", "mu", 1.0)
model.assignRegionProperties("PhB", "sigma", 5.7e7)
model.createRegion(-70.0, -15, mesh_size_3, "PhC_01")
model.assignRegionProperties("PhC_01", "mu", 1.0)
model.assignRegionProperties("PhC_01", "sigma", 5.7e7)
model.createRegion(70.0, -15, mesh_size_3, "PhC_02")
model.assignRegionProperties("PhC_02", "mu", 1.0)
model.assignRegionProperties("PhC_02", "sigma", 5.7e7)

amp = 0.0
frequency = 0.0
nTurns = 10

model.defineCoil("Coil_A", nTurns, "AC", False, [amp, frequency, 0.0, 0.0])
model.defineCoil("Coil_B", nTurns, "AC", False, [amp, frequency, 0.0, 0.0])
model.defineCoil("Coil_C", nTurns/2, "AC", False, [amp, frequency, 0.0, 0.0])
model.assignCoilToRegion("PhA", "Coil_A", 1)
model.assignCoilToRegion("PhB", "Coil_B", -1)
model.assignCoilToRegion("PhC_01", "Coil_C", -1)
model.assignCoilToRegion("PhC_02", "Coil_C", 1)

model.selectAt(0.0, 84.0)
model.selectAddIn(0.0, -62.0)
model.assignBC(1, [0.0], "A_0")
model.selectAt(-75.0, 80.0)
model.selectAddIn(-75.0, 62.0)
model.selectAddIn(-75.0, 25.0)
model.selectAddIn(-75.0, -1.75)
model.selectAddIn(-75.0, -15.0)
model.selectAddIn(-75.0, -40.0)
model.selectAddIn(-75.0, -57.0)
model.assignBC(8, [0.0, 150.0, 1.0], "Anti-Periodic BC prime")
model.selectAt(75.0, 80.0)
model.selectAddIn(75.0, 62.0)
model.selectAddIn(75.0, 25.0)
model.selectAddIn(75.0, -1.75)
model.selectAddIn(75.0, -15.0)
model.selectAddIn(75.0, -40.0)
model.selectAddIn(75.0, -57.0)
model.assignBC(8, [0.0, 0.0, 1.0], "Anti-Periodic BC second")
model.selectAt(0.0, -1.0)
model.assignBC(10, [1.0, 1.0], "Sliding BC rotor")
model.selectAt(0.0, -1.5)
model.assignBC(10, [1.0, 0.0], "Sliding BC stator")

model.selectAt(0.0, -1.0)
model.selectAddIn(0.0, -1.5)
model.subdivideShape("Number of Divisions", 250)
model.selectAt(-75.0, 80.0)
model.selectAddIn(-75.0, 62.0)
model.selectAddIn(-75.0, 25.0)
model.selectAddIn(-75.0, -1.75)
model.selectAddIn(-75.0, -15.0)
model.selectAddIn(-75.0, -40.0)
model.selectAddIn(-75.0, -57.0)
model.selectAddIn(75.0, 80.0)
model.selectAddIn(75.0, 62.0)
model.selectAddIn(75.0, 25.0)
model.selectAddIn(75.0, -1.75)
model.selectAddIn(75.0, -15.0)
model.selectAddIn(75.0, -40.0)
model.selectAddIn(75.0, -57.0)
model.subdivideShape("Minimum Edge Length", 3.0)
model.selectAt(0.0, 84.0)
model.selectAddIn(0.0, -62.0)
model.subdivideShape("Number of Divisions", 40)

model.setSubdivisionProperties("subdiv_ext_shapes")

rot_angle = 0.0
linear_motion_profile = [
    [0.0, 3.0],
    [1.0, 3.0]
]
model.addMotion("Motion 01", "Linear", [-80.0, 85.0, 160.0, 86.25, rot_angle], linear_motion_profile)
model.enableMotion("Motion 01")

model.defineAxialLength(100.0)
model.solverSettings("SimplicialLDLT", "Transient", "s", "mm", [True, False, False], [1e-3, 1e-1, 1, 1e-2, 16, 0, 0.0])
model.setDefaultMeshSize(5.0)
model.generateMesh()
model.saveModel()
model.run_solver_with_monitor()

VoltageA = model.getResultsInCoil("Coil_A", "Voltage")
VoltageB = model.getResultsInCoil("Coil_B", "Voltage")
VoltageC = model.getResultsInCoil("Coil_C", "Voltage")
plt.figure(figsize=(10, 6))
plt.plot([point[0] for point in VoltageA], [point[1] for point in VoltageA], marker='o', linestyle='-', color='b', label='Coil A Voltage')
plt.plot([point[0] for point in VoltageB], [point[1] for point in VoltageB], marker='x', linestyle='--', color='r', label='Coil B Voltage')
plt.plot([point[0] for point in VoltageC], [point[1] for point in VoltageC], marker='^', linestyle='-.', color='g', label='Coil C Voltage')
plt.title("Phase Voltage vs Time")
plt.xlabel("Time (s)")
plt.ylabel("Voltage (V)")
plt.grid()
plt.legend()
plt.show()

model.launch()

model.stop()
                        

Results

The output os the simulation is the back electromotive force (bEMF) induced in the coils as the permanent magnet assembly moves linearly relative to the stationary coil assembly. The induced bEMF is given for one section of the linear machine over the simulation time.

Voltage vs Time in Linear Machine

An animation of the magnetic field distribution during the operation of the linear machine is shown below:

Instantaneous field distributions are shown below:

Vector Magnetic Potential (A)

Vector Magnetic Potential (A)

Absolute Magnetic Flux Density (B)

Absolute Magnetic Flux Density (B)

Absolute Magnetic Field Intensity (H)

Absolute Magnetic Field Intensity (H)

Magnetic permeabily (μ)

Magnetic Permeability (μ)

Vector Field B

Vector Field B