Numerical Computing & Controls

MATLAB and Simulink — matrices, signals, block diagrams, and time-domain simulation.

Linear Algebra
NEW MATRIX ROWS 3 COLS 3 SET ?a
AFTER MATRIX ?a SET CELL 1,1 AS 2
AFTER MATRIX ?a SET CELL 1,2 AS 1
AFTER MATRIX ?a SET CELL 2,1 AS 1
AFTER MATRIX ?a SET CELL 2,2 AS 3

AFTER MATRIX ?a INVERSE SET ?inv
AFTER MATRIX ?a EIGENVALUES SET ?vals
AFTER MATRIX ?a TRANSPOSE SET ?t

NEW MATRIX ROWS 3 COLS 1 SET ?b
AFTER MATRIX SOLVE ?a WITH ?b SET ?x
Signal Processing
NEW SIGNAL FROM ARRAY ?data SAMPLERATE 44100 SET ?sig
AFTER SIGNAL ?sig FFT SET ?spectrum
AFTER SIGNAL ?sig FILTER "lowpass" CUTOFF 5000 SET ?filtered
PID Controller — Block Diagram
(* Coefficients are arrays, built the ordinary way *) NEW ARRAY SET ?num AFTER APPEND 1 TO ?num AFTER NEW ARRAY SET ?den AFTER APPEND 1 TO ?den AFTER APPEND 2 TO ?den AFTER APPEND 1 TO ?den (* Each ADD grows the model, so the model is reassigned. Blocks are numbered in the order they were added: 0, 1, 2, 3. *) AFTER NEW BLOCK DIAGRAM SET ?model AFTER BLOCK ?model ADD "step_input" VALUE 100 AT TIME 0 SET ?model AFTER BLOCK ?model ADD "sum" SIGNS 1,-1 SET ?model AFTER BLOCK ?model ADD "pid_controller" P 2.0 I 0.5 D 0.1 SET ?model AFTER BLOCK ?model ADD "transfer_function" NUMERATOR ?num DENOMINATOR ?den SET ?model AFTER BLOCK ?model CONNECT 0 TO 1 SET ?model AFTER BLOCK ?model CONNECT 1 TO 2 SET ?model AFTER BLOCK ?model CONNECT 2 TO 3 SET ?model AFTER BLOCK ?model CONNECT 3 TO 1 SET ?model AFTER BLOCK ?model SIMULATE DURATION 20 STEP 0.005 SET ?trace AFTER EMIT ?trace("final") AFTER BLOCK ?trace PLOT 3 SET ?svg
State Space and Stability
(* The poles of a denominator: a positive one means the system runs away *)
NEW ARRAY SET ?den
AFTER APPEND 1 TO ?den
AFTER APPEND 3 TO ?den
AFTER APPEND 2 TO ?den
AFTER BLOCK ?den STABILITY POLES SET ?poles
AFTER EMIT ?poles
(* -2, -1 — both negative, so it settles *)

Saving and Reopening

A block diagram, a matrix and a signal are all values, so all three persist the same way — SAVE INTO writes native OcaltQL source text, OPEN reads it back. A model built once is reusable by every later script, and a saved trace can be replotted without re-simulating.

A Reusable Control Model
NEW BLOCK DIAGRAM SET ?model
AFTER BLOCK ?model ADD "pid_controller" P 2.0 I 0.5 D 0.1 SET ?controller
AFTER BLOCK ?model SAVE INTO "/root/models/pid.oql" SET ?path

(* ...any later script... *)

BLOCK OPEN "/root/models/pid.oql" SET ?model
AFTER BLOCK ?model SIMULATE DURATION 10 STEP 0.01 SET PROMISE ?run
AFTER WAIT FOR ?run SET ?trace
AFTER BLOCK ?trace SAVE INTO "/root/models/pid-trace.oql" SET ?tracepath
Matrices and Signals
NEW MATRIX ROWS 3 COLS 3 SET ?a
AFTER MATRIX ?a SET CELL 1,1 AS 2
AFTER MATRIX ?a SAVE INTO "/root/data/stiffness.oql" SET ?path
AFTER MATRIX OPEN "/root/data/stiffness.oql" SET ?a2

AFTER NEW SIGNAL FROM ARRAY ?data SAMPLERATE 44100 SET ?sig
AFTER SIGNAL ?sig SAVE INTO "/root/data/capture.oql" SET ?sigpath
AFTER SIGNAL OPEN "/root/data/capture.oql" SET ?sig2
AFTER SIGNAL ?sig2 FFT SET ?spectrum
SAVE without INTO writes back to the path the value was opened from, exactly as it does for every other domain. A value built with NEW has no source path, so its first write must be SAVE INTO.