Skip to content

Commit

Permalink
1) Fix bugs of transfomations acting on SimplifiedGenerator;
Browse files Browse the repository at this point in the history
2) Modify the organization of `DegreesOfFreedom` and `Frameworks`;
3) Rename `TwistedBoundyCondtion` back to `Boundary`.
  • Loading branch information
waltergu committed Dec 1, 2021
1 parent ec9f777 commit 14df596
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 193 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "QuantumLattices"
uuid = "78ae1a1f-1d5d-5174-b61c-66e31b2346dc"
authors = ["waltergu <[email protected]>"]
version = "0.8.6"
version = "0.8.7"

[deps]
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Expand Down
110 changes: 3 additions & 107 deletions src/Essentials/DegreesOfFreedom.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
149 changes: 126 additions & 23 deletions src/Essentials/Frameworks.jl
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -39,15 +142,15 @@ 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.
"""
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))
Expand Down Expand Up @@ -205,15 +308,15 @@ 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.
"""
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)
Expand Down Expand Up @@ -324,15 +427,15 @@ 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.
"""
@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
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand All @@ -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

"""
Expand Down
Loading

0 comments on commit 14df596

Please sign in to comment.