Advection Operators
Analytic Warp 🌀
Section titled “Analytic Warp 🌀”add_analytic_warp_operator(ctx, field, opts)
Apply nonlinear analytic deformations to field values using special function profiles. Useful for implementing nonlinear response curves, soft saturation, and phase-space warping.
Method Signature
Section titled “Method Signature”add_analytic_warp_operator(ctx, field, [options]) -> operatorReturns: Operator handle (userdata)
Mathematical Formulation
Section titled “Mathematical Formulation”For each sample, the operator computes a profile-gradient response and applies an explicit Euler update:
where depends on profile:
- digamma: (trigamma)
- trigamma: (tetragamma)
- power:
- tanh:
- hyperexp: with
- qhyperexp: with
In continuity_mode = "clamped" or "limited", near singularities the operator may probe nearby samples to build a guarded response.
Parameters
Section titled “Parameters”Core Parameters:
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
profile | enum | "digamma" | see above | Analytic profile function |
delta | double | 1e-6 | >0 (floored) | Symmetric offset scale in response factor |
lambda | double | 0.0 | unbounded | Scaling applied to warp response |
bias | double | 0.0 | unbounded | Additive bias before profile evaluation |
Power Profile:
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
exponent | double | 2.0 | ≥0 | Power exponent for profile = "power" |
Hyperexp/Qhyperexp:
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
hyperexp_epsilon | double | context epsilon (fallback 1.0) | >0 | Pole shift control parameter |
hyperexp_depth | integer | context truncation level (fallback 8) | [1, 8192] | Truncation depth for sum |
hyperexp_q | double | 0.9 | (0, 1) | q-deformation parameter |
Complex Field Handling:
| Parameter | Type | Default | Description |
|---|---|---|---|
complex_mode | enum | "component" | component: process re/im independently; polar: preserve phase direction |
Continuity Guards:
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
continuity_mode | enum | "none" | none, strict, clamped, limited | Singularity handling policy |
continuity_clamp_min | double | -1e6 | unbounded | Lower bound for clamped mode |
continuity_clamp_max | double | 1e6 | unbounded | Upper bound for clamped mode |
continuity_tolerance | double | 1e-6 | >0 (floored) | Probe radius for guarded continuity modes |
Boundary & Initial Conditions
Section titled “Boundary & Initial Conditions”- Operates pointwise; no spatial boundary handling required
- Field values should be in a domain where the profile function is well-defined
- For digamma/trigamma, avoid non-positive integers (poles of gamma function)
Stability & Convergence
Section titled “Stability & Convergence”- Stability depends on the profile and
lambdaparameter - Large
lambdavalues can cause rapid field evolution; reduce timestep accordingly - Lua-side default
lambda = 0.0means no evolution unless you setlambdaexplicitly - The
continuity_modeoptions help guard against singularities:strict: Preserve direct analytic evaluation (no continuity fallback blend)clamped: Clamp gradient responses to[continuity_clamp_min, continuity_clamp_max]limited: Use guarded nearby probes and clamp within bounds
Performance Notes
Section titled “Performance Notes”- Pointwise operation; scales linearly with field size
qhyperexpevaluation scales with truncation depthhyperexp_depthhyperexpuses digamma/trigamma differences and is typically less sensitive tohyperexp_depth- Complex fields in
polarmode require additional magnitude/phase conversions
Examples
Section titled “Examples”-- Power-law nonlinearity with exponent 1.5ooc.add_analytic_warp_operator(ctx, field, { profile = "power", exponent = 1.5, lambda = 0.4})
-- Soft saturation using tanhooc.add_analytic_warp_operator(ctx, field, { profile = "tanh", lambda = 2.0, bias = 0.0})
-- Digamma warp with continuity protectionooc.add_analytic_warp_operator(ctx, field, { profile = "digamma", lambda = 0.1, continuity_mode = "clamped", continuity_clamp_min = -10.0, continuity_clamp_max = 10.0})
-- Hyperexponential with q-deformation (complex field, polar mode)ooc.add_analytic_warp_operator(ctx, complex_field, { profile = "qhyperexp", hyperexp_depth = 16, hyperexp_epsilon = 0.25, hyperexp_q = 0.85, complex_mode = "polar"})
-- Trigamma profile for second-derivative responseooc.add_analytic_warp_operator(ctx, field, { profile = "trigamma", delta = 1e-4, lambda = 0.05})Spatial Derivative ∇
Section titled “Spatial Derivative ∇”add_spatial_derivative_operator(ctx, src, dst, opts)
Compute first-order spatial derivatives using finite difference stencils. Fundamental building block for advection, gradient computation, and PDE discretization.
Method Signature
Section titled “Method Signature”add_spatial_derivative_operator(ctx, input, output, [options]) -> operatorReturns: Operator handle (userdata)
Mathematical Formulation
Section titled “Mathematical Formulation”The operator computes (or when axis = 1) using finite differences:
Central difference (default):
Forward difference:
Backward difference:
When skew_forward = true and method = "central", the runtime uses the forward stencil.
Parameters
Section titled “Parameters”| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
method | enum | "central" | central, forward, backward | Finite difference stencil |
axis | integer | 0 | [0, 1] | Derivative axis (0 = x, 1 = y) |
skew_forward | boolean | false | — | Bias central scheme toward upwind |
spacing | double | 1.0 | [1e-9, 10.0] | Grid spacing (alias: dx) |
boundary | enum | "periodic" | see below | Boundary handling policy |
accumulate | boolean | false | — | Add to output instead of overwriting |
Boundary options: periodic, neumann, dirichlet, reflective
Note: Lua accepts derivative as an alias for method.
Boundary & Initial Conditions
Section titled “Boundary & Initial Conditions”- Periodic: Wraps indices modulo field length
- Neumann: Zero normal derivative; ghost cells mirror interior values
- Dirichlet: Zero values at boundaries
- Reflective: Mirror-reflects values across boundary
Stability & Convergence
Section titled “Stability & Convergence”- Pure derivative operators are unconditionally stable
- Truncation error:
- Central:
- Forward/Backward:
- For advection problems, use upwind schemes (
forwardfor positive velocity,backwardfor negative) to ensure stability - Central schemes can introduce dispersion errors in advection;
skew_forwardprovides a compromise
Performance Notes
Section titled “Performance Notes”- Nonlocal operation requiring neighbor access
- Does not use dt scaling by default (pure spatial operator)
- For 2D gradients requiring both and , consider
add_gradient_operatorinstead
Runtime Configuration
Section titled “Runtime Configuration”Read current configuration:
local cfg = ooc.spatial_derivative_config(ctx, op_index)-- Returns: { input_field, output_field, spacing, method, method_index, axis, skew_forward, boundary, accumulate }Update configuration:
ooc.spatial_derivative_update(ctx, op_index, { axis = 1, method = "backward", spacing = 0.05, boundary = "neumann"})Examples
Section titled “Examples”-- Basic central differenceooc.add_spatial_derivative_operator(ctx, u, du_dx, { method = "central", spacing = 0.1})
-- Forward difference for upwind advection (positive velocity)ooc.add_spatial_derivative_operator(ctx, u, du_dx, { method = "forward", spacing = 0.05, boundary = "periodic"})
-- Y-derivative with Dirichlet boundariesooc.add_spatial_derivative_operator(ctx, u, du_dy, { method = "central", axis = 1, spacing = 0.1, boundary = "dirichlet"})
-- Accumulate derivative into existing fieldooc.add_spatial_derivative_operator(ctx, u, rhs, { method = "backward", spacing = dx, accumulate = true})
-- Query and modify at runtimelocal cfg = ooc.spatial_derivative_config(ctx, op_index)if cfg then ooc.log("∂/∂x: axis=%d method=%s dx=%.3g", cfg.axis, cfg.method, cfg.spacing)end
ooc.spatial_derivative_update(ctx, op_index, { method = "backward", skew_forward = false, boundary = "neumann"})Gradient ∇
Section titled “Gradient ∇”add_gradient_operator(ctx, input, output_x, output_y, opts)
Compute 2D gradient components using finite difference stencils. Outputs the X and Y partial derivatives to separate fields.
Method Signature
Section titled “Method Signature”add_gradient_operator(ctx, input, output_x, output_y, [options]) -> operatorReturns: Operator handle (userdata)
Mathematical Formulation
Section titled “Mathematical Formulation”For a scalar field , the gradient is:
The discrete approximation depends on the selected stencil:
- central2 (2nd-order central):
- central4 (4th-order central):
- forward1 (1st-order forward):
- backward1 (1st-order backward):
- forward2 (2nd-order forward):
- backward2 (2nd-order backward):
Parameters
Section titled “Parameters”| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
spacing_x | double | 1.0 | [1e-9, ∞) | Grid spacing in X direction |
spacing_y | double | spacing_x | [1e-9, ∞) | Grid spacing in Y direction (defaults to spacing_x if unset) |
axis_x | integer | -1 (auto) | [-1, 7] | Axis index for the X derivative (-1 selects automatically) |
axis_y | integer | -1 (auto) | [-1, 7] | Axis index for the Y derivative (-1 selects automatically; must differ from axis_x) |
stencil | enum | "central2" | see below | Finite difference stencil type |
boundary | enum | "periodic" | see below | Boundary condition handling |
accumulate | boolean | false | — | Add to output instead of overwriting |
scale_by_dt | boolean | true | — | Scale accumulated outputs by dt (accumulate = true only) |
Stencil options: forward1, backward1, forward2, backward2, central2, central4
Boundary options: periodic, neumann, dirichlet, reflective
Boundary & Initial Conditions
Section titled “Boundary & Initial Conditions”- Periodic: Wraps around domain edges using modular indexing
- Neumann: Zero-gradient at boundaries (ghost cells mirror interior)
- Dirichlet: Zero values at boundaries
- Reflective: Mirror-reflects values at boundaries
Stability & Convergence
Section titled “Stability & Convergence”- Central difference schemes are unconditionally stable for pure gradient computation
- Higher-order stencils (
central4) reduce truncation error from to - Forward/backward stencils introduce directional bias; use for upwind schemes in advection problems
- A single
stencilsetting is used for both gradient components
Performance Notes
Section titled “Performance Notes”- Outputs to two separate fields; ensure both are allocated before calling
- Complex fields are processed component-wise (real and imaginary gradients computed independently)
- Stencil width affects memory access patterns;
central4requires wider halos
Examples
Section titled “Examples”-- Basic 2D gradient with default central differenceslocal ux = ooc.add_field(ctx, {256, 256}, { fill = 0.0 })local uy = ooc.add_field(ctx, {256, 256}, { fill = 0.0 })ooc.add_gradient_operator(ctx, u, ux, uy, { spacing_x = 0.1, spacing_y = 0.1})
-- High-order gradient with Neumann boundariesooc.add_gradient_operator(ctx, u, ux, uy, { stencil = "central4", spacing_x = 0.05, boundary = "neumann"})
-- Upwind-style gradient for advection (single stencil applies to both axes)ooc.add_gradient_operator(ctx, u, ux, uy, { stencil = "forward2", boundary = "periodic"})Divergence ∇·
Section titled “Divergence ∇·”add_divergence_operator(ctx, vx, vy, out, opts)
Compute the scalar divergence of a 2D vector field using matched finite-difference stencils on the X and Y components.
Method Signature
Section titled “Method Signature”add_divergence_operator(ctx, input_x, input_y, output, [options]) -> operatorReturns: Operator handle (userdata)
Mathematical Formulation
Section titled “Mathematical Formulation”For a vector field :
The selected stencil is applied independently to each partial derivative before summation:
- central2:
- central4:
- forward1/backward1: first-order one-sided derivatives
- forward2/backward2: second-order one-sided derivatives
Parameters
Section titled “Parameters”| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
spacing_x | double | 1.0 | [1e-9, ∞) | Grid spacing for |
spacing_y | double | spacing_x | [1e-9, ∞) | Grid spacing for |
axis_x | integer | -1 (auto) | [-1, 7] | Axis index used for the X-derivative |
axis_y | integer | -1 (auto) | [-1, 7] | Axis index used for the Y-derivative |
stencil | enum | "central2" | see below | Finite-difference stencil for both partials |
boundary | enum | "periodic" | see below | Boundary sampling policy |
accumulate | boolean | false | — | Add into the output instead of overwriting |
scale_by_dt | boolean | true | — | Scale accumulated writes by dt (accumulate = true only) |
Stencil options: forward1, backward1, forward2, backward2, central2, central4
Boundary options: periodic, neumann, dirichlet, reflective
Boundary & Initial Conditions
Section titled “Boundary & Initial Conditions”- Uses the selected boundary policy when sampling neighbors
axis_xandaxis_ymust resolve to different axes- Complex fields are differentiated component-wise before summing
Stability & Convergence
Section titled “Stability & Convergence”- Pure divergence evaluation is unconditionally stable
central4improves truncation error overcentral2for smooth fields- One-sided stencils introduce directional bias and are best reserved for upwind-style workflows
Performance Notes
Section titled “Performance Notes”- Reads two input fields and writes one output field
- Wider stencils require broader halos and more neighbor fetches
accumulate = trueis useful when divergence is one term within a larger RHS assembly
Examples
Section titled “Examples”-- Incompressibility diagnosticooc.add_divergence_operator(ctx, vx, vy, div, { stencil = "central4", spacing_x = 0.5, spacing_y = 0.5})
-- Nonuniform grid spacing with Neumann boundariesooc.add_divergence_operator(ctx, flux_x, flux_y, rhs, { spacing_x = 0.1, spacing_y = 0.25, boundary = "neumann"})
-- Accumulate divergence contribution into an existing RHS fieldooc.add_divergence_operator(ctx, vx, vy, rhs, { accumulate = true, scale_by_dt = true})Curl ∇×
Section titled “Curl ∇×”add_curl_operator(ctx, vx, vy, out, opts)
Compute the scalar 2D curl (vorticity) of a vector field using the same stencil family as the gradient and divergence operators.
Method Signature
Section titled “Method Signature”add_curl_operator(ctx, input_x, input_y, output, [options]) -> operatorReturns: Operator handle (userdata)
Mathematical Formulation
Section titled “Mathematical Formulation”For a planar vector field , the scalar curl is:
Each partial derivative uses the selected stencil and its corresponding spacing:
spacing_xscalesspacing_yscales
Parameters
Section titled “Parameters”| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
spacing_x | double | 1.0 | [1e-9, ∞) | Grid spacing for |
spacing_y | double | spacing_x | [1e-9, ∞) | Grid spacing for |
axis_x | integer | -1 (auto) | [-1, 7] | Axis used for the X-derivative |
axis_y | integer | -1 (auto) | [-1, 7] | Axis used for the Y-derivative |
stencil | enum | "central2" | see below | Finite-difference stencil for both partials |
boundary | enum | "periodic" | see below | Boundary sampling policy |
accumulate | boolean | false | — | Add into the output instead of overwriting |
scale_by_dt | boolean | true | — | Scale accumulated writes by dt (accumulate = true only) |
Stencil options: forward1, backward1, forward2, backward2, central2, central4
Boundary options: periodic, neumann, dirichlet, reflective
Boundary & Initial Conditions
Section titled “Boundary & Initial Conditions”- Uses the selected boundary mode when sampling off-edge neighbors
axis_xandaxis_ymust resolve to different axes- Complex fields yield component-wise curl outputs
Stability & Convergence
Section titled “Stability & Convergence”- Curl evaluation itself is unconditionally stable
- Centered stencils minimize bias for vorticity diagnostics
- One-sided stencils are useful when matching a broader directional discretization scheme
Performance Notes
Section titled “Performance Notes”- Reads two component fields and writes one scalar output field
- Shares the same stencil cost profile as
add_divergence_operator - Useful for vorticity visualization, circulation estimates, and rotational forcing terms
Examples
Section titled “Examples”-- Basic vorticity fieldooc.add_curl_operator(ctx, vx, vy, omega, { stencil = "central4", spacing_x = 0.5, spacing_y = 0.5})
-- Periodic curl on a square latticeooc.add_curl_operator(ctx, flow_x, flow_y, vort, { boundary = "periodic", spacing_x = 0.1})
-- Add rotational term into an existing bufferooc.add_curl_operator(ctx, vx, vy, rhs, { accumulate = true, scale_by_dt = true})