Magnetoelastics

Magnetoelastics#

In this example we initialize a magnet magnetized to the right. The magnet is minimized and the elastic parameters are assigned together with a circular area in which an external sinusoidal field is applied in the y-direction. This simulation runs for 0.5 ns and returns an animation of the y-magnetization and the amplified displacement.

import numpy as np
import math
from tqdm import tqdm
import matplotlib.pyplot as plt
import matplotlib.animation as animation

from mumaxplus import World, Grid, Ferromagnet
import mumaxplus.util.shape as shapes


length, width, thickness = 1e-6, 1e-6, 20e-9
nx, ny, nz = 256, 256, 1
cx, cy, cz = length/nx, width/ny, thickness/nz
cellsize = (cx, cy, cz)

grid = Grid((nx, ny, nz))
world = World(cellsize, mastergrid=Grid((nx, ny, 0)), pbc_repetitions=(2, 2, 0))
magnet = Ferromagnet(world, grid)

magnet.msat = 1.2e6
magnet.aex = 18e-12
magnet.alpha = 0.004
Bdc = 5e-3
magnet.bias_magnetic_field = (Bdc, 0, 0)  # uniform term
magnet.magnetization = (1, 0, 0)

magnet.minimize()

magnet.enable_elastodynamics = True
magnet.rho = 8e3
magnet.B1 = -8.8e6
magnet.B2 = -8.8e6
magnet.C11 = 283e9
magnet.C44 = 58e9
magnet.C12 = 166e9

magnet.elastic_displacement = (0, 0, 0)

# add magnetic field excitation
f_B = 9.8e9
Bac = 1e-3
Bdiam = 200e-9  # excitation diameter

# circular magnetic field excitation at the center
Bshape = shapes.Circle(Bdiam).translate(*magnet.center)
Bmask = magnet._get_mask_array(Bshape, grid, world, "mask")
magnet.bias_magnetic_field.add_time_term(
            lambda t: (0, Bac * math.sin(2*math.pi*f_B * t), 0), mask=Bmask)

magnet.alpha = 0.004
magnet.eta = 1e10  # elastic force damping

# plotting
fig, ax = plt.subplots()

u_scale = 1e5  # amplification of displacement
u_skip  = 10  # don't show every displacement

world.timesolver.adaptive_timestep = False
world.timesolver.timestep = 1e-12

frames = 400
steps_per_frame = 2

# save magnetization and displacement
m = np.zeros(shape=(frames, ny, nx))
u = np.zeros(shape=(frames, *magnet.elastic_displacement.shape))
t = np.zeros(shape=(frames))

# run a simulation
print("Simulating...")
for i in tqdm(range(frames)):
    world.timesolver.steps(steps_per_frame)
    m[i,...] = magnet.magnetization.eval()[1,0,:,:]
    u[i,...] = magnet.elastic_displacement.eval()
    t[i] = world.timesolver.time


# Draw horizontal and vertical lines to connect neighbors
mgrid = magnet.meshgrid
horizontal = []
vertical = []
uxyz = magnet.elastic_displacement.eval()[:,...]
coord = mgrid + uxyz*u_scale
x, y = coord[:2,0,...]

lw = 0.8

for i in range(0, ny, u_skip):  # Iterate over rows
    line = ax.plot(x[i,:], y[i,:], 'k-', lw=lw)  # Horizontal lines
    horizontal.append(line[0])
line = ax.plot(x[-1,:], y[-1,:], 'k-', lw=lw)  # Horizontal lines
horizontal.append(line[0])  # include the last cell to encompass whole grid

for i in range(0, nx, u_skip):  # Iterate over cols
    line = ax.plot(x[:,i], y[:,i], 'k-', lw=lw)  # Vertical lines
    vertical.append(line[0])
line = ax.plot(x[:,-1], y[:,-1], 'k-', lw=lw)  # Vertical lines
vertical.append(line[0])


# imshow setup
im_extent = (-0.5*cx, length - 0.5*cx, -0.5*cy, width - 0.5*cy)
vmax, vmin = np.max(m), np.min(m)
vmax = max(abs(vmax), abs(vmin))
vmin = -vmax
m_im = ax.imshow(m[0,...], origin="lower", extent=im_extent, vmin=vmin, vmax=vmax, cmap="seismic")

# colorbar setup
cbar = plt.colorbar(m_im)
cbar.ax.set_ylabel(r"$<m_y>$", rotation=270)

# final touches
ax.set_xlabel("$x$ (m)")
ax.set_ylabel("$y$ (m)")
ax.set_xlim(im_extent[0], im_extent[1])
ax.set_ylim(im_extent[2], im_extent[3])

def update(i):
    ax.set_title(f"t = {t[i]*1e9:.2f} ns")

    m_im.set_data(m[i,...])

    coord = mgrid + u[i,...]*u_scale
    x,y = coord[:2,0,...]
    
    # Horizontal lines
    for k, j in enumerate(range(0, ny, u_skip)):
        horizontal[k].set_data(x[j,:], y[j,:])
    horizontal[-1].set_data(x[-1,:], y[-1,:])

    # Vertical lines
    for k, j in enumerate(range(0, nx, u_skip)):
        vertical[k].set_data(x[:,j], y[:,j])
    vertical[-1].set_data(x[:,-1], y[:,-1])

    return m_im, *horizontal, *vertical

# animation
print("Animating...")
animation_fig = animation.FuncAnimation(fig, update, frames=frames, interval=40, blit=True)
animation_fig.save("magnetoelastic.mp4")
print("Done!")