Skip to content

Commit

Permalink
round of fixes for Julia v0.7 (#96)
Browse files Browse the repository at this point in the history
* Fix deprecations

* round of fixes for Julia v0.7

* clarify that SymmetricTensor{4} is a minor symmetric one
fix #80
  • Loading branch information
fredrikekre authored Jun 20, 2018
1 parent f99f9e1 commit 55a0378
Show file tree
Hide file tree
Showing 11 changed files with 73 additions and 76 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ os:
- osx

julia:
- 0.7
- nightly

branches:
Expand Down
2 changes: 1 addition & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ makedocs(
deploydocs(
repo = "github.com/KristofferC/Tensors.jl.git",
target = "build",
julia = "nightly", # deploy from release bot
julia = "0.7",
deps = nothing,
make = nothing
)
5 changes: 5 additions & 0 deletions docs/src/man/constructing_tensors.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ end
Tensors can be created in multiple ways but they usually include running a function on tensor types of which there are two kinds, `Tensor{order, dim, T}` for non-symmetric tensors and `SymmetricTensor{order, dim, T}` for symmetric tensors.
The parameter `order` is an integer of value 1, 2 or 4, excluding 1 for symmetric tensors. The second parameter `dim` is an integer which corresponds to the dimension of the tensor and can be 1, 2 or 3. The last parameter `T` is the number type that the tensors contain, i.e. `Float64` or `Float32`.

```@docs
Tensors.Tensor
Tensors.SymmetricTensor
```

## [Zero tensors](@id zero_tensors)

A tensor with only zeros is created using the function `zero`, applied to the type of tensor that should be created:
Expand Down
3 changes: 1 addition & 2 deletions docs/src/man/other_operators.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,9 @@ $\mathbf{A} \cdot \mathbf{v}_i = \lambda_i \mathbf{v}_i \qquad i = 1, \dots, \te
where ``\lambda_i`` are the eigenvalues and ``\mathbf{v}_i`` are the corresponding eigenvectors.

```@docs
Tensors.eigfact
Tensors.eigen
Tensors.eigvals
Tensors.eigvecs
Tensors.eig
```

## Tensor square root
Expand Down
31 changes: 30 additions & 1 deletion src/Tensors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Base.@pure

using LinearAlgebra
# re-exports from LinearAlgebra
export , ×, dot, diagm, tr, det, norm, eig, eigvals, eigvecs, eigfact
export , ×, dot, diagm, tr, det, norm, eigvals, eigvecs, eigen

export AbstractTensor, SymmetricTensor, Tensor, Vec, FourthOrderTensor, SecondOrderTensor

Expand All @@ -22,11 +22,40 @@ export tovoigt, tovoigt!, fromvoigt, tomandel, tomandel!, frommandel
#########
abstract type AbstractTensor{order, dim, T <: Real} <: AbstractArray{T, order} end

"""
SymmetricTensor{order,dim,T<:Real}
Symmetric tensor type supported for `order ∈ (2,4)` and `dim ∈ (1,2,3)`.
`SymmetricTensor{4}` is a minor symmetric tensor, such that
`A[i,j,k,l] == A[j,i,k,l]` and `A[i,j,k,l] == A[i,j,l,k]`.
# Examples
```jldoctest
julia> SymmetricTensor{2,2,Float64}((1.0, 2.0, 3.0))
2×2 SymmetricTensor{2,2,Float64,3}:
1.0 2.0
2.0 3.0
```
"""
struct SymmetricTensor{order, dim, T, M} <: AbstractTensor{order, dim, T}
data::NTuple{M, T}
SymmetricTensor{order, dim, T, M}(data::NTuple) where {order, dim, T, M} = new{order, dim, T, M}(data)
end

"""
Tensor{order,dim,T<:Real}
Tensor type supported for `order ∈ (1,2,4)` and `dim ∈ (1,2,3)`.
# Examples
```jldoctest
julia> Tensor{1,3,Float64}((1.0, 2.0, 3.0))
3-element Tensor{1,3,Float64,3}:
1.0
2.0
3.0
```
"""
struct Tensor{order, dim, T, M} <: AbstractTensor{order, dim, T}
data::NTuple{M, T}

Expand Down
6 changes: 3 additions & 3 deletions src/eigen.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# MIT License: Copyright (c) 2016: Andy Ferris.
# See LICENSE.md for further licensing test

@inline function LinearAlgebra.eigfact(S::SymmetricTensor{2, 1, T}) where {T}
@inline function LinearAlgebra.eigen(S::SymmetricTensor{2, 1, T}) where {T}
@inbounds Eigen(Vec{1, T}((S[1, 1],)), one(Tensor{2, 1, T}))
end

function LinearAlgebra.eigfact(S::SymmetricTensor{2, 2, T}) where {T}
function LinearAlgebra.eigen(S::SymmetricTensor{2, 2, T}) where {T}
@inbounds begin
# eigenvalues from quadratic formula
trS_half = tr(S) / 2
Expand Down Expand Up @@ -36,7 +36,7 @@ end
# A small part of the code in the following method was inspired by works of David
# Eberly, Geometric Tools LLC, in code released under the Boost Software
# License. See LICENSE.md
function LinearAlgebra.eigfact(S::SymmetricTensor{2, 3, T}) where {T}
function LinearAlgebra.eigen(S::SymmetricTensor{2, 3, T}) where {T}
@inbounds begin
R = typeof((one(T)*zero(T) + zero(T))/one(T))
SR = convert(SymmetricTensor{2, 3, R}, S)
Expand Down
72 changes: 20 additions & 52 deletions src/math_ops.jl
Original file line number Diff line number Diff line change
Expand Up @@ -157,61 +157,30 @@ end

Base.:\(S1::SecondOrderTensor, S2::AbstractTensor) = inv(S1) S2

"""
eig(::SymmetricTensor{2})
Compute the eigenvalues and eigenvectors of a symmetric second order tensor.
`eig` is a wrapper around [`eigfact`](@ref) which extracts eigenvalues and
eigenvectors to a tuple.
# Examples
```jldoctest
julia> A = rand(SymmetricTensor{2, 2})
2×2 SymmetricTensor{2,2,Float64,3}:
0.590845 0.766797
0.766797 0.566237
julia> Λ, Φ = eig(A);
julia> Λ
2-element Tensor{1,2,Float64,2}:
-0.1883547111127678
1.345436766284664
julia> Φ
2×2 Tensor{2,2,Float64,4}:
-0.701412 0.712756
0.712756 0.701412
julia> Φ ⋅ diagm(Tensor{2, 2}, Λ) ⋅ inv(Φ) # Same as A
2×2 Tensor{2,2,Float64,4}:
0.590845 0.766797
0.766797 0.566237
```
"""
@inline LinearAlgebra.eig(S::SymmetricTensor) = (E = eigfact(S); (E.λ, E.Φ))

"""
eigvals(::SymmetricTensor{2})
Compute the eigenvalues of a symmetric second order tensor.
"""
@inline LinearAlgebra.eigvals(S::SymmetricTensor) = (E = eigfact(S); E.λ)
@inline LinearAlgebra.eigvals(S::SymmetricTensor) = (E = eigen(S); E.values)

"""
eigvecs(::SymmetricTensor{2})
Compute the eigenvectors of a symmetric second order tensor.
"""
@inline LinearAlgebra.eigvecs(S::SymmetricTensor) = (E = eigfact(S); E.Φ)
@inline LinearAlgebra.eigvecs(S::SymmetricTensor) = (E = eigen(S); E.vectors)

struct Eigen{T, dim, M}
λ::Vec{dim, T}
Φ::Tensor{2, dim, T, M}
values::Vec{dim, T}
vectors::Tensor{2, dim, T, M}
end

# destructure via iteration
Base.iterate(E::Eigen, state::Int=1) = iterate((E.values, E.vectors), state)

"""
eigfact(::SymmetricTensor{2})
eigen(A::SymmetricTensor{2})
Compute the eigenvalues and eigenvectors of a symmetric second order tensor
and return an `Eigen` object. The eigenvalues are stored in a `Vec`,
Expand All @@ -222,39 +191,36 @@ See [`eigvals`](@ref) and [`eigvecs`](@ref).
# Examples
```jldoctest
julia> A = rand(SymmetricTensor{2, 2})
2×2 SymmetricTensor{2,2,Float64,3}:
0.590845 0.766797
0.766797 0.566237
julia> A = rand(SymmetricTensor{2, 2});
julia> E = eigfact(A)
julia> E = eigen(A)
Tensors.Eigen{Float64,2,4}([-0.188355, 1.34544], [-0.701412 0.712756; 0.712756 0.701412])
julia> eigvals(E)
julia> E.values
2-element Tensor{1,2,Float64,2}:
-0.1883547111127678
1.345436766284664
julia> eigvecs(E)
julia> E.vectors
2×2 Tensor{2,2,Float64,4}:
-0.701412 0.712756
0.712756 0.701412
```
"""
LinearAlgebra.eigfact
LinearAlgebra.eigen

"""
eigvals(::Eigen)
Extract eigenvalues from an `Eigen` object, returned by [`eigfact`](@ref).
Extract eigenvalues from an `Eigen` object, returned by [`eigen`](@ref).
"""
@inline LinearAlgebra.eigvals(E::Eigen) = E.λ
@inline LinearAlgebra.eigvals(E::Eigen) = E.values
"""
eigvecs(::Eigen)
Extract eigenvectors from an `Eigen` object, returned by [`eigfact`](@ref).
Extract eigenvectors from an `Eigen` object, returned by [`eigen`](@ref).
"""
@inline LinearAlgebra.eigvecs(E::Eigen) = E.Φ
@inline LinearAlgebra.eigvecs(E::Eigen) = E.vectors

"""
sqrt(S::SymmetricTensor{2})
Expand Down Expand Up @@ -290,7 +256,9 @@ function Base.sqrt(S::SymmetricTensor{2,2})
end

function Base.sqrt(S::SymmetricTensor{2,3,T}) where T
λ, Φ = eig(S)
E = eigen(S)
λ = E.values
Φ = E.vectors
z = zero(T)
Λ = Tensor{2,3}(((λ[1]), z, z, z, (λ[2]), z, z, z, (λ[3])))
return symmetricΛΦ')
Expand Down
9 changes: 4 additions & 5 deletions src/symmetric.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
symmetric(::SecondOrderTensor)
symmetric(::FourthOrderTensor)
Computes the symmetric part of a second or fourth order tensor.
For a fourth order tensor, the symmetric part is the same as the minor symmetric part.
Returns a `SymmetricTensor`.
Computes the (minor) symmetric part of a second or fourth order tensor.
Return a `SymmetricTensor`.
# Examples
```jldoctest
Expand All @@ -31,7 +30,7 @@ end
"""
minorsymmetric(::FourthOrderTensor)
Computes the minor symmetric part of a fourth order tensor, returns a `SymmetricTensor{4}`.
Compute the minor symmetric part of a fourth order tensor, return a `SymmetricTensor{4}`.
"""
@inline function minorsymmetric(S::Tensor{4, dim}) where {dim}
SymmetricTensor{4, dim}(
Expand All @@ -52,7 +51,7 @@ end
"""
majorsymmetric(::FourthOrderTensor)
Computes the major symmetric part of a fourth order tensor, returns a `Tensor{4}`.
Compute the major symmetric part of a fourth order tensor, returns a `Tensor{4}`.
"""
@inline function majorsymmetric(S::FourthOrderTensor{dim}) where {dim}
Tensor{4, dim}(
Expand Down
6 changes: 1 addition & 5 deletions src/transpose.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,4 @@ Compute the major transpose of a fourth order tensor.
Tensor{4, dim}(@inline function(i, j, k, l) @inbounds S[k,l,i,j]; end)
end

if VERSION >= v"0.7.0-DEV.1415"
@inline Base.adjoint(S::AllTensors) = transpose(S)
else
@inline Base.ctranspose(S::AllTensors) = transpose(S)
end
@inline Base.adjoint(S::AllTensors) = transpose(S)
2 changes: 1 addition & 1 deletion test/F64.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Base.convert(::Type{F64}, a::F64) = a
Base.convert(::Type{Float64}, a::F64) = a.x
Base.convert(::Type{F64}, a::T) where {T <: Number} = F64(a)

# for testing of eigfact
# for testing of eigen
Base.acos(a::F64) = F64(acos(a.x))
Base.cos(a::F64) = F64(cos(a.x))
Base.sin(a::F64) = F64(sin(a.x))
12 changes: 6 additions & 6 deletions test/test_misc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -294,9 +294,9 @@ for T in (Float32, Float64, F64), dim in (1,2,3)
@test AA (@inferred inv(AA))::Tensor{4, dim, T} one(Tensor{4, dim, T})
@test AA_sym (@inferred inv(AA_sym))::SymmetricTensor{4, dim, T} one(SymmetricTensor{4, dim, T})

E = @inferred eigfact(t_sym)
Λ, Φ = @inferred eig(t_sym)
Λa, Φa = eig(Array(t_sym))
E = @inferred eigen(t_sym)
Λ, Φ = E
Λa, Φa = eigen(Array(t_sym))

@test Λ (@inferred eigvals(t_sym)) eigvals(E) Λa
@test Φ (@inferred eigvecs(t_sym)) eigvecs(E)
Expand All @@ -308,9 +308,9 @@ for T in (Float32, Float64, F64), dim in (1,2,3)
# test eigenfactorizations for a diagonal tensor
v = rand(T, dim)
d_sym = diagm(SymmetricTensor{2, dim, T}, v)
E = @inferred eigfact(d_sym)
Λ, Φ = @inferred eig(d_sym)
Λa, Φa = eig(Symmetric(Array(d_sym)))
E = @inferred eigen(d_sym)
Λ, Φ = E
Λa, Φa = eigen(Symmetric(Array(d_sym)))

@test Λ (@inferred eigvals(d_sym)) eigvals(E) Λa
@test Φ (@inferred eigvecs(d_sym)) eigvecs(E)
Expand Down

0 comments on commit 55a0378

Please sign in to comment.