97 lines
3.7 KiB
Typst
97 lines
3.7 KiB
Typst
#import "@preview/cetz:0.3.2"
|
|
#import "@preview/cetz-plot:0.1.1"
|
|
|
|
#set page(paper: "a4")
|
|
#set par(justify: true)
|
|
|
|
= Notes on hybrid system simulation
|
|
|
|
== The problem
|
|
|
|
The initial problem is _transparent assertions_. We want to simulate assertions
|
|
with their own solvers, because simulating assertions with the same solver as
|
|
the parent system changes the final results, when assertions are supposed to be
|
|
transparent.
|
|
|
|
Assertions are themselves hybrid systems, and can contain their own assertions.
|
|
We thus need a semantics that is both *independent* of the solver, which becomes
|
|
a parameter, and *recursive*, in that the simulation of an assertion is itself
|
|
the simulation of a hybrid system with assertions.
|
|
|
|
The main idea is as follows: a solver can be seen as a synchronous function (an
|
|
inner state, a step function, and a reset function).
|
|
```ocaml
|
|
type ('p, 'a, 'b) dnode = DNode :
|
|
{ s: 's; step: 's -> 'a -> 'b * 's; reset : 'p -> 's -> 's } ->
|
|
('p, 'a, 'b) dnode
|
|
```
|
|
An ODE solver is, in fact, a special case of a discrete node, which is
|
|
initialized with an initial value problem, takes as input a time horizon to
|
|
reach, and returns as output an actual time reached and a dense solution.
|
|
```ocaml
|
|
type ('y, 'yder) csolver =
|
|
(('y, 'yder) ivp, time, time * (time -> 'y)) dnode
|
|
```
|
|
Similarly, a zero-crossing solver is initialized with a zero-crossing problem,
|
|
takes as input a horizon and dense function, and returns an actual time reached
|
|
and optional zero-crossing.
|
|
```ocaml
|
|
type ('y, 'zin, 'zout) zsolver =
|
|
(('y, 'zout) zc, time * (time -> 'y), time * 'zin option) dnode
|
|
```
|
|
A complete solver is then a composition of these two: it is initialized with
|
|
both an `ivp` and `zc`, takes in a horizon, and returns an actual time reached,
|
|
dense solution and optional zero-crossing.
|
|
```ocaml
|
|
type ('y, 'yder, 'zin, 'zout) solver =
|
|
(('y, 'yder) ivp * ('y, 'zout) zc, time, time * (time -> 'y) * 'zin option) dnode
|
|
```
|
|
The construction of a full solver from an ODE and a zero-crossing solver is
|
|
available in the file `src/lib/hsim/solver.ml`.
|
|
|
|
The simulation of a hybrid system with a solver can itself be seen as a discrete
|
|
node, operating on streams of functions defined on successive intervals.
|
|
|
|
== Output format
|
|
|
|
In "lazy" mode, the output has format ```ocaml 'b signal = 'b value option```.
|
|
|
|
In "greedy" mode, the output has format ```ocaml 'b value list```.
|
|
|
|
Indeed, we cannot concatenate a discrete step (i.e. a function defined on a
|
|
singleton interval $[t,t]$) with anything else, as it may be hidden by the
|
|
(inclusive) border of the other function:
|
|
|
|
#align(center, ```ocaml
|
|
f = concat { start = 0.0; length = 1.0; u = fun t -> t }
|
|
{ start = 1.0; length = 0.0; u = fun t -> 2.0 }
|
|
```)
|
|
|
|
#columns(2, [
|
|
#align(center, cetz.canvas({
|
|
cetz-plot.plot.plot(
|
|
size: (1, 1), x-tick-step: 1, y-tick-step: 1, axis-style: "left", {
|
|
cetz-plot.plot.add(((0,0),(1,1)))
|
|
cetz-plot.plot.add(((1,2),), mark: "o", mark-size: .03)})}))
|
|
#colbreak()
|
|
#linebreak()
|
|
$ f(t) = cases(
|
|
t & "if" 0.0 <= t <= 1.0,
|
|
2.0 & "if" t = 1.0 + partial,
|
|
bot & "otherwise",
|
|
) $
|
|
])
|
|
|
|
How do we represent infinitesimal steps in floating-point numbers ?
|
|
|
|
A possible representation of the above could be
|
|
#align(center, ```ocaml
|
|
f = [{ start = 0.0; length = 1.0; u = fun t -> t };
|
|
{ start = 1.0; length = 0.0; u = fun _ -> 2.0 }]
|
|
```)
|
|
but returning a list is problematic, however, as it cannot be passed easily as
|
|
input to the underlying models. Unless the input can itself be considered as a
|
|
list, in which case the simulation simply operates over the whole list,
|
|
resetting the solver as needed. This has the advantage of not having to wait
|
|
several steps, providing nothing, until the solver is done integrating the
|
|
input, before we can provide it with another input.
|