Simulation

Simulated time

Simulated time

Simulation evaluates the resident model repeatedly over a hypothetical clock. It is separate from ledger time: a run is recorded as one replayable ledger event, while its internal steps do not create revisions or modify ordinary binding values.

Use STOCK(initial, net_flow) for integrated state, PREV(tracked, initial) for a one-step memory, and DELAY(tracked, lag_steps, initial) for a fixed history. SIM_TIME() and SIM_STEP() expose the current clock position. Outside a simulation resolve, state functions return their initializer and the clock functions return #N/A, so adding simulation formulas does not alter a point-estimate resolve.

{
  "simulation": { "t0": 0, "dt": 1, "steps": 52, "timeUnit": "week" }
}

Persisted clock defaults can be overridden per request. scenarioInputs apply only to that run. Euler is the default integrator; RK4 is available when every state is a STOCK and is rejected for models mixing discrete PREV/DELAY state. A materialize.frame request returns an immutable model-local frame with column t and one column per requested output.

Every run has a stable runId and records its normalized request plus result digest in model history. Simulation requests enforce configured step, sample, event, population, and wall-time limits.

The same simulation surface supports seeded Monte Carlo fan charts, parameter-matrix experiments and calibration, queue/process models, and spatial-agent playback. Each experiment row has its own replayable run ID. Five executable examples live in the simulation reference catalog.

See the function catalog for signatures and rules-and-schedules.md for wall-clock reactions.