diff --git a/Project.toml b/Project.toml index e4be775..1fd3f9f 100644 --- a/Project.toml +++ b/Project.toml @@ -31,9 +31,10 @@ julia = "1.6" [extras] Mendeleev = "c116f080-063d-490a-9873-2b5b2cce4c34" +SymPy = "24249f21-da20-56a4-8eb1-6a02cf4ae2e6" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" UnitfulAtomic = "a7773ee8-282e-5fa2-be4e-bd808c38a91a" [targets] -test = ["Mendeleev", "Test", "Unitful", "UnitfulAtomic"] +test = ["Mendeleev", "SymPy", "Test", "Unitful", "UnitfulAtomic"] diff --git a/src/metric.jl b/src/metric.jl index 073aa40..af7f124 100644 --- a/src/metric.jl +++ b/src/metric.jl @@ -1,4 +1,4 @@ -using StaticArrays: SHermitianCompact +using StaticArrays: SHermitianCompact, SDiagonal export MetricTensor, distance @@ -11,10 +11,8 @@ MetricTensor(data::AbstractMatrix) = MetricTensor(SHermitianCompact{3}(data)) Generate a `MetricTensor` from the three basis vectors. """ -function MetricTensor(𝐚::AbstractVector, 𝐛::AbstractVector, 𝐜::AbstractVector) - 𝐚𝐛𝐜 = (𝐚, 𝐛, 𝐜) - return MetricTensor([dot(𝐱, 𝐲) for 𝐱 in 𝐚𝐛𝐜, 𝐲 in 𝐚𝐛𝐜]) -end +MetricTensor(𝐚::AbstractVector, 𝐛::AbstractVector, 𝐜::AbstractVector) = + MetricTensor([dot(𝐱, 𝐲) for 𝐱 in (𝐚, 𝐛, 𝐜), 𝐲 in (𝐚, 𝐛, 𝐜)]) """ MetricTensor(lattice::Lattice) @@ -51,7 +49,7 @@ distance(𝐚::AbstractVector, g::MetricTensor, 𝐛::AbstractVector) = g(𝐚, Construct a `Lattice` from a `MetricTensor`. """ -Lattice(g::MetricTensor) = Lattice(latticeconstants(g)) +Lattice(g::MetricTensor) = Lattice(latticeconstants(g)...) """ latticeconstants(g::MetricTensor) @@ -65,6 +63,20 @@ function latticeconstants(g::MetricTensor) return a, b, c, α, β, γ end +# See https://github.com/JuliaLang/julia/blob/v1.10.0-beta1/stdlib/LinearAlgebra/src/uniformscaling.jl#L130-L131 +Base.one(::Type{MetricTensor{T}}) where {T} = + MetricTensor(SDiagonal(one(T), one(T), one(T))) +Base.one(g::MetricTensor) = one(typeof(g)) + +# See https://github.com/JuliaLang/julia/blob/v1.10.0-beta1/stdlib/LinearAlgebra/src/uniformscaling.jl#L132-L133 +Base.oneunit(::Type{MetricTensor{T}}) where {T} = + MetricTensor(SDiagonal(oneunit(T), oneunit(T), oneunit(T))) +Base.oneunit(g::MetricTensor) = oneunit(typeof(g)) + +# See https://github.com/JuliaLang/julia/blob/v1.10.0-beta1/stdlib/LinearAlgebra/src/uniformscaling.jl#L134-L135 +Base.zero(::Type{MetricTensor{T}}) where {T} = MetricTensor(zeros(T, 3, 3)) +Base.zero(lattice::MetricTensor) = zero(typeof(lattice)) + Base.parent(g::MetricTensor) = g.data Base.size(::MetricTensor) = (3, 3) diff --git a/src/volume.jl b/src/volume.jl index 29bbb22..0fc521c 100644 --- a/src/volume.jl +++ b/src/volume.jl @@ -20,7 +20,7 @@ cellvolume(cell::Cell) = cellvolume(Lattice(cell)) Calculate the cell volume from a `MetricTensor`. """ -cellvolume(g::MetricTensor) = sqrt(_det(g.data)) # `sqrt` is always positive! +cellvolume(g::MetricTensor) = sqrt(_det(parent(g))) # `sqrt` is always positive! """ crystaldensity(lattice::Lattice, atoms) diff --git a/test/metric.jl b/test/metric.jl index b8fe7c1..a24cc16 100644 --- a/test/metric.jl +++ b/test/metric.jl @@ -1,5 +1,23 @@ using LinearAlgebra: dot, norm, diagm -# using SymPy: symbols +using SymPy: symbols + +@testset "Test consistency of constructors of `MetricTensor`" begin + lattice = Lattice( + 4.59983732u"angstrom", 4.59983732u"angstrom", 2.95921356u"angstrom", 90, 90, 90 + ) + 𝐚, 𝐛, 𝐜 = basisvectors(lattice) + @test MetricTensor(lattice) == + MetricTensor(𝐚, 𝐛, 𝐜) == + MetricTensor( + 4.59983732u"angstrom", 4.59983732u"angstrom", 2.95921356u"angstrom", 90, 90, 90 + ) + @test Lattice(MetricTensor(lattice)) == lattice + @testset "Test `zero`, `one`, and `oneunit`" begin + @test one(MetricTensor(lattice)) == MetricTensor(one(lattice)) + @test oneunit(MetricTensor(lattice)) == MetricTensor(oneunit(lattice)) + @test zero(MetricTensor(lattice)) == MetricTensor(zero(lattice)) + end +end @testset "Test lengths in a hexagonal lattice" begin g = MetricTensor(1, 1, 2, 90, 90, 120) # Primitive hexagonal @@ -21,8 +39,8 @@ end @test distance(a, g, b)^2 == 13 / 9 end -# @testset "Symbolic calculation" begin -# a, c = symbols("a, c", positive = true) -# @test MetricTensor(a, a, c, 90, 90, 120) == -# MetricTensor([a^2 -0.5*a^2 0; -0.5*a^2 a^2 0; 0 0 c^2]) # Primitive hexagonal -# end +@testset "Test symbolic calculation" begin + a, c = symbols("a, c"; positive=true) + @test MetricTensor(a, a, c, 90, 90, 120) == + MetricTensor([a^2 -0.5*a^2 0; -0.5*a^2 a^2 0; 0 0 c^2]) # Primitive hexagonal +end