Source code for ttnopt.src.Hamiltonian

import math
import numpy as np

from typing import Optional, List
from ttnopt.src.Observable import Observable


[docs]class Hamiltonian: """A class for Hamiltonian. This class is used to store Hamiltonian as a List of Observable. """
[docs] def __init__( self, system_size: int, spin_size: List[str], model: str, interaction_indices: List[List[int]], interaction_coefs: List[List[float]], magnetic_field_X_indices: Optional[List[int]] = None, magnetic_field_X: Optional[List[float]] = None, magnetic_field_Y_indices: Optional[List[int]] = None, magnetic_field_Y: Optional[List[float]] = None, magnetic_field_Z_indices: Optional[List[int]] = None, magnetic_field_Z: Optional[List[float]] = None, ion_anisotropy_indices: Optional[List[int]] = None, ion_anisotropy: Optional[List[float]] = None, dzyaloshinskii_moriya_X_indices: Optional[List[List[int]]] = None, dzyaloshinskii_moriya_X: Optional[List[float]] = None, dzyaloshinskii_moriya_Y_indices: Optional[List[List[int]]] = None, dzyaloshinskii_moriya_Y: Optional[List[float]] = None, dzyaloshinskii_moriya_Z_indices: Optional[List[List[int]]] = None, dzyaloshinskii_moriya_Z: Optional[List[float]] = None, sod_X_indices: Optional[List[List[int]]] = None, sod_X: Optional[List[float]] = None, sod_Y_indices: Optional[List[List[int]]] = None, sod_Y: Optional[List[float]] = None, sod_Z_indices: Optional[List[List[int]]] = None, sod_Z: Optional[List[float]] = None, ): """ Args: system_size (int): The size of the system, indicating the number of sites or particles. spin_size (List[str]): A list of spin types or values, each corresponding to the spin state of each site in the system. model (str): The type of Hamiltonian model, which determines the specific interactions and parameters used (e.g., "Heisenberg", "Ising"). interaction_indices (List[List[int]]): A nested list of integer pairs, where each sub-list specifies two indices corresponding to sites or particles between which an interaction occurs. interaction_coefs (List[List[float]]): A nested list where each sub-list contains the coefficients for the interactions specified in `interaction_indices`, defining the strength and nature of each interaction. magnetic_field_indices (Optional[List[int]], optional): A list of site indices at which the magnetic field is applied. If None, no magnetic field is applied to any specific site. Defaults to None. magnetic_field (Optional[List[float]], optional): A list of magnetic field strengths, where each value corresponds to a specific site defined in `magnetic_field_indices`. Defaults to None. magnetic_field_axis (Optional[str], optional): The axis along which the magnetic field is applied, specified as a string ("x", "y", or "z"). Defaults to None. ion_anisotropy_indices (Optional[List[int]], optional): A list of indices specifying the sites with single-ion anisotropy. Defaults to None. ion_anisotropy (Optional[List[float]], optional): A list of single-ion anisotropy values corresponding to each site specified in `ion_anisotropy_indices`. Defaults to None. dzyaloshinskii_moriya_indices (Optional[List[List[int]]], optional): A nested list of integer pairs, where each sub-list specifies two indices corresponding to sites with Dzyaloshinskii-Moriya (DM) interaction. Defaults to None. dzyaloshinskii_moriya (Optional[List[List[float]]], optional): A list of DM interaction strengths, where each value corresponds to the pair specified in `dzyaloshinskii_moriya_indices`. Defaults to None. sod_indices (Optional[List[List[int]]], optional): A nested list of integer pairs, where each sub-list specifies two indices two indices corresponding to sites with second-order symmetric off-diagonal anisotropy interaction. Defaults to None. sod (Optional[List[List[float]]], optional): A list of SOD interaction strengths, where each value corresponds to the pair specified in `sod_indices`. Defaults to None. """ self.system_size = system_size self.spin_size = {i: spin_size[i] for i in range(self.system_size)} self.observables = [] if model == "XXZ": for i, coef in zip(interaction_indices, interaction_coefs): if all([c == 0.0 for c in coef]): continue operator_list = [] coef_list = [] if not coef[0] == 0.0: operator_list.append(["S+", "S-"]) coef_list.append(coef[0] / 2.0) operator_list.append(["S-", "S+"]) coef_list.append(coef[0] / 2.0) if not coef[0] == 0.0 and not coef[1] == 0.0: operator_list.append(["Sz", "Sz"]) coef_list.append(coef[0] * coef[1]) ob = Observable(i, operator_list, coef_list) self.observables.append(ob) if model == "XYZ": for i, coef in zip(interaction_indices, interaction_coefs): if all([c == 0.0 for c in coef]): continue operator_list = [] coef_list = [] if not coef[0] == 0.0: operator_list.append(["Sx", "Sx"]) coef_list.append(coef[0]) if not coef[1] == 0.0: operator_list.append(["Sy", "Sy"]) coef_list.append(coef[1]) if not coef[2] == 0.0: operator_list.append(["Sz", "Sz"]) coef_list.append(coef[2]) ob = Observable(i, operator_list, coef_list) self.observables.append(ob) if magnetic_field_X is not None and magnetic_field_X_indices is not None: for idx, c in zip(magnetic_field_X_indices, magnetic_field_X): if not c == 0.0: ob = Observable([idx], [["Sx"]], [-c]) self.observables.append(ob) if magnetic_field_Y is not None and magnetic_field_Y_indices is not None: for idx, c in zip(magnetic_field_Y_indices, magnetic_field_Y): if not c == 0.0: ob = Observable([idx], [["Sy"]], [-c]) self.observables.append(ob) if magnetic_field_Z is not None and magnetic_field_Z_indices is not None: for idx, c in zip(magnetic_field_Z_indices, magnetic_field_Z): if not c == 0.0: ob = Observable([idx], [["Sz"]], [-c]) self.observables.append(ob) if ion_anisotropy is not None and ion_anisotropy_indices is not None: for idx, c in zip(ion_anisotropy_indices, ion_anisotropy): if not c == 0.0: ob = Observable([idx], [["Sz2"]], [c]) self.observables.append(ob) if ( dzyaloshinskii_moriya_X is not None and dzyaloshinskii_moriya_X_indices is not None ): for i, c in zip(dzyaloshinskii_moriya_X_indices, dzyaloshinskii_moriya_X): if not c == 0.0: ob = Observable(i, [["Sy", "Sz"], ["Sz", "Sy"]], [c, -c]) self.observables.append(ob) if ( dzyaloshinskii_moriya_Y is not None and dzyaloshinskii_moriya_Y_indices is not None ): for i, c in zip(dzyaloshinskii_moriya_Y_indices, dzyaloshinskii_moriya_Y): if not c == 0.0: ob = Observable(i, [["Sz", "Sx"], ["Sx", "Sz"]], [c, -c]) self.observables.append(ob) if ( dzyaloshinskii_moriya_Z is not None and dzyaloshinskii_moriya_Z_indices is not None ): for i, c in zip(dzyaloshinskii_moriya_Z_indices, dzyaloshinskii_moriya_Z): if not c == 0.0: cc = np.array([c / 2.0j]) ob = Observable( i, [["S-", "S+"], ["S+", "S-"]], [cc.item(), -cc.item()], ) self.observables.append(ob) if sod_X is not None and sod_X_indices is not None: for i, c in zip(sod_X_indices, sod_X): if not c == 0.0: ob = Observable( i, [["Sy", "Sz"], ["Sz", "Sy"]], [c, c], ) self.observables.append(ob) if sod_Y is not None and sod_Y_indices is not None: for i, c in zip(sod_Y_indices, sod_Y): if not c == 0.0: ob = Observable( i, [["Sz", "Sx"], ["Sx", "Sz"]], [c, c], ) self.observables.append(ob) if sod_Z is not None and sod_Z_indices is not None: for i, c in zip(sod_Z_indices, sod_Z): if not c == 0.0: ob = Observable( i, [["Sx", "Sy"], ["Sy", "Sz"]], [c, c], ) self.observables.append(ob)