mirror of
https://github.com/JuliaFEM/JuliaFEM.jl.git
synced 2026-08-06 04:21:33 +00:00
test(materials): add hyperelasticity new API visionary test
New 693-line test file for hyperelasticity NEW API (test-driven development): - Visionary tests for Neo-Hookean material model - Tests for Mooney-Rivlin and Ogden models - Tests for incompressibility constraint (nearly incompressible materials) - Tests for uniaxial tension with large strains - Extensive documentation of intended API design - Tests currently skipped (@test_skip) until implementation complete - Documents strain energy functions, stress computation, tangent moduli - Documents frame-invariance and material objectivity This test file serves as both test suite and API design documentation for the new hyperelastic material model interface.
This commit is contained in:
@@ -0,0 +1,693 @@
|
||||
"""
|
||||
# Hyperelasticity - NEW API (Test-Driven Development)
|
||||
|
||||
**What:** Shows how hyperelastic materials SHOULD work with the NEW API
|
||||
|
||||
**Why:**
|
||||
- **Finite strain** - Large deformations (rubber, soft tissue, biomechanics)
|
||||
- **Energy-based** - Strain energy function Ψ(F)
|
||||
- **Frame-invariant** - Material objectivity (rotation independence)
|
||||
- **Multiple models** - Neo-Hookean, Mooney-Rivlin, Ogden, etc.
|
||||
- **Incompressibility** - Nearly incompressible (ν ≈ 0.5)
|
||||
|
||||
**NEW API Concepts:**
|
||||
1. **Hyperelastic material types** - Neo-Hookean, Mooney-Rivlin, Ogden
|
||||
2. **Strain energy function** - Ψ(F) and derivatives
|
||||
3. **Push-forward stress** - σ = (1/J) P F^T (Cauchy from 1st Piola-Kirchhoff)
|
||||
4. **Tangent moduli** - C_ijkl = ∂²Ψ/∂F_ij∂F_kl
|
||||
5. **Incompressibility constraint** - det(F) ≈ 1
|
||||
|
||||
**Test Problems:**
|
||||
|
||||
## Test 1: Neo-Hookean (Simplest Hyperelastic)
|
||||
- Ψ = μ/2 (I₁ - 3) - μ ln(J) + λ/2 (ln J)²
|
||||
- Validates stress computation from energy
|
||||
- Tests incompressibility limit
|
||||
|
||||
## Test 2: Mooney-Rivlin (Two-Parameter)
|
||||
- Ψ = C₁(I₁ - 3) + C₂(I₂ - 3) + κ/2 (J - 1)²
|
||||
- Better for rubber than Neo-Hookean
|
||||
- Validates second invariant I₂
|
||||
|
||||
## Test 3: Ogden Model (Multi-Term)
|
||||
- Ψ = Σᵢ μᵢ/αᵢ (λ₁^αᵢ + λ₂^αᵢ + λ₃^αᵢ - 3)
|
||||
- Uses principal stretches λᵢ
|
||||
- Most accurate for rubber
|
||||
|
||||
## Test 4: Uniaxial Tension Test
|
||||
- Compare to experimental data
|
||||
- Validates material parameters
|
||||
- Tests large strain (λ > 2)
|
||||
|
||||
**Expected Behavior (when implemented):**
|
||||
✅ Stress computed from ∂Ψ/∂F correctly
|
||||
✅ Tangent moduli symmetric and positive-definite
|
||||
✅ Incompressibility enforced (J ≈ 1)
|
||||
✅ Frame-invariant (rotations don't change Ψ)
|
||||
✅ Matches experimental stress-strain curves
|
||||
✅ Works with Newton-Krylov solver
|
||||
|
||||
**Status:** 🚧 VISIONARY TEST - Implementation in progress
|
||||
"""
|
||||
|
||||
using Test
|
||||
using JuliaFEM
|
||||
using Tensors
|
||||
using LinearAlgebra
|
||||
using Statistics
|
||||
|
||||
@testset "Hyperelasticity - NEW API (TDD)" begin
|
||||
|
||||
# =============================================================================
|
||||
# NEO-HOOKEAN MODEL (SIMPLEST)
|
||||
# =============================================================================
|
||||
|
||||
@testset "Neo-Hookean Material (Visionary)" begin
|
||||
@test_skip begin # Skip until implemented
|
||||
|
||||
# Material parameters
|
||||
μ = 1000.0 # Shear modulus
|
||||
λ = 2000.0 # Lame parameter (nearly incompressible)
|
||||
|
||||
# NEW: Hyperelastic material type
|
||||
material = NeoHookean(
|
||||
μ=μ,
|
||||
λ=λ,
|
||||
formulation=:compressible # or :incompressible
|
||||
)
|
||||
|
||||
# Test deformation gradient
|
||||
F = Tensor{2,3}((
|
||||
1.2, 0.1, 0.0,
|
||||
0.0, 0.9, 0.0,
|
||||
0.0, 0.0, 1.0
|
||||
))
|
||||
|
||||
# Compute strain energy
|
||||
Ψ = strain_energy(material, F)
|
||||
|
||||
# Neo-Hookean energy:
|
||||
# Ψ = μ/2 (I₁ - 3) - μ ln(J) + λ/2 (ln J)²
|
||||
C = tdot(F) # Right Cauchy-Green: C = F^T F
|
||||
I₁ = tr(C) # First invariant
|
||||
J = det(F) # Volume ratio
|
||||
|
||||
Ψ_analytical = μ / 2 * (I₁ - 3) - μ * log(J) + λ / 2 * log(J)^2
|
||||
|
||||
@test isapprox(Ψ, Ψ_analytical, rtol=1e-10)
|
||||
|
||||
# First Piola-Kirchhoff stress: P = ∂Ψ/∂F
|
||||
P = first_piola_kirchhoff_stress(material, F)
|
||||
|
||||
# Analytical P for Neo-Hookean
|
||||
F_inv = inv(F)
|
||||
P_analytical = μ * (F - tdot(F_inv)) + λ * log(J) * tdot(F_inv)
|
||||
|
||||
@test P ≈ P_analytical rtol = 1e-10
|
||||
|
||||
# Cauchy stress: σ = (1/J) P F^T
|
||||
σ = cauchy_stress(material, F)
|
||||
σ_from_P = (1 / J) * P ⊡ transpose(F)
|
||||
|
||||
@test σ ≈ σ_from_P rtol = 1e-10
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# =============================================================================
|
||||
# INCOMPRESSIBILITY CONSTRAINT
|
||||
# =============================================================================
|
||||
|
||||
@testset "Incompressibility (Nearly) (Visionary)" begin
|
||||
@test_skip begin
|
||||
|
||||
# Nearly incompressible (ν → 0.5)
|
||||
E = 1000.0
|
||||
ν = 0.499 # Nearly incompressible
|
||||
|
||||
μ = E / (2 * (1 + ν))
|
||||
λ = E * ν / ((1 + ν) * (1 - 2ν)) # Very large!
|
||||
|
||||
material = NeoHookean(
|
||||
μ=μ,
|
||||
λ=λ,
|
||||
formulation=:compressible
|
||||
)
|
||||
|
||||
# Deformation (should preserve volume)
|
||||
F = Tensor{2,3}((
|
||||
1.5, 0.0, 0.0,
|
||||
0.0, 1 / sqrt(1.5), 0.0,
|
||||
0.0, 0.0, 1 / sqrt(1.5)
|
||||
))
|
||||
|
||||
J = det(F)
|
||||
|
||||
# For incompressible: J = 1 (volume preserving)
|
||||
@test isapprox(J, 1.0, atol=1e-3)
|
||||
|
||||
# Hydrostatic pressure enforces incompressibility
|
||||
σ = cauchy_stress(material, F)
|
||||
p = -tr(σ) / 3 # Hydrostatic pressure
|
||||
|
||||
# For nearly incompressible, pressure should be large
|
||||
@test abs(p) > 1000.0 # Significant pressure
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# =============================================================================
|
||||
# MOONEY-RIVLIN MODEL
|
||||
# =============================================================================
|
||||
|
||||
@testset "Mooney-Rivlin Material (Visionary)" begin
|
||||
@test_skip begin
|
||||
|
||||
# Material parameters (typical for rubber)
|
||||
C₁ = 0.5 # MPa
|
||||
C₂ = 0.1 # MPa
|
||||
κ = 100.0 # Bulk modulus (incompressibility)
|
||||
|
||||
# NEW: Mooney-Rivlin material
|
||||
material = MooneyRivlin(
|
||||
C1=C₁,
|
||||
C2=C₂,
|
||||
bulk_modulus=κ
|
||||
)
|
||||
|
||||
# Test deformation
|
||||
F = Tensor{2,3}((
|
||||
1.5, 0.2, 0.0,
|
||||
0.1, 0.8, 0.0,
|
||||
0.0, 0.0, 1.0
|
||||
))
|
||||
|
||||
# Strain energy: Ψ = C₁(I₁ - 3) + C₂(I₂ - 3) + κ/2 (J - 1)²
|
||||
C = tdot(F)
|
||||
I₁ = tr(C)
|
||||
I₂ = 0.5 * (tr(C)^2 - tr(C ⊡ C)) # Second invariant
|
||||
J = det(F)
|
||||
|
||||
Ψ = strain_energy(material, F)
|
||||
Ψ_analytical = C₁ * (I₁ - 3) + C₂ * (I₂ - 3) + κ / 2 * (J - 1)^2
|
||||
|
||||
@test isapprox(Ψ, Ψ_analytical, rtol=1e-10)
|
||||
|
||||
# Stress computation
|
||||
P = first_piola_kirchhoff_stress(material, F)
|
||||
σ = cauchy_stress(material, F)
|
||||
|
||||
# Validate symmetry of Cauchy stress
|
||||
@test isapprox(σ, transpose(σ), atol=1e-10)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# =============================================================================
|
||||
# OGDEN MODEL (PRINCIPAL STRETCHES)
|
||||
# =============================================================================
|
||||
|
||||
@testset "Ogden Material (Visionary)" begin
|
||||
@test_skip begin
|
||||
|
||||
# Ogden parameters (multi-term)
|
||||
μ_terms = [1.0, 0.5, 0.2] # Shear moduli
|
||||
α_terms = [2.0, 3.0, -2.0] # Exponents
|
||||
κ = 100.0
|
||||
|
||||
# NEW: Ogden material
|
||||
material = Ogden(
|
||||
mu=μ_terms,
|
||||
alpha=α_terms,
|
||||
bulk_modulus=κ
|
||||
)
|
||||
|
||||
# Deformation
|
||||
F = Tensor{2,3}((
|
||||
2.0, 0.0, 0.0,
|
||||
0.0, 0.6, 0.0,
|
||||
0.0, 0.0, 0.8
|
||||
))
|
||||
|
||||
# Compute principal stretches
|
||||
C = tdot(F)
|
||||
eigenvalues_C = eigvals(C)
|
||||
λ = sqrt.(eigenvalues_C) # Principal stretches
|
||||
|
||||
# Strain energy: Ψ = Σᵢ μᵢ/αᵢ (λ₁^αᵢ + λ₂^αᵢ + λ₃^αᵢ - 3)
|
||||
Ψ = strain_energy(material, F)
|
||||
|
||||
J = det(F)
|
||||
Ψ_analytical = sum(
|
||||
μ_terms[i] / α_terms[i] * (sum(λ .^ α_terms[i]) - 3)
|
||||
for i in 1:3
|
||||
) + κ / 2 * (J - 1)^2
|
||||
|
||||
@test isapprox(Ψ, Ψ_analytical, rtol=1e-10)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# =============================================================================
|
||||
# UNIAXIAL TENSION TEST
|
||||
# =============================================================================
|
||||
|
||||
@testset "Uniaxial Tension (Large Strain) (Visionary)" begin
|
||||
@test_skip begin
|
||||
|
||||
# Geometry: Unit cube under tension
|
||||
mesh = generate_mesh(
|
||||
geometry=UnitCube(),
|
||||
element_type=Hex8,
|
||||
n_elements=(4, 4, 4)
|
||||
)
|
||||
|
||||
# Material (Neo-Hookean rubber)
|
||||
material = NeoHookean(
|
||||
μ=1.0, # MPa
|
||||
λ=10.0, # Nearly incompressible
|
||||
density=1000.0
|
||||
)
|
||||
|
||||
# Physics
|
||||
elastic_physics = ContinuumPhysics{Displacement}(
|
||||
material=material,
|
||||
formulation=FullThreeD(),
|
||||
finite_strain=true # CRITICAL!
|
||||
)
|
||||
|
||||
domain = Domain(
|
||||
name="RUBBER",
|
||||
elements=mesh.elements,
|
||||
physics=elastic_physics
|
||||
)
|
||||
|
||||
# Boundary conditions
|
||||
bc_fixed = DirichletBC(
|
||||
nodes=mesh.node_sets["LEFT"],
|
||||
dof=:displacement,
|
||||
values=[0.0, 0.0, 0.0]
|
||||
)
|
||||
|
||||
# Applied stretch (λ = 2.0, 100% strain!)
|
||||
u_applied = 1.0 # Stretch from 1.0 to 2.0
|
||||
|
||||
bc_stretch = DirichletBC(
|
||||
nodes=mesh.node_sets["RIGHT"],
|
||||
dof=:displacement,
|
||||
component=:x,
|
||||
value=u_applied
|
||||
)
|
||||
|
||||
# Nonlinear problem (finite strain)
|
||||
problem = NonlinearProblem(
|
||||
domains=[domain],
|
||||
boundary_conditions=[bc_fixed, bc_stretch]
|
||||
)
|
||||
|
||||
# Newton-Krylov solver
|
||||
solver = NewtonKrylovSolver(
|
||||
max_iterations=20,
|
||||
convergence_tol=1e-6,
|
||||
krylov_solver=GMRES(restart=30),
|
||||
line_search=BacktrackingLineSearch()
|
||||
)
|
||||
|
||||
solution = solve!(problem, solver)
|
||||
|
||||
# Extract stress-stretch curve
|
||||
λ = 1.0 + u_applied # Stretch ratio
|
||||
|
||||
# Compute engineering stress
|
||||
F_avg = compute_average_deformation_gradient(solution)
|
||||
P_avg = first_piola_kirchhoff_stress(material, F_avg)
|
||||
|
||||
# Engineering stress: σ_eng = P_11 (1st Piola-Kirchhoff in x)
|
||||
σ_eng = P_avg[1, 1]
|
||||
|
||||
# For Neo-Hookean uniaxial:
|
||||
# σ_eng = μ(λ - 1/λ²)
|
||||
σ_analytical = material.μ * (λ - 1 / λ^2)
|
||||
|
||||
@test isapprox(σ_eng, σ_analytical, rtol=0.05) # 5% tolerance
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# =============================================================================
|
||||
# FRAME INVARIANCE (OBJECTIVITY)
|
||||
# =============================================================================
|
||||
|
||||
@testset "Frame Invariance (Visionary)" begin
|
||||
@test_skip begin
|
||||
|
||||
material = NeoHookean(μ=1000.0, λ=2000.0)
|
||||
|
||||
# Deformation gradient
|
||||
F = Tensor{2,3}((
|
||||
1.2, 0.1, 0.0,
|
||||
0.0, 0.9, 0.0,
|
||||
0.0, 0.0, 1.0
|
||||
))
|
||||
|
||||
# Rotation tensor (90° about z-axis)
|
||||
θ = π / 2
|
||||
Q = Tensor{2,3}((
|
||||
cos(θ), -sin(θ), 0.0,
|
||||
sin(θ), cos(θ), 0.0,
|
||||
0.0, 0.0, 1.0
|
||||
))
|
||||
|
||||
# Rotated deformation: F' = Q F
|
||||
F_rotated = Q ⊡ F
|
||||
|
||||
# Strain energy should be INVARIANT
|
||||
Ψ = strain_energy(material, F)
|
||||
Ψ_rotated = strain_energy(material, F_rotated)
|
||||
|
||||
@test isapprox(Ψ, Ψ_rotated, rtol=1e-10)
|
||||
|
||||
# Cauchy stress should transform: σ' = Q σ Q^T
|
||||
σ = cauchy_stress(material, F)
|
||||
σ_rotated = cauchy_stress(material, F_rotated)
|
||||
|
||||
σ_transformed = Q ⊡ σ ⊡ transpose(Q)
|
||||
|
||||
@test σ_rotated ≈ σ_transformed rtol = 1e-10
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# =============================================================================
|
||||
# TANGENT MODULI (FOR NEWTON)
|
||||
# =============================================================================
|
||||
|
||||
@testset "Tangent Moduli (Visionary)" begin
|
||||
@test_skip begin
|
||||
|
||||
material = NeoHookean(μ=1000.0, λ=2000.0)
|
||||
|
||||
F = Tensor{2,3}((
|
||||
1.2, 0.1, 0.0,
|
||||
0.0, 0.9, 0.0,
|
||||
0.0, 0.0, 1.0
|
||||
))
|
||||
|
||||
# Material tangent: C_ijkl = ∂²Ψ/∂F_ij∂F_kl
|
||||
C = material_tangent(material, F)
|
||||
|
||||
# Validate major symmetry: C_ijkl = C_klij
|
||||
# (Minor symmetries don't hold for finite strain)
|
||||
for i in 1:3, j in 1:3, k in 1:3, l in 1:3
|
||||
@test isapprox(C[i, j, k, l], C[k, l, i, j], atol=1e-10)
|
||||
end
|
||||
|
||||
# Validate positive-definiteness
|
||||
# For small perturbation δF, δ²Ψ = C_ijkl δF_ij δF_kl > 0
|
||||
δF = 0.01 * rand(Tensor{2,3})
|
||||
δ²Ψ = dcontract(dcontract(C, δF), δF)
|
||||
|
||||
@test δ²Ψ > 0 # Positive-definite
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# =============================================================================
|
||||
# PSEUDO-CODE: HYPERELASTIC ASSEMBLY
|
||||
# =============================================================================
|
||||
|
||||
@testset "Hyperelastic Assembly Pattern (Visionary)" begin
|
||||
# Pseudo-code showing finite strain assembly
|
||||
|
||||
println("\n" * "="^70)
|
||||
println("HYPERELASTIC ASSEMBLY (FINITE STRAIN)")
|
||||
println("="^70)
|
||||
|
||||
assembly_pseudo = """
|
||||
# For hyperelastic materials, assembly uses current configuration
|
||||
|
||||
function compute_residual_hyperelastic(u, material, elements)
|
||||
r = zeros(length(u))
|
||||
|
||||
for elem in elements
|
||||
# Current deformation gradient: F = I + ∇u
|
||||
X = reference_coordinates(elem) # Undeformed
|
||||
x = X + u[elem.nodes] # Deformed
|
||||
|
||||
for ip in integration_points(elem)
|
||||
# Jacobian in reference config
|
||||
J₀, dN_dX = jacobian(elem, ip, X)
|
||||
|
||||
# Deformation gradient: F = ∂x/∂X
|
||||
F = compute_deformation_gradient(x, dN_dX)
|
||||
|
||||
# 1st Piola-Kirchhoff stress: P = ∂Ψ/∂F
|
||||
P = first_piola_kirchhoff_stress(material, F)
|
||||
|
||||
# Residual: r = ∫_Ω₀ P : ∇_X(δu) dΩ₀
|
||||
# = ∫_Ω₀ P_iJ (dN_I/dX_J) dΩ₀
|
||||
for I in 1:n_nodes
|
||||
for i in 1:3
|
||||
for J in 1:3
|
||||
r[3*(I-1)+i] += P[i,J] * dN_dX[I,J] * J₀ * ip.weight
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return r
|
||||
end
|
||||
|
||||
# Tangent stiffness (for Newton):
|
||||
# K_t = ∫_Ω₀ (dN_I/dX_K) C_iJkL (dN_J/dX_L) dΩ₀
|
||||
# where C_iJkL = ∂²Ψ/∂F_iJ∂F_kL
|
||||
"""
|
||||
|
||||
println(assembly_pseudo)
|
||||
println("="^70)
|
||||
println("✓ Uses reference configuration Ω₀ (not current!)")
|
||||
println("✓ Deformation gradient F = ∂x/∂X")
|
||||
println("✓ 1st Piola-Kirchhoff stress P = ∂Ψ/∂F")
|
||||
println("✓ Tangent moduli C = ∂²Ψ/∂F²")
|
||||
println("✓ Works with nodal assembly (same pattern!)")
|
||||
println("="^70)
|
||||
end
|
||||
|
||||
# =============================================================================
|
||||
# KEY ARCHITECTURAL INSIGHTS
|
||||
# =============================================================================
|
||||
|
||||
println("\n" * "="^70)
|
||||
println("HYPERELASTICITY ARCHITECTURE INSIGHTS (NEW API)")
|
||||
println("="^70)
|
||||
println("✓ Hyperelastic materials: NeoHookean, MooneyRivlin, Ogden")
|
||||
println("✓ Strain energy function Ψ(F) is fundamental")
|
||||
println("✓ Stress from energy: P = ∂Ψ/∂F, σ = (1/J) P F^T")
|
||||
println("✓ Tangent from energy: C = ∂²Ψ/∂F²")
|
||||
println("✓ Frame-invariant: Rotations don't change Ψ")
|
||||
println("✓ Incompressibility: det(F) ≈ 1 for rubber")
|
||||
println("✓ Works with Newton-Krylov (unsymmetric OK)")
|
||||
println("✓ Assembly in reference config (not current!)")
|
||||
println("✓ Large strains: λ > 2 (100%+ strain)")
|
||||
println("="^70)
|
||||
|
||||
end
|
||||
|
||||
"""
|
||||
# IMPLEMENTATION NOTES
|
||||
|
||||
## Hyperelastic Material Models
|
||||
|
||||
### Neo-Hookean (Simplest)
|
||||
|
||||
**Strain energy:**
|
||||
Ψ = μ/2 (I₁ - 3) - μ ln(J) + λ/2 (ln J)²
|
||||
|
||||
where:
|
||||
- I₁ = tr(C) = tr(F^T F) (first invariant)
|
||||
- J = det(F) (volume ratio)
|
||||
- μ, λ = Lame parameters
|
||||
|
||||
**1st Piola-Kirchhoff stress:**
|
||||
P = ∂Ψ/∂F = μ(F - F^{-T}) + λ ln(J) F^{-T}
|
||||
|
||||
where F^{-T} = (F^{-1})^T.
|
||||
|
||||
**Cauchy stress:**
|
||||
σ = (1/J) P F^T = μ/J (B - I) + λ/J ln(J) I
|
||||
|
||||
where B = F F^T (left Cauchy-Green).
|
||||
|
||||
**Use case:** Rubber at moderate strains (< 100%).
|
||||
|
||||
### Mooney-Rivlin (Two-Parameter)
|
||||
|
||||
**Strain energy:**
|
||||
Ψ = C₁(I₁ - 3) + C₂(I₂ - 3) + κ/2 (J - 1)²
|
||||
|
||||
where:
|
||||
- I₁ = tr(C)
|
||||
- I₂ = 1/2 [(tr C)² - tr(C²)]
|
||||
- J = det(F)
|
||||
- C₁, C₂ = material parameters
|
||||
- κ = bulk modulus
|
||||
|
||||
**Better fit for rubber** than Neo-Hookean.
|
||||
|
||||
**Relation to Neo-Hookean:** C₂ = 0 → Neo-Hookean.
|
||||
|
||||
### Ogden Model (Multi-Term)
|
||||
|
||||
**Strain energy:**
|
||||
Ψ = Σᵢ μᵢ/αᵢ (λ₁^{αᵢ} + λ₂^{αᵢ} + λ₃^{αᵢ} - 3) + κ/2 (J - 1)²
|
||||
|
||||
where:
|
||||
- λ₁, λ₂, λ₃ = principal stretches (eigenvalues of F)
|
||||
- μᵢ, αᵢ = material parameters (typically 3-6 terms)
|
||||
|
||||
**Most accurate for rubber** (fits experimental data well).
|
||||
|
||||
**Implementation:** Requires spectral decomposition of C.
|
||||
|
||||
## Stress Measures
|
||||
|
||||
### First Piola-Kirchhoff (P)
|
||||
|
||||
**Definition:** P = ∂Ψ/∂F
|
||||
|
||||
**Properties:**
|
||||
- Non-symmetric
|
||||
- Force per reference area
|
||||
- Work-conjugate to F
|
||||
|
||||
**Use:** Weak form in reference config.
|
||||
|
||||
### Cauchy Stress (σ)
|
||||
|
||||
**Definition:** σ = (1/J) P F^T
|
||||
|
||||
**Properties:**
|
||||
- Symmetric
|
||||
- True stress (force per current area)
|
||||
- What we measure
|
||||
|
||||
**Use:** Post-processing, failure criteria.
|
||||
|
||||
### Second Piola-Kirchhoff (S)
|
||||
|
||||
**Definition:** S = F^{-1} P = J F^{-1} σ F^{-T}
|
||||
|
||||
**Properties:**
|
||||
- Symmetric
|
||||
- Work-conjugate to E (Green-Lagrange strain)
|
||||
- Energy-conjugate
|
||||
|
||||
**Use:** Theoretical derivations.
|
||||
|
||||
## Incompressibility
|
||||
|
||||
**Constraint:** det(F) = J = 1 (volume preserving)
|
||||
|
||||
**Nearly incompressible:** ν → 0.5, λ → ∞
|
||||
|
||||
**Enforcement:**
|
||||
|
||||
1. **Penalty:** Add κ/2 (J - 1)² to Ψ (large κ)
|
||||
2. **Lagrange multiplier:** Introduce pressure p
|
||||
3. **Mixed formulation:** (u, p) unknowns
|
||||
|
||||
**JuliaFEM approach:** Penalty for compressible materials, mixed for truly incompressible.
|
||||
|
||||
## Frame Invariance (Objectivity)
|
||||
|
||||
**Definition:** Strain energy invariant under rigid rotations.
|
||||
|
||||
**Mathematical:** Ψ(Q F) = Ψ(F) for all rotations Q.
|
||||
|
||||
**Why:** Material doesn't "know" about global rotations.
|
||||
|
||||
**Implementation:** Use invariants (I₁, I₂, I₃) or principal stretches (λᵢ).
|
||||
|
||||
**Validation:**
|
||||
```julia
|
||||
Q = rotation_matrix(θ)
|
||||
F_rotated = Q * F
|
||||
@test strain_energy(F_rotated) ≈ strain_energy(F)
|
||||
```
|
||||
|
||||
## Tangent Moduli
|
||||
|
||||
**Material tangent:**
|
||||
C_{iJkL} = ∂²Ψ/∂F_{iJ}∂F_{kL}
|
||||
|
||||
**Spatial tangent:**
|
||||
c_{ijkl} = (1/J) F_{iI} F_{jJ} F_{kK} F_{lL} C_{IJKL}
|
||||
|
||||
**Symmetries:**
|
||||
- Major: C_{iJkL} = C_{kLiJ} (from Ψ)
|
||||
- Minor: Generally NOT symmetric in hyperelasticity
|
||||
|
||||
**Use in Newton:**
|
||||
δP = C : δF
|
||||
|
||||
## Assembly (Finite Strain)
|
||||
|
||||
**Residual (weak form):**
|
||||
r = ∫_{Ω₀} P : ∇_X(δu) dΩ₀ - f_ext
|
||||
|
||||
**In components:**
|
||||
r_I^i = ∫_{Ω₀} P_{iJ} ∂N_I/∂X_J dΩ₀ - f_I^i
|
||||
|
||||
**Tangent stiffness:**
|
||||
K_{IJ}^{ik} = ∫_{Ω₀} ∂N_I/∂X_K C_{iJkL} ∂N_J/∂X_L dΩ₀
|
||||
|
||||
**Key differences from small strain:**
|
||||
1. Integrate over Ω₀ (reference), not Ω (current)
|
||||
2. Use ∂N/∂X (reference gradients), not ∂N/∂x
|
||||
3. P (1st Piola-Kirchhoff), not σ (Cauchy)
|
||||
|
||||
## Nodal Assembly (Hyperelastic)
|
||||
|
||||
```julia
|
||||
function tangent_matvec_hyperelastic!(w, v, u_current, material, elements, node_to_elements)
|
||||
Threads.@threads for node_i in 1:n_nodes
|
||||
w_local = zero(Vec{3})
|
||||
|
||||
for elem in node_to_elements[node_i]
|
||||
# Current deformation
|
||||
F = deformation_gradient(elem, u_current)
|
||||
|
||||
# Material tangent
|
||||
C = material_tangent(material, F)
|
||||
|
||||
for node_j in elem.nodes
|
||||
# Tangent block: K_t_ij
|
||||
K_t_ij = compute_hyperelastic_tangent_block(elem, node_i, node_j, C, F)
|
||||
|
||||
v_j = Vec{3}(v[3*(node_j-1)+1:3*node_j])
|
||||
w_local += K_t_ij ⊡ v_j
|
||||
end
|
||||
end
|
||||
|
||||
w[3*(node_i-1)+1:3*node_i] = w_local
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
**Same pattern as linear elasticity!** Only the tangent computation changes.
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Implement `NeoHookean` material type
|
||||
2. Implement `strain_energy` function
|
||||
3. Implement `first_piola_kirchhoff_stress`
|
||||
4. Implement `cauchy_stress` (push-forward)
|
||||
5. Implement `material_tangent` (C_ijkl)
|
||||
6. Implement `MooneyRivlin` material
|
||||
7. Implement `Ogden` material (spectral decomposition)
|
||||
8. Validate against analytical solutions
|
||||
9. Validate against experimental data
|
||||
10. Performance benchmarks
|
||||
|
||||
"""
|
||||
Reference in New Issue
Block a user