2. Lattice translations¶
fh_comm works with integer lattices \(\Lambda = (\mathbb{Z}_{/L})^n\) in arbitrary dimension \(n\), assuming periodic boundary conditions. As such, the lattice corrdinates of an operator must be integers. Nevertheless, other lattice structures, like triangular lattices, are supported as well by embedding them in a three-dimensional integer lattice.
[1]:
import fh_comm as fhc
The following utility function “wraps” the coordinates according to the periodic boundary conditions:
[2]:
fhc.periodic_wrap((13, -2, 1), (10, 10, 10))
[2]:
(3, 8, 1)
The SubLattice class implements a sublattice by specifying its basis vectors. The input basis is automatically transformed to an equivalent basis with smallest-possible entries:
[3]:
sublatt = fhc.SubLattice([[1, 1], [5, 2]])
print(sublatt.basis)
[[ 1 1]
[ 2 -1]]
Some utility functions for sublattices:
[4]:
sublatt.contains([2, 0])
[4]:
False
[5]:
sublatt.nearest_point([2, 0])
[5]:
(2, 1)
Sublattices are used to specify translation-invariant Hamiltonians of the form
where \(\Lambda'\) is a sublattice and \(h^{\text{loc}}\) a local operator; \(h^{\text{loc}}_i\) denotes the same operator shifted by lattice vector \(i\).
Computing the commutator of two such Hamiltonians can then be achieved via the relation
where the commutator on the right only needs to be evaluated once, setting \(i = 0\) without loss of generality. This functionality is implemented by the function commutator_translation (see below).
As demonstration, we define two operators and compute their commutator, both without and with lattice translations.
[6]:
h = fhc.HoppingOp((0, 0), (1, 0), 0, 0.25)
n = fhc.NumberOp((3, 1), 0, 1.0)
The usual commutator is zero, since the operators act on disjoint sites:
[7]:
print(fhc.commutator(h, n))
<zero op>
However, when using shifted copies according to the sublattice, the commutator becomes non-zero:
[8]:
print(fhc.commutator_translation(h, n, sublatt))
(0.25) g_{(0, 0), (1, 0), up}