results.export.csv's form listed only nodes and sets, so the parameter check refused the
probe's set, at, mode and frame and the reactions' about point that the command documents.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
Four field kinds in the schema, each checked and described in JSON Schema: labels (nodes or
elements, typed as 1-5, 8 with Use selection taking the viewport's picks), points (rows of
x, y, z, added and removed), multi (checkboxes: coupling DOFs, step output) and number or
auto (the deformed scale). Node and element lists, probe and Delaunay points and block
corners use them; the remaining JSON fields hold geometry-specific shapes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
results.export.csv runs solve.probe or results.reactions and writes their reply as an RFC 4180
CSV: a row per node (node, x, y, z and the quantities the step has, columns it does not have
left out) or per set with the total and the applied load; numbers in shortest round-trip form,
so they read back bit for bit. A stale result is refused. The results panel has Export CSV…
beside Reaction sums and under the probed node: the save picker, or the form without one.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
results.contour takes range {min?, max?} (or "auto"), kept until the field changes: a
singular peak no longer squeezes the field into the bottom bands. Values above a clamped
maximum go to an extra band drawn in the over colour, split exactly at the clamp; the legend
shows that band up to the true maximum and says it is clamped. The results panel has Legend
max/min (Auto or a value), the MCP show_results tool a range argument, and headless pictures
follow the clamp too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
diagnostics.crash_reports.delete deletes one report or all. The window lists each report
(when, what, how many times) with Report…, Copy Path and Delete, and Delete All; ui.prompt
answers it over the control channel.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
The README video's model as a sample: the corpus cantilever-i-beam design opened as geometry,
swept all-hex, clamped at F2:start, 1 kN on F2:top through a kinematic coupling; static step
Load. It has a Start-card thumbnail and a gallery capture; a test checks its tip deflection
against beam theory with shear.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
- geometry.bodies lists each body's vertices; geometry.datum.point by
vertex takes the design's vertex names (labelled Vertex, not Mesh
vertex) (#346).
- geometry.centre: the point for what is picked: a vertex, nodes, a
hole's centre (cylindrical faces or circular edges), else a centroid
(#351).
- mesh.cells' form: the cells first, and a method drop-down per cell
(schema kind RefChoices) instead of JSON (#344).
- interaction.rigid_wall(.delete): rigid walls of an explicit step from
the Interactions tab, no longer coming soon (#350).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
The same check as the app's Help › Check for Updates and fieldcraft-cli update --check: the
latest release, whether it is newer, its page, whether it is signed and the asset this install
would download. It only reports. Checking reaches the network, so only the desktop app and the
CLI switch it on; tests, scratch sessions and the browser build refuse without asking.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
crash: a panic hook and a locked per-run command journal (adapted from
SolidCraft's crash reports). A panic in a command becomes a report with
the model from before it and the command; one outside commands, or an
unclean exit found at the next start (abort, segfault, a crash in a
graphics driver, a kill: what #248 needs), a report with the model the
journal starts from (autosave, file or a copy) and the commands since,
the last control request and the dead run's log lines. Reports are
bounded, deduplicated by signature and replayable (crash::replay, with
writes confined to a scratch folder). The crash folder follows the
automation temp area in --control and CI runs.
logfile: a small size-rotated file logger behind the log facade.
bug_report: GitHub bug-form drafts. Version, OS and what happened by
default, home folder shown as ~; the command journal only with Share my
session, the model only with Include the model as well; a session too
long for the link becomes a file to attach and the clipboard text.
Commands: diagnostics.crash_reports, diagnostics.crash_report,
diagnostics.bug_report (Tools › Help, with its icon) and
diagnostics.crash_test (FIELDCRAFT_CRASH_TEST=1 only).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
view.hide, view.show, view.isolate and view.show_all change which
bodies, surfaces, datums, boundary conditions, loads, reference points
and couplings the viewport draws. The hidden items are view state: the
manifest's `view` keeps them, a change marks the model unsaved, but it
is neither journalled nor undone and leaves results current. Items that
go away are forgotten. Headless pictures leave hidden items out; the
glyph builders take a filter. Tools > View > Show All claims the
commands.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
A datum point by coordinates, at a mesh vertex, a fraction along a
design edge, at a face's centre, or where a datum axis crosses a datum
plane. Datum planes take three datum points or a normal to a datum axis;
axes take two datum points. geometry.datum.edit, .axis.edit and
.point.edit redefine a datum of their kind (partitions cut again);
geometry.datum.delete with cascade also deletes the partitions that cut
by it. The ribbon shows Datum Plane, Datum Axis, Datum Point and
Partition, each with its own icon; edit and delete leave the ribbon
(still commands, claimed by their entries).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
The ~40 parameter checks give a ProblemKind instead of text; Session::execute looks the problem
up in the command's form (a group's missing field becomes that field's own path). Replies still
name keys; forms phrase the same problem by label. A test refuses every field of every form and
checks each refusal names a field of that form.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
Field gains `help`: one or two sentences of our own wording with a
typical value (yield stress: the initial yield, 276 MPa for 6061-T6,
250 MPa for mild steel; hardening modulus explained; and so on), set
next to each field in cmd/forms.rs. Dim::name gives the dimension
("stress"), Field::unit_label the unit or, with no unit system, the
dimension in brackets, and Field::help_text the tooltip with the unit or
where to set the unit system. The JSON Schema description carries the
help too. A test checks every form field has help and every dimensioned
field shows a unit or dimension in every system.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
schema::Problem now holds the &'static Field it is about and a ProblemKind
(Required, NotANumber, Below, Above, NotAChoice, UnknownVariant, ...).
Problem::for_form phrases it by the field's label, Problem::for_agents by
its JSON path, from the same data. The form no longer rewrites problem
text by string matching or re-walks the field tree; field_at moves to
schema.rs for the engine's own Param errors. The forms test matches
EngineError::Param { key, .. } directly.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
Seed design edges by their persistent names with a count or a size, a bias
and a constraint; one undo step each, saved with the model. Seeds on edges a
reopened design lacks are reported as stale.
Part of #230.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
file.sample crank-mirror partitions the crank arm on its symmetry plane, sweeps
one half all-hex (hex20) and mirrors it into one conforming mesh, then defines
the crank-arm model. Samples may now run preparing commands (datums,
partitions) before their script sees the bodies. Its test checks the halves
alike and joined, every element valid and the sets on both halves; the heavy
test solves it: sigma_xx at the root -62.43 / +62.43 MPa against M/Z = 62.5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
A symmetry condition (zero normal displacement, zero rotation about the
in-plane axes) on a datum plane normal to X, Y or Z, with its set given or made
of the open design's faces on the plane (a partition's cut faces), so half a
symmetric part is solved as a half. Half a 40 mm bar cut at its mid-width, with
the condition and half the load, bends as the whole bar to 2e-12 with half the
reaction. Inclined planes are refused as not supported yet.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
The bodies' elements are reflected across a datum plane (or a point and
normal) with fieldcraft_mesh::mirror and joined on it. The image is tagged as
the design's body at the reflected place (found by volume and centroid, or
named in `as`), its faces with that body's faces under them, so sets by face
name reach both halves. Half a bar meshed hex8 or hex20 and mirrored has the
whole bar's node and element counts and volume, and its bending deflection to
1e-12; tet4 and tet10 mirror valid and conforming.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
Each cell (a body of the open design) gets its own method: structured hex where
one fits (auto falls back to tet and says why), or tet. All go into one mesh.
Cells on either side of a partition are joined: where their element faces
match node for node the nodes are merged; otherwise (hex next to tet, or
different divisions) the two partition faces get a set each and a dual mortar
tie, the reported hex-tet transition. A 40 mm bar cut in half, one half hex,
the other tet, stretches F L / (E A) to 1e-6.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
Datum planes by principal plane and offset, three points, or point and
normal; datum axes by principal axis, two points, or point and direction.
geometry.partition cuts the open design by a datum plane and keeps the
partition in the model, so geometry.open, file.open and undo cut the design
again. Requirements, forms and the Prepare entries are wired; features.md
lists them as ready.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
Opening a design over a model kept its mesh and every definition silently,
even when the design was another part (#145, #114). geometry.open now takes
`model`: "keep" (default: same-design reopen keeps the mesh and sets that
follow persistent face names) or "new" (clears mesh, definitions and
imported surfaces, keeps the unit system). The reply says whether the design
is `related` to the model's geometry references and lists `stale` mesh
bodies and sets. One undo step either way.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
file.sample crank-arm: a 170 mm 6061-T6 crank built in SolidCraft
(crates/engine/samples/crank-arm.json), swept along z by mesh.hex.generate
as 7274 hex20 elements of 3 mm (scaled Jacobian min 0.17). The hex variant
drops the pocket floor fillet and boss chamfers, and its root arcs meet the
bosses 20 degrees off tangent so the arm's top face has no zero-angle cusp.
The square bore is fixed and 1500 N acts on the pedal hole; the faces are
picked by their surfaces, not their names. Its heavy test matches the root
bending stress to M/Z = 62.6 MPa within 3 % (0.3 % in practice).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
file.sample bracket-hex: the corpus bracket split into 30 SolidCraft cells,
meshed by mesh.hex.blocks as one conforming hex20 mesh of 3 mm, clamped at
the upright and loaded at the foot. The sample's script finds the clamp and
load faces in every cell that has them. Its test matches the tip deflection
of a fine tet10 solution within 1 % and checks the clamp carries the load.
Closes#166
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
file.sample heated-bracket: the corpus filleted bracket in steel, tet10, its
hole bores clamped, the upright's end held at 120 C and the rest cooled by
still air; one coupled temperature-displacement step. Its test checks the
temperatures against the heater and the air, then warms the bracket evenly,
clamps one hole, and matches the free thermal expansion alpha dT times the
distance from the hole along x.
Closes#165
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
file.sample flow-past: air at 25 mm/s past the upright L-bracket in a box of
2.5 mm lattice cells (Re 83), inlet, outlet, a no-slip floor and slip walls;
the fluid step reports the force on each named face. Its test holds the
drag coefficient on the upright's frontal area between 1 and 3.5 (2.3) and
the lattice's mass change under 1 %. No picture: the viewport does not draw
flow results yet (M12).
Part of #164 (its streamlines wait for a flow display in the viewport)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
file.sample rubber-seal: a gasket ring of hybrid hex8 elements in four
mapped quarter blocks, squeezed 2.5 mm between plates bonded to it
(nonlinear static, Mooney-Rivlin rubber). Its test frees the plates and
matches the closed form for incompressible uniaxial compression within 3 %,
and bounds the bonded ring's extra stiffness. The plates are prescribed
displacements until implicit contact (#161) can press it into a groove.
Closes#163
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
file.sample drop-test: an L-bracket standing on its foot (a SolidCraft script
in sample.rs) swept into hex8, falling 2 m onto a rigid floor tilted 15 deg;
explicit dynamics for 1 ms with gravity and plasticity. Its test checks the
mass against rho V, the impact speed sqrt(2 g h) and kinetic energy, the
energy balance and the momentum the floor takes. docs/examples.md starts
with it, and its picture is docs/media/examples/drop-test.png.
Closes#162
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
solve.nonlinear counts the slipping nodes, solve.probe gives a secondary node's shear traction
and slip, and the results display draws contact_shear and contact_slip, contact_status coding
stick and slip.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
solve.nonlinear summarises each contact (normal force, largest pressure, closed nodes, deepest
penetration, augmentations), solve.probe gives a secondary node's pressure, gap and status per
contact, and the results display draws contact_pressure, contact_gap and contact_status. The
contact commands, the catalogue and the model docs say what nonlinear static steps do with a
pair.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
An explicit step may ask for mass scaling to a target time increment (on
a set, or the whole model): elements whose stable increment is below it
get the density that reaches it, with their lumped masses, frequency
bound and hourglass scales; adiabatic heating keeps the physical
density. The run reports the elements scaled, the added mass in all and
per section with its fraction, a warning, and the added mass's kinetic
energy in the energy account. Verified on a uniform bar scaled to twice
its increment (added mass 3×, increment doubled, a quarter of the
kinetic energy left to the physical mass). ROADMAP and parity note the
hyperelastic materials and mass scaling.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
NonlinearStatic.arc_length {constraint, max_load_factor, displacement_limit}: Riks–Crisfield
arc-length increments (cylindrical or spherical arc, tangent predictor signed by the angle
criterion, the constraint's quadratic root chosen by the angle with the last iterate), arcs
grown, shrunk and cut back as increments are. The converged state's tangent is factored for the
next predictor (LDLᵀ when indefinite); its negative eigenvalues are recorded per increment and
changes in their count are reported as limit or bifurcation points. Ends at the maximum load
factor, a displacement limit or the increment cap. Abaqus *STATIC, RIKS; LS-DYNA refuses it by
name; forms gain the arc-length group. A shallow arch of hex20 snaps through on the closed-form
path (1.9 %), both limit points found, inertia 0 → 1 → 0 between them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
Fixes the build of develop: #171 crossed with the typed command forms, so BUCKLE lacked its
form. SOLVE_BUCKLE follows SOLVE_FREQUENCY; the step form gains the buckle variant and the
nonlinear step's imperfection group.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
cmd/forms.rs describes each command's parameters: model definitions (sets,
materials with elasticity, plasticity, hyperelasticity, damage, thermal and fluid
options, sections, reference points, couplings, masses, springs, boundary
conditions, loads, fluid domains, steps including nonlinear and explicit),
meshers, solvers, deck export, files and results. Tests check that every command
has a form and that a form's defaults are accepted or refused only for the
required fields left empty.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo