Details¶
[This section is not meant to be a gentle introduction to lattices; it exists mainly to review the conventions used throughout the Bravais.jl
codebase.]
The direct Bravais lattice¶
A Bravais lattice in dimensions is defined, given some “primitive vectors” , to be all points where each . (There is one primitive vector for each dimension in which the lattice extends.)
We cannot address (or store information about) an infinite number of points on a computer, so instead we choose a finite number of contiguous points from our infinite lattice, and label them as the points we will consider. If we wish to emulate a system without boundary and maintain the translation symmetry of the lattice, we will implement “periodic boundary conditions” (PBC, also known as Born-von Karman boundary conditions) in all directions. Another option is to implement fully open boundary conditions (OBC), in which case the lattice is simply truncated beyond the points of the finite lattice. Yet another option is to have OBC in some dimensions and PBC in others; one example of this is cylindrical boundary conditions in a 2D system.
Let’s get a bit more mathmatical. Given positive integers along with the primitive vectors , we define a finite lattice with sites, each site given by where and . (We will refer to as the “index” of the site, and as the “site label.”)
At this point, the finite lattice only represents a subset of the original lattice sites. For the case of periodic boundary conditions, we would like to repeat our “finite” lattice, tiling it throughout the lattice such that every site of our original infinite lattice is represented by some site on our finite lattice.
We define vectors , each of which is some linear combination of the primitive vectors, such that each site on the infinite lattice can be written uniquely as , where . There will often (particularly for ) be infinitely many different ways of choosing these vectors, some of which will result in “helical” boundary conditions (in which translating the length of the lattice in one dimension also results in an offset in one or more other dimensions).
Note
On an infinite lattice, there are many possible ways of choosing the primitive vectors, and they are all equivalent to each other. On a finite lattice, however, this is no longer the case. The choice of primitive vectors will dictate how the points of the finite lattice are arranged.
The reciprocal lattice¶
The reciprocal lattice of a Bravais lattice is defined as all wave vectors satisfying for all points in the infinite Bravais lattice. In other words, we require for some . This can best be achieved by choosing the reciprocal lattice’s primitive vectors such that . Then each can be written as with . This gives , which will always satisfy the original condition . (For more details, see e.g. Ashcroft and Mermin pages 86-87.)
It is worth noting that the reciprocal of the reciprocal lattice is the direct lattice itself.
Allowed momenta¶
We will begin by studying the case in which the boundary conditions in each direction are periodic/twisted [1]. With periodic/twisted boundary conditions on a finite lattice, only certain momenta are possible in the system. After exploring the case of fully periodic/twisted boundary conditions, we will extend our reasoning to include the (somewhat simpler) case in which one or all dimensions have open boundary conditions.
Bloch’s theorem says given a periodic system, the eigenstates of any Hamiltonian can be chosen such that each is associated with a wave vector such that for every in the lattice [2]. Our goal in the following is to determine, given some boundary conditions on a finite lattice, what wave vectors are allowed.
For a Bravais lattice, there will be as many allowed momenta as there are points on the finite lattice assuming PBC in each direction. Typically, allowed momenta are given by points within the first Brillouin Zone (BZ). We want to uniquely label the allowed momenta, but for simplicity we will label them systematically without the requirement that they be in the first Brillouin Zone.
We define the “twist” values such that
for all . (For a system without any twisted boundary conditions, .) We can combine our knowledge that is in the lattice with Bloch’s theorem to give , or equivalently , for all .
We know that the ‘s must be linear combinations of the primitive vectors, so we can write them as , where each is an integer. (For periodic/twisted boundary conditions, our diagonal elements must be , the lattice extent in each direction. We will see later that for any dimension in which we have open boundary conditions, we instead have .) We will also write our wave vector in terms of fractions of the reciprocal lattice’s basis vectors: . Then,
With this, our requirement becomes
for all , where each is some nonnegative integer less than . This can also be written as a matrix equation, .
Let us assume within the Bravais.jl code, for vast simplification, that is lower triangular (i.e. only the values for which are allowed to be nonzero) [3]. We can then solve the above equation iteratively for each beginning with . Rewriting it with this assumption gives:
We then solve for to give
which holds for any dimension in which there are periodic/twisted boundary conditions.
Now we briefly consider the case of open boundary conditions. For any direction in which there is open boundary conditions, set (i.e. the corresponding row and column of the matrix must be zero) and . Then (zero momentum) is the only unique solution in that direction, as we expect.
How many allowed momenta are there in a system? For a system with fully periodic boundary conditions, it is the same as the number of sites in the finite lattice. For a system with fully open boundary conditions, there is just one allowed momentum, . More generally, the number of allowed momenta is the product over all dimensions with periodic/twisted BC’s of the number of the lattice extent in that direction. Phrased more simply, the number of allowed momenta is the product of all nonzero diagonal elements of .
For a lattice with a basis, the allowed momenta are given entirely by the underlying Bravais lattice.
As one might expect, the Bravais.jl package provides a mechanism for enumerating of the allowed momenta in a system.
[1] | Twisted boundary conditions are geometrically equivalent to periodic boundary conditions, but with the added “twist” that the wavefunction picks up a nontrivial phase when translated across the boundary. From here forward we will use the phrase PBC to refer generically to both cases. |
[2] | For details see e.g. Ashcroft and Mermin, page 134. |
[3] | This is not a significant restriction, and in many cases—i.e. all cases with non-helical boundaries—the matrix will actually be diagonal. |
Allowed total momenta¶
The above discussion considers the allowed momenta of a single particle wavefunction. In particular, for a single particle, if we translate the length of the system in the direction, we pick up a phase . More generally (i.e. in second quantization), with particle count , translating all particles the length of the system will pick up a phase . Thus, in a system where we have multiple particles, we may wish to determine the possible total momenta. We define to be the total momenta with “charge” (i.e. particle count) . (What we previously called above is now .) We first generalize the above equation for arbitrary charge:
From this we can derive a recursion relation for :
For OBC, the denominator technically blows up, but it should be obvious that .
Lattice with a basis¶
Generic lattice code¶
OK, so what do we need to determine a lattice? , , , , and the lower triangular matrix . Note for the diagonal elements that (for periodic or twisted boundary conditions) or (for open boundary conditions). For simplicity we assume that . We rely on the user implementing the lattice type to specify the concept of “nearest neighbors”, as what is meant by the th nearest neighbors depends on the details of the lattice spacing in each direction.
Here’s a table for our variables and what symbols are used in the code
Symbol | Internal variable name | Description | |
---|---|---|---|
N[i] |
dimensions(lattice)[i] |
lattice extent in each direction | |
D |
ndimensions(lattice) ` |
number of dimensions | |
N_tot |
length(lattice) |
total number of sites |
And we are going to want to be able to talk about realizations of these lattice points in real space, so the following things matter.
Symbol | Internal variable name | Description | |
---|---|---|---|
a[:,i] |
primvecs(lattice)[:,i] |
primitive vectors | |
b[:,i] |
recivecs(lattice)[:,i] |
reciprocal lattice primitive vectors |
As soon as we want to start talking about allowed momenta, the following two things matter as well.
Symbol | Internal variable name | |
---|---|---|
η[i] |
twist(lattice)[i] |
|
M[i,j] |
repeater(lattice)[i,j] |
Our basic BravaisLattice
type contains all of these things.
One important thing we’d like to be able to do is map sites on the finite lattice to/from sites on the infinite lattice.
We have a wraparound()
(and wraparound_site!
, and wraparoundη
) function, which takes a site that may or may not be on the actual finite lattice, and returns its lattice index along with the phase that it picks up. So for instance given the site , it returns the site index of along with the phase picked up when [un]wrapping the boundary conditions. As above, the phase returned is defined by
There is also a translation_operators()
method, which returns a “translation operator” (really a vector meant for mapping) for each dimension in which is nonzero (i.e. for each direction that is not OBC). So, for instance, translation_operators()[i][alpha]
returns the new site index (along with any phase picked up ) of the site such that
Wrapping condition in second quantization¶
We wish to generalize the above wrapping equation to second quantization. Note that . Using this, we get
Together, these imply
As a result of this,
when working in second quantization. (Explain this.) where is the “charge” (poorly chosen name, which should be updated.)
API Reference¶
realspace()¶
momentum() function, kdotr¶
nearest_neighbors() functions¶
Returns (via a callback) , , and , such that the relevant hopping term would be . (FIXME, I have changed this.)
Specific lattice implementations¶
Hypercubic¶
- works in any dimension
- does not double count bonds on a two-leg ladder (fixme: do we really want this?)
- when considering nearest neighbors, do we really want it to be this general? oh well, we can have subclasses that specialize it, since next-nearest neighbors will mean something different depending on dimension.