Skip to content

CalculiX stateful path: emit against numsim-materials' calculix_interface.h instead of hand-rolling STATEV/TIME/orientation #160

Description

@petlenz

Context

CalculiXExternalTarget (#127) emits a self-contained CalculiX external behaviour for stateless recipes. Its own header already names the sequel:

SCOPE (first cut, linear elasticity): stateless recipes only ... State variables (the STATEV round-trip) are the numsim-materials-backed follow-up.

That follow-up now exists: numsim-materials PR #51 adds umat/calculix_interface.h, a tested adapter for the native call_external_umat_user hook (NUMSIM_MATERIALS_DEFINE_CALCULIX_BEHAVIOUR(TRAITS, FUNC, MODELNAME)) that marshals CalculiX's conventions onto the existing umat_dispatch / umat_registry / material_point_evaluator stack.

This issue is to build the stateful path on that, rather than growing the hand-rolled marshalling.

Why this matters more than ordinary dedup

The emitted entry currently comments out exactly the arguments that only matter once a material has state:

/*iel*/  /*iint*/  /*mi*/  /*NSTATV*/  /*time*/  /*ttime*/  /*iorien*/

That is correct today — stateless, time-independent elasticity needs none of them. But each is a silent-wrong-answer trap the moment state appears. The review of PR #51 found three of them in a freshly written adapter, all invisible under exactly the elastic/one-increment/point-(1,1) configuration this target is scoped to:

  1. STATEV indexed at point (1,1) for every integration point. ccx passes the whole xstate(nstate_, mi(1), *) array base (umat_main.f:40,233), not a per-point slice as umat_abaqus.f:295 does, so the callee must index at nstatv*((iint-1) + mi1*(iel-1)). Every Gauss point otherwise shares one slot.
  2. TIME not rebased. ccx gives step time at the increment END and total time at the STEP start; the Abaqus convention wants both rebased onto the increment start (umat_abaqus.f:187-188). Passing them through is right only on the first increment of the first step.
  3. Tangent transposed for major-asymmetric tangents, when reading a column-major buffer row-major.

Anyone extending this target by hand would have to rediscover all three. Reusing #51 inherits them already fixed and regression-tested (each test was verified to fail against the pre-fix code).

Note (3) is already correct here: emit_stiff21_packing in src/targets/calculix_boundary.h symmetrizes (0.5 * (d6[i*6+j] + d6[j*6+i])), which makes the storage order moot. (1) and (2) are simply out of scope today.

Proposed shape: two emission modes, one target

Stateless (unchanged). Keep emitting the standalone plugin. The generated .so has no numsim-materials dependency — a real feature worth preserving, since there is no runtime library to ship, and stateless elasticity exercises none of the machinery below. Do not route this through #51.

Stateful (new). Emit:

  • a builder that constructs the material graph from the recipe (state variables -> history properties, evolution equations -> the solver/return-map contract), with *USER MATERIAL constants bound positionally, as umat_registry::builder already expects;
  • a registration for the model name;
  • NUMSIM_MATERIALS_DEFINE_CALCULIX_BEHAVIOUR(policy, NCG_UMAT, "<MODEL>").

This inherits, already tested: the STATEV offset, the TIME rebasing, the iorien/beta guards, per-thread contexts, the props-invariance check, and the fatal/cutback (PNEWDT = 0.25) semantics.

Mode selection follows the existing scope check: a recipe with state variables takes the materials-backed path; otherwise the standalone one. This pairs naturally with the can_emit() capability query in #137.

Drift risk to close regardless

The CalculiX convention knowledge is now encoded independently in two repos:

  • src/targets/calculix_boundary.h (emit_stiff21_packing, the abq_std boundary)
  • numsim-materials umat/calculix_interface.h

They agree today. Nothing keeps them agreeing, and a divergence is silent. At minimum, cross-reference them in both files and point at the same umat_abaqus.f / umat_user.f line numbers as the shared source of truth.

Validation

Neither path has yet been run against a real ccx through the @LIB,FUNC deck. The golden-file harness in #128 is the natural gate: it should cover the stateless path first, then the stateful one, with a plastic material whose STATEV round-trip actually spans increments and integration points.

Depends on

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions