diff --git a/src/materials/abstract_material.jl b/src/materials/abstract_material.jl deleted file mode 100644 index 737a9fc..0000000 --- a/src/materials/abstract_material.jl +++ /dev/null @@ -1,232 +0,0 @@ -""" -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