Architecture

STARK’s public API is straightforward. Users work through a single entry point, Simulation, which exposes all physics subsystems. Internally, Stark orchestrates time stepping and uses SymX’s Newton solves.

Component Map

        flowchart TD
    Sim["Simulation"]

    Def["deformables"]
    RB["rigidbodies"]
    Int["interactions"]
    Pre["presets"]

    Core["Stark"]
    SymX["SymX"]

    Sim --> Def
    Sim --> RB
    Sim --> Int
    Sim --> Pre
    Sim --> Core
    Def & RB & Int -.->|register| Core
    Core --> SymX
    

Simulation

Simulation is the single public entry point. Constructing it with a Settings object is all that is needed to start a simulation:

stark::Settings settings;
settings.output.directory = "./output";
settings.simulation.max_time_step_size = 0.01;

stark::Simulation simulation(settings);

The four subsystems are available as public shared_ptr fields:

simulation.deformables   // deformable meshes and FEM energies
simulation.rigidbodies   // rigid bodies and joints
simulation.interactions  // cross-system contact and attachments
simulation.presets       // high-level scene factories

Once the scene is built, the simulation is advanced by calling run():

simulation.run();                  // run until no time events remain
simulation.run(5.0);               // run for exactly 5 seconds
simulation.run_one_time_step();    // advance by a single time step

Time-dependent boundary conditions and scripted motions are registered through simulation.get_script() or simulation.add_time_event(). See Simulation Loop for the full API.


Physics Subsystems

deformables

Manages all deformable objects: rods, shells (or cloth), and volumetric soft bodies.

Internally, all deformable node positions and velocities are stored in a single flat array inside PointDynamics. When you add a mesh, its nodes are appended to that shared array and identified by a PointSetHandler. This flat representation keeps internals simple and improves parallelism and vectorization.

The energy models that act on point sets are:

Model

Description

EnergyLumpedInertia

Mass and Rayleigh damping for any topology

EnergyPrescribedPositions

Penalty-based kinematic boundary conditions

EnergySegmentStrain

1D stretching for rods and cables

EnergyTriangleStrain

2D membrane strain for cloth and shells

EnergyDiscreteShells

Bending stiffness

EnergyTetStrain

3D volumetric FEM for soft bodies

In practice you almost never compose these by hand. The Presets subsystem wraps the most common combinations into single calls. The Deformables page covers the full API for when you need direct control.

rigidbodies

Manages rigid bodies and the constraints between them.

Like deformables, all rigid-body state lives in a single flat array inside RigidBodyDynamics. Each body has six DOFs (3 translational, 3 rotational) and is identified by a RigidBodyHandler.

The energy models are:

Model

Description

EnergyRigidBodyInertia

Mass, inertia tensor, and Rayleigh damping

EnergyRigidBodyConstraints

All joints, motors, and springs between bodies

See Rigid Bodies and Rigid Body Constraints for the full API.

interactions

Manages energies that couple the two state systems — or connect objects of the same system across separate point sets.

Model

Description

EnergyFrictionalContact

IPC-based frictional contact (deformable–deformable, rigid–deformable, rigid–rigid)

EnergyAttachments

Penalty-based gluing of surface or point pairs

See Contact and Attachments.

presets

High-level factory calls that compose inertia, strain, bending, and output registration into single calls. Most users should start here. See Presets for the full list.


Stark class

Stark is the engine that drives the simulation.

Its key components are:

  • GlobalPotential — the SymX energy registry. Energy models call global_potential->add_potential(...) during construction to register their symbolic expression and the state variables it acts on.

  • Callbacks — hook points for injecting logic at fixed moments in the loop: before_time_step, on_time_step_accepted, after_time_step, and write_frame.

  • EventDrivenScript — fires lambdas at specified simulation times or on solver events.

  • Settings — output paths, time step size, Newton tolerances, contact parameters, and more.

Under normal use you do not interact with Stark directly. When writing a custom energy model that extends STARK, you access it through simulation.get_stark(). See Extending STARK for a worked example.