Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 39 additions & 4 deletions src/vector_conversion.jl
Original file line number Diff line number Diff line change
Expand Up @@ -66,26 +66,59 @@ get_params_eltype(::AbstractMaterial) = Float64

# Conversion functions
"""
tovector!(v::AbstractVector, m::AbstractMaterial)
tovector!(v::AbstractVector, m::AbstractMaterial; offset = 0)

Put the material parameters of `m` into the vector `v`.
This is typically used when the parameters should be fitted.

tovector!(v::AbstractVector, s::AbstractMaterialState)
tovector!(v::AbstractVector, s::AbstractMaterialState; offset = 0)

Put the state variables in `s` into the vector `v`.
This is typically used when differentiating the material
wrt. the the old state variables.

tovector!(v::AbstractVector, a::Union{SecondOrderTensor, FourthOrderTensor}; offset = 0)

Puts the Mandel components of `a` into the vector `v`.
"""
function tovector! end

# Tensors.jl implementation
function tovector!(v::AbstractVector, a::SecondOrderTensor; offset = 0)
return tomandel!(v, a; offset)
end
function tovector!(v::AbstractVector, a::Union{Tensor{4, <:Any, <:Any, M}, SymmetricTensor{4, <:Any, <:Any, M}}; offset = 0) where {M}
N = round(Int, sqrt(M))
m = reshape(view(v, offset .+ (1:M)), (N, N))
tomandel!(m, a)
return v
end

"""
fromvector(v::AbstractVector, ::MT) where {MT<:AbstractMaterial}
fromvector(v::AbstractVector, ::MT; offset = 0) where {MT<:AbstractMaterial}
Create a material of type `MT` with the parameters according to `v`

fromvector(v::AbstractVector, ::ST) where {ST<:AbstractMaterialState}
fromvector(v::AbstractVector, ::ST; offset = 0) where {ST<:AbstractMaterialState}
Create a material state of type `ST` with the values according to `v`

fromvector(v, ::TT; offset = 0) where {TT <: Union{SecondOrderTensor, FourthOrderTensor}}

Create a tensor with shape of `TT` with entries from the Mandel components in `v`.
"""
function fromvector end

# Tensors.jl implementation
function fromvector(v::AbstractVector, ::TT; offset = 0) where {TT <: SecondOrderTensor}
return frommandel(Tensors.get_base(TT), v; offset)
end

function fromvector(v::AbstractVector, ::TT; offset = 0) where {TT <: FourthOrderTensor}
TB = Tensors.get_base(TT)
M = Tensors.n_components(TB)
N = round(Int, sqrt(M))
return frommandel(TB, reshape(view(v, offset .+ (1:M)), (N, N)))
end

"""
tovector(m::AbstractMaterial)

Expand All @@ -108,6 +141,8 @@ function tovector(s::AbstractMaterialState)
return tovector!(zeros(T, get_num_statevars(s)), s)
end

tovector(a::Union{SecondOrderTensor, FourthOrderTensor}) = (m = tomandel(a); reshape(m, length(m)))

# Backwards compatibility
const get_parameter_type = get_params_eltype
const material2vector! = tovector!
Expand Down
8 changes: 4 additions & 4 deletions test/TestMaterials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ function MMB.material_response(
end

MMB.get_num_params(::LinearElastic) = 2
function MMB.tovector!(v::Vector, m::LinearElastic)
v[1] = m.G
v[2] = m.K
function MMB.tovector!(v::Vector, m::LinearElastic; offset = 0)
v[1 + offset] = m.G
v[2 + offset] = m.K
return v
end
MMB.fromvector(v::Vector, ::LinearElastic) = LinearElastic(v[1], v[2])
MMB.fromvector(v::Vector, ::LinearElastic; offset = 0) = LinearElastic(v[1 + offset], v[2 + offset])

function MMB.differentiate_material!(
diff::MaterialDerivatives,
Expand Down
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ include("TestMaterials.jl")
using .TestMaterials
include("utils4testing.jl")

include("vector_conversion.jl")
include("stressiterations.jl")
include("differentiation.jl")
include("errors.jl")
Expand Down
37 changes: 37 additions & 0 deletions test/vector_conversion.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
function test_invertible_conversion(x)
v1 = tovector(x)
# Basic test
@test isa(v1, AbstractVector)
@test v1 ≈ tovector(fromvector(v1, x))

# Ensure that we are not using the values in 'x'
v2 = rand(length(v1))
@test v2 ≈ tovector(fromvector(v2, x))

# Ensure that offset is working as intended
v3 = zeros(length(v1) + 2)
r1, r2 = rand(2)
v3[1] = r1
v3[end] = r2
v4 = copy(v3) # Do copy here to keep 2:end-1 filled with zeros
tovector!(v3, x; offset = 1)
@test v3[1] == r1
@test v3[end] == r2
@test v3[2:end-1] ≈ v1
@test v4 === tovector!(v4, fromvector(v3, x; offset = 1); offset = 1)
@test v3 ≈ v4
end

@testset "vector_conversion" begin
@testset "tensors" begin
@testset for TT in (Tensor{2,2}, Tensor{4,3}, SymmetricTensor{2,3}, SymmetricTensor{4,2})
test_invertible_conversion(rand(TT))
end
end
@testset "materials" begin
@testset for m in (LinearElastic(rand(), rand()),)
test_invertible_conversion(m)
# TODO: For state variables as well
end
end
end
Loading