You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The function `f` will be called with `observed` and `modified` `NamedTuple`s that are derived from their respective `NamedTuple` definitions.
88
-
Each declaration`NamedTuple` should map an expression to a symbol; for example if we pass `observed=(; x = a + b)` this will alias the result of executing `a+b` in the system as `x`
89
-
so the value of `a + b` will be accessible as `observed.x` in `f`. `modified` currently restricts symbolic expressions to only bare variables, so only tuples of the form
90
-
`(; x = y)` or `(; x)` (which aliases `x` as itself) are allowed.
91
-
92
-
The argument NamedTuples (for instance `(;x=y)`) will be populated with the declared values on function entry; if we require `(;x=y)` in `observed` and `y=2`, for example,
93
-
then the NamedTuple `(;x=2)` will be passed as `observed` to the affect function `f`.
94
-
95
-
The NamedTuple returned from `f` includes the values to be written back to the system after `f` returns. For example, if we want to update the value of `x` to be the result of `x + y` we could write
96
-
97
-
ImperativeAffect(observed=(; x_plus_y = x + y), modified=(; x)) do m, o
98
-
@set! m.x = o.x_plus_y
99
-
end
100
-
101
-
Where we use Setfield to copy the tuple `m` with a new value for `x`, then return the modified value of `m`. All values updated by the tuple must have names originally declared in
102
-
`modified`; a runtime error will be produced if a value is written that does not appear in `modified`. The user can dynamically decide not to write a value back by not including it
103
-
in the returned tuple, in which case the associated field will not be updated.
(affects(cb) isa FunctionalAffect ||affects(cb) isa ImperativeAffect)
183
78
end
@@ -203,13 +98,13 @@ sharp discontinuity between integrator steps (which in this example would not no
203
98
guaranteed to be triggered.
204
99
205
100
Once detected the integrator will "wind back" through a root-finding process to identify the point when the condition became active; the method used
206
-
is specified by `rootfind` from [`SciMLBase.RootfindOpt`](@ref). If we denote the time when the condition becomes active at tc,
101
+
is specified by `rootfind` from [`SciMLBase.RootfindOpt`](@ref). If we denote the time when the condition becomes active as `tc``,
207
102
the value in the integrator after windback will be:
208
103
* `u[tc-epsilon], p[tc-epsilon], tc` if `LeftRootFind` is used,
209
104
* `u[tc+epsilon], p[tc+epsilon], tc` if `RightRootFind` is used,
210
105
* or `u[t], p[t], t` if `NoRootFind` is used.
211
106
For example, if we want to detect when an unknown variable `x` satisfies `x > 0` using the condition `x ~ 0` on a positive edge (that is, `D(x) > 0`),
212
-
then left root finding will get us `x=-epsilon`, right root finding `x=epsilon` and no root finding whatever the next step of the integrator was after
107
+
then left root finding will get us `x=-epsilon`, right root finding `x=epsilon` and no root finding will produce whatever the next step of the integrator was after
213
108
it passed through 0.
214
109
215
110
Multiple callbacks in the same system with different `rootfind` operations will be grouped
@@ -405,7 +300,6 @@ end
405
300
406
301
namespace_affects(af::Vector, s) = Equation[namespace_affect(a, s) for a in af]
@warn"Expression $(expr) is aliased as $sym, which has already been used. The first definition will be used."
1121
-
end
1122
-
end
1123
-
return (syms_dedup, exprs_dedup)
1124
-
end
1125
-
1126
-
obs_exprs =observed(affect)
1127
-
if!affect.skip_checks
1128
-
for oexpr in obs_exprs
1129
-
invalid_vars =invalid_variables(sys, oexpr)
1130
-
iflength(invalid_vars) >0
1131
-
error("Observed equation $(oexpr) in affect refers to missing variable(s) $(invalid_vars); the variables may not have been added (e.g. if a component is missing).")
@warn ("Expression $mexpr cannot be assigned to; currently only unknowns and parameters may be updated by an affect.")
1143
-
end
1144
-
invalid_vars =unassignable_variables(sys, mexpr)
1145
-
iflength(invalid_vars) >0
1146
-
error("Modified equation $(mexpr) in affect refers to missing variable(s) $(invalid_vars); the variables may not have been added (e.g. if a component is missing) or they may have been reduced away.")
@warn"The symbols $overlapping_syms are declared as both observed and modified; this is a code smell because it becomes easy to confuse them and assign/not assign a value."
1156
-
end
1157
-
1158
-
# sanity checks done! now build the data and update function for observed values
1159
-
mkzero(sz) =
1160
-
if sz === ()
1161
-
0.0
1162
-
else
1163
-
zeros(sz)
1164
-
end
1165
-
obs_fun =build_explicit_observed_function(
1166
-
sys, Symbolics.scalarize.(obs_exprs);
1167
-
array_type = Tuple)
1168
-
obs_sym_tuple = (obs_syms...,)
1169
-
1170
-
# okay so now to generate the stuff to assign it back into the system
0 commit comments