diff --git a/src/LinearElastic.jl b/src/LinearElastic.jl index 96c73bc..b15936f 100644 --- a/src/LinearElastic.jl +++ b/src/LinearElastic.jl @@ -33,6 +33,8 @@ end struct LinearElasticState <: AbstractMaterialState end +strainmeasure(::LinearElastic) = EngineeringStrain() + # define which state belongs to the material initial_material_state(::LinearElastic) = LinearElasticState() diff --git a/src/MaterialModels.jl b/src/MaterialModels.jl index 3825b92..fb0415d 100644 --- a/src/MaterialModels.jl +++ b/src/MaterialModels.jl @@ -33,6 +33,12 @@ Defines the type of strain measure the a material uses, i.e Deformation gradient """ abstract type StrainMeasure end +""" + AbstractDim +Defines the state of stress or strain in 2d/1d problems, e.g. PlaneStress() or PlaneStrain() +""" +abstract type AbstractDim{dim} end + """ material_response(m::AbstractMaterial, Δε::SymmetricTensor{2,3}, state::AbstractMaterialState, Δt; cache, options) @@ -71,7 +77,6 @@ As the residual functions depend i.a. on the strain increment, the function and """ function update_cache! end -include("traits.jl") include("LinearElastic.jl") include("Plastic.jl") include("CrystalViscoPlastic/slipsystems.jl") @@ -83,6 +88,7 @@ include("FiniteStrain/yeoh.jl") include("FiniteStrain/stvenant.jl") include("nonlinear_solver.jl") +include("traits.jl") include("wrappers.jl") export initial_material_state, get_cache diff --git a/src/traits.jl b/src/traits.jl index 9fe1fb4..b798cc1 100644 --- a/src/traits.jl +++ b/src/traits.jl @@ -3,6 +3,7 @@ struct GreenLagrange <: StrainMeasure end struct RightCauchyGreen <: StrainMeasure end struct DeformationGradient <: StrainMeasure end struct VelocityGradient <: StrainMeasure end +struct EngineeringStrain <: StrainMeasure end strainmeasure(m::AbstractMaterial) = error("Strain measure for material $m not defined ") @@ -56,12 +57,14 @@ end Function for automatically converting the output stress and tangent from any material, to any other stress/tangent defined by `output_tangent` (dSdC, dPᵀdF etc.) """ - function material_response(output_tangent::AbstractTangent, m::AbstractMaterial, F::Tensor{2}, state::AbstractMaterialState, Δt::Float64 = 0.0; cache=nothing, options=nothing) - straintype = strainmeasure(m); + material_response(ThreeD(), output_tangent, m, F, state, Δt; cache=cache, options=options) +end +function material_response(dim::AbstractDim, output_tangent::AbstractTangent, m::AbstractMaterial, F::Tensor{2}, state::AbstractMaterialState, Δt::Float64 = 0.0; cache=nothing, options=nothing) + straintype = strainmeasure(m); strain = compute_strain(F, straintype) - stress, strain, newstate = material_response(m, strain, state, Δt, cache=cache, options=options) + stress, strain, newstate = material_response(dim, m, strain, state, Δt, cache=cache, options=options) out_stress, out_tangent = transform_tangent(stress, strain, F, default_tangent(straintype), output_tangent) return out_stress, out_tangent, newstate diff --git a/src/wrappers.jl b/src/wrappers.jl index 82bfb6c..127a2d4 100644 --- a/src/wrappers.jl +++ b/src/wrappers.jl @@ -1,15 +1,17 @@ -abstract type AbstractDim{dim} end struct Dim{dim} <: AbstractDim{dim} end # generic struct UniaxialStrain{dim} <: AbstractDim{dim} end # 1D uniaxial strain state struct UniaxialStress{dim} <: AbstractDim{dim} end # 1D uniaxial stress state struct PlaneStrain{dim} <: AbstractDim{dim} end # 2D plane strain state struct PlaneStress{dim} <: AbstractDim{dim} end # 2D plane stress state +struct ThreeD{dim} <: AbstractDim{dim} end + # constructors without dim parameter UniaxialStrain() = UniaxialStrain{1}() UniaxialStress() = UniaxialStress{1}() PlaneStrain() = PlaneStrain{2}() PlaneStress() = PlaneStress{2}() +ThreeD() = ThreeD{3}() reduce_dim(A::Tensor{1,3}, ::AbstractDim{dim}) where dim = Tensor{1,dim}(i->A[i]) reduce_dim(A::Tensor{2,3}, ::AbstractDim{dim}) where dim = Tensor{2,dim}((i,j)->A[i,j]) @@ -17,13 +19,35 @@ reduce_dim(A::Tensor{4,3}, ::AbstractDim{dim}) where dim = Tensor{4,dim}((i,j,k, reduce_dim(A::SymmetricTensor{2,3}, ::AbstractDim{dim}) where dim = SymmetricTensor{2,dim}((i,j)->A[i,j]) reduce_dim(A::SymmetricTensor{4,3}, ::AbstractDim{dim}) where dim = SymmetricTensor{4,dim}((i,j,k,l)->A[i,j,k,l]) +#default increase_dim(A::Tensor{1,dim,T}) where {dim, T} = Tensor{1,3}(i->(i <= dim ? A[i] : zero(T))) increase_dim(A::Tensor{2,dim,T}) where {dim, T} = Tensor{2,3}((i,j)->(i <= dim && j <= dim ? A[i,j] : zero(T))) increase_dim(A::SymmetricTensor{2,dim,T}) where {dim, T} = SymmetricTensor{2,3}((i,j)->(i <= dim && j <= dim ? A[i,j] : zero(T))) +#RightCauchyGreen, pad with 1 instead of 0 +increase_dim(A::SymmetricTensor{2,dim,T}, ::RightCauchyGreen) where {dim, T} = SymmetricTensor{2,3}((i,j)->(i <= dim && j <= dim ? A[i,j] : ((i==(dim+1) && j==(dim+1)) ? one(T) : zero(T))) ) +increase_dim(A::SymmetricTensor{2,dim,T}, ::GreenLagrange) where {dim, T} = increase_dim(A) +increase_dim(A::SymmetricTensor{2,dim,T}, ::EngineeringStrain) where {dim, T} = increase_dim(A) + +# Pass-through function for 3d +function material_response( + dim::ThreeD{3}, + m::AbstractMaterial, + Δε::AbstractTensor{2,3,T}, + state::AbstractMaterialState, + Δt = nothing; + cache = nothing, + options = Dict{Symbol, Any}(), + ) where {T} + + σ, dσdε, material_state = material_response(m, Δε, state, Δt; cache=cache, options=options) + + return σ, dσdε, material_state +end + # restricted strain states function material_response( - dim::Union{Dim{d}, UniaxialStrain{d}, PlaneStrain{d}}, + dim::Union{UniaxialStrain{d}, PlaneStrain{d}}, m::AbstractMaterial, Δε::AbstractTensor{2,d,T}, state::AbstractMaterialState, @@ -32,7 +56,7 @@ function material_response( options = Dict{Symbol, Any}(), ) where {d,T} - Δε_3D = increase_dim(Δε) + Δε_3D = increase_dim(Δε, strainmeasure(m)) σ, dσdε, material_state = material_response(m, Δε_3D, state, Δt; cache=cache, options=options) return reduce_dim(σ, dim), reduce_dim(dσdε, dim), material_state @@ -53,7 +77,7 @@ function material_response( max_iter = get(options, :plane_stress_max_iter, 10) converged = false - Δε_3D = increase_dim(Δε) + Δε_3D = increase_dim(Δε, strainmeasure(m)) zero_idxs = get_zero_indices(dim, Δε_3D) nonzero_idxs = get_nonzero_indices(dim, Δε_3D)