Files
OneCAD-Simulation/AGENTS.md
T
40f98f0af9 Implicit solver: fem kernels (tet4/10, hex8, hex20), sparse Cholesky, block Lanczos, solve.* commands (M4) (#23)
* Renumber the layer table for solver crates: fem at L1, solver at L2, fsi at L3

L0 model -> L1 geometry, mesh, fem, decks, render -> L2 solver (explicit, lbm later)
-> L3 fsi (later) -> L4 doc -> L5 io -> L6 engine -> L7 ui-egui, mcp -> apps.
UI_MIN_LAYER moves to 7, the testkit sits above it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm

* modelcraft-fem: element kernels for tet4, tet10, hex8 (full, incompatible modes), hex20 (full, reduced)

Shape functions, Gauss and conical-product quadrature, stiffness, consistent and HRZ-lumped
mass, body forces, consistent pressure loads on faces, integration-point stresses and their
least-squares extrapolation to nodes, isotropic and orthotropic elasticity. The element table is
one row per kind, so wedges, shells and beams are added locally.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm

* modelcraft-solver: linear static and frequency analysis with an analytic verification suite

Assembly from the resolved model on the node graph, boundary conditions by elimination,
consistent pressure, gravity and body-force loads, nested-dissection ordering, sparse up-looking
Cholesky with a factor-size cap, reactions, integration-point and nodal-averaged stresses, von
Mises; shift-invert block Lanczos with full reorthogonalization for natural modes, participation
and effective mass. ADR 0001 records the own-linear-algebra decision (determinism, wasm).

Verified against closed forms: displacement and traction patch tests for every element, cantilever
tip deflection (Timoshenko) with convergence rates, Lamé cylinder, Kirsch hole (Kt -> 3),
cantilever and free-free beam frequencies with six rigid-body modes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm

* Engine: solve.static, solve.frequency and solve.probe; results kept in the session

Results are stored per step, restored on a failed command and cleared when the model changes.
Caps (degrees of freedom, factor entries, Lanczos vectors) may only be lowered; hostile parameters
are tested against a solvable session.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm

* docs: implicit solver architecture, roadmap M4, parity and references

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm

* Simplify the solver: shared face integration, block assembly, cached extrapolation

- model: one face integrator (nodal::face_normal_weights) for tractions and pressures
- fem: mid-side tables from ElementKind::edges, orthotropic via inverse3, symmetric
  accumulation without a symmetrize pass, incompatible-mode recovery without K_uu, model's
  coordinate check, dead table rows removed
- solver: one pattern search per node pair (block, scalar and diagonal adds), extrapolation built
  once per element type, reactions from the prescribed rows only, matrices dropped after
  restriction, the free-body shift keyed on the factorization error, step selection in the solver,
  Error::Element naming the element
- engine: the solver owns the default step and the shift check; the model comparison runs once

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm

* docs: results are stamped with the session revision

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm

---------

Co-authored-by: jyviko <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-13 17:44:21 -04:00

8.3 KiB
Raw Blame History

ModelCraft — instructions for agents

ModelCraft is a clean-room, open-source, pure-Rust CAE modeling application: it turns geometry into analysis-ready finite element models (volume meshes, materials, sections, boundary conditions, loads and steps), writes them as Abaqus input, Nastran bulk data and LS-DYNA keyword decks, and solves linear static and modal problems with its own solver. It targets the pre-processing done today in Abaqus/CAE, Nastran pre-processors and LS-PrePost, and aims to beat them on meshing robustness, speed, openness and agent control.

Siblings with the same conventions: ../solidcraft (parametric CAD, Fusion-class), and the storytold Craft apps (storytold/cadcraft, vectorcraft, photocraft, …). Code adapted from them (MIT OR Apache-2.0) is noted in ATTRIBUTION.md.

Product name

ModelCraft everywhere: crates modelcraft-*, binaries modelcraft and modelcraft-cli, .modelcraft models, MODELCRAFT_* environment variables, docs, CI and packaging.

Start every session here

  1. Read ROADMAP.md (milestones, what is next) and your task.
  2. docs/architecture.md: crates, layers, the meshing pipeline.
  3. docs/adr/: library decisions (what we may depend on, what is rejected for licence reasons).
  4. Meshing work: docs/meshing/literature.md (the papers each algorithm comes from).

Never crash

People trust ModelCraft with their models; a crash loses their work. This outranks feature work.

  • No panics in non-test code: no unwrap(), expect(), panic!, unreachable!, todo!, unimplemented!; no unsafe (unsafe_code = "forbid").
  • Errors are Result<T, E> through the crate's error type and ?. An unfinished feature returns an error ("not supported yet: …"); it never panics.
  • Input-derived numbers are hostile (command parameters, model files, solver decks, control-channel input): get() not [i], finite checks, caps on sizes and loop counts.
  • Bound every iterative algorithm. Mesh refinement, smoothing, untangling and solver iterations have explicit iteration and element-count caps and report when they stop early.
  • SolidCraft calls are guarded: everything that calls solidcraft-kernel goes through solidcraft_kernel::guard inside modelcraft-geometry, which turns a panic into an error.
  • Last-resort guard: Session::execute runs every command under catch_unwind; an error or an escaped panic restores the model and reports EngineError.
  • Prove it: every crash fix lands with a regression test (see hostile_params_never_panic).
  • Every production crate root carries #![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)].

Non-negotiables

  • Independent. Behaviour is designed from public documentation, published papers, general CAE conventions and user feedback. Never copy another product's code, icons, artwork, help text, element or material libraries, templates or examples.
  • No commercial CAE products. Agents must not drive, script, automate or extract data from commercial CAE or meshing products (Abaqus, MSC/NX/Simcenter Nastran, LS-DYNA, LS-PrePost, HyperMesh, ANSA, Femap, Patran, ANSYS, …): no test data, measurements, decks, results or ids produced with them. Deck formats come from the vendors' publicly available reference manuals; we write our own descriptions and our own examples, never copy manual text or example decks.
  • Expected values are analytic. Reference tests compare with closed-form solutions (patch tests, beams, plates, Lamé cylinders, Kirsch plates, natural frequencies, wave and shock solutions) and with mesh invariants (positive Jacobians, conserved volume, watertight boundaries). A separate benchmark suite may compare with reference values published in papers (lid-driven cavity, Schäfer–Turek, Turek–Hron, Taylor bar), each tagged with its source; the analytic suite is the gate. Never values produced with a commercial product.
  • Algorithms come from papers. Meshing and solver methods are implemented from published papers and theses, cited in the module docs and in docs/meshing/literature.md.
  • Never read, copy or link GPL/LGPL/AGPL code: TetGen, CGAL, Gmsh, Netgen, CalculiX, Code_Aster, OpenRadioss, Elmer, deal.II, FreeFEM, Salome, OpenFOAM — don't even read their sources. Permissively licensed code (MIT, BSD, Apache-2.0, MPL-2.0) may be read for reference; anything adapted is noted in ATTRIBUTION.md with its licence.
  • Assets — absolutely essential. ModelCraft contains no iconography, images, fonts or artwork from commercial CAE products — ever. Icons are original artwork made with VectorCraft: commit the editable .vectorcraft source beside the exported SVG/PNG. Any file asset must be original or openly licensed and must have a row in ATTRIBUTION.md (cargo xtask assets enforces it). Screenshots of commercial software are never committed.
  • Test geometry is our own. Meshing and solver test parts are built with SolidCraft and committed as recipes (scripts or designs) that regenerate them; analytic shapes are generated in code. No public CAD datasets (ABC, MAMBO, Thingi10K, GrabCAD) and nothing made in a commercial CAD or CAE product.
  • Everything is a command. User-visible behaviour = a command in crates/engine/src/cmd/* (CommandSpec: our own dotted, lower-case id <area>.<thing>[.<variant>] such as mesh.node.add or mesh.tet.generate, never another product's keyword; label; params doc; JSON run) + tests. The UI, scripts, CLI and control channel all reach the same commands.
  • Programmatic calls never open dialogs.
  • Layering is enforced by cargo xtask layers (docs/architecture.md): L0 model → L1 geometry, mesh, fem, decks, render → L2 solvers (solver; explicit, lbm later) → L3 fsi (later) → L4 doc → L5 io → L6 engine → L7 ui-egui, mcp → apps. Nothing below L7 depends on egui/eframe/winit/wgpu/rfd. Only crates/geometry may use solidcraft-*.
  • Determinism. The same input gives the same mesh, deck and CPU solver result, bit for bit, on every platform: no hash-order iteration into output, no thread-count-dependent results. GPU solver backends (wgpu, f32) are the one exception: deterministic per device, and checked against the CPU reference within a stated tolerance.
  • Robust geometry. Meshing decisions (orientation, in-sphere, intersection) use exact or adaptive-precision predicates, never a bare floating-point sign.
  • Units. The model is unit-consistent and never converts (the user picks e.g. mm, t, s, N, MPa); geometry from SolidCraft is in millimetres. Z is up.
  • Rust only. Never break wasm: everything below the apps builds for wasm32-unknown-unknown (cargo xtask wasm, part of cargo xtask ci).
  • Quality gates: GitHub CI runs cargo xtask ci (fmt, assets, licences, layers, clippy -D warnings, tests, wasm) on every PR; don't run the full gate locally. Before pushing: cargo fmt --all, cargo check the touched crates, and run the tests you added or changed. Commit after each working step (a layer that compiles with its tests passing), not one big commit per PR.
  • Publishing: origin is github.com/jyviko/modelcraft. Changes land through pull requests: branch, push, open a PR, let CI run, then gh pr merge --squash when green. Rebase onto main (never merge main into a branch); never force-push main. Never commit plan/, .agent-files/, worktrees/ or target*/; check git ls-files before pushing.

Running

  • cargo run -p modelcraft-cli -- commands lists every command with its parameters.
  • cargo run -p modelcraft-cli -- run script.json runs a script (a JSON array of {"command", "params"}) and prints the model summary.
  • cargo run --release -p modelcraft -- --sample --control PORT opens the desktop app with the sample model and a control channel on 127.0.0.1:PORT (docs/control-protocol.md). For UI work, look at the result: ui.screenshot {path} (needs a presented frame) or ui.render {path} (CPU render, no window needed), then read the PNG.
  • Build with CARGO_TARGET_DIR=<repo>/target. Parallel agents: separate target dirs, one worktree each.

Roadmap

ROADMAP.md (committed) tracks milestones. Update it whenever a milestone task lands.