Dear all,
I am trying to do some simulations with AFM medium. In the process of understanding how each parameter works, I have stumbled across a functionality that I cannot explain with the API documentation of mumax+. When I set up a ferromagnet via the Antiferromagnet function, by setting the parameters of one sublattice to zero, it works, as I would expect. However, if I set up Msat for the omitted sublattice, I would still expect it to work as before, which it doesn't. Notably, the omitted sublattice aligns, which it shouldn't, since Aex for that sublattice I set to zero.
I also set the parameters afmex_cell and afmex_nn to zero to remove any coupling between the sublattices.
For reference, my code is below. I hope it works for you. If anyone has an idea what I am doing wrong, it would be invaluable.
I really appreciate any help you can provide.
Sincerely,
Miroslav Polách
=======================================================================
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import FuncFormatter
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from mumaxplus import Antiferromagnet, Ferromagnet, Grid, World
from mumaxplus.util import plot_field
# Fuctions for visualization
def plot_cube_with_section(ax, out_of_plane='z'):
"""Plot a cube and its cross-section plane on a given axis."""
r = [0, 1]
vertices = np.array([
[r[0], r[0], r[0]], [r[1], r[0], r[0]],
[r[1], r[1], r[0]], [r[0], r[1], r[0]],
[r[0], r[0], r[1]], [r[1], r[0], r[1]],
[r[1], r[1], r[1]], [r[0], r[1], r[1]]
])
faces = [
[vertices[0], vertices[1], vertices[2], vertices[3]],
[vertices[4], vertices[5], vertices[6], vertices[7]],
[vertices[0], vertices[1], vertices[5], vertices[4]],
[vertices[2], vertices[3], vertices[7], vertices[6]],
[vertices[1], vertices[2], vertices[6], vertices[5]],
[vertices[4], vertices[7], vertices[3], vertices[0]]
]
# Draw cube
ax.add_collection3d(Poly3DCollection(faces, facecolors='white', edgecolors='k', alpha=0.3))
# Add cross-section plane
s = np.linspace(0, 1, 2)
if out_of_plane == 'z':
xx, yy = np.meshgrid(s, s)
zz = np.full_like(xx, 0.5)
ax.plot_surface(xx, yy, zz, color='gray', alpha=0.6)
#ax.set_title("XY Plane (z = 0.5)")
elif out_of_plane == 'y':
xx, zz = np.meshgrid(s, s)
yy = np.full_like(xx, 0.5)
ax.plot_surface(xx, yy, zz, color='gray', alpha=0.6)
#ax.set_title("XZ Plane (y = 0.5)")
elif out_of_plane == 'x':
yy, zz = np.meshgrid(s, s)
xx = np.full_like(yy, 0.5)
ax.plot_surface(xx, yy, zz, color='gray', alpha=0.6)
#ax.set_title("YZ Plane (x = 0.5)")
else:
raise ValueError("plane must be 'z', 'y', or 'x'")
# Aesthetics
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.set_zlim(0, 1)
ax.set_box_aspect([1,1,1])
ax.set_xticks([]); ax.set_yticks([]); ax.set_zticks([])
#########################################################
###################### mumax+ code ######################
#########################################################
cross_sections = False # set to True to plot only cross-section planes in the plots
# cell size
length, width, thickness = 3e-9, 3e-9, 3e-9
world = World(cellsize=(length, width, thickness))
# number of cells
n = 15
nx, ny, nz = n, n, n
grid = Grid((nx, ny, nz))
# magnet envirnment
AFM = Antiferromagnet(world, grid, name="Ferromagnet")
AFM.afmex_cell = 0
AFM.afmex_nn = 0
# material parameters - Magnetite Fe3O4
AFM.sub1.msat = 0.48e6
AFM.sub1.aex = 7e-12
AFM.sub1.kc1 = -13e3
AFM.sub1.anisC1 = (1,0,0)
AFM.sub1.anisC2 = (0,1,0)
AFM.sub1.alpha = 0.1
# material parameters - other sublattice
AFM.sub2.msat = 0 # if set to 0.48e6, the sub2 also minimizes
AFM.sub2.aex = 0
AFM.sub2.kc1 = 0
AFM.sub2.alpha = 0
np.random.seed(1983)
m = np.zeros(AFM.sub1.magnetization.shape)
m[:,:,:,:] += np.random.normal(0, 1, size=m[:,:,:,:].shape)
AFM.sub1.magnetization = m
#np.random.seed(1984)
#m = np.zeros(AFM.sub2.magnetization.shape)
#m[:,:,:,:] += np.random.normal(0, 1, size=m[:,:,:,:].shape)
#AFM.sub2.magnetization = m
# plot_field(AFM.full_magnetization, arrow_size=1, show=True, layer=nz//2, title=False)
AFM.relax()
# show full magnetization
outofplane_axes = ['z', 'y', 'x']
fig = plt.figure(figsize=(12, 3))
for i, out_axis in enumerate(outofplane_axes, 1):
if cross_sections:
ax = fig.add_subplot(1, 3, i, projection='3d')
plot_cube_with_section(ax, out_axis)
else:
ax = fig.add_subplot(1, 3, i)
ax.xaxis.set_major_formatter(FuncFormatter(lambda x, _: f"{x*1e9:g}"))
ax.yaxis.set_major_formatter(FuncFormatter(lambda y, _: f"{y*1e9:g}"))
if out_axis == 'x':
m = AFM.full_magnetization()[:, :, :, [n//2]]
m = np.moveaxis(m, 3, 1)
world_help = World(cellsize=(length, width, thickness))
magnet_help = Ferromagnet(world_help, Grid((nx, ny, 1)), name="2D_projection")
magnet_help.magnetization = m
plot_field(magnet_help.magnetization, arrow_size=2, ax=ax, title=False, xlabel="$y$ (nm)", ylabel="$z$ (nm)")
if out_axis == 'y':
m = AFM.full_magnetization()[:, :, [n//2], :]
m = np.moveaxis(m, 2, 1)
world_help = World(cellsize=(length, width, thickness))
magnet_help = Ferromagnet(world_help, Grid((nx, ny, 1)), name="2D_projection")
magnet_help.magnetization = m
plot_field(magnet_help.magnetization, arrow_size=2, ax=ax, title=False, xlabel="$x$ (nm)", ylabel="$z$ (nm)")
if out_axis == 'z':
m = AFM.full_magnetization()[:, [n//2], :, :]
world_help = World(cellsize=(length, width, thickness))
magnet_help = Ferromagnet(world_help, Grid((nx, ny, 1)), name="2D_projection")
magnet_help.magnetization = m
plot_field(magnet_help.magnetization, arrow_size=2, ax=ax, title=False, xlabel="$x$ (nm)", ylabel="$y$ (nm)")
if cross_sections:
plt.tight_layout()
plt.savefig("cube_NP_cross_sections.pdf", dpi=300)
else:
plt.tight_layout()
if n <= 10:
plt.savefig("AFM_cube_text_full_magnetization_small.pdf", dpi=300)
elif n <= 20:
plt.savefig("AFM_cube_text_full_magnetization_medium.pdf", dpi=300)
else:
plt.savefig("AFM_cube_text_full_magnetization_large.pdf", dpi=300)
plt.show()
# show magnetization of sublattice 1
fig = plt.figure(figsize=(12, 3))
for i, out_axis in enumerate(outofplane_axes, 1):
if cross_sections:
ax = fig.add_subplot(1, 3, i, projection='3d')
plot_cube_with_section(ax, out_axis)
else:
ax = fig.add_subplot(1, 3, i)
ax.xaxis.set_major_formatter(FuncFormatter(lambda x, _: f"{x*1e9:g}"))
ax.yaxis.set_major_formatter(FuncFormatter(lambda y, _: f"{y*1e9:g}"))
if out_axis == 'x':
m = AFM.sub1.magnetization()[:, :, :, [n//2]]
m = np.moveaxis(m, 3, 1)
world_help = World(cellsize=(length, width, thickness))
magnet_help = Ferromagnet(world_help, Grid((nx, ny, 1)), name="2D_projection")
magnet_help.magnetization = m
plot_field(magnet_help.magnetization, arrow_size=2, ax=ax, title=False, xlabel="$y$ (nm)", ylabel="$z$ (nm)")
if out_axis == 'y':
m = AFM.sub1.magnetization()[:, :, [n//2], :]
m = np.moveaxis(m, 2, 1)
world_help = World(cellsize=(length, width, thickness))
magnet_help = Ferromagnet(world_help, Grid((nx, ny, 1)), name="2D_projection")
magnet_help.magnetization = m
plot_field(magnet_help.magnetization, arrow_size=2, ax=ax, title=False, xlabel="$x$ (nm)", ylabel="$z$ (nm)")
if out_axis == 'z':
m = AFM.sub1.magnetization()[:, [n//2], :, :]
world_help = World(cellsize=(length, width, thickness))
magnet_help = Ferromagnet(world_help, Grid((nx, ny, 1)), name="2D_projection")
magnet_help.magnetization = m
plot_field(magnet_help.magnetization, arrow_size=2, ax=ax, title=False, xlabel="$x$ (nm)", ylabel="$y$ (nm)")
if cross_sections:
plt.tight_layout()
plt.savefig("cube_NP_cross_sections.pdf", dpi=300)
else:
plt.tight_layout()
if n <= 10:
plt.savefig("AFM_cube_text_sub1_magnetization_small.pdf", dpi=300)
elif n <= 20:
plt.savefig("AFM_cube_text_sub1_magnetization_medium.pdf", dpi=300)
else:
plt.savefig("AFM_cube_text_sub1_magnetization_large.pdf", dpi=300)
plt.show()
# show magnetization of sublattice 2
fig = plt.figure(figsize=(12, 3))
for i, out_axis in enumerate(outofplane_axes, 1):
if cross_sections:
ax = fig.add_subplot(1, 3, i, projection='3d')
plot_cube_with_section(ax, out_axis)
else:
ax = fig.add_subplot(1, 3, i)
ax.xaxis.set_major_formatter(FuncFormatter(lambda x, _: f"{x*1e9:g}"))
ax.yaxis.set_major_formatter(FuncFormatter(lambda y, _: f"{y*1e9:g}"))
if out_axis == 'x':
m = AFM.sub2.magnetization()[:, :, :, [n//2]]
m = np.moveaxis(m, 3, 1)
world_help = World(cellsize=(length, width, thickness))
magnet_help = Ferromagnet(world_help, Grid((nx, ny, 1)), name="2D_projection")
magnet_help.magnetization = m
plot_field(magnet_help.magnetization, arrow_size=2, ax=ax, title=False, xlabel="$y$ (nm)", ylabel="$z$ (nm)")
if out_axis == 'y':
m = AFM.sub2.magnetization()[:, :, [n//2], :]
m = np.moveaxis(m, 2, 1)
world_help = World(cellsize=(length, width, thickness))
magnet_help = Ferromagnet(world_help, Grid((nx, ny, 1)), name="2D_projection")
magnet_help.magnetization = m
plot_field(magnet_help.magnetization, arrow_size=2, ax=ax, title=False, xlabel="$x$ (nm)", ylabel="$z$ (nm)")
if out_axis == 'z':
m = AFM.sub2.magnetization()[:, [n//2], :, :]
world_help = World(cellsize=(length, width, thickness))
magnet_help = Ferromagnet(world_help, Grid((nx, ny, 1)), name="2D_projection")
magnet_help.magnetization = m
plot_field(magnet_help.magnetization, arrow_size=2, ax=ax, title=False, xlabel="$x$ (nm)", ylabel="$y$ (nm)")
if cross_sections:
plt.tight_layout()
plt.savefig("cube_NP_cross_sections.pdf", dpi=300)
else:
plt.tight_layout()
if n <= 10:
plt.savefig("AFM_cube_text_sub2_magnetization_small.pdf", dpi=300)
elif n <= 20:
plt.savefig("AFM_cube_text_sub2_magnetization_medium.pdf", dpi=300)
else:
plt.savefig("AFM_cube_text_sub2_magnetization_large.pdf", dpi=300)
plt.show()
# print average magnetizations
print((AFM.sub1.magnetization.average()))
print((AFM.sub2.magnetization.average()))