Pade Approximant — Control Systems/Polynomials
Control_Systems/Polynomials/Pade_Approximant · 1 input / 2 output port(s) at insert · exports to Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text
Description#
The block's own DESCRIPTION_HTML, rendered verbatim — the same text the config dialog's info panel and the library navigator show. Fix a wrong sentence in the block's .cpp (R-D9), never here.
Pade Approximant
Control Systems / Polynomials
Reports the [m/n] Padé approximant of a dead time e−sT as two coefficient vectors, with the delay T arriving on a port. In descending powers of s,
P(s) = Σk ak·(−T)k·sk and Q(s) = Σk bk·Tk·sk, where ak = (m+n−k)! m! / ((m+n)! k! (m−k)!) and bk is the same with n in place of m. At m = n = 1 that is the textbook (1 − Ts/2) / (1 + Ts/2).
It reports the coefficients; it does not delay anything. Wire the two outputs into Continuous / Transfer Function for the approximated delay itself. For a true dead time reach for Continuous / Transport Delay instead – the reason to approximate is to keep the model finite-dimensional, and so linearizable.
Ports
- T – the dead time in seconds. Scalar. Zero is valid and gives the constant 1 on both sides; a negative value is accepted and describes a lead rather than a lag.
- num – P's coefficients, descending powers of s, as a column of m + 1 entries.
- den – Q's coefficients, descending, as a column of n + 1 entries.
Parameters
- Numerator Order – m, a whole number from 0 to 8. The numerator then has m + 1 entries. Default 2.
- Denominator Order – n, the same range; the denominator
has n + 1 entries. Default 2. Equal orders are the usual choice and are
what MATLAB's
pade(T, N)produces; m < n gives a strictly proper approximation, which a state space needs. - Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.
Code export
All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text. The two orders are structural and are baked into the generated body – they decide how many coefficients exist – so nothing is exposed as a tunable parameter on the generated core.
Every emitted body raises T to one power at a time and scales it by an inlined constant, so no target divides, iterates or evaluates a factorial at run time. The three HDL targets are therefore genuine synthesizable Q16.16. Note that a high power of T there is formed by repeated multiplication in fixed point, so each power carries one more rounding than the last – at Q16.16 that is about 1.5×10−5 per step.
Simulink bridge
None (Support::None). pade is a MATLAB
function, and the Symbolic Math Toolbox this block answers ships no Simulink
library at all, so there is no library path a diagram could name. Simulink's own
Transport Delay is a different thing – it delays a signal rather than
reporting an approximation's coefficients – so mapping onto it would be
wrong rather than partial. The bridge reports this block instead of dropping it
silently, and it therefore has no parity testbench; code export
verification still covers it across all ten languages. No configuration of it
crosses either, including "Sampling Time (s)", which has no counterpart to be
written to.
Notes
- Algebraic, with no state: the output depends only on the current input.
- The normalization is P(0) = Q(0) = 1, and MATLAB's is not. Control
System Toolbox scales both polynomials so the leading coefficient is 1;
this leaves the constant term at 1. They are the same transfer function
– both sides carry the same factor. Measured at T = 1.3, m = n = 2:
pade(1.3, 2)gives [1, −4.615384615384615, 7.1005917159763312] over [1, 4.615384615384615, 7.1005917159763312], and this block gives [0.14083333333333334, −0.65, 1] over [0.14083333333333334, 0.65, 1] – the same numbers divided by 0.14083333333333334 on both sides. The choice is deliberate: MATLAB's divisor is proportional to Tm and so runs to infinity as the delay approaches zero, which a block whose delay is a signal cannot afford. - A delay of zero is not a special case. Every power of T above the zeroth vanishes and both outputs become the constant 1, so the ratio is 1 – which is what e0 is. Nothing divides by T anywhere.
- No state space: the map is a polynomial in the input rather than a linear one, so there is no A/B/C/D to merge and model reduction correctly declines it. The approximation has a state space; feed these coefficients to Transfer Function to get it.
Code facts#
| Fact | Value |
|---|---|
| registered type | Control_Systems/Polynomials/Pade_Approximant |
| family | Control_Systems/Polynomials |
| solver environment class | ICoreBlock_0_Control_Systems_1_Polynomials_2_Pade_Approximant |
| source | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Polynomials/Pade_Approximant/ICoreBlock_0_Control_Systems_1_Polynomials_2_Pade_Approximant.cpp |
| header | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Polynomials/Pade_Approximant/ICoreBlock_0_Control_Systems_1_Polynomials_2_Pade_Approximant.h |
| default size on canvas | 122 × 80 px |
| ports at insert | 1 in, 2 out |
| code generators implemented | Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text |
Ports#
| # | Direction | Signal type | Description label |
|---|---|---|---|
| 1 | in | ICoreDouble | T |
| 2 | out | ICoreDouble | num |
| 3 | out | ICoreDouble | den |
Ports the constructor creates. A block whose port list changes with its configuration adds or removes ports at load time; the count above is the one a freshly inserted block has.
Configuration variables#
| Config variable | Default | Simulink parameter |
|---|---|---|
Numerator Order | 2 | — |
Denominator Order | 2 | — |
Every block also carries Sampling Time (s) from ICoreBlockSolverEnvironment: zero or less inherits the solver's rate, a positive value runs the block at that period.
Simulink bridge#
| support | Support::None |
| Simulink path | — |
| port-count rule | PortsParam::None |
SampleTime parameter | yes |
Caveat (shown to the user): the Pade approximant of a dead time is a MATLAB function (pade), not a Simulink library block -- the Symbolic Math Toolbox this block answers ships no Simulink library at all -- and Simulink's Transport Delay is a different thing, delaying a signal rather than reporting an approximation's coefficients, so mapping onto it would be wrong rather than partial; the block is reported rather than dropped when a model crosses
Catalog contract: src/ICoreBlocks/ICoreCoder/ICoreCommandSystem/SimulinkBridge/ICoreSimulinkBlockCatalog.h
Description vs code#
The lists agree. check_block_descriptions.py finds no disagreement between the description's Ports, Parameters, Code export and Simulink bridge lists and the code's.
The verdict above is
tools/docs/check_block_descriptions.py(P7.1), which compares LISTS. It cannot read a sentence: "stateless" on a block with a state, an initial-value semantic the recursion does not implement, a "not synthesizable" caveat the HDL banner contradicts. That is the agent audit (P7.3) on BLOCK_DESCRIPTION_AUDIT.md, and this tool's green is not a substitute for one.
File banner (developer view)#
The top comment of the block's .cpp — the maths, the realization and the export strategy, addressed to whoever changes it. It must not contradict the description above (P7.5).
Pade Approximant -- a dead time as a ratio of polynomials, with the dead time on a wire Every coefficient of the [m/n] approximant of exp(-sT) is a CONSTANT times a power of T:
P(s) = SUM(k) (m+n-k)! m! / ((m+n)! k! (m-k)!) * (-T)^k * s^k k = 0..m Q(s) = SUM(k) (m+n-k)! n! / ((m+n)! k! (n-k)!) * ( T)^k * s^k k = 0..n
The constants depend on the two ORDERS alone and are settled when the configuration is read; every target then multiplies a running power of T by them. No solve, no iteration and no division survives into a generated core, which is what makes this exportable to all ten targets and synthesizable in the three fixed-point ones.
⚠ THE RUNNING POWER IS SHARED BETWEEN THE TWO OUTPUTS AND BUILT ASCENDING. T^k is formed once per k and used by both polynomials, so the emitted body has one multiply per power rather than one per coefficient -- and it walks k UPWARDS while both outputs are written in DESCENDING order, which is why the two index expressions run opposite ways.
Verified against MATLAB R2026a rather than asserted. At T = 1.3, m = n = 2,
pade(1.3, 2)returns [1, -4.615384615384615, 7.1005917159763312] over [1, 4.615384615384615, 7.1005917159763312]. This block returns [0.14083333333333334, -0.65, 1] over [0.14083333333333334, 0.65, 1] -- the same ratio, both sides divided by 0.14083333333333334. The normalization is different on purpose and the header says why: MATLAB's divides by a coefficient proportional to T^m, which is unbounded as the delay goes to zero.
Sample results#
| t | in ICoreDouble-Out-0 | out ICoreDouble-Out-0 [3x1] entry 0 | out ICoreDouble-Out-1 [3x1] entry 0 |
|---|---|---|---|
| 0 | -2 | [0.3333, 1, 1] | [0.3333, -1, 1] |
| 0.4 | 0.5 | [0.02083, -0.25, 1] | [0.02083, 0.25, 1] |
| 0.8 | -2 | [0.3333, 1, 1] | [0.3333, -1, 1] |
| 1.2 | 0.5 | [0.02083, -0.25, 1] | [0.02083, 0.25, 1] |
| 1.6 | -2 | [0.3333, 1, 1] | [0.3333, -1, 1] |
| 2 | 0.5 | [0.02083, -0.25, 1] | [0.02083, 0.25, 1] |
| 2.4 | -2 | [0.3333, 1, 1] | [0.3333, -1, 1] |
| 2.8 | 0.5 | [0.02083, -0.25, 1] | [0.02083, 0.25, 1] |
| 3.2 | -2 | [0.3333, 1, 1] | [0.3333, -1, 1] |
| 3.6 | 0.5 | [0.02083, -0.25, 1] | [0.02083, 0.25, 1] |
| 4 | -2 | [0.3333, 1, 1] | [0.3333, -1, 1] |
| 4.4 | 0.5 | [0.02083, -0.25, 1] | [0.02083, 0.25, 1] |
| 4.8 | -2 | [0.3333, 1, 1] | [0.3333, -1, 1] |
| 5.2 | 0.5 | [0.02083, -0.25, 1] | [0.02083, 0.25, 1] |
Every 4th of 60 samples, from the table stimulus.
The same rig also ran:
| Stimulus | What it is | Output range |
|---|---|---|
impulse | Impulse: one sample of 1 at k = 5, 0 elsewhere (Repeating Sequence Stair) | 0 … 0.08333 |
ramp | Ramp: slope 1 from t = 0 | 0 … 2.803 |
sine | Sine Wave: amplitude 1, 2 rad/s, no phase, no bias | 0 … 0.08333 |
step | Step: 0 -> 1 at t = 1 s | 0 … 0.08333 |
Plotted: table — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample
Category static · sample time 0.1 · 60 steps · commit ba0d5f47abbf16b9e248ecce5a0d14210ec2f9d7 · produced by docsSample --out <folder> --blocks Polynomial_Coefficients Characteristic_Polynomial Pade_Approximant --steps 60 · data docs/generated/samples/Control_Systems__Polynomials__Pade_Approximant.json · the SVG is generated from those numbers by tools/docs/plot_svg.py, so it is a run and not a drawing (R-D10).