def test_spatially_varying_anisotropy_axis(tmpdir, debug=False): Ms = 1e6 A = 1.3e-11 K1 = 6e5 lb = bloch_parameter(A, K1) unit_length = 1e-9 nx = 20 Lx = nx * lb / unit_length mesh = df.IntervalMesh(nx, 0, Lx) # anisotropy axis goes from (0, 1, 0) at x=0 to (1, 0, 0) at x=Lx expr_a = df.Expression(("x[0] / sqrt(pow(x[0], 2) + pow(Lx-x[0], 2))", "(Lx-x[0]) / sqrt(pow(x[0], 2) + pow(Lx-x[0], 2))", "0"), Lx=Lx, degree=1) # in theory, a discontinuous Galerkin (constant over the cell) is a good # choice to represent material parameters. In this case though, the # parameter varies linearly, so we use the usual CG. V = df.VectorFunctionSpace(mesh, "CG", 1, dim=3) a = Field(V, expr_a) sim = Simulation(mesh, Ms, unit_length) sim.set_m((1, 1, 0)) sim.add(UniaxialAnisotropy(K1, a)) sim.relax() # probe the easy axis and the magnetisation along the interval points = 100 xs = np.linspace(0, Lx, points) axis_xs = np.zeros((points, 3)) m_xs = np.zeros((points, 3)) for i, x in enumerate(xs): axis_xs[i] = a(x) m_xs[i] = sim.m_field(x) # we want to the magnetisation to follow the easy axis # it does so, except at x=0, what is happening there? diff = np.abs(m_xs - axis_xs) assert diff.max() < 0.02 if debug: old = os.getcwd() os.chdir(tmpdir) fig = plt.figure() ax = fig.add_subplot(111) ax.plot(xs, axis_xs[:, 0], "b+", label="a_x") ax.plot(xs, m_xs[:, 0], "r--", label="m_x") ax.legend(loc="upper left") ax.set_ylim((0, 1.05)) ax.set_xlabel("x (nm)") plt.savefig('spatially_varying_easy_axis.png') plt.close() sim.m_field.save_pvd('spatially_varying_easy_axis.pvd') os.chdir(old)
def run_simulation(plot=False): mu0 = 4.0 * np.pi * 10**-7 # vacuum permeability N/A^2 Ms = 1.0e6 # saturation magnetisation A/m A = 13.0e-12 # exchange coupling strength J/m Km = 0.5 * mu0 * Ms**2 # magnetostatic energy density scale kg/ms^2 lexch = (A / Km)**0.5 # exchange length m unit_length = 1e-9 K1 = Km L = lexch / unit_length nx = 10 Lx = nx * L ny = 1 Ly = ny * L nz = 30 Lz = nz * L mesh = df.BoxMesh(df.Point(0, 0, 0), df.Point(Lx, Ly, Lz), nx, ny, nz) # Anisotropy easy axis is (0, 0, 1) in the lower half of the film and # (1, 0, 0) in the upper half. This is a toy model of the exchange spring # systems that Bob Stamps is working on. boundary = Lz / 2.0 expr_a = df.Expression(("x[2] <= b ? 0 : 1", "0", "x[2] <= b ? 1 : 0"), b=boundary, degree=1) V = df.VectorFunctionSpace(mesh, "DG", 0, dim=3) a = Field(V, expr_a) sim = Simulation(mesh, Ms, unit_length) sim.set_m((1, 0, 1)) sim.add(UniaxialAnisotropy(K1, a)) sim.add(Exchange(A)) sim.relax() if plot: points = 200 zs = np.linspace(0, Lz, points) axis_zs = np.zeros((points, 3)) # easy axis probed along z-axis m_zs = np.zeros((points, 3)) # magnetisation probed along z-axis for i, z in enumerate(zs): axis_zs[i] = a((Lx / 2.0, Ly / 2.0, z)) m_zs[i] = sim.m_field((Lx / 2.0, Ly / 2.0, z)) fig = plt.figure() ax = fig.add_subplot(111) ax.plot(zs, axis_zs[:, 0], "-o", label="a_x") ax.plot(zs, axis_zs[:, 2], "-x", label="a_z") ax.plot(zs, m_zs[:, 0], "-", label="m_x") ax.plot(zs, m_zs[:, 2], "-", label="m_z") ax.set_xlabel("z (nm)") ax.legend(loc="upper left") plt.savefig(os.path.join(MODULE_DIR, "profile.png")) sim.m_field.save_pvd(os.path.join(MODULE_DIR, 'exchangespring.pvd'))