Utility Operators
Coordinate 📐
Section titled “Coordinate 📐”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”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.add_coordinate_operator(ctx, field, { mode = "index", normalize = "unit"})
-- Signed index ramp [-1, 1]ooc.add_coordinate_operator(ctx, field, { mode = "index", normalize = "signed", gain = 2.0, bias = 0.5})
-- X-axis coordinate with custom spacingooc.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.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.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.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.add_coordinate_operator(ctx, field, { mode = "coord", coord_mode = "separable", coord_combine = "multiply", normalize = "signed"})Phase Rotate 🔄
Section titled “Phase Rotate 🔄”add_phase_rotate_operator(ctx, field, opts)
Apply a uniform phase rotation to all field samples. Complex fields use the full complex rotation, while real fields use the projected cosine factor. This makes the operator useful for frequency shifting, demodulation, and rotating reference frames.
Method Signature
Section titled “Method Signature”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.
For real-valued fields or real-constrained spectra, the operator applies the projected real multiplier
instead of the full complex exponential.
Cartesian implementation:
Parameters
Section titled “Parameters”| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
phase_rate | double | 0.0 | unbounded | Angular rotation rate in rad/s (required) |
Boundary & Initial Conditions
Section titled “Boundary & Initial Conditions”- Operates elementwise; no boundary handling required
- Complex fields rotate in the complex plane; real fields receive the projected cosine factor
- Initial phase determines starting point; rotation is relative
Stability & Convergence
Section titled “Stability & Convergence”- Complex fields: Rotation is unitary and magnitude-preserving
- Real fields: The projected cosine factor can attenuate or sign-flip samples, so the operation is no longer norm-preserving
- 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)
- Complex fields use the full 2x2 rotation; real fields use only the cosine projection
- 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.add_phase_rotate_operator(ctx, carrier, { phase_rate = 2 * math.pi})
-- Negative rotation (clockwise in complex plane)ooc.add_phase_rotate_operator(ctx, signal, { phase_rate = -1.0})
-- Demodulation: shift carrier frequency to basebandlocal carrier_freq = 440.0 -- Hzooc.add_phase_rotate_operator(ctx, modulated_signal, { phase_rate = -2 * math.pi * carrier_freq})
-- Slow phase drift for visualizationooc.add_phase_rotate_operator(ctx, wave, { phase_rate = 0.1})
-- Rotating reference frame for oscillator analysislocal omega_0 = 100.0 -- natural frequencyooc.add_phase_rotate_operator(ctx, oscillator_state, { phase_rate = -omega_0 -- move to co-rotating frame})Copy 📋
Section titled “Copy 📋”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”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.add_copy_operator(ctx, source, destination)
-- Accumulate input into running sum (scaled by dt)ooc.add_copy_operator(ctx, flux, integral, { accumulate = true, scale_by_dt = true})
-- Accumulate without dt scaling (raw summation)ooc.add_copy_operator(ctx, sample, buffer, { accumulate = true, scale_by_dt = false})
-- Double-buffering patternlocal u_prev = ooc.add_field(ctx, {N}, { fill = 0.0 })ooc.add_copy_operator(ctx, u, u_prev) -- snapshot before update-- ... operators that modify u ...Scale ⚖️
Section titled “Scale ⚖️”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”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 (preferadd_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.add_scale_operator(ctx, signal, attenuated, { scale = 0.5})
-- Invert field signooc.add_scale_operator(ctx, u, u_neg, { scale = -1.0})
-- In-place scalingooc.add_scale_operator(ctx, field, field, { scale = 0.99 -- gentle decay})
-- Accumulate scaled values (e.g., for weighted averaging)ooc.add_scale_operator(ctx, sample, weighted_sum, { scale = weight, accumulate = true})
-- Diffusion coefficient applicationlocal D = 0.01ooc.add_laplacian_operator(ctx, u, lap_u)ooc.add_scale_operator(ctx, lap_u, du_dt, { scale = D })Zero Field 🗑️
Section titled “Zero Field 🗑️”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”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.add_field(ctx, {N}, { fill = 0.0 })ooc.add_zero_field_operator(ctx, accumulator)-- ... operators that accumulate into the field ...
-- Reset state before stimulus injectionooc.add_zero_field_operator(ctx, state)ooc.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.add_zero_field_operator(ctx, buffer_b)ooc.add_copy_operator(ctx, buffer_a, buffer_b, { accumulate = true })