Have a personal or library account? Click to login
Fidimag – A Finite Difference Atomistic and Micromagnetic Simulation Package Cover

Fidimag – A Finite Difference Atomistic and Micromagnetic Simulation Package

Open Access
|Sep 2018

Figures & Tables

jors-6-223-g1.png
Figure 1

Snapshots of the unit magnetisation. The plots were created with the code in the function plot_quiver of listing 1. (a) The initial unit magnetisation of the bar of Permalloy described in standard problem #4. (b) The magnetisation conguration at the moment of the reversal of the average magnetisation. (c) The magnetisation after a nanosecond of simulation time has elapsed.

Listing 1

Solution to the standard problem #4. The simulation defined in the function compute_initial_magnetisation returns the relaxed magnetisation configuration in absence of an applied magnetic field. In the function compute_dynamics that makes up the second simulation, the magnetic field that causes the magnetisation reversal is added on line 42. The snapshots in Figure 1 were made using the code in the function plot_quiver.

import os
import matplotlib.pyplot as plt
import numpy as np
from fidimag.micro import Sim, UniformExchange, Demag, Zeeman
from fidimag.common import CuboidMesh
from fidimag.common.constant import mu_0
 
mesh = CuboidMesh(nx=200, ny=50, nz=1, dx=2.5, dy=2.5, dz=3, unit_length=1e-9)
 
A = 1.3e-11
Ms = 8.0e5
alpha = 0.02
gamma = 2.211e5
mT = 0.001 / mu_0
 
 
def compute_initial_magnetisation():
     sim = Sim(mesh, name=‘problem4_init’)
     sim.driver.set_tols(rtol=1e-10, atol=1e-10)
     sim.driver.alpha = 0.5
     sim.driver.gamma = gamma
     sim.Ms = Ms
     sim.do_precession = False # saves time - not interested in dynamics here
     sim.set_m((1, 0.25, 0.1))
     sim.add(UniformExchange(A))
     sim.add(Demag())
     sim.relax(dt=1e-13, stopping_dmdt=0.01, max_steps=5000, save_m_steps=None, save_vtk_steps=None)
     return sim.spin
 
 
def compute_dynamics(initial_magnetisation):
     sim = Sim(mesh, name=‘problem4_dynamics’)
     sim.set_m(initial_magnetisation)
     sim.driver.set_tols(rtol=1e-10, atol=1e-10)
     sim.driver.alpha = alpha
     sim.driver.gamma = gamma
     sim.Ms = Ms
     sim.add(UniformExchange(A))
     sim.add(Demag())
     sim.add(Zeeman([-24.6 * mT, 4.3 * mT, 0], name=‘H’), save_field=True)
 
     crossed_zero = False
     ts = np.linspace(0, 1e-9, 201)
     for t in ts:
          sim.driver.run_until(t)
          mx, my, mz = sim.compute_average()
 
          print(“t = {:.3} ns\t mx = {:.3}”.format(t*1e9, mx))
          if mx <= 0 and not crossed_zero:
               print(“Crossed zero!”)
               np.save(“problem4_m_when_mz_0.npy”, sim.spin)
               crossed_zero = True
     return sim.spin
 
 
def plot_quiver(m, filename):
     m.shape = (50, 200, 3)
     skip = 5
     m = m[1::skip, 1::skip]
 
     xyz = mesh.coordinates
     xyz.shape = (50, 200, 3)
     xyz = xyz[1::skip, 1::skip]
     plt.figure(figsize=(12, 3))
     plt.axes().set_aspect(‘equal’)
     plt.quiver(xyz[:,:,0], xyz[:,:,1],
              m[:,:,0], m[:,:,1], m[:,:,1],
              pivot=‘mid’, scale=45, cmap=plt.get_cmap(‘jet’), edgecolors=‘None’)
     c = plt.colorbar()
     plt.xlabel(“x (nm)”)
     plt.ylabel(“y (nm)”)
     c.set_label(“$m_\mathrm{y}$ (1)”)
     plt.clim([0, 1])
     plt.xlim([0, 500])
     plt.ylim([0, 125])
     plt.savefig(filename)
 
 
if __name__ == ‘__main__’:
     m0_file = “problem4_m0.npy”
     if not os.path.exists(m0_file):
          m0 = compute_initial_magnetisation()
          np.save(m0_file, m0)
     else:
          m0 = np.load(m0_file)
     mf_file = “problem4_mf.npy”
     if not os.path.exists(mf_file):
          mf = compute_dynamics(m0)
          np.save(mf_file, mf)
     else:
          mf = np.load(mf_file)
 
     plot_quiver(m0, “problem4_m0.pdf”)
     plot_quiver(np.load(“problem4_m_when_mz_0.npy”), “problem4_m_when_mz_0.pdf”)
     plot_quiver(mf, “problem4_mf.pdf”)
jors-6-223-g2.png
Figure 2

The components of the average magnetisation over time as computed with Fidimag and by OOMMF.

Listing 2

Solution to the standard problem #3. The code that computes the energy difference between the two possible magnetic configurations has been abstracted into the function energy_difference in the module cube_sim that is imported in line 6. The function energy_difference can then be handed off to a bisect method provided by SciPy to find the cube size for which both configurations have the same energy.

”””
Solution to µmag standard problem #3 with fidimag.
    http://www.ctcms.nist.gov/~rdm/mumag.org.html
 
”””
from .cube_sim import energy_difference
from scipy.optimize import bisect
 
single_domain_limit = bisect(energy_difference, 8, 8.5, xtol=0.1)
print(“L = {:.2} nm.”.format(str(single_domain_limit))
jors-6-223-g3.png
Figure 3

Architecture of Fidimag as reflected by the directory structure and Python modules. Code useful to micromagnetic and atomistic simulations was extracted into a common namespace. The red arrows point to user-facing parts of the system.

jors-6-223-g4.png
Figure 4

Cuboid mesh and hexagonal lattice labelled according to the index of the sites.

Listing 3

Definition of a 2 nm wide sphere geometry using micromagnetics.

import fidimag
import numpy as np
 
mesh = fidimag.common.CuboidMesh(nx=6, ny=6, nz=6,
                                 dx=1, dy=1, dz=1,
                                 unit_length=1e-9)
sim = fidimag.micro.Sim(mesh)
Ms = 1e6 # A / m
 
def sphere(r):
     x, y, z = r
     if x ** 2 + y ** 2 <= 2 ** 2:
         return Ms
     else:
         return 0
sim.set_Ms(sphere)
Listing 4

A unit test in which a scalar field s is created on a hexagonal mesh, saved to a VTK file and compared to a reference file.

def test_save_scalar_field_hexagonal_mesh(tmpdir):
     mesh = HexagonalMesh(radius=1, nx=3, ny=3)
     s = scalar_field(mesh, lambda r: r[0] + r[1])
     vtk = VTK(mesh, directory=str(tmpdir), filename=”scalar_hexagonal”)
     vtk.save_scalar(s, name=”s”)
     assert same_as_ref(vtk.write_file(), REF_DIR)
DOI: https://doi.org/10.5334/jors.223 | Journal eISSN: 2049-9647
Language: English
Submitted on: Feb 14, 2018
|
Accepted on: Aug 15, 2018
|
Published on: Sep 6, 2018
Published by: Ubiquity Press
In partnership with: Paradigm Publishing Services
Publication frequency: 1 issue per year

© 2018 Marc-Antonio Bisotti, David Cortés-Ortuño, Ryan Pepper, Weiwei Wang, Marijan Beg, Thomas Kluyver, Hans Fangohr, published by Ubiquity Press
This work is licensed under the Creative Commons Attribution 4.0 License.