Skip to content

Commit 1adc77a

Browse files
committed
Add stress_ad/tangent_ad helpers and manual stress for SethHill
1 parent a36bc79 commit 1adc77a

File tree

1 file changed

+59
-5
lines changed

1 file changed

+59
-5
lines changed

src/constitutive.jl

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -582,11 +582,65 @@ function constitutive(material::Neohookean, F::SMatrix{3,3,Float64,9})
582582
end
583583

584584
# ---------------------------------------------------------------------------
585-
# AD-based constitutive fallback for Elastic models without a manual
586-
# implementation. Specific methods above take dispatch priority; this
587-
# catches anything else (e.g. SethHill, or new models added by developers).
588-
# Stress (P = ∂W/∂F) and tangent (AA = ∂²W/∂F²) are computed via
589-
# ForwardDiff acting on the strain_energy function.
585+
# AD primitives — composable building blocks for mixed manual/AD constitutive
586+
# implementations. Any Elastic model with a strain_energy method can use
587+
# these independently, e.g. manual stress + AD tangent, or vice-versa.
588+
# ---------------------------------------------------------------------------
589+
590+
function stress_ad(material::Elastic, F::SMatrix{3,3,Float64,9})
591+
Fv = Vector{Float64}(undef, 9)
592+
Fv .= vec(F)
593+
W_func = x -> strain_energy(material, SMatrix{3,3,eltype(x),9}(x))
594+
W = W_func(Fv)
595+
Pv = ForwardDiff.gradient(W_func, Fv)
596+
P = SMatrix{3,3,Float64,9}(reshape(Pv, 3, 3))
597+
return W, P
598+
end
599+
600+
function tangent_ad(material::Elastic, F::SMatrix{3,3,Float64,9})
601+
Fv = Vector{Float64}(undef, 9)
602+
Fv .= vec(F)
603+
W_func = x -> strain_energy(material, SMatrix{3,3,eltype(x),9}(x))
604+
Hmat = ForwardDiff.hessian(W_func, Fv)
605+
return SArray{Tuple{3,3,3,3},Float64,4,81}(reshape(Hmat, 3, 3, 3, 3))
606+
end
607+
608+
# SethHill: manual (W, P) — shares intermediates — plus AD tangent.
609+
function constitutive(material::SethHill, F::SMatrix{3,3,Float64,9})
610+
C = F' * F
611+
F⁻¹ = inv(F)
612+
F⁻ᵀ = F⁻¹'
613+
J = det(F)
614+
Jᵐ = J^material.m
615+
J⁻ᵐ = 1.0 / Jᵐ
616+
J²ᵐ = Jᵐ * Jᵐ
617+
J⁻²ᵐ = 1.0 / J²ᵐ
618+
Cbar = J^(-2 / 3) * C
619+
Cbar⁻¹ = J^(2 / 3) * F⁻¹ * F⁻ᵀ
620+
Cbarⁿ = Cbar^material.n
621+
Cbar⁻ⁿ = Cbar⁻¹^material.n
622+
Cbar²ⁿ = Cbarⁿ * Cbarⁿ
623+
Cbar⁻²ⁿ = Cbar⁻ⁿ * Cbar⁻ⁿ
624+
trCbarⁿ = tr(Cbarⁿ)
625+
trCbar⁻ⁿ = tr(Cbar⁻ⁿ)
626+
trCbar²ⁿ = tr(Cbar²ⁿ)
627+
trCbar⁻²ⁿ = tr(Cbar⁻²ⁿ)
628+
Wbulk = material.κ / 4 / material.m^2 * ((Jᵐ - 1)^2 + (J⁻ᵐ - 1)^2)
629+
Wshear = material.μ / 4 / material.n^2 * (trCbar²ⁿ + trCbar⁻²ⁿ - 2 * trCbarⁿ - 2 * trCbar⁻ⁿ + 6)
630+
W = Wbulk + Wshear
631+
Pbulk = material.κ / 2 / material.m * (J²ᵐ - Jᵐ - J⁻²ᵐ + J⁻ᵐ) * F⁻ᵀ
632+
Pshear =
633+
material.μ / material.n *
634+
(1 / 3 * (-trCbar²ⁿ + trCbarⁿ + trCbar⁻²ⁿ - trCbar⁻ⁿ) * F⁻ᵀ + F⁻ᵀ * (Cbar²ⁿ - Cbarⁿ - Cbar⁻²ⁿ + Cbar⁻ⁿ))
635+
P = Pbulk + Pshear
636+
AA = tangent_ad(material, F)
637+
return W, P, AA
638+
end
639+
640+
# ---------------------------------------------------------------------------
641+
# Full AD fallback for Elastic models without any manual implementation.
642+
# Specific methods above take dispatch priority; this catches anything else
643+
# (e.g. new models added by a developer who only defines strain_energy).
590644
# ---------------------------------------------------------------------------
591645

592646
function constitutive(material::Elastic, F::SMatrix{3,3,Float64,9})

0 commit comments

Comments
 (0)