Spin Hamiltonian

Tutorial tasks

  • Create a spin Hamiltonian of the orthorhombic ferromagnet with three magnetic axes (easy, medium and hard).

  • Change convention of the spin Hamiltonian. Inspect how (if?) the parameters are changing when you do so.

  • Add some magnetic field to the Hamiltonian. Check the values of the Hamiltonian's parameters that store the magnetic field.

  • Add magnetic dipole-dipole interaction. Test both energy and distance cut-offs. Which parameters of the spin Hamiltonian store magnetic dipole-dipole interaction?

magnopy.SpinHamiltonian is the main class that stores the spin Hamiltonian in magnopy.

It is created on some crystal, which was discussed in the previous section, and adds interaction parameters to it.

Creating a Hamiltonian

An empty spin Hamiltonian is created from three objects

  • cell

  • atoms

  • convention

import numpy as np
import magnopy

# Cubic cell with a = 1
cell = np.eye(3)

# One atom per unit cell
atoms = dict(
    names=["Fe"],
    positions=[[0.0, 0.0, 0.0]],
    spins=[2.5],
    g_factors=[2],
)

# Convention
convention = magnopy.Convention(
    multiple_counting=True, spin_normalized=False, c1=1, c21=1, c22=1 / 2
)

# Create a Hamiltonian
spinham = magnopy.SpinHamiltonian(cell=cell, atoms=atoms, convention=convention)

Adding parameter to the Hamiltonian

Now everything is ready to add some parameters to the spin Hamiltonian. Magnopy stores the parameters in the form that closely resembles mathematical form of the spin Hamiltonian, which can be found in Spin Hamiltonian page (see "Expanded form").

Magnopy supports up to four-spin terms with full tensors of the interaction parameters. For the purpose of this tutorial we will focus on the first three terms of the expanded form.

For each term of the spin Hamiltonian there are two functions defined, that add and remove a parameter from the Hamiltonian. For example, to add an isotropic exchange parameter between two different cites with the bond along the first lattice vector use

spinham.add_22(alpha=0, beta=0, nu=(1, 0, 0), parameter=np.eye(3))

Note several things:

  • alpha and beta are indices of the lists in atoms. In that example they both point to the first atom.

  • Due to the translation symmetry of the Hamiltonian it is enough to specify all parameters for some chosen unit cell. This unit cell is commonly labeled as (0, 0, 0). Index alpha specifies the first atom, that is in (0, 0, 0) unit cell. Index beta specify the second atom, that is understood to be located in the unit cell specified by nu. In the example above second atom is from (1, 0, 0) unit cell.

  • Any parameter for the term that involves two spins is a 3x3 matrix. An isotropic parameter in the matrix form is a diagonal matrix with all diagonal elements being the same.

To add on-site anisotropy use

spinham.add_21(alpha=0, parameter=np.diag([-0.1, -0.2, -0.2]))

To check what parameters you have in the spin Hamiltonian use the property, that is defined for each term of the expanded form. For example for two-spins/two-sites term

for alpha, beta, nu, parameter in spinham.p22:
    print(alpha, beta, nu)
    print(parameter)
0 0 (1, 0, 0)
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
0 0 (-1, 0, 0)
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]

Visualizing

Note

This functionality of magnopy is experimental.

One can visualize on-site (involves one site) and two-spin/two-sites parameters with magnopy with magnopy.experimental.plot_spinham()

pe1, pe2 = magnopy.experimental.plot_spinham(
    spinham, distance_digits=3, _sphinx_gallery_fix=True
)

This function returns two instances of magnopy.PlotlyEngine. First one is for the on-site parameters

Hint

Hover over the magnetic sites to see the values of parameters.

Click on the legend to hide some of the elements.

pe1.show(axes_visible=False)


Adn second one with all the exchange bonds

Hint

Double-click on some element of the legend to hide all other elements.

pe2.show(axes_visible=False)


If you add some Dzyaloshinskii–Moriya interaction, then DMI vectors are displayed as well

spinham.add_22(
    alpha=0,
    beta=0,
    nu=(0, 1, 0),
    parameter=magnopy.converter22.from_dmi(dmi=(0.5, 0, 0))
    + magnopy.converter22.from_iso(iso=1),
)

_, pe2 = magnopy.experimental.plot_spinham(
    spinham, distance_digits=3, _sphinx_gallery_fix=True
)


pe2.show(axes_visible=False)


Changing convention

All parameters that are added to the Hamiltonian are expected to be compliant with the Hamiltonian's convention. The latter can always be checked with

spinham.convention.summary()
custom convention where
  * Bonds are counted multiple times in the sum;
  * Spin vectors are not normalized;
  * c1 = 1.0;
  * c21 = 1.0;
  * c22 = 0.5;
  * Undefined c31 factor;
  * Undefined c32 factor;
  * Undefined c33 factor;
  * Undefined c41 factor;
  * Undefined c421 factor;
  * Undefined c422 factor;
  * Undefined c43 factor;
  * Undefined c44 factor.

Once the parameters are added to the Hamiltonian there is an option of changing the convention. Magnopy will recompute all the parameters in the way, that the Hamiltonian will describe the same physical system.

new_convention = magnopy.Convention.get_predefined(name="GROGU")

spinham.convention = new_convention

Adding magnetic field

Due to the design choices that were made in magnopy, external magnetic field takes the form of the one-spin/one-site parameter (c1, add_1, remove_1). To save the effort of converting the vector of magnetic field to the parameter every time, magnopy has a method that is convenient to use. For example, to add an external magnetic field directed along the y axis with the value of 1.42 Tesla use

spinham.add_magnetic_field(h=(0.0, 1.42, 0.0))

Magnetic field is stored in the form of the one-spin/one-site parameter

pe1, pe2 = magnopy.experimental.plot_spinham(
    spinham, distance_digits=3, _sphinx_gallery_fix=True
)


pe1.show(axes_visible=False)


Adding magnetic dipole-dipole interaction

Magnetic dipole-dipole interaction can be written as a two-spin/two-sites parameter. To save the burden of manual conversion in every use, magnopy has a pre-defined method that adds magnetic dipole-dipole interaction to the spin Hamiltonian.

This interaction is of the long range. Currently magnopy only implements its inclusion by the cut-off value.

  • Cut-off by distance: all interaction with the distance that is shorter than cut-off are added

spinham.add_dipole_dipole(R_cut=2)

Magnetic dipole dipole interaction modifies two-spins/two-sites parameters

_, pe2 = magnopy.experimental.plot_spinham(
    spinham, distance_digits=3, _sphinx_gallery_fix=True
)


pe2.show(axes_visible=False, legend_position="left")


  • Cut-off by parameter value (in meV): all interactions that are larger than the cut-off are added.

# Technically this line adds the dipole dipole term for the second time as we did not
# create the new Hamiltonian, but used the one from above. Do not do that, do not be like
# us.
spinham.add_dipole_dipole(E_cut=0.5)

See magnopy.SpinHamiltonian.add_dipole_dipole() for more details.

Arithmetic operations

Mathematical form of the spin Hamiltonian involves a lot of summation. One would like to easily sum two Hamiltonians and get a Hamiltonian with combined effects.

Magnopy supports addition and subtraction of two Hamiltonians. Moreover, it supports multiplication of the Hamiltonian by any number.

Important

For summation and subtraction the Hamiltonians shall be defined on the same cell and atoms.

Hint

To get an independent instance of spin Hamiltonian with the same cell, atoms and convention, but with no parameters you can use magnopy.SpinHamiltonian.get_empty().

For example, imagine that you created a Hamiltonian with some set of parameters and you would like to optimize spin directions on it and then get energy contributions of different terms. This can be done as

# Get exchange term
spinham_exchange = magnopy.SpinHamiltonian(
    cell=cell, atoms=atoms, convention=convention
)

spinham_exchange.add_22(alpha=0, beta=0, nu=(1, 0, 0), parameter=np.eye(3))

# Now get a Zeeman term
spinham_zeeman = spinham_exchange.get_empty()
spinham_zeeman.add_magnetic_field(h=(1.42, 0, 0))

# Next get magnetic dipole-dipole term
spinham_dd = spinham_exchange.get_empty()
spinham_dd.add_dipole_dipole(R_cut=20)

# Finally get full Hamiltonian
spinham_full = spinham_exchange + spinham_zeeman + spinham_dd

Now spinham_full can be used to optimize energy and get spin_direction of the local minima (covered in the next sections), then obtained spin_directions can be used with each individual term to compute their contribution.

Total running time of the script: (0 minutes 1.044 seconds)

Gallery generated by Sphinx-Gallery