Skip to content

Operators

Every operator is a discrete-time state-space operator, y[t] = g(s[t], u[t], ε[t]) and s[t+1] = f(s[t], u[t], ε[t]), working on arrays with one value per lane. The equations below are in physical units; each operator discretizes them exactly for the step it runs at. See Operators for the ideas behind them.

In parameter units, [in] is the unit of the operator's main input, [out] the unit of its output, s is seconds and 1 means dimensionless. Changeable parameters can be targeted by events (they are then promoted to signals); per lane parameters may differ between the lanes of a batch.

In a scenario, use an operator under custom, with its parameters as keys:

custom:
  - {id: feed_total, op: sum, weights: [1, 1], inputs: {in0: FIC-101.cv, in1: FIC-102.cv}}

Sources

Operators without inputs: constants, schedules driven by events, stochastic processes and the clock.

constant

Constant source.

y[t] = value

Inputs: none · Outputs: out · Direct feedthrough: none · Random numbers per step: 0

Parameter Default Unit Range Description Changeable Per lane
value 0.0 [out] output value yes yes

clock

The current time, in seconds from the start of the run.

y[t] = t        (0 while the plant settles; negative during a burn-in)

Inputs: none · Outputs: out · Direct feedthrough: none · Random numbers per step: 0

schedule

Piecewise profile driven by events.

y[t] = v1                                           if t >= t1
y[t] = v0 + (v1 − v0)·(t − t0)/(t1 − t0)            if t0 <= t < t1

An event at time te restarts the profile from the current value: t0 = te, v0 = y[te], v1 = the event's target, t1 = te + ramp duration (t1 = t0 for a step). A ramp that starts from an unset (NaN) value becomes a step.

Inputs: none · Outputs: out · Direct feedthrough: none · Random numbers per step: 0

Parameter Default Unit Range Description Changeable Per lane
value 0.0 [out] value before any event (NaN = unset) yes

ou

Ornstein–Uhlenbeck source, parametrized by its stationary standard deviation.

a = exp(−dt/τ)
x[t+1] = μ + (x[t] − μ)·a + σ·√(1 − a²)·ε[t]
y[t] = x[t]

The stationary distribution is N(μ, σ²) whatever the step size.

Inputs: none · Outputs: out · Direct feedthrough: none · Random numbers per step: 1

Parameter Default Unit Range Description Changeable Per lane
mean 0.0 [out] long-run mean μ yes yes
std required [out] ≥ 0 stationary standard deviation σ yes yes
tau required s ≥ 0 correlation time τ yes yes

ar

Autoregressive source of order p, parametrized by its stationary standard deviation.

x[t+1] = μ + Σᵢ φᵢ·(x[t+1−i] − μ) + σₑ·ε[t],   y[t] = x[t]

The coefficients φ are per base step. σₑ is chosen so that the stationary standard deviation of x equals std.

Inputs: none · Outputs: out · Direct feedthrough: none · Random numbers per step: 1

Parameter Default Unit Range Description Changeable Per lane
coef required 1 coefficients φ₁…φₚ, per base step
mean 0.0 [out] mean μ yes yes
std required [out] ≥ 0 stationary standard deviation yes yes

Dynamic operators

Operators whose output depends on their inputs, and for most of them on a state.

sum

Weighted sum of n inputs.

y[t] = bias + Σᵢ wᵢ·inᵢ[t]

The inputs are named in0 … in(n−1), one per weight.

Inputs: in0, in1, … (numbered) · Outputs: out · Direct feedthrough: all · Random numbers per step: 0

Parameter Default Unit Range Description Changeable Per lane
weights [1.0, 1.0] [out]/[in] weight of each input
bias 0.0 [out] constant offset yes yes

product

Product of n inputs.

y[t] = gain · Πᵢ inᵢ[t]

The inputs are named in0 … in(n−1).

Inputs: in0, in1, … (numbered) · Outputs: out · Direct feedthrough: all · Random numbers per step: 0

Parameter Default Unit Range Description Changeable Per lane
n 2 1 ≥ 1 number of inputs
gain 1.0 [out]/Π[in] constant factor yes yes

weighted_mean

Weighted mean of n inputs, with the weights given by n more inputs.

y[t] = Σᵢ wᵢ[t]·xᵢ[t] / Σᵢ wᵢ[t]      over the inputs with wᵢ[t] > 0, if there are any
y[t] = y[t−1]                          otherwise (with no weight at all, the mean holds)

The inputs are x0 … x(n−1) and w0 … w(n−1). An input without positive weight takes no part, so it may be undefined (NaN).

Inputs: x0, x1, w0, w1, … (numbered) · Outputs: out · Direct feedthrough: all · Random numbers per step: 0

Parameter Default Unit Range Description Changeable Per lane
n 2 1 ≥ 1 number of weighted inputs

log_linear

A law that is linear in the logarithm: power laws, exponentials and Arrhenius terms.

ln y[t] = bias + Σᵢ wᵢ·fᵢ(inᵢ[t]),   fᵢ(u) = u ("lin"), ln u ("log") or 1/u ("inv")

For example y = A·exp(−E/(R·T))·r^b has bias = ln A, T with "inv" and weight −E/R, and r with "log" and weight b. An input outside the domain of its transform (u ≤ 0 for log and inv) gives NaN.

Inputs: in0, … (numbered) · Outputs: out · Direct feedthrough: all · Random numbers per step: 0

Parameter Default Unit Range Description Changeable Per lane
weights required 1 weight of each transformed input
transforms required 1 lin, log or inv for each input
bias 0.0 ln[out] constant term of ln y yes yes

first_order

First-order lag with gain, exact for a zero-order-hold input.

a = exp(−dt/τ)
y[t+1] = a·y[t] + K·(1 − a)·u[t]        (a NaN input holds the state)

Inputs: u · Outputs: out · Direct feedthrough: none · Random numbers per step: 0

Parameter Default Unit Range Description Changeable Per lane
K 1.0 [out]/[in] static gain yes yes
tau required s ≥ 0 time constant yes yes
initial 0.0 [out] initial output (before settling) yes

fopdt

First-order plus dead time, exact for a zero-order-hold input, including dead times that are not a whole number of steps.

θ = m·dt + θ′ with 0 ≤ θ′ < dt, a = exp(−dt/τ), c = exp(−(dt − θ′)/τ)

y[t+1] = a·y[t] + K·(1 − c)·u[t−m] + K·(c − a)·u[t−m−1]        (a NaN input holds the state)

Inputs: u · Outputs: out · Direct feedthrough: none · Random numbers per step: 0

Parameter Default Unit Range Description Changeable Per lane
K 1.0 [out]/[in] static gain yes yes
tau required s ≥ 0 time constant yes yes
theta 0.0 s ≥ 0 dead time yes
initial 0.0 [out] initial output (before settling) yes

integrator

Integrator with optional limits, exact for a zero-order-hold input.

x[t+1] = min(max(x[t] + k·dt·u[t], lo), hi),   y[t] = x[t]        (a NaN input holds the state)

Inputs: u · Outputs: out · Direct feedthrough: none · Random numbers per step: 0

Parameter Default Unit Range Description Changeable Per lane
k 1.0 [out]/([in]·s) integration gain yes yes
lo -inf [out] lower limit yes
hi inf [out] upper limit yes
initial 0.0 [out] initial output (before settling) yes

variable_delay

Transport delay whose transit time is set by a rate signal (plug flow).

Q(t) = ∫₀ᵗ rate(s) ds, the cumulative throughput (rate held constant over each step). The value leaving at t entered at the time t* for which Q(t) − Q(t*) = capacity:

y[t] = u(t*), interpolated linearly between stored input samples.

With a constant rate r the transit time is capacity / r; with the default rate of 1, capacity is simply the delay in seconds. A zero rate holds the output: the content stays in place, and nothing new enters (input samples with no throughput share one buffer slot). Transit times shorter than one step are clamped to one step (counted in warnings).

Inputs: u, rate (optional: rate = 1.0) · Outputs: out · Direct feedthrough: none · Random numbers per step: 0

Parameter Default Unit Range Description Changeable Per lane
capacity required [rate]·s ≥ 0 throughput needed to cross the segment (seconds at rate 1)
max_delay NaN s longest transit time to support; NaN means capacity (rate >= 1)
initial 0.0 [in] content before any input has been stored

saturation

Saturation (hard limits).

y[t] = min(max(u[t], lo), hi)

Inputs: u · Outputs: out · Direct feedthrough: u · Random numbers per step: 0

Parameter Default Unit Range Description Changeable Per lane
lo -inf [in] lower limit yes yes
hi inf [in] upper limit yes yes

stiction

Stick-slip hysteresis (the two-parameter model of He et al., 2007), in input units.

r[t] = r[t−1] + u[t] − u[t−1]                (accumulated input change since the last move)
if |r[t]| > fs:  y[t] = u[t] − sign(r[t])·fd,  then r ← sign(r[t])·fd   (slip)
else:            y[t] = y[t−1]                                          (stick)

fs is the static band and fd ≤ fs the dynamic band. fs = fd = 0 passes the input through; fs = fd = d gives a pure dead band of width 2d; a very large fs holds the output.

Inputs: u · Outputs: out · Direct feedthrough: u · Random numbers per step: 0

Parameter Default Unit Range Description Changeable Per lane
fs 0.0 [in] ≥ 0 static band yes yes
fd 0.0 [in] ≥ 0 dynamic band (≤ fs) yes yes

Feedback operators

Controllers. They read measured values and always write their output.

pid

PID block with output limits, back-calculation anti-windup, a filtered derivative on the measurement, and MAN/AUTO/CAS modes. The block always writes its output; mode, manual output and remote setpoint are inputs.

r[t] = rsp[t] in CAS (when finite), otherwise sp[t]
e[t] = σ·(r[t] − pv[t]),   σ = +1 (reverse acting) or −1 (direct acting)
D[t] = β·D[t−1] − σ·Kc·Td/(Tf + dt)·(pv[t] − pv[t−1]),   Tf = α·Td,   β = Tf/(Tf + dt)
v[t] = bias + Kc·e[t] + I[t] + D[t],   y[t] = min(max(v[t], lo), hi)
I[t+1] = I[t] + Kc·dt/Ti·e[t] + (dt/Tt)·(y[t] − v[t])            (AUTO and CAS)
MAN: y[t] = min(max(man_out[t], lo), hi), or y[t−1] when man_out is NaN (hold);
     I[t+1] = y[t] − bias − Kc·e[t] − D[t], so switching back is bumpless.

A NaN measurement holds the last output and freezes the integral. Ti ≤ 0 or Ti = inf disables integral action; Tt = 0 selects Ti (or √(Ti·Td) with Td > 0).

Inputs: pv, sp, rsp, mode, man_out (optional: rsp = NaN, mode = 1.0, man_out = NaN) · Outputs: out · Direct feedthrough: pv, sp, rsp, mode, man_out · Random numbers per step: 0

Parameter Default Unit Range Description Changeable Per lane
Kc 1.0 [out]/[pv] ≥ 0 controller gain (positive; use direct for the action) yes yes
Ti inf s integral time (≤ 0 or inf: no integral action) yes yes
Td 0.0 s ≥ 0 derivative time yes yes
alpha 0.1 1 ≥ 1e-06 derivative filter factor, Tf = alpha·Td yes yes
Tt 0.0 s ≥ 0 anti-windup tracking time (0 = automatic) yes yes
lo 0.0 [out] lower output limit yes yes
hi 100.0 [out] upper output limit yes yes
bias 0.0 [out] output offset yes yes
direct False 1 direct acting (output rises when pv rises)

Observation operators

Stages of an observation chain; the final stage is what feedback operators read.

lag

First-order lag with unit gain, exact for a zero-order-hold input.

a = exp(−dt/τ)
y[t+1] = a·y[t] + (1 − a)·u[t]        (a NaN input holds the state)

Inputs: u · Outputs: out · Direct feedthrough: none · Random numbers per step: 0

Parameter Default Unit Range Description Changeable Per lane
tau required s ≥ 0 time constant yes yes

bias

Additive offset.

y[t] = u[t] + offset

Inputs: u · Outputs: out · Direct feedthrough: u · Random numbers per step: 0

Parameter Default Unit Range Description Changeable Per lane
offset 0.0 [in] additive offset yes yes

white_noise

Additive Gaussian white noise.

y[t] = u[t] + std·ε[t]

Inputs: u · Outputs: out · Direct feedthrough: u · Random numbers per step: 1

Parameter Default Unit Range Description Changeable Per lane
std required [in] ≥ 0 noise standard deviation yes yes

clip

Measurement range limits.

y[t] = min(max(u[t], lo), hi)

Inputs: u · Outputs: out · Direct feedthrough: u · Random numbers per step: 0

Parameter Default Unit Range Description Changeable Per lane
lo -inf [in] bottom of the range yes yes
hi inf [in] top of the range yes yes

quantize

Quantization to a fixed resolution.

y[t] = step·round(u[t] / step)      (step = 0 passes the input through)

While the engine settles to a steady state, the input passes through unquantized, so a noise-free loop does not hunt around a quantization step.

Inputs: u · Outputs: out · Direct feedthrough: u · Random numbers per step: 0

Parameter Default Unit Range Description Changeable Per lane
step required [in] ≥ 0 resolution yes yes

delay

Fixed dead time of an observation stage, for example between taking a sample and reporting its value.

y[t] = u(t − delay), interpolated linearly between stored input samples

Inputs: u · Outputs: out · Direct feedthrough: none · Random numbers per step: 0

Parameter Default Unit Range Description Changeable Per lane
delay required s ≥ 0 dead time

gate

Passes the input while open and gives NaN while closed (an empty slot).

y[t] = u[t]   if open[t] ≥ 0.5
y[t] = NaN    otherwise

Inputs: u, open (optional: open = 1.0) · Outputs: out · Direct feedthrough: u, open · Random numbers per step: 0

sample_hold

Sample-and-hold at a fixed period.

y[t] = u[t]      if (t − phase) is a whole multiple of the period
y[t] = y[t−1]    otherwise

The period and phase must be whole multiples of the base step.

Inputs: u · Outputs: out · Direct feedthrough: u · Random numbers per step: 0

Parameter Default Unit Range Description Changeable Per lane
period required s ≥ 0 sampling period
phase 0.0 s ≥ 0 time of the first sample