# CommonMath
_Source: `GridKit/CommonMath.md`_
Smooth, autodiff-friendly replacements for piecewise functions used across GridKit component models. See [CommonMath.hpp](../../../GridKit/CommonMath.hpp) for implementation details.
## Primitives
The scale $\mu=4\cdot f_{\text{sync}}=240$ is chosen so $\sigma$ behaves like a step on inputs while keeping derivatives finite. As $\mu \to \infty$, these functions approach their exact targets.
| Name | Description | Usage |
|------|-------------|-------|
| `sigmoid` | Step function | `GENSAL`, `GENROU`, `REGCA`, `REECA` |
| `ramp` | Smooth one-sided ramp | `REGCA`, `REECA`, `REPCA` |
| `qramp` | Exact one-sided quadratic ramp | `IEEET1` |
### $\sigma$ - `sigmoid`
The sigmoid is also known as the logistic function. The equivalent `tanh` form is used for numerical stability because the exponential form can divide by a very large value.
```{math}
\begin{aligned}
\sigma(x)
&=
\begin{cases}
0 & x\le 0 \\[0pt]
1 & x\gt 0
\end{cases} \\[0pt]
&\approx \dfrac{1}{2}\left(1+\tanh\left(\dfrac{\mu x}{2}\right)\right)
\end{aligned}
```
```{image} ../../Figures/CommonMath/sigmoid.svg
```
### $\rho$ - `ramp`
`ramp` is the softplus approximation to the one-sided ramp. We do not use $x\sigma(x)$ directly because it introduces a negative tail for $x \lt 0$, while softplus stays nonnegative and approaches $\max(x, 0)$ as the smoothing becomes sharp.
```{math}
\begin{aligned}
\rho(x)
&= x\,\sigma(x) \\[0pt]
&\approx \dfrac{x+\lvert x\rvert}{2}+\dfrac{\ln\!\left(1+e^{-\mu\lvert x\rvert}\right)}{\mu}
\end{aligned}
```
```{image} ../../Figures/CommonMath/ramp.svg
```
### $q$ - `qramp`
*Note*: the implementation of the quadratic ramp `q(x)` could be optimized with Enzyme features down the road so that we don't need the smooth approximation.
```{math}
q(x)=x^2\,\sigma(x)
```
```{image} ../../Figures/CommonMath/qramp.svg
```
(anti-windup-indicator)=
## Derived Functions
| Name | Description | Usage |
|------|-------------|-------|
| `max` | Smooth binary maximum | `REECA`, `REECB` |
| `min` | Smooth binary minimum | `REECA` |
| `clamp` | Bounded saturation | `IEEEST`, `REECA`, `REECB`, `REPCA` |
| `deadband1` | Type 1 no-offset signed two-sided deadband | - |
| `deadband2` | Type 2 offset signed two-sided deadband | `REECA`, `REECB`, `REPCA` |
| `slew` | Symmetric slew-rate limiter | - |
| `linseg` | Saturated linear segment contribution | `REGCA`, `REECA` |
| `above` | Above-lower-limit indicator | `REPCA` |
| `below` | Below-upper-limit indicator | - |
| `inside` | Interior pulse indicator | - |
| `outside` | Outside-band indicator | `REECA`, `REECB` |
| `antiwindup` | Anti-windup limited derivative | `IEEET1`, `SEXS-PTI`, `TGOV1`, `REECA`, `REECB`, `REPCA` |
### `max`
```{math}
\begin{aligned}
\text{max}(x,y)
&=
\begin{cases}
x & x\gt y \\[0pt]
y & x\le y
\end{cases} \\[0pt]
&\approx y+\rho(x-y)
\end{aligned}
```
```{image} ../../Figures/CommonMath/max.svg
```
### `min`
```{math}
\begin{aligned}
\text{min}(x,y)
&=
\begin{cases}
x & x\lt y \\[0pt]
y & x\ge y
\end{cases} \\[0pt]
&\approx x-\rho(x-y)
\end{aligned}
```
```{image} ../../Figures/CommonMath/min.svg
```
### `clamp`
```{math}
\begin{aligned}
\text{clamp}(x;\ell,u)
&=
\begin{cases}
\ell & x\lt \ell \\[0pt]
x & \ell\le x\le u \\[0pt]
u & x\gt u
\end{cases} \\[0pt]
&\approx \ell+\rho(x-\ell)-\rho(x-u)
\end{aligned}
```
```{image} ../../Figures/CommonMath/clamp.svg
```
### `deadband1`
```{math}
\begin{aligned}
\text{deadband1}(x;\ell,u)
&=
\begin{cases}
x & x\lt \ell \\[0pt]
0 & \ell\le x\le u \\[0pt]
x & x\gt u
\end{cases} \\[0pt]
&\approx x\left[\sigma(\ell-x)+\sigma(x-u)\right]
\end{aligned}
```
```{image} ../../Figures/CommonMath/deadband1.svg
```
### `deadband2`
```{math}
\begin{aligned}
\text{deadband2}(x;\ell,u)
&=
\begin{cases}
x-\ell & x\lt \ell \\[0pt]
0 & \ell\le x\le u \\[0pt]
x-u & x\gt u
\end{cases} \\[0pt]
&\approx \rho(x-u)-\rho(\ell-x)
\end{aligned}
```
```{image} ../../Figures/CommonMath/deadband2.svg
```
### `slew`
```{math}
\begin{aligned}
\text{slew}(f;r)
&=
\begin{cases}
-r & f\lt -r \\[0pt]
f & -r\le f\le r \\[0pt]
r & f\gt r
\end{cases} \\[0pt]
&\approx -r+\rho(f+r)-\rho(f-r)
\end{aligned}
```
```{image} ../../Figures/CommonMath/slew.svg
```
### `linseg`
```{math}
\begin{aligned}
\text{linseg}(x;a,b,h)
&=
\begin{cases}
0 & x\lt a \\[0pt]
\dfrac{h}{b-a}(x-a) & a\le x\le b \\[0pt]
h & x\gt b
\end{cases} \\[0pt]
&\approx \dfrac{h}{b-a}\left[\rho(x-a)-\rho(x-b)\right]
\end{aligned}
```
```{image} ../../Figures/CommonMath/linseg.svg
```
### `above`
```{math}
\begin{aligned}
\text{above}(x;\ell)
&=
\begin{cases}
0 & x\le \ell \\[0pt]
1 & x\gt \ell
\end{cases} \\[0pt]
&\approx \sigma(x-\ell)
\end{aligned}
```
```{image} ../../Figures/CommonMath/above.svg
```
### `below`
```{math}
\begin{aligned}
\text{below}(x;u)
&=
\begin{cases}
1 & x\lt u \\[0pt]
0 & x\ge u
\end{cases} \\[0pt]
&\approx \sigma(u-x)
\end{aligned}
```
```{image} ../../Figures/CommonMath/below.svg
```
### `inside`
```{math}
\begin{aligned}
\text{inside}(x;\ell,u)
&=
\begin{cases}
1 & \ell\lt x\lt u \\[0pt]
0 & \text{else}
\end{cases} \\[0pt]
&\approx \sigma(x-\ell)+\sigma(u-x)-1
\end{aligned}
```
```{image} ../../Figures/CommonMath/inside.svg
```
### `outside`
```{math}
\begin{aligned}
\text{outside}(x;\ell,u)
&=
\begin{cases}
1 & x\lt \ell\ \lor\ x\gt u \\[0pt]
0 & \text{else}
\end{cases} \\[0pt]
&\approx \sigma(\ell-x)+\sigma(x-u)
\end{aligned}
```
```{image} ../../Figures/CommonMath/outside.svg
```
### `antiwindup`
```{math}
\begin{aligned}
\text{antiwindup}(x,f;\ell,u)
&=
\begin{cases}
f & \ell\lt x\lt u \\[0pt]
f & x\le\ell\ \land\ f\gt 0 \\[0pt]
f & x\ge u\ \land\ f\lt 0 \\[0pt]
0 & \text{otherwise}
\end{cases} \\[0pt]
\phi_L
&= \text{above}(x;\ell) \\[0pt]
\phi_U
&= \text{below}(x;u) \\[0pt]
\phi(x,f)
&= \phi_L\phi_U+(1-\phi_U)\sigma(-f)+(1-\phi_L)\sigma(f) \\[0pt]
\text{antiwindup}(x,f;\ell,u)
&\approx \phi(x,f)\,f
\end{aligned}
```