Interface Functions
Mandatory methods
SymbolicIndexingInterface.symbolic_container
— Functionsymbolic_container(p)
Using p
, return an object that implements the symbolic indexing interface. In case p
itself implements the interface, p
can be returned as-is. All symbolic indexing interface methods fall back to calling the same method on symbolic_container(p)
, so this may be used for trivial implementations of the interface that forward all calls to another object.
SymbolicIndexingInterface.is_variable
— Functionis_variable(sys, sym)
Check whether the given sym
is a variable in sys
.
SymbolicIndexingInterface.variable_index
— Functionvariable_index(sys, sym, [i])
Return the index of the given variable sym
in sys
, or nothing
otherwise. If constant_structure
is false
, this accepts the current time index as an additional parameter i
.
SymbolicIndexingInterface.variable_symbols
— Functionvariable_symbols(sys, [i])
Return a vector of the symbolic variables being solved for in the system sys
. If constant_structure(sys) == false
this accepts an additional parameter indicating the current time index. The returned vector should not be mutated.
For types that implement Base.getindex
with symbolic indices using this interface, the shorthand sys[solvedvariables]
can be used as shorthand for sys[variable_symbols(sys)]
. See: solvedvariables
.
SymbolicIndexingInterface.is_parameter
— Functionis_parameter(sys, sym)
Check whether the given sym
is a parameter in sys
.
SymbolicIndexingInterface.parameter_index
— Functionparameter_index(sys, sym)
Return the index of the given parameter sym
in sys
, or nothing
otherwise.
SymbolicIndexingInterface.parameter_symbols
— Functionparameter_symbols(sys)
Return a vector of the symbolic parameters of the given system sys
. The returned vector should not be mutated.
SymbolicIndexingInterface.is_independent_variable
— Functionis_independent_variable(sys, sym)
Check whether the given sym
is an independent variable in sys
. The returned vector should not be mutated.
SymbolicIndexingInterface.independent_variable_symbols
— Functionindependent_variable_symbols(sys)
Return a vector of the symbolic independent variables of the given system sys
.
SymbolicIndexingInterface.is_observed
— Functionis_observed(sys, sym)
Check whether the given sym
is an observed value in sys
.
SymbolicIndexingInterface.is_time_dependent
— Functionis_time_dependent(sys)
Check if sys
has time as (one of) its independent variables.
SymbolicIndexingInterface.constant_structure
— Functionconstant_structure(sys)
Check if sys
has a constant structure. Constant structure systems do not change the number of variables or parameters over time.
SymbolicIndexingInterface.all_variable_symbols
— Functionall_variable_symbols(sys)
Return a vector of variable symbols in the system, including observed quantities.
For types that implement Base.getindex
with symbolic indices using this interface, The shorthand sys[allvariables]
can be used as shorthand for sys[all_variable_symbols(sys)]
. See: allvariables
.
SymbolicIndexingInterface.all_symbols
— Functionall_symbols(sys)
Return an array of all symbols in the system. This includes parameters and independent variables.
SymbolicIndexingInterface.solvedvariables
— Constantconst solvedvariables = SolvedVariables()
This singleton is used as a shortcut to allow indexing of all solution variables (excluding observed quantities). It has a symbolic_type
of ScalarSymbolic
. See: variable_symbols
.
SymbolicIndexingInterface.allvariables
— Constantconst allvariables = AllVariables()
This singleton is used as a shortcut to allow indexing of all solution variables (including observed quantities). It has a symbolic_type
of ScalarSymbolic
. See all_variable_symbols
.
Optional Methods
Observed equation handling
SymbolicIndexingInterface.observed
— Functionobserved(sys, sym, [states])
Return the observed function of the given sym
in sys
. The returned function should have the signature (u, p) -> [values...]
where u
and p
is the current state and parameter vector, respectively. If istimedependent(sys) == true
, the function should accept the current time t
as its third parameter. If constant_structure(sys) == false
, accept a third parameter, which can either be a vector of symbols indicating the order of states or a time index, which identifies the order of states. This function does not need to be defined if is_observed
always returns false
. Thus, it is mandatory to always check is_observed
before using this function.
See also: is_time_dependent
, constant_structure
Parameter indexing
SymbolicIndexingInterface.parameter_values
— Functionparameter_values(p)
-parameter_values(p, i)
Return an indexable collection containing the value of each parameter in p
. The two- argument version of this function returns the parameter value at index i
. The two-argument version of this function will default to returning parameter_values(p)[i]
.
If this function is called with an AbstractArray
, it will return the same array.
SymbolicIndexingInterface.set_parameter!
— Functionset_parameter!(sys, val, idx)
Set the parameter at index idx
to val
for system sys
. This defaults to modifying parameter_values(sys)
. If any additional bookkeeping needs to be performed or the default implementation does not work for a particular type, this method needs to be defined to enable the proper functioning of setp
.
See: parameter_values
SymbolicIndexingInterface.getp
— Functiongetp(sys, p)
Return a function that takes an array representing the parameter vector or an integrator or solution of sys
, and returns the value of the parameter p
. Note that p
can be a direct index or a symbolic value, or an array/tuple of the aforementioned.
Requires that the integrator or solution implement parameter_values
. This function typically does not need to be implemented, and has a default implementation relying on parameter_values
.
SymbolicIndexingInterface.setp
— Functionsetp(sys, p)
Return a function that takes an array representing the parameter vector or an integrator or problem of sys
, and a value, and sets the parameter p
to that value. Note that p
can be a direct index or a symbolic value.
Requires that the integrator implement parameter_values
and the returned collection be a mutable reference to the parameter vector in the integrator. In case parameter_values
cannot return such a mutable reference, or additional actions need to be performed when updating parameters, set_parameter!
must be implemented.
SymbolicIndexingInterface.ParameterIndexingProxy
— Typestruct ParameterIndexingProxy
This struct wraps any struct implementing the symbolic indexing interface. It allows getindex
and setindex!
operations to get/set parameter values. Requires that the wrapped type support getp
and setp
for getting and setting parameter values respectively.
State indexing
SymbolicIndexingInterface.Timeseries
— Typestruct Timeseries <: IsTimeseriesTrait end
Trait indicating a type contains timeseries data. This affects the behaviour of functions such as state_values
and current_time
.
See also: NotTimeseries
, is_timeseries
SymbolicIndexingInterface.NotTimeseries
— Typestruct NotTimeseries <: IsTimeseriesTrait end
Trait indicating a type does not contain timeseries data. This affects the behaviour of functions such as state_values
and current_time
. Note that if a type is NotTimeseries
this only implies that it does not store timeseries data. It may still be time-dependent. For example, an ODEProblem
only stores the initial state of a system, so it is NotTimeseries
, but still time-dependent. This is the default trait variant for all types.
See also: Timeseries
, is_timeseries
SymbolicIndexingInterface.is_timeseries
— Functionis_timeseries(x) = is_timeseries(typeof(x))
-is_timeseries(::Type)
Get the timeseries trait of a type. Defaults to NotTimeseries
for all types.
See also: Timeseries
, NotTimeseries
SymbolicIndexingInterface.state_values
— Functionstate_values(p)
-state_values(p, i)
Return an indexable collection containing the values of all states in the integrator or problem p
. If is_timeseries(p)
is Timeseries
, return a vector of arrays, each of which contain the state values at the corresponding timestep. In this case, the two-argument version of the function can also be implemented to efficiently return the state values at timestep i
. By default, the two-argument method calls state_values(p)[i]
If this function is called with an AbstractArray
, it will return the same array.
See: is_timeseries
SymbolicIndexingInterface.set_state!
— Functionset_state!(sys, val, idx)
Set the state at index idx
to val
for system sys
. This defaults to modifying state_values(sys)
. If any additional bookkeeping needs to be performed or the default implementation does not work for a particular type, this method needs to be defined to enable the proper functioning of setu
.
See: state_values
SymbolicIndexingInterface.current_time
— Functioncurrent_time(p)
-current_time(p, i)
Return the current time in the integrator or problem p
. If is_timeseries(p)
is Timeseries
, return the vector of timesteps at which the state value is saved. In this case, the two-argument version of the function can also be implemented to efficiently return the time at timestep i
. By default, the two- argument method calls current_time(p)[i]
See: is_timeseries
SymbolicIndexingInterface.getu
— Functiongetu(sys, sym)
Return a function that takes an integrator, problem or solution of sys
, and returns the value of the symbolic sym
. If sym
is not an observed quantity, the returned function can also directly be called with an array of values representing the state vector. sym
can be a direct index into the state vector, a symbolic state, a symbolic expression involving symbolic quantities in the system sys
, a parameter symbol, or the independent variable symbol, or an array/tuple of the aforementioned. If the returned function is called with a timeseries object, it can also be given a second argument representing the index at which to find the value of sym
.
At minimum, this requires that the integrator, problem or solution implement state_values
. To support symbolic expressions, the integrator or problem must implement observed
, parameter_values
and current_time
.
This function typically does not need to be implemented, and has a default implementation relying on the above functions.
SymbolicIndexingInterface.setu
— Functionsetu(sys, sym)
Return a function that takes an array representing the state vector or an integrator or problem of sys
, and a value, and sets the the state sym
to that value. Note that sym
can be a direct index, a symbolic state, or an array/tuple of the aforementioned.
Requires that the integrator implement state_values
and the returned collection be a mutable reference to the state vector in the integrator/problem. Alternatively, if this is not possible or additional actions need to be performed when updating state, set_state!
can be defined. This function does not work on types for which is_timeseries
is Timeseries
.
Symbolic Trait
SymbolicIndexingInterface.ScalarSymbolic
— Typestruct ScalarSymbolic <: SymbolicTypeTrait end
Trait indicating a type is a scalar symbolic variable.
See also: ArraySymbolic
, NotSymbolic
, symbolic_type
SymbolicIndexingInterface.ArraySymbolic
— Typestruct ArraySymbolic <: SymbolicTypeTrait end
Trait indicating type is a symbolic array. Calling collect
on a symbolic array must return an AbstractArray
containing ScalarSymbolic
variables for each element in the array, in the same shape as the represented array. For example, if a
is a symbolic array representing a 2x2 matrix, collect(a)
must return a 2x2 array of scalar symbolic variables.
See also: ScalarSymbolic
, NotSymbolic
, symbolic_type
SymbolicIndexingInterface.NotSymbolic
— Typestruct NotSymbolic <: SymbolicTypeTrait end
Trait indicating a type is not symbolic.
See also: ScalarSymbolic
, ArraySymbolic
, symbolic_type
SymbolicIndexingInterface.symbolic_type
— Functionsymbolic_type(x) = symbolic_type(typeof(x))
-symbolic_type(::Type)
Get the symbolic type trait of a type. Default to NotSymbolic
for all types except Symbol
and Expr
, both of which are ScalarSymbolic
.
See also: ScalarSymbolic
, ArraySymbolic
, NotSymbolic
SymbolicIndexingInterface.hasname
— Functionhasname(x)
Check whether the given symbolic variable (for which symbolic_type(x) != NotSymbolic()
) has a valid name as per getname
.
SymbolicIndexingInterface.getname
— Functiongetname(x)::Symbol
Get the name of a symbolic variable as a Symbol
Types
SymbolicIndexingInterface.SymbolCache
— Typestruct SymbolCache{V,P,I}
-function SymbolCache(vars, [params, [indepvars]])
A struct implementing the symbolic indexing interface for the trivial case of having a vector of variables, parameters, and independent variables. This struct does not implement observed
, and is_observed
returns false
for all input symbols. It is considered time dependent if it contains at least one independent variable.
The independent variable may be specified as a single symbolic variable instead of an array containing a single variable if the system has only one independent variable.