Files
JuliaFEM.jl/src/problems_elasticity.jl
T

864 lines
28 KiB
Julia
Raw Normal View History

2015-10-28 04:29:14 +02:00
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
2016-07-03 05:01:18 +03:00
""" Elasticity equations.
2016-05-25 22:33:47 +03:00
2016-07-03 05:01:18 +03:00
Field equation is:
2016-08-04 13:15:19 +03:00
2016-07-03 05:01:18 +03:00
m∂²u/∂t² = ∇⋅σ - b
Weak form is: find u∈U such that ∀v in V
δW := ∫ρ₀∂²u/∂t²⋅δu dV₀ + ∫S:δE dV₀ - ∫b₀⋅δu dV₀ - ∫t₀⋅δu dA₀ = 0
where
ρ₀ = density
b₀ = displacement load
t₀ = displacement traction
Formulations
------------
plane stress, plane strain, 3D
References
----------
https://en.wikipedia.org/wiki/Linear_elasticity
https://en.wikipedia.org/wiki/Finite_strain_theory
https://en.wikipedia.org/wiki/Stress_measures
https://en.wikipedia.org/wiki/Mooney%E2%80%93Rivlin_solid
https://en.wikipedia.org/wiki/Strain_energy_density_function
https://en.wikipedia.org/wiki/Plane_stress
https://en.wikipedia.org/wiki/Hooke's_law
2016-05-25 22:33:47 +03:00
"""
2016-02-03 06:49:42 +02:00
type Elasticity <: FieldProblem
# these are found from problem.properties for type Problem{Elasticity}
formulation :: Symbol
finite_strain :: Bool
2016-06-17 16:14:58 +03:00
geometric_stiffness :: Bool
store_fields :: Vector{Symbol}
2016-02-03 06:49:42 +02:00
end
function Elasticity()
# formulations: plane_stress, plane_strain, continuum
2016-06-27 16:11:33 +03:00
return Elasticity(:continuum, false, false, [])
2016-02-03 06:49:42 +02:00
end
2016-05-25 22:33:47 +03:00
function get_unknown_field_name(problem::Problem{Elasticity})
2016-02-03 06:49:42 +02:00
return "displacement"
end
function get_formulation_type(problem::Problem{Elasticity})
return :incremental
end
2016-05-25 22:33:47 +03:00
function assemble!(assembly::Assembly, problem::Problem{Elasticity}, element::Element, time=0.0)
props = problem.properties
2016-02-11 16:16:15 +02:00
gdofs = get_gdofs(problem, element)
formulation = props.formulation
if formulation in [:plane_stress, :plane_strain]
formulation = :plane
end
Km, Kg, f = assemble(problem, element, time, Val{formulation})
add!(assembly.K, gdofs, gdofs, Km)
add!(assembly.Kg, gdofs, gdofs, Kg)
add!(assembly.f, gdofs, f)
2016-05-22 00:22:17 +03:00
end
2016-07-03 05:01:18 +03:00
typealias Elasticity2DSurfaceElements Union{Poi1, Seg2, Seg3}
typealias Elasticity2DVolumeElements Union{Tri3, Tri6, Quad4, Quad8, Quad9}
typealias Elasticity3DSurfaceElements Union{Poi1, Tri3, Tri6, Quad4, Quad8, Quad9}
2016-11-30 16:18:57 +02:00
typealias Elasticity3DVolumeElements Union{Tet4, Wedge6, Wedge15, Hex8, Tet10, Hex20, Hex27}
2016-07-03 05:01:18 +03:00
2016-10-28 15:46:04 +03:00
function initialize_internal_params!(params, ip, type_) #::Type{Val{:type_2d}})
2016-10-09 13:52:21 +03:00
param_keys = keys(params)
all_keys = ip.fields.keys
ip_fields = filter(x->isdefined(all_keys, x), collect(1:length(all_keys)))
if !("params_initialized" in ip_fields)
for key in param_keys
update!(ip, key, 0.0 => params[key])
end
2016-10-28 15:46:04 +03:00
if type_ == Val{:type_2d}
update!(ip, "stress", 0.0 => [0.0,0.0,0.0])
update!(ip, "strain", 0.0 => [0.0,0.0,0.0])
elseif type_ == Val{:type_3d}
update!(ip, "stress", 0.0 => [0.0,0.0,0.0,0.0,0.0,0.0])
update!(ip, "strain", 0.0 => [0.0,0.0,0.0,0.0,0.0,0.0])
else
error("daa")
end
2016-10-09 13:52:21 +03:00
update!(ip, "prev_time", 0.0 => 0.0)
update!(ip, "params_initialized", 0.0 => true)
2016-10-02 17:34:05 +03:00
end
end
2016-07-03 05:01:18 +03:00
2016-10-09 13:52:21 +03:00
function get_keys(element)
all_keys = element.fields.keys
idx = filter(x->isdefined(all_keys, x), collect(1:length(all_keys)))
map(x -> all_keys[x], idx)
end
2016-10-28 15:46:04 +03:00
#function initialize_internal_params!(params, ip_id, ::Type{Val{:type_3d}})
# if !(ip_id in keys(params))
# params[ip_id] = Dict{Any, Any}()
# params[ip_id]["last_stress"] = [0.0,0.0,0.0,0.0,0.0,0.0]
# params[ip_id]["last_strain"] = [0.0,0.0,0.0,0.0,0.0,0.0]
# end
#end
2016-10-03 08:47:20 +03:00
""" Elasticity equations for 2d cases. """
2016-07-03 05:01:18 +03:00
function assemble{El<:Elasticity2DVolumeElements}(problem::Problem{Elasticity}, element::Element{El}, time, ::Type{Val{:plane}})
2016-02-03 06:49:42 +02:00
props = problem.properties
dim = get_unknown_field_dimension(problem)
2016-05-22 00:22:17 +03:00
nnodes = length(element)
BL = zeros(3, dim*nnodes)
BNL = zeros(4, dim*nnodes)
Km = zeros(dim*nnodes, dim*nnodes)
Kg = zeros(dim*nnodes, dim*nnodes)
f = zeros(dim*nnodes)
2016-10-03 08:47:20 +03:00
Dtan = zeros(3,3)
2016-05-25 22:33:47 +03:00
for ip in get_integration_points(element)
2016-05-25 22:33:47 +03:00
detJ = element(ip, time, Val{:detJ})
w = ip.weight*detJ
N = element(ip, time)
dN = element(ip, time, Val{:Grad})
2016-06-19 20:01:37 +03:00
# kinematics
gradu = element("displacement", ip, time, Val{:Grad})
fill!(BL, 0.0)
if props.finite_strain
2016-06-19 20:01:37 +03:00
strain = 1/2*(gradu + gradu' + gradu'*gradu)
F = eye(dim) + gradu
for i=1:size(dN, 2)
BL[1, 2*(i-1)+1] += F[1,1]*dN[1,i]
BL[1, 2*(i-1)+2] += F[2,1]*dN[1,i]
BL[2, 2*(i-1)+1] += F[1,2]*dN[2,i]
BL[2, 2*(i-1)+2] += F[2,2]*dN[2,i]
BL[3, 2*(i-1)+1] += F[1,1]*dN[2,i] + F[1,2]*dN[1,i]
BL[3, 2*(i-1)+2] += F[2,1]*dN[2,i] + F[2,2]*dN[1,i]
end
else # linearized strain
strain = 1/2*(gradu + gradu')
F = eye(dim)
for i=1:size(dN, 2)
BL[1, 2*(i-1)+1] = dN[1,i]
BL[2, 2*(i-1)+2] = dN[2,i]
BL[3, 2*(i-1)+1] = dN[2,i]
BL[3, 2*(i-1)+2] = dN[1,i]
end
end
2016-06-19 20:01:37 +03:00
strain_vec = [strain[1,1]; strain[2,2]; strain[1,2]]
# calculate stress
2016-05-25 22:33:47 +03:00
E = element("youngs modulus", ip, time)
nu = element("poissons ratio", ip, time)
2016-05-22 02:34:38 +03:00
if props.formulation == :plane_stress
D = E/(1.0 - nu^2) .* [
1.0 nu 0.0
nu 1.0 0.0
0.0 0.0 (1.0-nu)/2.0]
elseif props.formulation == :plane_strain
2016-10-03 08:47:20 +03:00
D = E/((1.0+nu)*(1.0-2.0*nu)) .* [
1.0-nu nu 0.0
nu 1.0-nu 0.0
0.0 0.0 (1.0-2.0*nu)/2.0]
2016-05-22 02:34:38 +03:00
else
error("unknown plane formulation: $(props.formulation)")
end
2016-10-09 13:52:21 +03:00
# calculate stress
2016-10-09 13:52:21 +03:00
element_keys = get_keys(element)
if "plasticity" in element_keys
plastic_def = element("plasticity")[ip.id]
calculate_stress! = plastic_def["type"]
2016-10-03 08:47:20 +03:00
yield_surface_ = plastic_def["yield_surface"]
2016-10-02 17:34:05 +03:00
params = plastic_def["params"]
2016-10-09 13:52:21 +03:00
initialize_internal_params!(params, ip, Val{:type_2d})
if time == 0.0
error("Given step time = $(time). Please select time > 0.0")
end
t_last = ip("prev_time", time)
update!(ip, "prev_time", time => t_last)
dt = time - t_last
stress_last = ip("stress", t_last)
strain_last = ip("strain", t_last)
2016-10-02 17:34:05 +03:00
dstrain_vec = strain_vec - strain_last
2016-10-02 18:43:34 +03:00
stress_vec = [0.0, 0.0, 0.0]
2016-10-09 13:52:21 +03:00
calculate_stress!(stress_vec, stress_last, dstrain_vec, D, params, Dtan, yield_surface_, time, dt, Val{:type_2d})
2016-10-02 17:34:05 +03:00
else
stress_vec = D * ([1.0, 1.0, 2.0] .* strain_vec)
2016-10-03 08:47:20 +03:00
Dtan[:,:] = D[:,:]
2016-10-02 17:34:05 +03:00
end
2016-06-27 16:11:33 +03:00
:strain in props.store_fields && update!(ip, "strain", time => strain_vec)
:stress in props.store_fields && update!(ip, "stress", time => stress_vec)
:stress11 in props.store_fields && update!(ip, "stress11", time => stress_vec[1])
:stress22 in props.store_fields && update!(ip, "stress22", time => stress_vec[2])
:stress12 in props.store_fields && update!(ip, "stress12", time => stress_vec[3])
2016-05-25 22:33:47 +03:00
2016-10-02 17:34:05 +03:00
Km += w*BL'*Dtan*BL
2016-10-03 08:47:20 +03:00
2016-10-09 13:52:21 +03:00
2016-06-19 20:01:37 +03:00
# stress = [stress_vec[1] stress_vec[3]; stress_vec[3] stress_vec[2]]
# cauchy_stress = F'*stress*F/det(F)
# cauchy_stress = [cauchy_stress[1,1]; cauchy_stress[2,2]; cauchy_stress[1,2]]
# update!(ip, "cauchy stress", time => cauchy_stress)
2016-08-04 13:15:19 +03:00
2016-06-19 20:01:37 +03:00
# material stiffness end
if props.geometric_stiffness
# take geometric stiffness into account
fill!(BNL, 0.0)
for i=1:size(dN, 2)
BNL[1, 2*(i-1)+1] = dN[1,i]
BNL[2, 2*(i-1)+1] = dN[2,i]
BNL[3, 2*(i-1)+2] = dN[1,i]
BNL[4, 2*(i-1)+2] = dN[2,i]
end
S2 = zeros(2*dim, 2*dim)
S2[1,1] = stress_vec[1]
S2[2,2] = stress_vec[2]
S2[1,2] = S2[2,1] = stress_vec[3]
S2[3:4,3:4] = S2[1:2,1:2]
2016-08-04 13:15:19 +03:00
Kg += w*BNL'*S2*BNL # geometric stiffness
2016-05-25 02:44:29 +03:00
end
2016-06-19 20:01:37 +03:00
# rhs, internal and external load
2016-08-04 13:15:19 +03:00
2016-06-19 20:01:37 +03:00
f -= w*BL'*stress_vec
2016-02-03 06:49:42 +02:00
if haskey(element, "displacement load")
2016-05-25 22:33:47 +03:00
b = element("displacement load", ip, time)
2016-07-03 21:16:03 +03:00
f += w*vec(b*N)
2016-02-03 06:49:42 +02:00
end
2016-06-19 20:01:37 +03:00
2016-05-25 02:44:29 +03:00
for i=1:dim
if haskey(element, "displacement load $i")
2016-05-25 22:33:47 +03:00
b = element("displacement load $i", ip, time)
f[i:dim:end] += w*vec(b*N)
2016-05-25 02:44:29 +03:00
end
end
end
return Km, Kg, f
end
2016-07-03 05:01:18 +03:00
function assemble{El<:Elasticity2DSurfaceElements}(problem::Problem{Elasticity}, element::Element{El}, time::Real, ::Type{Val{:plane}})
props = problem.properties
dim = get_unknown_field_dimension(problem)
2016-06-25 04:12:53 +03:00
nnodes = length(element)
Km = zeros(dim*nnodes, dim*nnodes)
Kg = zeros(dim*nnodes, dim*nnodes)
f = zeros(dim*nnodes)
2016-05-25 22:33:47 +03:00
for ip in get_integration_points(element)
2016-05-25 22:33:47 +03:00
detJ = element(ip, time, Val{:detJ})
w = ip.weight*detJ
N = element(ip, time)
2016-02-03 06:49:42 +02:00
if haskey(element, "displacement traction force")
2016-05-25 22:33:47 +03:00
T = element("displacement traction force", ip, time)
f += w*vec(T*N)
2016-02-03 06:49:42 +02:00
end
for i=1:dim
# traction force for ith component
if haskey(element, "displacement traction force $i")
2016-05-25 22:33:47 +03:00
T = element("displacement traction force $i", ip, time)
f[i:dim:end] += w*vec(T*N)
2016-02-03 06:49:42 +02:00
end
end
if haskey(element, "nt displacement traction force")
# traction force given in normal-tangential direction
2016-05-25 22:33:47 +03:00
T = element("nt displacement traction force", ip, time)
Q = element("normal-tangential coordinates", ip, time)
f += w*vec(Q'*T*N)
2016-02-03 06:49:42 +02:00
end
2016-02-03 06:49:42 +02:00
end
return Km, Kg, f
2016-02-03 06:49:42 +02:00
end
2016-05-30 01:03:34 +03:00
""" Elasticity equations, 3d, linear. """
2016-07-03 05:01:18 +03:00
function assemble{El<:Elasticity3DVolumeElements}(problem::Problem{Elasticity}, element::Element{El}, time::Real, ::Type{Val{:continuum_linear}})
2016-02-11 16:16:15 +02:00
props = problem.properties
dim = get_unknown_field_dimension(problem)
2016-05-30 01:03:34 +03:00
nnodes = length(element)
ndofs = dim*nnodes
BL = zeros(6, ndofs)
Km = zeros(ndofs, ndofs)
Kg = zeros(ndofs, ndofs)
2016-05-30 01:03:34 +03:00
f = zeros(ndofs)
2016-02-03 06:49:42 +02:00
for ip in get_integration_points(element)
detJ = element(ip, time, Val{:detJ})
w = ip.weight*detJ
N = element(ip, time)
dN = element(ip, time, Val{:Grad})
2016-02-11 16:16:15 +02:00
2016-05-30 01:03:34 +03:00
fill!(BL, 0.0)
for i=1:nnodes
BL[1, 3*(i-1)+1] = dN[1,i]
BL[2, 3*(i-1)+2] = dN[2,i]
BL[3, 3*(i-1)+3] = dN[3,i]
BL[4, 3*(i-1)+1] = dN[2,i]
BL[4, 3*(i-1)+2] = dN[1,i]
BL[5, 3*(i-1)+2] = dN[3,i]
BL[5, 3*(i-1)+3] = dN[2,i]
BL[6, 3*(i-1)+1] = dN[3,i]
BL[6, 3*(i-1)+3] = dN[1,i]
2016-05-30 01:03:34 +03:00
end
E = element("youngs modulus", ip, time)
nu = element("poissons ratio", ip, time)
D = E/((1.0+nu)*(1.0-2.0*nu)) * [
1.0-nu nu nu 0.0 0.0 0.0
nu 1.0-nu nu 0.0 0.0 0.0
nu nu 1.0-nu 0.0 0.0 0.0
0.0 0.0 0.0 0.5-nu 0.0 0.0
0.0 0.0 0.0 0.0 0.5-nu 0.0
0.0 0.0 0.0 0.0 0.0 0.5-nu]
Km += w*BL'*D*BL
2016-05-30 01:03:34 +03:00
if haskey(element, "displacement load")
T = element("displacement load", ip, time)
f += w*vec(T*N)
end
for i=1:dim
if haskey(element, "displacement load $i")
b = element("displacement load $i", ip, time)
f[i:dim:end] += w*vec(b*N)
end
end
end
if get_formulation_type(problem) == :incremental
2016-02-11 16:16:15 +02:00
if haskey(element, "displacement")
2016-05-30 01:03:34 +03:00
u = vec(element["displacement"](time))
f -= Kt*u
end
2016-05-30 01:03:34 +03:00
end
return Km, Kg, f
2016-05-30 01:03:34 +03:00
end
""" Material and geometric stiffness for linear buckling analysis. """
2016-07-03 05:01:18 +03:00
function assemble{El<:Elasticity3DVolumeElements}(problem::Problem{Elasticity}, element::Element{El}, time::Real, ::Type{Val{:continuum_buckling}})
2016-05-30 01:03:34 +03:00
props = problem.properties
dim = get_unknown_field_dimension(problem)
nnodes = length(element)
ndofs = dim*nnodes
BL = zeros(6, ndofs)
BNL = zeros(9, ndofs)
Km = zeros(ndofs, ndofs)
Kg = zeros(ndofs, ndofs)
f = zeros(ndofs)
2016-05-30 01:03:34 +03:00
for ip in get_integration_points(element)
detJ = element(ip, time, Val{:detJ})
w = ip.weight*detJ
N = element(ip, time)
dN = element(ip, time, Val{:Grad})
gradu = element("displacement", ip, time, Val{:Grad})
strain = 1/2*(gradu' + gradu)
fill!(BL, 0.0)
for i=1:nnodes
BL[1, 3*(i-1)+1] = dN[1,i]
BL[2, 3*(i-1)+2] = dN[2,i]
BL[3, 3*(i-1)+3] = dN[3,i]
BL[4, 3*(i-1)+1] = dN[2,i]
BL[4, 3*(i-1)+2] = dN[1,i]
BL[5, 3*(i-1)+2] = dN[3,i]
BL[5, 3*(i-1)+3] = dN[2,i]
BL[6, 3*(i-1)+1] = dN[3,i]
BL[6, 3*(i-1)+3] = dN[1,i]
2016-05-30 01:03:34 +03:00
end
fill!(BNL, 0.0)
for i=1:size(dN, 2)
BNL[1, 3*(i-1)+1] = dN[1,i]
BNL[2, 3*(i-1)+1] = dN[2,i]
BNL[3, 3*(i-1)+1] = dN[3,i]
BNL[4, 3*(i-1)+2] = dN[1,i]
BNL[5, 3*(i-1)+2] = dN[2,i]
BNL[6, 3*(i-1)+2] = dN[3,i]
BNL[7, 3*(i-1)+3] = dN[1,i]
BNL[8, 3*(i-1)+3] = dN[2,i]
BNL[9, 3*(i-1)+3] = dN[3,i]
2016-02-11 16:16:15 +02:00
end
E = element("youngs modulus", ip, time)
nu = element("poissons ratio", ip, time)
2016-05-25 02:44:29 +03:00
D = E/((1.0+nu)*(1.0-2.0*nu)) * [
1.0-nu nu nu 0.0 0.0 0.0
nu 1.0-nu nu 0.0 0.0 0.0
nu nu 1.0-nu 0.0 0.0 0.0
0.0 0.0 0.0 0.5-nu 0.0 0.0
0.0 0.0 0.0 0.0 0.5-nu 0.0
0.0 0.0 0.0 0.0 0.0 0.5-nu]
2016-02-11 16:16:15 +02:00
strain_vec = [strain[1,1]; strain[2,2]; strain[3,3]; strain[1,2]; strain[2,3]; strain[1,3]]
stress_vec = D * ([1.0, 1.0, 1.0, 2.0, 2.0, 2.0].*strain_vec)
2016-05-30 01:03:34 +03:00
S3 = zeros(3*dim, 3*dim)
S3[1,1] = stress_vec[1]
S3[2,2] = stress_vec[2]
S3[3,3] = stress_vec[3]
S3[1,2] = S3[2,1] = stress_vec[4]
S3[2,3] = S3[3,2] = stress_vec[5]
S3[1,3] = S3[3,1] = stress_vec[6]
2016-05-30 01:03:34 +03:00
S3[4:6,4:6] = S3[7:9,7:9] = S3[1:3,1:3]
2016-05-30 01:03:34 +03:00
Km += w*BL'*D*BL
Kg += w*BNL'*S3*BNL
2016-05-30 01:03:34 +03:00
end
return Km, Kg, f
2016-05-30 01:03:34 +03:00
end
""" Elasticity equations, 3d nonlinear. """
2016-07-03 05:01:18 +03:00
function assemble{El<:Elasticity3DVolumeElements}(problem::Problem{Elasticity}, element::Element{El}, time::Real, ::Type{Val{:continuum}})
2016-05-30 01:03:34 +03:00
props = problem.properties
dim = get_unknown_field_dimension(problem)
nnodes = length(element)
ndofs = dim*nnodes
BL = zeros(6, ndofs)
BNL = zeros(9, ndofs)
Km = zeros(ndofs, ndofs)
Kg = zeros(ndofs, ndofs)
2016-05-30 01:03:34 +03:00
f = zeros(ndofs)
for ip in get_integration_points(element)
detJ = element(ip, time, Val{:detJ})
w = ip.weight*detJ
N = element(ip, time)
dN = element(ip, time, Val{:Grad})
# kinematics; calculate deformation gradient and strain
gradu = zeros(dim, dim)
if haskey(element, "displacement")
gradu += element("displacement", ip, time, Val{:Grad})
end
2016-06-17 16:14:58 +03:00
strain = 1/2*(gradu' + gradu)
2016-05-30 01:03:34 +03:00
F = eye(dim)
if props.finite_strain
F += gradu
strain += 1/2*gradu'*gradu
end
2016-02-11 16:16:15 +02:00
2016-06-17 16:14:58 +03:00
# material stiffness start
2016-02-11 16:16:15 +02:00
fill!(BL, 0.0)
2016-05-30 01:03:34 +03:00
for i=1:nnodes
2016-02-11 16:16:15 +02:00
BL[1, 3*(i-1)+1] = F[1,1]*dN[1,i]
BL[1, 3*(i-1)+2] = F[2,1]*dN[1,i]
BL[1, 3*(i-1)+3] = F[3,1]*dN[1,i]
BL[2, 3*(i-1)+1] = F[1,2]*dN[2,i]
BL[2, 3*(i-1)+2] = F[2,2]*dN[2,i]
BL[2, 3*(i-1)+3] = F[3,2]*dN[2,i]
BL[3, 3*(i-1)+1] = F[1,3]*dN[3,i]
BL[3, 3*(i-1)+2] = F[2,3]*dN[3,i]
BL[3, 3*(i-1)+3] = F[3,3]*dN[3,i]
BL[4, 3*(i-1)+1] = F[1,1]*dN[2,i] + F[1,2]*dN[1,i]
BL[4, 3*(i-1)+2] = F[2,1]*dN[2,i] + F[2,2]*dN[1,i]
BL[4, 3*(i-1)+3] = F[3,1]*dN[2,i] + F[3,2]*dN[1,i]
BL[5, 3*(i-1)+1] = F[1,2]*dN[3,i] + F[1,3]*dN[2,i]
BL[5, 3*(i-1)+2] = F[2,2]*dN[3,i] + F[2,3]*dN[2,i]
BL[5, 3*(i-1)+3] = F[3,2]*dN[3,i] + F[3,3]*dN[2,i]
BL[6, 3*(i-1)+1] = F[1,3]*dN[1,i] + F[1,1]*dN[3,i]
BL[6, 3*(i-1)+2] = F[2,3]*dN[1,i] + F[2,1]*dN[3,i]
BL[6, 3*(i-1)+3] = F[3,3]*dN[1,i] + F[3,1]*dN[3,i]
2016-02-03 06:49:42 +02:00
end
2016-05-25 02:44:29 +03:00
2016-06-17 16:14:58 +03:00
strain_vec = [strain[1,1]; strain[2,2]; strain[3,3]; strain[1,2]; strain[2,3]; strain[1,3]]
2016-05-30 01:03:34 +03:00
2016-06-17 16:14:58 +03:00
# calculate stress
2016-05-30 01:03:34 +03:00
E = element("youngs modulus", ip, time)
nu = element("poissons ratio", ip, time)
D = E/((1.0+nu)*(1.0-2.0*nu)) * [
1.0-nu nu nu 0.0 0.0 0.0
nu 1.0-nu nu 0.0 0.0 0.0
nu nu 1.0-nu 0.0 0.0 0.0
0.0 0.0 0.0 0.5-nu 0.0 0.0
0.0 0.0 0.0 0.0 0.5-nu 0.0
0.0 0.0 0.0 0.0 0.0 0.5-nu]
2016-10-03 08:47:20 +03:00
element_keys = get_keys(element)
if "plasticity" in element_keys
2016-10-28 15:46:04 +03:00
plastic_def = element("plasticity")[ip.id]
calculate_stress! = plastic_def["type"]
yield_surface_ = plastic_def["yield_surface"]
params = plastic_def["params"]
initialize_internal_params!(params, ip, Val{:type_3d})
if time == 0.0
error("Given step time = $(time). Please select time > 0.0")
end
t_last = ip("prev_time", time)
update!(ip, "prev_time", time => t_last)
dt = time - t_last
stress_last = ip("stress", t_last)
strain_last = ip("strain", t_last)
dstrain_vec = strain_vec - strain_last
stress_vec = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
plastic_strain = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
Dtan = [0.0 0.0 0.0 0.0 0.0 0.0;
0.0 0.0 0.0 0.0 0.0 0.0;
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0;
0.0 0.0 0.0 0.0 0.0 0.0;
0.0 0.0 0.0 0.0 0.0 0.0]
calculate_stress!(stress_vec, stress_last, dstrain_vec, plastic_strain, D, params, Dtan, yield_surface_, time, dt, Val{:type_3d})
# plastic_def = element.dev["plasticity"]
# calculate_stress! = plastic_def["stress"]
# params = plastic_def["params"]
# yield_surface_ = plastic_def["yield_surface"]
# (stress_last, strain_last) = get_internal_params(element.dev, ip.id, Val{:type_3d})
# dstrain_vec = strain_vec - strain_last
# calculate_stress!(stress_vec, stress_last, dstrain_vec, D, params, Dtan, yield_surface_, Val{:type_3d})
2016-10-03 08:47:20 +03:00
else
2016-10-28 15:46:04 +03:00
2016-10-03 08:47:20 +03:00
stress_vec = D * ([1.0, 1.0, 1.0, 2.0, 2.0, 2.0].*strain_vec)
Dtan = D
end
2016-06-27 16:11:33 +03:00
:strain in props.store_fields && update!(ip, "strain", time => strain_vec)
:stress in props.store_fields && update!(ip, "stress", time => stress_vec)
:stress11 in props.store_fields && update!(ip, "stress11", time => stress_vec[1])
:stress22 in props.store_fields && update!(ip, "stress22", time => stress_vec[2])
:stress33 in props.store_fields && update!(ip, "stress33", time => stress_vec[3])
:stress12 in props.store_fields && update!(ip, "stress12", time => stress_vec[4])
:stress23 in props.store_fields && update!(ip, "stress23", time => stress_vec[5])
:stress13 in props.store_fields && update!(ip, "stress13", time => stress_vec[6])
2016-10-28 15:46:04 +03:00
:plastic_strain in props.store_fields && update!(ip, "plastic_strain", time => plastic_strain)
2016-05-30 01:03:34 +03:00
2016-10-03 08:47:20 +03:00
Km += w*BL'*Dtan*BL
2016-05-30 01:03:34 +03:00
# material stiffness end
2016-06-19 20:01:37 +03:00
if props.geometric_stiffness
# take geometric stiffness into account
2016-05-30 01:03:34 +03:00
2016-06-17 16:14:58 +03:00
fill!(BNL, 0.0)
for i=1:size(dN, 2)
BNL[1, 3*(i-1)+1] = dN[1,i]
BNL[2, 3*(i-1)+1] = dN[2,i]
BNL[3, 3*(i-1)+1] = dN[3,i]
BNL[4, 3*(i-1)+2] = dN[1,i]
BNL[5, 3*(i-1)+2] = dN[2,i]
BNL[6, 3*(i-1)+2] = dN[3,i]
BNL[7, 3*(i-1)+3] = dN[1,i]
BNL[8, 3*(i-1)+3] = dN[2,i]
BNL[9, 3*(i-1)+3] = dN[3,i]
end
S3 = zeros(3*dim, 3*dim)
S3[1,1] = stress_vec[1]
S3[2,2] = stress_vec[2]
S3[3,3] = stress_vec[3]
S3[1,2] = S3[2,1] = stress_vec[4]
S3[2,3] = S3[3,2] = stress_vec[5]
S3[1,3] = S3[3,1] = stress_vec[6]
S3[4:6,4:6] = S3[7:9,7:9] = S3[1:3,1:3]
2016-02-11 16:16:15 +02:00
Kg += w*BNL'*S3*BNL
2016-05-25 02:44:29 +03:00
2016-06-17 16:14:58 +03:00
end
2016-05-30 01:03:34 +03:00
# external load start
2016-02-11 16:16:15 +02:00
2016-02-03 06:49:42 +02:00
if haskey(element, "displacement load")
2016-02-11 16:16:15 +02:00
T = element("displacement load", ip, time)
f += w*vec(T*N)
2016-02-03 06:49:42 +02:00
end
2016-06-17 16:14:58 +03:00
2016-05-25 02:44:29 +03:00
for i=1:dim
if haskey(element, "displacement load $i")
b = element("displacement load $i", ip, time)
f[i:dim:end] += w*vec(b*N)
2016-05-25 02:44:29 +03:00
end
end
2016-02-11 16:16:15 +02:00
2016-05-30 01:03:34 +03:00
# external load end
2016-06-17 16:14:58 +03:00
if get_formulation_type(problem) == :incremental
f -= w*BL'*stress_vec
end
end
return Km, Kg, f
2016-02-11 16:16:15 +02:00
end
""" Elasticity equations, surface traction for continuum formulation. """
2016-07-03 05:01:18 +03:00
function assemble{El<:Elasticity3DSurfaceElements}(problem::Problem{Elasticity}, element::Element{El}, time::Real, ::Type{Val{:continuum}})
2016-02-11 16:16:15 +02:00
props = problem.properties
dim = get_unknown_field_dimension(problem)
nnodes = size(element, 2)
Km = zeros(dim*nnodes, dim*nnodes)
Kg = zeros(dim*nnodes, dim*nnodes)
2016-02-11 16:16:15 +02:00
f = zeros(dim*nnodes)
2016-07-14 12:43:41 +03:00
has_concentrated_forces = false
for ip in get_integration_points(element)
detJ = element(ip, time, Val{:detJ})
w = ip.weight*detJ
N = element(ip, time)
2016-02-03 06:49:42 +02:00
if haskey(element, "displacement traction force")
T = element("displacement traction force", ip, time)
f += w*vec(T*N)
2016-02-03 06:49:42 +02:00
end
2016-02-11 16:16:15 +02:00
for i in 1:dim
if haskey(element, "displacement traction force $i")
T = element("displacement traction force $i", ip, time)
f[i:dim:end] += w*vec(T*N)
2016-02-03 06:49:42 +02:00
end
2016-07-14 12:43:41 +03:00
if haskey(element, "concentrated force $i")
has_concentrated_forces = true
T = element("concentrated force $i", ip, time)
f[i:dim:end] += w*vec(T*N)
end
2016-02-03 06:49:42 +02:00
end
if haskey(element, "surface pressure")
2016-05-31 00:31:43 +03:00
J = element(ip, time, Val{:Jacobian})'
n = cross(J[:,1], J[:,2])
n /= norm(n)
# sign convention, positive pressure is towards surface
p = -element("surface pressure", ip, time)
2016-05-31 00:31:43 +03:00
f += w*p*vec(n*N)
end
2016-02-03 06:49:42 +02:00
end
2016-07-14 12:43:41 +03:00
if has_concentrated_forces
update!(element, "concentrated force", time => Any[f])
end
return Km, Kg, f
2016-02-03 06:49:42 +02:00
end
2016-07-03 05:01:18 +03:00
function assemble{El<:Elasticity3DSurfaceElements}(problem::Problem{Elasticity}, element::Element{El}, time::Real, ::Type{Val{:continuum_linear}})
2016-05-30 01:03:34 +03:00
return assemble(problem, element, time, Val{:continuum})
end
2016-02-23 15:00:30 +02:00
""" Elasticity equations using ForwardDiff
"""
function assemble(problem::Problem{Elasticity}, element::Element, time::Real, ::Type{Val{:forwarddiff}})
dim = get_unknown_field_dimension(problem)
nnodes = size(element, 2)
function get_residual_vector(u::Vector)
u = reshape(u, dim, nnodes)
u = Field([u[:,i] for i=1:nnodes])
r = zeros(dim, nnodes)
for ip in get_integration_points(element)
JT = transpose(get_jacobian(element, ip, time))
n, m = size(JT)
if n == m
w = ip.weight*det(JT)
elseif m == 1
w = ip.weight*norm(JT)
elseif m == 2
w = ip.weight*norm(cross(JT[:,1], JT[:,2]))
else
error("jacobian $JT")
end
# calculate internal forces
if haskey(element, "youngs modulus") && haskey(element, "poissons ratio")
grad = element(ip, time, Val{:grad})
gradu = grad*u
# kinematics
F = I + gradu
E = 1/2*(F'*F - I)
# material
young = element("youngs modulus", ip, time)
poisson = element("poissons ratio", ip, time)
mu = young/(2*(1+poisson))
lambda = young*poisson/((1+poisson)*(1-2*poisson))
if problem.properties.formulation == :plane_stress
lambda = 2*lambda*mu/(lambda + 2*mu) # <- correction for plane stress
end
# stress
S = lambda*trace(E)*I + 2*mu*E
r += w*F*S*grad
end
# calculate external forces - volume load
if haskey(element, "displacement load")
basis = element(ip, time)
b = element("displacement load", ip, time)
r -= w*b*basis
end
# external forces - surface traction force
if haskey(element, "displacement traction force")
basis = element(ip, time)
T = element("displacement traction force", ip, time)
r -= w*T*basis
end
end
return vec(r)
end
field = element("displacement", time)
Km, allresults = ForwardDiff.jacobian(get_residual_vector, vec(field),
2016-02-23 15:00:30 +02:00
AllResults, cache=autodiffcache)
Kg = zeros(Km)
2016-02-23 15:00:30 +02:00
f = -ForwardDiff.value(allresults)
return Km, Kg, f
2016-02-23 15:00:30 +02:00
end
2016-02-03 06:49:42 +02:00
###############################
# Plastic material #
###############################
#=
include("vonmises.jl")
abstract PlaneStressLinearElasticPlasticProblem <: LinearElasticityProblem
function PlaneStressLinearElasticPlasticProblem(name="plane stress linear elasticity", dim::Int=2, elements=[])
return Problem{PlaneStressLinearElasticPlasticProblem}(name, dim, elements)
end
""" Elasticity equations, plane stress. """
function assemble!{E<:CG, P<:PlaneStressLinearElasticPlasticProblem}(assembly::Assembly, problem::Problem{P}, element::Element{E}, time::Real)
gdofs = get_gdofs(element, problem.dim)
ndim, nnodes = size(E)
B = zeros(3, 2*nnodes)
for ip in get_integration_points(element)
w = ip.weight
J = get_jacobian(element, ip, time)
N = element(ip, time)
if haskey(element, "youngs modulus") && haskey(element, "poissons ratio")
nu = element("poissons ratio", ip, time)
E_ = element("youngs modulus", ip, time)
C = E_/(1.0 - nu^2) .* [
1.0 nu 0.0
nu 1.0 0.0
0.0 0.0 (1.0-nu)/2.0]
dN = element(ip, time, Val{:grad})
fill!(B, 0.0)
for i=1:size(dN, 2)
B[1, 2*(i-1)+1] = dN[1,i]
B[2, 2*(i-1)+2] = dN[2,i]
B[3, 2*(i-1)+1] = dN[2,i]
B[3, 2*(i-1)+2] = dN[1,i]
end
add!(assembly.stiffness_matrix, gdofs, gdofs, w*B'*C*B*det(J))
end
if haskey(element, "displacement load")
b = element("displacement load", ip, time)
add!(assembly.force_vector, gdofs, w*N'*b*det(J))
end
if haskey(element, "displacement traction force")
T = element("displacement traction force", ip, time)
L = w*T*N*norm(J)
add!(assembly.force_vector, gdofs, vec(L))
end
end
end
include("elasticplastic.jl")
2015-12-12 15:22:31 +02:00
2015-10-28 04:29:14 +02:00
# Elasticity problems
abstract ElasticityProblem <: AbstractProblem
abstract PlaneStressElasticityProblem <: ElasticityProblem
2015-10-28 04:29:14 +02:00
2015-11-27 10:10:00 +02:00
function get_unknown_field_name{P<:ElasticityProblem}(::Type{P})
return "displacement"
end
2015-10-28 04:29:14 +02:00
2015-11-27 10:10:00 +02:00
function get_unknown_field_type{P<:ElasticityProblem}(::Type{P})
return Vector{Float64}
2015-10-28 04:29:14 +02:00
end
2015-12-17 15:47:36 +02:00
2016-02-03 06:49:42 +02:00
=#
2016-07-14 12:43:41 +03:00
2016-11-13 13:24:08 +02:00
function (problem::Problem)(element::Element, ip, time::Float64, ::Type{Val{:E}})
2016-07-14 12:43:41 +03:00
haskey(element, "displacement") || return nothing
gradu = element("displacement", ip, time, Val{:Grad})
eps = 0.5*(gradu + gradu')
return eps
end
2016-11-13 13:24:08 +02:00
function (problem::Problem)(element::Element, ip, time::Float64, ::Type{Val{:S}})
2016-07-14 12:43:41 +03:00
haskey(element, "displacement") || return nothing
props = problem.properties
eps = problem(element, ip, time, Val{:E})
eps == nothing && return nothing
E = element("youngs modulus", ip, time)
nu = element("poissons ratio", ip, time)
mu = E/(2.0*(1.0+nu))
la = E*nu/((1.0+nu)*(1.0-2.0*nu))
if props.formulation in [:plane_stress, :plane_strain]
la = 2.0*la*mu/(la+2.0*mu)
end
S = la*trace(eps)*I + 2.0*mu*eps
return S
end
2016-11-13 13:24:08 +02:00
function (problem::Problem)(element::Element, ip, time::Float64, ::Type{Val{:COORD}})
2016-07-14 12:43:41 +03:00
haskey(element, "geometry") || return nothing
return element("geometry", ip, time)
end