diff --git a/docs/make.jl b/docs/make.jl new file mode 100644 index 0000000..87c5298 --- /dev/null +++ b/docs/make.jl @@ -0,0 +1,8 @@ +using Documenter + +import Pkg +Pkg.activate("../") +using LatticeGPU + +makedocs(sitename="LatticeGPU", modules=[LatticeGPU], doctest=true, + repo = "https://igit.ific.uv.es/alramos/latticegpu.jl") diff --git a/docs/src/groups.md b/docs/src/groups.md new file mode 100644 index 0000000..8426a1a --- /dev/null +++ b/docs/src/groups.md @@ -0,0 +1,161 @@ + +# Groups and Algebras + +The module `Groups` contain generic data types to deal with group and +algebra elements. Group elements $$g\in SU(N)$$ are represented in +some compact notation. For the case $$N=2$$ we use two complex numbers +(Caley-Dickson representation, i.e. $$g=(z_1,z_2)$$ with +$$|z_1|^2 + |z_2|^2=1$$). For the case $$N=3$$ we only store two +rows of the $$N\times N$$ unitary matrix. + +Group operations translate straightforwardly in matrix operations, +except for $$SU(2)$$, where we use +```math +\forall g=(z_1, z_2)\in SU(2)\, \Longrightarrow\, g^{-1} = +(\overline z_1, -z_2) +``` +and +```math +\forall g=(z_1, z_2), g'=(w_1,w_2)\in SU(2)\, \Longrightarrow \, g g'= (z_1w_1 - \overline w_2 z_2, w_2z_1 + z_2\overline w_1)\,. +``` + +Group elements can be "casted" into arrays. The abstract type +[`GMatrix`](@ref) represent generic $$ N\\times N$$ complex arrays. + + +Algebra elements $$X \in \mathfrak{su}(N)$$ are traceless +anti-hermitian matrices represented trough $$N^2-1$$ real numbers +$$X^a$$. We have +```math + X = \sum_{a=1}^{N^2-1} X^a T^a +``` +where $$T^a$$ are a basis of the $$\mathfrak{su}(N)$$ algebra with +the conventions +```math + (T^a)^+ = -T^a \,\qquad + {\rm Tr}(T^aT^b) = -\frac{1}{2}\delta_{ab}\,. +``` + +If we denote by $$\{\mathbf{e}_i\}$$ the usual ortonormal basis of +$$\mathbb R^N$$, the $$N^2-1$$ matrices $$T^a$$ can always be written in the +following way +1. symmetric matrices ($$N(N-1)/2$$) + ```math + (T^a)_{ij} = \frac{\imath}{2}(\mathbf{e}_i\otimes\mathbf{e}_j + + \mathbf{e}_j\otimes \mathbf{e}_i)\quad (1\le i < j \le N) + ``` +1. anti-symmetric matrices ($$N(N-1)/2$$) + ```math + (T^a)_{ij} = \frac{1}{2}(\mathbf{e}_i\otimes\mathbf{e}_j - + \mathbf{e}_j\otimes \mathbf{e}_i)\quad (1\le i < j \le N) + ``` +1. diagonal matrices ($$N-1$$). With $$l=1,...,N-1$$ and $$a=l+N(N-1)$$ + ```math + (T^a)_{ij} = \frac{\imath}{2}\sqrt{\frac{2}{l(l+1)}} + \left(\sum_{j=1}^l\mathbf{e}_j\otimes\mathbf{e}_j - + l\mathbf{e}_{l+1}\otimes \mathbf{e}_{l+1}\right) + \quad (l=1,\dots,N-1;\, a=l+N(N-1)) + ``` + +For example in the case of $$\mathfrak{su}(2)$$, and denoting the Pauli +matrices by $$\sigma^a$$ we have +```math + T^a = \frac{\imath}{2}\sigma^a \quad(a=1,2,3)\,, +``` +while for $$\mathfrak{su}(3)$$ we have $$T^a=\imath \lambda^a/2$$ (with +$$\lambda^a$$ the Gell-Mann matrices) up to a permutation. + + +## Some examples + +```@setup exs +import Pkg # hide +Pkg.activate("/home/alberto/code/julia/LatticeGPU/") # hide +using LatticeGPU # hide +``` + +Here we just show some example codes playing with groups and +elements. The objective is to get an idea on how group operations +We can generate some random group elements. +```@repl exs +# Generate random groups elements, +# check they are actually from the grup +g = rand(SU2{Float64}) +println("Are we in a group?: ", isgroup(g)) +g = rand(SU3{Float64}) +println("Are we in a group?: ", isgroup(g)) +``` + +We can also do some simple operations +```@repl exs +X = rand(SU3alg{Float64}) +g1 = exp(X); +g2 = exp(X, -2.0); # e^{-2X} +g = g1*g1*g2; +println("Is this one? ", dev_one(g)) +``` + +## Types + +### Groups + +The generic interface reads + +```@docs +Group +``` + +Concrete supported implementations are +```@docs +SU2 +SU3 +``` + +### Algebras + +The generic interface reads +```@docs +Algebra +``` + +With the following concrete implementations +```@docs +SU2alg +SU3alg +``` + +### GMatrix + +The generic interface reads +```@docs +GMatrix +``` + +With the following concrete implementations +```@docs +M2x2 +M3x3 +``` + + +## Generic `Group` methods + +```@docs +inverse +dag +tr +dev_one +unitarize +isgroup +projalg +``` + +## Generic `Algebra` methods + +```@docs +exp +expm +alg2mat +``` + + diff --git a/docs/src/index.md b/docs/src/index.md new file mode 100644 index 0000000..577388b --- /dev/null +++ b/docs/src/index.md @@ -0,0 +1,8 @@ + +# LatticeGPU.jl documentation + + +```@contents +``` + + diff --git a/src/Groups/AlgebraSU2.jl b/src/Groups/AlgebraSU2.jl index 0eb57db..ac969bb 100644 --- a/src/Groups/AlgebraSU2.jl +++ b/src/Groups/AlgebraSU2.jl @@ -11,11 +11,21 @@ SU2alg(x::T) where T <: AbstractFloat = SU2alg{T}(x,0.0,0.0) SU2alg(v::Vector{T}) where T <: AbstractFloat = SU2alg{T}(v[1],v[2],v[3]) + +""" + projalg([z::Complex,] g::T) where T <: Union{Group, GMatrix} + +Projects the group element/matrix `g` (or `zg`) to the algebra. This amounts to the following operation: + +\`\` X = {\\rm projalg}(g) = -X^a\\frac{1}{2} {\\rm tr}\\{T^a(g - g^{\\dagger})\\} \`\` + +where the substraction of group elements has to be understood in the matrix sense. This method returns an [`Algebra`](@ref) type. The generators of the algebra are the elements \`\` T^a\`\`. +""" projalg(g::SU2{T}) where T <: AbstractFloat = SU2alg{T}(imag(g.t2), real(g.t2), imag(g.t1)) projalg(z::Complex{T}, g::SU2{T}) where T <: AbstractFloat = SU2alg{T}(imag(z*g.t2), real(z*g.t2), imag(z*g.t1)) dot(a::SU2alg{T}, b::SU2alg{T}) where T <: AbstractFloat = a.t1*b.t1 + a.t2*b.t2 + a.t3*b.t3 -norm(a::SU2alg{T}) where T <: AbstractFloat = sqrt(a.t1^2 + a.t2^2 + a.t3^2) -norm2(a::SU2alg{T}) where T <: AbstractFloat = a.t1^2 + a.t2^2 + a.t3^2 +norm(a::SU2alg{T}) where T <: AbstractFloat = sqrt(a.t1^2 + a.t2^2 + a.t3^2) +norm2(a::SU2alg{T}) where T <: AbstractFloat = a.t1^2 + a.t2^2 + a.t3^2 Base.:+(a::SU2alg{T}) where T <: AbstractFloat = SU2alg{T}(a.t1,a.t2,a.t3) Base.:-(a::SU2alg{T}) where T <: AbstractFloat = SU2alg{T}(-a.t1,-a.t2,-a.t3) @@ -26,6 +36,11 @@ Base.:*(a::SU2alg{T},b::Number) where T <: AbstractFloat = SU2alg{T}(a.t1*b,a Base.:*(b::Number,a::SU2alg{T}) where T <: AbstractFloat = SU2alg{T}(a.t1*b,a.t2*b,a.t3*b) Base.:/(a::SU2alg{T},b::Number) where T <: AbstractFloat = SU2alg{T}(a.t1/b,a.t2/b,a.t3/b) +""" + alg2mat(a::T) where T <: Algebra + +Returns the [`Algebra`](@ref) element as a [`GMatrix`](@ref) type. +""" function alg2mat(a::SU2alg{T}) where T <: AbstractFloat u11::Complex{T} = complex(0.0, a.t3)/2 @@ -41,11 +56,10 @@ Base.:*(a::SU2,b::SU2alg) = a*alg2mat(b) Base.:/(a::SU2alg,b::SU2) = alg2mat(a)/b Base.:\(a::SU2,b::SU2alg) = a\alg2mat(b) - """ - function Base.exp(a::T, t::Number=1) where {T <: Algebra} + exp(a::T, t::Number=1) where {T <: Algebra} -Computes `exp(a)` +Computes `exp(ta)` """ function Base.exp(a::SU2alg{T}) where T <: AbstractFloat @@ -83,9 +97,9 @@ end """ - function expm(g::G, a::A) where {G <: Algebra, A <: Algebra} + expm(g::G, a::A, t=1) where {G <: Group, A <: Algebra} -Computes `exp(a)*g` +Computes `g*exp(ta)` """ function expm(g::SU2{T}, a::SU2alg{T}) where T <: AbstractFloat @@ -105,12 +119,6 @@ function expm(g::SU2{T}, a::SU2alg{T}) where T <: AbstractFloat return SU2{T}(t1,t2) end -""" - function expm(g::SU2, a::SU2alg, t::Float64) - -Computes `exp(t*a)*g` - -""" function expm(g::SU2{T}, a::SU2alg{T}, t::T) where T <: AbstractFloat rm = t*sqrt( a.t1^2+a.t2^2+a.t3^2 )/2.0 diff --git a/src/Groups/GroupSU2.jl b/src/Groups/GroupSU2.jl index d0415a1..6faf622 100644 --- a/src/Groups/GroupSU2.jl +++ b/src/Groups/GroupSU2.jl @@ -16,15 +16,39 @@ using CUDA, Random SU2(a::T, b::T) where T <: AbstractFloat = SU2{T}(complex(a), complex(b)) + +""" + inverse(g::T) where T <: Group + +Returns the group inverse of `g`. +""" inverse(b::SU2{T}) where T <: AbstractFloat = SU2{T}(conj(b.t1), -b.t2) + +""" + dag(g::T) where T <: Group + +Returns the group inverse of `g`. +""" dag(a::SU2{T}) where T <: AbstractFloat = inverse(a) norm(a::SU2{T}) where T <: AbstractFloat = sqrt(abs2(a.t1) + abs2(a.t2)) norm2(a::SU2{T}) where T <: AbstractFloat = abs2(a.t1) + abs2(a.t2) -tr(g::SU2{T}) where T <: AbstractFloat = complex(2.0*real(g.t1), 0.0) + +""" + tr(g::T) where T <: Group + +Returns the trace of the groups element `g`. +""" +tr(g::SU2{T}) where T <: AbstractFloat = complex(2*real(g.t1), 0.0) + +""" + dev_one(T) where T <: Group + +Returns the distance to the unit group element +""" dev_one(g::SU2{T}) where T <: AbstractFloat = sqrt(( abs2(g.t1 - one(T)) + abs2(g.t2))/2) """ - function unitarize(a::T) where {T <: Group} + unitarize(a::T) where {T <: Group} Return a unitarized element of the group. """ @@ -40,6 +64,11 @@ Base.:*(a::SU2{T},b::SU2{T}) where T <: AbstractFloat = SU2{T}(a.t1*b.t1-a.t2*co Base.:/(a::SU2{T},b::SU2{T}) where T <: AbstractFloat = SU2{T}(a.t1*conj(b.t1)+a.t2*conj(b.t2),-a.t1*b.t2+a.t2*b.t1) Base.:\(a::SU2{T},b::SU2{T}) where T <: AbstractFloat = SU2{T}(conj(a.t1)*b.t1+a.t2*conj(b.t2),conj(a.t1)*b.t2-a.t2*conj(b.t1)) +""" + isgroup(g::T) where T <: Group + +Returns `true` if `g` is a group element, `false` otherwise. +""" function isgroup(a::SU2{T}) where T <: AbstractFloat tol = 1.0E-10 if (abs2(a.t1) + abs2(a.t2) - 1.0 < 1.0E-10) diff --git a/src/Groups/GroupSU3.jl b/src/Groups/GroupSU3.jl index bf7d2f8..ea9173b 100644 --- a/src/Groups/GroupSU3.jl +++ b/src/Groups/GroupSU3.jl @@ -12,7 +12,7 @@ inverse(a::SU3{T}) where T <: AbstractFloat = SU3{T}(conj(a.u11),conj(a.u21),(a.u12*a.u23 - a.u13*a.u22), conj(a.u12),conj(a.u22),(a.u13*a.u21 - a.u11*a.u23)) dag(a::SU3{T}) where T <: AbstractFloat = inverse(a) tr(a::SU3{T}) where T <: AbstractFloat = a.u11+a.u22+conj(a.u11*a.u22 - a.u12*a.u21) -dev_one(g::SU3{T}) where T <: AbstractFloat = sqrt(( abs2(g.u11 - one(T)) + abs2(g.u12) + abs2(g.u13) + abs2(g.u21) + abs2(g.u22 - one(T)) + abs2(g.u23) )/6) +dev_one(g::SU3{T}) where T <: AbstractFloat = sqrt(( abs2(g.u11 - one(T)) + abs2(g.u12) + abs2(g.u13) + abs2(g.u21) + abs2(g.u22 - one(T)) + abs2(g.u23) )/6) function unitarize(g::SU3{T}) where T <: AbstractFloat diff --git a/src/Groups/GroupU1.jl b/src/Groups/GroupU1.jl index cb2afaa..8e34f98 100644 --- a/src/Groups/GroupU1.jl +++ b/src/Groups/GroupU1.jl @@ -64,20 +64,9 @@ Base.:/(a::U1alg{T},b::Number) where T <: AbstractFloat = U1alg{T}(a.t/b) isgroup(a::U1{T}) where T <: AbstractFloat = (abs(a.t) -1.0) < 1.0E-10 -""" - function Base.exp(a::U1alg, t::Number=1) - -Computes `exp(a)` -""" Base.exp(a::U1alg{T}) where T <: AbstractFloat = U1{T}(CUDA.cos(a.t), CUDA.sin(a.t)) Base.exp(a::U1alg{T}, t::T) where T <: AbstractFloat = U1{T}(CUDA.cos(t*a.t), CUDA.sin(t*a.t)) -""" - function expm(g::U1, a::U1alg; t=1) - -Computes `exp(a)*g` - -""" expm(g::U1{T}, a::U1alg{T}) where T <: AbstractFloat = U1{T}(CUDA.cos(a.t), CUDA.sin(a.t))*g expm(g::U1{T}, a::U1alg{T}, t::T) where T <: AbstractFloat = U1{T}(CUDA.cos(t*a.t), CUDA.sin(t*a.t))*g diff --git a/src/Groups/Groups.jl b/src/Groups/Groups.jl index 62353af..34ee296 100644 --- a/src/Groups/Groups.jl +++ b/src/Groups/Groups.jl @@ -16,10 +16,39 @@ using CUDA, Random import Base.:*, Base.:+, Base.:-,Base.:/,Base.:\,Base.exp,Base.one,Base.zero import Random.rand +""" + abstract type Group + +This abstract type encapsulates group types (i.e. \`\`SU(N)\`\`). The following operations/methods are assumed to be defined for a each group. +- `*,/,\\`: Usual group operations. +- [`inverse`](@ref), [`dag`](@ref): The group inverse. +- [`tr`](@ref) +- [`dev_one`](@ref) +- [`unitarize`](@ref) +- [`isgroup`](@ref) +- [`projalg`](@ref) +""" abstract type Group end + +""" + abstract type Algebra + +This abstract type encapsulates algebra types (i.e. \`\` {\\rm su}(N)\`\`). The following operations/methods are assumed to be defined for each algebra: +- `+,-`: Usual operation of Algebra elements. +- `*,/`: Multiplication/division by Numbers +- `*`: Multiplication of [`Algebra`](@ref) and [`Group`](@ref) or [`GMatrix`](@ref) elements. These routines use the matrix form of the group elements, and return a [`GMatrix`](@ref) type. +- [`exp`](@ref), [`expm`](@ref): Exponential map. Returns a [`Group`](@ref) element. +""" abstract type Algebra end -export Group, Algebra +""" + abstract type GM + +This abstract type encapsulates \`\` N\\times N \`\` matrix types. The usual matrix operations (`+,-,*,/`) are expected to be defined for this case. +""" +abstract type GMatrix end + +export Group, Algebra, GMatrix ## # SU(2) and 2x2 matrix operations diff --git a/src/Groups/SU2Types.jl b/src/Groups/SU2Types.jl index a1adb14..4a6a0f7 100644 --- a/src/Groups/SU2Types.jl +++ b/src/Groups/SU2Types.jl @@ -9,18 +9,34 @@ ### created: Sun Oct 3 09:22:48 2021 ### + +""" + struct SU2{T} <: Group + +\`\`SU(2)\`\` elements. The type `T <: AbstractFloat` can be used to define single or double precision elements. +""" struct SU2{T} <: Group t1::Complex{T} t2::Complex{T} end -struct M2x2{T} +""" + struct M2x2{T} <: GMatrix + +Generic \`\` 2\\times 2\`\` complex matrix. +""" +struct M2x2{T} <: GMatrix u11::Complex{T} u12::Complex{T} u21::Complex{T} u22::Complex{T} end +""" + struct SU2alg{T} <: Algebra + +\`\`{\\rm su}(2)\`\` Algebra elements. +""" struct SU2alg{T} <: Algebra t1::T t2::T diff --git a/src/Groups/SU3Types.jl b/src/Groups/SU3Types.jl index 5fa0d9c..3b9203c 100644 --- a/src/Groups/SU3Types.jl +++ b/src/Groups/SU3Types.jl @@ -20,6 +20,11 @@ import Base.convert +""" + struct SU3{T} <: Group + +\`\`SU(3)\`\` elements. The type `T <: AbstractFloat` can be used to define single or double precision elements. +""" struct SU3{T} <: Group u11::Complex{T} u12::Complex{T} @@ -30,7 +35,12 @@ struct SU3{T} <: Group end Base.one(::Type{SU3{T}}) where T <: AbstractFloat = SU3{T}(one(T),zero(T),zero(T),zero(T),one(T),zero(T)) -struct M3x3{T} +""" + struct M3x3{T} <: Group + +3x3 Complex matrix. The type `T <: AbstractFloat` can be used to define single or double precision elements. +""" +struct M3x3{T} <: GMatrix u11::Complex{T} u12::Complex{T} u13::Complex{T} @@ -44,6 +54,11 @@ end Base.one(::Type{M3x3{T}}) where T <: AbstractFloat = M3x3{T}(one(T),zero(T),zero(T),zero(T),one(T),zero(T),zero(T),zero(T),one(T)) Base.zero(::Type{M3x3{T}}) where T <: AbstractFloat = M3x3{T}(zero(T),zero(T),zero(T),zero(T),zero(T),zero(T),zero(T),zero(T),zero(T)) +""" + struct SU3alg{T} <: Group + +\`\`su(3)\`\` elements. The type `T <: AbstractFloat` can be used to define single or double precision elements. +""" struct SU3alg{T} <: Algebra t1::T t2::T diff --git a/src/LatticeGPU.jl b/src/LatticeGPU.jl index 96a8f57..de9b226 100644 --- a/src/LatticeGPU.jl +++ b/src/LatticeGPU.jl @@ -15,7 +15,7 @@ module LatticeGPU include("Groups/Groups.jl") using .Groups -export Group, Algebra +export Group, Algebra, GMatrix export SU2, SU2alg, SU3, SU3alg, M3x3, M2x2, U1, U1alg, SU3fund export dot, expm, exp, dag, unitarize, inverse, tr, projalg, norm, norm2, isgroup, alg2mat, dev_one