Context Creation
On this page
Lifecycle at a Glance ✨
The simulation context (ctx) is the core object managing state, operators, fields, and execution. Use the following functions to create and control contexts:
| Function | Parameters | Description |
|---|---|---|
create |
[config] |
Create a new simulation context with optional configuration. |
context_init_with_universe |
[config], [universe] |
Create a new context with an explicit universe (q/K/epsilon/poles). |
step |
ctx |
Advance the simulation by one timestep. |
on_step |
ctx, fn |
Register a callback to execute after each step (accepts nil to clear). |
run |
ctx, [config] |
Start a scheduling loop (GUI mode) with optional config. |
pause |
ctx |
Pause the scheduling loop. |
resume |
ctx |
Resume a paused scheduling loop. |
shutdown |
ctx |
Shutdown the simulation context, releasing resources. |
Quick Setup 💡
- Create & configure — call
create()with optional config, then set your timestep. - Add state — allocate fields and operators, then attach an integrator with
set_integrator. - Drive the loop — step manually with
stepor hand off to a scheduler viarun. Useon_stepfor lightweight instrumentation.
Configuration Keys 🔑
Top-level Config
| Key | Type | Notes |
|---|---|---|
worker_count |
integer |
Number of worker threads; defaults to the runtime’s autodetected value. |
enable_logging |
boolean |
Enable the async scheduler logger; uses log_path when set. |
enable_profiling |
boolean |
Enable per-operator profiling counters and snapshots. |
enable_timestep_heuristics |
boolean |
Enable adaptive timestep heuristics and timestep_decision. |
frame_time_budget_ms |
double |
Soft budget for per-frame work; used by schedulers that honor frame pacing. |
base_seed |
integer |
Seed for context RNG streams (noise, stochastic integrators, scripted RNG). |
backend |
string |
Backend request: auto, cpu, cuda, or metal. |
backend_fallback |
string |
Policy when the requested backend is unavailable: allow, warn, or fail. |
log_path |
string |
Optional log file path for the async logger (safe relative path only). |
continuity_override |
table |
Optional continuity guard applied across operators (see below). |
Note: Implicit Global Config
If you call
create()orcontext_init_with_universe()without an explicit config table, Oakfield will also look for a globalsim_configtable and apply the same keys from there.
Continuity Override
| Key | Type | Allowed Values | Notes |
|---|---|---|---|
enabled |
boolean |
true/false |
Toggles continuity guards globally. |
mode |
string |
none, strict, clamped, limited |
Modes mirror operator schema defaults; strict preserves analytic continuity while clamped/limited bound singularities. |
clamp_min / clamp_max |
double |
any | Hard bounds applied when clamped or limited. |
tolerance |
double |
any | Blending window for limited mode. |
boundary |
string |
neumann, dirichlet, periodic, reflective |
Inherits boundary policy definitions from operator schemas. |
spacing |
double[] |
positive | Optional array of spatial spacings; overrides default operator spacing. |
dx |
double |
positive | Optional scalar spacing override; dx is used when spacing is not an array. |
Note: Continuity Override Behavior
Continuity overrides are applied immediately after creation via
context_set_continuity_override, so the first operator you register already reflects the chosen policy.
Runtime Continuity Controls
You can update (or disable) the global continuity override at any time:
-- enable/replace override
ooc.context_set_continuity_override(ctx, true, {
mode = "limited",
tolerance = 1.0e-3,
boundary = "neumann",
})
-- disable override (keeps defaults from schemas)
ooc.context_set_continuity_override(ctx, false)
Note: Scheduler-backed Execution
worker_count,enable_logging,enable_profiling,enable_timestep_heuristics,frame_time_budget_ms, andlog_pathprimarily affect scheduler-backed execution.That includes
run(ctx, ...), and alsostep(ctx)when the runtime chooses the scheduler path internally (for example: multi-worker execution with an attached integrator and no Lua operator callbacks). Whenstepfalls back to the legacy single-threaded path, those knobs have little or no effect.
Caution: Log Path Safety
log_pathmust be a safe relative path (no absolute paths or..traversal). Invalid paths raise an error when the config is applied.
Example 📖
local ctx = ooc.create({
worker_count = 2,
log_path = "logs/run.log",
continuity_override = {
enabled = true,
mode = "clamped",
clamp_min = -4.0,
clamp_max = 4.0,
boundary = "neumann",
}
})
ooc.set_timestep(ctx, 0.025)
local field = ooc.add_field(ctx, {768}, {
type = "complex_double",
fill = {0.0, 0.0}
})
local integrator = ooc.create_context_integrator(ctx, "rkf45", {
initial_dt = 0.025,
tolerance = 1.0e-3,
safety = 0.9
})
ooc.set_integrator(ctx, integrator)
ooc.on_step(ctx, function(c)
local t = ooc.get_time(c)
ooc.log("step %d at t=%.3f", ooc.get_step_index(c), t)
end)
ooc.step(ctx) -- single-step drive
ooc.shutdown(ctx)
Tip: When to use run
run,pause, andresumeare thin scheduling helpers intended for GUI/evented drivers.For scriptable batch jobs (as in
lua/scripts/cli/*), explicitsteploops keep control flow and logging predictable.
Universe & Seeding (Advanced) 🧬
Most scripts should use create. If you need to control the special-function universe at context construction time, use:
context_init_with_universe([config], [universe]) -> ctx
The function accepts either order (config/universe are auto-detected by keys). universe may include:
q(number)K(integer, non-negative)epsilon(number)sieve_sigma(number)poles(array of{x,y,z,residue,type};typeis"digamma"|"trigamma"|"tetragamma")
You can read the normalized base seed used for deterministic RNG streams with:
context_seed(ctx) -> integer
Representation & Time Model 🧭
Representation mode governs determinism guarantees and what kinds of operators/kernels are allowed:
context_set_representation_mode(ctx, mode)
context_representation_mode(ctx) -> mode_value, mode_name
mode accepts strict, relaxed, or exploration.
Common aliases are also accepted:
explore/experimentalforexploration
Time model controls whether dt refinement is treated as convergent (continuous flow) or as part of a discrete map:
context_set_time_model(ctx, "continuous" | "map")
Aliases:
flowforcontinuousdiscreteformap
Backend Escape Hatch 🔌
Most scripts should use the backend / backend_fallback config keys. For lower-level host integration, the context also exposes its raw backend pointer:
context_backend(ctx) -> lightuserdata|nil
context_set_backend(ctx, backend_ptr_or_nil)
Passing nil detaches any explicitly assigned backend. This is primarily for embedders or tooling that already owns backend instances.
Drift Sandbox 🧪
Drift mode is a “no side effects” evaluation mode used by tooling to probe operators without updating continuity counters/warp masks. Some operators also implement optional save/restore hooks so state is reverted.
context_begin_drift(ctx)
context_end_drift(ctx)
context_in_drift(ctx) -> boolean
Context Logger 🧾
Attach a per-context logger callback (distinct from the scheduler’s async logger):
context_set_logger(ctx, fn_or_nil)
fn_or_nil is called as fn(level_int, message_string).
Emit warnings through the context logger (falls back to stderr if no logger is set):
context_log_warning(ctx, fmt, ...)
Determinism & Kernel Gating 🧷
These helpers let tooling decide whether a kernel-backed operator is allowed given the current backend and representation policy:
context_allows_determinism(ctx, flags) -> boolean
context_kernel_allowed(ctx, required_features, determinism_flags) -> boolean
context_kernel_allowed_mode(ctx, mode, required_features, determinism_flags) -> boolean
flags / determinism_flags can be an integer bitmask or a table of strings:
"pure_time", "rewind_safe", "no_stateful_nodes", "deterministic_rng_only".
Memory Limits & Scratch Accounting 🧠
Contexts track memory usage for fields and scratch allocations and enforce configurable limits:
context_set_memory_limits(ctx, limits_table)
context_get_memory_limits(ctx) -> limits_table
context_memory_usage(ctx) -> {fields, scratch, total}
context_check_field_limits(ctx, element_count, field_bytes) -> ok, result_code
context_reserve_scratch(ctx, bytes) -> ok, result_code
context_release_scratch(ctx, bytes)
limits_table keys:
max_field_elementsmax_field_bytesmax_fieldsmax_total_field_bytesmax_scratch_bytes_per_operator
Diagnostics & Special-Function Flush 🩺
Read the context diagnostics snapshot (fault counts, representation adjustments, etc.):
context_diagnostics(ctx) -> table|nil
context_diagnostics_const(ctx) -> table|nil
When compiled with SIM_DIAGNOSTICS, you can flush accumulated special-function diagnostics into the context:
context_flush_special_diagnostics(ctx)
If diagnostics are disabled, the Lua binding returns false, "SIM_DIAGNOSTICS disabled".
Manual Operator Application 🧰
Apply a single operator immediately (bypassing step/integrators). Useful for debugging or tooling:
context_apply_operator(ctx, operator_or_index) -> ok, result_code