Commit Graph
13 Commits
Author SHA1 Message Date
Christian Svensson f7dcd46b2f engine: draw fluid results as slices, coloured obstacles and streamlines
After solve.fluid the results view had nothing to draw: a fluid step's
fields are per cell, the view only knew nodal fields, and the deformed
display it built dropped the geometry surfaces, so even the part
vanished.

A fluid step now has its own display (`engine::flow`, on render's
flow display data), shared by the headless pictures and the window:
the part drawn as it is, its faces coloured by the field in the fluid
beside them, the field on a slice through the domain and streamlines
seeded on the inlet face upstream of the obstacles, coloured by speed
when the legend shows velocity. It is first shown with velocity
magnitude on a slice through the middle, normal to the horizontal axis
across the flow.

New commands: results.slice {step, field: velocity|pressure, axis:
x|y|z|none, position, frame}, results.surface {step, show} and
results.streamlines {step, show, count, max_steps, seeds | line,
frame}, which replies with what it traced. results.contour takes
velocity and pressure for fluid steps (a new `pressure` field) with
the usual bands and legend clamp, and results.frame walks a fluid
step's frames. Streamlines leave the coming-soon list. Hostile
parameters are refused, and the counts are capped.

Part of #193.
2026-10-17 07:25:04 -04:00
jyvikoandClaude Opus 5.5 5112855b83 results: clamp the contour legend's range; values above it in an over colour (#191)
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
2026-10-15 11:07:46 -04:00
jyvikoandClaude Opus 5.5 91e8467e4f engine, render: hidden bodies hide their mesh and results; solve totals without round-off
- DisplayMesh::from_model_hiding leaves out a hidden body's elements (and the
  nodes only they use); Session::hidden_elements names them, so the viewport,
  probing and headless pictures skip hidden bodies (#365).
- A solve summary's applied and reaction totals set the round-off of
  cancelling sums to 0 (#319).
- results::principal for the probe's principal stresses (#329).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 09:36:54 -04:00
jyvikoandClaude Opus 5.5 0966dfa2a6 engine: result units, per-step staleness, step symbols, true-scale nonlinear results
- Quantity names the unit of every number the results show from the model's
  unit system (mm, MPa, N, N·mm, mJ, mW, °C or K); Field::title puts it in the
  legend title, and calls a mode shape normalised (#321).
- A solved step's result stays current through edits that leave what it reads
  alone (Model::step_inputs: other steps and what only they use), and comes
  back current on undo (#318).
- Session::step_glyphs: the symbols of what a solved step used, for drawing
  over its results; no load arrows on a frequency step's modes (#327).
- Nonlinear static steps open deformed at true scale like explicit ones, and
  their automatic scale is 1 (auto_scale, shared by the viewport and the
  headless pictures) (#326).
- results.reactions with an empty sets list sums the step's boundary-condition
  sets, as its form says (#328).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 09:36:54 -04:00
jyvikoandClaude Opus 5.5 464a4d50c1 solver: heat flow through each heat load, and the imbalance (#362)
solve.heat's reply and the results report give heat_flows: each convection,
flux and source load's heat into the body, the prescribed temperatures'
total and their sum; the results panel lists them for a heat step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 09:14:34 -04:00
jyvikoandClaude Opus 5.5 5758dc7911 Results: a static step first shows its contours undeformed
The first look at a solved static step draws the von Mises contours on the
true geometry; the deformed shape comes when asked for (Deformed,
results.deformed, results.animate), at the automatic scale. Frequency steps
still open on mode 1 deformed and explicit steps at true scale, as the
owner's notes in #77 ask; a 0.24 mm deflection drawn as 10 mm no longer
reads as a failed part.

Fixes #77

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-14 22:29:44 -04:00
jyvikoandClaude Opus 5.5 32c5c1b307 engine: friction output of implicit contact
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
2026-10-14 15:14:14 -04:00
jyvikoandClaude Opus 5.5 5770288f47 engine: contact output of nonlinear static steps
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
2026-10-14 14:58:32 -04:00
jyvikoandClaude Opus 5.5 2183fdbe81 solver: nonlinear static analysis by Newton–Raphson with automatic increments
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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
2026-10-14 04:00:21 -04:00
jyvikoandClaude Opus 5.5 d5bd74570f Rename the project to FieldCraft
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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
2026-10-13 23:51:40 -04:00
e900f41ce3 FEM foundation B: heat transfer and thermal stress (solids, 2D, explicit), coupled temperature–displacement, solve.heat (#45)
* 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 <noreply@anthropic.com>
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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm

* clippy

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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 <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>
2026-10-13 22:15:03 -04:00
a17752a49f Lattice Boltzmann flow on the CPU: model, solver, engine (M12) (#36)
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 <2501648+jyviko@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:03:12 -04:00
0e97f8dd1d Results display (M4) and offscreen full-UI capture (#28)
* 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 <noreply@anthropic.com>
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 <noreply@anthropic.com>
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 <noreply@anthropic.com>
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 <noreply@anthropic.com>
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 <noreply@anthropic.com>
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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm

* docs/features.md after the rebase

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>
2026-10-13 19:23:05 -04:00