Files
JuliaFEM.jl/src/materials_plasticity.jl
T

121 lines
3.9 KiB
Julia
Raw Normal View History

2015-12-09 15:45:15 +02:00
using ForwardDiff
2016-10-03 08:47:20 +03:00
"""
Creating functions for newton: xₙ₊₁ = xₙ - df⁻¹ * f and initial values
"""
function find_root!(f, df, x; max_iter=50, norm_acc=1e-9)
converged = false
for i=1:max_iter
2016-10-02 17:34:05 +03:00
dx = -df(x) \ f(x)
x += dx
2016-10-03 08:47:20 +03:00
norm(dx) < norm_acc && (converged = true; break)
end
2016-10-02 18:43:34 +03:00
converged || error("No convergence in radial return!")
2016-10-02 17:34:05 +03:00
return x
end
2015-12-10 21:16:56 +02:00
2016-10-03 08:47:20 +03:00
"""
Equivalent tensile stress.
More info can be found from: https://en.wikipedia.org/wiki/Von_Mises_yield_criterion
Section: Reduced von Mises equation for different stress conditions
"""
function equivalent_stress(stress, ::Type{Val{:type_3d}})
stress_ten = [stress[1] stress[6] stress[5];
stress[6] stress[2] stress[4];
stress[5] stress[4] stress[3]]
stress_dev = stress_ten - 1/3 * trace(stress_ten) * eye(3)
s = vec(stress_dev)
return sqrt(3/2 * dot(s, s))
end
2015-12-12 15:22:31 +02:00
2016-10-03 08:47:20 +03:00
"""
http://www.efunda.com/formulae/solid_mechanics/mat_mechanics/hooke_plane_stress.cfm
2016-10-03 08:47:20 +03:00
von mises: plane stress
https://andriandriyana.files.wordpress.com/2008/03/yield_criteria.pdf
"""
function equivalent_stress(stress, ::Type{Val{:type_2d}})
s1, s2, t12 = stress
# Calculating principal stresses
# http://www.engineersedge.com/material_science/principal_vonmises_stress__13418.htm
se1 = (s1 + s2)/2 + sqrt(((s1 - s2)/2)^2 + t12^2)
se2 = (s1 + s2)/2 - sqrt(((s1 - s2)/2)^2 + t12^2)
2016-10-02 17:34:05 +03:00
return sqrt(se1^2 -se1*se2 + se2^2)
end
2016-10-03 08:47:20 +03:00
"""
https://andriandriyana.files.wordpress.com/2008/03/yield_criteria.pdf
"""
function yield_function(stress, stress_y, ::Type{Val{:von_mises}}, type_)
equivalent_stress(stress, type_) - stress_y
end
2016-10-03 08:47:20 +03:00
function radial_return(params, dstrain, D, stress_y, stress_base, yield_surface_, type_)
# Creating wrapper for gradient
2016-10-03 08:47:20 +03:00
vm_wrap(stress_) = yield_function(stress_, stress_y, yield_surface_, type_)
2016-10-02 17:34:05 +03:00
dfds = x -> ForwardDiff.gradient(vm_wrap, x)
# Stress rate and total strain
2016-10-03 08:47:20 +03:00
dstress = params[1:end-1]
stress_tot = stress_base + dstress
# Calculating plastic strain rate
dstrain_p = params[end] * dfds(stress_tot)
# Calculating equations
2016-10-02 17:34:05 +03:00
function_1 = dstress - D * (dstrain - dstrain_p)
function_2 = vm_wrap(stress_tot)
[vec(function_1); function_2]
end
2016-10-28 15:46:04 +03:00
function ideal_plasticity!(stress_new, stress_last, dstrain_vec, pstrain, D, params, Dtan, yield_surface_, time, dt, type_)
# Test stress
2016-10-02 17:34:05 +03:00
dstress = vec(D * dstrain_vec)
2016-10-03 08:47:20 +03:00
stress_trial = stress_last + dstress
2016-10-02 17:34:05 +03:00
stress_y = params["yield_stress"]
2016-10-03 08:47:20 +03:00
yield_curr = x -> yield_function(x, stress_y, yield_surface_, type_)
2016-10-02 18:43:34 +03:00
2016-10-03 08:47:20 +03:00
# Calculating and checking for yield
yield = yield_curr(stress_trial)
if isless(yield, 0.0)
2016-10-28 15:46:04 +03:00
2016-10-03 08:47:20 +03:00
stress_new[:] = stress_trial[:]
2016-10-02 17:34:05 +03:00
Dtan[:,:] = D[:,:]
else
2016-10-02 17:34:05 +03:00
# Creating functions for newton: xₙ₊₁ = xₙ - df⁻¹ \ f and initial values
2016-10-03 08:47:20 +03:00
f = stress_ -> radial_return(stress_, dstrain_vec, D, stress_y, stress_last, yield_surface_, type_)
2016-10-02 17:34:05 +03:00
df = x -> ForwardDiff.jacobian(f, x)
2016-10-03 08:47:20 +03:00
# Calculating root (two options)
vals = [vec(stress_trial - stress_last); 0.0]
#results = nlsolve(not_in_place(f), vals).zero
2016-10-02 18:43:34 +03:00
results = find_root!(f, df, vals)
2016-10-02 17:34:05 +03:00
2016-10-02 18:43:34 +03:00
# extracting results
2016-10-03 08:47:20 +03:00
dstress = results[1:end-1]
plastic_multiplier = results[end]
2016-10-02 18:43:34 +03:00
# Updating stress
stress_new[:] = stress_last + dstress
2016-10-28 15:46:04 +03:00
2016-10-02 18:43:34 +03:00
# Calculating plastic strain
2016-10-03 08:47:20 +03:00
dfds_ = x -> ForwardDiff.gradient(yield_curr, x)
2016-10-02 17:34:05 +03:00
dep = plastic_multiplier * dfds_(vec(stress_new))
2016-10-02 18:43:34 +03:00
# Equations for consistent tangent matrix can be found from:
# http://homes.civil.aau.dk/lda/continuum/plast.pdf
# equations: 152 & 153
2016-10-03 08:47:20 +03:00
D2g = x -> ForwardDiff.hessian(yield_curr, x)
2016-10-02 17:34:05 +03:00
Dc = (D^-1 + plastic_multiplier * D2g(stress_new))^-1
dfds = dfds_(stress_new)
2016-10-02 18:43:34 +03:00
Dtan[:,:] = Dc - (Dc * dfds * dfds' * Dc) / (dfds' * Dc * dfds)[1]
2016-10-28 15:46:04 +03:00
pstrain[:] = plastic_multiplier * dfds
end
end