From 14df5969611e1dc864efb580928e19dae62fff09 Mon Sep 17 00:00:00 2001 From: waltergu Date: Wed, 1 Dec 2021 20:41:00 +0800 Subject: [PATCH] 1) Fix bugs of transfomations acting on `SimplifiedGenerator`; 2) Modify the organization of `DegreesOfFreedom` and `Frameworks`; 3) Rename `TwistedBoundyCondtion` back to `Boundary`. --- Project.toml | 2 +- src/Essentials/DegreesOfFreedom.jl | 110 +------------------- src/Essentials/Frameworks.jl | 149 +++++++++++++++++++++++----- src/QuantumLattices.jl | 8 +- test/Essentials/DegreesOfFreedom.jl | 56 +---------- test/Essentials/Frameworks.jl | 51 +++++++++- 6 files changed, 183 insertions(+), 193 deletions(-) diff --git a/Project.toml b/Project.toml index 6809c3fe..e1931ffe 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "QuantumLattices" uuid = "78ae1a1f-1d5d-5174-b61c-66e31b2346dc" authors = ["waltergu "] -version = "0.8.6" +version = "0.8.7" [deps] DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" diff --git a/src/Essentials/DegreesOfFreedom.jl b/src/Essentials/DegreesOfFreedom.jl index 8823567a..7e7ad411 100644 --- a/src/Essentials/DegreesOfFreedom.jl +++ b/src/Essentials/DegreesOfFreedom.jl @@ -3,19 +3,19 @@ module DegreesOfFreedom using MacroTools: @capture using Printf: @printf, @sprintf using StaticArrays: SVector -using ..QuantumOperators: OperatorUnit, ID, OperatorProd, OperatorSum, Operator, Operators, valuetolatextext, Transformation +using ..QuantumOperators: OperatorUnit, ID, OperatorProd, OperatorSum, Operator, Operators, valuetolatextext using ..Spatials: AbstractPID, AbstractBond, Point, Bonds, pidtype using ...Essentials: dtype using ...Interfaces: id, value, decompose, dimension, add! using ...Prerequisites: Float, atol, rtol, decimaltostr, concatenate -using ...Prerequisites.Traits: rawtype, fulltype, efficientoperations, commontype, parametertype, reparameter +using ...Prerequisites.Traits: rawtype, fulltype, efficientoperations, commontype, parametertype using ...Prerequisites.CompositeStructures: CompositeDict, CompositeTuple, NamedContainer using ...Prerequisites.VectorSpaces: CartesianVectorSpace import LinearAlgebra: ishermitian import ..QuantumOperators: idtype, script, optype import ..Spatials: pidtype, rcoord, icoord -import ...Essentials: kind, reset!, update, update! +import ...Essentials: kind, reset!, update! import ...Interfaces: id, value, rank, expand, expand!, ⊗ import ...Prerequisites.Traits: parameternames, isparameterbound, contentnames, getcontent import ...Prerequisites.VectorSpaces: shape, ndimshape @@ -27,7 +27,6 @@ export Subscript, Subscripts, SubscriptsID, @subscript_str, subscriptexpr, wildc export AbstractCoupling, Coupling, Couplings, couplingcenters, couplingpoints, couplinginternals, @couplings export Metric, OIDToTuple, Table export TermFunction, TermAmplitude, TermCouplings, TermModulate, Term, ismodulatable, abbr -export Parameters, TwistedBoundaryCondition, plain """ IID <: OperatorUnit @@ -1374,107 +1373,4 @@ Get the `attr` script of an oid, which is contained in its index. """ @inline script(::Val{attr}, oid::OID; kwargs...) where attr = script(Val(attr), oid.index; kwargs...) -""" - Parameters{Names}(values::Number...) where Names - -A NamedTuple that contain the key-value pairs. -""" -const Parameters{Names} = NamedTuple{Names, <:Tuple{Vararg{Number}}} -@inline Parameters{Names}(values::Number...) where {Names} = NamedTuple{Names}(values) -@inline @generated function update(params::Parameters; parameters...) - names = fieldnames(params) - values = [:(get(parameters, $name, getfield(params, $name))) for name in QuoteNode.(names)] - return :(Parameters{$names}($(values...))) -end - -""" - match(params₁::Parameters, params₂::Parameters; atol=atol, rtol=rtol) -> Bool - -Judge whether the second set of parameters matches the first. -""" -function Base.match(params₁::Parameters, params₂::Parameters; atol=atol, rtol=rtol) - for name in keys(params₂) - haskey(params₁, name) && !isapprox(getfield(params₁, name), getfield(params₂, name); atol=atol, rtol=rtol) && return false - end - return true -end - -""" - TwistedBoundaryCondition{Names}(values::AbstractVector{<:Number}, vectors::AbstractVector{<:AbstractVector{<:Number}}) where Names - -Boundary twist of operators. -""" -struct TwistedBoundaryCondition{Names, D<:Number, V<:AbstractVector} <: Transformation - values::Vector{D} - vectors::Vector{V} - function TwistedBoundaryCondition{Names}(values::AbstractVector{<:Number}, vectors::AbstractVector{<:AbstractVector{<:Number}}) where Names - @assert length(Names)==length(values)==length(vectors) "TwistedBoundaryCondition error: mismatched names, values and vectors." - datatype = promote_type(eltype(values), Float) - new{Names, datatype, eltype(vectors)}(convert(Vector{datatype}, values), vectors) - end -end -@inline Base.valtype(::Type{<:TwistedBoundaryCondition}, M::Type{<:Operator}) = reparameter(M, :value, promote_type(Complex{Int}, valtype(M))) -@inline Base.valtype(B::Type{<:TwistedBoundaryCondition}, MS::Type{<:Operators}) = (M = valtype(B, eltype(MS)); Operators{M, idtype(M)}) - -""" - keys(bound::TwistedBoundaryCondition) -> Tuple{Vararg{Symbol}} - keys(::Type{<:TwistedBoundaryCondition{Names}}) where Names -> Names - -Get the names of the boundary parameters. -""" -@inline Base.keys(bound::TwistedBoundaryCondition) = keys(typeof(bound)) -@inline Base.keys(::Type{<:TwistedBoundaryCondition{Names}}) where Names = Names - -""" - (bound::TwistedBoundaryCondition)(operator::Operator; origin::Union{AbstractVector, Nothing}=nothing) -> Operator - -Get the boundary twisted operator. -""" -@inline function (bound::TwistedBoundaryCondition)(operator::Operator; origin::Union{AbstractVector, Nothing}=nothing) - values = isnothing(origin) ? bound.values : bound.values-origin - return replace(operator, operator.value*exp(1im*mapreduce(u->angle(u, bound.vectors, values), +, id(operator)))) -end - -""" - update!(bound::TwistedBoundaryCondition; parameters...) -> TwistedBoundaryCondition - -Update the values of the boundary twisted phase. -""" -@inline @generated function update!(bound::TwistedBoundaryCondition; parameters...) - exprs = [] - for (i, name) in enumerate(QuoteNode.(keys(bound))) - push!(exprs, :(bound.values[$i] = get(parameters, $name, bound.values[$i]))) - end - return Expr(:block, exprs..., :(return bound)) -end - -""" - merge!(bound::TwistedBoundaryCondition, another::TwistedBoundaryCondition) -> typeof(bound) - -Merge the values and vectors of the twisted boundary condition from another one. -""" -@inline function Base.merge!(bound::TwistedBoundaryCondition, another::TwistedBoundaryCondition) - @assert keys(bound)==keys(another) "merge! error: mismatched names of boundary parameters." - bound.values .= another.values - bound.vectors .= another.vectors - return bound -end - -""" - Parameters(bound::TwistedBoundaryCondition) - -Get the parameters of the twisted boundary condition. -""" -@inline Parameters(bound::TwistedBoundaryCondition) = NamedTuple{keys(bound)}(ntuple(i->bound.values[i], Val(fieldcount(typeof(keys(bound)))))) - -""" - plain - -Plain boundary condition without any twist. -""" -const plain = TwistedBoundaryCondition{()}(Float[], SVector{0, Float}[]) -@inline Base.valtype(::Type{typeof(plain)}, M::Type{<:Operator}) = M -@inline Base.valtype(::Type{typeof(plain)}, M::Type{<:Operators}) = M -@inline (::typeof(plain))(operator::Operator; kwargs...) = operator - end #module diff --git a/src/Essentials/Frameworks.jl b/src/Essentials/Frameworks.jl index 18d28df1..02560dcf 100644 --- a/src/Essentials/Frameworks.jl +++ b/src/Essentials/Frameworks.jl @@ -1,31 +1,134 @@ module Frameworks using Printf: @printf, @sprintf +using StaticArrays: SVector using LaTeXStrings: latexstring using Serialization: serialize using TimerOutputs: TimerOutputs, TimerOutput, @timeit using RecipesBase: RecipesBase, @recipe, @series -using ..QuantumOperators: Operators, Transformation, optype +using ..QuantumOperators: Operator, Operators, Transformation, optype, idtype using ..Spatials: Bonds, AbstractLattice, acrossbonds, isintracell -using ..DegreesOfFreedom: Hilbert, Table, Term, TwistedBoundaryCondition, plain, ismodulatable -using ...Essentials: update -using ...Prerequisites: atol, rtol, decimaltostr -using ...Prerequisites.Traits: efficientoperations +using ..DegreesOfFreedom: Hilbert, Table, Term, ismodulatable +using ...Prerequisites: Float, atol, rtol, decimaltostr +using ...Prerequisites.Traits: efficientoperations, reparameter -import ..DegreesOfFreedom: Parameters import ...Interfaces: id, add!, expand, expand! -import ...Essentials: update!, reset! +import ...Essentials: update, update!, reset! import ...Prerequisites.Traits: contentnames, getcontent +export Parameters, Boundary, plain export Entry, Engine, AbstractGenerator, Generator, SimplifiedGenerator, Action, Assignment, Algorithm export prepare!, run!, save, rundependences! """ - Entry{C, A<:NamedTuple, B<:NamedTuple, P<:Parameters, D<:TwistedBoundaryCondition} + Parameters{Names}(values::Number...) where Names + +A NamedTuple that contain the key-value pairs. +""" +const Parameters{Names} = NamedTuple{Names, <:Tuple{Vararg{Number}}} +@inline Parameters{Names}(values::Number...) where {Names} = NamedTuple{Names}(values) +@inline @generated function update(params::Parameters; parameters...) + names = fieldnames(params) + values = [:(get(parameters, $name, getfield(params, $name))) for name in QuoteNode.(names)] + return :(Parameters{$names}($(values...))) +end + +""" + match(params₁::Parameters, params₂::Parameters; atol=atol, rtol=rtol) -> Bool + +Judge whether the second set of parameters matches the first. +""" +function Base.match(params₁::Parameters, params₂::Parameters; atol=atol, rtol=rtol) + for name in keys(params₂) + haskey(params₁, name) && !isapprox(getfield(params₁, name), getfield(params₂, name); atol=atol, rtol=rtol) && return false + end + return true +end + +""" + Boundary{Names}(values::AbstractVector{<:Number}, vectors::AbstractVector{<:AbstractVector{<:Number}}) where Names + +Boundary twist of operators. +""" +struct Boundary{Names, D<:Number, V<:AbstractVector} <: Transformation + values::Vector{D} + vectors::Vector{V} + function Boundary{Names}(values::AbstractVector{<:Number}, vectors::AbstractVector{<:AbstractVector{<:Number}}) where Names + @assert length(Names)==length(values)==length(vectors) "Boundary error: mismatched names, values and vectors." + datatype = promote_type(eltype(values), Float) + new{Names, datatype, eltype(vectors)}(convert(Vector{datatype}, values), vectors) + end +end +@inline Base.valtype(::Type{<:Boundary}, M::Type{<:Operator}) = reparameter(M, :value, promote_type(Complex{Int}, valtype(M))) +@inline Base.valtype(B::Type{<:Boundary}, MS::Type{<:Operators}) = (M = valtype(B, eltype(MS)); Operators{M, idtype(M)}) + +""" + keys(bound::Boundary) -> Tuple{Vararg{Symbol}} + keys(::Type{<:Boundary{Names}}) where Names -> Names + +Get the names of the boundary parameters. +""" +@inline Base.keys(bound::Boundary) = keys(typeof(bound)) +@inline Base.keys(::Type{<:Boundary{Names}}) where Names = Names + +""" + (bound::Boundary)(operator::Operator; origin::Union{AbstractVector, Nothing}=nothing) -> Operator + +Get the boundary twisted operator. +""" +@inline function (bound::Boundary)(operator::Operator; origin::Union{AbstractVector, Nothing}=nothing) + values = isnothing(origin) ? bound.values : bound.values-origin + return replace(operator, operator.value*exp(1im*mapreduce(u->angle(u, bound.vectors, values), +, id(operator)))) +end + +""" + update!(bound::Boundary; parameters...) -> Boundary + +Update the values of the boundary twisted phase. +""" +@inline @generated function update!(bound::Boundary; parameters...) + exprs = [] + for (i, name) in enumerate(QuoteNode.(keys(bound))) + push!(exprs, :(bound.values[$i] = get(parameters, $name, bound.values[$i]))) + end + return Expr(:block, exprs..., :(return bound)) +end + +""" + merge!(bound::Boundary, another::Boundary) -> typeof(bound) + +Merge the values and vectors of the twisted boundary condition from another one. +""" +@inline function Base.merge!(bound::Boundary, another::Boundary) + @assert keys(bound)==keys(another) "merge! error: mismatched names of boundary parameters." + bound.values .= another.values + bound.vectors .= another.vectors + return bound +end + +""" + Parameters(bound::Boundary) + +Get the parameters of the twisted boundary condition. +""" +@inline Parameters(bound::Boundary) = NamedTuple{keys(bound)}(ntuple(i->bound.values[i], Val(fieldcount(typeof(keys(bound)))))) + +""" + plain + +Plain boundary condition without any twist. +""" +const plain = Boundary{()}(Float[], SVector{0, Float}[]) +@inline Base.valtype(::Type{typeof(plain)}, M::Type{<:Operator}) = M +@inline Base.valtype(::Type{typeof(plain)}, M::Type{<:Operators}) = M +@inline (::typeof(plain))(operator::Operator; kwargs...) = operator + +""" + Entry{C, A<:NamedTuple, B<:NamedTuple, P<:Parameters, D<:Boundary} An entry of quantum operators (or representations of quantum operators) related to (part of) a quantum lattice system. """ -mutable struct Entry{C, A<:NamedTuple, B<:NamedTuple, P<:Parameters, D<:TwistedBoundaryCondition} +mutable struct Entry{C, A<:NamedTuple, B<:NamedTuple, P<:Parameters, D<:Boundary} constops::C alterops::A boundops::B @@ -39,7 +142,7 @@ end Entry(terms::Tuple{Vararg{Term}}, bonds::Bonds, hilbert::Hilbert; half::Bool=false, table::Union{Nothing, Table}=nothing, - boundary::TwistedBoundaryCondition=plain + boundary::Boundary=plain ) Construct an entry of quantum operators based on the input terms, bonds, Hilbert space and (twisted) boundary condition. @@ -47,7 +150,7 @@ Construct an entry of quantum operators based on the input terms, bonds, Hilbert function Entry(terms::Tuple{Vararg{Term}}, bonds::Bonds, hilbert::Hilbert; half::Bool=false, table::Union{Nothing, Table}=nothing, - boundary::TwistedBoundaryCondition=plain + boundary::Boundary=plain ) constterms, alterterms, choosedterms = termclassifier(terms) innerbonds = filter(acrossbonds, bonds, Val(:exclude)) @@ -205,7 +308,7 @@ end reset!(entry::Entry{<:Operators}, terms::Tuple{Vararg{Term}}, bonds::Bonds, hilbert::Hilbert; half::Bool=false, table::Union{Nothing, Table}=nothing, - boundary::TwistedBoundaryCondition=entry.boundary + boundary::Boundary=entry.boundary ) -> Entry Reset an entry of quantum operators by the new terms, bonds, Hilbert space and (twisted) boundary condition. @@ -213,7 +316,7 @@ Reset an entry of quantum operators by the new terms, bonds, Hilbert space and ( function reset!(entry::Entry{<:Operators}, terms::Tuple{Vararg{Term}}, bonds::Bonds, hilbert::Hilbert; half::Bool=false, table::Union{Nothing, Table}=nothing, - boundary::TwistedBoundaryCondition=entry.boundary + boundary::Boundary=entry.boundary ) empty!(entry) constterms, alterterms, _ = termclassifier(terms) @@ -324,7 +427,7 @@ end Generator(terms::Tuple{Vararg{Term}}, bonds::Bonds, hilbert::Hilbert; half::Bool=false, table::Union{Table,Nothing}=nothing, - boundary::TwistedBoundaryCondition=plain + boundary::Boundary=plain ) Construct a generator of operators. @@ -332,7 +435,7 @@ Construct a generator of operators. @inline function Generator(terms::Tuple{Vararg{Term}}, bonds::Bonds, hilbert::Hilbert; half::Bool=false, table::Union{Table,Nothing}=nothing, - boundary::TwistedBoundaryCondition=plain + boundary::Boundary=plain ) return Generator(Entry(terms, bonds, hilbert; half=half, table=table, boundary=boundary), terms, bonds, hilbert, half, table) end @@ -426,11 +529,11 @@ Get an empty copy of a generator. end """ - reset!(gen::Generator, lattice::AbstractLattice, boundary::TwistedBoundaryCondition=gen.operators.boundary) -> Generator + reset!(gen::Generator, lattice::AbstractLattice, boundary::Boundary=gen.operators.boundary) -> Generator Reset a generator by a new lattice and a new twisted boundary condition. """ -function reset!(gen::Generator, lattice::AbstractLattice, boundary::TwistedBoundaryCondition=gen.operators.boundary) +function reset!(gen::Generator, lattice::AbstractLattice, boundary::Boundary=gen.operators.boundary) reset!(gen.bonds, lattice) reset!(gen.hilbert, lattice.pids) isnothing(gen.table) || reset!(gen.table, gen.hilbert) @@ -443,7 +546,7 @@ end The simplified generator for an entry of (representations of) quantum operators. -Usually, an instance of this type comes out as the result of a transformation on an instance of `Generator`. +Usually, an instance of this type comes out as the result of a transformation on an instance of `Generator`/`SimplifiedGenerator`. """ mutable struct SimplifiedGenerator{E<:Entry, T<:Union{Table, Nothing}} <: AbstractGenerator{E, T} operators::E @@ -455,19 +558,19 @@ end """ SimplifiedGenerator(operators::Entry; table::Union{Table,Nothing}=nothing, sourceid::UInt=objectid(nothing)) -Construct an simplified generator of operators. +Construct an simplified generator of (representations of) quantum operators. """ @inline function SimplifiedGenerator(operators::Entry; table::Union{Table,Nothing}=nothing, sourceid::UInt=objectid(nothing)) return SimplifiedGenerator(operators, table, sourceid) end """ - (transformation::Transformation)(gen::Generator; table::Union{Table, Nothing}=nothing, kwargs...) -> SimplifiedGenerator + (transformation::Transformation)(gen::AbstractGenerator; table::Union{Table, Nothing}=nothing, kwargs...) -> SimplifiedGenerator -Get the result of a transformation on an instance of `Generator`. +Get the result of a transformation on an instance of `AbstractGenerator`. """ -@inline function (transformation::Transformation)(gen::Generator; table::Union{Table, Nothing}=nothing, kwargs...) - return SimplifiedGenerator(transformation(gen.operators; kwargs...); table=table, sourceid=objectid((transformation, gen))) +@inline function (transformation::Transformation)(gen::AbstractGenerator; table::Union{Table, Nothing}=nothing, kwargs...) + return SimplifiedGenerator(transformation(getcontent(gen, :operators); kwargs...); table=table, sourceid=objectid((transformation, gen))) end """ diff --git a/src/QuantumLattices.jl b/src/QuantumLattices.jl index 08092e0d..657f9341 100644 --- a/src/QuantumLattices.jl +++ b/src/QuantumLattices.jl @@ -31,12 +31,12 @@ export allbonds, zerothbonds, insidebonds, acrossbonds, intrabonds, interbonds # Essentials.DegreesOfFreedom export CompositeIID, CompositeInternal, Index, OID, IIDSpace, Hilbert -export Subscript, Subscripts, SubscriptsID, Coupling, Couplings, OIDToTuple, Table, Term, LaTeX, Boundary -export statistics, iidtype, ismodulatable, abbr, otype, twist, plain, @subscript_str, @couplings +export Subscript, Subscripts, SubscriptsID, Coupling, Couplings, OIDToTuple, Table, Term, LaTeX +export statistics, iidtype, ismodulatable, abbr, @subscript_str, @couplings # Essentials.Frameworks -export Parameters, Generator, SimplifiedGenerator, Action, Engine, Assignment, Algorithm -export prepare!, run!, rundependences! +export Parameters, Boundary, Generator, SimplifiedGenerator, Action, Engine, Assignment, Algorithm +export prepare!, run!, rundependences!, plain # Essentials.QuantumSystems ## Canonical fermionic/bosonic systems diff --git a/test/Essentials/DegreesOfFreedom.jl b/test/Essentials/DegreesOfFreedom.jl index b92a7988..29f35873 100644 --- a/test/Essentials/DegreesOfFreedom.jl +++ b/test/Essentials/DegreesOfFreedom.jl @@ -1,15 +1,13 @@ using Test using Printf: @printf, @sprintf using StaticArrays: SVector -using LinearAlgebra: dot using QuantumLattices.Essentials.DegreesOfFreedom using QuantumLattices.Essentials.QuantumOperators: ID, Operator, Operators, sequence, id, idtype, LaTeX, latexformat using QuantumLattices.Essentials.Spatials: AbstractPID, PID, CPID, Point, Bond, Bonds, Lattice, pidtype, rcoord, icoord -using QuantumLattices.Essentials: kind, update, update!, reset! -using QuantumLattices.Interfaces: decompose, rank, expand, ⊗ +using QuantumLattices.Essentials: kind, update!, reset! +using QuantumLattices.Interfaces: rank, expand, ⊗ using QuantumLattices.Prerequisites: Float, decimaltostr -using QuantumLattices.Prerequisites.Traits: parameternames, isparameterbound, contentnames, getcontent, reparameter -using QuantumLattices.Prerequisites.CompositeStructures: NamedContainer +using QuantumLattices.Prerequisites.Traits: parameternames, isparameterbound, contentnames, getcontent import QuantumLattices.Essentials.QuantumOperators: latexname, script import QuantumLattices.Essentials.DegreesOfFreedom: ishermitian, statistics, couplingcenters, abbr @@ -34,13 +32,6 @@ end @inline shape(iidspace::IIDSpace{DID{Symbol}, DFock}) = (1:iidspace.internal.nnambu,) @inline shape(iidspace::IIDSpace{DID{Int}, DFock}) = (iidspace.iid.nambu:iidspace.iid.nambu,) -function Base.angle(id::OID{<:Index{<:AbstractPID, DID{Int}}}, vectors::AbstractVector{<:AbstractVector{Float}}, values::AbstractVector{Float}) - phase= (length(vectors) == 1) ? 2pi*dot(decompose(id.icoord, vectors[1]), values) : - (length(vectors) == 2) ? 2pi*dot(decompose(id.icoord, vectors[1], vectors[2]), values) : - (length(vectors) == 3) ? 2pi*dot(decompose(id.icoord, vectors[1], vectors[2], vectors[3]), values) : - error("angle error: not supported number of input basis vectors.") - (id.index.iid.nambu == 1) ? phase : -phase -end @inline script(::Val{:site}, index::Index{<:AbstractPID, <:DID}; kwargs...) = index.pid.site @inline script(::Val{:nambu}, index::Index{<:AbstractPID, <:DID}; kwargs...) = index.iid.nambu==2 ? "\\dagger" : "" @@ -465,44 +456,3 @@ end @test script(Val(:site), oid) == 1 @test script(Val(:nambu), oid) == "\\dagger" end - -@testset "Parameters" begin - ps1 = Parameters{(:t1, :t2, :U)}(1.0im, 1.0, 2.0) - ps2 = Parameters{(:t1, :U)}(1.0im, 2.0) - ps3 = Parameters{(:t1, :U)}(1.0im, 2.1) - @test match(ps1, ps2) == true - @test match(ps1, ps3) == false - @test update(ps1; ps3...) == Parameters{(:t1, :t2, :U)}(1.0im, 1.0, 2.1) -end - -@testset "TwistedBoundaryCondition" begin - op = Operator(4.5, - OID(Index(PID(1), DID(2)), SVector(0.5, 0.5), SVector(0.0, 0.0)), - OID(Index(PID(2), DID(1)), SVector(1.5, 1.5), SVector(1.0, 1.0)) - ) - bound = TwistedBoundaryCondition{(:θ₁, :θ₂)}([0.1, 0.2], [[1.0, 0.0], [0.0, 1.0]]) - M = reparameter(typeof(op), :value, Complex{Float64}) - @test valtype(typeof(bound), typeof(op)) == M - @test keys(bound) == keys(typeof(bound)) == (:θ₁, :θ₂) - @test Parameters(bound) == (θ₁=0.1, θ₂=0.2) - - another = TwistedBoundaryCondition{(:θ₁, :θ₂)}([0.0, 0.0], [[2.0, 0.0], [0.0, 2.0]]) - @test merge!(deepcopy(bound), another) == another - - @test bound(op) ≈ replace(op, 4.5*exp(2im*pi*0.3)) - @test bound(op, origin=[0.05, 0.15]) ≈ replace(op, 4.5*exp(2im*pi*0.1)) - update!(bound, θ₁=0.3) - @test bound(op) ≈ replace(op, 4.5*exp(2im*pi*0.5)) - @test bound(op, origin=[0.1, 0.1]) ≈ replace(op, 4.5*exp(2im*pi*0.3)) - - ops = Operators{M}(op) - @test valtype(typeof(bound), typeof(ops)) == typeof(ops) - @test bound(ops) ≈ Operators(replace(op, 4.5*exp(2im*pi*0.5))) - @test map!(bound, ops) ≈ ops ≈ Operators(replace(op, 4.5*exp(2im*pi*0.5))) - - @test valtype(typeof(plain), typeof(op)) == typeof(op) - @test valtype(typeof(plain), typeof(ops)) == typeof(ops) - @test plain(op) == op - @test plain(ops) == ops - @test update!(plain) == plain -end diff --git a/test/Essentials/Frameworks.jl b/test/Essentials/Frameworks.jl index 898e3f79..4c43ef86 100644 --- a/test/Essentials/Frameworks.jl +++ b/test/Essentials/Frameworks.jl @@ -3,16 +3,16 @@ using Printf: @printf using LinearAlgebra: tr, dot using StaticArrays: SVector using QuantumLattices.Essentials.Frameworks -using QuantumLattices.Essentials: reset! +using QuantumLattices.Essentials: update, reset! using QuantumLattices.Essentials.Spatials: Point, AbstractPID, PID, Bond, Bonds, Lattice, acrossbonds, zerothbonds, decompose using QuantumLattices.Essentials.DegreesOfFreedom: SimpleIID, SimpleInternal, IIDSpace, Coupling, Subscript, Subscripts, SubscriptsID -using QuantumLattices.Essentials.DegreesOfFreedom: Term, Hilbert, Index, Table, OID, OIDToTuple, @couplings, TwistedBoundaryCondition +using QuantumLattices.Essentials.DegreesOfFreedom: Term, Hilbert, Index, Table, OID, OIDToTuple, @couplings using QuantumLattices.Essentials.QuantumOperators: ID, Operator, Operators, id, idtype, Identity using QuantumLattices.Prerequisites: Float using QuantumLattices.Interfaces: expand!, expand, add! -using QuantumLattices.Prerequisites.Traits: contentnames +using QuantumLattices.Prerequisites.Traits: contentnames, reparameter -import QuantumLattices.Essentials.DegreesOfFreedom: Parameters +import QuantumLattices.Essentials.Frameworks: Parameters import QuantumLattices.Essentials: prepare!, run!, update! import QuantumLattices.Essentials.DegreesOfFreedom: ishermitian, couplingcenters import QuantumLattices.Prerequisites.VectorSpaces: shape, ndimshape @@ -49,6 +49,47 @@ const FCoupling{V, I<:ID{FID}, C<:Subscripts, CI<:SubscriptsID} = Coupling{V, I, @inline ishermitian(::Type{<:Term{:Mu}}) = true @inline ishermitian(::Type{<:Term{:Hp}}) = false +@testset "Parameters" begin + ps1 = Parameters{(:t1, :t2, :U)}(1.0im, 1.0, 2.0) + ps2 = Parameters{(:t1, :U)}(1.0im, 2.0) + ps3 = Parameters{(:t1, :U)}(1.0im, 2.1) + @test match(ps1, ps2) == true + @test match(ps1, ps3) == false + @test update(ps1; ps3...) == Parameters{(:t1, :t2, :U)}(1.0im, 1.0, 2.1) +end + +@testset "Boundary" begin + op = Operator(4.5, + OID(Index(PID(1), FID(2)), SVector(0.5, 0.5), SVector(0.0, 0.0)), + OID(Index(PID(2), FID(1)), SVector(1.5, 1.5), SVector(1.0, 1.0)) + ) + bound = Boundary{(:θ₁, :θ₂)}([0.1, 0.2], [[1.0, 0.0], [0.0, 1.0]]) + M = reparameter(typeof(op), :value, Complex{Float64}) + @test valtype(typeof(bound), typeof(op)) == M + @test keys(bound) == keys(typeof(bound)) == (:θ₁, :θ₂) + @test Parameters(bound) == (θ₁=0.1, θ₂=0.2) + + another = Boundary{(:θ₁, :θ₂)}([0.0, 0.0], [[2.0, 0.0], [0.0, 2.0]]) + @test merge!(deepcopy(bound), another) == another + + @test bound(op) ≈ replace(op, 4.5*exp(2im*pi*0.3)) + @test bound(op, origin=[0.05, 0.15]) ≈ replace(op, 4.5*exp(2im*pi*0.1)) + update!(bound, θ₁=0.3) + @test bound(op) ≈ replace(op, 4.5*exp(2im*pi*0.5)) + @test bound(op, origin=[0.1, 0.1]) ≈ replace(op, 4.5*exp(2im*pi*0.3)) + + ops = Operators{M}(op) + @test valtype(typeof(bound), typeof(ops)) == typeof(ops) + @test bound(ops) ≈ Operators(replace(op, 4.5*exp(2im*pi*0.5))) + @test map!(bound, ops) ≈ ops ≈ Operators(replace(op, 4.5*exp(2im*pi*0.5))) + + @test valtype(typeof(plain), typeof(op)) == typeof(op) + @test valtype(typeof(plain), typeof(ops)) == typeof(ops) + @test plain(op) == op + @test plain(ops) == ops + @test update!(plain) == plain +end + @testset "Generator" begin @test contentnames(AbstractGenerator) == (:operators, :table) @test contentnames(Generator) == (:operators, :terms, :bonds, :hilbert, :half, :table) @@ -58,7 +99,7 @@ const FCoupling{V, I<:ID{FID}, C<:Subscripts, CI<:SubscriptsID} = Coupling{V, I, bonds = Bonds(lattice) hilbert = Hilbert{FFock}(pid->FFock(2), lattice.pids) table = Table(hilbert, OIDToTuple(:scope, :site)) - boundary = TwistedBoundaryCondition{(:θ,)}([0.1], lattice.vectors) + boundary = Boundary{(:θ,)}([0.1], lattice.vectors) t = Term{:Hp}(:t, 2.0, 1, couplings=@couplings(FCoupling(1.0, (2, 1)))) μ = Term{:Mu}(:μ, 1.0, 0, couplings=@couplings(FCoupling(1.0, (2, 1))), modulate=true)