Source code for radtools.crystal.properties

from math import pi

import numpy as np
from tqdm import tqdm

__all__ = ["dipole_dipole_energy", "dipole_dipole_interaction"]

CONSTANT = 1.25663706212 * 9.2740100783**2 * 6.241509074 / 1000 / 4 / pi


[docs] def dipole_dipole_energy(magnetic_centres, progress_bar=True, normalize=True): r""" Computes magnetic dipole-dipole energy. This function computes the magnetic dipole-dipole energy of the set of magnetic centres: .. math:: E = -\frac{\mu_0}{4\pi}\sum_{i > j}\frac{1}{\vert r_{ij}\vert^3}\left(3(\vec{m_i} \cdot \vec{r_{ij}})(\vec{m_j} \cdot \vec{r_{ij}}) - (\vec{m_i}\cdot\vec{m_j})\right) Parameters ---------- magnetic_centres: (N, 2, 3) |array_like|_ List of N magnetic centres. First element along second axis is magnetic moment (in Bohr magnetons). Second element along second axis if position (in Angstrom). progress_bar : bool, default True Whether to show progressbar. normalize : bool, default True Whether to normalize energy to the number of magnetic centres. Returns ------- energy : float Dipole-dipole energy of the system of ``magnetic_centres``. Normalized to the number of magnetic centres N. See Also -------- dipole_dipole_interaction : between two sets of magnetic centres. """ magnetic_centres = np.array(magnetic_centres) energy = 0 if progress_bar: for_range = tqdm(range(len(magnetic_centres) - 1)) else: for_range = range(len(magnetic_centres) - 1) N = len(magnetic_centres) for i in for_range: m_i = magnetic_centres[i, 0] r_i = magnetic_centres[i, 1] r_ij = magnetic_centres[i + 1 :, 1] - r_i r_ij_norm = np.linalg.norm(r_ij, axis=1) r_ij_norm_5 = (r_ij.T / r_ij_norm**5).T first_term = np.sum( r_ij_norm_5.T * np.diag(magnetic_centres[i + 1 :, 0] @ r_ij.T), axis=1, ) second_term = np.sum((magnetic_centres[i + 1 :, 0].T) / r_ij_norm**3, axis=1) energy += m_i @ (-3 * first_term + second_term) if normalize: energy /= N return energy * CONSTANT
[docs] def dipole_dipole_interaction( magnetic_centres1, magnetic_centres2, progress_bar=True, normalize=True ): r""" Computes magnetic dipole-dipole interaction. This function computes dipole-dipole interaction between two sets of magnetic centres (:math:`mc_1` and :math:`mc_2`): .. math:: E = -\frac{\mu_0}{4\pi}\sum_{i \in mc_1, j \in mc_2}\frac{1}{\vert r_{ij}\vert^3}\left(3(\vec{m_i} \cdot \vec{r_{ij}})(\vec{m_j} \cdot \vec{r_{ij}}) - (\vec{m_i}\cdot\vec{m_j})\right) Parameters ---------- magnetic_centres1: (N, 2, 3) |array_like|_ List of N magnetic centres of the first set. First element along second axis is magnetic moment (in Bohr magnetons). Second element along second axis if position (in Angstrom). magnetic_centres2: (M, 2, 3) |array_like|_ List of M magnetic centres of the second set. First element along second axis is magnetic moment (in Bohr magnetons). Second element along second axis if position (in Angstrom). Python cycle is running along this set. progress_bar : bool, default True Whether to show progressbar. normalize : bool, default True Whether to normalize energy to the number of magnetic centres. Returns ------- energy : float Magnetic dipole-dipole interaction between ``magnetic_centres1`` and ``magnetic_centres2``. Normalized to :math:`N\cdot M`. See Also -------- dipole_dipole_energy : within one set of magnetic centres. """ magnetic_centres1 = np.array(magnetic_centres1) magnetic_centres2 = np.array(magnetic_centres2) energy = 0 if progress_bar: for_range = tqdm(range(len(magnetic_centres2) - 1)) else: for_range = range(len(magnetic_centres2) - 1) NM = len(magnetic_centres1) + len(magnetic_centres2) for i in for_range: m_i = magnetic_centres2[i, 0] r_i = magnetic_centres2[i, 1] r_ij = magnetic_centres1[:, 1] - r_i r_ij_norm = np.linalg.norm(r_ij, axis=1) r_ij_norm_5 = (r_ij.T / r_ij_norm**5).T first_term = np.sum( r_ij_norm_5.T * np.diag(magnetic_centres1[:, 0] @ r_ij.T), axis=1, ) second_term = np.sum((magnetic_centres1[:, 0].T) / r_ij_norm**3, axis=1) energy += m_i @ (-3 * first_term + second_term) if normalize: energy /= NM return energy * CONSTANT
if __name__ == "__main__": dipole_dipole_energy( [[[1, 0, 0], [0, 0, 0]], [[1, 0, 0], [1, 0, 0]]], progress_bar=False )