forked from 1b-agent/fieldcraft-upstream
* render: display data from the FE model, orbit camera and CPU rasterizer modelcraft-render (L1, no GPU): DisplayMesh (the unshared faces of solid elements, shells, element edges, line elements, nodes), the orbit camera and a CPU rasterizer with PNG output for headless snapshots, adapted from SolidCraft's render crate. Workspace: egui/eframe/egui-wgpu 0.36 and SolidCraft's patched egui-wgpu from the pinned rev. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * engine: sample model script (a hex8 block and a tet4 cube) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * Desktop app: egui/wgpu viewport, model tree, commands, status bar, control channel modelcraft-ui-egui (L5): ModelApp over the engine Session; GPU viewport (lit faces, element edges, nodes) with a CPU fallback; orbit/pan/zoom, standard views and fit; model tree; commands panel generated from the registry with a JSON parameter form; status bar; control request handling (engine.*, ui.*, ui.screenshot, ui.render). apps/modelcraft: eframe window, --sample, --control PORT loopback JSON-lines server. Adapted from SolidCraft's ui-egui and app. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * THIRD-PARTY-LICENSES: the desktop app's dependencies Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * docs: control protocol, desktop app in architecture, roadmap and attribution Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * render: simplify the display mesh (sorted face keys over maps, no unused fields) Interior faces are found by sorting fixed-size face keys instead of a BTreeMap of Vecs, edges are deduplicated by sort, and each element's corners are looked up once. Drops the unused `element` fields on DisplayTri/DisplayLine, the unused Mat4::IDENTITY and corner_count, and hoists the line colour out of the raster loop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * viewport: split GPU geometry into batches within the buffer limit; refuse oversized CPU renders A mesh with a few million boundary triangles made one vertex buffer larger than the device's max_buffer_size (256 MiB under the limits eframe requests), and wgpu's default error handler panicked. Geometry is now uploaded in batches of whole primitives, each at most 128 MiB and the device limit, and all are drawn. A device error handler logs errors and shows them in the status bar instead of panicking. The CPU renderer refuses sizes over 8192 per side or 16 MP, and scenes over 20 million primitives, with an error, and allocates its buffers fallibly. ui.render reports a size out of range instead of clamping it; the CPU viewport fits a large window into the limit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm --------- Co-authored-by: jyviko <2501648+jyviko@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
108 lines
7.8 KiB
Markdown
108 lines
7.8 KiB
Markdown
# 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) and with mesh
|
|
invariants (positive Jacobians, conserved volume, watertight boundaries).
|
|
- **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`, `solver`, `decks`, `render` → L2 `doc` → L3 `io` → L4 `engine` → L5
|
|
`ui-egui`, `mcp` → apps. Nothing below L5 depends on egui/eframe/winit/wgpu/rfd. **Only
|
|
`crates/geometry` may use `solidcraft-*`.**
|
|
- **Determinism.** The same input gives the same mesh and the same deck, bit for bit, on every
|
|
platform: no hash-order iteration into output, no thread-count-dependent results.
|
|
- **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.
|