📡 Log Channels#
Named log streams emitted by the solver (SimpleLog / logging.push / logging.mark in the C++/Rust sources). Pull a channel out of a finished session with session.get.log.numbers(name) for (x, y) pairs or session.get.log.number(name) for the latest scalar; session.get.log.stdout() / stderr() return the raw text streams. See frontend.SessionGet.
SL-rod-toi#
Format |
list[(time, ratio)] |
Name |
SL-rod-toi |
Safety |
the buffer outlives the call and names rods floats. |
Description |
Fraction in (0, 1] of the rescaled search direction the ROD strain limiter allows, reported separately from the shell limiter’s because a rod-only scene never marks that one. The docstring above is what makes the channel askable by name: a value that only reaches stdout ties every caller to the exact phrasing of a printed line. |
SL-toi#
Format |
list[(time, ratio)] |
Name |
Strain-Limit Time of Impact |
Safety |
the buffer outlives the call and names faces floats. |
a limit |
the barrier above raises the cost of stretching and this |
question from the accepted toi below |
this one says whether |
Description |
Fraction in (0, 1] of the rescaled search direction that can be taken without violating the configured shell or rod strain limits, as returned by the strain-limiting line search. A value of 1.0 means strain limits never bound the step, smaller values mean the strain limiter clamped it. |
asm-contact#
Format |
list[(time, ms)] |
Name |
Assembly |
STEP B15a. The constraint layer |
geometry outside the solved |
incidental |
every friction term anchors itself on the |
Description |
Diagnostic sub-timer of “matrix assembly”: wall-clock ms for the self-contact / collision-mesh Hessian + force assembly (the CSR fill path, including the dynamic-matrix rebuild). |
asm-copy#
Format |
list[(time, ms)] |
Name |
Assembly |
snapshot boundary is where it is for a reason |
moving it would change |
Description |
Diagnostic sub-timer of “matrix assembly”: wall-clock ms to snapshot the elastic fixed matrix into tmp_fixed (the contact-stiffness reference read by the contact assembly). |
asm-elastic#
Format |
list[(time, ms)] |
Name |
Assembly |
Description |
Diagnostic sub-timer of “matrix assembly”: wall-clock ms spent assembling the elastic (membrane / bending / solid) Hessian and force into the fixed matrix. |
asm-strainlimit#
Format |
list[(time, ms)] |
Name |
Assembly |
go back to the state afterwards. Nothing allocates |
adopt_from_dataset |
Description |
Diagnostic sub-timer of “matrix assembly”: wall-clock ms for the strain-limiting Hessian / force contributions. |
clock#
Format |
list[(time, MHz)] |
Name |
GPU SM Clock Speed |
Description |
GPU streaming-multiprocessor clock speed in MHz, sampled from nvidia-smi once per simulation step. Useful for correlating slow steps with thermal or power-related clock throttling on the device. |
dt#
Format |
list[(time, seconds)] |
Name |
Target Step Size |
Description |
Target integration step size in seconds at the start of this simulation step, computed as the configured dt scaled by the current playback rate. The actually advanced step size can be smaller (see the Final Step Size channel) if the line search reduces it. |
final-dt#
Format |
list[(time, seconds)] |
Name |
Final Step Size |
Description |
Step size in seconds that was actually integrated this simulation step. In easy cases this matches the target dt, but it is reduced by the advanced TOI fraction when contacts or strain limits shorten the step, and can also be reduced when enable_retry is on and the PCG solve fails. |
frame-to-time#
Format |
list[(frame, seconds)] |
Name |
Video Frame to Simulation Time Map |
Description |
Pairs of (video frame index, simulation time in seconds) emitted once per output frame. Lets you look up which simulation time each output frame corresponds to, which is useful when the playback rate varies over time. |
initial-check-intersection#
Format |
list[(time, ms)] |
Name |
Initial Intersection Check Time |
Description |
Wall-clock time in milliseconds spent scanning the previous and current vertex positions for self-intersections at the start of the simulation. Only a single record is expected. Useful for diagnosing geometry that begins the simulation already tangled. |
initial-lbvh-build#
AGAINST THEM |
rebuild_trees below fits every BVH to vertex.curr, |
Format |
list[(time, ms)] |
Name |
Initial LBVH Build Time |
Safety |
both CVec`s hold `vertices position triples, and the device |
THE ANALYTIC COLLIDER LAYER, allocated on every scene |
a sphere and a |
The masks are not applied here |
the collision window table may not |
gate REFUSES a scene |
tightening it here declines scenes that are |
Description |
Wall-clock time in milliseconds to build the initial LBVH (Linear Bounding Volume Hierarchy) over faces, edges, and vertices at the start of the simulation, including the collision-mesh BVH. Only a single record is expected. |
initialize#
Format |
list[(time, ms)] |
Name |
Initialization Time |
Description |
Total wall-clock time in milliseconds spent inside the one-time solver initialization (buffer allocation, contact setup, initial LBVH build, initial intersection check). Only a single record is expected, written when the initialize scope exits. The leading time column is the simulation time at the moment of recording, which is 0 for initialization. |
lbvh-build#
Format |
list[(time, ms)] |
Name |
LBVH Build Time |
pose, not merely refreshed |
the Morton order is recomputed, so the tree’s |
Description |
Wall-clock time in milliseconds to rebuild the LBVH (Linear Bounding Volume Hierarchy) over faces, edges, and vertices at the start of each simulation step. This BVH underpins broad-phase contact detection, so this cost tracks mesh size and how often primitives are deactivated by collision windows. |
line-search#
Format |
list[(time, ms)] |
Name |
Line Search Time |
Description |
Wall-clock time in milliseconds spent in the per-iteration line search, which runs continuous collision detection (CCD) plus strain-limit CCD to find the largest feasible substep along the rescaled search direction. One entry per Newton iteration. CLOSED AFTER BOTH STRAIN LIMITERS, NOT BEFORE THEM. The scope opens above the contact sweep and closes after SL_toi and SL_rod_toi are marked, so the limiters are inside the measured span and their two lines print ABOVE > line_search. Recording it where the contact sweep ends would report a shorter time under the line_search name and put the lines in the wrong order. |
matrix-assembly#
Format |
list[(time, ms)] |
Name |
Matrix Assembly Time |
Description |
Wall-clock time in milliseconds spent assembling the global system matrix and right-hand side for the Newton linear solve, including inertia, elastic, stitch, strain-limiting, and contact contributions. One entry per Newton iteration. CLOSED AFTER num_contact AND NOT BEFORE IT, which is what puts > matrix_assembly below * num_contact in the stream. |
max-search-dir#
Format |
list[(time, meters)] |
Name |
Max Search Direction Magnitude |
Safety |
the buffer outlives the call and names vertices floats. |
Description |
Maximum per-vertex magnitude (L2 norm) of the Newton search direction returned by the linear solve for this Newton iteration, in meters. Compared against the max_dx parameter to decide whether the search direction must be rescaled before the line search. |
max-sigma#
Format |
list[(time, ratio)] |
Name |
Max Stretch Ratio |
Safety |
both buffers outlive the calls and name their counts. |
the start-of-step pose. Telemetry rather than a term of the solve |
nothing |
Description |
Maximum stretch ratio among all shell faces and rod edges in the scene, measured at the start of the step before the Newton loop. For shells this is the largest singular value of the deformation gradient (scaled by the shrink factor), for rods it is the current edge length divided by its rest length. A value of 1.02 means a 2 percent stretch. Useful for diagnosing strain-limit tightness. |
max-velocity#
Format |
list[(time, m/s)] |
LEAVING THE DOMAIN IS NOT CAUGHT ANYWHERE ELSE |
the overflow guards |
Name |
Max Vertex Velocity |
Safety |
both buffers outlive the calls and name vertices floats. |
Description |
Maximum speed (in meters per second) among all non-pinned vertices, measured from the previous to the current positions at the start of the step. Pinned (fixed) vertices are excluded. Useful for spotting explosions or abrupt motion in the simulation. |
newton-steps#
Format |
list[(time, iterations)] |
Name |
Newton Iteration Count |
Description |
Number of Newton iterations consumed in this simulation step (before the trailing error-reduction iteration). Values above the configured min_newton_steps indicate the solver needed extra iterations to reach the target advanced step size. |
num-contact#
Format |
list[(time, count)] |
Name |
Total Contact Count |
the advance here, and the report is a HOST CONTRACT |
the kind |
Description |
Total number of active contact and constraint pairs assembled into the system matrix for this Newton iteration, summed across self-contact, collision-mesh contact, and analytic constraints (sphere, floor). A useful proxy for how crowded the collision scene is at this iteration. |
pcg-iter#
Format |
list[(time, iterations)] |
Name |
Linear Solve Iteration Count |
Description |
Number of preconditioned conjugate gradient (PCG) iterations consumed during the linear solve for this Newton iteration. High values indicate an ill-conditioned system or a tight tolerance and often correlate with long linear-solve times. |
pcg-linsolve#
Format |
list[(time, ms)] |
Name |
Linear Solve Time |
Description |
Wall-clock time in milliseconds spent in the preconditioned conjugate gradient (PCG) linear solve for the Newton step direction. One entry per Newton iteration. Typically the dominant per-iteration cost. RECORDED BEFORE THE VERDICT IS READ, because the scope closes before the outcome is tested: a solve that ran to the iteration cap still spent the time it spent, and dropping the row there would leave the stream shortest exactly where it is most worth reading. A ? inside a branch above escapes without this row, and that path is a Fatal that ends the run rather than a failed step. |
pcg-resid#
Format |
list[(time, ratio)] |
Name |
Linear Solve Relative Residual |
Description |
Final relative residual reached by the PCG linear solve for this Newton iteration. When this stays well below the configured tolerance, the solve converged cleanly, values close to the tolerance indicate the iteration cap was hit. In a scene with rigid (PDRD) bodies the reduced solve measures each degree-of-freedom group against its own initial residual, and this reports the worst group, so a body and the cloth cannot mask each other. |
playback#
Format |
list[(time, ratio)] |
Name |
Playback Speed |
Description |
Playback rate applied this step, as a multiplier on the configured dt. A value of 1.0 means real-time playback, below 1.0 slows motion down, and above 1.0 speeds it up. The value can change between steps when the scene scripts playback over time. |
schwarz-fallback#
Format |
list[(time, count)] |
Name |
Schwarz Block-Jacobi Fallback |
Description |
1 if the solver fell back from the Schwarz preconditioner to the SPD-safe block-Jacobi base for this Newton iteration’s PCG solve, else 0. Always 0 under the block-jacobi preconditioner; a nonzero entry is worth reviewing. Recorded every iteration but only printed when nonzero so the common 0 case does not clutter the log. A STRUCTURAL ZERO HERE, NOT AN UNMEASURED ONE, which is why it is quiet rather than a number whose print is decided per iteration. Two things could raise it and this driver has neither: there is no memory guard that degrades Schwarz to block-Jacobi, and schwarz.rs builds its aggregate term so the rz <= 0 breakdown cannot arise. The channel is recorded so a reader asking for it by name gets an answer, and the day a degrade path is added this becomes a Number and starts printing. |
time-per-frame#
/ interpolated |
see pin_at_frame below. |
Format |
list[(frame, ms)] |
Name |
Time Per Video Frame |
Description |
Wall-clock time in milliseconds elapsed between producing the previous output video frame and this one. Because each simulation step can advance less than one frame’s worth of time, this aggregates however many solver steps were needed to cross the frame boundary. |
time-per-step#
Format |
list[(time, ms)] |
Name |
Time Per Simulation Step |
Description |
Wall-clock time in milliseconds spent inside a single advance call (one simulation step). Note that a step does not advance by a fixed dt: the actual step size is reduced by the accumulated time of impact found during the inner Newton loop, so these values also reflect how hard the solver had to work to progress the step. |
toi#
Format |
list[(time, ratio)] |
Name |
Line Search Time of Impact |
Description |
Fraction in (0, 1] of the rescaled Newton search direction that can be taken without causing a collision or violating strain limits, as the minimum of the contact CCD result and the strain-limit TOI. A value of 1.0 means the full Newton step was accepted, smaller values mean the line search cut it short. |
toi-advanced#
Format |
list[(time, ratio)] |
Name |
Advanced Fractional Step Size |
Description |
Fraction in (0, 1] of the target step size that the Newton loop actually advanced, accumulated across all its iterations. The final Final Step Size equals this fraction times the target dt. A value of 1.0 means the full target step completed, smaller values mean contacts or strain limits forced a partial step. |
toi-recale#
Format |
list[(time, ratio)] |
Name |
Search Direction Rescale Factor |
Description |
Scalar in (0, 1] applied to the Newton search direction before the line search, so that no per-vertex displacement exceeds the configured max_dx. A value of 1.0 means the direction was already within budget, smaller values clamp an over-eager step. |