Module BitStringAddresses.jl
This module contains the implementations of BitString and various Fock addresses. The addresses serve as a basis for a Hamiltonian.
While there are not restrictions on the type of address a Hamiltonian uses, Rimu provides implementations for Bosonic, Fermionic, and mixed Fock States.
When implementing a new address type, care must be taken to make them space-efficient and stack-allocated - avoid using arrays to represent your addresses at all costs!
Fock addresses
Rimu provides a variety of address implementations (see below) that should make it straightforward to implement efficient Hamiltonians.
Currently, only single-particle operators are implemented directly (via move_particle). To implement multi-particle operators, convert the address to the onr representation and back. See the implementation of HubbardMom1D for an example.
Fock address API
Rimu.BitStringAddresses.AbstractFockAddress — TypeAbstractFockAddressSupertype representing a Fock state.
Rimu.BitStringAddresses.SingleComponentFockAddress — TypeSingleComponentFockAddress{M}A type representing a single component Fock state with M modes.
Implemented subtypes: BoseFS, FermiFS.
Supported functionality
Rimu.BitStringAddresses.BoseFS — TypeBoseFS{N,M,S} <: SingleComponentFockAddressAddress type that represents a Fock state of N spinless bosons in M modes by wrapping a bitstring of type S <: BitString.
Constructors
BoseFS{N,M}(bs::BitString): Unsafe constructor. Does not check whether the number of particles inbsis equal toN.BoseFS(::BitString): Automatically determineNandM. This constructor is not type stable!BoseFS{[N,M,S]}(onr): CreateBoseFS{N,M}fromonrrepresentation. This is efficient as long as at leastNis provided.
See also: SingleComponentFockAddress, FermiFS, BitString.
Rimu.BitStringAddresses.FermiFS — TypeFermiFS{N,M,S} <: SingleComponentFockAddressAddress type that represents a Fock state of N fermions of the same spin in M modes by wrapping a bitstring of type S <: BitString.
Constructors
FermiFS{N,M}(bs::BitString): Unsafe constructor. Does not check whether the number of particles inbsis equal toN.FermiFS(::BitString): Automatically determineNandM. This constructor is not type stable!FermiFS{[N,M,S]}(onr): CreateFermiFS{N,M}fromonrrepresentation. This is efficient as long as at leastNis provided.
See also: SingleComponentFockAddress, BoseFS, BitString.
Rimu.BitStringAddresses.BoseFS2C — TypeBoseFS2C{NA,NB,M,AA,AB} <: AbstractFockAddressAddress type that constructed with two BoseFS{N,M,S}. It represents a Fock state with two components, e.g. two different species of bosons with particle number NA from species S and particle number NB from species B. The number of modes M is expected to be the same for both components.
Rimu.BitStringAddresses.CompositeFS — TypeCompositeFS(addresses::SingleComponentFockAddress...) <: AbstractFockAddressUsed to encode addresses for multi-component models. All component addresses are expected have the same number of modes.
See also: BoseFS, FermiFS, SingleComponentFockAddress, num_modes
Rimu.BitStringAddresses.num_particles — Functionnum_particles(::Type{<:AbstractFockAddress})
num_particles(::AbstractFockAddress)Number of particles represented by address.
Rimu.BitStringAddresses.num_modes — Functionnum_modes(::Type{<:AbstractFockAddress})
num_modes(::AbstractFockAddress)Number of modes represented by address.
Rimu.BitStringAddresses.num_components — Functionnum_components(::Type{<:AbstractFockAddress})
num_components(::AbstractFockAddress)Number of components in address.
Rimu.BitStringAddresses.onr — Functiononr(bs)Compute and return the occupation number representation of the bit string address bs as an SVector{M,Int32}, where M is the number of modes.
onr(add::AbstractFockAddress, geom::LatticeGeometry)Returns the occupation number representation of a Fock state address as an SArray with the shape of the lattice geometry geom. For composite addresses, a tuple of onrs is returned.
Rimu.BitStringAddresses.near_uniform — Functionnear_uniform(BoseFS{N,M})
near_uniform(BoseFS{N,M,S}) -> bfs::BoseFS{N,M,S}Create bosonic Fock state with near uniform occupation number of M modes with a total of N particles. Specifying the bit address type S is optional.
Examples
julia> near_uniform(BoseFS{7,5,BitString{14}})
BoseFS{7,5}((2, 2, 1, 1, 1))
julia> near_uniform(BoseFS{7,5})
BoseFS{7,5}((2, 2, 1, 1, 1))Rimu.BitStringAddresses.occupied_modes — Functionoccupied_modes(::SingleComponentFockAddress)Iterate over all occupied modes in an address. Iterates BoseFSIndex for BoseFS, and an integers for FermiFS.
Example
julia> b = BoseFS((1,5,0,4));
julia> foreach(println, occupied_modes(b))
[1, 1, 0]
[5, 2, 2]
[4, 4, 9]julia> f = FermiFS((1,1,0,1,0,0,1));
julia> foreach(println, occupied_modes(f))
1
2
4
7Rimu.BitStringAddresses.is_occupied — Functionis_occupied(::SingleComponentFockAddress, i)Return true if index i points to an occupied mode.
Rimu.BitStringAddresses.num_occupied_modes — Functionnum_occupied_modes(::SingleComponentFockAddress)Get the number of occupied modes in address. Equivalent to length(occupied_modes(address)), or the number of non-zeros in its ONR representation.
Example
julia> num_occupied_modes(BoseFS((1, 0, 2)))
2
julia> num_occupied_modes(FermiFS((1, 1, 1, 0)))
3Rimu.BitStringAddresses.find_occupied_mode — Functionfind_occupied_mode(::SingleComponentFockAddress, k)Find the k-th occupied mode in address. Returns BoseFSIndex for BoseFS, and an integer for FermiFS. When unsuccessful it returns zero.
Example
julia> find_occupied_mode(BoseFS((1, 0, 2)), 2)
3-element Rimu.BitStringAddresses.BoseFSIndex with indices SOneTo(3):
2
3
3
julia> find_occupied_mode(FermiFS((1, 1, 1, 0)), 2)
2Rimu.BitStringAddresses.find_mode — Functionfind_mode(::SingleComponentFockAddress, i)Find the i-th mode in address. Returns BoseFSIndex for BoseFS, and an integer index for FermiFS. Does not check bounds.
julia> find_mode(BoseFS((1, 0, 2)), 2)
3-element Rimu.BitStringAddresses.BoseFSIndex with indices SOneTo(3):
0
2
2
julia> find_mode(FermiFS((1, 1, 1, 0)), 2)
2Rimu.BitStringAddresses.move_particle — Functionmove_particle(add::SingleComponentFockAddress, i, j) -> nadd, αMove particle from mode i to mode j. Returns the new Fock state address nadd and amplitude α. Equivalent to
\[a^{\dagger}_i a_j |\mathrm{add}\rangle \to α|\mathrm{nadd}\rangle\]
Note that the modes in BoseFS are indexed by BoseFSIndex, while the ones in FermiFS are indexed by integers (see example below). For illegal moves where α == 0 the value of nadd is undefined.
Example
julia> b = BoseFS((1, 1, 3, 0))
BoseFS{5,4}((1, 1, 3, 0))
julia> i = find_occupied_mode(b, 2)
3-element Rimu.BitStringAddresses.BoseFSIndex with indices SOneTo(3):
1
2
2
julia> j = find_mode(b, i.mode + 1)
3-element Rimu.BitStringAddresses.BoseFSIndex with indices SOneTo(3):
3
3
4
julia> move_particle(b, i, j)
(BoseFS{5,4}((1, 0, 4, 0)), 2.0)
julia> move_particle(b, j, j)
(BoseFS{5,4}((1, 1, 3, 0)), 3.0)julia> f = FermiFS((1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0))
FermiFS{7,12}((1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0))
julia> i = find_occupied_mode(f, 2)
6
julia> move_particle(f, i, i + 1)
(FermiFS{7,12}((1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0)), 0.0)
julia> move_particle(f, i, i - 1)
(FermiFS{7,12}((1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0)), 1.0)
julia> move_particle(f, i, 12)
(FermiFS{7,12}((1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1)), -1.0)BitStrings
The atomic addresses, BoseFS and FermiFS, are implemented as bitstrings. Using this approach over an occupation number representation makes the addresses much more space-efficient. The API for BitStrings is as follows.
BitString API
Rimu.BitStringAddresses.BitString — TypeBitString{B,N,T<:Unsigned}Type for storing bitstrings of static size. Holds B bits in N chunks, where each chunk is of type T.
N is chosen automatically to accommodate B bits as efficiently as possible.
Constructors
BitString{B,N,T}(::SVector{N,T}): unsafe constructor. Does not check for ghost bits.BitString{B,N,T}(i::T): as above, but setsias the rightmost chunk.BitString{B}(::Integer): Convert integer toBitString. Integer is truncated to the correct number of bits.
Rimu.BitStringAddresses.num_bits — Functionnum_bits(::Type{<:BitString})
num_bits(s::BitString)Total number of bits stored in bitstring.
Rimu.BitStringAddresses.num_chunks — Functionnum_chunks(::Val{B})Determine the number and type of chunks needed to store B bits.
num_chunks(::Type{<:BitString})
num_chunks(s::BitString)Number of chunks in bitstring. Equivalent to length(chunks(s)).
Rimu.BitStringAddresses.chunk_type — Functionchunk_type(::Type{<:BitString})
chunk_type(s::BitString)Type of unsigned integer used to store the chunks.
Rimu.BitStringAddresses.chunk_bits — Functionchunks_bits(::Type{<:BitString}, i)
chunks_bits(s, i)Number of bits in the i-th chunk of s.
Rimu.BitStringAddresses.top_chunk_bits — Functiontop_chunk_bits(::Type{<:BitString})
top_chunk_bits(s::BitString)Number of bits stored in top chunk. Equivalent to chunk_bits(s, 1).