Skip to content

Epic: generated mixed-type return-map materials with consistent tangent (graph-coupled) #102

Description

@petlenz

Goal

Generate a mixed-type local return-map material — one whose internal state is a vector of heterogeneous unknowns (scalars, tensor-to-scalar quantities, symmetric/general tensors) solved together by a local Newton iteration — together with its consistent tangent dσ/dε, on the graph-coupled NumSimMaterialTarget path.

This epic is the umbrella that sequences the already-filed slices (#86, #92, #35, #85) and their cross-repo dependencies (numsim-materials#11/#12) into one end-to-end feature. It does not restate their designs — see each issue.

Where we are: the scalar case is shipped

PR #101 (Phase 2b) emits the N = 1 scalar special case end-to-end: a state z solving R(z, ε) = 0 via backward_euler, plus the closed-form consistent tangent

dσ/dε = ∂σ/∂ε + ∂σ/∂z · (−∂R/∂ε / ∂R/∂z)

Because the state is scalar, ∂R/∂z is a scalar → the correction is a division, no inverse, no flattening. emit_residual_material() hard-rejects anything larger:

reqs.size() != 1 || svs.size() != 1"supports exactly one scalar state variable … coupled multi-state return maps need the numsim-materials vector solver (numsim-materials#12)."

So the general case is loudly gated, not silently broken.

What changes for a vector/mixed-type state

The math generalizes by the implicit-function theorem, but the scalar reciprocal becomes a block matrix solve:

(∂R/∂X) · dX/dε = −∂R/∂ε            dσ/dε = ∂σ/∂ε + ∂σ/∂X · dX/dε

∂R/∂X is a heterogeneous block Jacobian; every block is a CAS diff already available (all verified against the pin in PR 2b):

∂Rᵢ / ∂xⱼ xⱼ scalar / t2s (1 DOF) xⱼ tensor (6 DOF, Mandel)
Rᵢ scalar / t2s diff(scalar/t2s, scalar) → scalar diff(t2s, tensor) → rank-2
Rᵢ tensor diff(tensor, scalar) → rank-2 (cas#275) diff(tensor, tensor) → rank-4

A tensor-to-scalar unknown is scalar-valued (1 DOF) — its tensor character only shows up in the coupling-derivative shapes, so the flattening collapses to two classes: scalar (1) and symmetric-tensor (6, Mandel). CAS provides every derivative block already — the missing pieces are runtime linear algebra, not symbolic.

The deliberate architectural consequence (roadmap D14/D16): codegen emits the blocks and the numsim-materials vector solver assembles the tangent numerically, reusing its factorized Newton Jacobian — no symbolic rank-4 inverse is emitted (keeps cas#276/#250/#287 off the primary path).

Work breakdown (existing issues — this epic sequences, does not duplicate)

codegen

numsim-materials (runtime deps)

  • numsim-materials#11 — Mandel transform utilities (sym tensor ↔ 6-vector, rank-4 ↔ 6×6).
  • numsim-materials#12 — generic vector/tensor-valued local Newton solver (current solvers are scalar-only); it owns the dense solve (Eigen, D6′) and reuses the factorization for the tangent (D16).

verification

Acceptance criterion

A generated J2 plasticity with kinematic hardening — state = Δγ (scalar) + back-stress X (symmetric tensor) — solved as one coupled local Newton, with its consistent tangent FD-verified end-to-end through the real solver (Phase E golden).

Corrections / status notes

Dependencies at a glance

#101 (scalar case, DONE) ──▶ this epic
   ├─ codegen:   #92, #86, #85, recipe API
   ├─ materials: #11 (Mandel), #12 (vector solver)   ← hard runtime prereqs
   ├─ verify:    #90
   └─ KT/switched (#35) — unblocked (cas#241 closed), greenfield

Roadmap reference: do-a-detailed-review-dreamy-giraffe.md, Phases B/D/E.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions