Utility Operators
📐 Coordinate
Section titled “📐 Coordinate”sim_add_coordinate_operator(ctx, field, opts)
Generate index or coordinate-mapped values into a field. Creates spatial basis functions, gradients, positional encodings, or time-varying coordinate masks.
Method Signature
Section titled “Method Signature”sim_add_coordinate_operator(ctx, field, [options]) -> operatorReturns: Operator handle (userdata)
Mathematical Formulation
Section titled “Mathematical Formulation”Index Mode:
For a field with elements, the raw coordinate at index is simply .
Coordinate Modes:
- axis: or depending on
coord_axis - angle: where is
coord_angle - radial: with optional moving center
- separable: where is multiply or add
Normalization:
Final output:
Parameters
Section titled “Parameters”Core Parameters:
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
mode | enum | "index" | index, coord | Source mapping mode |
normalize | enum | "none" | see below | Normalization applied to coordinate |
gain | double | 1.0 | unbounded | Multiplicative gain after normalization |
bias | double | 0.0 | unbounded | Additive bias after gain |
time_offset | double | 0.0 | unbounded | Time offset for coordinate evaluation |
accumulate | boolean | false | — | Add to output instead of overwriting |
scale_by_dt | boolean | true | — | Scale accumulated writes by dt |
Normalization options: none, unit, centered, signed
Coordinate Mode Parameters (when mode = "coord"):
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
coord_mode | enum | "axis" | see below | Coordinate mapping mode |
coord_axis | enum | "x" | x, y | Axis for axis-mode |
coord_combine | enum | "multiply" | multiply, add | Combine rule for separable mode |
coord_angle | double | 0.0 | radians | Angle for angle-mode |
Coordinate mode options: axis, angle, radial, separable
Spatial Parameters:
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
origin_x | double | 0.0 | unbounded | X origin (mapped to index 0) |
origin_y | double | 0.0 | unbounded | Y origin (mapped to index 0) |
spacing_x | double | 1.0 | >0 | Grid spacing in X direction |
spacing_y | double | 1.0 | >0 | Grid spacing in Y direction |
Radial Mode Parameters:
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
coord_center_x | double | 0.0 | unbounded | Radial center X position |
coord_center_y | double | 0.0 | unbounded | Radial center Y position |
coord_velocity_x | double | 0.0 | unbounded | Radial center X velocity (units/s) |
coord_velocity_y | double | 0.0 | unbounded | Radial center Y velocity (units/s) |
Boundary & Initial Conditions
Section titled “Boundary & Initial Conditions”- Operates elementwise; no boundary handling required
- Output field is overwritten (or accumulated into) regardless of initial state
- For 2D fields, assumes row-major layout with
spacing_xandspacing_y
Stability & Convergence
Section titled “Stability & Convergence”- Unconditionally stable (pure assignment operation)
- Time-varying radial coordinates depend on simulation time; ensure
time_offsetaligns with your integration scheme - No temporal accumulation issues when
accumulate = false
Performance Notes
Section titled “Performance Notes”- Lightweight pointwise operation; O(N) complexity
- Radial mode requires square root per element
- Moving radial center (nonzero velocity) uses simulation time
- Consider precomputing static coordinates once rather than every timestep
Examples
Section titled “Examples”-- Linear index ramp normalized to [0, 1]ooc.sim_add_coordinate_operator(ctx, field, { mode = "index", normalize = "unit"})
-- Signed index ramp [-1, 1]ooc.sim_add_coordinate_operator(ctx, field, { mode = "index", normalize = "signed", gain = 2.0, bias = 0.5})
-- X-axis coordinate with custom spacingooc.sim_add_coordinate_operator(ctx, field, { mode = "coord", coord_mode = "axis", coord_axis = "x", spacing_x = 0.1, origin_x = -5.0, normalize = "none"})
-- Radial distance from center of 256x256 fieldooc.sim_add_coordinate_operator(ctx, field, { mode = "coord", coord_mode = "radial", coord_center_x = 128, coord_center_y = 128, normalize = "signed"})
-- Moving radial center for tracking applicationsooc.sim_add_coordinate_operator(ctx, field, { mode = "coord", coord_mode = "radial", coord_center_x = 64, coord_center_y = 64, coord_velocity_x = 10.0, -- moves right at 10 units/s coord_velocity_y = 0.0})
-- Angled gradient at 45 degreesooc.sim_add_coordinate_operator(ctx, field, { mode = "coord", coord_mode = "angle", coord_angle = math.pi / 4, gain = 2.0, bias = -1.0})
-- Separable X*Y coordinate productooc.sim_add_coordinate_operator(ctx, field, { mode = "coord", coord_mode = "separable", coord_combine = "multiply", normalize = "signed"})🔄 Phase Rotate
Section titled “🔄 Phase Rotate”sim_add_phase_rotate_operator(ctx, field, opts)
Apply a uniform complex rotation to all field samples. Fundamental operation for frequency shifting, demodulation, and rotating reference frames.
Method Signature
Section titled “Method Signature”sim_add_phase_rotate_operator(ctx, field, [options]) -> operatorReturns: Operator handle (userdata)
Mathematical Formulation
Section titled “Mathematical Formulation”For each complex sample :
where is the phase_rate in radians per second.
Equivalent polar form:
The magnitude is preserved; only the phase advances by per timestep.
Cartesian implementation:
Parameters
Section titled “Parameters”| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
phase_rate | double | unbounded | Angular rotation rate in rad/s (required) |
Boundary & Initial Conditions
Section titled “Boundary & Initial Conditions”- Operates elementwise; no boundary handling required
- Complex fields only: Real fields are unaffected (no imaginary component to rotate)
- Initial phase determines starting point; rotation is relative
Stability & Convergence
Section titled “Stability & Convergence”- Unconditionally stable: Rotation is unitary (magnitude-preserving)
- Energy-conserving: remains constant
- Phase accumulates linearly with time:
- For very large , consider reducing timestep to avoid phase aliasing
Performance Notes
Section titled “Performance Notes”- Requires one sin/cos evaluation per timestep (not per element)
- Two multiplications and one addition per complex element
- Very efficient; rotation matrix is computed once per step
- No memory allocation beyond the field itself
Examples
Section titled “Examples”-- Rotate at 1 Hz (2π rad/s)ooc.sim_add_phase_rotate_operator(ctx, carrier, { phase_rate = 2 * math.pi})
-- Negative rotation (clockwise in complex plane)ooc.sim_add_phase_rotate_operator(ctx, signal, { phase_rate = -1.0})
-- Demodulation: shift carrier frequency to basebandlocal carrier_freq = 440.0 -- Hzooc.sim_add_phase_rotate_operator(ctx, modulated_signal, { phase_rate = -2 * math.pi * carrier_freq})
-- Slow phase drift for visualizationooc.sim_add_phase_rotate_operator(ctx, wave, { phase_rate = 0.1})
-- Rotating reference frame for oscillator analysislocal omega_0 = 100.0 -- natural frequencyooc.sim_add_phase_rotate_operator(ctx, oscillator_state, { phase_rate = -omega_0 -- move to co-rotating frame})📋 Copy
Section titled “📋 Copy”sim_add_copy_operator(ctx, input, output, opts)
Copy input field samples to an output field, with optional accumulation. Fundamental building block for field routing, buffering, and multi-stage pipelines.
Method Signature
Section titled “Method Signature”sim_add_copy_operator(ctx, input, output, [options]) -> operatorReturns: Operator handle (userdata)
Mathematical Formulation
Section titled “Mathematical Formulation”For each sample index :
Parameters
Section titled “Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
accumulate | boolean | false | Add to output instead of overwriting |
scale_by_dt | boolean | true | Scale accumulated writes by dt |
Boundary & Initial Conditions
Section titled “Boundary & Initial Conditions”- No boundary handling required; operates elementwise
- Input and output fields must have compatible shapes and element counts
- Complex fields are copied component-wise (both real and imaginary parts)
Stability & Convergence
Section titled “Stability & Convergence”- Pure copy is unconditionally stable
- When accumulating, ensure time integration is handled correctly to avoid unbounded growth
Performance Notes
Section titled “Performance Notes”- Minimal computational overhead; essentially a memory copy
- When
accumulate = false, may be optimized to a direct memcpy - Useful for double-buffering or creating field snapshots before destructive operations
Examples
Section titled “Examples”-- Simple field copyooc.sim_add_copy_operator(ctx, source, destination)
-- Accumulate input into running sum (scaled by dt)ooc.sim_add_copy_operator(ctx, flux, integral, { accumulate = true, scale_by_dt = true})
-- Accumulate without dt scaling (raw summation)ooc.sim_add_copy_operator(ctx, sample, buffer, { accumulate = true, scale_by_dt = false})
-- Double-buffering patternlocal u_prev = ooc.sim_add_field(ctx, {N}, { fill = 0.0 })ooc.sim_add_copy_operator(ctx, u, u_prev) -- snapshot before update-- ... operators that modify u ...⚖️ Scale
Section titled “⚖️ Scale”sim_add_scale_operator(ctx, input, output, opts)
Scale input field samples by a constant factor. Essential for applying gain, normalization, or unit conversion.
Method Signature
Section titled “Method Signature”sim_add_scale_operator(ctx, input, output, [options]) -> operatorReturns: Operator handle (userdata)
Mathematical Formulation
Section titled “Mathematical Formulation”For each sample index :
where is the scale parameter.
Parameters
Section titled “Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
scale | double | 1.0 | Multiplicative scale factor |
accumulate | boolean | false | Add to output instead of overwriting |
scale_by_dt | boolean | true | Scale accumulated writes by dt |
Boundary & Initial Conditions
Section titled “Boundary & Initial Conditions”- No boundary handling required; operates elementwise
- Input and output fields must have compatible shapes
- Complex fields: scale applies to both real and imaginary parts
Stability & Convergence
Section titled “Stability & Convergence”- Unconditionally stable for any finite scale value
scale > 1.0amplifies;scale < 1.0attenuatesscale = 0.0zeros the output (prefersim_add_zero_field_operatorfor clarity)- Negative scales invert the sign of the field
Performance Notes
Section titled “Performance Notes”- Single multiplication per element; highly efficient
- Can operate in-place when
input == output - Consider fusing with other operators when possible to reduce memory bandwidth
Examples
Section titled “Examples”-- Apply gain of 0.5ooc.sim_add_scale_operator(ctx, signal, attenuated, { scale = 0.5})
-- Invert field signooc.sim_add_scale_operator(ctx, u, u_neg, { scale = -1.0})
-- In-place scalingooc.sim_add_scale_operator(ctx, field, field, { scale = 0.99 -- gentle decay})
-- Accumulate scaled values (e.g., for weighted averaging)ooc.sim_add_scale_operator(ctx, sample, weighted_sum, { scale = weight, accumulate = true})
-- Diffusion coefficient applicationlocal D = 0.01ooc.sim_add_laplacian_operator(ctx, u, lap_u)ooc.sim_add_scale_operator(ctx, lap_u, du_dt, { scale = D })🗑️ Zero Field
Section titled “🗑️ Zero Field”sim_add_zero_field_operator(ctx, field)
Overwrite all samples in a field with zeros. Commonly used to reset accumulators, clear buffers, or initialize state at the start of each timestep.
Method Signature
Section titled “Method Signature”sim_add_zero_field_operator(ctx, field) -> operatorReturns: Operator handle (userdata)
Note: This operator takes no options table—just the context and field.
Mathematical Formulation
Section titled “Mathematical Formulation”For each sample index :
For complex fields, both real and imaginary components are set to zero.
Parameters
Section titled “Parameters”None. The operator simply zeros the specified field.
Boundary & Initial Conditions
Section titled “Boundary & Initial Conditions”- No boundary handling required; all elements are set to zero
- Operates in-place on the target field
Stability & Convergence
Section titled “Stability & Convergence”- Unconditionally stable; always produces zeros
- Does not depend on timestep or field state
Performance Notes
Section titled “Performance Notes”- Highly optimized; typically compiled to a fast memory-set operation
- Does not use time (
uses_time = false) or timestep (uses_dt = false) - Preserves real subspace (complex fields become real zero + imaginary zero)
Examples
Section titled “Examples”-- Zero a field at each step (useful for accumulators)local accumulator = ooc.sim_add_field(ctx, {N}, { fill = 0.0 })ooc.sim_add_zero_field_operator(ctx, accumulator)-- ... operators that accumulate into the field ...
-- Reset state before stimulus injectionooc.sim_add_zero_field_operator(ctx, state)ooc.sim_add_stimulus_operator(ctx, state, { type = "stimulus_sine", amplitude = 1.0, wavenumber = 0.5, omega = 0.1})
-- Clear a buffer in a ping-pong schemeooc.sim_add_zero_field_operator(ctx, buffer_b)ooc.sim_add_copy_operator(ctx, buffer_a, buffer_b, { accumulate = true })