Performance evidence¶
Equivalent finite-J2 return-map execution (2026-10-25)¶
The batched finite-J2 update reuses its existing elastic trial SVD to recover the new plastic gradient. It no longer reconstructs and then solves against the same elastic gradient. The scalar implementation remains an independent arithmetic reference; the material law, state schema, tangent and acceptance criteria are unchanged. Cyclic loading, unloading, reversal, rotations and isochoric prehistory with condition numbers up to 10^4 are checked, including batch/chunk boundaries.
A fresh 64-increment serial periodic-J2/plane-contact confirmation alternates
baseline/candidate/candidate/baseline after warm-up. Solve-and-observe means
are 28.36284 -> 27.46857 s (3.15% less); all four runs retain 64 accepted
increments and 208 Newton corrections, with identical line-search and linear
reason histories. Maximum displacement/state/stress difference is 5.042e-11;
maximum per-point relative tangent error is 5.355e-12. Individual timings,
source hashes, comparisons and the fixed baseline are retained in
evidence/performance/2026-10-25-j2-svd-return-confirmation.json.
This is a bounded implicit solve measurement, excluding setup and publication.
It is not the complete explicit composite run below, which uses another material
route. Do not add this percentage to earlier tangent, preconditioner or predictor
measurements, or use it as evidence of contact mesh independence. Ordinary
installed partial/restart/continuous paths are verified separately in
evidence/contact/2026-10-25-installed-periodic-contact.json.
Complete installed trajectory (2026-10-22)¶
The frozen native wheel at 1ed3c1e1 completed the unchanged 255,041-Hex8,
100,000-increment review model with 25 field frames in 12,295.686 s
(3 h 24 min 56 s), measured from process launch through preparation,
calculation, publication and shutdown. No competing numerical job or local
build was launched during this run; light source review and metadata work
continued. This is an observed local runtime, not a promise for another machine.
The project's own comparable timer was 12,293.966 s versus 14,932.091 s for
the previous frozen 743f10b4 run (17.67% less). The older run had competing
load and a sleep interval, so this difference is not an isolated causal
speedup. Its UTC elapsed duration was 15,322.966 s; do not mix that clock
with the project timer. The controlled alternating late-path screen supports
12.11% less advancement time for the selected combined optimization.
All 25 frames (177 numeric visualization datasets), five final material arrays, 60 checkpoint arrays, 100,000 accepted times, 10,000 accepted-history records and 800 observation records compare equal to the frozen baseline. Numeric arrays are finite and both history hash chains verify. The XDMF view now retains 17-digit coordinates rather than the old 16-digit text rounding. Independent VTK 9.6 reads all 25 frames as one Hex8 volume, matches every field to its HDF5 data and gives zero Warp coordinate error. The field companions occupy approximately 544 MiB; mesh data are shared between frames.
The sufficient cell screen, topology/coordinate identity reuse and operational restart compatibility are reusable core changes. Material law, mass, time grid, geometry, contact settings and worker budgets are unchanged. Execution parity and visualization checks do not establish vendor equivalence, mass-scaling accuracy or a general thermodynamic first law. Confidential model assets and full numerical archives remain local.
Portable decisions, not machine-specific requirements¶
Performance settings are choices to measure, not physical properties of a model. Do not turn this page's worker counts, backend, mesh or time step into requirements for unrelated problems or another computer. Separate three questions:
- Equivalent execution: can caching, batching or scheduling remove work while preserving accepted fields, internal variables and work histories?
- Numerical method: does a different time step, mass, penalty or spatial approximation retain the required physical accuracy? This needs convergence evidence, not just an execution-parity check.
- Platform policy: which available solver/backend and worker budget suits the new machine? Record the selected policy and actual measured runtime.
For an implicit problem, explicitly selecting a supported linear backend can matter more than changing Python code. For example, where the PETSc installation provides MUMPS:
from agentfem import solvers
solver_options = solvers.newton(
linear_solver=solvers.direct_solver(package="mumps"),
)
Pass the policy through the ordinary model.step(..., solver_options=...)
route. This is an option, not a universal default; an unavailable requested
backend must fail, not silently select another algorithm. Check the actual
solver summary, convergence and representative accepted states. Reusing a KSP
owner does not mean reusing an obsolete numerical factorization after its
matrix changes. An implicit linear-solver improvement does not accelerate an
explicit central-difference problem that has no such solve.
For native explicit execution, body and contact may overlap. Inclusive body and contact times therefore cannot be added, and a short owner wait does not mean contact is cheap. Use the phase ledger to locate the critical path, then compare unprofiled advancement and, when claiming full-run performance, the complete installed process. History encoding and visualization cadence are separate output choices; retain scientific samples and accepted-state semantics.
Completed core migration and next installed candidate (2026-10-14)¶
The frozen b962a777 generic-core run has now completed the same 255,041-cell,
100,000-increment review path in 15,465.05 s (4 h 17 min 45 s), including
preparation, export and worker shutdown. The previous migrated-core run took
19,119.11 s; the earlier private implementation took 13,529.51 s. The new
measured total is 19.11% below the former and remains 14.31% above the latter.
These are local complete timings, not a hardware-normalized commercial-solver
comparison or an isolated causal experiment: lightweight source/metadata work
overlapped the new run, and the earlier core run had additional build/test load.
Final compared nodal/material/damage/contact arrays and all 10,000 shared reporting stations agreed exactly. Actual ParaView read one volume mesh with 255,041 Hex8 cells, a complete displacement vector and zero Warp coordinate error. The retained fixed-inertia, initial-adjustment and penalty-contact experiment has not been independently validated against the source solver.
Candidate 608c50bb additionally reuses instance-owned sleeping native workers
and keeps rigid-contact residuals in indexed boundary-node storage through
serial assembly. Two fresh 100→600-increment spans took 81.678/80.525 s, versus
86.036 s for a current-HEAD baseline: about 5.7% less mean segment time. Early
checkpoint comparisons passed; body-only replays at steps 20,000/60,000/90,000
retained all 12 arrays bitwise, but worker reuse alone gave no meaningful late
body-time reduction. Do not infer full-run savings from that short segment or
attribute the combined change to a faster material law.
The selected macOS source-built wheel passed 238 targeted installed tests, nine contact tests per MPI rank, and clean-checkout installed platform acceptance. Its source-archive/native-header packaging is checked separately. The frozen project subsequently completed its full fresh run in 14,646.987 s (4 h 4 min 7 s), 5.29% below the preceding core baseline. All 374 final checkpoint checks pass, including 60 bitwise-equal numeric arrays, and all 10,000 reporting records agree. Actual ParaView confirms one 3D Hex8 volume with complete displacement and zero Warp coordinate error. This is measured end-to-end improvement, not a strictly sub-four-hour result. Lightweight source/metadata work and read-only diagnostics overlapped the run, so it is not an isolated causal benchmark. No mass, loading duration, increment, contact tolerance or material law was changed for this execution optimization.
Frozen-project delivery preflight¶
Before starting a shared frozen project, run the standalone tool from a source checkout or copy it alongside the trusted delivery (it needs only Python 3.11+ for metadata checks):
python tools/check_frozen_project.py /path/to/project --requirements /path/to/requirements.json
python tools/check_frozen_project.py /path/to/project --requirements /path/to/requirements.json --probe --output new-preflight.json
The project must declare a agentfem.frozen-core-project.v2 manifest containing
an installed-site path and nonempty file SHA-256 map. The separate requirements
document uses agentfem.frozen-project-requirements.v1, names the artifact's
system, machine and python_cache_tag, and declares imports and pinned
native_libraries. This is a bounded frozen-delivery format, not a general
environment solver or automatic installer. Only probe code you trust: the probe
imports modules and loads libraries, though it does not execute the case.
Missing/corrupt files and incompatible binary platforms fail before imports.
The optional probe checks the pinned AgentFEM import, reports missing native
dependencies and has a timeout. runtime_ready is separate from
scientifically_validated; neither elapsed time nor a matching machine makes
a physical model correct. For another platform, rebuild the artifact and verify
it there instead of relaxing file checks or changing the engineering Model.
Accepted state and reporting boundaries (2026-10-12)¶
The first frozen generalized native run exposed a migration regression:
private parallel cell auxiliaries had become serial, and mutable auxiliary
outputs needed full-cell copies at the immutable execution boundary. The
candidate correction provides explicit, bounded cell_workers and creates
detached gradient, viscosity and gathered-cell outputs directly in immutable
storage. Each cell retains its original arithmetic order. This fixes missing
execution paths, not the physical model. Byte-identical tests do not establish
a speedup: compare frozen installed runs and multiple nonlinear stations
before promoting a worker budget. Keep the original slower run and its timing.
Installed migration check (2026-10-13)¶
The first frozen generic-core full run (runtime 38b007c0) completed 100,000
increments in 19,119.11 s, versus 13,529.51 s for the earlier private execution.
All compared final scientific fields, material histories and work/contact
records agreed exactly. This is a recorded regression, not a speedup. Local
builds, short tests and a three-second diagnostic overlapped the generic run,
so these two complete timings are not an isolated performance experiment.
After it exited, installed candidate b962a777 was compared sequentially with
installed baseline 7e3c567c, on the same 255,041-cell model and Apple Silicon
host (4 performance and 6 efficiency cores, 32 GiB RAM). Both used 8 material
workers, the same contact settings, process-local TCP transport, and one
OpenBLAS/OMP thread. The candidate explicitly selected 4 auxiliary workers;
physics, inertia, fixed time grid and reporting cadence were unchanged.
| Fresh-run pair; increments 100–600 | Baseline | Candidate | Time reduction |
|---|---|---|---|
| 1 | 93.416 s | 86.286 s | 7.6% |
| 2 | 93.054 s | 88.776 s | 4.6% |
Each run started from zero and advanced 600 increments; the table excludes preparation and its first 100 increments. Both final checkpoint comparisons passed with identical numerical arrays and shared numeric histories. The variation and early loading range limit the interpretation of these savings.
Read-only replay of the same archived states separately measured the complete body trial: gather, geometry admission, material/force update, viscosity and scatter. Two warmups preceded 15 timed repetitions per station.
| Archived accepted step | Baseline median | Candidate median | Time reduction |
|---|---|---|---|
| 20,000 | 96.737 ms | 66.544 ms | 31.2% |
| 60,000 | 107.008 ms | 66.582 ms | 37.8% |
| 90,000 | 112.418 ms | 70.755 ms | 37.1% |
All 12 output arrays at each station were byte-identical, including stress, hidden state, internal work, force and viscosity response. Replay did not migrate checkpoint identity or commit a global increment. It excludes contact, global acceptance and I/O. It therefore does not establish a 31–38% whole-run speedup. The private input assets and detailed archives are retained locally, not distributed as a public benchmark. A new frozen complete run is the next timing gate; independent vendor agreement remains unverified.
The reusable core now has immutable field-record transport and exact live-field comparison before borrowing an accepted material-history snapshot. External field writes remain observable. The optional finite-Hex record cache is off by default: correctness tests alone do not establish a throughput benefit.
results.AcceptedHistoryJournal(path).append_records(new_records) provides
single-writer, append-only accepted reporting, avoiding repeated serialization
of an ever-growing history. Submit only new records, preserve the returned
sha256_tip in final evidence, and read with
read_accepted_history(path, expected_tip=...). It rejects invalid batches
before writing and poisons the writer after I/O failure. It is not a solver
checkpoint, MPI collector or scientific certification.
The architecture priority is one authoritative accepted state per lifecycle:
Operator produces trial response, State accepts/rejects it, Result publishes
observations. An exclusive array owner must not silently replace live fields
when callbacks may access them. The reusable native fused execution and local
exact repair have since moved into the optional built-in execution modules,
with arbitrary state-width, repair-failure and observer tests (see
native_explicit_execution.md). Private material laws remain external; no
fixed native ABI state width belongs in the generic core. Installed full-model
timing remains a separate promotion gate.
For performance promotion, compare repeated early/nonlinear/late segments at identical accepted stations, including hidden history, work, damage and rollback. Then time one complete installed-project run including preparation, checkpoints and export. A projected wall time is not a full-run result. Thread counts, numerical inertia and private contact assumptions are not defaults for other cases. Avoid a broad Model/Procedure redesign merely to accommodate one fast experimental implementation.
Bounded constitutive stress conversion measurement (2026-10-09)¶
The shared finite-strain quadrature driver converts Cauchy to first Piola stress
in NumPy blocks of 1,024 points, replacing a Python loop of individual 3-by-3
inversions. For 20,000 float64 points on the development Apple Silicon host,
five warm repetitions gave median 0.06990 s for the scalar expression and
0.00533 s for the chunked expression (13.1x for conversion only).
Inputs used NumPy seed 823, F = I + normal(0, 0.03) and random stress arrays;
OpenBLAS/OMP thread counts were one. The maximum absolute difference was
8.88e-16. Empty partitions, invalid determinants and nonfinite input/output
remain explicitly checked. This excludes constitutive updates, assembly, I/O
and the global solve; no whole-solver acceleration factor follows from it.
The private finite-Hex residual also separates array-based rollback snapshots
from JSON-ready durable snapshots. On a 4,096-cell (16x16x16) unit cube with
the finite-strain J2 state schema, five warm snapshots measured median
0.00379 s for list expansion versus 0.000156 s for copied arrays (24.2x for
snapshot creation only). tracemalloc peak allocations were 22.54 MB versus
4.36 MB. These are Python-tracked allocations, not process RSS. Real disk
checkpoints originally retained the JSON auxiliary contract. The subsequent
optional numeric-tree encoding below also removes that expansion from durable
serial material snapshots; neither measurement is a whole-solver speedup.
tools/benchmark_checkpoint_arrays.py --size 16 separately compares durable
auxiliary serialization for 4,096 finite-J2 cells, including copied state,
encoding and atomic file writes, but excluding nodal archives and solving.
JSON uses 14,048,099 bytes; typed numeric arrays plus metadata use 4,365,404 bytes
(about 69% less). Python-traced peak allocations are 79,684,017 versus 8,730,193
bytes (about 89% less); these are not process RSS measurements. Every restored
gradient and material field is compared with its source. This measurement
overlapped a capacity run, so its wall times are not presented as a speedup.
The optional v6 format uses non-executable NumPy arrays and a small JSON tree;
existing JSON auxiliary checkpoints retain v5 and remain readable. This does
not extend serial material history to MPI-portable restart.
tools/benchmark_finite_hex_trial.py --size 16 --repeats 7 measures a complete
private serial trial (material, geometry admission, force and spectral screen),
excluding mesh preparation, commit, restore and I/O. On the same host with
OMP_NUM_THREADS=1 and OPENBLAS_NUM_THREADS=1, caching immutable state-layout
sizes and replacing scalar NumPy energy
sum checks with the identical scalar tolerance reduced the warm median from
0.27001 s to 0.22358 s (17.2%). The force norm remained 0.7198301095792459.
Neither material equations nor rejection tolerances changed; boundary tests
compare both sides of the former NumPy tolerance. --profile is diagnostic
only and must not be enabled for comparable wall-clock measurements.
These environment settings do not prove that every runtime uses one thread. A subsequent process sample found the old MPI launcher supervisor consuming CPU in two libfabric sockets threads while waiting for its child. NumPy build metadata alone does not establish the library actually loaded at runtime; the October 10 environment loads conda OpenBLAS through its BLAS/LAPACK dylibs. Treat the measurements above as bounded same-environment observations, not certified single-thread benchmarks. The lightweight installed MPI entry now probes the linked vendor without initializing MPI in the supervisor; the numerical child retains its normal runtime and environment. Timeout and interruption still terminate the owned process group. The transport itself is not silently reconfigured. The underlying mechanisms are documented in the mpi4py initialization controls and libfabric sockets provider. This supervisor saving is not an acceleration factor for the numerical kernel.
Optional MPI idle-CPU diagnostic (2026-10-10)¶
tools/diagnose_mpi_idle.py measures bounded, isolated single-rank children.
It never initializes MPI in its parent or changes the user's environment:
On this macOS ARM64 host with MPICH 5.0.1 and libfabric 2.5.1, three paired
two-second observations measured 1.963–1.995 equivalent CPU cores while idle
with FI_PROVIDER unset, versus less than 0.000036 with FI_PROVIDER=tcp.
A process sample attributed two busy background threads to the sockets
connection listener and endpoint connection manager. These are MPI runtime
threads, not material integration or an unbounded Python loop.
Raw observations are archived in
evidence/hex8/2026-10-10-mpi-idle.json.
The same installed AgentFEM wheel passed the same 50 selected tests per rank
on two ranks with both the default provider and TCP. The selection covers
finite Hex state/energy, ordinary Step output, checkpoint restore, small-strain
Hex and transient rollback. This is local compatibility evidence, not a
multi-node scaling study or a Windows guarantee. Use a process-local
FI_PROVIDER=tcp only after checking the relevant installed MPI runtime;
AgentFEM does not set it automatically. The libfabric project documents the
TCP provider
and marks the older sockets provider deprecated in its
provider overview.
Reducing idle CPU is useful independently of solve time, but is not a solver speedup factor. Keep the provider identical on both sides of a performance comparison. Thread-limit environment variables alone do not prove that MPI has no background threads.
The serial 32,768-cell, 500-increment affine endurance diagnostic completed
with maximum displacement/stress/reference-energy absolute errors of
4.44e-16 / 7.00e-13 / 6.00e-14. Bounded provider batches reduced observed peak
process RSS from 1,054,834,688 to 724,598,784 bytes (about 31%). The older run
was a dirty development diagnostic; the newer run identifies clean commit
f5991141. Both had brief diagnostic overlap, so their 1,090.9 / 1,062.4 s
wall times are not offered as a controlled speedup. The check is an affine
path endurance test, not a spatial convergence or industrial validation result.
A further local trial optimization admits a frozen displacement copy once, then reuses that same admitted geometry through material and force evaluation. It does not cache admission across increments or skip standalone geometry checks. Nine warmed 4,096-cell trials measured 0.21909 s before and 0.19580 s after (about 10.6% less trial time), with identical force norm. Those runs used OMP/OpenBLAS/vecLib limits of one and no concurrent numerical workload. Input-mutation isolation, folded-cell rejection and downstream rollback remain covered by targeted tests. This is again a trial measurement, not a whole-solve or cross-software performance claim.
AgentFEM records execution cost as a first-class part of
SimulationResult. Performance evidence explains the cost of a computation;
it does not turn a completed solve into a scientifically verified result.
The public result contains a stable agentfem.performance-evidence record:
result = model.step(target=displacement).solve_result()
print(result.performance["wall_seconds"])
print(result.performance["workload"]["global_dofs"])
print(result.performance["solver"]["convergence"])
The same record is written to result.json and travels into scientific
datasets through the ordinary result summary.
wall_seconds normally covers the measured public execution call, including
solve and result/output construction. A transient result instead accumulates
its recorded run() calls and the final result construction, so checkpointed
or deliberately segmented execution remains visible. Work completed before
the declared boundary is not retroactively counted. In particular, mesh/model
construction and a JIT compilation completed while creating the numerical
problem remain outside the boundary; compilation triggered lazily during a
measured stage remains inside it. Every manifest records the exact boundary so
a warm solve cannot be presented as an end-to-end cold-start measurement.
What is recorded¶
The common contract separates four kinds of evidence:
| record | meaning |
|---|---|
stages |
wall-clock time and call count for solve, result/output, assembly, history, or provider-owned stages |
workload |
global degrees of freedom, global cells, dimensions, and finite-element identity |
solver |
declared solver policy and convergence/iteration evidence |
parallel |
MPI rank count and the timing reduction rule |
Runtime versions, operating system, machine architecture, scalar precision, PETSc and MPI identity remain in the result's runtime provenance. They are referenced rather than copied into the performance record, so the two sources cannot silently disagree.
MPI interpretation¶
Timing is measured on every rank. Before publication, AgentFEM reduces each
stage to minimum, mean, and maximum rank time. seconds is the maximum: the
parallel critical path that determines elapsed solve time. The spread between
minimum and maximum exposes load imbalance.
Stage timings may be nested and therefore must not be added. For example,
residual_assembly may be included inside run_wall. Call counts are retained
as a single value when every rank agrees and as a min/max range otherwise.
Comparing two programs¶
A defensible performance comparison requires the same physical model and a declared accuracy target. Record at least:
- equations, material laws, loads, constraints, and time interval;
- mesh, element order, global degrees of freedom, and time increments;
- nonlinear and linear tolerances, algorithms, and preconditioners;
- requested fields, output cadence, and checkpoint policy;
- hardware, rank/thread count, software versions, and timing boundary;
- field norms, quantities of interest, balances, and convergence evidence.
Startup, mesh generation, JIT compilation, solve, output, and verification should be compared separately. A faster run with different physics or a looser accuracy target is not an AgentFEM performance claim.
Do not confuse recording a discretization with requiring it to remain fixed for every comparison. Execution optimizations hold it fixed; numerical-method studies may vary mesh or time grid while comparing error, histories and quantities at common physical stations. Bitwise equality is appropriate for unchanged arithmetic, not a universal gate on new algorithms or hardware. Wall-time targets and winning worker counts are observations on a declared machine, not scientific correctness requirements or global defaults.
Contact search measurement¶
tools/benchmark_contact_search.py measures the existing serial triangle BVH
against exhaustive projection on a deterministic planar grid. It checks exact
facet/status identity and tolerance-bounded points, normals, gaps and barycentric
coordinates before timing. Tree construction is reported separately; warmed
query batches alternate execution order and retain individual samples.
Geometry, query and search implementation hashes identify the comparison.
OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 PYTHONPATH=src python tools/benchmark_contact_search.py --output /tmp/contact-search.json
The 2026-10-09 local 128/512/2048-facet, 16-query audit evaluates only 32 exact
facets per batch in each case, versus exhaustive counts of 2048/8192/32768.
All projections agree. This confirms existing pruning; it is not a new
algorithmic improvement, an end-to-end FEM speedup, or distributed scaling
evidence. Timings depend on the machine and are not CI acceptance thresholds.
Curved/ambiguous geometry and MPI correctness remain covered by separate
regressions, not by this planar performance fixture. Profile a representative
full solve before investing in search optimization; do not extrapolate this
microbenchmark to industrial forming. Raw local samples are retained under
evidence/contact/2026-10-09-search-microbenchmark.json in the repository.
Finite-material transport comparison¶
The 2026-10-09 controlled comparison uses clean source 07ee074b, macOS ARM64,
Python 3.11.15, DOLFINx 0.11.0, PETSc 3.25.3 and MPICH 5.0.1. Other numerical
jobs were finished first. Each pair alternates execution order after warmup;
raw times, runtime versions and thread environment are retained. The two routes
use the identical native J2 integration and tangent implementation: only the
ordered per-point object protocol versus optional columnar transport differs.
| Fixed workload | Ordered median | Columnar median | Time reduction |
|---|---|---|---|
| 4,096-cell complete trial, nine measured pairs | 0.17674 s | 0.08102 s | 54.2% |
| 4,096 cells, 200 increments, three measured pairs | 38.8836 s | 17.9949 s | 53.7% |
The first boundary excludes commit, restore and I/O. The second includes time integration, geometry/stability checks, transactions and scheduled monitoring, but excludes setup and disk I/O. This is approximately 2.16 times faster for the measured trajectory, not a general application or industrial-forming speedup. Both routes retain the same equations, tolerances and acceptance checks. All compared nodal/material fields agree within 2e-12 absolute/relative tolerance. The affine trajectory remains in the elastic branch of finite-strain J2 and independently matches displacement, stress and stored energy. It does not measure plastic-path throughput or validate the private route for public use.
Reproduction tools are tools/benchmark_material_transport.py and
tools/benchmark_finite_hex_transport_run.py; raw records are
evidence/hex8/2026-10-09-columnar-trial.json and
evidence/hex8/2026-10-09-columnar-trajectory.json. Do not multiply these factors
by separate checkpoint or geometry microbenchmark factors.
Bounded finite-plastic kernel consolidation (2026-10-10)¶
After the earlier capacity job exited, clean numerical source b8ac0ddd was
measured on Apple M5 (10 logical cores, 32 GiB RAM), macOS ARM64, with the same
default MPI provider on both sides and OMP/OpenBLAS/Accelerate limits requested
as one. This does not suppress the separately diagnosed MPI background threads.
Three paired 4,096-cell, 1,000-increment plastic trajectories alternate execution
order after warmup. The reference reinstates the committed nine-column analytic
tangent, general signed spectral algebra and former geometry contraction;
the optimized route uses batched tangent directions, the applicable spherical
reference-Gram bound and dense cached geometry contraction.
| Same plastic trajectory | Reference | Optimized |
|---|---|---|
| Pair 1 | 85.580 s | 53.751 s |
| Pair 2 | 88.388 s | 54.628 s |
| Pair 3 | 88.648 s | 55.055 s |
| Median | 88.388 s | 54.628 s |
This is 1.62x, or 38.2% less elapsed integration time, for this workload. All final displacement, velocity, stress and state arrays are identical; numeric history entries agree within 1e-12. Material equations, time increments, energy accounting and rejection checks are unchanged. Preparation and disk I/O are excluded. This comparison already uses columnar transport on both sides and must not be multiplied by the earlier 2.16x transport result. It is not an arbitrary distorted-mesh, interface, contact, MPI-scaling or forming speed claim.
tools/benchmark_finite_hex_kernels.py --size 16 --pairs 3 reproduces this
comparison from the development Git history, including pinned reference
0c0df953; it is not a wheel-only benchmark. Raw samples, source hash, runtime
environment and separate microkernel timings are retained in
evidence/hex8/2026-10-10-finite-kernels-trajectory.json.
Microkernel speedups are not whole-solver speedups and must not be multiplied.
Scientific trust boundary¶
SimulationResult.performance is operational evidence. It does not modify
trust_level, satisfy a verification claim, or establish accuracy. A release
or publication performance claim must pair this record with benchmark and
convergence evidence under a named applicability boundary.