Five cases against closed forms: a Mooney-Rivlin block in Treloar's
uniaxial, equibiaxial and pure-shear modes and a Yeoh block in uniaxial
tension (the compressible energy's stresses, exact); a stretched
Mooney-Rivlin tube inflated by a follower pressure (Rivlin's incompressible
solution, 0.6 % at nu = 0.4995); free and fully held thermal expansion at a
thermal stretch of 1.2 (exact); a bar held at its ends heated past yield
(exact). docs/fem.md, the literature, ROADMAP (M15, M17), parity and the
oracle page follow.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
Four cases, each against its closed form: uniaxial tension of a J2 cube to a
logarithmic strain of 0.2 (Kirchhoff stress exact; 0.13 % from the explicit
solver's hypoelastic Cauchy stress, the elastic volume change between the two
laws), the Bauschinger effect of linear kinematic hardening on a load path
back to zero strain (exact), Hill's elastic-perfectly plastic thick cylinder
(bore displacement at a plastic radius of 1.5a within 0.009 %, collapse
pressure within 2e-8; the pending case is now active) and a cantilever's
plastic collapse, converged 3.1 % above beam theory's hinge, the bound a
continuum exceeds. docs/fem.md, the literature, ROADMAP (M15), parity and the
oracle page follow.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
filleted-bracket-blocks splits the bracket with SolidCraft's Split Body
into three slabs across its width, the fillet corner halved along its
diagonal and a four-cell O-grid round each hole; the corpus runner meshes
partitioned parts as one conforming block mesh. A heavy test clamps the
upright, loads the foot and checks hex8 and hex20 converge (hex20 tip
deflection within 0.1 % of a fine tet10 solution). Roadmap M5:
conforming interfaces done.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
Meshes the open design's bodies (or the listed ones) as the cells of one
conforming all-hex mesh with one size and tessellation tolerance for all;
elements carry their cell's body, boundary faces its B-rep faces. A cell
that is no block, or cells that touch without sharing whole faces, is an
error naming the bodies. Catalogue entry with its VectorCraft icon, the
MCP mesh tool's hex_blocks method, docs/features.md.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
hex_mesh_cells meshes cells that meet face to face (SolidCraft split
bodies) as one conforming all-hex mesh: each cell a mapped block after
smoothly meeting faces are joined (virtual topology: the halves of a hole,
a plane running into a fillet), vertices, edges and faces shared by
identity, interval assignment over all cells, each shared face meshed
once, radial edges graded off curved faces. finish spans several cells:
tags per cell, hex20 mid-edge nodes shared across cells, a closed
2-manifold boundary and no free internal face.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
Theory cases for the nonlinear solver, each frozen as a fixture: uniaxial
stretch of a neo-Hookean block to twice its length (closed form), the
nonlinear patch test on a distorted hex8 mesh, a quarter turn of the same
mesh (objectivity: zero stress), the elastica of a hex20 cantilever at
P L²/(E I) = 1, 2, 5, 10 against Bisshopp–Drucker (0.2–0.5 %), and the
inflation of a thick neo-Hookean tube by a follower pressure against
Rivlin's closed form (0.08 % at the bore). A finite-strain Cook's membrane
is pending its transcribed reference. docs/fem.md describes the
formulation, the material point interface, the follower-pressure choice and
what nonlinear steps refuse; the literature, parity and roadmap pages
follow.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
solve.nonlinear follows a nonlinear static step in load increments: dead
loads and prescribed displacements ramp with the load factor, a pressure
follows the deformed faces (its load stiffness symmetrised so the
supernodal Cholesky stays), the consistent tangent is refactored every
iteration with an optional line search, and an increment converges on
force, displacement and energy together. Increments start from the
extrapolated last one, grow after fast convergence and are cut back on
inversion, a non-finite or growing residual, an indefinite tangent or too
many iterations; the step stops cleanly at the minimum increment, the
increment cap or the Newton iteration limit. Elements are assembled in
parallel in label order (same bits on any thread count). Results carry
Cauchy stress, logarithmic strain, the increment history and a displacement
frame per increment, which results.frame and the results panel show.
Trusses, shells, beams, plane stress, incompatible modes, temperature and
centrifugal loads are refused by name; couplings warn that they stay
linear.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
The setup's symbols (fieldcraft_render::glyphs) are built with the display
data and drawn over the model in every style, at the drawn nodes (a results
plot's deformed shape), muted over results; the clipping radius holds them.
Theme tokens give their colours in light and dark. The browser's Loads & BCs
and Interactions rows get eye toggles (ui.set show_loads, show_interactions),
also in the view menu. The GPU viewport draws reference point names with the
interface's font; the bottom left says which definitions are sampled.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
view::scene draws the boundary conditions, loads and interactions as the
viewport does (muted over a results plot) and frames them; Shown.sampled and
the MCP picture info's sampled_symbols list definitions drawn with a sample.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
A command run by a script, the control channel, MCP, the command search
or the browser left the ribbon on whatever tab it showed, so an agent's
session never showed the stage it was at. `catalogue::stage_tab` is the
rule, from the catalogue: a command's entry tab, none for the Tools tab
(files, history, the model summary). The app follows it after a command
that changed the model or the results display (queries leave the ribbon
alone); a script follows its last command with a stage. A ribbon click
runs a command of the tab shown, so it never moves the ribbon: a test
checks every entry and drop-down command against its tab.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
The demo used the corpus I-beam, which is extruded along z and so stood
upright. A new corpus part, cantilever-i-beam, is the same section on the
YZ plane extruded along x, web upright: a sweep along a horizontal axis
for the meshers, and a cantilever that bends downward on screen. The
i-beam part is unchanged (its corpus row and the meshing tests keep it).
The demo clamps it at x = 0 and loads the free end with 1000 N in -z
through a kinematic coupling, and now checks the solution against beam
theory and stops when it is off: tip deflection (bending plus shear)
within 3 %, root bending stress (stress_xx along the top flange,
extrapolated to the root, nodes from the Abaqus deck) within 2 %.
docs/meshing/corpus.md regenerated with the new part.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
A factor of 0 was refused, so a picture sequence swinging the deformation
out from the undeformed shape had to start at a small factor or switch
`show` off. 0 is now a factor like any other (the view stays deformed), and
the results panel no longer works around the refusal. The MCP show_results
docs say so, beside `deformed: false`.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
`ui.view` and the MCP `screenshot` tool only turned to the named views, so
a picture sequence could only cut between them. `Orientation` (render) is a
camera orientation in degrees, {yaw, pitch, distance?}, checked as hostile
input: angles finite, distance finite and above 0, yaw wrapped, pitch
clamped to ±90, distance to 0.001–1e9. `modelcraft_engine::view::orientation`
parses it from JSON for both callers:
- control channel `ui.camera {yaw, pitch, distance?}` turns the app's camera;
- MCP `screenshot {camera}` turns it first (bridged through `ui.camera`,
headless in the CPU render, framed unless a distance is given). `view` and
`camera` are not given together.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
Crates fieldcraft-*, binaries fieldcraft and fieldcraft-cli, the .fieldcraft file (format tag
fieldcraft/1, manifest fieldcraft.json), FIELDCRAFT_* environment variables, the MCP server
name, egui widget ids (fc_*), the app icon document FieldCraft.icon and its generated family,
docs and licences. No compatibility shim: no files of the earlier name exist.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
Main's oracle job failed at 8cba3a7: scordelis-lo-roof-solid u_z moved from
-0.3014029226397275 (blessed before #50) beyond its 1e-9 band. The case is a
thin shell (R/t = 100) of one layer of hex20R solids, ill-conditioned, so
rounding alone moves u_z by about 1e-9 relative: on macOS #50's multithreaded
supernodal factorisation moved it by 8.2e-10 (to -0.3014029223929), #52's
interpolation order by a further 1.3e-10 (to -0.3014029223541), and Linux
CI by slightly more, past the band. #52 kept the lattice geometry the same.
The result itself is unchanged at the 1e-9 level (0.33% from the
reference).
A quantity may now set `fixture_relative` (with a required
`fixture_reason`) for a wider fixture band; Scordelis-Lo uses 1e-7 and is
re-blessed. Moved-fixture messages print full precision.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* mesh: one transfinite interpolation for mapped hex and mesh.block; stable oracle report
mesh.block's lattice is now built from the structured hex mesher's
transfinite code: faces by quad::transfinite_grid, the interior by the new
quad::transfinite_volume (Gordon-Thiel, blended by the block's graded
parameters), which hex::mapped now calls too. 2D patches are the
transfinite_grid of their sides. Edge curves return their corners exactly.
Oracle: a zero-reference quantity (rounding noise) keeps its absolute
tolerance as its fixture band, and docs/oracle.md shows such noise and
relative errors inside the fixture band as bounds, so the report no longer
changes with the order of floating-point operations (it failed the
'docs/oracle.md is current' check on main after #50). Scordelis-Lo moved by
1.4e-9 relative (an ill-conditioned thin shell of solids: sub-ulp node
changes) and is re-blessed.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* simplify: shared face filling and lattice index; faces blended like the volume; exact ends for every edge
quad::transfinite_faces fills a block's six faces (with a per-face hook
that hex::mapped uses to project onto its B-rep faces) and
quad::lattice_index fixes the lattice layout for all three users.
transfinite_grid_blended blends faces by the block's graded parameters, so
faces and interior use one parametrisation and mesh.block reproduces its
earlier Gordon-Hall lattice (the Scordelis-Lo fixture is back to its
blessed value). Straight edges also return their corners exactly.
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]>
* Structured hex meshing: multi-level extrude and revolve, one-to-one sweep, mapped blocks (M5)
modelcraft_mesh::hex::hex_mesh meshes a face-tagged boundary surface with
hexahedra by the first structured method that fits: a straight or
rotational multi-level sweep (imprinted cross-section arrangement, cuts at
reflex corners, mapped/annulus/free regions), a one-to-one sweep through
rings of linking faces (least-squares affine layers with residual
correction), or a mapped logical cube (trivariate transfinite
interpolation). Interval assignment couples shared curves; boundary quads
carry B-rep face tags; the certified validity gate, a tiling check and a
fidelity check guard the output; hex20 mid-edge nodes go onto the faces.
Shape::face_surfaces exposes the analytic face surfaces; the corpus runner
gets a structured hex column.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* mesh.hex.generate: structured hex meshing as a command
Meshes one body, every body of the open design or an imported surface,
replaces the mesh, tags element faces with the B-rep faces (so sets by
geometry resolve) and reports per body the method, counts and quality.
The quality pass certifies each element once and feeds the validity gate
(quality::validity_gate_checks). Shape::size gives the cached body size
for defaults instead of a full measure.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Hex: disk O-grids, convex interval cost, early size guard, hex20 corpus column
Smooth single-loop sections (cylinders, tori, vases) get a butterfly O-grid
instead of the free mesher; interval assignment raises counts by the
squared relative error so equal sides share increments evenly; a mesh far
beyond the element limit is refused before any work and mapped limits are
no longer swallowed. The corpus reports hex8 and hex20 quality.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Catalogue: structured hex commands ready (mesh.hex.sweep, mesh.hex.mapped, mesh.hex.generate)
mesh.hex.sweep and mesh.hex.mapped run mesh.hex.generate with the sweeping
methods or the mapped one; mesh.hex.generate is the sweep entry's related
command. The planned M6 octree entry moves to mesh.hex.octree (its icon
renamed with it). docs/features.md regenerated.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Docs: structured hex literature (B8), architecture, roadmap, parity; corpus hex column
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Hex: simplify review fixes
Prepare each sweep frame's cross-section once (arrangement, cuts, fill)
and reuse it across refinement retries; candidate frames come from one
setup pass. Edge triangles come from the feature edges, layer counts go
through size::edge_divisions, sweep residual weights are computed once
per node, flux shape functions live on the stack, and the arrangement's
exact side test and distances serve the region probe. The engine takes
the boundary options mesh.tet.generate takes and names unnamed faces by
index like it; the corpus hex20 run reuses the winning method; the
mapped entry lists mesh.hex.generate too; the octree icon is redrawn
under its new id.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Regenerate docs/features.md and docs/meshing/corpus.md after rebasing
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Regenerate docs/features.md and docs/meshing/corpus.md after rebasing onto main
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Regenerate docs/features.md and docs/meshing/corpus.md after rebasing onto main
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Regenerate docs/features.md and docs/meshing/corpus.md after rebasing onto main
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Regenerate docs/features.md after rebasing onto main
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Regenerate docs/features.md after rebasing onto main
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Regenerate docs/features.md after rebasing onto main
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]>
The isotropic elasticity splits into D_dev + K m mᵀ; an element-wise
discontinuous pressure is condensed out (p̂ = K M⁻¹ Gᵀ u), leaving
K_dev + K G M⁻¹ Gᵀ (Hughes §4.3–4.5). Q2–P1disc and P2–P0 are inf-sup
stable; Q1–P0 does not lock; tet4 and wedge6 still lock and are refused, as
are orthotropic materials (named at the section). ElementDofs counts the
condensed pressures. Verified: element patch, rigid modes and totals for
every hybrid kind, a block in uniaxial strain at ν = 0.4999 (exact), Lamé's
cylinder in plane strain at ν = 0.4999 (hex20 1e-5, tet10 1.3e-3, hex8
2.5e-3 vs the locking displacement hex8 at −80 %). Every non-hybrid result
of the test suites hashes identically before and after.
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
Co-authored-by: jyviko <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
* Heat transfer and thermal stress: thermal materials, temperature BCs, heat loads, heat transfer and coupled temperature–displacement steps, solve.heat
Model: Material.thermal (conductivity, specific heat, expansion, isotropic or
per axis; reference temperature), BoundaryCondition::Temperature (dof 11),
loads SurfaceFlux, Convection, HeatSource and Temperature (a field in static
steps), procedures HeatTransfer { transient (θ-method) } and
CoupledTemperatureDisplacement; checks for missing conductivity/specific
heat/expansion. fem: heat conduction kernels (conductivity, capacity,
source, face flux/film, heat flux) on the DofLayout (one T per node), thermal
strain load and stress D(ε − ε_th) for every solid formulation incl.
incompatible modes. Solver: steady and transient heat transfer, thermal loads
in static steps, coupled steps (exact one-way coupling). Engine: solve.heat,
temperature/heat-flux result fields, probes. Decks refuse heat transfer by
name. Analytic verification: slab, source+convection/flux, thick cylinder,
erfc semi-infinite solid, free/constrained expansion, bimetal strip, coupled
step.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* thermal: strains in 2D elements and explicit dynamics
Plane::thermal_load and stresses_with for plane stress (εzz free), plane
strain (σzz = −D₃·ε_th) and axisymmetric elements, incompatible modes
included; the solver's 2D kernels take them. Explicit dynamics turns a
step's temperature loads into a per-element thermal strain rate (reached
linearly over the step) subtracted from each strain increment, so it feeds
J2 and Johnson–Cook updates. Verified: free expansion in every 2D theory
and element, a biaxially held plate, an explicit free bar (ΔL = αΔT L,
stress-free) and a clamped bar at −EαΔT, capped at the yield stress with
perfect plasticity.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* clippy
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* thermal: trusses take the axial thermal strain; keep the roadmap's M7 line
Truss::thermal_load and stresses_with project the thermal strain on the
member's tangent (Σ αₖ tₖ² ΔT); the static solver applies them to rod2/rod3
(#38). Explicit trusses take none yet and a warning says so.
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]>
* Native file pickers, background opening, drag and drop and recent files
Open (models, SolidCraft designs and tagged meshes in one picker), Save, Save As, Write
Deck and Recover go through the host's file pickers (rfd in the desktop app, injected as
Services so the UI crate stays portable and tests answer them). Files open on a copy of the
session in a worker thread and replace it only on success; files dropped on the window or
named on the command line open the same way. A recent-files list, an unsaved-changes prompt,
Cmd/Ctrl+O/S/Shift+S. Programmatic calls never open a picker: ui.start opens the form.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Samples and one-click Solve: results reachable from the window
file.sample {name} opens a ready-to-run sample (the two parts, the cantilever with static and
frequency steps, the bar impact) in place of the model; solve.run solves every step in order.
Help > Samples, the empty viewport's start screen and the Tools > Samples entry open them
(asking first over unsaved changes); Solve runs in the background like a file opening and the
Results tab comes up. --sample [parts|cantilever|impact] on the command line.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* The Craft-family shell: title bar, workspace ribbon, browser, context panel, timeline
The window now follows SolidCraft's and VectorCraft's layout and themes:
- title bar with the mark, quick actions (File menu, save, undo, redo, Solve, search,
theme, help), the model's document tab and the version; integrated under the macOS
traffic lights, own caption buttons and resize zones elsewhere (titlebar.rs);
- workspaces (Prepare, Model, Analysis, Results) with their tabs, and panels of icon
buttons whose labelled drop-downs list the whole catalogue, coming-soon entries greyed
with their milestone; panels collapse, then go into a » menu, when narrow;
- the browser: geometry and mesh with eye toggles, definitions with counts, results;
- no permanent Commands list: command search (S, Cmd/Ctrl+K) and a command line;
- the context panel on the right only with context: the command form, results controls,
the selected definition's properties with Edit and Delete;
- navigation bar and orientation gizmo in the viewport; the journal timeline at the bottom
with undo positions;
- SolidCraft's light and dark tokens; craft-ui (IconButton, Tab, WidgetPalette).
Menus and the search are view state (ui.set {menu, palette}), so captures show them.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Shell polish, docs and licences
Menus painted as the family's (flat File menu with recent files, decks and samples), the
legend sized to its text, two-line panel labels inside the ribbon, glyphs the UI font has,
offscreen captures without fade-in, ui.start runs in-window file actions (samples, recover,
solve) but never a native picker, ui.select. Control protocol, architecture, ROADMAP, AGENTS
and ATTRIBUTION updated; THIRD-PARTY-LICENSES.txt with craft-ui and rfd.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Title bar mark from the application icon; fluid steps and domains in the shell
The title bar draws the app icon's bracket (assets/app-icon/icon-small.svg's faces) as
SolidCraft draws its mark; the window keeps its title-bar flags after the rebase.
solve.run solves fluid steps too (solve.fluid); the browser lists fluid domains.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Simplify: cached per-frame data, one command per timeline roll, workspace setters
- Icon textures are kept per pixel size (the shell draws several sizes a frame; the cache
used to clear on every size change and rasterise again).
- Opening a model or recovering one starts from an empty session instead of copying the
current one; the replaced session is freed off the window thread.
- Element counts, timeline items, search results and the selected definition's properties
are cached until what they show changes; timeline tooltips are built on hover; long lists
in properties are summarised.
- edit.undo and edit.redo take a count: a timeline click is one command.
- solve.run dispatches on the step's procedure (no string round trip) and reports its name.
- The workspace and tab change together through UiState::select_tab/select_workspace
(ui.set {workspace} alone now sticks); no per-frame syncing.
- One busy guard, Kind::verbs, a fit flag for background jobs, ModelApp::home_view, the title
bar's actions as an enum, dead code removed.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Title bar: Solve and tools at the right end; no traffic-light inset in full screen
The owner's feedback on the title bar: Solve, search, theme and help sit at its right end
before the version; on macOS the left group (mark, name, quick actions) moves into the
traffic lights' room in full screen, where there are none, and back when leaving it. The
layout is a pure function (bar_layout) tested for both states, narrow windows and custom
caption buttons. ui.fullscreen {on} for agents.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Caps labels in Inter SemiBold
egui has no bold weight of its default font, so the ribbon's tabs and panel labels, the
workspace switcher and its menu, menu headings, the browser header, the context panel's
headers and the Solve label were thin, especially in the light theme. They now use a label
font family: Inter SemiBold 4.1 (SIL OFL 1.1, unmodified, fonts/OFL.txt, ATTRIBUTION.md),
with egui's fonts as fallback, installed with the theme on the live and offscreen contexts.
theme::label_font falls back to the default font until the family is bound (fonts take
effect from the next pass), so nothing can panic. Panels widen to their label's longest word.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* docs: regenerate features.md after rebase
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]>
The pending 2D LE1 case becomes a real one; the plasticity cases stay
pending with what they still need (static J2 for the collapse pressure,
the transcribed measurements for the Taylor bar).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
The large-deformation explicit core of #42 (objective stress rates, updated
kinematics) moves the bar wave and rigid-wall impact results by a few 1e-4
relative; both still pass their references (u_end 0.034%, rebound KE
-0.54%). Fixtures updated deliberately for that change.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
The oracle binary (modelcraft-testkit) runs each case's recipe through the
command engine, measures its quantities by JSON pointers into step outputs
or commands, compares them with the cited references and the frozen
fixtures, and writes docs/oracle.md. 20 theory cases (patch tests of every
solid element, Timoshenko cantilevers, Lame, Kirsch, beam frequencies,
torsion and bending through couplings, explicit waves and impact, CDT
invariants), 8 published benchmarks (MacNeal-Harder patch, straight and
curved cantilevers, thick cylinder, Scordelis-Lo with solids, NAFEMS LE1,
LE10, FV32) and 10 pending cases with citations.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
A structured mesh of a six-sided block from its corners, with circular
and elliptical edges (Gordon-Hall transfinite interpolation), grading,
named faces, edges and vertices as geometry tags, and joining to the
existing mesh face to face (refused otherwise). solve.probe takes "at"
points and reports the nearest node with a result.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Model, fem and decks: point masses, rotary inertia, springs, dashpots and rod3 trusses
Model: PointMass and Spring definitions (spring | dashpot; to ground or
two-point; along a degree of freedom, a vector or the line of the ends) on a
set or reference point, resolved per node; ElementKind::Rod3. fem: rod2/rod3
truss kernel on Basis::Line2/Line3 declaring ElementDofs (translations).
Decks: Abaqus T3D3, MASS, ROTARYI, SPRING1/2/A, DASHPOT1/2/A; Nastran CONM1,
CELAS2, CDAMP2; LS-DYNA ELEMENT_MASS/INERTIA and ELEMENT_DISCRETE; what a
format cannot take is reported. Commands model.mass.* and model.spring.*.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Implicit solver: trusses, point masses, rotary inertia and springs on the DofLayout
Trusses declare their translations like solids; point masses, inertia and
springs ask the layout for the kinds they need at their nodes (translations,
rotations), and reference points they use get six degrees of freedom. The
matrix pattern takes rows for those points; dashpots are ignored with a
warning. Existing results are bit-identical (hash-checked).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Explicit solver: trusses, point masses, springs and dashpots on the node-major layout
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* docs: fem.md on trusses and discrete elements in the layout; regenerate features.md
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* docs: trusses in plane models and corotational explicit trusses
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]>
Survey of ~40 papers for meshing curved B-rep faces for shells: frontal-Delaunay point placement in
the cross-field metric (Remacle et al. 2013), recombination to all-quad, cleanup (Reberol et al.
2021), global parity by minimum T-join, verification on shell benchmarks; licences of every code
base. Also fixes the Lee & Lo 1994 author initials in literature.md B7.2.
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
Co-authored-by: jyviko <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
- model: materials gain solver-neutral plastic (bilinear isotropic/kinematic,
hardening table, Johnson-Cook with adiabatic heating), damage (Johnson-Cook
D1-D5) and erosion (plastic strain); explicit steps gain nonlinear_geometry
(default on) and stress_rate (jaumann | green_naghdi).
- fem: rotation (Hughes-Winget, Flanagan-Taylor), plasticity (radial return,
capped bracketed Newton for Johnson-Cook, damage; the update takes the
mechanical strain increment so thermal strains can be subtracted), closed-form
hex8 gradients for deformed configurations.
- explicit: updated Lagrangian hex8/tet4, per-element material state, erosion
with reported energy, plastic work in the energy account.
- solver: warns that the linear solver uses the elastic constants of plastic
materials (results hash-identical).
- decks: Abaqus *PLASTIC (+ Johnson-Cook keywords), Nastran MATS1/TABLES1,
LS-DYNA *MAT_PLASTIC_KINEMATIC / *MAT_PIECEWISE_LINEAR_PLASTICITY; what a
format cannot express is reported as Unsupported.
- engine: model.material.plasticity, model.material.damage (catalogue ready),
explicit element probe, eroded elements in the solve summary.
Step commits before the rebase onto the DOF framework: branch explicit-x2-steps.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
Model: planar section kinds with Extent, element edges in sets, edge-weighted 2D loads,
centrifugal load, 2D model checks. fem: Plane kernels on Basis::{Tri3,Tri6,Quad4,Quad8}
declaring ElementDofs::new(DofSet::PLANE); QM6 incompatible modes with the
Wilson-Ibrahimbegovic correction. Solver: Kernel enum on the DofLayout; 3D results
bit-identical (hash-checked). Decks: Abaqus CPS/CPE/CAX, Nastran membranes and RFORCE,
LS-DYNA ELFORM 12/13. Mesh: free triangle mesher, planar region meshing, face boundaries.
Engine: mesh.planar with tagged edges. Analytic verification suite in solver/tests/plane.rs.
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
Co-authored-by: jyviko <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Model: Newtonian fluid materials; fluid domains (box, spacing, conditions on
the box faces, obstacle bodies with conditions on their named faces, initial
velocity, body acceleration); fluid steps with caps. Deck writers refuse
fluid steps; a fluid-only model needs no mesh in model.check; one step
selector (Model::select_step) for every solver.
New L2 crate modelcraft-lbm: D3Q19 two-relaxation-time collision with Guo
forcing; halfway bounce-back walls (moving walls after Ladd), slip faces,
periodic pairs; Zou–He velocity and pressure faces with the D3Q19
transverse correction; obstacles voxelised from the face-tagged boundary
surface with exact predicates and symbolic perturbation; momentum-exchange
forces per box face and per B-rep face; unit conversion, automatic time step
and Mach/tau limits; bounded runs with frames and force histories.
Engine: model.fluid_domain.create/edit/delete, model.fluid_domain.boundary,
solve.fluid (obstacles from the open design or imported surfaces, lowerable
caps), solve.probe for fluid fields and wall force histories. Fluid Domain,
Inlet & Outlet and Lattice Boltzmann toolbar entries are ready.
Verification (analytic): plane Poiseuille exact with Λ = 3/16 and second
order (2.000) with Λ = 1/4; Couette exact with the wall shear; Taylor–Green
decay second order (2.01, 2.00); staircase pipe; Stokes drag of a sphere
array within 1.7% of Hasimoto at R = 6; Zou–He channel; mass conserved to
round-off; bit-for-bit reproducibility. Benchmark: Schäfer–Turek 2D-1.
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
Co-authored-by: jyviko <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
* fem: DofKind/DofLayout and the shape-function library with second derivatives
DofKind (Ux..Rz, T, P), DofSet, ElementDofs (per-node kinds and condensed
internal unknowns) and DofLayout: mesh nodes by label, kinds in order, then
reference points. basis::Basis covers line2/3, tri3/6, quad4/8/9, tet4/10,
wedge6/15, pyramid5, hex8/20/27 with values, first and second natural
derivatives (second-order forward AD, fem::jet) and the physical gradients,
Hessians and Laplacians with the map's second-derivative term. Tested for
Kronecker delta, partition of unity, polynomial completeness, finite
differences, affine and curved maps.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* solver, explicit: number degrees of freedom with DofLayout
The implicit mesh numbers its unknowns with a DofLayout (mesh nodes by label
with the kinds their elements declare, then six per coupled reference point);
assembly adds element blocks by (node, DofKind), so a node may carry any mix
of kinds; couplings, boundary conditions, loads and results address
(node, kind). The explicit system keeps node-major translations, now checked
against its layout (NODE_DOFS). Solid formulations declare their ElementDofs.
Every static, frequency and explicit result of the solver, explicit, engine
and io test suites hashes bit-identically before and after (957 results).
docs/fem.md describes the DOF model and the shape-function conventions.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* fem, solver: simplify after review
Block offsets resolved once per node pair; add_scalar/add_diagonal take
the kinds like add_block; one checked Jacobian inverse (dense::positive_inverse)
for the solid kernels and the basis library; static natural-node tables; the
Hessian path inverts the Jacobian once.
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]>
* ui.capture: the whole window drawn offscreen and rasterised on the CPU
ui.screenshot falls back to it when no frame is presented (hidden window,
locked screen), so agents can look at panels and the toolbar.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Draw the open design and imported surfaces in the viewport
DisplayMesh keeps node labels on every element primitive (for results),
gains add_surface (geometry faces and their boundaries, coincident points
welded) and displaced (elements moved by nodal offsets). Bodies are
tessellated at a thousandth of their size; meshed models show the geometry
as boundaries only.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* results.* commands: deformed shape, contours, mode shapes, animation, reaction sums
The results display is session state (ResultsView), set by commands that are
not edits. Nodal fields (displacement, von Mises, principal and component
stresses; principal stresses in closed form after Smith 1961) and reaction
force and moment sums per set. Results kept from an earlier revision stay
viewable, marked stale; solve.probe says when a result is stale. The Results
tab's display and reaction entries are ready.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Results display: deformed shape, contours with legend, mode shapes and animation, probe, reaction sums
The viewport draws the session's results view: elements moved by their nodes'
displacements or a mode shape (automatic or given scale), faces split exactly
along contour band boundaries into flat-coloured pieces (same on GPU and CPU),
a legend with levels and extremes, a results panel whose controls run the
results.* commands, a click probing the nearest node (solve.probe), and stale
results marked. Solving from the form shows the result on the Results tab.
sample::cantilever is a solvable model for tests and demos.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Simplify the results display (review)
One Contour in the plot; the results scene reuses scene::build; a solve shows
its result through the engine (ResultsView::for_result) and the UI raises the
Results tab when a view appears; the plot's scale and contour values are kept
across animation frames; design bodies are tessellated once per design; the
first content is framed where the display is rebuilt; field_values in one
match; probe reuses results::displacements.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Results display for explicit steps: field frames, energy histories
The results view works on the engine's step results (static, frequency,
explicit): ResultsView.frame and results.frame {frame | time} pick an explicit
field frame; the deformed shape (true scale) and contours (element stresses
averaged to the nodes, velocity) follow it; animation runs through the frames.
The Results panel has a frame slider and plots the kinetic, internal, hourglass
and external energies with their values at the frame. sample::impact is a
steel bar flying onto a rigid wall.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* docs/features.md after the rebase
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]>
* docs: verification and validation against theory, experiments and published benchmarks; fixtures
Owner decision 2026-10-13: test against experimental and theoretical data; results published by
vendors (e.g. Abaqus benchmark and verification manuals) may be used as cited reference values for
our own models of the same problems; once a case matches, its result becomes a fixture so fidelity
cannot regress. Commercial products are still never run and their files and text never copied.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* docs: V&V policy in AGENTS.md, ADR 0001 and the roadmap
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]>
Owner 2026-10-13: cover the element families a full CAE code offers, simple ones first (1D and
2D). docs/elements.md lists point/discrete, 1D, 2D, shell/membrane, 3D and special-purpose
families with status and the task that brings each.
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
Co-authored-by: jyviko <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
* fem: wedge6 element (triangle × interval, 3 × 2 points), patch and cantilever tests
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* solver: reference points, kinematic and distributing couplings, moments by constraint elimination
Coupled reference points get six degrees of freedom; kinematic couplings are rigid
links, distributing couplings least-squares interpolation constraints. Every
constraint row and prescribed value is eliminated master-slave (Abel-Shephard
pivot choice), so the reduced matrix stays SPD; no coupling gives the old
elimination bit for bit. Verified: rigid motion of a coupled block, clamping
through a point, distributing tension vs pressure, bending and tube torsion.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* engine: reference point results in solve.static and solve.probe
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* docs: couplings, moments and wedge6 in the solver docs, literature and roadmap
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* solver: simplify constraint elimination and reference point plumbing
Rows combine by one sort; T_f transposed once; K and M reduced in one pass on a
shared pattern; prescribed motion computed once; reference point loads and BCs go
through Resolved like node ones (Mesh::label_dofs); one dof-direction rule;
StepResult::locate for probes; dead Csr::restrict removed.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* solver: refuse oversized reductions before allocating them
A held distributing coupling point makes a dense (3N)^2 block; estimate it from
the constraint rows and refuse it against the factorization's memory budget
with a clear message, before anything is built. Other reductions with
dependents count their entries first (stopping at the budget) and reserve
fallibly.
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]>
* 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]>