{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Tutorial 03: Uniaxial anisotropy energy term\n", "\n", "> Interactive online tutorial:\n", "> [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/ubermag/oommfc/master?filepath=docs%2Fipynb%2Findex.ipynb)\n", "\n", "Uniaxial anisotropy energy density is computed as\n", "\n", "$$w_\\text{a} = -K (\\mathbf{m}\\cdot\\mathbf{u})^{2}$$\n", "\n", "where $\\mathbf{m}$ is the normalised ($|\\mathbf{m}|=1$) magnetisation, $K$ is the uniaxial anisotropy constant, and $\\mathbf{u}$ is the anisotropy axis. Uniaxial anisotropy energy term tends to align all magnetic moments parallel or antiparallel to the anisotropy axis.\n", "\n", "In `oommfc`, $\\mathbf{m}$ is a part of the magnetisation field `system.m`. Therefore, only uniaxial anisotropy constant $K$ and axis $\\mathbf{u}$ should be provided as input parameters to uniquely define the energy term. Both $K$ and $\\mathbf{u}$ can be constant in space or spatially varying.\n", "\n", "## Spatially constant $K$ and $\\mathbf{u}$\n", "\n", "Let us start by assembling a simple simple simulation where neither $K$ nor $\\mathbf{u}$ vary in space. The sample is a \"one-dimensional\" chain of magnetic moments." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import oommfc as oc\n", "\n", "p1 = (-10e-9, 0, 0)\n", "p2 = (10e-9, 1e-9, 1e-9)\n", "cell = (1e-9, 1e-9, 1e-9)\n", "mesh = oc.Mesh(p1=p1, p2=p2, cell=cell)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The mesh is" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "518f5fb33f284a98892fd41b07a078a5", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Output()" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "mesh.k3d()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The system has a Hamiltonian, which consists of only uniaxial anisotropy energy term." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "K = 1e5 # uniaxial anisotropy constant (J/m**3)\n", "u = (0, 0, 1) # uniaxial anisotropy axis\n", "system = oc.System(name='uniaxialanisotropy-constant-K-u')\n", "system.hamiltonian = oc.UniaxialAnisotropy(K1=K, u=u)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We are going to minimise the system's energy using `oommfc.MinDriver` later. Therefore, we do not have to define the system's dynamics equation. Finally, we need to define the system's magnetisation (`system.m`). We are going to make it random with $M_\\text{s}=8\\times10^{5} \\,\\text{Am}^{-1}$" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "import random\n", "import discretisedfield as df\n", "\n", "Ms = 8e5 # saturation magnetisation (A/m)\n", "\n", "def m_fun(pos):\n", " return [2*random.random()-1 for i in range(3)]\n", "\n", "system.m = df.Field(mesh, dim=3, value=m_fun, norm=Ms)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The magnetisation, we set is" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "e0b167fe842b48899a3febb26eb3d0e1", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Output()" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "system.m.k3d_vectors(color_field=system.m.z)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, we can minimise the system's energy by using `oommfc.MinDriver`." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2019/08/25 21:26: Running OOMMF (uniaxialanisotropy-constant-K-u.mif) ... (2.0 s)\n" ] } ], "source": [ "md = oc.MinDriver()\n", "md.drive(system)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We expect that now all magnetic moments are aligned parallel or antiparallel to the anisotropy axis (in the $z$-direction)." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "b3a54e530a0f4b5dbcb207d74d145d80", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Output()" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "system.m.k3d_vectors(color_field=system.m.z)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, we can delete the files created by `oommfc`." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "system.delete()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Spatially varying $\\mathbf{K}$\n", "\n", "There are two different ways how a parameter can be made spatially varying, by using:\n", "1. Dictionary\n", "2. `discretisedfield.Field`\n", "\n", "### Dictionary\n", "\n", "In order to define a parameter using a dictionary, regions must be defined in the mesh. Regions are defined as a dictionary, whose keys are the strings and values are `discretisedfield.Region` objects, which take two corner points of the region as input parameters. " ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "p1 = (-10e-9, 0, 0)\n", "p2 = (10e-9, 1e-9, 1e-9)\n", "cell = (1e-9, 1e-9, 1e-9)\n", "regions = {'region1': df.Region(p1=(-10e-9, 0, 0), p2=(0, 1e-9, 1e-9)),\n", " 'region2': df.Region(p1=(0, 0, 0), p2=(10e-9, 1e-9, 1e-9))}\n", "mesh = oc.Mesh(p1=p1, p2=p2, cell=cell, regions=regions)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "8f586b3855424ff584239efa5bb1dda9", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Output()" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "mesh.k3d_regions()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us say that there is no uniaxial anisotropy ($K=0$) in region 1, whereas in region 2 it is $K=10^{5} \\,\\text{Jm}^{-3}$. $\\mathbf{u}$ is in the $z$-direction. `K` is now defined as a dictionary:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "K = {'region1': 0, 'region2': 1e5}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The system object is" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "system = oc.System(name='uniaxialanisotropy-dict-K')\n", "system.hamiltonian = oc.UniaxialAnisotropy(K1=K, u=u)\n", "system.m = df.Field(mesh, dim=3, value=m_fun, norm=Ms)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Its magnetisation is" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "b4d133dd41bf453c8ec4d53ad38573a6", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Output()" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "system.m.k3d_vectors(color_field=system.m.z)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "After we minimise the energy" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2019/08/25 21:26: Running OOMMF (uniaxialanisotropy-dict-K.mif) ... (2.0 s)\n" ] } ], "source": [ "md.drive(system)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The magnetisation is as we expected." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "1ae09d6ae4a24d3f8d74935a8b233394", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Output()" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "system.m.k3d_vectors(color_field=system.m.z)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "system.delete()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `discretisedfield.Field`\n", "\n", "Let us define the spatailly varying uniaxial anisotropy, so that\n", "\n", "$\\mathbf{u}(x, y, z) = \\left\\{\n", "\\begin{array}{ll}\n", "(0, 0, 1) & x \\le 0 \\\\\n", "(1, 0, 0) & x > 0 \\\\\n", "\\end{array}\n", "\\right. $\n", "\n", "The value of `u` for the spatially varying anisotropy is set using a Python function." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "def u_fun(pos):\n", " x, y, z = pos\n", " if x <= 0:\n", " return (0, 0, 1)\n", " else:\n", " return (1, 0, 0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The uniaxial anisotropy parameters are" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "K = 1e5\n", "u = df.Field(mesh, dim=3, value=u_fun)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The system is" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "system = oc.System(name='uniaxialanisotropy-field-u')\n", "system.hamiltonian = oc.UniaxialAnisotropy(K1=K, u=u)\n", "system.m = df.Field(mesh, dim=3, value=m_fun, norm=Ms)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "and its magnetisation is" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "921217dc99864ddf8621d1caea9e0ec7", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Output()" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "system.m.k3d_vectors(color_field=system.m.z)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "After the energy minimisation, the magnetisation is:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2019/08/25 21:26: Running OOMMF (uniaxialanisotropy-field-u.mif) ... (1.9 s)\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "836504d87fc040748742dd380bffce4e", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Output()" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "md.drive(system)\n", "system.m.k3d_vectors(color_field=system.m.z)" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "system.delete()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Other\n", "\n", "More details on various functionality can be found in the [API Reference](https://oommfc.readthedocs.io/en/latest/)." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.4" } }, "nbformat": 4, "nbformat_minor": 2 }