Skip to content

Commit a571774

Browse files
docs: add documentation for assertions functionality
1 parent edfad23 commit a571774

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

docs/src/basics/Debugging.md

+17
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,23 @@ dsol = solve(dprob, Tsit5());
3535
Now we see that it crashed because `u1` decreased so much that it became negative and outside the domain of the `` function.
3636
We could have figured that out ourselves, but it is not always so obvious for more complex models.
3737

38+
Suppose we also want to validate that `u1 + u2 >= 2.0`. We can do this via the assertions functionality.
39+
40+
```@example debug
41+
@mtkbuild sys = ODESystem(eqs, t; defaults, assertions = [(u1 + u2 >= 2.0) => "Oh no!"])
42+
```
43+
44+
The assertions must be an iterable of pairs, where the first element is the symbolic condition and
45+
the second is the message to be logged when the condition fails.
46+
47+
```@repl debug
48+
dsys = debug_system(sys; functions = []);
49+
dprob = ODEProblem(dsys, [], (0.0, 10.0));
50+
dsol = solve(dprob, Tsit5());
51+
```
52+
53+
Note the messages containing the failed assertion and corresponding message.
54+
3855
```@docs
3956
debug_system
4057
```

src/debugging.jl

+18-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ function debug_sub(ex, funcs; kw...)
4343
maketerm(typeof(ex), f, args, metadata(ex))
4444
end
4545

46+
"""
47+
$(TYPEDSIGNATURES)
48+
49+
A function which takes a condition `expr` and returns `NaN` if it is false,
50+
and zero if it is true. In case the condition is false and `log == true`,
51+
`message` will be logged as an `@error`.
52+
"""
4653
function _debug_assertion(expr::Bool, message::String, log::Bool)
4754
expr && return 0.0
4855
log && @error message
@@ -51,9 +58,19 @@ end
5158

5259
@register_symbolic _debug_assertion(expr::Bool, message::String, log::Bool)
5360

61+
"""
62+
Boolean parameter added to models returned from `debug_system` to control logging of
63+
assertions.
64+
"""
5465
const ASSERTION_LOG_VARIABLE = only(@parameters __log_assertions_ₘₜₖ::Bool = false)
5566

56-
function get_assertions_expr(assertions::Dict{BasicSymbolic, String})
67+
"""
68+
$(TYPEDSIGNATURES)
69+
70+
Get a symbolic expression as per the requirement of `debug_system` for all the assertions
71+
in `assertions`. `is_split` denotes whether the corresponding system is a split system.
72+
"""
73+
function get_assertions_expr(assertions::Dict{BasicSymbolic, String}, is_split::Bool)
5774
term = 0
5875
for (k, v) in assertions
5976
term += _debug_assertion(k, "Assertion $k failed:\n$v", ASSERTION_LOG_VARIABLE)

src/systems/abstractsystem.jl

+8
Original file line numberDiff line numberDiff line change
@@ -2297,6 +2297,14 @@ ERROR: Function /(1, sin(P(t))) output non-finite value Inf with input
22972297
1 => 1
22982298
sin(P(t)) => 0.0
22992299
```
2300+
2301+
Additionally, all assertions in the system are validated in the equations. If any of
2302+
the conditions are false, the right hand side of at least one of the equations of
2303+
the system will evaluate to `NaN`. A new parameter is also added to the system which
2304+
controls whether the message associated with each assertion will be logged when the
2305+
assertion fails. This parameter defaults to `true` and can be toggled by
2306+
symbolic indexing with `ModelingToolkit.ASSERTION_LOG_VARIABLE`. For example,
2307+
`prob.ps[ModelingToolkit.ASSERTION_LOG_VARIABLE] = false` will disable logging.
23002308
"""
23012309
function debug_system(
23022310
sys::AbstractSystem; functions = [log, sqrt, (^), /, inv, asin, acos], kw...)

0 commit comments

Comments
 (0)