Source code for qlinks.models.spin_one_xy

from __future__ import annotations

from dataclasses import dataclass

from qlinks.lattice import BoundaryCondition, ChainLattice
from qlinks.models.base import (
    HamiltonianBuilderName,
    HamiltonianModelBase,
    HamiltonianTermSpec,
    validate_builder_name,
)
from qlinks.operators import (
    LocalSquareValueDiagonalOperator,
    LocalValueDiagonalOperator,
    SpinOneXYBondOperator,
    UpdateSpinOneXYBondOperator,
)
from qlinks.variables import LocalSpace, VariableLayout


[docs] @dataclass(frozen=True) class SpinOneXYChainModel(HamiltonianModelBase): """ Spin-1 XY chain in the S^z product basis. Local basis: m_i in {-1, 0, +1} Hamiltonian: H = J_xy * sum_<ij> (S^x_i S^x_j + S^y_i S^y_j) = J_xy/2 * sum_<ij> (S^+_i S^-_j + S^-_i S^+_j) No constraints are imposed at this stage. """ length: int boundary_condition: BoundaryCondition | str = BoundaryCondition.OPEN j_xy: complex = 1.0 h_z: complex = 0.0 d_z: complex = 0.0 def _make_lattice(self) -> ChainLattice: return ChainLattice( self.length, boundary_condition=self.boundary_condition, ) def _make_layout(self) -> VariableLayout: return VariableLayout.from_lattice_sites( self.lattice, LocalSpace.spin_one(), )
[docs] def make_constraints( self, layout: VariableLayout | None = None, ): return ()
[docs] def make_sectors( self, layout: VariableLayout | None = None, ): return ()
[docs] def make_kinetic_operators( self, layout: VariableLayout | None = None, *, builder: HamiltonianBuilderName = "sparse", ) -> tuple[object, ...]: validate_builder_name(builder) if layout is None: layout = self.layout if builder == "sparse": return tuple( SpinOneXYBondOperator( layout=layout, lattice=self.lattice, link_id=int(link_id), coefficient=self.j_xy, ) for link_id in self.lattice.link_ids ) if builder == "optimized": return tuple( UpdateSpinOneXYBondOperator( layout=layout, lattice=self.lattice, link_id=int(link_id), coefficient=self.j_xy, ) for link_id in self.lattice.link_ids ) raise NotImplementedError( "SpinOneXYChainModel currently supports kinetic terms only for " "builder='sparse' or builder='optimized'." )
[docs] def make_potential_operators( self, layout: VariableLayout | None = None, *, builder: HamiltonianBuilderName = "sparse", ) -> tuple[object, ...]: validate_builder_name(builder) if layout is None: layout = self.layout operators: list[object] = [] if builder not in ("sparse", "optimized"): if self.h_z == 0 and self.d_z == 0: return () raise NotImplementedError( "SpinOneXYChainModel currently supports potential terms only for " "builder='sparse' or builder='optimized'." ) for site_id in self.lattice.site_ids: variable_index = int(layout.site_variable_index(int(site_id))) if self.h_z != 0: operators.append( LocalValueDiagonalOperator( layout=layout, variable_index=variable_index, coefficient=self.h_z, name="spin_one_zeeman_z", ) ) if self.d_z != 0: operators.append( LocalSquareValueDiagonalOperator( layout=layout, variable_index=variable_index, coefficient=self.d_z, name="spin_one_single_ion_anisotropy", ) ) return tuple(operators)
[docs] def make_operators( self, layout: VariableLayout | None = None, *, builder: HamiltonianBuilderName = "sparse", ) -> tuple[object, ...]: return ( *self.make_kinetic_operators(layout, builder=builder), *self.make_potential_operators(layout, builder=builder), )
[docs] def make_terms( self, layout: VariableLayout, *, builder: HamiltonianBuilderName = "sparse", ) -> tuple[HamiltonianTermSpec, ...]: kinetic_operators = self.make_kinetic_operators( layout, builder=builder, ) potential_operators = self.make_potential_operators( layout, builder=builder, ) terms = [ HamiltonianTermSpec.from_operators( name="kinetic", operators=kinetic_operators, kind="kinetic", ), ] if len(potential_operators) > 0: terms.append( HamiltonianTermSpec.from_operators( name="potential", operators=potential_operators, kind="potential", ) ) return tuple(terms)