Skip to content

Commit 93e4475

Browse files
authored
Support tovector and fromvector for even-ordered tensors (#14)
1 parent aa675c7 commit 93e4475

File tree

4 files changed

+81
-8
lines changed

4 files changed

+81
-8
lines changed

src/vector_conversion.jl

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,26 +66,59 @@ get_params_eltype(::AbstractMaterial) = Float64
6666

6767
# Conversion functions
6868
"""
69-
tovector!(v::AbstractVector, m::AbstractMaterial)
69+
tovector!(v::AbstractVector, m::AbstractMaterial; offset = 0)
70+
7071
Put the material parameters of `m` into the vector `v`.
7172
This is typically used when the parameters should be fitted.
7273
73-
tovector!(v::AbstractVector, s::AbstractMaterialState)
74+
tovector!(v::AbstractVector, s::AbstractMaterialState; offset = 0)
75+
7476
Put the state variables in `s` into the vector `v`.
7577
This is typically used when differentiating the material
7678
wrt. the the old state variables.
79+
80+
tovector!(v::AbstractVector, a::Union{SecondOrderTensor, FourthOrderTensor}; offset = 0)
81+
82+
Puts the Mandel components of `a` into the vector `v`.
7783
"""
7884
function tovector! end
7985

86+
# Tensors.jl implementation
87+
function tovector!(v::AbstractVector, a::SecondOrderTensor; offset = 0)
88+
return tomandel!(v, a; offset)
89+
end
90+
function tovector!(v::AbstractVector, a::Union{Tensor{4, <:Any, <:Any, M}, SymmetricTensor{4, <:Any, <:Any, M}}; offset = 0) where {M}
91+
N = round(Int, sqrt(M))
92+
m = reshape(view(v, offset .+ (1:M)), (N, N))
93+
tomandel!(m, a)
94+
return v
95+
end
96+
8097
"""
81-
fromvector(v::AbstractVector, ::MT) where {MT<:AbstractMaterial}
98+
fromvector(v::AbstractVector, ::MT; offset = 0) where {MT<:AbstractMaterial}
8299
Create a material of type `MT` with the parameters according to `v`
83100
84-
fromvector(v::AbstractVector, ::ST) where {ST<:AbstractMaterialState}
101+
fromvector(v::AbstractVector, ::ST; offset = 0) where {ST<:AbstractMaterialState}
85102
Create a material state of type `ST` with the values according to `v`
103+
104+
fromvector(v, ::TT; offset = 0) where {TT <: Union{SecondOrderTensor, FourthOrderTensor}}
105+
106+
Create a tensor with shape of `TT` with entries from the Mandel components in `v`.
86107
"""
87108
function fromvector end
88109

110+
# Tensors.jl implementation
111+
function fromvector(v::AbstractVector, ::TT; offset = 0) where {TT <: SecondOrderTensor}
112+
return frommandel(Tensors.get_base(TT), v; offset)
113+
end
114+
115+
function fromvector(v::AbstractVector, ::TT; offset = 0) where {TT <: FourthOrderTensor}
116+
TB = Tensors.get_base(TT)
117+
M = Tensors.n_components(TB)
118+
N = round(Int, sqrt(M))
119+
return frommandel(TB, reshape(view(v, offset .+ (1:M)), (N, N)))
120+
end
121+
89122
"""
90123
tovector(m::AbstractMaterial)
91124
@@ -108,6 +141,8 @@ function tovector(s::AbstractMaterialState)
108141
return tovector!(zeros(T, get_num_statevars(s)), s)
109142
end
110143

144+
tovector(a::Union{SecondOrderTensor, FourthOrderTensor}) = (m = tomandel(a); reshape(m, length(m)))
145+
111146
# Backwards compatibility
112147
const get_parameter_type = get_params_eltype
113148
const material2vector! = tovector!

test/TestMaterials.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ function MMB.material_response(
3131
end
3232

3333
MMB.get_num_params(::LinearElastic) = 2
34-
function MMB.tovector!(v::Vector, m::LinearElastic)
35-
v[1] = m.G
36-
v[2] = m.K
34+
function MMB.tovector!(v::Vector, m::LinearElastic; offset = 0)
35+
v[1 + offset] = m.G
36+
v[2 + offset] = m.K
3737
return v
3838
end
39-
MMB.fromvector(v::Vector, ::LinearElastic) = LinearElastic(v[1], v[2])
39+
MMB.fromvector(v::Vector, ::LinearElastic; offset = 0) = LinearElastic(v[1 + offset], v[2 + offset])
4040

4141
function MMB.differentiate_material!(
4242
diff::MaterialDerivatives,

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ include("TestMaterials.jl")
88
using .TestMaterials
99
include("utils4testing.jl")
1010

11+
include("vector_conversion.jl")
1112
include("stressiterations.jl")
1213
include("differentiation.jl")
1314
include("errors.jl")

test/vector_conversion.jl

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
function test_invertible_conversion(x)
2+
v1 = tovector(x)
3+
# Basic test
4+
@test isa(v1, AbstractVector)
5+
@test v1 tovector(fromvector(v1, x))
6+
7+
# Ensure that we are not using the values in 'x'
8+
v2 = rand(length(v1))
9+
@test v2 tovector(fromvector(v2, x))
10+
11+
# Ensure that offset is working as intended
12+
v3 = zeros(length(v1) + 2)
13+
r1, r2 = rand(2)
14+
v3[1] = r1
15+
v3[end] = r2
16+
v4 = copy(v3) # Do copy here to keep 2:end-1 filled with zeros
17+
tovector!(v3, x; offset = 1)
18+
@test v3[1] == r1
19+
@test v3[end] == r2
20+
@test v3[2:end-1] v1
21+
@test v4 === tovector!(v4, fromvector(v3, x; offset = 1); offset = 1)
22+
@test v3 v4
23+
end
24+
25+
@testset "vector_conversion" begin
26+
@testset "tensors" begin
27+
@testset for TT in (Tensor{2,2}, Tensor{4,3}, SymmetricTensor{2,3}, SymmetricTensor{4,2})
28+
test_invertible_conversion(rand(TT))
29+
end
30+
end
31+
@testset "materials" begin
32+
@testset for m in (LinearElastic(rand(), rand()),)
33+
test_invertible_conversion(m)
34+
# TODO: For state variables as well
35+
end
36+
end
37+
end

0 commit comments

Comments
 (0)