Skip to content

CalculiX target: dlopen'd .so material (no ccx recompile per material) - #127

Open
petlenz wants to merge 4 commits into
mainfrom
feature-calculix-so
Open

CalculiX target: dlopen'd .so material (no ccx recompile per material)#127
petlenz wants to merge 4 commits into
mainfrom
feature-calculix-so

Conversation

@petlenz

@petlenz petlenz commented Aug 1, 2026

Copy link
Copy Markdown
Member

Adds CalculiXExternalTarget (make_target("calculix")) — codegen's first target whose output runs in a real external FE solver. It emits <Model>_ext.cpp compiling to lib<MODEL>.so, which CalculiX loads at runtime via dlopen: build ccx once with external-behaviour support, then each new material is just a new .so selected by name in the deck — no ccx recompile per material.

Supersedes the earlier two-PR split (#125 compiled-in umat_user_ + #126 external): the compiled-in approach needed a ccx relink per material and is dropped in favour of the .so path.

Mechanism (verified against ccx 2.22 source)

A deck *MATERIAL, NAME=@<LIB>_<FUNC> makes ccx (which uppercases the name) dlopen("lib<LIB>.so") + dlsym("<FUNC>") (external.c, -DCALCULIX_EXTERNAL_BEHAVIOURS_SUPPORT -ldl). The STANDARD interface passes native quantities under Abaqus-flavored names — STRAN1=emec (tensorial), STRESS=stre, DDSDDE=stiff(21) packed — handled by a tmech abq_std Voigt boundary + column-major stiff(21) packing (src/targets/calculix_boundary.h). The emitted plugin is a per-thread lifecycle: a thread_local stateless evaluator (ccx runs the element loop multi-threaded) that reads the material constants from MPROPS on every call (ccx interpolates them by temperature).

Verification

  • CI (no external deps): calculix_check_driver calls the emitted NCG_UMAT through the exact calculixptr ABI and checks stre/stiff vs an independent isotropic oracle + a packing-order negative control + a read-constants-every-call regression + the icmd==3 stress-only path. Full suite 275 + 7 green.
  • Real ccx (manual, examples/calculix/): build ccx once with external support, compile the codegen'd .so, run by @-name. Confirmed S11=0.027, S22=S33=0.013 (uniaxial) and S12=0.007 (simple shear — pins the tensorial convention).

Review

Went through a 3-lens review (architecture · C++/ABI · correctness); REVIEW.md has the findings. Fixes folded in: per-call MPROPS (was a stale thread_local cache — CRITICAL), symmetry guard (reject non-symmetric deformation-gradient inputs), shared boundary helper, shear-convention validation deck, single-table factory, and hardened build scripts.

Scope

Stateless (elastic). The STATEV round-trip for stateful J2 (numsim-materials-backed evaluate()) is the next step; the per-thread evaluator scaffold is already in place for it.

🤖 Generated with Claude Code

petlenz pushed a commit that referenced this pull request Aug 1, 2026
petlenz pushed a commit that referenced this pull request Aug 1, 2026
# Conflicts:
#	tests/calculix/linear_elastic/gold/gen_gold_shear.inp
#	tests/calculix/linear_elastic/gold/gen_gold_uniaxial.inp
#	tests/calculix/linear_elastic/shear.inp
#	tests/calculix/linear_elastic/uniaxial.inp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant