Table of Contents

Milling physics, training and measured data

  • Physics runs in the native kernel. The per-step milling physics migrated into core.dll in stages: the engagement is scan-converted natively at the substraction completion point, the force kernel is reached through the same handle with no managed marshal, and the sequential cutting-temperature and wear chain runs from a native thermal session held per (tool, cutting parameter) pack. The switch is EnableNativeMillingPhysics, surfaced runtime-only (not persisted to project XML) as EnableNativeMillingPhysics and EnableNativeMillingPhysics, and it now defaults to true. Public entry points that used to reach the managed kernel still work: without a session pack they build an ad-hoc physics pack per live (cutting parameter, tool) pair and run natively.
  • MillingToolPhysicsPack is an immutable record holding one tool's scalar derivations for one cutting-parameter set — spindle-buckle-to-tip length, observation height, effective cutting diameter, the bending/Z-deflection pair, the simplified rake angle, the minimum uncut chip thickness. MachiningSession owns the packs keyed by tool id (GetToolPhysicsPack) and invalidation is explicit at the points that know the state changed: every run-op start and the tool-change act, plus InvalidateToolPhysicsPacks. The corresponding MillingTool / MillingCutter members are now deliberately uncached pure computations.
  • Milling-force waveforms are reproducible again. The parallel per-step force build read lazily built scalar caches on the shared tool objects; a thread could pass a cache guard and then read a value a concurrent writer had stored in between, so two plays of the same NC exported different forces in the thin-chip window of each tooth pass. The caches were first republished as single immutable references and then removed in favour of the frozen session pack.
  • Thermal gating and seeding. The sequential cutting-temperature and wear build now checks EnablePhysics (spindle temperature deliberately keeps running), and the tool-change thermal seeding re-arms whenever the incoming chain state has no flute temperature list — which covers fault and cancel re-seeds, stop-then-replay residue, and EnablePhysics being switched on mid-session. The shank temperature list is seeded to the exact node count the thermal FEM builds, so trailing shank nodes no longer sit at 0 K after a tool change.
  • Cutter geometry is validated up front. GetUpperBeamGeometryIssues collects upper-beam and shank configuration problems as keyed messages — for example an extended-cylinder beam whose full length sits below the flute height (Cutter-UpperBeam--ExtendedCylinderFullLengthTooShort), which inverts the shank solid and makes the shank thermal model unbuildable. They are reported once per tool at BeginSession and at each tool change, instead of surfacing later as a null-reference cascade inside the thermal physics with nothing naming the beam.
  • RakeFaceCuttingPara3d no longer throws on a six-field parameter string (the guard read the seventh element behind a >= 6 check), and the published coefficient index mappings are corrected: the LocalProfileMillingPara(Vec3d, Vec3d) constructor maps (x,y,z) to (Ksr, Kst, Ksa) / (Kpr, Kpt, Kpa), and the 2d element index range is 0–3 with 0=Ksc, 1=Ksn, 2=Kpc, 3=Kpn.
  • Training diagnostics name their cause. The per-step warnings split into Train-StepLuggage--Unreadable (the step luggage row could not be read back) and Train-StepEngagement--Missing (the row is present but the engagement was never built because physics was inactive at simulation time). The gather pass counts both against the eligible steps: silent at zero, one summary warning at or below MissingEngagementAbortRatio (default 0.25), and a configuration error above it. The breakdown in that summary is the diagnosis: misses sitting on the engagement level mean the play itself ran with physics inactive, while a scattered few on the luggage level are the read-back path, where a segment that covers a step but lacks its row is dropped and answers null once before the next read rebuilds it. Above the ratio the training aborts instead of continuing on what is left, because a parameter file built from a fraction of the play is indistinguishable from a sound one once it has been written — its coefficients are read back later as a real effect. Set the ratio to 1 to never abort. A gather pass that produces no samples at all now reports immediately rather than throwing inside the SVD solve, separating “not one step touched the workpiece” from “touched steps whose mapped force data yielded no usable shots”.
  • New training knobs. EnableDesignMatrixSolver (default false) solves the least squares on a thin QR of the design matrix instead of forming the normal equations, which square the condition number; DesignMatrixSvdRelativeTol is its truncation cutoff. EnableCwePhasePairing (default false) determines each step's rotation phase with a cutter-workpiece-engagement block-pairing detector instead of the self-bootstrapped lead parameter, for one-flute and symmetric two-flute cutters in light radial side cuts. ReTrainAnchorOutputScale exposes the virtual anchor weight. LastMillingParaTrainResult captures the outcome — kind, sample flags, outlier ratio, success, output file, parameter name and note, correlation R, filtered sample count, parameter XML, timestamp — so a caller reads it without re-opening the .mp file.
  • Time mapping is reworked around absolute wall-clock time. AddTimeDataByFile accepts DateTime windows, stored as IFileTimeSection forms, and the project-scoped MappingAnchorDateTime — seeded set-once from the date of the first controller instant seen — converts controller timestamps onto one run-relative axis. EndTimecode replaces AccumulatedTime as the canonical end-of-step time.
  • CSV timing survives midnight. Step durations derive from full date-bearing instants, so a multi-day recording no longer produces negative durations and a negative chart time axis, and a non-physical duration from a spliced recording is clamped with a validation warning instead of stalling physics evaluation.
  • Wall-clock time is dense. The trio moved into one optional sub-object, StepActualTime (Timecode / Instant / IsInterpolated), reached through ActualTime. On CSV plays every built step is stamped: steps built from a controller row re-anchor, and the steps between extrapolate along the machine timeline and are marked interpolated, which makes the actual-time mapper window per-step exact instead of sparse-anchor scaled. Pure NC plays keep null stamps.
  • An empty step-shot pairing window is a data gap, not something to interpolate across. The window builder used to expand outward to the rows bracketing the gap, silently pairing such steps with force values that were never measured — a training run over a file whose transients had been carved out produced a plausible correlation and a full set of coefficients derived entirely from fabricated rows. Such a window now skips its step and one Map-ShotGap--StepsSkipped warning per mapping call carries the count; a window-edge row is interpolated only when its bracketing rows span at most two spindle revolutions.
  • “No cut / No data for step” on freshly-simulated steps is fixed. The bulk step-data readers cached the absence of rows the writer had not committed yet, so a step that had just been simulated could report no data until the program was re-run. A covered-but-missing index now drops the stale segment and re-reads.
  • New end-of-play warnings, each once per session: Play-Touch--None (the play finished without any step touching the workpiece), Tool-FluteCount--Zero (physics is on and a milling cutter resolves to zero flutes, so feed per tooth is undefined), and Play-Physics--None (physics is on and at least one step touched the workpiece but no touched step carries a physics brief — naming the three things that gate it: a tool bound to the spindle, the spindle actually rotating, and the workpiece cutting parameter). That last state previously surfaced one process later, as a training run gathering zero samples.
  • Performance is collected in its own section below.