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 <: AbstractObservableThe different abstract types have different requirements and are meant to be used for different purposes.
- AbstractHamiltonians are fully featured models that define a Hilbert space and a linear operator over a scalar field. They can be passed as a Hamiltonian into- ProjectorMonteCarloProblemor- ExactDiagonalizationProblem.
- AbstractOperatorand- AbstractObservableare supertypes of- AbstractHamiltonianwith less stringent conditions. They are useful for defining observables that can be used in a three-way- dotproduct, or passed as observables into a- ReplicaStrategythat can be inserted with the keyword- replica_strategyinto a- ProjectorMonteCarloProblem.
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 an- AbstractOperatorColumn
AbstractOperatorColumn has its own interface methods:
- parent_operator(column)returns the operator of the column
- diagonal_element(column)returns the diagonal element of the column
- num_offdiagonals(column)(this can be an upper bound) returns the number of off-diagonal elements in the column
- offdiagonals(column)returns an object representing the off-diagonal elements of the column
- random_offdiagonal(column)returns a random off-diagonal element in the column
Optional additional methods to implement:
- LOStructure(::Type{typeof(op)}): defaults to- AdjointUnknown
- has_random_offdiagonal(::Type{typeof(op)}): defaults to- true.
- has_iterable_offdiagonals(::Type{typeof(op)}): defaults to- true.
- dimension(::AbstractHamiltonian, addr): defaults to dimension of address space
- allows_address_type(h::AbstractHamiltonian, type): defaults to- type :< typeof(starting_address(h))
- momentum(::AbstractHamiltonian): no default
Alternative Interface (deprecated)
- starting_address(::AbstractHamiltonian)
- diagonal_element(op, address)
- num_offdiagonals(op, address)and
- get_offdiagonal(op, address, chosen)or- offdiagonals(op, address)
Provides the following functions and methods:
- ProjectorMonteCarloProblem(H): use this Hamiltonian for FCIQMC
- ExactDiagonalizationProblem(H): use this Hamiltonian for exact diagonalization
- *(H, v): deterministic matrix-vector multiply (allocating)
- H(v): equivalent to- H * v.
- mul!(w, H, v): mutating matrix-vector multiply.
- dot(x, H, v): compute- x⋅(H*v)minimizing allocations.
- H[address1, address2]: indexing with- getindex()- mostly for testing purposes (slow!)
- BasisSetRepresentation: construct a basis set representation
- sparse,- 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)
truePart of the AbstractHamiltonian interface. See also AbstractOperatorColumn.
Rimu.Interfaces.operator_column — Functionoperator_column(operator::AbstractOperator, address) -> column <: AbstractOperatorColumn
*(o::AbstractOperator, a::AbstractFockAddress) -> columnReturn 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.0Part 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 the- operator,
- starting_address(c::AbstractOperatorColumn)- returns the starting- address,
- diagonal_element(c::AbstractOperatorColumn)- returns the diagonal element of the column- c, $⟨α|Ĥ|α⟩$, where $α$ is the starting address,
- num_offdiagonals(c::AbstractOperatorColumn)- returns an upper bound on the number of off-diagonal elements in the column- c,
- offdiagonals(c::AbstractOperatorColumn)- returns an object representing the off-diagonal elements of the column- c,
- random_offdiagonal(c::AbstractOperatorColumn)- returns a random off-diagonal element in the column- c.
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.666666666666664Part 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, matrixelementGenerate 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)
10Part 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 its- adjointis implemented.
- AdjointUnknown():- adjointfor 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.3860838210861882e81Part 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)::BoolReturn 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))
trueWhen 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)::BoolReturn 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))
trueWhen 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 Hamiltonian- hand Fock address- a.
- Base.getindex(::AbstractOffdiagonals, i): should be equivalent to- get_offdiagonal(h, a, i).
- Base.size(::AbstractOffdiagonals): should be equivalent to- num_offdiagonals(h, a).
See also offdiagonals, AbstractHamiltonian, AbstractOperator.
Rimu.Hamiltonians.Offdiagonals — TypeOffdiagonals(h, address) <: AbstractOffdiagonalsIterator 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 <: AbstractOperatorColumnDefault 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 to- eltype(eltype(op))
- LOStructure(::Type{typeof(op)}): defaults to- AdjointUnknown
- has_random_offdiagonal(::Type{typeof(op)}): defaults to- false
- has_iterable_offdiagonals(::Type{typeof(op)}): defaults to- false
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 AbstractHamiltonians, AbstractOperators do not need to have a starting_address. Moreover, the eltype of an AbstractOperator can be a vector value whereas AbstractHamiltonians 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, see- has_iterable_offdiagonals(::Type{typeof(op)})below
Optional additional methods to implement:
- VectorInterface.scalartype(ham): defaults to- eltype(eltype(ham))
- LOStructure(::Type{typeof(ham)}): defaults to- AdjointUnknown
- dimension(ham, addr): defaults to dimension of address space
- undo_transform(ham, op): the default implementation returns- op.
- has_iterable_offdiagonals(::Type{typeof(op)}): defaults to- true
- has_random_offdiagonal(::Type{typeof(op)}): defaults to- false. If this set to- true, the method- random_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)and
- get_offdiagonal(op, address, chosen)or- offdiagonalsreturning an- AbstractVectorobject.
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} endAbstract type for defining wrappers over AbstractHamiltonians 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)and- Base.adjointif known, defaults to- AdjointUnknown.
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) -> valModify 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)): If- true, tests that the- offdiagonals(column)is iterable.
- test_random_offdiagonal = has_random_offdiagonal(typeof(h)): If- true, tests that the- random_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_addressreturns an- allows_address_typeaddress
- LOStructureis one of- IsDiagonal,- IsHermitian,- AdjointKnown
- the AbstractOperatorinterface is tested
- the AbstractObservableinterface 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.0sSee 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.0sRimu.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 the- eltypeof the observable
- LOStructureis 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.0sSee 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)): If- true, tests that the- offdiagonals(column)is iterable.
- test_random_offdiagonal = has_random_offdiagonal(typeof(op)): If- true, tests that the- random_offdiagonal(column)is defined.
The following properties are tested:
- operator_column(op, addr)returns a- columnobject that is subtype to- AbstractOperatorColumn
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 the- eltypeof the operator
- offdiagonalsiterates- address => valuepairs of consistent type (only if- test_iterable_offdiagonals==true)
- random_offdiagonalreturns a tuple with the correct types (only if- test_random_offdiagonal == true)
- mul!and- dotwork as expected
- dimensionreturns a consistent value
- the AbstractObservableinterface 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.0sSee 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...) -> dfFind all distinct blocks of h. Returns a DataFrame with columns
- block_id: index of block in order found
- block_E0: noninteracting energy of all elements in the block
- block_size: number of elements in the block
- addr: first address that generates the block with e.g.- BasisSetRepresentation
- indices: tuple of mode indices that allow recreation of the generating address- addr; in this case use e.g.- BoseFS(M; indices .=> 1)This is useful when the- DataFrameis loaded from file since- Arrow.jlconverts custom types to- NamedTuples.
- t_basis: time to generate the basis for each block
Keyword arguments:
- target_energy: only blocks with this noninteracting energy are found
- max_energy: only blocks with noninteracting energy less than this are found
- max_blocks: exit after finding this many blocks
- method: Choose between- :verticesand- :combfor method of enumerating tuples of quantum numbers
- save_to_file=nothing: if set then the- DataFramerecording blocks is saved after each new block is found
- additional kwargs: passed toisapproxfor 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 ith 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