From a03732ffd1f48cb2ffe562064a4d0f5a016484d2 Mon Sep 17 00:00:00 2001 From: Brandon Flores Date: Mon, 20 Nov 2023 14:40:56 -0600 Subject: [PATCH 01/19] Added implementation of `SpinBivector` --- src/Electrum.jl | 2 +- src/data/spin.jl | 84 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/src/Electrum.jl b/src/Electrum.jl index 30ea3953..9655ecbf 100644 --- a/src/Electrum.jl +++ b/src/Electrum.jl @@ -136,7 +136,7 @@ export energy, occupancy, energies, occupancies, min_energy, max_energy, min_occ max_occupancy, fermi # Spin data: multiplicity and direction include("data/spin.jl") -export Multiplicity +export Multiplicity, SpinBivector # Real and reciprocal space data grids include("data/grids.jl") export DataGrid, RealDataGrid, ReciprocalDataGrid diff --git a/src/data/spin.jl b/src/data/spin.jl index 1ca90006..28a85583 100644 --- a/src/data/spin.jl +++ b/src/data/spin.jl @@ -39,3 +39,87 @@ end Base.UnitRange(s::Multiplicity) = first(s):last(s) Base.show(io::IO, s::Multiplicity) = print(io, typeof(s), "()") + +#---Spin bivectors---------------------------------------------------------------------------------# +""" + Electrum._is_skew_symmetric(m::AbstractMatrix) + +Returns `true` if a matrix is skew-symmetric (equivalently, antisymmetric). +""" +function _is_skew_symmetric(m::AbstractMatrix) + size(m,1) == size(m,2) || return false + for a in axes(m,1) + for b in a:lastindex(m) + m[a,b] == -m[b,a] || return false + end + end + return true +end + +""" + SpinBivector{D,T} + +A skew-symmetric matrix representing a spin [bivector](https://en.wikipedia.org/wiki/Bivector) in +`D` dimensions. No automatic normalization has been implemented for this type. + +# Why the spin axis is a bivector + +The identification of a spin direction with a vector is only possible in 3D. This is because the +axis of rotation is defined by the [Hodge dual](https://en.wikipedia.org/wiki/Hodge_star_operator) +of the rotation plane. The Hodge dual is a linear map relating `k`-dimensional objects in +`D`-dimensional space to `D-k`-dimensional objects in the same space. + +A bivector is a 2-dimensional object, and in three dimensions, its Hodge dual is a vector. This is +not the case in any other number of dimensions. To allow for generality in describing spin, this +representation is used instead. +""" +struct SpinBivector{D,T} <: StaticMatrix{D,D,T} + data::SVector{D,SVector{D,T}} + function SpinBivector(m::StaticMatrix{D,D,T}) where {D,T} + @assert _is_skew_symmetric(m) "Input matrix is not skew-symmetric." + return new{D,T}(SVector(eachcol(m))) + end +end + +SpinBivector{D}(m::AbstractMatrix) where D = SpinBivector(SMatrix{D,D}(m)) +SpinBivector{D,T}(m::AbstractMatrix) where D = SpinBivector(SMatrix{D,D,T}(m)) + +function Base.getproperty(b::SpinBivector, s::Symbol) + s === :matrix && return hcat(getfield(b, :data)...) + return getfield(b, s) +end + +Base.propertynames(::SpinBivector; private = false) = private ? (:data, :matrix) : (:matrix,) + +Base.getindex(b::SpinBivector, i...) = getindex(b.matrix) +# Really only for resolving method ambiguities +# Base.getindex(b::SpinBivector, i::Int) = getindex(b.matrix, i) +# Base.getindex(b::SpinBivector, i::Int...) = getindex(b.matrix, i...) + +DataSpace(::Type{<:SpinBivector{D}}) = ByRealSpace{D}() +# Required for StaticArray subtypes +Tuple(b::SpinBivector) = Tuple(b.matrix) + +# Constructors for taking wedge products implicitly +""" + SpinBivector(u::StaticVector{D}, v::StaticVector{D}) + SpinBivector{D}(u::AbstractVector, v::AbstractVector) + SpinBivector{D,T}(u::AbstractVector, v::AbstractVector) + +Constructs a spin bivector from the wedge products of vectors `u` and `v`, which define a bivector. + +The first constructor may be used if only one argument is a `StaticVector{D}` (the other will +automatically be converted to the correct size). +""" +SpinBivector(u::StaticVector{D}, v::StaticVector{D}) where D = SpinBivector(u*v' - v*u') +# Convert one argument to a StaticVector if needed +SpinBivector(u::StaticVector{D}, v::AbstractVector) where D = SpinBivector(u, SVector{D}(v)) +SpinBivector(u::AbstractVector, v::StaticVector{D}) where D = SpinBivector(SVector{D}(u), v) + +function SpinBivector{D}(u::AbstractVector, v::AbstractVector) where D + return SpinBivector(SVector{D}(u), SVector{D}(v)) +end + +function SpinBivector{D,T}(u::AbstractVector, v::AbstractVector) where {D,T} + return SpinBivector(SVector{D,T}(u), SVector{D,T}(v)) +end From 8561b393304c6f794455b27da78844f1b6465b18 Mon Sep 17 00:00:00 2001 From: Brandon Flores Date: Mon, 20 Nov 2023 15:28:51 -0600 Subject: [PATCH 02/19] Added basic documentation for `SpinBivector` --- CHANGELOG.md | 1 + docs/src/api/data.md | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fecc91b..4725c444 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Added - `eachvertex` iterator for the vertices of the parallelepiped representation of a unit cell. + - `SpinBivector` type representing spin direction in a dimension-agnostic way. ### Changed - The Types section of the documentation has been split up into separate sections for lattice diff --git a/docs/src/api/data.md b/docs/src/api/data.md index 3c88dba3..a17ee088 100644 --- a/docs/src/api/data.md +++ b/docs/src/api/data.md @@ -37,6 +37,7 @@ Electrum.weight ## Spin states ```@docs Electrum.Multiplicity +Electrum.SpinBivector ``` ## Energies and occupancies From b3260a2c1b540c9d3c737f6f7010b737bad02331 Mon Sep 17 00:00:00 2001 From: Brandon Flores Date: Mon, 20 Nov 2023 15:29:58 -0600 Subject: [PATCH 03/19] Changed "Spin" test section to "Multiplicity" --- test/spin.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spin.jl b/test/spin.jl index 139540ea..45e33e57 100644 --- a/test/spin.jl +++ b/test/spin.jl @@ -1,4 +1,4 @@ -@testset "Spin" begin +@testset "Multiplicity" begin @test all(size(Multiplicity(n)) == (n,) for n in 1:100) @test all(last(Multiplicity(n)) == (n - 1)//2 for n in 1:100) @test all(Multiplicity(n)[2] == -(n - 1)//2 + 1 for n in 2:100) From 0189ddbac9f19bb9027d022f5a42fc26feea5383 Mon Sep 17 00:00:00 2001 From: Brandon Flores Date: Mon, 20 Nov 2023 15:32:45 -0600 Subject: [PATCH 04/19] Added missing type parameters --- src/data/spin.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/data/spin.jl b/src/data/spin.jl index 28a85583..f5687bb8 100644 --- a/src/data/spin.jl +++ b/src/data/spin.jl @@ -77,12 +77,12 @@ struct SpinBivector{D,T} <: StaticMatrix{D,D,T} data::SVector{D,SVector{D,T}} function SpinBivector(m::StaticMatrix{D,D,T}) where {D,T} @assert _is_skew_symmetric(m) "Input matrix is not skew-symmetric." - return new{D,T}(SVector(eachcol(m))) + return new{D,T}(SVector{D}(eachcol(m))) end end SpinBivector{D}(m::AbstractMatrix) where D = SpinBivector(SMatrix{D,D}(m)) -SpinBivector{D,T}(m::AbstractMatrix) where D = SpinBivector(SMatrix{D,D,T}(m)) +SpinBivector{D,T}(m::AbstractMatrix) where {D,T} = SpinBivector(SMatrix{D,D,T}(m)) function Base.getproperty(b::SpinBivector, s::Symbol) s === :matrix && return hcat(getfield(b, :data)...) @@ -96,7 +96,7 @@ Base.getindex(b::SpinBivector, i...) = getindex(b.matrix) # Base.getindex(b::SpinBivector, i::Int) = getindex(b.matrix, i) # Base.getindex(b::SpinBivector, i::Int...) = getindex(b.matrix, i...) -DataSpace(::Type{<:SpinBivector{D}}) = ByRealSpace{D}() +DataSpace(::Type{<:SpinBivector{D}}) where D = ByRealSpace{D}() # Required for StaticArray subtypes Tuple(b::SpinBivector) = Tuple(b.matrix) From bc8fc49680ef791745baa331e73da3081cae22ca Mon Sep 17 00:00:00 2001 From: Brandon Flores Date: Mon, 20 Nov 2023 15:36:11 -0600 Subject: [PATCH 05/19] Added some tests for `SpinBivector` --- test/spin.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/spin.jl b/test/spin.jl index 45e33e57..3ba88254 100644 --- a/test/spin.jl +++ b/test/spin.jl @@ -21,3 +21,11 @@ # Text representation @test eval(Meta.parse(repr(Multiplicity(3)))) === Multiplicity(3) end + +@testset "Spin bivectors" begin + z_matrix = @SMatrix [0 1 0; -1 0 0; 0 0 0] + s_z = SpinBivector(z_matrix) + @test_throws AssertionError SpinBivector{3}([1 2 3; 4 5 6; 7 8 9]) + @test SpinBivector(SVector{3}(1, 0, 0), [0, 1, 0]) === s_z + @test SpinBivector([0, 1, 0], SVector{3}(1, 0, 0)) === -s_z +end From 4f0ac1fb4c3ed3ed1742a2fb6e08bf7950298629 Mon Sep 17 00:00:00 2001 From: Brandon Flores Date: Mon, 20 Nov 2023 15:39:20 -0600 Subject: [PATCH 06/19] Fixed index iteration in `Electrum._is_skew_symmetric` --- src/data/spin.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/data/spin.jl b/src/data/spin.jl index f5687bb8..db63e5bf 100644 --- a/src/data/spin.jl +++ b/src/data/spin.jl @@ -47,9 +47,9 @@ Base.show(io::IO, s::Multiplicity) = print(io, typeof(s), "()") Returns `true` if a matrix is skew-symmetric (equivalently, antisymmetric). """ function _is_skew_symmetric(m::AbstractMatrix) - size(m,1) == size(m,2) || return false - for a in axes(m,1) - for b in a:lastindex(m) + size(m, 1) == size(m, 2) || return false + for a in axes(m, 1) + for b in (a+1):lastindex(m, 1) m[a,b] == -m[b,a] || return false end end From 9b001f2a994a7e70471be5967691d69b70be514d Mon Sep 17 00:00:00 2001 From: Brandon Flores Date: Mon, 20 Nov 2023 15:45:34 -0600 Subject: [PATCH 07/19] Resolved indexing method ambiguities --- src/data/spin.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data/spin.jl b/src/data/spin.jl index db63e5bf..1220dc73 100644 --- a/src/data/spin.jl +++ b/src/data/spin.jl @@ -93,8 +93,8 @@ Base.propertynames(::SpinBivector; private = false) = private ? (:data, :matrix) Base.getindex(b::SpinBivector, i...) = getindex(b.matrix) # Really only for resolving method ambiguities -# Base.getindex(b::SpinBivector, i::Int) = getindex(b.matrix, i) -# Base.getindex(b::SpinBivector, i::Int...) = getindex(b.matrix, i...) +Base.getindex(b::SpinBivector, i::Int) = getindex(b.matrix, i) +Base.getindex(b::SpinBivector, i::Int...) = getindex(b.matrix, i...) DataSpace(::Type{<:SpinBivector{D}}) where D = ByRealSpace{D}() # Required for StaticArray subtypes From 7438e7cd011687fb5e22773bd0acb620398014b6 Mon Sep 17 00:00:00 2001 From: Brandon Flores Date: Mon, 20 Nov 2023 15:50:23 -0600 Subject: [PATCH 08/19] Added equality for `SpinBivector` --- src/data/spin.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/data/spin.jl b/src/data/spin.jl index 1220dc73..880fbd79 100644 --- a/src/data/spin.jl +++ b/src/data/spin.jl @@ -96,6 +96,7 @@ Base.getindex(b::SpinBivector, i...) = getindex(b.matrix) Base.getindex(b::SpinBivector, i::Int) = getindex(b.matrix, i) Base.getindex(b::SpinBivector, i::Int...) = getindex(b.matrix, i...) +Base.:(==)(a::SpinBivector, b::SpinBivector) = (a.matrix == b.matrix) DataSpace(::Type{<:SpinBivector{D}}) where D = ByRealSpace{D}() # Required for StaticArray subtypes Tuple(b::SpinBivector) = Tuple(b.matrix) From b819e7db3f09baa500ee2a832c47e37bef0c0648 Mon Sep 17 00:00:00 2001 From: Brandon Flores Date: Mon, 20 Nov 2023 15:53:04 -0600 Subject: [PATCH 09/19] Added a few extra `SpinBivector` tests --- test/spin.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/spin.jl b/test/spin.jl index 3ba88254..800589e3 100644 --- a/test/spin.jl +++ b/test/spin.jl @@ -25,7 +25,12 @@ end @testset "Spin bivectors" begin z_matrix = @SMatrix [0 1 0; -1 0 0; 0 0 0] s_z = SpinBivector(z_matrix) + @test s_z[1,2] == 1 + @test s_z[2,1] == -1 + @test !Electrum._is_skew_symmetric([1 2 3; 4 5 6; 7 8 9]) @test_throws AssertionError SpinBivector{3}([1 2 3; 4 5 6; 7 8 9]) @test SpinBivector(SVector{3}(1, 0, 0), [0, 1, 0]) === s_z @test SpinBivector([0, 1, 0], SVector{3}(1, 0, 0)) === -s_z + @test SpinBivector{3}([0 1 0; -1 0 0; 0 0 0]) === s_z + @test SpinBivector{3,Int}([0 1 0; -1 0 0; 0 0 0]) === s_z end From e90d92b7d2452d388bd7153c92e0ef5bec6535fd Mon Sep 17 00:00:00 2001 From: Brandon Flores Date: Wed, 29 Nov 2023 15:34:26 -0600 Subject: [PATCH 10/19] Redefined the inner/outer constructors of `SpinBivector` --- src/data/spin.jl | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/data/spin.jl b/src/data/spin.jl index 880fbd79..66f69725 100644 --- a/src/data/spin.jl +++ b/src/data/spin.jl @@ -75,14 +75,22 @@ representation is used instead. """ struct SpinBivector{D,T} <: StaticMatrix{D,D,T} data::SVector{D,SVector{D,T}} - function SpinBivector(m::StaticMatrix{D,D,T}) where {D,T} + function SpinBivector{D,T}(m::StaticMatrix) where {D,T} @assert _is_skew_symmetric(m) "Input matrix is not skew-symmetric." - return new{D,T}(SVector{D}(eachcol(m))) + return new(SVector{D,T}.(eachcol(m))) end end -SpinBivector{D}(m::AbstractMatrix) where D = SpinBivector(SMatrix{D,D}(m)) -SpinBivector{D,T}(m::AbstractMatrix) where {D,T} = SpinBivector(SMatrix{D,D,T}(m)) +# Needed to resolve method ambiguities +SpinBivector{D,T}(::StaticArray) where {D,T} = error("Input must be a skew-symmetric matrix.") +SpinBivector{D}(::StaticArray) where D = error("Input must be a skew-symmetric matrix.") +SpinBivector(::StaticArray) = error("Input must be a skew-symmetric matrix.") + +SpinBivector{D}(m::StaticMatrix) where D = SpinBivector{D,eltype(m)}(m) +SpinBivector(m::StaticMatrix{D,D}) where D = SpinBivector{D,eltype(m)}(m) + +SpinBivector{D,T}(m::AbstractMatrix) where {D,T} = SpinBivector{D,T}(SMatrix{D,D}(m)) +SpinBivector{D}(m::AbstractMatrix) where D = SpinBivector{D,eltype(m)}(SMatrix{D,D}(m)) function Base.getproperty(b::SpinBivector, s::Symbol) s === :matrix && return hcat(getfield(b, :data)...) @@ -117,10 +125,10 @@ SpinBivector(u::StaticVector{D}, v::StaticVector{D}) where D = SpinBivector(u*v' SpinBivector(u::StaticVector{D}, v::AbstractVector) where D = SpinBivector(u, SVector{D}(v)) SpinBivector(u::AbstractVector, v::StaticVector{D}) where D = SpinBivector(SVector{D}(u), v) -function SpinBivector{D}(u::AbstractVector, v::AbstractVector) where D - return SpinBivector(SVector{D}(u), SVector{D}(v)) -end - function SpinBivector{D,T}(u::AbstractVector, v::AbstractVector) where {D,T} return SpinBivector(SVector{D,T}(u), SVector{D,T}(v)) end + +function SpinBivector{D}(u::AbstractVector, v::AbstractVector) where D + return SpinBivector(SVector{D}(u), SVector{D}(v)) +end From cd9f10346674b917e9087c6bcc7d1a8391fab154 Mon Sep 17 00:00:00 2001 From: Brandon Flores Date: Wed, 29 Nov 2023 15:57:07 -0600 Subject: [PATCH 11/19] Created `_wedge_matrix` kernel --- src/data/spin.jl | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/data/spin.jl b/src/data/spin.jl index 66f69725..7cee0a07 100644 --- a/src/data/spin.jl +++ b/src/data/spin.jl @@ -109,6 +109,22 @@ DataSpace(::Type{<:SpinBivector{D}}) where D = ByRealSpace{D}() # Required for StaticArray subtypes Tuple(b::SpinBivector) = Tuple(b.matrix) +""" + Electrum._wedge_matrix(u::AbstractVector, v::AbstractVector) -> AbstractMatrix + +Returns a bivector, the wedge product of vectors `u` and `v`, represented as a skew-symmetric +matrix. This function will throw a `DimensionMismatch` if `u` and `v` have different lengths. +""" +function _wedge_matrix(u::AbstractVector, v::AbstractVector) + length(u) === length(v) || DimensionMismatch("Vectors must be the same length.") + return u*v' - v*u' +end + +# Try to produce a static matrix whenever possible +_wedge_matrix(u::StaticVector{D}, v::StaticVector{D}) where D = u*v' - v*u' +_wedge_matrix(u::StaticVector{D}, v::AbstractVector) where D = _wedge_matrix(u, SVector{D}(v)) +_wedge_matrix(u::AbstractVector, v::StaticVector{D}) where D = _wedge_matrix(SVector{D}(u), v) + # Constructors for taking wedge products implicitly """ SpinBivector(u::StaticVector{D}, v::StaticVector{D}) @@ -120,15 +136,10 @@ Constructs a spin bivector from the wedge products of vectors `u` and `v`, which The first constructor may be used if only one argument is a `StaticVector{D}` (the other will automatically be converted to the correct size). """ -SpinBivector(u::StaticVector{D}, v::StaticVector{D}) where D = SpinBivector(u*v' - v*u') -# Convert one argument to a StaticVector if needed -SpinBivector(u::StaticVector{D}, v::AbstractVector) where D = SpinBivector(u, SVector{D}(v)) -SpinBivector(u::AbstractVector, v::StaticVector{D}) where D = SpinBivector(SVector{D}(u), v) - -function SpinBivector{D,T}(u::AbstractVector, v::AbstractVector) where {D,T} - return SpinBivector(SVector{D,T}(u), SVector{D,T}(v)) +function SpinBivector(u::AbstractVector, v::AbstractVector) + w = _wedge_matrix(u,v) + w isa StaticArray && return SpinBivector(w) + error("Vector lengths cannot be inferred from input types. Use SpinBivector{D} instead.") end -function SpinBivector{D}(u::AbstractVector, v::AbstractVector) where D - return SpinBivector(SVector{D}(u), SVector{D}(v)) -end +(T::Type{<:SpinBivector{D}})(u::AbstractVector, v::AbstractVector) where D = T(_wedge_matrix(u,v)) From 4d0f42a44fc10ab98567b527145798c006d6a23b Mon Sep 17 00:00:00 2001 From: Brandon Flores Date: Wed, 29 Nov 2023 16:05:56 -0600 Subject: [PATCH 12/19] Resolved `Base.getindex` method ambiguities --- src/data/spin.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/data/spin.jl b/src/data/spin.jl index 7cee0a07..20b8f39e 100644 --- a/src/data/spin.jl +++ b/src/data/spin.jl @@ -99,7 +99,6 @@ end Base.propertynames(::SpinBivector; private = false) = private ? (:data, :matrix) : (:matrix,) -Base.getindex(b::SpinBivector, i...) = getindex(b.matrix) # Really only for resolving method ambiguities Base.getindex(b::SpinBivector, i::Int) = getindex(b.matrix, i) Base.getindex(b::SpinBivector, i::Int...) = getindex(b.matrix, i...) From d784082da37e7e5b022dd32a6fa80e5c151fa74d Mon Sep 17 00:00:00 2001 From: Brandon Flores Date: Wed, 29 Nov 2023 16:13:24 -0600 Subject: [PATCH 13/19] Resolved `Electrum._wedge_matrix` method ambiguities --- src/data/spin.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/data/spin.jl b/src/data/spin.jl index 20b8f39e..edf36f96 100644 --- a/src/data/spin.jl +++ b/src/data/spin.jl @@ -108,6 +108,8 @@ DataSpace(::Type{<:SpinBivector{D}}) where D = ByRealSpace{D}() # Required for StaticArray subtypes Tuple(b::SpinBivector) = Tuple(b.matrix) +_vector_length_mismatch() = throw(DimensionMismatch("Vectors must be the same length.")) + """ Electrum._wedge_matrix(u::AbstractVector, v::AbstractVector) -> AbstractMatrix @@ -115,7 +117,7 @@ Returns a bivector, the wedge product of vectors `u` and `v`, represented as a s matrix. This function will throw a `DimensionMismatch` if `u` and `v` have different lengths. """ function _wedge_matrix(u::AbstractVector, v::AbstractVector) - length(u) === length(v) || DimensionMismatch("Vectors must be the same length.") + length(u) === length(v) || _vector_length_mismatch() return u*v' - v*u' end @@ -123,6 +125,8 @@ end _wedge_matrix(u::StaticVector{D}, v::StaticVector{D}) where D = u*v' - v*u' _wedge_matrix(u::StaticVector{D}, v::AbstractVector) where D = _wedge_matrix(u, SVector{D}(v)) _wedge_matrix(u::AbstractVector, v::StaticVector{D}) where D = _wedge_matrix(SVector{D}(u), v) +# Needed to resolve method ambiguities +_wedge_matrix(::StaticVector, ::StaticVector) = _vector_length_mismatch() # Constructors for taking wedge products implicitly """ From 913dc50bb1c6bdb2f8eff30cd3c83de46ea59f36 Mon Sep 17 00:00:00 2001 From: Brandon Flores Date: Wed, 29 Nov 2023 16:21:41 -0600 Subject: [PATCH 14/19] Ensured negation of a `SpinBivector` is a `SpinBivector` --- src/data/spin.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/data/spin.jl b/src/data/spin.jl index edf36f96..4a00b1df 100644 --- a/src/data/spin.jl +++ b/src/data/spin.jl @@ -146,3 +146,6 @@ function SpinBivector(u::AbstractVector, v::AbstractVector) end (T::Type{<:SpinBivector{D}})(u::AbstractVector, v::AbstractVector) where D = T(_wedge_matrix(u,v)) + +# TODO: mathematical operations should return reasonable types +Base.:-(s::SpinBivector) = typeof(s)(-s.matrix) From e2be0024042bf73aa8f6dc0022eea7cf61c30c65 Mon Sep 17 00:00:00 2001 From: Brandon Flores Date: Wed, 29 Nov 2023 18:04:51 -0600 Subject: [PATCH 15/19] Added way more tests for `SpinBivector` --- test/spin.jl | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/test/spin.jl b/test/spin.jl index 800589e3..348ac958 100644 --- a/test/spin.jl +++ b/test/spin.jl @@ -23,14 +23,41 @@ end @testset "Spin bivectors" begin + x = [1, 0, 0] + y = [0, 1, 0] + (sx, sy) = SVector{3}.((x, y)) z_matrix = @SMatrix [0 1 0; -1 0 0; 0 0 0] s_z = SpinBivector(z_matrix) - @test s_z[1,2] == 1 - @test s_z[2,1] == -1 + @test Electrum._is_skew_symmetric(z_matrix) @test !Electrum._is_skew_symmetric([1 2 3; 4 5 6; 7 8 9]) @test_throws AssertionError SpinBivector{3}([1 2 3; 4 5 6; 7 8 9]) - @test SpinBivector(SVector{3}(1, 0, 0), [0, 1, 0]) === s_z - @test SpinBivector([0, 1, 0], SVector{3}(1, 0, 0)) === -s_z + @test SpinBivector(sx, y) === s_z + @test SpinBivector(y, sx) === -s_z @test SpinBivector{3}([0 1 0; -1 0 0; 0 0 0]) === s_z @test SpinBivector{3,Int}([0 1 0; -1 0 0; 0 0 0]) === s_z + # Constructor with wedge product + @test SpinBivector(sx, sy) === s_z + @test SpinBivector{3}(x, y) === s_z + @test SpinBivector{3,Float64}(x, y) == s_z + # Wedge product kernel for AbstractVector + @test Electrum._wedge_matrix(sx, sy) == Electrum._wedge_matrix(x, y) + # Properties + @test :data in propertynames(s_z, private = true) + @test only(propertynames(s_z, private = true)) == :matrix + # Indexing + @test s_z[1,2] == 1 + @test s_z[2] == 1 + @test s_z[2,1] == -1 + @test s_z[4] == -1 + # Bad constructor inputs + @test_throws ErrorException SpinBivector(x, y) + @test_throws ErrorException SpinBivector(@SVector [1, 2, 3]) + @test_throws ErrorException SpinBivector{3}(@SVector [1, 2, 3]) + @test_throws ErrorException SpinBivector{3,Int}(@SVector [1, 2, 3]) + @test_throws ErrorException SpinBivector(@SArray [1 2; 3 4;; 5 6; 7 8]) + @test_throws DimensionMismatch SpinBivector(@SVector [1, 0], @SVector [0, 1, 0]) + @test_throws DimensionMismatch SpinBivector{3}([1, 0, 0], [0, 1]) + # Traits + @test Electrum.DataSpace(SpinBivector{3}) === ByRealSpace{3}() + @test Electrum.DataSpace(s_z) === ByRealSpace{3}() end From a2f30b4b20c78ad9d01dc06122a1cf735fcc8975 Mon Sep 17 00:00:00 2001 From: Brandon Flores Date: Wed, 29 Nov 2023 18:12:55 -0600 Subject: [PATCH 16/19] Fixed array specification in test --- test/spin.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spin.jl b/test/spin.jl index 348ac958..29c5fc9d 100644 --- a/test/spin.jl +++ b/test/spin.jl @@ -54,7 +54,7 @@ end @test_throws ErrorException SpinBivector(@SVector [1, 2, 3]) @test_throws ErrorException SpinBivector{3}(@SVector [1, 2, 3]) @test_throws ErrorException SpinBivector{3,Int}(@SVector [1, 2, 3]) - @test_throws ErrorException SpinBivector(@SArray [1 2; 3 4;; 5 6; 7 8]) + @test_throws ErrorException SpinBivector(@SArray [1; 2;; 3; 4;;; 5; 6;;; 7; 8;;;]) @test_throws DimensionMismatch SpinBivector(@SVector [1, 0], @SVector [0, 1, 0]) @test_throws DimensionMismatch SpinBivector{3}([1, 0, 0], [0, 1]) # Traits From 8926b250e8566e2d43f63f8208b1358d287e1a28 Mon Sep 17 00:00:00 2001 From: Brandon Flores Date: Wed, 29 Nov 2023 18:19:10 -0600 Subject: [PATCH 17/19] Changed the way some `SVector` arguments are specified --- test/spin.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spin.jl b/test/spin.jl index 29c5fc9d..3199c249 100644 --- a/test/spin.jl +++ b/test/spin.jl @@ -55,7 +55,7 @@ end @test_throws ErrorException SpinBivector{3}(@SVector [1, 2, 3]) @test_throws ErrorException SpinBivector{3,Int}(@SVector [1, 2, 3]) @test_throws ErrorException SpinBivector(@SArray [1; 2;; 3; 4;;; 5; 6;;; 7; 8;;;]) - @test_throws DimensionMismatch SpinBivector(@SVector [1, 0], @SVector [0, 1, 0]) + @test_throws DimensionMismatch SpinBivector(SVector{2}(1, 0), SVector{3}(0, 1, 0)) @test_throws DimensionMismatch SpinBivector{3}([1, 0, 0], [0, 1]) # Traits @test Electrum.DataSpace(SpinBivector{3}) === ByRealSpace{3}() From 6ca9edcc33ef2bd19cea7b0e7dff309c3d45bfaa Mon Sep 17 00:00:00 2001 From: Brandon Flores Date: Wed, 29 Nov 2023 19:19:49 -0600 Subject: [PATCH 18/19] Changed multidimensional array declaration --- test/spin.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spin.jl b/test/spin.jl index 3199c249..cf2aad16 100644 --- a/test/spin.jl +++ b/test/spin.jl @@ -54,7 +54,7 @@ end @test_throws ErrorException SpinBivector(@SVector [1, 2, 3]) @test_throws ErrorException SpinBivector{3}(@SVector [1, 2, 3]) @test_throws ErrorException SpinBivector{3,Int}(@SVector [1, 2, 3]) - @test_throws ErrorException SpinBivector(@SArray [1; 2;; 3; 4;;; 5; 6;;; 7; 8;;;]) + @test_throws ErrorException SpinBivector(SArray{Tuple{2,2,2}}(1, 2, 3, 4, 5, 6, 7, 8)) @test_throws DimensionMismatch SpinBivector(SVector{2}(1, 0), SVector{3}(0, 1, 0)) @test_throws DimensionMismatch SpinBivector{3}([1, 0, 0], [0, 1]) # Traits From 668e1de77c48e47593efd42cb81f9f20b5f8e482 Mon Sep 17 00:00:00 2001 From: Brandon Flores Date: Wed, 29 Nov 2023 20:07:40 -0600 Subject: [PATCH 19/19] Fixed (hopefully final) test issues --- test/spin.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/spin.jl b/test/spin.jl index cf2aad16..c32f17fb 100644 --- a/test/spin.jl +++ b/test/spin.jl @@ -43,12 +43,12 @@ end @test Electrum._wedge_matrix(sx, sy) == Electrum._wedge_matrix(x, y) # Properties @test :data in propertynames(s_z, private = true) - @test only(propertynames(s_z, private = true)) == :matrix + @test only(propertynames(s_z)) == :matrix # Indexing - @test s_z[1,2] == 1 - @test s_z[2] == 1 @test s_z[2,1] == -1 - @test s_z[4] == -1 + @test s_z[1,2] == 1 + @test s_z[2] == -1 + @test s_z[4] == 1 # Bad constructor inputs @test_throws ErrorException SpinBivector(x, y) @test_throws ErrorException SpinBivector(@SVector [1, 2, 3]) @@ -58,6 +58,6 @@ end @test_throws DimensionMismatch SpinBivector(SVector{2}(1, 0), SVector{3}(0, 1, 0)) @test_throws DimensionMismatch SpinBivector{3}([1, 0, 0], [0, 1]) # Traits - @test Electrum.DataSpace(SpinBivector{3}) === ByRealSpace{3}() - @test Electrum.DataSpace(s_z) === ByRealSpace{3}() + @test Electrum.DataSpace(SpinBivector{3}) === Electrum.ByRealSpace{3}() + @test Electrum.DataSpace(s_z) === Electrum.ByRealSpace{3}() end