ModelingToolkit - component defaults

I have some background with Modelica, where the specification and modification of defaults is relatively simple. From the ModelingToolkit documentation [p. 2 of ModelingToolkit.jl documentation]:

Often it is a good idea to specify reasonable values for the initial state and the parameters of a model component. Then, these do not have to be explicitly specified when constructing the ODEProblem.

function unitstep_fol_factory(;name)
    @parameters τ
    @variables t x(t)
    ODESystem(D(x) ~ (1 - x)/τ; name, defaults=Dict(x=>0.0, τ=>1.0))
end

ODEProblem(unitstep_fol_factory(name=:fol),[],(0.0,5.0),[]) |> solve

If I don’t specify defaults, initial values and parameters are specified by (separate) arrays of pairs, e.g., [x => 0], [tau => 1.0]. But for defaults, it seems like the default initial values and parameters are specified in a single dictionary.

OK – not a big problem [although somewhat unsystematic?]

Question 1: if I specify defaults, do I need to specify defaults for all states and parameters, or is it possible to specify defaults for a subset? [And… if the system is not in state space form but needs to be “reduced” to state space form by index reduction, etc. – how can I know how many states there are? Normally, I’d have to do structural_simplify first to see the names of the states??]

Question 2: how do I specify parameters that differ from default values? I don’t want to specify all parameters, but just those that are different.

  • Do I simply add parameters or initial values that differ from the defaults?
  • Or do I need to specify the complete set of values? [Which would reduce the advantage of specifying defaults.]

In other words, if the defaults are as follows (assume different system, but same name as example above…):

..., defaults = Dict(x => 0, y => 1.0, a => 3.0, b => 2.0))

and I want to change initial value of y and parameter value of a (but keep the defaults of x and b), I do:

u0 = [y => -1.0]
p = [a => 2.5]

ODEProblem(unitstep_fol_factory(name=:fol),u0,(0.0,5.0),p) |> solve

Or is there another way to do it?

I think we want all people to be putting it on the symbols, but defaults was exposed from earlier versions. We need to figure out whether it should stay public API exposed.

I think these go hand-in-hand. If you specify a subset, then at construction time you need to specify the values or you will get an error. For example, if your components are missing a parameter r, then at construction time you’ll be told component1.r and component2.r are not defined etc. (that’s not the exact error message, but it’ll point it out like that). And then you need to do:

ODEProblem(unitstep_fol_factory(name=:fol),[],(0.0,5.0),[component1.r => 2.0, component2.r => 3.0])

to fill in the missing values. So basically, you only need to know values at numerical problem construction time, but at numerical problem construction time you do need to make sure that a whole consistent set of u0 and p are given, otherwise it will error and tell you which values are missing.

I think the docs are a little confusing here because it’s still a little in flux. I think that in general a u0 and p map are not both needed, so this should probably just be:

@named fol = unitstep_fol_factory()
ODEProblem(fol,[component1.r => 2.0, component2.r => 3.0],(0.0,5.0))

What’s a state vs parameter vs observed variable is is kind of an internal solver detail since structural_simplify can change the designation on variables as is required for performance. It’s probably about time to clean that up.

2 Likes

I agree that it may not be necessary to differentiate between initial states and parameters [as long as “parameter” is well defined as a model “constant”] - both may be considered unknowns during model fitting.

  • Still, for model fitting, it may be of interest to only compute subsets of initial states (e.g., observable states) and parameters (e.g., identifiable parameters).

To make things clearer, it would also be useful if documentation and (new) examples/presentations made a clear distinction between variables and parameters.

  • Are time and space variables (t, x) parameters or variables?
  • Quite a few presentations float around stating, e.g., @parameters t, x, a and then @variables u(t,x). But time t and space x are not constants, so passing on these in, e.g., parameter estimation is meaningsless.
  • This “confusion” may stem from phrases like describing PDEs as “distributed parameter” systems.
  • In other fields, t and x are described as independent variables.
  • I think it would clarify MTK documentation if t and x (temporal and spatial position) are defined as (independent) variables, while “parameter” is reserved for constants.
  • Thus, the above example should then be @parameters a and @variables t, x, u(t,x)

That doesn’t really matter. We generally just make them variables. We call them independent variables in the MTK docs, @parameters a and @variables t, x, u(t,x) is what it should be, and anything that doesn’t match that needs a docs update.

1 Like

Yeah, I guess it works both ways. But I agree on your current choice that the independent variables are variables. (Nothing to do with past presentations :-o ).