Advanced operator usage and custom Hamiltonians
Rimu
can be used to work with custom Hamiltonians and observables that are user-defined and not part of the Rimu.jl
package. To make this possible and reliable, Rimu
exposes a number of interfaces and provides helper functions to test compliance with the interfaces through the submodule Rimu.InterfaceTests
, see Interface tests. This section covers the relevant interfaces, the interface functions as well as potentially useful helper functions.
In order to define custom Hamiltonians or observables it is useful to know how the operator type hierarchy works in Rimu
. For an example of how to implement custom Hamiltonians that are not part of the Rimu.jl
package, see RimuLegacyHamiltonians.jl
.
Operator type hierarchy
Rimu
offers a hierarchy of abstract types that define interfaces with different requirements for operators:
AbstractHamiltonian <: AbstractOperator <: AbstractObservable
The different abstract types have different requirements and are meant to be used for different purposes.
AbstractHamiltonian
s are fully featured models that define a Hilbert space and a linear operator over a scalar field. They can be passed as a Hamiltonian intoProjectorMonteCarloProblem
orExactDiagonalizationProblem
.AbstractOperator
andAbstractObservable
are supertypes ofAbstractHamiltonian
with less stringent conditions. They are useful for defining observables that can be used in a three-waydot
product, or passed as observables into aReplicaStrategy
that can be inserted with the keywordreplica_strategy
into aProjectorMonteCarloProblem
.
Hamiltonians interface
Behind the implementation of a particular model is a more abstract interface for defining Hamiltonians. If you want to define a new model you should make use of this interface. A new model Hamiltonian should subtype to AbstractHamiltonian
and implement the relevant methods.
Rimu.Interfaces.AbstractHamiltonian
— TypeAbstractHamiltonian{T} <: AbstractOperator{T}
Supertype that provides an interface for linear operators over a linear space with scalar type T
that are suitable for FCIQMC (with ProjectorMonteCarloProblem
). Indexing is done with addresses (typically not integers) from an address space that may be large (and will not need to be completely generated).
AbstractHamiltonian
instances operate on vectors of type AbstractDVec
from the module DictVectors
and work well with addresses of type AbstractFockAddress
from the module BitStringAddresses
. The type works well with the external package KrylovKit.jl.
For available implementations see Hamiltonians
.
Interface
Mandatory methods to implement:
starting_address(op::AbstractHamiltonian)
operator_column(op, address)
returns anAbstractOperatorColumn
AbstractOperatorColumn
has its own interface methods:
parent_operator(column)
returns the operator of the columndiagonal_element(column)
returns the diagonal element of the columnnum_offdiagonals(column)
(this can be an upper bound) returns the number of off-diagonal elements in the columnoffdiagonals(column)
returns an object representing the off-diagonal elements of the columnrandom_offdiagonal(column)
returns a random off-diagonal element in the column
Optional additional methods to implement:
LOStructure(::Type{typeof(op)})
: defaults toAdjointUnknown
has_random_offdiagonal(::Type{typeof(op)})
: defaults totrue
.has_iterable_offdiagonals(::Type{typeof(op)})
: defaults totrue
.dimension(::AbstractHamiltonian, addr)
: defaults to dimension of address spaceallows_address_type(h::AbstractHamiltonian, type)
: defaults totype :< typeof(starting_address(h))
momentum(::AbstractHamiltonian)
: no default
Alternative Interface (deprecated)
starting_address(::AbstractHamiltonian)
diagonal_element(op, address)
num_offdiagonals(op, address)
andget_offdiagonal(op, address, chosen)
oroffdiagonals(op, address)
Provides the following functions and methods:
ProjectorMonteCarloProblem(H)
: use this Hamiltonian for FCIQMCExactDiagonalizationProblem(H)
: use this Hamiltonian for exact diagonalization*(H, v)
: deterministic matrix-vector multiply (allocating)H(v)
: equivalent toH * v
.mul!(w, H, v)
: mutating matrix-vector multiply.dot(x, H, v)
: computex⋅(H*v)
minimizing allocations.H[address1, address2]
: indexing withgetindex()
- mostly for testing purposes (slow!)BasisSetRepresentation
: construct a basis set representationsparse
,Matrix
: construct a (sparse) matrix representation
See also Hamiltonians
, Interfaces
, AbstractOperatorColumn
, AbstractOperator
, AbstractObservable
.
Rimu.Interfaces.starting_address
— Functionstarting_address(h::AbstractHamiltonian)
starting_address(column::AbstractOperatorColumn)
Return the starting address for the Hamiltonian h
, or for the column
.
Example
julia> address = BoseFS((3, 2, 1));
julia> H = HubbardMom1D(address);
julia> address == starting_address(H)
true
Part of the AbstractHamiltonian
interface. See also AbstractOperatorColumn
.
Rimu.Interfaces.operator_column
— Functionoperator_column(operator::AbstractOperator, address) -> column <: AbstractOperatorColumn
*(o::AbstractOperator, a::AbstractFockAddress) -> column
Return a (lazy) object representing the column of operator
given by address
. In quantum notation, the column
represents the object
\[ Ĥ|α⟩ = ∑ᵦ|β⟩⟨β|Ĥ|α⟩,\]
where $α$ is the address
and $β$ represents all reachable addresses with nonzero matrix element $⟨β|Ĥ|α⟩$ of the operator
$Ĥ$. Columns iterate over pairs address => matrix_element
.
For more information and the definition of an interface see AbstractOperatorColumn
.
Example
julia> address = BoseFS(0,1,0);
julia> H = HubbardReal1D(address; u=6.0);
julia> column = H * address # construct column with `*` operator
HubbardReal1D(fs"|0 1 0⟩"; u=6.0, t=1.0) * fs"|0 1 0⟩"
julia> operator_column(H, address) == column
true
julia> diagonal_element(column) == column[address] # access elements with `getindex`
true
julia> DVec(column) # materialise as a `DVec`
DVec{BoseFS{1, 3, BitString{3, 1, UInt8}},Float64} with 2 entries, style = IsDeterministic{Float64}()
fs"|1 0 0⟩" => -1.0
fs"|0 0 1⟩" => -1.0
Part of the AbstractHamiltonian
interface. See also AbstractOperatorColumn
, parent_operator
, starting_address
, diagonal_element
, offdiagonals
, num_offdiagonals
, random_offdiagonal
.
Rimu.Interfaces.AbstractOperatorColumn
— TypeAbstractOperatorColumn{A,T,O}
Abstract type for operator columns returned by operator_column(operator, address)
or operator * address
. The type parameters represent the address type (A
), the eltype (T
), and the type of the operator (O
).
In quantum notation, the column represents the object
\[ Ĥ|α⟩ = ∑ᵦ|β⟩⟨β|Ĥ|α⟩,\]
where $α$ is the address
and $β$ represents all reachable addresses with nonzero matrix element $⟨β|Ĥ|α⟩$ of the operator
$Ĥ$.
Interface
The default constructor for AbstractOperatorColumn
is operator_column(operator, address)
. The interface for AbstractOperatorColumn
is defined by the following functions:
parent_operator(c::AbstractOperatorColumn)
- returns theoperator
,starting_address(c::AbstractOperatorColumn)
- returns the startingaddress
,diagonal_element(c::AbstractOperatorColumn)
- returns the diagonal element of the columnc
, $⟨α|Ĥ|α⟩$, where $α$ is the starting address,num_offdiagonals(c::AbstractOperatorColumn)
- returns an upper bound on the number of off-diagonal elements in the columnc
,offdiagonals(c::AbstractOperatorColumn)
- returns an object representing the off-diagonal elements of the columnc
,random_offdiagonal(c::AbstractOperatorColumn)
- returns a random off-diagonal element in the columnc
.
Methods for these functions need to be implemented for a new type of AbstractOperator
.
Part of the AbstractHamiltonian
and AbstractOperator
interface. See also operator_column
.
Rimu.Interfaces.parent_operator
— Methodparent_operator(c::AbstractOperatorColumn)
Return the operator of the column c
. This is the operator that was used to construct the column with operator_column
.
Part of the AbstractHamiltonian
and AbstractOperator
interface. See also AbstractOperatorColumn
and operator_column
.
Rimu.Interfaces.diagonal_element
— Functiondiagonal_element(column::AbstractOperatorColumn)
diagonal_element(ham, address) # (deprecated)
Compute the diagonal matrix element of the linear operator ham
at address address
, where column = operator_column(ham, address)
.
Example
julia> H = HubbardMom1D(BoseFS(3, 2, 1));
julia> column = operator_column(H, starting_address(H));
julia> diagonal_element(column)
8.666666666666664
Part of the AbstractHamiltonian
interface. See also AbstractOperatorColumn
and operator_column
.
Rimu.Interfaces.offdiagonals
— Functionoffdiagonals(column::AbstractOperatorColumn)
offdiagonals(h::AbstractHamiltonian, address) # (deprecated)
Return an iterator over nonzero off-diagonal matrix elements of h
in the same column as address
. Will iterate over pairs (newaddress, matrixelement)
or newaddress => matrixelement
.
Example
julia> address = BoseFS(3,2,1);
julia> H = HubbardReal1D(address);
julia> h = offdiagonals(H * address)
6-element Rimu.Hamiltonians.Offdiagonals{BoseFS{6, 3, BitString{8, 1, UInt8}}, Float64, HubbardReal1D{Float64, BoseFS{6, 3, BitString{8, 1, UInt8}}, 1.0, 1.0}}:
(fs"|2 3 1⟩", -3.0)
(fs"|2 2 2⟩", -2.449489742783178)
(fs"|3 1 2⟩", -2.0)
(fs"|4 1 1⟩", -2.8284271247461903)
(fs"|4 2 0⟩", -2.0)
(fs"|3 3 0⟩", -1.7320508075688772)
Part of the AbstractHamiltonian
interface. See also AbstractOperatorColumn
and operator_column
.
Rimu.Interfaces.random_offdiagonal
— Functionrandom_offdiagonal(column::AbstractOperatorColumn)
random_offdiagonal(ham::AbstractHamiltonian, address) # deprecated
-> newaddress, probability, matrixelement
Generate a single random excitation, i.e. choose from one of the accessible off-diagonal elements in the column ham * address
. The result is a tuple of the new address newaddress
, the probability of this excitation probability
, and the matrix element matrixelement
of the excitation.
Part of the AbstractHamiltonian
interface. See also AbstractOperatorColumn
and operator_column
.
Rimu.Interfaces.num_offdiagonals
— Functionnum_offdiagonals(column::AbstractOperatorColumn)
num_offdiagonals(ham, address) # (deprecated)
Compute the number of number of reachable configurations from address address
, where column = operator_column(ham, address)
. If necessary, this may be an upper bound.
Example
julia> H = HubbardMom1D(BoseFS(3, 2, 1));
julia> column = operator_column(H, starting_address(H));
julia> num_offdiagonals(column)
10
Part of the AbstractHamiltonian
interface. See also AbstractOperatorColumn
and operator_column
.
Rimu.Interfaces.get_offdiagonal
— Functionnewadd, me = get_offdiagonal(ham, address, chosen) # (deprecated)
Compute value me
and new address newadd
of a single (off-diagonal) matrix element in a Hamiltonian ham
. The off-diagonal element is in the same column as address address
and is indexed by integer index chosen
.
Example
julia> addr = BoseFS(3, 2, 1);
julia> H = HubbardMom1D(addr);
julia> get_offdiagonal(H, addr, 3)
(BoseFS{6,3}(2, 1, 3), 1.0)
Part of the AbstractHamiltonian
interface.
The following functions come with default implementations, but may be customized.
Rimu.Interfaces.LOStructure
— TypeLOStructure(op::AbstractHamiltonian)
LOStructure(typeof(op))
Return information about the structure of the linear operator op
. LOStructure
is used as a trait to speficy symmetries or other properties of the linear operator op
that may simplify or speed up calculations. Implemented instances are:
IsDiagonal()
: The operator is diagonal.IsHermitian()
: The operator is complex and Hermitian or real and symmetric.AdjointKnown()
: The operator is not Hermitian, but itsadjoint
is implemented.AdjointUnknown()
:adjoint
for this operator is not implemented.
Part of the AbstractHamiltonian
interface.
In order to define this trait for a new linear operator type, define a method for LOStructure(::Type{<:MyNewLOType}) = …
.
Rimu.Hamiltonians.dimension
— Functiondimension(h::AbstractHamiltonian, addr=starting_address(h))
dimension(h::AbstractObservable, addr)
dimension(addr::AbstractFockAddress)
dimension(::Type{<:AbstractFockAddress})
Return the estimated dimension of Hilbert space. May return a BigInt
number.
When called on an address or address type, the dimension of the linear space spanned by the address type is returned. When called on an AbstractHamiltonian
, an upper bound on the dimension of the matrix representing the Hamiltonian is returned.
Examples
julia> dimension(OccupationNumberFS(1,2,3))
16777216
julia> dimension(HubbardReal1D(OccupationNumberFS(1,2,3)))
28
julia> dimension(BoseFS{200,100})
1386083821086188248261127842108801860093488668581216236221011219101585442774669540
julia> Float64(ans)
1.3860838210861882e81
Part of the AbstractHamiltonian
interface. See also BasisSetRepresentation
.
Extended Help
The default fallback for dimension
called on an AbstractHamiltonian
is to return the dimension of the address space, which provides an upper bound. For new Hamiltonians a tighter bound can be provided by defining a custom method.
When extending AbstractHamiltonian
, define a method for the two-argument form dimension(h::MyNewHamiltonian, addr)
. For number-conserving Hamiltonians, the function Hamiltonians.number_conserving_dimension
may be useful.
When extending AbstractFockAddress
, define a method for dimension(::Type{MyNewFockAddress})
.
Rimu.Interfaces.has_adjoint
— Functionhas_adjoint(op)
Return true if adjoint
is defined on op
.
Part of the AbstractHamiltonian
interface.
See also LOStructure
.
Rimu.Interfaces.has_iterable_offdiagonals
— Functionhas_iterable_offdiagonals(operatortype::Type)::Bool
Return true
if the operator's columns have iterable offdiagonals
.
Example
julia> using Rimu.Interfaces
julia> h = HubbardReal1D(BoseFS(1,2,3));
julia> has_iterable_offdiagonals(typeof(h))
true
When extending the interface, implement a method for has_iterable_offdiagonals(::Type{<:MyNewOperator})
.
Part of the AbstractHamiltonian
interface. See also AbstractOperatorColumn
and operator_column
.
Rimu.Interfaces.has_random_offdiagonal
— Functionhas_random_offdiagonal(operatortype::Type)::Bool
Return true
if the operator's columns have a random_offdiagonal
method implemented.
Example
julia> using Rimu.Interfaces
julia> h = HubbardReal1D(BoseFS(1,2,3));
julia> has_random_offdiagonal(typeof(h))
true
When extending the interface, implement a method for Rimu.Interfaces.has_random_offdiagonal(::Type{<:MyNewOperator})
.
Part of the AbstractHamiltonian
interface. See also AbstractOperatorColumn
and operator_column
.
Rimu.Interfaces.allows_address_type
— Functionallows_address_type(operator, addr_or_type)
Returns true
if addr_or_type
is a valid address for operator
. Otherwise, returns false
.
Part of the AbstractHamiltonian
interface.
Extended help
Defaults to addr_or_type <: typeof(starting_address(operator))
. Overload this function if the operator can be used with addresses of different types.
Base.eltype
— Functioneltype(op::AbstractObservable)
Return the type of the elements of the operator. This can be a vector value. For the underlying scalar type use scalartype
.
Part of the AbstractObservable
interface.
New types do not have to implement this method explicitly. An implementation is provided based on the AbstractObservable
's type parameter.
VectorInterface.scalartype
— Functionscalartype(op::AbstractObservable)
Return the type of the underlying scalar field of the operator. This may be different from the element type of the operator returned by eltype
, which can be a vector value.
Part of the AbstractObservable
interface.
New types do not have to implement this method explicitly. An implementation is provided based on the AbstractObservable
's type parameter.
LinearAlgebra.mul!
— FunctionLinearAlgebra.mul!(w::AbstractDVec, op::AbstractOperator, v::AbstractDVec)
In place multiplication of op
with v
and storing the result in w
. The result is returned. Note that w
needs to have a valtype
that can hold a product of instances of eltype(op)
and valtype(v)
. Moreover, the StochasticStyle
of w
needs to be <:IsDeterministic
.
Part of the AbstractOperator
interface.
Rimu.Interfaces.undo_transform
— Functionundo_transform(ham::AbstractHamiltonian, operator)
Modify the operator
in a way that undoes the transform that was applied to ham
. See TransformUndoer
.
This interface relies on unexported functionality, including
Base.adjoint
— Functionadjoint(::LOStructure, op::AbstractObservable)
Represent the adjoint of an AbstractObservable
. Extend this method to define custom adjoints.
LinearAlgebra.dot
— Functiondot(w, op::AbstractObservable, v)
Evaluate w⋅op(v)
minimizing memory allocations.
Rimu.Hamiltonians.AbstractOffdiagonals
— TypeAbstractOffdiagonals{A,T}<:AbstractVector{Tuple{A,T}}
Iterator over new address and matrix elements for reachable off-diagonal matrix elements of a linear operator.
See Offdiagonals
for a default implementation.
Methods to define
offdiagonals(h, a)::AbstractOffdiagonals
: This function is used to construct the correct type of offdiagonals for a given combination of Hamiltonianh
and Fock addressa
.Base.getindex(::AbstractOffdiagonals, i)
: should be equivalent toget_offdiagonal(h, a, i)
.Base.size(::AbstractOffdiagonals)
: should be equivalent tonum_offdiagonals(h, a)
.
See also offdiagonals
, AbstractHamiltonian
, AbstractOperator
.
Rimu.Hamiltonians.Offdiagonals
— TypeOffdiagonals(h, address) <: AbstractOffdiagonals
Iterator over new address and matrix element for reachable off-diagonal matrix elements of linear operator h
from address address
. Represents an abstract vector containing the non-zero off-diagonal matrix elements of the column of h
indexed by address
. To construct this iterator use offdiagonals
.
This is the default implementation of AbstractOffdiagonals
defined in terms of num_offdiagonals
and get_offdiagonal
.
See also offdiagonals
, AbstractHamiltonian
, AbstractOperator
.
Rimu.Hamiltonians.check_address_type
— Functioncheck_address_type(h::AbstractObservable, addr_or_type)
Throw an ArgumentError
if addr_or_type
is not compatible with h
, otherwise return true
. Acceptable arguments are either an address or an address type, or a tuple or array thereof.
See also allows_address_type
.
Rimu.Hamiltonians.number_conserving_dimension
— Functionnumber_conserving_dimension(address <: AbstractFockAddress)
Return the dimension of the Fock space spanned by the address type assuming particle number conservation.
See also number_conserving_bose_dimension
, number_conserving_fermi_dimension
, dimension
.
Rimu.Hamiltonians.number_conserving_bose_dimension
— Functionnumber_conserving_bose_dimension(n, m)
Return the dimension of the number-conserving Fock space for n
bosons in m
modes: binomial(n + m - 1, n)
.
See also number_conserving_fermi_dimension
, number_conserving_dimension
.
Rimu.Hamiltonians.number_conserving_fermi_dimension
— Functionnumber_conserving_fermi_dimension(n, m)
Return the dimension of the number-conserving Fock space for n
fermions in m
modes: binomial(m, n)
.
See also number_conserving_bose_dimension
, number_conserving_dimension
.
Rimu.Interfaces.OffdiagonalsOperatorColumn
— TypeOffdiagonalsOperatorColumn <: AbstractOperatorColumn
Default column, using the deprecated interface with offdiagonals(op, address)
and diagonal_element(op, address)
.
See also operator_column
.
Operator and observable interface
Rimu.Interfaces.AbstractObservable
— TypeAbstractObservable{T}
Most permissive supertype for operators in the type hierarchy:
AbstractHamiltonian{T} <: AbstractOperator{T} <: AbstractObservable{T}
AbstractObservable
provides an interface for operators that can appear in a three-way dot product dot(x, op, y)
with two vectors of type AbstractDVec
. The result is a value of type T
, which is also returned by the eltype
function. This may be a vector type associated with a scalar type returned by the scalartype
function.
The AbstractObservable
type is useful for defining observables that can be calculated in the context of a ProjectorMonteCarloProblem
using AllOverlaps
.
Interface
Basic interface methods to implement:
Optional additional methods to implement:
VectorInterface.scalartype(op)
: defaults toeltype(eltype(op))
LOStructure(::Type{typeof(op)})
: defaults toAdjointUnknown
has_random_offdiagonal(::Type{typeof(op)})
: defaults tofalse
has_iterable_offdiagonals(::Type{typeof(op)})
: defaults tofalse
See also AbstractOperator
, AbstractHamiltonian
, Interfaces
.
Rimu.Interfaces.AbstractOperator
— TypeAbstractOperator{T} <: AbstractObservable{T}
Supertype that provides an interface for linear operators over a linear space with elements of type T
(returned by eltype
) and general (custom type) indices called 'addresses'.
AbstractOperator
instances operate on vectors of type AbstractDVec
from the module DictVectors
and work well with addresses of type AbstractFockAddress
from the module BitStringAddresses
.
The defining feature of an AbstractOperator
is that it can be applied to a vector with mul!(y, op, x)
and that three-way dot products can be calculated with dot(x, op, y)
.
The AbstractOperator
type is useful for defining operators that are not necessarily Hamiltonians, but that can be used in the context of a ProjectorMonteCarloProblem
as observable operators in a ReplicaStrategy
, e.g. for defining correlation functions. In contrast to AbstractHamiltonian
s, AbstractOperator
s do not need to have a starting_address
. Moreover, the eltype
of an AbstractOperator
can be a vector value whereas AbstractHamiltonian
s require a scalar eltype
.
AbstractHamiltonian{T} <: AbstractOperator{T} <: AbstractObservable{T}
The AbstractOperator
type is part of the AbstractObservable
hierarchy. It is more restrictive than AbstractObservable
in that it requires the interface for the generation of diagonal and off-diagonal elements.
For concrete implementations see Hamiltonians
. In order to implement a Hamiltonian for use in ProjectorMonteCarloProblem
or ExactDiagonalizationProblem
use the type AbstractHamiltonian
instead.
Interface
Mandatory methods to implement:
allows_address_type(op, type)
operator_column(op, address)
diagonal_element(column)
num_offdiagonals(column)
(this can be an upper bound)offdiagonals(column)
required for deterministic operations, seehas_iterable_offdiagonals(::Type{typeof(op)})
below
Optional additional methods to implement:
VectorInterface.scalartype(ham)
: defaults toeltype(eltype(ham))
LOStructure(::Type{typeof(ham)})
: defaults toAdjointUnknown
dimension(ham, addr)
: defaults to dimension of address spaceundo_transform(ham, op)
: the default implementation returnsop
.has_iterable_offdiagonals(::Type{typeof(op)})
: defaults totrue
has_random_offdiagonal(::Type{typeof(op)})
: defaults tofalse
. If this set totrue
, the methodrandom_offdiagonal(column)
needs to be implemented.
Alternative Interface (deprecated)
If the number of non-zero matrix elements that can be reached from any address is known, and they can be separately generated:
allows_address_type(op, type)
diagonal_element(op, address)
num_offdiagonals(op, address)
andget_offdiagonal(op, address, chosen)
oroffdiagonals
returning anAbstractVector
object.
In order to calculate observables efficiently, it may make sense to implement custom methods for Interfaces.dot_from_right(x, ham, y)
and LinearAlgebra.mul!(y, ham, x)
.
See also AbstractHamiltonian
, Interfaces
.
Hamiltonian wrapper interface
ModifiedHamiltonian
provides an interface for wrapping Hamiltonians into a new type with modified properties. Fully implemented Hamiltonian wrappers are documented in the Hamiltonians section.
Rimu.Hamiltonians.ModifiedHamiltonian
— Typeabstract type ModifiedHamiltonian{T} <: AbstractHamiltonian{T} end
Abstract type for defining wrappers over AbstractHamiltonian
s that modify diagonal and off-diagonal elements via the functions modify_diagonal
and modify_offdiagonal
.
The ModifiedHamiltonian
can only be used to implement wrappers that modify the (off)-diagonals individually and cannot be used to introduce additional off-diagonal elements to the Hamiltonian.
The following need to be implemented
parent_operator
modify_diagonal
modify_offdiagonal
LOStructure(p)
andBase.adjoint
if known, defaults toAdjointUnknown
.
The following are provided:
Rimu.Interfaces.parent_operator
— Methodparent_operator(::ModifiedHamiltonian)
Return the Hamiltonian that is being modified. See ModifiedHamiltonian
.
Rimu.Hamiltonians.modify_diagonal
— Functionmodify_diagonal(ham::ModifiedHamiltonian, source, value) -> val
Modify the diagonal element value
at address source
to val
. Specifically, value = diagonal_element(operator_column(parent_operator(ham), source))
. See ModifiedHamiltonian
.
Rimu.Hamiltonians.modify_offdiagonal
— Functionmodify_offdiagonal(ham::ModifiedHamiltonian, source, dest, element) -> (addr => val)
Modify an offdiagonal element dest => element
reachable from the address source
in the parent_operator
of ham
.
Should return a Pair
of modified address addr
and modified value val
. See ModifiedHamiltonian
.
Interface tests
Helper functions that can be used for testing the various interfaces are provided in the (unexported) submodule Rimu.InterfaceTests
.
Rimu.InterfaceTests
— ModuleThe module Rimu.InterfaceTests
provides functions to test compliance with the AbstractObservable
, AbstractOperator
, and AbstractHamiltonian
interfaces. Load the module with using Rimu.InterfaceTests
.
The module exports the following functions:
Testing functions
Rimu.InterfaceTests.test_hamiltonian_interface
— Functiontest_hamiltonian_interface(h, addr=starting_address(h); kwargs...)
The main purpose of this test function is to check that all required methods of the AbstractHamiltonian
interface are defined and work as expected.
Keyword arguments
test_iterable_offdiagonals = has_iterable_offdiagonals(typeof(h))
: Iftrue
, tests that theoffdiagonals(column)
is iterable.test_random_offdiagonal = has_random_offdiagonal(typeof(h))
: Iftrue
, tests that therandom_offdiagonal(column)
is defined.
This function also tests the following properties of the Hamiltonian:
dimension(h) ≥ dimension(h, addr)
scalartype(h) === eltype(h)
- Hamiltonian action on a vector <:
AbstractDVec
starting_address
returns anallows_address_type
addressLOStructure
is one ofIsDiagonal
,IsHermitian
,AdjointKnown
- the
AbstractOperator
interface is tested - the
AbstractObservable
interface is tested
Example
julia> using Rimu.InterfaceTests
julia> test_hamiltonian_interface(HubbardRealSpace(BoseFS(2,0,3,1)));
Test Summary: | Pass Total Time
Observable interface: HubbardRealSpace | 4 4 0.0s
Test Summary: | Pass Total Time
allows_address_type | 1 1 0.0s
Test Summary: | Pass Total Time
Operator interface: HubbardRealSpace | 9 9 0.0s
Test Summary: | Pass Total Time
allows_address_type | 1 1 0.0s
Test Summary: | Pass Total Time
Hamiltonians-only tests with HubbardRealSpace | 6 6 0.0s
See also test_operator_interface
, test_observable_interface
.
Rimu.InterfaceTests.test_hamiltonian_structure
— Functiontest_hamiltonian_structure(h::AbstractHamiltonian; sizelim=20)
Test the LOStructure
of a small Hamiltonian h
by instantiating it as a sparse matrix and checking whether the structure of the matrix is constistent with the result of LOStructure(h)
and the eltype
is consistent with eltype(h)
.
This function is intended to be used in automated test for small Hamiltonians where instantiating the matrix is quick. A warning will print if the dimension of the Hamiltonian is larger than 20
.
Example
julia> using Rimu.InterfaceTests
julia> test_hamiltonian_structure(HubbardRealSpace(BoseFS(2,0,1)));
Test Summary: | Pass Total Time
structure | 4 4 0.0s
Rimu.InterfaceTests.test_observable_interface
— Functiontest_observable_interface(obs, addr)
This function tests compliance with the AbstractObservable
interface for an observable obs
at address addr
(typically <: AbstractFockAddress
) by checking that all required methods are defined.
The following properties are tested:
dot(v, obs, v)
returns a value of the same type as theeltype
of the observableLOStructure
is set consistently
Example
julia> using Rimu.InterfaceTests
julia> test_observable_interface(ReducedDensityMatrix(2), FermiFS(1,0,1,1));
Test Summary: | Pass Total Time
Observable interface: ReducedDensityMatrix | 4 4 0.0s
See also AbstractObservable
, test_operator_interface
, test_hamiltonian_interface
.
Rimu.InterfaceTests.test_operator_interface
— Functiontest_operator_interface(op, addr; kwargs...)
This function tests compliance with the AbstractOperator
interface for an operator op
at address addr
(typically <: AbstractFockAddress
) by checking that all required methods are defined.
Keyword arguments
test_iterable_offdiagonals = has_iterable_offdiagonals(typeof(op))
: Iftrue
, tests that theoffdiagonals(column)
is iterable.test_random_offdiagonal = has_random_offdiagonal(typeof(op))
: Iftrue
, tests that therandom_offdiagonal(column)
is defined.
The following properties are tested:
operator_column(op, addr)
returns acolumn
object that is subtype toAbstractOperatorColumn
If test_random_offdiagonal
is true
, tests are performed that require random_offdiagonal(column)
to be defined. If test_iterable_offdiagonals
is true
, tests are performed that require offdiagonals(column)
to be iterable.
diagonal_element(column)
returns a value of the same type as theeltype
of the operatoroffdiagonals
iteratesaddress => value
pairs of consistent type (only iftest_iterable_offdiagonals==true
)random_offdiagonal
returns a tuple with the correct types (only iftest_random_offdiagonal == true
)mul!
anddot
work as expecteddimension
returns a consistent value- the
AbstractObservable
interface is tested
Example
julia> using Rimu.InterfaceTests
julia> test_operator_interface(SuperfluidCorrelator(3), BoseFS(1, 2, 3, 1));
Test Summary: | Pass Total Time
Observable interface: SuperfluidCorrelator | 4 4 0.0s
Test Summary: | Pass Total Time
allows_address_type | 1 1 0.0s
Test Summary: | Pass Total Time
Operator interface: SuperfluidCorrelator | 9 9 0.0s
See also AbstractOperator
, test_observable_interface
, test_hamiltonian_interface
.
Utilities for harmonic oscillator models
Useful utilities for harmonic oscillator in Cartesian basis, see HOCartesianContactInteractions
and HOCartesianEnergyConservedPerDim
.
Rimu.Hamiltonians.get_all_blocks
— Functionget_all_blocks(h::Union{HOCartesianContactInteractions,HOCartesianEnergyConservedPerDim};
target_energy = nothing,
max_energy = nothing,
max_blocks = nothing,
method = :vertices,
kwargs...) -> df
Find all distinct blocks of h
. Returns a DataFrame
with columns
block_id
: index of block in order foundblock_E0
: noninteracting energy of all elements in the blockblock_size
: number of elements in the blockaddr
: first address that generates the block with e.g.BasisSetRepresentation
indices
: tuple of mode indices that allow recreation of the generating addressaddr
; in this case use e.g.BoseFS(M; indices .=> 1)
This is useful when theDataFrame
is loaded from file sinceArrow.jl
converts custom types toNamedTuple
s.t_basis
: time to generate the basis for each block
Keyword arguments:
target_energy
: only blocks with this noninteracting energy are foundmax_energy
: only blocks with noninteracting energy less than this are foundmax_blocks
: exit after finding this many blocksmethod
: Choose between:vertices
and:comb
for method of enumerating tuples of quantum numberssave_to_file=nothing
: if set then theDataFrame
recording blocks is saved after each new block is found- additional
kwargs
: passed toisapprox
for comparing block energies. Useful for anisotropic traps
Note: If h
was constructed with option block_by_level = false
then the block seeds addr
are determined by parity. In this case the blocks are not generated; t_basis
will be zero, and block_size
will be an estimate. Pass the seed addresses to BasisSetRepresentation
with an appropriate filter
to generate the blocks.
Rimu.Hamiltonians.fock_to_cart
— Functionfock_to_cart(addr, S; zero_index = true)
Convert a Fock state address addr
to Cartesian harmonic oscillator basis indices $n_x,n_y,\ldots$. These indices are bounded by S
which is a tuple of the maximum number of states in each dimension. By default the groundstate in each dimension is indexed by 0
, but this can be changed by setting zero_index = false
.
Underlying integrals for the interaction matrix elements are implemented in the following unexported functions
Rimu.Hamiltonians.four_oscillator_integral_general
— Functionfour_oscillator_integral_general(i, j, k, l; max_level = typemax(Int))
Integral of four one-dimensional harmonic oscillator functions,
\[ \mathcal{I}(i,j,k,l) = \int_{-\infty}^\infty dx \, \phi_i(x) \phi_j(x) \phi_k(x) \phi_l(x)\]
Indices i,j,k,l
start at 0
for the groundstate.
This integral has a closed form in terms of the hypergeometric $_{3}F_2$ function, and is non-zero unless $i+j+k+l$ is odd. See e.g. Titchmarsh (1948). This is a generalisation of the closed form in Papenbrock (2002), which is is the special case where $i+j == k+l$, but is numerically unstable for large arguments. Used in HOCartesianContactInteractions
and HOCartesianEnergyConservedPerDim
.
Rimu.Hamiltonians.ho_delta_potential
— Functionho_delta_potential(S, i, j; [vals])
Returns the matrix element of a delta potential at the centre of a trap, i.e. the product of two harmonic oscillator functions evaluated at the origin,
\[ v_{ij} = \phi_{\mathbf{n}_i}(0) \phi_{\mathbf{n}_j}(0)\]
which is only non-zero for even-parity states. The i
th single particle state corresponds to a $D$-tuple of harmonic oscillator indices $\mathbf{n}_i$. S
defines the bounds of Cartesian harmonic oscillator indices for each dimension. The optional keyword argument vals
allows passing pre-computed values of $\phi_i(0)$ to speed-up the calculation. The values can be calculated with log_abs_oscillator_zero
.
See also HOCartesianCentralImpurity
.
Rimu.Hamiltonians.log_abs_oscillator_zero
— Functionlog_abs_oscillator_zero(n)
Compute the logarithm of the absolute value of the $n^\mathrm{th}$ 1D harmonic oscillator function evaluated at the origin. The overall sign is determined when the matrix element is evaluated in ho_delta_potential
.
Index
Rimu.InterfaceTests
Rimu.Hamiltonians.AbstractOffdiagonals
Rimu.Hamiltonians.ModifiedHamiltonian
Rimu.Hamiltonians.Offdiagonals
Rimu.Interfaces.AbstractHamiltonian
Rimu.Interfaces.AbstractObservable
Rimu.Interfaces.AbstractOperator
Rimu.Interfaces.AbstractOperatorColumn
Rimu.Interfaces.LOStructure
Rimu.Interfaces.OffdiagonalsOperatorColumn
Base.adjoint
Base.eltype
LinearAlgebra.dot
LinearAlgebra.mul!
Rimu.Hamiltonians.check_address_type
Rimu.Hamiltonians.dimension
Rimu.Hamiltonians.fock_to_cart
Rimu.Hamiltonians.four_oscillator_integral_general
Rimu.Hamiltonians.get_all_blocks
Rimu.Hamiltonians.ho_delta_potential
Rimu.Hamiltonians.log_abs_oscillator_zero
Rimu.Hamiltonians.modify_diagonal
Rimu.Hamiltonians.modify_offdiagonal
Rimu.Hamiltonians.number_conserving_bose_dimension
Rimu.Hamiltonians.number_conserving_dimension
Rimu.Hamiltonians.number_conserving_fermi_dimension
Rimu.InterfaceTests.test_hamiltonian_interface
Rimu.InterfaceTests.test_hamiltonian_structure
Rimu.InterfaceTests.test_observable_interface
Rimu.InterfaceTests.test_operator_interface
Rimu.Interfaces.allows_address_type
Rimu.Interfaces.diagonal_element
Rimu.Interfaces.get_offdiagonal
Rimu.Interfaces.has_adjoint
Rimu.Interfaces.has_iterable_offdiagonals
Rimu.Interfaces.has_random_offdiagonal
Rimu.Interfaces.num_offdiagonals
Rimu.Interfaces.offdiagonals
Rimu.Interfaces.operator_column
Rimu.Interfaces.parent_operator
Rimu.Interfaces.parent_operator
Rimu.Interfaces.random_offdiagonal
Rimu.Interfaces.starting_address
Rimu.Interfaces.undo_transform
VectorInterface.scalartype