Field Examples
1D Complex Waveform with Initializer
Section titled “1D Complex Waveform with Initializer”A 1024-element complex field seeded with a unit-magnitude sinusoid at angular frequency 3:
local ctx = ooc.create()ooc.set_timestep(ctx, 0.01)
local wave = ooc.add_field(ctx, {1024}, { type = "complex_double", origin = -math.pi, spacing = 2 * math.pi / 1024, initializer = function(i, x) return { math.cos(3 * x), math.sin(3 * x) } end})
local v = wave:values()ooc.log("wave rank=%d first=%0.3f+%0.3fi", wave:rank(), v[1][1], v[1][2])Spectral Representation Metadata
Section titled “Spectral Representation Metadata”Tag a complex field as spectral and Hermitian-constrained when it stores the Fourier image of a real physical signal:
local ctx = ooc.create()
local spectrum = ooc.add_field(ctx, {256}, { type = "complex_double", representation = { domain = "spectral", value_kind = "complex_real_constraint", }, fill = {0.0, 0.0}})
ooc.log("domain=%s value_kind=%s components=%d", spectrum:domain(), spectrum:value_kind(), spectrum:components())If you provide both top-level domain / value_kind and representation = { ... }, the nested representation table wins.
2D Real Field — Radial Gaussian
Section titled “2D Real Field — Radial Gaussian”A 256 × 256 real field with a Gaussian blob centred at the physical origin. The initializer receives row index ix, column index iy, and their physical coordinates x, y:
local ctx = ooc.create()
local blob = ooc.add_field(ctx, {256, 256}, { origin = -1.0, spacing = 2.0 / 256, initializer = function(ix, iy, x, y) return math.exp(-8 * (x * x + y * y)) end})
-- Read center value: row 128 (0-based 127), col 128 (0-based 127)local vals = blob:values()local shape = blob:shape()local cols = shape[2]local center = vals[(127 * cols) + 128] -- 1-based: row*cols + colooc.log("center = %.4f", center)2D Complex Field — Spiral Phase
Section titled “2D Complex Field — Spiral Phase”Initialize a 512 × 512 complex field with a spiral phase pattern using math.atan:
local ctx = ooc.create()
local spiral = ooc.add_field(ctx, {512, 512}, { type = "complex_double", origin = -math.pi, spacing = 2 * math.pi / 512, initializer = function(ix, iy, x, y) local theta = math.atan(y, x) return { math.cos(theta), math.sin(theta) } end})Reading Parameters and Checking Layout Mid-Run
Section titled “Reading Parameters and Checking Layout Mid-Run”Add a field, then inspect its storage metadata, representation tags, and cached stats:
local ctx = ooc.create()local field = ooc.add_field(ctx, {64}, { type = "complex_double", representation = { domain = "spectral", value_kind = "complex", }, fill = {1.0, 0.0}})
local info = ooc.field_info(ctx, 0)ooc.log("format=%s bytes=%d elements=%d", info.format, info.byte_size, info.element_count)ooc.log("domain=%s value_kind=%s", field:domain(), field:value_kind())
local snapshot = field:values()ooc.log("first element = %s", tostring(snapshot[1]))
local stats = ooc.field_stats(ctx, field)ooc.log("rms=%.4f max=%.4f", stats.rms, stats.max_abs)stats:refresh()
local counts = ooc.field_continuity_counts(ctx, 0)ooc.log("continuity dirty=%d stable=%d", counts.dirty, counts.stable)After grabbing snapshots, feed them into Lua visualizations or write them to disk; the Field handle remains valid as long as the context is alive.
Writing Values Back with Set Values
Section titled “Writing Values Back with Set Values”field:set_values(table) replaces the field buffer from a Lua table. The table must have at least as many entries as the field has elements.
Real field — sine wave:
local ctx = ooc.create()local f = ooc.add_field(ctx, {256}, { fill = 0.0 })local data = {}for i = 1, 256 do data[i] = math.sin(2 * math.pi * (i - 1) / 256)endf:set_values(data)Complex field — unit phasors:
local ctx = ooc.create()local g = ooc.add_field(ctx, {512}, { type = "complex_double" })local data = {}for i = 1, 512 do local x = 2 * math.pi * (i - 1) / 512 data[i] = { math.cos(x), math.sin(x) }endg:set_values(data)Higher-rank seeding (rank ≥ 3) — initializers are not supported for rank ≥ 3, so use set_values:
local ctx = ooc.create()local vol = ooc.add_field(ctx, {32, 32, 32}, { fill = 0.0 })local data = {}for i = 1, 32 * 32 * 32 do data[i] = math.random() endvol:set_values(data)One-Shot Stats with Field Stats Compute
Section titled “One-Shot Stats with Field Stats Compute”field_stats_compute returns an immediate stats table without needing a step context:
local ctx = ooc.create()local field = ooc.add_field(ctx, {128}, { type = "complex_double", initializer = function(i, x) local phase = 2 * math.pi * i / 128 return { math.cos(phase), math.sin(phase) } end})
local s = ooc.field_stats_compute(field)ooc.log("mean=%.4f rms=%.4f max=%.4f coherence=%.4f", s.mean, s.rms, s.max_abs, s.phase_coherence)Custom Stats with the Accumulator API
Section titled “Custom Stats with the Accumulator API”Process a subset of elements (e.g. every other row) and compute stats manually:
local ctx = ooc.create()local field = ooc.add_field(ctx, {32, 32}, { initializer = function(ix, iy, x, y) return math.sin(0.2 * ix) * math.cos(0.15 * iy) end})
local shape = field:shape()local cols = shape[2]local vals = field:values()local acc = ooc.field_stats_accumulator_begin()
-- Accumulate only the even rowsfor row = 1, shape[1], 2 do for col = 1, cols do local v = vals[(row - 1) * cols + col] ooc.field_stats_accumulate_real(acc, v) endend
local result = ooc.field_stats_accumulator_finish(acc)ooc.log("even-row rms=%.4f count=%d", result.rms, result.count)Reuse an accumulator across frames to avoid repeated allocation:
local ctx = ooc.create()local field = ooc.add_field(ctx, {64}, { initializer = function(i, x) return math.sin(2 * math.pi * i / 64) end})
local acc = ooc.field_stats_accumulator_begin()
for step = 1, 100 do ooc.field_stats_accumulator_begin(acc) -- reset in-place for _, v in ipairs(field:values()) do ooc.field_stats_accumulate_real(acc, v) end local s = ooc.field_stats_accumulator_finish(acc) ooc.log("step %d rms=%.4f", step, s.rms)endFull Spectral + Phase Pipeline
Section titled “Full Spectral + Phase Pipeline”Compute spectral entropy and phase-coherence metrics for a complex field:
local ctx = ooc.create()local field = ooc.add_field(ctx, {256}, { type = "complex_double", initializer = function(i, x) local phase = 2 * math.pi * i / 256 return { math.cos(phase), math.sin(phase) } end})
-- Step 1: base statslocal s = ooc.field_stats_compute(field)
-- Step 2: spectral stats — updates s.spectral_entropy, s.spectral_bandwidth, etc.local ok, dom_k = ooc.field_stats_compute_spectral_view(field, s)
-- Step 3: phase metrics — updates s.phase_coherence, s.phase_coherence_ema, etc.if ok then ooc.field_stats_compute_phase_metrics(field, s, nil, dom_k)end
-- Step 4: hysteresis lock state (requires ctx + field index)ooc.field_stats_update_phase_lock(ctx, 0, s)
ooc.log("entropy=%.3f coherence=%.3f ema=%.3f lock=%d", s.spectral_entropy, s.phase_coherence, s.phase_coherence_ema, s.phase_lock_state)Tuning Phase-Lock Hysteresis
Section titled “Tuning Phase-Lock Hysteresis”Adjust the global phase config before starting a run to set lock/unlock thresholds and EMA smoothing:
ooc.field_stats_set_phase_config({ lock_on = 0.85, lock_off = 0.70, smoothing_constant = 0.05, weighted = true, deramp_enabled = false,})
local cfg = ooc.field_stats_get_phase_config()ooc.log("lock_on=%.2f lock_off=%.2f alpha=%.3f", cfg.lock_on, cfg.lock_off, cfg.smoothing_constant)Iterating All Fields in a Context
Section titled “Iterating All Fields in a Context”local ctx = ooc.create()ooc.add_field(ctx, {32}, { fill = 0.0 })ooc.add_field(ctx, {32}, { type = "complex_double", representation = { domain = "spectral", value_kind = "complex", }, fill = {1.0, 0.0}})
for i = 0, ooc.field_count(ctx) - 1 do local info = ooc.field_info(ctx, i) local stats = ooc.field_stats(ctx, i) ooc.log("[%d] %s rms=%.4f max=%.4f", i, info.format, stats.rms, stats.max_abs)end