Files
JuliaFEM.jl/src/materials/abstract_material.jl
T
Jukka Aho 3f5e913e32 refactor(materials): Remove duplicate compute_stress stub
Replace function stub declaration with comment pointing to canonical definition in materials/api.jl. Preserves comprehensive documentation about stress computation interface.

Eliminates documentation replacement warning while maintaining API contract documentation.
2025-11-20 18:23:54 +02:00

233 lines
7.0 KiB
Julia
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Abstract type hierarchy for material models in JuliaFEM.
This module defines the base abstract type `AbstractMaterial` and the standard
interface that all material models must implement.
# Type Hierarchy
```
AbstractMaterial
├── AbstractElasticMaterial (stateless materials)
│ ├── LinearElastic
│ └── NeoHookean
└── AbstractPlasticMaterial (stateful materials)
├── PerfectPlasticity
└── FiniteStrainPlasticity
```
# Interface Requirements
All concrete material types must implement:
```julia
compute_stress(
material::AbstractMaterial,
ε::SymmetricTensor{2,3,T},
state_old,
Δt::Float64
) -> (σ::SymmetricTensor{2,3,T}, 𝔻::SymmetricTensor{4,3,T}, state_new)
```
Where:
- `material` - Material model instance
- `ε` - Strain tensor (small strain or Green-Lagrange for finite strain)
- `state_old` - Material state from previous timestep (`nothing` for stateless)
- `Δt` - Time increment [s]
- `σ` - Stress tensor (Cauchy or 2nd Piola-Kirchhoff)
- `𝔻` - Tangent modulus (∂σ/∂ε)
- `state_new` - Updated material state (`nothing` for stateless)
# Material State Convention
**For stateless materials (elastic):**
- `state_old = nothing`
- `state_new = nothing`
- No history dependence
**For stateful materials (plastic, damage, etc.):**
- `state_old::MaterialState` - Frozen during Newton iterations
- `state_new::MaterialState` - Computed but NOT stored until convergence
- State updated only after successful time step
# Design Principles
1. **Uniform API** - Same function signature for all materials
2. **Type stability** - Concrete return types (no Union types)
3. **Zero allocation** - Stack-allocated tensors (Tensors.jl)
4. **Composability** - Materials work with any element type
5. **GPU-ready** - All operations are POD (plain old data)
# Example Usage
```julia
using Tensors
# Create material
steel = LinearElastic(E=200e9, ν=0.3)
# Define strain
ε = SymmetricTensor{2,3}((0.001, 0.0, 0.0, 0.0, 0.0, 0.0))
# Compute stress
σ, 𝔻, _ = compute_stress(steel, ε, nothing, 0.0)
```
"""
using Tensors
"""
AbstractMaterial
Base abstract type for all material models.
All concrete material types must inherit from this type and implement
the `compute_stress` interface.
# Required Interface
```julia
compute_stress(
material::AbstractMaterial,
ε::SymmetricTensor{2,3,T},
state_old,
Δt::Float64
) where T -> (σ, 𝔻, state_new)
```
# See Also
- [`AbstractElasticMaterial`](@ref) - Base type for stateless materials
- [`AbstractPlasticMaterial`](@ref) - Base type for stateful materials
- [`compute_stress`](@ref) - Standard interface function
"""
# abstract type AbstractMaterial end
# MOVED TO: src/api.jl (included first to avoid order dependencies)
"""
AbstractElasticMaterial <: AbstractMaterial
Base abstract type for stateless elastic materials.
Elastic materials have no internal state variables and stress depends
only on current strain. Examples: LinearElastic, NeoHookean.
For these materials:
- `state_old = nothing`
- `state_new = nothing`
- `compute_stress` is a pure function of strain
# Subtypes
- `LinearElastic` - Linear isotropic elasticity (Hooke's law)
- `NeoHookean` - Hyperelastic material (finite strain)
"""
# abstract type AbstractElasticMaterial <: AbstractMaterial end
# MOVED TO: src/api.jl (included first to avoid order dependencies)
"""
AbstractPlasticMaterial <: AbstractMaterial
Base abstract type for stateful plastic materials.
Plastic materials have internal state variables (e.g., plastic strain)
that evolve during loading. Examples: PerfectPlasticity, FiniteStrainPlasticity.
For these materials:
- `state_old::PlasticityState` - State at beginning of time step
- `state_new::PlasticityState` - State after loading (committed only on convergence)
- History-dependent behavior (path-dependent)
# Subtypes
- `PerfectPlasticity` - Von Mises plasticity without hardening
- `FiniteStrainPlasticity` - Multiplicative plasticity (finite strain)
"""
# abstract type AbstractPlasticMaterial <: AbstractMaterial end
# MOVED TO: src/api.jl (included first to avoid order dependencies)
"""
compute_stress(material, ε, state_old, Δt) -> (σ, 𝔻, state_new)
Standard interface for computing stress and tangent modulus.
This function must be implemented by all concrete material types.
# Arguments
- `material::AbstractMaterial` - Material model instance
- `ε::SymmetricTensor{2,3,T}` - Strain tensor
- Small strain: ε = ½(∇u + ∇uᵀ)
- Large strain: E = ½(FᵀF - I) (Green-Lagrange)
- `state_old` - Material state from previous timestep
- `nothing` for stateless materials (elastic)
- `MaterialState` for stateful materials (plastic, damage, etc.)
- `Δt::Float64` - Time increment [s]
# Returns
- `σ::SymmetricTensor{2,3,T}` - Stress tensor
- Small strain: Cauchy stress
- Large strain: 2nd Piola-Kirchhoff stress
- `𝔻::SymmetricTensor{4,3,T}` - Material tangent modulus (∂σ/∂ε)
- `state_new` - Updated material state
- `nothing` for stateless materials
- `MaterialState` for stateful materials
# Type Constraints
- Input strain `ε` and output stress `σ` have same element type `T`
- Tangent `𝔻` is 4th-order symmetric tensor
- Return type is concrete (no `Any` or `Union`)
# Performance Requirements
- Zero allocations (stack-only computation)
- Type-stable (concrete return types)
- SIMD-friendly (Tensors.jl operations)
# Examples
## Stateless Material (Linear Elastic)
```julia
steel = LinearElastic(E=200e9, ν=0.3)
ε = SymmetricTensor{2,3}((0.001, 0.0, 0.0, 0.0, 0.0, 0.0))
σ, 𝔻, state_new = compute_stress(steel, ε, nothing, 0.0)
@assert state_new === nothing # Stateless
```
## Stateful Material (Perfect Plasticity)
```julia
steel = PerfectPlasticity(E=200e9, ν=0.3, σ_y=250e6)
state₀ = initial_state(steel)
ε = SymmetricTensor{2,3}((0.002, 0.0, 0.0, 0.0, 0.0, 0.0))
σ, 𝔻, state₁ = compute_stress(steel, ε, state₀, 1.0)
@assert state₁ !== state₀ # State evolved
```
# Implementation Notes
## Newton Iteration Compatibility
Material models must be compatible with Newton-Raphson iteration:
- `state_old` is frozen during all Newton iterations
- `state_new` is computed but NOT stored until convergence
- If Newton fails, material state remains unchanged
## Thread Safety
Implementations should be thread-safe:
- No shared mutable state
- Pure functions (for stateless materials)
- State updates are copy-on-write (for stateful materials)
## GPU Compatibility
For GPU compatibility:
- Use only Tensors.jl operations (no dynamic allocations)
- Avoid function pointers or closures in hot paths
- All types should be POD (plain old data)
# See Also
- [`AbstractMaterial`](@ref) - Base abstract type
- [`AbstractElasticMaterial`](@ref) - Stateless materials
- [`AbstractPlasticMaterial`](@ref) - Stateful materials
"""
# Note: compute_stress function stub is defined in materials/api.jl
# Note: Concrete implementations are in separate files:
# - src/materials/linear_elastic.jl
# - src/materials/neo_hookean.jl
# - src/materials/perfect_plasticity.jl
# - src/materials/finite_strain_plasticity.jl