The matrix-free sweep
Textbook PGS assembles the and sweeps its rows. Steel’s general sweep stores two vectors per row instead, the Jacobian row and its response , and keeps the world’s velocity live for the whole solve. A row update reads , projects, and writes the impulse change back into :
Because after every update, equals the dense residual . The two are the same iteration; every off-diagonal coupling is applied and none is stored. Each row costs work proportional to the world’s DOF count instead of its row count, and memory grows with rows times DOFs instead of rows squared. Newton 1.8 removed the dense Delassus path for this reason (solve_mode="split" now runs "serial").
The toy stacks boxes on the ground in one dimension; contact sits under box . Its exact impulse is the weight of everything above it times . Each sweep runs from the ground up. Load reaches the ground slowly, and more slowly as the stack grows or as heavy boxes sit on light ones, which is why tall stacks and large mass ratios are iteration-limited. The green and blue curves lie on top of each other: the matrix-free update and the dense update agree to rounding. The orange curve adds Nesterov extrapolation with gradient restart, the idea behind nesterov_momentum; the toy shows the mechanism, not Steel’s measured rates. The 3D stack is an exploded view of the same plain sweep: each contact’s four arrows grow toward the tick that marks its exact load.
On ordinary scalar rows cfm only shifts the denominator (drive rows of drive_mode="rows", the coupled friction modes’ contact blocks and compliant normal rows leave it out): each update moves over of the way, like a relaxation below 1, and an unregularized row converges to the same impulse. It changes a converged answer only where a row is regularized: a single resting contact under contact_regularization settles deeper by the factor , and cfm floors the regularization of enable_bilateral_preelimination. Solver documentation of this is in review in skild-ai/newton#24. Tutorial: Relaxation and CFM
Small worlds
Section titled “Small worlds”Very small worlds, such as one arm and one object, are solved by specialized kernels that keep the whole problem, including a small dense response matrix, in . A classification kernel assigns every world each step from its live row counts; anything that does not fit a specialized kernel runs the general sweep, so correctness never depends on a fast path.
Serial and colored, immediate and propagation
Section titled “Serial and colored, immediate and propagation”`solve_mode="serial"` (default)
A fused kernel sweeps each world’s rows in order, one warp per world, with every iteration in one launch; some configurations use specialized small-world kernels instead. Best for articulated robots and small scenes.
`solve_mode="colored"`
Contacts of a world are colored so no two in a color share a responding body, and each color is solved in parallel. Requires articulated_contact_response="propagation". Best for piles of free bodies.
`articulated_contact_response="immediate"` (default)
Contacts on articulations are dense rows over the articulation’s coordinates with response . Required for loop closures, Nesterov momentum and coupled use.
`"propagation"`
Contacts are fixed-size rows at the touched bodies with each body’s 6×6 response from the articulated-body factorization; each iteration propagates the impulses through the tree. Which response is faster depends on the model.
Step through one world: an arm whose two fingers hold a box, next to a stack of two boxes. Serial and colored change the order rows are swept in; immediate and propagation change how a contact on an articulation reaches the joints. Tutorial: Solve modes · Iterations and Nesterov momentum
Steel docs and tutorials are licensed under Apache-2.0. Third-party notices. "Skild", "Skild AI" and the Skild logo are trademarks of Skild AI and are not licensed under Apache-2.0.