diff --git a/src/Hamiltonians/abstract.jl b/src/Hamiltonians/abstract.jl index e95601601..36facc2ee 100644 --- a/src/Hamiltonians/abstract.jl +++ b/src/Hamiltonians/abstract.jl @@ -63,7 +63,7 @@ When extending [`AbstractFockAddress`](@ref), define a method for dimension(h::AbstractHamiltonian) = dimension(h, starting_address(h)) dimension(::AbstractHamiltonian, addr) = dimension(addr) dimension(addr::AbstractFockAddress) = dimension(typeof(addr)) -# dimension(_) = Inf # fallback +dimension(::T) where {T<:Number} = typemax(T) # e.g. integer addresses function dimension(::Type{<:BoseFS{N,M}}) where {N,M} return number_conserving_bose_dimension(N,M) diff --git a/src/Interfaces/hamiltonians.jl b/src/Interfaces/hamiltonians.jl index be7515b83..553e179e4 100644 --- a/src/Interfaces/hamiltonians.jl +++ b/src/Interfaces/hamiltonians.jl @@ -18,14 +18,15 @@ For available implementations see [`Hamiltonians`](@ref Main.Hamiltonians). # Interface -Methods that need to be implemented: +Basic interface methods to implement: -* [`num_offdiagonals(::AbstractHamiltonian, address)`](@ref) -* [`get_offdiagonal(::AbstractHamiltonian, address, chosen::Integer)`](@ref) -* [`diagonal_element(::AbstractHamiltonian, address)`](@ref) * [`starting_address(::AbstractHamiltonian)`](@ref) +* [`diagonal_element(::AbstractHamiltonian, address)`](@ref) +* [`num_offdiagonals(::AbstractHamiltonian, address)`](@ref) +* [`get_offdiagonal(::AbstractHamiltonian, address, chosen::Integer)`](@ref) (optional, see + below) -Optional methods to implement: +Optional additional methods to implement: * [`LOStructure(::Type{typeof(lo)})`](@ref LOStructure): defaults to `AdjointUnknown` * [`dimension(::AbstractHamiltonian, addr)`](@ref Main.Hamiltonians.dimension): defaults to @@ -34,7 +35,7 @@ Optional methods to implement: `typeof(starting_address(h))` * [`momentum(::AbstractHamiltonian)`](@ref Main.Hamiltonians.momentum): no default -Provides: +Provides the following functions and methods: * [`offdiagonals`](@ref): iterator over reachable off-diagonal matrix elements * [`random_offdiagonal`](@ref): function to generate random off-diagonal matrix element @@ -46,6 +47,11 @@ Provides: * [`BasisSetRep`](@ref Main.Hamiltonians.sparse): construct a basis set repesentation * [`sparse`](@ref Main.Hamiltonians.sparse), [`Matrix`](@ref): construct a (sparse) matrix representation +Alternatively to the above, [`offdiagonals`](@ref) can be implemented instead of +[`get_offdiagonal`](@ref). Sometimes this can be done efficiently. In this case +[`num_offdiagonals`](@ref) should provide an upper bound on the number of elements obtained +when iterating [`offdiagonals`](@ref). + See also [`Hamiltonians`](@ref Main.Hamiltonians), [`Interfaces`](@ref). """ abstract type AbstractHamiltonian{T} end diff --git a/test/Hamiltonians.jl b/test/Hamiltonians.jl index 0e4c56956..495b61376 100644 --- a/test/Hamiltonians.jl +++ b/test/Hamiltonians.jl @@ -13,12 +13,11 @@ function exact_energy(ham) end """ - test_hamiltonian_interface(H, addr) + test_hamiltonian_interface(H, addr=starting_address(H)) The main purpose of this test function is to check that all required methods are defined. """ -function test_hamiltonian_interface(H) - addr = starting_address(H) +function test_hamiltonian_interface(H, addr=starting_address(H)) @testset "$(nameof(typeof(H)))" begin @testset "*, mul!, and call" begin v = DVec(addr => eltype(H)(2.0)) @@ -59,11 +58,23 @@ function test_hamiltonian_interface(H) end end @testset "dimension" begin - @test dimension(H) ≥ dimension(H, starting_address(H)) + @test dimension(H) == dimension(H, starting_address(H)) + @test dimension(addr) ≥ dimension(H, addr) end @testset "allowed_address_type" begin + @test starting_address(H) isa allowed_address_type(H) @test addr isa allowed_address_type(H) end + @testset "offdiagonals" begin + # `get_offdiagonal` is not mandatory but `offdiagonals` is + if length(methods(get_offdiagonal, (typeof(H), typeof(add), Int))) > 0 + ods = [get_offdiagonal(H, addr, i) for i in 1:num_offdiagonals(H, addr)] + @test ods == offdiagonals(H, addr) + end + number_of_nonzero_offdiagonals = length(DVec(offdiagonals(H, addr))) + @test number_of_nonzero_offdiagonals ≤ num_offdiagonals(H, addr) + @test number_of_nonzero_offdiagonals ≤ dimension(H, addr) + end end end @@ -139,6 +150,7 @@ end HubbardReal1D(BoseFS((1, 2, 3, 4)); u=1.0, t=2.0), HubbardReal1DEP(BoseFS((1, 2, 3, 4)); u=1.0, t=2.0, v_ho=3.0), HubbardMom1D(BoseFS((6, 0, 0, 4)); t=1.0, u=0.5), + HubbardMom1D(OccupationNumberFS(6, 0, 0, 4); t=1.0, u=0.5), HubbardMom1D(BoseFS((6, 0, 0, 4)); t=1.0, u=0.5 + im), ExtendedHubbardReal1D(BoseFS((1,0,0,0,1)); u=1.0, v=2.0, t=3.0), HubbardRealSpace(BoseFS((1, 2, 3)); u=[1], t=[3]),