ExchangeParameter#
For the full reference see ExchangeParameter
ExchangeParameter is a wrap around numpy.ndarray with a number
of predefined properties, which are specific for the exchange parameter.
The full exchange parameter \(\boldsymbol{J}\) is a \(3\times3\) matrix of real numbers. It is usually separated into three parts:
Isotropic (Heisenberg) exchange (
iso):
Symmetric anisotropic exchange (
aniso):
Antisymmetric anisotropic (Dzyaloshinskii-Moriya) exchange (
dmi):
Isotropic exchange is a scalar, anisotropic part is a traceless symmetric part of the full matrix and antisymmetric part of full matrix can be described via Dzyaloshinskii-Moriya vector.
Import#
The following import statements are equivalent:
>>> # Exact import
>>> from radtools.spinham.parameter import ExchangeParameter
>>> # Explicit import
>>> from radtools.spinham import ExchangeParameter
>>> # Recommended import
>>> from radtools import ExchangeParameter
Creation#
The constructor of ExchangeParameter takes the following arguments:
matrix- the \(3 \times 3\) matrix of the exchange parameter.iso- the isotropic part of the exchange parameter.aniso- the anisotropic part of the exchange parameter.dmi- the Dzyaloshinskii-Moriya vector.
If the matrix is provided, all other parameters are ignored and corresponding
values are calculated from the matrix. If matrix is not provided,
the other parameters are used to calculate the matrix.
>>> J = ExchangeParameter(iso=1)
>>> J
ExchangeParameter(array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]]))
For the full list of constructor parameters see
ExchangeParameter documentation.
String representation#
For the exchange parameter convenient string representation is defined:
>>> print(J)
1.0000 0.0000 0.0000
0.0000 1.0000 0.0000
0.0000 0.0000 1.0000
>>> J = ExchangeParameter(dmi=(1, 1, 1))
>>> print(J)
0.0000 1.0000 -1.0000
-1.0000 0.0000 1.0000
1.0000 -1.0000 0.0000
It supports string formatting. The format is passed to print_2d_array() function internally:
>>> print(f"{J:.2f}")
0.00 1.00 -1.00
-1.00 0.00 1.00
1.00 -1.00 0.00
>>> print(f"{J:.2e}")
0.00e+00 1.00e+00 -1.00e+00
-1.00e+00 0.00e+00 1.00e+00
1.00e+00 -1.00e+00 0.00e+00
The full matrix of the exchange parameter is stored as a \(3 \times 3\) numpy.ndarray. Every other parameter is calculated from it. The examples below are grouped by the type of exchange interaction.
Full exchange matrix#
>>> J = ExchangeParameter(matrix=[[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> J.matrix
array([[1., 2., 3.],
[4., 5., 6.],
[7., 8., 9.]])
Symmetric and asymmetric part can be accessed as:
>>> J.symm_matrix
array([[1., 3., 5.],
[3., 5., 7.],
[5., 7., 9.]])
>>> J.asymm_matrix
array([[ 0., -1., -2.],
[ 1., 0., -1.],
[ 2., 1., 0.]])
For each element of the exchange matrix the following properties are defined:
>>> J.xx
1.0
>>> J.xy
2.0
>>> J.xz
3.0
>>> J.yx
4.0
>>> J.yy
5.0
>>> J.yz
6.0
>>> J.zx
7.0
>>> J.zy
8.0
>>> J.zz
9.0
Isotropic exchange#
Isotropic exchange is a scalar and it is defined as a trace of the exchange matrix divided by 3:
>>> J.iso
5.0
For isotropic exchange matrix form is defined:
>>> J.iso_matrix
array([[5., 0., 0.],
[0., 5., 0.],
[0., 0., 5.]])
Anisotropic exchange#
Note
Anisotropic exchange is a traceless part of symmetric part of full exchange matrix.
>>> J.aniso
array([[-4., 3., 5.],
[ 3., 0., 7.],
[ 5., 7., 4.]])
Anisotropic exchange is often reduced to the diagonal part, thus diagonal part and its matrix form are explicitly defined:
>>> J.aniso_diagonal
array([-4., 0., 4.])
>>> J.aniso_diagonal_matrix
array([[-4., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 4.]])
Dzyaloshinskii-Moriya interaction#
Note
Dzyaloshinskii-Moriya interaction is an antisymmetric part of full exchange matrix.
>>> J.dmi
array([-1., 2., -1.])
Matrix form of DMI is accessible via:
>>> J.dmi_matrix
array([[ 0., -1., -2.],
[ 1., 0., -1.],
[ 2., 1., 0.]])
Two useful values are defined for DMI: its module and relative strength to isotropic exchange:
>>> round(J.dmi_module, 4)
2.4495
>>> round(J.rel_dmi, 4)
0.4899
Arithmetic operations#
Arithmetic operations are defined for the exchange parameter.
They act on the full exchange matrix and return ExchangeParameter instance.
>>> J1 = ExchangeParameter(matrix=[[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> J2 = ExchangeParameter(matrix=[[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> J1 + J2
ExchangeParameter(array([[ 2., 4., 6.],
[ 8., 10., 12.],
[14., 16., 18.]]))
>>> J1 - J2
ExchangeParameter(array([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]]))
>>> 2 * J2
ExchangeParameter(array([[ 2., 4., 6.],
[ 8., 10., 12.],
[14., 16., 18.]]))
>>> J2 / 2
ExchangeParameter(array([[0.5, 1. , 1.5],
[2. , 2.5, 3. ],
[3.5, 4. , 4.5]]))
>>> J1 // 3
ExchangeParameter(array([[0., 0., 1.],
[1., 1., 2.],
[2., 2., 3.]]))
>>> J1 % 3
ExchangeParameter(array([[1., 2., 0.],
[1., 2., 0.],
[1., 2., 0.]]))
>>> -J1
ExchangeParameter(array([[-1., -2., -3.],
[-4., -5., -6.],
[-7., -8., -9.]]))
>>> abs(-J1)
ExchangeParameter(array([[1., 2., 3.],
[4., 5., 6.],
[7., 8., 9.]]))
>>> J1 == J2
True
>>> J1 != J2
False
Matrix multiplication works with instances of ExchangeParameter as well, but
it returns instance of numpy.ndarray:
>>> import numpy as np
>>> a = np.eye(3)
>>> J @ a
array([[1., 2., 3.],
[4., 5., 6.],
[7., 8., 9.]])
NumPy interface#
Array interface is defined for the exchange parameter. It aims any numpy function on the full exchange matrix.
Transpose is defined explicitly in order to return ExchangeParameter instance:
>>> J.T
ExchangeParameter(array([[1., 4., 7.],
[2., 5., 8.],
[3., 6., 9.]]))
Any other numpy function should work as expected, however it is not tested:
>>> np.sum(J)
45.0
>>> np.diag(J)
array([1., 5., 9.])
>>> np.iscomplex(J)
array([[False, False, False],
[False, False, False],
[False, False, False]])