Sparse Second Order — Control Systems/Continues
Control_Systems/Continues/Sparse_Second_Order · 1 input / 1 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.
Sparse Second Order
Control Systems / Continues
A continuous linear system stated in second-order form, the way a structural or mechanical model is normally written:
M·q″ + C·q′ + K·q = B·u
y = F·q + G·q′ + D·u
with nq generalized coordinates, m inputs and p outputs, so M, C and K are [nq,nq], B is [nq,m], F and G are [p,nq] and D is [p,m]. Internally it is the equivalent first-order system on the state x = [q; q′], with A = [0 I; −M\K −M\C], so every linear-analysis and model-reduction command treats it exactly like a State Space block.
Ports
- Input – the force/input vector u, [m,1], sized from the column count of B and D.
- Output – the measurement vector y, [p,1], sized from the row count of F, G and D.
Parameters
- M – the mass matrix, [nq,nq]. It must be invertible: a singular M makes the model a differential-algebraic system rather than an ODE, which this block does not solve, and the run stops with a message naming the block.
- C – the damping matrix, [nq,nq]. Zero for an undamped system.
- K – the stiffness matrix, [nq,nq].
- B – the input matrix, [nq,m]; its column count sets the input port width.
- F – the displacement output matrix, [p,nq].
- G – the velocity output matrix, [p,nq]. Zero for a pure displacement measurement.
- D – the direct feedthrough matrix, [p,m].
- q0 – initial displacement, [nq,1].
- dq0 – initial velocity, [nq,1]. Together they form the [2·nq,1] initial state.
- 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. A deployable target runs a discrete model, so the export carries the assembled first-order system discretized by the run's method – the same set the discrete solver path uses, so the generated code matches the in-app simulation. The matrices are inverted and assembled at export time and baked into the body as constants: no target ever inverts M, and none of M, C, K is retunable on the generated core.
Simulink bridge
Import and export, mapped to cstblocks/Sparse Second Order (the
library is cstblocks, not the "Control System Toolbox" display
name, which add_block does not accept). All nine parameters cross
by their own names as plain pass-through values – M,
C, K, B, F, G,
D, q0 and dq0 – so the round trip
is lossless. "Sampling Time (s)" does NOT cross: this Simulink block
defines no SampleTime parameter at all, so the rate stays on the
ICore side and a block given an explicit period reports that it did not
cross.
Notes
- Stateful and continuous: the state is [q; q′] and the solver integrates it between steps.
- Being linear with a valid state space, the block is directly usable by the model reduction and linear-analysis commands – the second-order form is how the system is stated, not a different kind of dynamics.
- Simulink calls the block "sparse" because it stores M, C and K in sparse form for very large structural models. ICore holds them densely; the mathematics is identical, and the difference only shows as memory use on models far larger than a diagram carries.
Code facts#
| Fact | Value |
|---|---|
| registered type | Control_Systems/Continues/Sparse_Second_Order |
| family | Control_Systems/Continues |
| solver environment class | ICoreBlock_0_Control_Systems_1_Continues_2_Sparse_Second_Order |
| source | src/ICoreSDK/ICoreBlockLibrary/Blocks/Control_Systems/Continues/Sparse_Second_Order/ICoreBlock_0_Control_Systems_1_Continues_2_Sparse_Second_Order.cpp |
| header | src/ICoreSDK/ICoreBlockLibrary/Blocks/Control_Systems/Continues/Sparse_Second_Order/ICoreBlock_0_Control_Systems_1_Continues_2_Sparse_Second_Order.h |
| default size on canvas | 130 × 90 px |
| ports at insert | 1 in, 1 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 | — |
| 2 | out | ICoreDouble | — |
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 |
|---|---|---|
M | 1 | M |
C | 0 | C |
K | 1 | K |
B | 1 | B |
F | 1 | F |
G | 0 | G |
D | 0 | D |
q0 | 0 | q0 |
dq0 | 0 | dq0 |
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::Both |
| Simulink path | cstblocks/Sparse Second Order |
| port-count rule | PortsParam::None |
SampleTime parameter | no — the counterpart defines none; the rate stays on the ICore side |
| ICore config | Simulink parameter | Value translation |
|---|---|---|
M | M | passes through |
C | C | passes through |
K | K | passes through |
B | B | passes through |
F | F | passes through |
G | G | passes through |
D | D | passes through |
q0 | q0 | passes through |
dq0 | dq0 | passes through |
Caveat (shown to the user): the block runs at the surrounding Simulink rate; "Sampling Time (s)" does not cross, because this Simulink block defines no SampleTime parameter
Catalog contract: src/ICoreSDK/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).
Sparse Second Order block — a structural model in the form it is written in M q'' + C q' + K q = B u y = F q + G q' + D u
Underneath it is a plain continuous linear state space on x = [q; q'], assembled ONCE per loadBlockConfig rather than per step:
A = [ 0 I ; -M\K -M\C ] B_ss = [ 0 ; M\B ] C_ss = [ F G ] D_ss = D
Having a real state space is what makes the block mergeable by the reduction commands and exportable through the shared discretization (ADDING_NEW_BLOCKS.md §4) — the second-order form is a way of STATING the system, not a different kind of block.
Code export (Python/MATLAB/Java/Rust/C/C++, three HDLs and PLC ST) Targets cannot integrate an ODE, so every generator realizes the DISCRETIZED recursion, exactly as the continuous State Space block does: y[k] = C x[k] + D u[k] x[k+1] = A x[k] + B u[k] discretized by the MODEL's method, so the export matches the in-app simulation.
Sample results#
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.09991 … 0.09987 |
ramp | Ramp: slope 1 from t = 0 | 0 … 6.265 |
sine | Sine Wave: amplitude 1, 2 rad/s, no phase, no bias | -0.863 … 0.8631 |
table | Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample | -0.2189 … 0.976 |
Plotted: step — Step: 0 -> 1 at t = 1 s
Category dynamic · sample time 0.1 · 60 steps · commit ccf005c8 · produced by docsSample --out <folder> --steps 60 · data docs/generated/samples/Control_Systems__Continues__Sparse_Second_Order.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).