# The formula language

The Wavelace page at https://www.wavelace.com/documentation/, as Markdown.

Everything the formula box takes, and everything it refuses. Wavelace compiles what you type once and hands it to whichever renderer is on show, so this page is the whole language in one place.

## The shape of a formula

A formula is compiled once against the whole variable set, and each renderer feeds it what it has. That is why one formula draws in any renderer that takes one: a wave formula written in `x` reads the angle as `x` in polar, and a surface formula in `x` and `y` becomes a true sheet in wave, because each ribbon slice is fed its own depth. Switching between them keeps what you typed.

Two of the twelve read a description rather than a formula, bodies and bellman, and have a field of their own; [what they read](https://www.wavelace.com/documentation/#specs) is further down. A formula is not carried through them: leaving one, the renderer you arrive in opens on its own.

Nothing is declared. There are no statements, no assignment and no names of your own: a formula is one expression, and its value is the number drawn.

## The eight variables

All eight reach every formula, whatever the renderer does with them, so a name is never an error. But a name does not hold the same thing everywhere. A renderer that has no second parameter of its own puts something else in `v`: a surface puts `y` there, a wave slice its own depth.

Any other single letter (`a`, `k`, `A`, though not `e` or `E`, which are Euler's number) is a free variable: the app gives it a slider of its own, from -10 to 10, worth 1 until it is moved, and a link carries the value under `let`. The Greek letters are letters too: `\omega`, `\alpha`, a pasted `ω`, each becoming its glyph, so `A \sin(\omega t - k x)` has three sliders, and a letter before a name multiplies it, `\omega t` as `a x`. Not `\pi`, `\theta` and `\tau`, which keep their meanings, nor `\Gamma`, the gamma function (`\gamma` is a letter), nor `\Sigma` and `\Pi`, which are the sum and the product here. A subscripted letter is a name of its own, and free: `x_0` is a fixed point and not the axis, so `\sin(k(x - x_0) - \omega(t - t_0))` has four sliders, and the plate reads `x₀`. Letters written together multiply when no more than one of them is free, so `\sin(kx - \omega t)` is `\sin(k x - \omega t)` as a textbook means it. A longer name is refused otherwise, and so is one that reads as notation: a Greek letter typed out (`omega`, `mu`), a differential (`dx`), and letters before a bracket, which are a call: `ta(x)` is a mistyped `tan`, not t times a. The complex renderer has them too, beside the `c` and `i` that are its own: its parser reads a free letter as a value the shader is handed.

- x: the first axis, and what a one-variable formula is usually written in (surface, quantum 2D; wave, quantum — x; polar, curve, shape — the first parameter)
- y: the second (surface, quantum 2D — y; wave, quantum — the slice's own depth; polar, curve, shape — the second parameter)
- z: the third (surface, quantum 2D; polar, curve, shape — zero; wave, quantum — the slice's own depth)
- r: a distance (surface, quantum 2D — hypot(x, y); wave, quantum — abs(x); polar, curve, shape — the first parameter)
- th: an angle; a pasted θ becomes this (surface, quantum 2D — atan2(y, x); wave, quantum — x; polar, curve, shape — the first parameter)
- u: a parameter a curve or a sheet runs over (surface, quantum 2D — hypot(x, y); wave, quantum — x; polar, curve, shape — the first parameter)
- v: a second parameter (surface, quantum 2D — y; wave, quantum — the slice's own depth; polar, curve, shape — the second parameter)
- t: the clock, in seconds at Speed 1

- Feeds x and t: `sin(x - t) / (1 + 0.15*x^2) * 3` [Open Travelling Ripple](https://www.wavelace.com/app#p=1)
- Feeds the angle as th: `sin(6*th + t) + 0.4*sin(17*th - 2*t)` [Open Polar Mandala](https://www.wavelace.com/app#p=22)
- Feeds x, y, and r and θ with them: `sin(x + y + t) + cos(x - y + t)` [Open Cross Ripple](https://www.wavelace.com/app#p=29)
- A letter of its own, on a slider: the picture changes kind as it is dragged: `\mu x - z - x(x^2 + z^2),  -0.2y,  x + \mu z - z(x^2 + z^2)` [Open Hopf Bifurcation](https://www.wavelace.com/app#p=147)
- Greek and a subscript, each a slider: `\frac{1}{\sqrt{(\omega_0^2 - x^2)^2 + (\gamma x)^2}}` [Open Resonance Curve](https://www.wavelace.com/app#p=130)

## Operators

The arithmetic is what you would type: `+ - * /` with `^` for a power. A product may be silent, as in maths: `2x`, `3(x + 1)`, `x(y + 1)` and `sin x cos y` all multiply. A leading minus binds loosely, so `-x^2` is the negative of `x²`, as it reads on paper.

Comparisons and `&&`, `||` and the ternary `a ? b : c` are there, and a comparison is worth 0 or 1, which is how a wall or a mask is written as a formula. A single `&` or `|` is refused by name rather than quietly doing arithmetic on the bits.

`%` is the remainder and keeps the sign of its left side; `mod(a, b)` is the floored modulo and does not.

- A comparison is 0 or 1, so a wall is a formula: `3*(abs(x) < 0.4)` [Open Tunnelling Barrier](https://www.wavelace.com/app#p=69)
- A ternary, and a hole drawn on purpose: `(x^2/9 - y^2/4)*(1 + 0.25*sin(t)) + (x^2/9 + y^2/4 < 1 ? 0 : 0/0)` [Open Saddle (elliptic)](https://www.wavelace.com/app#p=67)

## Functions and constants

Every name below is callable, and nothing outside this list is: an unknown name is reported rather than read as a product of its letters.

- abs
- acos
- acosh
- asin
- asinh
- atan
- atan2: the angle of (y, x), over the whole turn rather than a half of it
- atanh
- besselJ: besselJ(n, x) for orders 0 and 1; any other order is a hole rather than a guess
- cbrt: the cube root, which unlike a power of a third is defined for a negative x
- ceil
- combinations: combinations(n, k), exact where the factorials it is written from would have overflowed
- cos
- cosh
- cot: 1/tan
- csc: 1/sin
- deg: degrees, as radians: 30° and 30^\circ both become deg(30)
- erf: the error function, to 1.5e−7
- exp
- factorial: exact on the integers to 170!, and continued through gamma between them
- floor
- gamma: the gamma function, carrying its reflection below ½, so gamma(−0.5) is −2√π; a hole at each pole
- hypot: the distance, hypot(x, y) = sqrt(x² + y²), without the overflow a squared sum can reach
- log: the natural logarithm; \ln reaches it too, and \log_{10} reaches log10
- log10
- log2
- max
- min
- mod: the floored modulo, never negative for a positive b, unlike the % operator
- pow: pow(a, b) is a^b, for where a power reads better as a call
- round
- sec: 1/cos
- sign: −1, 0 or 1
- sin
- sinc: sin(x)/x, and 1 at the origin
- sinh
- sqrt
- superformula: Gielis's superformula (2003), the radius of a star, a flower or a polygon at the angle θ: superformula(θ, m, n₁, n₂, n₃, a, b) is (|cos(mθ/4)/a|^n₂ + |sin(mθ/4)/b|^n₃)^(−1/n₁), m lobes a turn, a small n₁ spiky; a and b may be left out, and are then 1
- tan
- tanh

The constants:

- E
- PI
- inf
- pi
- tau

A lowercase `e` is a spelling of `E` wherever it stands on its own, so `2e` is two times e as `2pi` is two times π. Between digits it is still an exponent: `1e3` is a thousand.

## Sums, products, integrals and derivatives

Four functions take an expression as their first argument and a variable to bind it to. The variable is a dummy: it shadows any plot variable of the same name for the length of the call, and may be any name that is not already a function's or a constant's.

- integral(expression, variable, from, to): or paste `\int_a^b … du`
- sum(expression, variable, from, to): or paste `\sum_{k=1}^{n}`
- prod(expression, variable, from, to): or paste `\prod_{k=1}^{n}`
- diff(expression, variable): or paste `\frac{d}{dx}`

Each is worked out afresh at every point drawn. An integral is Simpson's rule on 128 panels; one to `inf` is taken over the first forty units and left as a hole wherever the integrand has not died away by then, so a divergent integral draws nothing rather than a number. A sum or a product runs over the whole numbers between its limits, to a thousand terms, and past that the point is left blank. A derivative is a central difference at a step of `∛ε` scaled by the point, which holds about nine digits and costs two evaluations of its expression.

- An integral worked out at every point: `integral(u^(x - 1)*exp(-u), u, 0, inf)` [Open Gamma Function](https://www.wavelace.com/app#p=106)
- The closed form of the same thing, where the integral leaves a hole: `gamma(x)` [Open Gamma Poles](https://www.wavelace.com/app#p=121)
- A sum whose last term is the clock: `sum(sin((2*k-1)*(x - t))/(2*k-1), k, 1, 1 + floor(mod(t, 12)))` [Open Partial Sums](https://www.wavelace.com/app#p=118)
- A derivative of a formula, not of a table: `diff(sin(x^2 - t), x)` [Open Chain Rule](https://www.wavelace.com/app#p=127)

## What you can paste in

LaTeX pastes straight in. The commands that stand for a name or an operator:

- \sin: `sin`
- \cos: `cos`
- \tan: `tan`
- \arcsin: `asin`
- \arccos: `acos`
- \arctan: `atan`
- \sinh: `sinh`
- \cosh: `cosh`
- \tanh: `tanh`
- \exp: `exp`
- \ln  \log: `log`
- \min: `min`
- \max: `max`
- \sqrt: `sqrt`
- \cdot  \times: `*`
- \div: `/`
- \pi: `pi`
- \theta  \vartheta: `th`
- \tau: `tau`
- \infty: `inf`
- \sec: `sec`
- \csc: `csc`
- \cot: `cot`
- \sum: `sum`
- \prod: `prod`
- \Gamma: `gamma`
- \arcsinh  \arsinh: `asinh`
- \arccosh  \arcosh: `acosh`
- \arctanh  \artanh: `atanh`
- \lfloor: `floor(`
- \rfloor  \rceil: `)`
- \lceil: `ceil(`
- \le  \leq: `<=`
- \ge  \geq: `>=`
- \ne  \neq: `!=`
- the Greek letters: `\alpha` α, `\beta` β, `\gamma` γ, `\delta` δ, `\epsilon` ε, `\varepsilon` ε, `\zeta` ζ, `\eta` η, `\iota` ι, `\kappa` κ, `\varkappa` κ, `\lambda` λ, `\mu` μ, `\nu` ν, `\xi` ξ, `\rho` ρ, `\varrho` ρ, `\sigma` σ, `\varsigma` σ, `\upsilon` υ, `\phi` φ, `\varphi` φ, `\chi` χ, `\psi` ψ, `\omega` ω, `\Delta` Δ, `\Theta` Θ, `\Lambda` Λ, `\Xi` Ξ, `\Phi` Φ, `\Psi` Ψ, `\Omega` Ω: each a letter, a free variable with a slider of its own ([variables](https://www.wavelace.com/documentation/#variables)), pasted or spelled

And the forms that are read rather than looked up:

- x_1: and x_{12}, x_i, \omega_0: a subscript makes a name of its own, a free variable with a dial
- 90^\circ: and a pasted 90°: degrees, deg(90), after a number, a name or a bracket
- \frac{a}{b}: and \dfrac, \tfrac
- \sqrt[n]{a}: the nth root; \sqrt{a} is the square one
- \binom{n}{k}: and \dbinom, \tbinom
- \int_a^b … du: the limits either order, the d-variable after the integrand
- \sum_{k=1}^{n}: and \prod; the term after it, and no more
- \frac{d}{dx}: and \frac{\partial}{\partial x}, which mean the same here
- \begin{cases} … \end{cases}: each row a value and a condition, becoming a ternary
- \left( … \right): any fence, including \left[ … \right], which is a round bracket here, and \left| … \right| and \lvert … \rvert
- \operatorname{arcsinh}: a name spelled as an operator
- \text{…}: prose, dropped
- \hat{x}: and \bar, \vec, \tilde, \overline, \overrightarrow: a name, decorated
- \limits: after \int, skipped
- \,: and \; \! \: \quad \qquad: spacing, dropped
- $…$: and \( \) \[ \] \displaystyle; a leading head the field already shows, z = or V(x) =, goes too

A function written without brackets takes the atom after it, so `\sin 2x` is `sin(2x)`. The single space LaTeX uses to end a command name is not a separator, which is why `\sin 2\pi x` is `sin(2*pi*x)`; a space you type is one, so `\sin 2 \pi x` is `sin(2)*pi*x`, exactly as `sin 2 x` is `sin(2)*x`.

A power written on a function moves onto its value, so `\cos^2 x` is `cos(x)^2`; a `^{-1}` is the inverse function for the six that have one (sin, cos, tan, sinh, cosh, tanh), and refused by name for anything else, since reading it as a reciprocal would be a guess.

Symbols paste in too, and are converted before anything else reads them. What each becomes, and what the plate above the plot prints back:

- x² − θ: `x^(2) - th`  and the plate prints  `x² − θ`
- sin θ·cos 2θ: `sin(th) *cos(2*th)`  and the plate prints  `sin(θ) · cos(2θ)`
- √(x² + 1): `sqrt(x^(2) + 1)`  and the plate prints  `sqrt(x² + 1)`
- √(1 + cos x): `sqrt(1 + cos(x))`  and the plate prints  `sqrt(1 + cos(x))`
- √2x + √2 x: `sqrt(2*x) + sqrt(2)*x`  and the plate prints  `sqrt(2x) + sqrt(2) · x`
- 2π x: `2*pi*x`  and the plate prints  `2 · π · x`
- ∫_{0}^{∞} sin(u) e^{-x u} du: `integral(sin(u)*exp(-x*u), u, 0, inf)`  and the plate prints  `∫₀^∞ sin(u) · exp(−x · u) du`
- Σ_{k=1}^{9} sin(k x)/k: `sum(sin(k*x)/k, k, 1, 9)`  and the plate prints  `Σ_(k=1)⁹ sin(k · x)/k`
- ∏_{k=1}^{4} cos(k x): `prod(cos(k*x), k, 1, 4)`  and the plate prints  `∏_(k=1)⁴ cos(k · x)`
- sin⁻¹(x): `asin(x)`  and the plate prints  `asin(x)`
- sin 30°: `sin(deg(30))`  and the plate prints  `sin(deg(30))`
- x ≤ 1 ? x : 1: `x <= 1 ? x : 1`  and the plate prints  `x <= 1 ? x : 1`
- 2[x + 1]²: `2*(x + 1)^(2)`  and the plate prints  `2(x + 1)²`
- A sin(ω t − k x): `A*sin(ω*t - k*x)`  and the plate prints  `A · sin(ω · t − k · x)`

- A preset that ships as LaTeX: `e^{-\frac{x^2+y^2}{4}}\cos t` [Open Gaussian Bump](https://www.wavelace.com/app#p=66)
- Degrees, and a subscripted letter: `\max(x\tan(45° + 30°\sin t) - \frac{9.8 x^2}{2 v_0^2\cos^2(45° + 30°\sin t)}, 0)` [Open Launch Angle](https://www.wavelace.com/app#p=131)
- \left|…\right| and \frac, pasted as printed: `\left(\left|\cos\frac{m\theta}{4}\right|^{n_2} + \left|\sin\frac{m\theta}{4}\right|^{n_3}\right)^{-1/n_1}` [Open Gielis Supershape](https://www.wavelace.com/app#p=134)

## What is refused, and why

These are refused rather than guessed at, a refusal being more use than a wrong curve. `\Sigma` and `\Pi` are the two Greek capitals that are not letters here: the pasted `Σ` already means `\sum` and `Π` means `\prod`, so a plate that printed either would paste back as the operator. `\varpi` is `\pi` in another hand. `\Gamma` is the gamma function and lowercase `\gamma` a letter, with nothing folding one into the other.

- \Sigma x: LaTeX command not supported: \Sigma
- \varpi: LaTeX command not supported: \varpi
- \pm 1: LaTeX command not supported: \pm
- x \circ y: LaTeX command not supported: \circ
- \nabla x: LaTeX command not supported: \nabla
- \lim x: LaTeX command not supported: \lim
- x_{k=1}: a subscript is one letter or digits: x_1, x_{12}, x_i
- |x|: | is not supported: write abs(x), or \left|x\right| when pasting
- \partial x: LaTeX command not supported: \partial
- sec^{-1}(x): sec^{-1} is not supported; the inverses this app has are sin^{-1}, cos^{-1}, tan^{-1}, sinh^{-1}, cosh^{-1}, tanh^{-1}
- x = 1: = is not supported: a formula is one expression, not an equation (the renderer writes its own left-hand side)
- x, y: a comma outside brackets is not supported: a formula is one expression
- sin(): sin needs an argument: sin() has no value to give

Nor is there a computer algebra system here, or iteration, or a differential equation written in the formula box. The last two have renderers of their own: complex for iteration, flow for a system of equations.

## The complex renderer's own language

The complex renderer parses its own formulas and compiles them to a shader, so every pixel is worked out on the GPU. It is a different language from the one above: none of the binders, none of the special functions.

It reads `i`, `pi`, `PI`, `e`, `E`, `tau`, `z`, `c`, `t`, `x`, `y`, `u`, `v`, `r`, `th`, where `i` is the imaginary unit and `c` is the pixel's own `z`, and calls `abs`, `acos`, `arg`, `asin`, `atan`, `atan2`, `cbrt`, `conj`, `cos`, `cosh`, `exp`, `hypot`, `im`, `log`, `max`, `min`, `pow`, `re`, `sin`, `sinh`, `sqrt`, `tan`, `tanh`.

- The Mandelbrot set, with Iterations up: `z^2 + c` [Open Mandelbrot](https://www.wavelace.com/app#p=47)
- A Julia set steered by two letters: `z^2 + \frac{a + b i}{5}` [Open Julia Dials](https://www.wavelace.com/app#p=141)

## The renderers, and what each feeds

What each one feeds a formula, in its own words:

- Wave · y = f(x, t): one expression. Feeds x and t; each ribbon slice also gets its depth as z and y. Any other letter, Latin, Greek or subscripted (x_1), becomes a slider.
- Polar · r = f(θ, t): one expression. Feeds θ (th) and t; a formula written in x reads the angle as x. Any other letter, Latin, Greek or subscripted (x_1), becomes a slider.
- Surface · z = f(x, y, t): one expression. Feeds x, y and t, plus r = hypot(x, y) and θ = atan2(y, x). Any other letter, Latin, Greek or subscripted (x_1), becomes a slider.
- Curve · (x, y, z) = f(u, t): Three expressions in u and t; u runs over the turns. Any other letter, Latin, Greek or subscripted (x_1), becomes a slider.
- Shape · (x, y, z) = f(u, v, t): Three expressions in u, v and t; u runs over the turns, v over 0 → π × span of v. Any other letter, Latin, Greek or subscripted (x_1), becomes a slider.
- Complex · w = f(z, t): one expression. Feeds z, c (= z) and t; i is the imaginary unit. Iterations > 0 applies f repeatedly. Any other letter, Latin, Greek or subscripted (x_1), becomes a slider.
- Quantum · ψ under V(x): one expression. Schrödinger's equation with ħ = m = 1: a Gaussian packet evolves under V(x); walls at ±span reflect. T and R are the probability right and left of x = 0. Any other letter, Latin, Greek or subscripted (x_1), becomes a slider.
- Quantum 2D · ψ under V(x, y): one expression. Schrödinger's equation in the plane, ħ = m = 1; the floor is tinted where V exceeds the packet's energy. T and R are the probability right and left of x = 0. Any other letter, Latin, Greek or subscripted (x_1), becomes a slider.
- Flow · (ẋ, ẏ, ż) = f(x, y, z, t): three expressions. A vector field: each seed moves at the velocity the expressions give at its position (RK4). y is up; a pasted z-up system reads with y and z swapped. Any other letter, Latin, Greek or subscripted (x_1), becomes a slider.
- Swarm · f(r) between bodies: one expression. The force between any two bodies at distance r, positive pulling them together: 1/r^2 is gravity. Unit masses start on a disc in the floor plane, turning at the swirl rate about their own centroid, so the cloud as a whole stays put. Distances are softened. Any other letter, Latin, Greek or subscripted (x_1), becomes a slider.
- Bodies · mechanical systems: a description, not a formula. A first line saying gravity, pendulum, charges, springs, restricted or elastic, then one line per body, rod, charge, mass, particle or spring: m x y vx vy, l m a (the angle), m q x y vx vy, x y vx vy, or l m k a s (a spring hung from the one above: its length, its bob, its stiffness, the angle and the stretch). Springs and restricted read a second kind of line too: a spring, from to k rest, joins two masses by number, and restricted's two primaries are lines naming only m. Values may be expressions. RK4; the energy drift is the check. Any other letter, Latin, Greek or subscripted (x_1), becomes a slider.
- Bellman · v(s) = maxₐ [R(s, a) + γ v(s′)]: a description, not a formula. One row per line: . empty, # wall, a number a terminal with that reward, S a start. Each sweep applies the Bellman update to every cell; the tiles rise to v(s) and the arrows point where the max is taken.

## What bodies and bellman read

Two renderers read a description in a field of their own. Both take one item per line, and a `;` counts as a new line, which is how a whole description fits in a link.

`bodies` runs a mechanical system. The first line names it, `gravity`, `pendulum`, `charges`, `springs`, `restricted` or `elastic`, with a colon after it if you like; every line after that is one item, written as `key=value` pairs with spaces between them. A value may be an expression, `vy=sqrt(1/2.2)` or `a=pi/3`, as long as it is a constant: it may not name a variable. A letter in it, `m=k`, becomes a slider as it does in a formula, and dragging it starts the system again from the beginning. Every system is integrated by the same fourth-order Runge–Kutta step, and the readout shows the energy and how far it has drifted, which is the check on the integrator.

### `gravity`

Point masses pulling on each other in the floor plane, with G = 1 and the pull softened at very short range. One body per line, at least two bodies, and each names `x` or `y`. The plate shows `r̈ᵢ = G Σⱼ mⱼ (rⱼ − rᵢ) / |rⱼ − rᵢ|³`.

- m: its mass; `1` when left out
- x: where it starts, across the floor; `0` when left out
- y: where it starts, along the floor; `0` when left out
- vx: its starting velocity across; `0` when left out
- vy: its starting velocity along; `0` when left out

```
gravity
m=1  x=0  y=0
m=0.001  x=1  y=0  vx=0  vy=1
```

[Open it in the app](https://www.wavelace.com/app#m=bodies&f=gravity%0Am%3D1++x%3D0++y%3D0%0Am%3D0.001++x%3D1++y%3D0++vx%3D0++vy%3D1)

### `pendulum`

A chain of rigid rods hung from one pivot, each with a bob at its end, under g = 9.81: one rod is a simple pendulum, two a double, three a triple. One rod per line, at least one rod. The plate shows `M(θ) θ̈ + C(θ, θ̇) + G(θ) = 0`.

- l: its length; `1` when left out
- m: the mass of the bob at its end; `1` when left out
- a: the angle it starts at, in radians from straight down; `0` when left out

```
pendulum
l=1  m=1  a=2.4
l=1  m=1  a=2.4
```

[Open it in the app](https://www.wavelace.com/app#m=bodies&f=pendulum%0Al%3D1++m%3D1++a%3D2.4%0Al%3D1++m%3D1++a%3D2.4)

### `charges`

Point charges in the floor plane under Coulomb's law with k = 1: like signs repel and unlike attract, the force softened at very short range as gravity's is. One charge per line, at least two charges, and each names `x` or `y`. The plate shows `mᵢ r̈ᵢ = k Σⱼ qᵢ qⱼ (rᵢ − rⱼ) / |rᵢ − rⱼ|³`.

- m: its mass; `1` when left out
- q: its charge, negative for the other sign; `1` when left out
- x: where it starts, across the floor; `0` when left out
- y: where it starts, along the floor; `0` when left out
- vx: its starting velocity across; `0` when left out
- vy: its starting velocity along; `0` when left out

```
charges
m=1000  q=1  x=0  y=0
m=1  q=1  x=-3  y=0.5  vx=2
```

[Open it in the app](https://www.wavelace.com/app#m=bodies&f=charges%0Am%3D1000++q%3D1++x%3D0++y%3D0%0Am%3D1++q%3D1++x%3D-3++y%3D0.5++vx%3D2)

### `springs`

Masses in the floor plane joined by the springs named after them, each pulling its two ends together when stretched past its natural length and pushing them apart inside it; no gravity, nothing softened. One mass per line, at least two masses, and each names `x` or `y`. The plate shows `mᵢ r̈ᵢ = Σⱼ kᵢⱼ (|rⱼ − rᵢ| − ℓᵢⱼ) (rⱼ − rᵢ) / |rⱼ − rᵢ|`.

- m: its mass; `1` when left out
- x: where it starts, across the floor; `0` when left out
- y: where it starts, along the floor; `0` when left out
- vx: its starting velocity across; `0` when left out
- vy: its starting velocity along; `0` when left out

A line naming `from=` or `to=` is a spring, at least one spring, wherever it sits; it takes these.

- from: the number of the mass at one end, the masses counted from 1 in the order written
- to: the number of the mass at the other end
- k: its stiffness; `1` when left out
- rest: its natural length; left out, the distance its two masses start at, so a chain written at rest stays at rest

```
springs
m=1  x=-1  y=0  vx=0  vy=0.5
m=1  x=1  y=0  vx=0  vy=-0.5
k=1  from=1  to=2
```

[Open it in the app](https://www.wavelace.com/app#m=bodies&f=springs%0Am%3D1++x%3D-1++y%3D0++vx%3D0++vy%3D0.5%0Am%3D1++x%3D1++y%3D0++vx%3D0++vy%3D-0.5%0Ak%3D1++from%3D1++to%3D2)

### `restricted`

The restricted three-body problem: two heavy bodies on a circular orbit, seen in the frame that turns with them so they stand still, one unit apart about their barycentre at the origin, and massless particles that feel their gravity with the centrifugal and Coriolis terms of the turning frame, G = 1, softened as gravity is. A particle's place and velocity are read in that turning frame, and the energy readout is the sum of the particles' Jacobi integrals, the one quantity the turning frame keeps. One particle per line, at least one particle, and each names `x` or `y`. The plate shows `r̈ᵢ = Σⱼ mⱼ (rⱼ − rᵢ) / |rⱼ − rᵢ|³ + Ω² rᵢ − 2 Ω × ṙᵢ`.

- x: where it starts, across the floor; `0` when left out
- y: where it starts, along the floor; `0` when left out
- vx: its starting velocity across; `0` when left out
- vy: its starting velocity along; `0` when left out

A line naming `m=` is a primary, exactly two primaries, wherever it sits; it takes these.

- m: its mass; a primary's line names nothing else, since the pair sits one unit apart about its barycentre, the first written on the left, turning at √(m₁ + m₂)

```
restricted
m=0.99
m=0.01
x=0.49  y=0.866
```

[Open it in the app](https://www.wavelace.com/app#m=bodies&f=restricted%0Am%3D0.99%0Am%3D0.01%0Ax%3D0.49++y%3D0.866)

### `elastic`

A bob on a spring hung from a pivot under g = 9.81, free to swing and to bounce, or a chain of them: each spring pulls its bob towards what it hangs from when stretched past its natural length and pushes when shorter, and the bob below pulls back; nothing is softened. The pivot hangs at the chain's resting length, so a chain written with no angle and no stretch rests with its last bob on the floor. One spring per line, at least one spring, and each names `k`. The plate shows `mᵢ r̈ᵢ = Σⱼ kⱼ (|dⱼ| − ℓⱼ) d̂ⱼ − mᵢ g ŷ`.

- l: its natural length; `1` when left out
- m: the mass of the bob at its end; `1` when left out
- k: its stiffness
- a: the angle it starts at, in radians from straight down; `0` when left out
- s: how far past its natural length it starts stretched, negative for shorter; left out, the stretch the load below gives it hanging still

```
elastic
l=1  m=1  k=29.43  a=0.05  s=0.3
```

[Open it in the app](https://www.wavelace.com/app#m=bodies&f=elastic%0Al%3D1++m%3D1++k%3D29.43++a%3D0.05++s%3D0.3)

### `bellman`

A grid world, one row of cells per line with spaces between the cells, every row as long as the first, and at most 40 cells on a side. A cell is one of these, and nothing in it is an expression. The discount, the slip and the reward for a step are dials, in the table below.

- .: an empty cell
- #: a wall: a move into it stays where it was
- S: an empty cell that is also the start the greedy walk is drawn from
- +1: a terminal with that reward, where the walk ends; any number, as +1, -1 or 0.5

```
. . +1
# . -1
S . .
```

[Open it in the app](https://www.wavelace.com/app#m=bellman&f=.+.+%2B1%0A%23+.+-1%0AS+.+.)

### What they refuse

In the app's own words, as for a formula. The last good description keeps running while the field says why the new one did not take.

- orbit; m=1 x=0 y=0; m=1 x=1 y=0: the first line names the system: gravity, pendulum, charges, springs, restricted or elastic
- gravity; m=1 x=0 y=0: gravity needs at least two bodies, one per line
- gravity; m=1; m=2: each body needs x= or y=
- gravity; m=1 x=0 y=0 vz=1; m=1 x=1 y=0: vz is not a key of gravity: m x y vx vy
- pendulum; l=1 m=1 a=t: "t" must be a constant
- pendulum; l=1 m=1 a: cannot read "a": expected key=value
- charges; m=0 q=1 x=0; q=1 x=1: m=0: a charge needs a mass to move
- springs; x=0; x=1: springs needs at least one spring, one per line
- springs; x=0; x=1; from=1 to=3: to=3 names no mass: there are 2, numbered from 1 in the order written
- springs; x=0 k=2; x=1; from=1 to=2: k is not a key of springs: m x y vx vy (a spring's line names from= and to=)
- restricted; m=0.99; m=0.01: restricted needs at least one particle, one per line
- restricted; m=1; x=0.49 y=0.866: restricted needs exactly two primaries, one per line
- restricted; m=0.99; m=0.01; m=0 x=0.5: x is not a key of a primary: m (a particle's line names x= or y=)
- restricted; m=0; m=1; x=0.49: m=0: a primary needs a mass
- elastic; l=1 m=1: each spring needs k=
- elastic; l=1 m=1 k=0: k=0: a spring needs a stiffness
- elastic; l=1 k=10 x=1: x is not a key of elastic: l m k a s
- . . +1; # .: row 2 has 2 cells, row 1 has 3
- . . x: cannot read "x": cells are . # S or a number
- a row of 41 cells: at most 40 cells on a side

## The dials

Three dials are on every renderer and the rest appear where they mean something. Each says how it enters the formula, in the words of the renderer offering it: a dial borrowed for another quantity means that quantity there, and says so. The range is the renderer's own, and the app shows it on the dial. A free variable, any single letter the formula names that is not one of the eight, Latin or Greek, is a dial of its own below these, from -10 to 10, and there may be any number of them.

- span: (wave — `x`: x runs over ±span; surface — `x, y`: x and y run over ±span; complex — `z`: z runs over ±span; quantum — `x`: x runs over ±span; the walls are there; quantum 2D — `x, y`: x and y run over ±span; the walls are there; flow — `x, y, z`: the plot shows ±span; swarm, bodies — the plot shows ±span)
- speed: every renderer — `t`: how fast t advances
- amp: (wave — `× y`: multiplies y; polar — `× r`: multiplies r; surface — `× z`: multiplies z; curve, shape — `× (x, y, z)`: scales the whole figure; complex — `× |w|`: multiplies the height, |w|; quantum, quantum 2D — `× |ψ|²`: scales the drawn height of |ψ|²; flow, swarm, bodies — `× y`: scales the drawn height; bellman — `× v`: scales the drawn height of v(s))
- depth: (wave — `z`: each ribbon slice sits at its depth z, and is fed it; polar — `t`: older copies of the curve, stacked above; surface, shape, quantum 2D — grid resolution; the top stop is a lit solid; curve — `t`: older copies of the curve, left in place; complex — `n`: f applied n times; 0 is off; quantum — `t`: how much of the past the ribbon keeps; flow — `t`: how much of each seed's path stays on; past 80, further back, the same points spread thinner; swarm, bodies — `t`: how much of each body's path stays on; past 80, further back, the same points spread thinner; bellman — `k`: how many sweeps the clock runs through)
- turns: (polar — `θ`: θ runs 0 → 2π × turns; curve, shape — `u`: u runs 0 → 2π × turns)
- vspan: shape — `v`: v runs 0 → π × span of v
- x0: (quantum, quantum 2D — `x₀`: where the packet starts; flow — `x₀`: where the seeds start; swarm — `x₀`: where the cloud starts)
- y0: (quantum 2D — `y₀`: where the packet starts, along y; flow — `y₀`: where the seeds start, along y; swarm — `y₀`: where the cloud starts, along y; bellman — `r`: the reward for every step that is not terminal)
- z0: flow — `z₀`: where the seeds start, along z
- seeds: (flow — `n`: how many seeds ride the field; swarm — `n`: how many bodies)
- sigma: (quantum, quantum 2D — `σ`: the packet's width; flow — `σ`: how far the seeds spread from the centre; swarm — `R`: the cloud's radius; bellman — `γ`: the discount on the next state's value)
- k0: (quantum, quantum 2D — `k₀`: the packet's momentum, along x; swarm — `ω`: the cloud's initial spin; bellman — `p`: the chance a move slips sideways)

## Sharing and embedding

The part after the `#` carries the whole plot: renderer, formula, dials and camera. A browser never sends it to a server, so copying the address copies what is on screen. The same link opens the embed page, which is the plot and nothing else:

```
<iframe src="https://www.wavelace.com/embed#p=42&trace=1" title="Wavelace" loading="lazy" style="display:block;width:100%;aspect-ratio:4/3;border:0"></iframe>
```

The Embed panel in the app writes that for you, with the options below as switches. Each is written into a link only where it differs from the value in brackets, which is what a link means by leaving it out:

- play: the clock runs, so a plot opens moving (on)
- spin: the camera turns by itself (off)
- ground: the floor and its grid (on)
- trace: wave, polar and curve: draw the curve from its start as the clock runs (off)
- particles: the dots in the quantum renderers (on)
- fill: surface, shape and quantum 2D below the solid stop: the mesh as a filled sheet (on)
- deck: the embed's bar of playback, views and toggles (on)
- formula: the formula over the plot (on)
- title: the name under it (on)
- orbit: the orbit drag; the view buttons still work without it (on)
- pan: the shift-drag and right-drag pan (on)

Writing a link by hand, the formula goes in `f=` and the hash is read as a query string, so a plus must be written `%2B`, a newline `%0A` and a hash `%23`. A renderer that takes a description rather than a formula needs all three:

- A grid, written out: `../app#m=bellman&f=.+.+%2B1%0A%23+.+-1%0AS+.+.`

To keep a still of the plot rather than a live one, the app's Picture button saves it as a PNG, or copies it, at the shape and scale you choose.

[Open the app and try it &rarr;](https://www.wavelace.com/app)
