diff --git a/examples/relax-hopfion.ipynb b/examples/relax-hopfion.ipynb new file mode 100644 index 0000000..6a75155 --- /dev/null +++ b/examples/relax-hopfion.ipynb @@ -0,0 +1,262 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "id": "55f0586c", + "metadata": {}, + "source": [ + "# Hopfion in a nanodisk\n", + "\n", + "In this tutorial we relax a hopfion in a chiral magnetic nanodisk and calculate its Hopf index. We consider a nanodisk with a radius $r=100 \\, \\text{nm}$, a thickness $t=70 \\, \\text{nm}$, and ends at the top and bottom of thickness $d=10 \\, \\text{nm}$ in which the unit magnetization field $\\boldsymbol{m}$ is frozen along the $z$-direction.\n", + "\n", + "This tutorial draws on the works [Y. Liu, R. K. Lake and J. Zang. Binding a hopfion in a chiral magnet nanodisk. Phys. Rev. B 98, 174437 (2019)](https://doi.org/10.1103/PhysRevB.98.174437) and [P. Sutcliffe. Hopfions in chiral magnets. J. Phys. A: Math. Theor. 51 375401 (2018)](https://doi.org/10.1088/1751-8121/aad521)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a19ea274", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import oommfc as oc\n", + "import discretisedfield as df\n", + "import micromagneticmodel as mm\n", + "from discretisedfield.tools import hopf_index" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "60719044", + "metadata": {}, + "source": [ + "We define the region 'cylinder', in which the magnetization evoles, as well as 'top' and 'bottom', the two fixed layers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d7e56983", + "metadata": {}, + "outputs": [], + "source": [ + "r = 100e-9\n", + "t = 70e-9\n", + "d = 10e-9\n", + "\n", + "region = df.Region(p1=(-r, -r, -d), p2=(r, r, t+d))\n", + "subregions = {'bottom': df.Region(p1=(-r, -r, -d), p2=(r, r, 0)),\n", + " 'cylinder': df.Region(p1=(-r, -r, 0), p2=(r, r, t)),\n", + " 'top': df.Region(p1=(-r, -r, t), p2=(r, r, t+d))}\n", + "mesh = df.Mesh(region=region, cell=(2e-9, 2e-9, 2e-9), subregions=subregions)\n", + "\n", + "mesh.k3d.subregions()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "cf2c9340", + "metadata": {}, + "source": [ + "We consider a system with symmetric exchange and DMI energy." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cf8bd5dd", + "metadata": {}, + "outputs": [], + "source": [ + "system = mm.System(name='hopfion')\n", + "\n", + "system.energy = (mm.Exchange(A=2.195e-12)\n", + " + mm.DMI(D=3.95e-4, crystalclass='T'))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "47e2e851", + "metadata": {}, + "source": [ + "The magnetization is set to be zero outside of the disk geometry." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4bb00e1e", + "metadata": {}, + "outputs": [], + "source": [ + "Ms = 3.84e5\n", + "\n", + "def Ms_fun(pos):\n", + " x, y, z = pos\n", + " if (x**2 + y**2)**0.5 < r:\n", + " return Ms\n", + " else:\n", + " return 0" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "7b213d51", + "metadata": {}, + "source": [ + "We initialise a hopfion spin texture as a toroidal skyrmion tube with major radius $L=t/2$, skyrmion radius $R=t/4$, and skyrmion domain wall width of $w=t/8$." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1552d5fa", + "metadata": {}, + "outputs": [], + "source": [ + "L = t/2\n", + "R = t/4\n", + "w = t/8\n", + "\n", + "def m_init(pos):\n", + " \n", + " x, y, z = pos\n", + "\n", + " # Translate to centre of nanodisk\n", + " z -= t/2\n", + "\n", + " # Angle around origin in x-y-plane\n", + " psi = np.arctan2(y, x)\n", + "\n", + " # x-coordinate in reference plane with a centre coinciding with the skyrmion's centre\n", + " xPrime = (x - L*np.cos(psi)) * np.cos(psi) + (y - L*np.sin(psi)) * np.sin(psi)\n", + "\n", + " # Set magnetization in this reference frame\n", + " rho = np.sqrt(xPrime**2 + z**2)\n", + " Phi = np.arctan2(z, xPrime)\n", + " Theta = 2 * np.arctan2(np.sinh(R/w), np.sinh(rho/w))\n", + " myPrime = np.cos(Phi) * np.sin(Theta)\n", + " mz = np.cos(Theta)\n", + " mxPrime = np.sin(Phi) * np.sin(Theta)\n", + "\n", + " # Transform magnetization back to global coordinates\n", + " mx = mxPrime*np.cos(psi) - myPrime*np.sin(psi)\n", + " my = mxPrime*np.sin(psi) + myPrime*np.cos(psi)\n", + " \n", + " return (mx, my, mz)\n", + "\n", + "m = {'bottom': (0, 0, 1), 'cylinder': m_init, 'top': (0, 0, 1)}\n", + "system.m = df.Field(mesh, nvdim=3, value=m, norm=Ms_fun)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "62ea5962", + "metadata": {}, + "source": [ + "We can image the initialised hopfion texture." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2bacce76", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "system.m.sel('x').mpl()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "877ebbd9", + "metadata": {}, + "source": [ + "We can also calculate the Hopf index of this hopfion texture." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cd01d7b7", + "metadata": {}, + "outputs": [], + "source": [ + "print(hopf_index(system.m))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "bc60b0f0", + "metadata": {}, + "source": [ + "We relax the system with the subregions 'top' and 'bottom' fixed." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cfc1699e", + "metadata": {}, + "outputs": [], + "source": [ + "md = oc.MinDriver()\n", + "md.drive(system, fixed_subregions=['bottom', 'top'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fa219a39", + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "system.m.plane('x').mpl()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e5e9b1bf", + "metadata": {}, + "outputs": [], + "source": [ + "print(hopf_index(system.m))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.8.16" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}