22 struct SymbolCache{V,P,I}
33 function SymbolCache(vars, [params, [indepvars]])
44
5- A struct implementing the symbolic indexing interface for the trivial case
6- of having a vector of variables, parameters, and independent variables. This
7- struct does not implement `observed`, and `is_observed` returns `false` for
8- all input symbols. It is considered time dependent if it contains
9- at least one independent variable.
5+ A struct implementing the symbolic indexing interface for the trivial case of having a
6+ vector of variables, parameters, and independent variables. It is considered time
7+ dependent if it contains at least one independent variable. It returns `true` for
8+ `is_observed(::SymbolCache, sym)` if `sym isa Expr`. Functions can be generated using
9+ `observed` for `Expr`s involving variables in the `SymbolCache` if it has at most one
10+ independent variable.
1011
1112The independent variable may be specified as a single symbolic variable instead of an
1213array containing a single variable if the system has only one independent variable.
1314"""
1415struct SymbolCache{
1516 V <: Union{Nothing, AbstractVector} ,
1617 P <: Union{Nothing, AbstractVector} ,
17- I
18+ I,
19+ D <: Dict
1820}
1921 variables:: V
2022 parameters:: P
2123 independent_variables:: I
24+ defaults:: D
2225end
2326
24- function SymbolCache (vars = nothing , params = nothing , indepvars = nothing )
25- return SymbolCache {typeof(vars), typeof(params), typeof(indepvars)} (vars,
27+ function SymbolCache (vars = nothing , params = nothing , indepvars = nothing ;
28+ defaults = Dict {Symbol, Union{Symbol, Expr, Number}} ())
29+ return SymbolCache {typeof(vars), typeof(params), typeof(indepvars), typeof(defaults)} (
30+ vars,
2631 params,
27- indepvars)
32+ indepvars,
33+ defaults)
2834end
2935
3036function is_variable (sc:: SymbolCache , sym)
@@ -62,6 +68,45 @@ function independent_variable_symbols(sc::SymbolCache)
6268 end
6369end
6470is_observed (sc:: SymbolCache , sym) = false
71+ is_observed (:: SymbolCache , :: Expr ) = true
72+ function observed (sc:: SymbolCache , expr:: Expr )
73+ let cache = Dict {Expr, Function} ()
74+ return get! (cache, expr) do
75+ fnbody = Expr (:block )
76+ declared = Set {Symbol} ()
77+ MacroTools. postwalk (expr) do sym
78+ sym isa Symbol || return
79+ sym in declared && return
80+ if sc. variables != = nothing &&
81+ (idx = findfirst (isequal (sym), sc. variables)) != = nothing
82+ push! (fnbody. args, :($ sym = u[$ idx]))
83+ push! (declared, sym)
84+ elseif sc. parameters != = nothing &&
85+ (idx = findfirst (isequal (sym), sc. parameters)) != = nothing
86+ push! (fnbody. args, :($ sym = p[$ idx]))
87+ push! (declared, sym)
88+ elseif sym === sc. independent_variables ||
89+ sc. independent_variables isa Vector &&
90+ sym == only (sc. independent_variables)
91+ push! (fnbody. args, :($ sym = t))
92+ push! (declared, sym)
93+ end
94+ end
95+ fnexpr = if is_time_dependent (sc)
96+ :(function (u, p, t)
97+ $ fnbody
98+ return $ expr
99+ end )
100+ else
101+ :(function (u, p)
102+ $ fnbody
103+ return $ expr
104+ end )
105+ end
106+ return RuntimeGeneratedFunctions. @RuntimeGeneratedFunction (fnexpr)
107+ end
108+ end
109+ end
65110function is_time_dependent (sc:: SymbolCache )
66111 sc. independent_variables === nothing && return false
67112 if symbolic_type (sc. independent_variables) == NotSymbolic ()
@@ -75,10 +120,11 @@ all_variable_symbols(sc::SymbolCache) = variable_symbols(sc)
75120function all_symbols (sc:: SymbolCache )
76121 vcat (variable_symbols (sc), parameter_symbols (sc), independent_variable_symbols (sc))
77122end
123+ default_values (sc:: SymbolCache ) = sc. defaults
78124
79125function Base. copy (sc:: SymbolCache )
80126 return SymbolCache (sc. variables === nothing ? nothing : copy (sc. variables),
81127 sc. parameters === nothing ? nothing : copy (sc. parameters),
82128 sc. independent_variables isa AbstractArray ? copy (sc. independent_variables) :
83- sc. independent_variables)
129+ sc. independent_variables, copy (sc . defaults) )
84130end
0 commit comments