Skip to content

Commit ed2bab5

Browse files
author
dd
committed
documentation added
1 parent 7620bdd commit ed2bab5

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed

docs/src/basics/Composition.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,3 +337,84 @@ plot(sol(tv)[y], sol(tv)[x], line_z=tv)
337337
vline!([-1.5, 1.5], l=(:black, 5), primary=false)
338338
hline!([0], l=(:black, 5), primary=false)
339339
```
340+
341+
### Generalized affect support
342+
In some instances, a more flexible response to events is needed, which cannot be encapsulated by
343+
an equation. For example, a component may implement complex behavior that it is inconvenient or
344+
impossible to capture in equations.
345+
346+
ModelingToolkit therefore supports Julia functions as affects: instead of an equation, an affect is
347+
defined as a `tuple`:
348+
```
349+
[x ~ 0] => (affect!, [v, x], [p, q], ctx)
350+
```
351+
352+
where, `affect!` is a Julia function with the signature: `affect!(integ, u, p, ctx)`; `[u,v]` and `[p,q]`
353+
are the states (variables) and parameters that are accessed by `affect!`, respectively; and `ctx` is a
354+
context that is passed to `affect!` as the `ctx` argument.
355+
356+
`affect!` receives the `DiffEqs` integrator as its first argument, which can then be used to access states
357+
and parameters that are provided in the `u` and `p` arguments (implemented as `NamedTuple`s):
358+
359+
```
360+
function affect!(integ, u, v, ctx)
361+
# integ.t is the current time
362+
# integ.u[u.v] is the value of the state `v` above
363+
# integ.p[p.q] is the value of the parameter `q` above
364+
end
365+
```
366+
367+
When accessing variables of a sub-system, it could be useful to rename them (alternatively, an affect function
368+
may be reused in different contexts):
369+
```
370+
[x ~ 0] => (affect!, [resistor₊v => :v, x], [p, q => :p2], ctx)
371+
```
372+
373+
Here, `resistor₊v` is passed as `v` while `q` has been renamed `p2`.
374+
375+
As an example, here is the bouncing ball example from `DiffEqs` using ModelingToolkit:
376+
377+
```@example events
378+
sts = @variables y(t), v(t)
379+
par = @parameters g = 9.8
380+
bb_eqs = [D(y) ~ v
381+
D(v) ~ -g]
382+
383+
function bb_affect!(integ, u, p, ctx)
384+
integ.u[u.v] = -integ.u[u.v]
385+
end
386+
387+
@named bb_model = ODESystem(bb_eqs, t, sts, par,
388+
continuous_events = [[y ~ 0] => (bb_affect!, [v], [], nothing)])
389+
390+
bb_sys = structural_simplify(bb_model)
391+
u0 = [v => 0.0, y => 50.0]
392+
393+
bb_prob = ODEProblem(bb_sys, u0, (0, 15.0))
394+
bb_sol = solve(bb_prob, Tsit5())
395+
396+
plot(bb_sol)
397+
```
398+
399+
### Discrete events support
400+
In addition to continuous events, discrete events are also supported.
401+
402+
TBD
403+
404+
Two important sub-classes of discrete events are periodic and set-time events. A periodic event is triggered at
405+
fixed intervals (e.g. every Δt seconds). To specify a periodic interval, pass the interval as the condition for
406+
the event:
407+
408+
```
409+
discrete_events=[1.0 => [v ~ -v]]
410+
```
411+
412+
will change the sign of `v` at t=1.0, 2.0, ...
413+
414+
Alternatively, the event may be triggered at specific set times:
415+
```
416+
discrete_events=[[1.0, 4.0] => [v ~ -v]]
417+
```
418+
419+
will change the sign of `v` *only* at t=1.0, 4.0.
420+

0 commit comments

Comments
 (0)