Note
Go to the end to download the full example code.
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:
alphaandbetaare indices of the lists inatoms. 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). Indexalphaspecifies the first atom, that is in(0, 0, 0)unit cell. Indexbetaspecify the second atom, that is understood to be located in the unit cell specified bynu. 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)