Hamiltonian

configuration file section: [hamiltonian]

Hamiltonian

The full Spin-Hamiltonian is the sum over all interactions.


Zeeman

Zeeman

### External magnetic field [T]
external_field.magnitude = 25.0
external_field.direction = [0.0, 0.0, 1.0]
spirit.hamiltonian.set_field(p_state, magnitude, direction, idx_image=-1, idx_chain=-1)

Set the (homogeneous) external magnetic field.

spirit.hamiltonian.get_field(p_state, idx_image=-1, idx_chain=-1)

Returns the magnitude and an array of shape(3) containing the direction of the external magnetic field.

void Hamiltonian_Set_Field(State *state, scalar magnitude, const scalar *direction, int idx_image = -1, int idx_chain = -1)

Set the (homogeneous) external magnetic field [T].

void Hamiltonian_Get_Field(State *state, scalar *magnitude, scalar *direction, int idx_image = -1, int idx_chain = -1)

Retrieves the external magnetic field [T].

Anisotropy

The anisotropy term is implemented in terms of three components:

Uniaxial Anisotropy

Uniaxial Anisotropy

Cubic Anisotropy

Cubic Anisotropy

### Uniaxial anisotropy constant [meV]
anisotropy.magnitude     = 0.0
anisotropy.normal        = [0.0, 0.0, 1.0]

### Cubic anisotropy constant [meV]
cubic_anisotropy = 0.0

By specifying a number of anisotropy axes via n_anisotropy, This way one or more anisotropy axes can be set for the atoms in the basis cell. Specify columns via headers: an index i and an axis Kx Ky Kz or Ka Kb Kc, as well as optionally a magnitude K. The optional column K4 can be used to also specify the cubic anisotropy on a per-atom basis.

anisotropy = """
i  Kx Ky Kz    K   K4
0   0  0  1  1.0  0.0
"""
spirit.hamiltonian.get_anisotropy(p_state, idx_image=-1, idx_chain=-1)

Get the magnetocrystalline anisotropy.

spirit.hamiltonian.set_anisotropy(p_state, magnitude, normal, idx_image=-1, idx_chain=-1)

Set the (homogeneous) magnetocrystalline anisotropy.

void Hamiltonian_Set_Anisotropy(State *state, scalar magnitude, const scalar *normal, int idx_image = -1, int idx_chain = -1)

Set a global uniaxial anisotropy [meV].

void Hamiltonian_Get_Anisotropy(State *state, scalar *magnitude, scalar *normal, int idx_image = -1, int idx_chain = -1)

Retrieves the uniaxial anisotropy [meV].

Biaxial Anisotropy

Biaxial Anisotropy

Where for any site \(j\) the vectors \(\hat{K}_j^{(1)}\), \(\hat{K}_j^{(2)}\) and \(\hat{K}_j^{(3)} = \hat{K}_j^{(1)} \times \hat{K}_j^{(2)}\) are pairwise orthonormal.

The uniaxial anisotropy is equivalent to the biaxial anisotropy up to an offset to the total energy when setting

equivalence

The configuration uses two tables: biaxial_anisotropy_axes and biaxial_anisotropy_terms.

### Biaxial anisotropy axes (normalized)
biaxial_anisotropy_axes = """
i  k1x k1y k1z  k2x k2y k2z
0  0.0 0.0 1.0  1.0 0.0 0.0
"""
### Biaxial anisotropy terms with k [meV]
### This example is equivalent to a uniaxial anisotropy
biaxial_anisotropy_terms = """
i  n1 n2 n3    K
0   1  0  0  1.0
"""
spirit.hamiltonian.get_biaxial_anisotropy(p_state, n_indices=None, n_terms=None, idx_image=-1, idx_chain=-1)

Get the data representing the biaxial anisotropy.

spirit.hamiltonian.set_biaxial_anisotropy(p_state, magnitude, exponents, primary, secondary, n_terms=None, idx_image=-1, idx_chain=-1)

Set the (homogeneous) biaxial magnetocrystalline anisotropy.

void Hamiltonian_Set_Biaxial_Anisotropy(State *state, const scalar *magnitude, const int exponents[][3], const scalar *primary, const scalar *secondary, int n_terms, int idx_image = -1, int idx_chain = -1)

Set a global biaxial anisotropy [meV].

void Hamiltonian_Get_Biaxial_Anisotropy(State *state, int *indices, scalar primary[][3], scalar secondary[][3], int *site_p, int n_indices, scalar *magnitude, int exponents[][3], int n_terms, int idx_image = -1, int idx_chain = -1)

Retrieves the biaxial anisotropy [meV].

Pair interactions

Heisenberg exchange

Exchange

Dzyaloshinskii–Moriya Interaction (DMI)

DMI

where it is important to note that <ij> denotes the unique pairs of interacting spins i and j. Consequently, pair-wise interaction parameters always mean energy per unique pair <ij> (i.e., not per neighbour).

Pair-wise interactions are typically handled in terms of (isotropic) neighbour shells:

### Exchange: number of shells and constants [meV / unique pair]
Jij = [10.0, 1.0]

### DMI: number of shells and constants [meV / unique pair]
Dij = [6.0, 0.5]
### Chirality of DM vectors (+/-1=bloch, +/-2=neel)
dmi_chirality = 2

You may alternatively input pair interaction explicitly as a table, giving you more granular control over the system and the ability to specify non-isotropic interactions.

### Pairs
pairs = """
i j   da db dc    Jij   Dij  Dijx Dijy Dijz
0 0    1  0  0   10.0   6.0   1.0  0.0  0.0
0 0    0  1  0   10.0   6.0   0.0  1.0  0.0
0 0    0  0  1   10.0   6.0   0.0  0.0  1.0
"""

Leaving out either exchange or DMI in the pairs is allowed and columns can be placed in arbitrary order. Note that instead of specifying the DM-vector as Dijx Dijy Dijz, you may specify it as Dija Dijb Dijc if you prefer. You may also specify the magnitude separately as a column Dij, but note that if you do, the vector (e.g. Dijx Dijy Dijz) will be normalized. If the Jij or Dij keywords used for shells are present the associated columns in this table will be ignored. This allows combining neighbour shell interactions with an anisotropic part.

spirit.hamiltonian.CHIRALITY_BLOCH = 1

DMI Bloch chirality type for neighbour shells

spirit.hamiltonian.CHIRALITY_NEEL = 2

DMI Neel chirality type for neighbour shells

spirit.hamiltonian.CHIRALITY_BLOCH_INVERSE = -1

DMI Bloch chirality type for neighbour shells with opposite sign

spirit.hamiltonian.CHIRALITY_NEEL_INVERSE = -2

DMI Neel chirality type for neighbour shells with opposite sign

spirit.hamiltonian.set_dmi(p_state, n_shells, D_ij, chirality=1, idx_image=-1, idx_chain=-1)

Set the Dzyaloshinskii-Moriya interaction in terms of neighbour shells.

spirit.hamiltonian.set_exchange(p_state, n_shells, J_ij, idx_image=-1, idx_chain=-1)

Set the Exchange interaction in terms of neighbour shells.

SPIRIT_CHIRALITY_BLOCH 1

Bloch chirality.

SPIRIT_CHIRALITY_NEEL 2

Neel chirality.

SPIRIT_CHIRALITY_BLOCH_INVERSE -1

Bloch chirality, inverted DM vectors.

SPIRIT_CHIRALITY_NEEL_INVERSE -2

Neel chirality, inverted DM vectors.

void Hamiltonian_Set_DMI(State *state, int n_shells, const scalar *dij, int chirality = SPIRIT_CHIRALITY_BLOCH, int idx_image = -1, int idx_chain = -1)

Set the Dzyaloshinskii-Moriya interaction in terms of neighbour shells [meV].

void Hamiltonian_Get_DMI_Shells(State *state, int *n_shells, scalar *dij, int *chirality, int idx_image = -1, int idx_chain = -1)

Retrieves the Dzyaloshinskii-Moriya interaction in terms of neighbour shells.

Note: if the interactions were specified as pairs, this function will retrieve n_shells=0.

int Hamiltonian_Get_DMI_N_Pairs(State *state, int idx_image = -1, int idx_chain = -1)

Returns the number of Dzyaloshinskii-Moriya interaction pairs.

void Hamiltonian_Set_Exchange(State *state, int n_shells, const scalar *jij, int idx_image = -1, int idx_chain = -1)

Set the exchange interaction in terms of neighbour shells [meV].

void Hamiltonian_Get_Exchange_Shells(State *state, int *n_shells, scalar *jij, int idx_image = -1, int idx_chain = -1)

Retrieves the exchange interaction in terms of neighbour shells.

Note: if the interactions were specified as pairs, this function will retrieve n_shells=0.

int Hamiltonian_Get_Exchange_N_Pairs(State *state, int idx_image = -1, int idx_chain = -1)

Returns the number of exchange interaction pairs.

void Hamiltonian_Get_Exchange_Pairs(State *state, int idx[][2], int translations[][3], scalar *Jij, int idx_image = -1, int idx_chain = -1)

Two-Site Anisotropy

Two-Site Anisotropy

The Two-Site Anisotropy interaction covers the symmetric, traceless part of the two-site interaction tensor. It is specified in terms of the symmetry reduced Cartesian coordinates in a table. If one of the diagonal entries is omitted it will be computed from the other two to ensure that the trace of the tensor vanishes.

Warning

This interaction can overlap with the Heisenberg exchange, if \(K_{ij}^{xx} + K_{ij}^{yy} + K_{ij}^{zz} \neq 0\).

### Two Site Anisotropy in meV per pair
two_site_anisotropy = """
i j   da db dc   Kijxx  Kijyy  Kijzz  Kijyz  Kijxz  Kijxy
0 0    1  0  0    -1.0    0.5    0.5    0.0    0.0    0.0
0 0    0  1  0     0.5   -1.0    0.5    0.0    0.0    0.0
0 0    0  0  1     0.5    0.5   -1.0    0.0    0.0    0.0
"""

Not yet implemented

Not yet implemented

Dipole-Dipole Interaction

Dipole-Dipole Interaction

Via the keyword ddi_method the method employed to calculate the dipole-dipole interactions is specified.

  `none`   -  Dipole-Dipole interactions are neglected
  `fft`    -  Uses a fast convolution method to accelerate the calculation (RECOMMENDED)
  `cutoff` -  Lets only spins within a maximal distance of 'ddi_radius' interact
  `fmm`    -  Uses the Fast-Multipole-Method (NOT YET IMPLEMENTED!)

If the cutoff-method has been chosen the cutoff-radius can be specified via ddi_radius. Note: If ddi_radius < 0 a direct summation (i.e. brute force) over the whole system is performed. This is very inefficient and only encouraged for very small systems and/or unit-testing/debugging.

If the boundary conditions are periodic ddi_n_periodic_images specifies how many images are taken in the respective direction. Note: The images are appended on both sides (the edges get filled too) i.e. 1 0 0 → one image in +a direction and one image in -a direction

If the boundary conditions are open in a lattice direction and sufficiently many periodic images are chosen, zero-padding in that direction can be skipped. This improves the speed and memory footprint of the calculation, but comes at the cost of a very slight asymmetry in the interactions (decreasing with increasing periodic images). If ddi_pb_zero_padding is set to 1, zero-padding is performed - even if the boundary condition is periodic in a direction. If it is set to 0, zero-padding is skipped.

### Dipole-dipole interaction caclulation method
### (none, fft, fmm, cutoff)
ddi_method               = 'fft'

### DDI number of periodic images (fft and fmm) in (a b c)
ddi_n_periodic_images    = [4, 4, 4]

### DDI cutoff radius (if cutoff is used)
ddi_radius               = 0.0

ddi_pb_zero_padding      = 1.0
spirit.hamiltonian.DDI_METHOD_NONE = 0

Dipole-dipole interaction: do not calculate

spirit.hamiltonian.DDI_METHOD_FFT = 1

Dipole-dipole interaction: use FFT convolutions

spirit.hamiltonian.DDI_METHOD_CUTOFF = 3

Dipole-dipole interaction: use a direct summation with a cutoff radius

spirit.hamiltonian.get_ddi(p_state, idx_image=-1, idx_chain=-1)

Returns a dictionary, containing information about the used ddi settings

spirit.hamiltonian.set_ddi(p_state, ddi_method, n_periodic_images=[4, 4, 4], radius=0.0, pb_zero_padding=True, idx_image=-1, idx_chain=-1)

Set the dipolar interaction calculation method.

  • ddi_method: one of the integers defined above

  • n_periodic_images: the number of periodical images in the three translation directions, taken into account when boundaries in the corresponding direction are periodical

  • radius: the cutoff radius for the direct summation method

  • pb_zero_padding: if True zero padding is used for periodical directions

SPIRIT_DDI_METHOD_NONE 0

Do not use dipolar interactions.

SPIRIT_DDI_METHOD_FFT 1

Use fast Fourier transform (FFT) convolutions.

SPIRIT_DDI_METHOD_CUTOFF 3

Use a direct summation with a cutoff radius.

void Hamiltonian_Set_DDI(State *state, int ddi_method, int n_periodic_images[3], scalar cutoff_radius = 0, bool pb_zero_padding = true, int idx_image = -1, int idx_chain = -1)

Configure the dipole-dipole interaction

  • ddi_method: see integers defined above

  • n_periodic_images: how many repetition of the spin configuration to append along the translation directions [a, b, c], if periodical boundary conditions are used

  • cutoff_radius: the distance at which to stop the direct summation, if used

  • pb_zero_padding: if True zero padding is used even for periodical directions

void Hamiltonian_Get_DDI(State *state, int *ddi_method, int n_periodic_images[3], scalar *cutoff_radius, bool *pb_zero_padding, int idx_image = -1, int idx_chain = -1)

Retrieves the dipole-dipole interaction configuration.

  • ddi_method: see integers defined above

  • n_periodic_images: how many repetitions of the spin configuration to append along the translation directions [a, b, c], if periodical boundary conditions are used

  • cutoff_radius: the distance at which to stop the direct summation, if method_cutoff is used

  • pb_zero_padding: if True zero padding is used even for periodical directions

Quadruplet Interaction

Quadruplet Interaction

Quadruplets are specified in meV per unique quadruplet <ijkl>.

### Quadruplets in meV per unique quadruplet <ijkl>
quadruplets = """
i    j  da_j  db_j  dc_j    k  da_k  db_k  dc_k    l  da_l  db_l  dc_l    Q
0    0  1     0     0       0  0     1     0       0  0     0     1       3.0
"""

Columns for these may also be placed in arbitrary order.

Not yet implemented

Not yet implemented

Custom Interaction

The Hamiltonian implementation is modular, so custom interactions can be easily implemented. See Custom Interaction for details.