Use ControlSystemIdentification.jl for a ModelingToolkit.jl model

Hi,

I have an LTI model defined in ModelingToolkit.jl:

@named T_a_out = TimeVaryingFunction(input_funcs[:T_a])
@named Φ_hp_out = TimeVaryingFunction(input_funcs[:Φ_hp])
@named Φ_cv_out = TimeVaryingFunction(input_funcs[:Φ_cv])
@named Φ_s_out = TimeVaryingFunction(input_funcs[:Φ_s])

vars = @variables T_i(t) T_e(t) T_h(t) T_a(t) Φ_hp(t) Φ_cv(t) Φ_s(t)
pars = @parameters C_i = params[:C_i] C_e = params[:C_e] C_h = params[:C_h] R_ie = params[:R_ie] R_ea = params[:R_ea] R_ih = params[:R_ih] A_w = params[:A_w] A_e = params[:A_e]

eqs = [
    # inputs
    T_a ~ T_a_out.output.u
    Φ_hp ~ Φ_hp_out.output.u
    Φ_cv ~ Φ_cv_out.output.u
    Φ_s ~ Φ_s_out.output.u

    # dynamics
    C_i * D(T_i) ~ A_w * Φ_s + (T_h - T_i) * R_ih + (T_e - T_i) * R_ie
    C_e * D(T_e) ~ A_e * Φ_s + (T_a - T_e) * R_ea + (T_i - T_e) * R_ie
    C_h * D(T_h) ~ Φ_cv + Φ_hp + (T_i - T_h) * R_ih
]

ODESystem(eqs, t, vars, pars; systems=[T_a_out, Φ_hp_out, Φ_cv_out, Φ_s_out], name)

Now I’m trying to estimate the parameters of this model using ControlSystemIdentification.jl.

Is there a guide on how to do this? I assume I need some glue code from ControlSystemsMTK.jl, but has anyone worked this out?

I have done this a few times, but never published the glue code. The pieces you need are

  • ModelingToolkit.generate_control_function to generate a function that computes \dot x = f(x, u, p, t) where x is the state and $u$$ is some external input (if present). In your case, I would remove the TimeVaryingFunction and instead treat those as external inputs (if I understand your use case correctly).
  • SeeToDee.jl to discretize the function f from above.
  • Call nonlinear_pem with the discretized dynamics function returned by SeeToDee.jl

Ah, if you have an LTI model, you can call named_ss from ContorlSystemsMTK or ModelingToolkit.linearize_symbolic to obtain the statespace matrices A,B,C,D, you can then make use of structured_pem to estimate the parameters. You’d need to write some glue code yourself in this case, this special-case pipeline of an LTI model from MTK hasn’t been explored yet.

You find some relevant utilities here, in particular the symbolic linearization and code generation that would give you the constructor function you need for structured_pem.

Okay thanks, unfortunately I don’t have the skills to get that working yet. I thought this would be a very common usecase.

You can use the utilities to estimate a generic nonlinear model, it will not be as performant as if the linearity was exploited, but it will get the job done. Here’s a fully working example.

Not really, MTK is a tool for generic, nonlinear acausal modeling. As such, it can of course model simple LTI systems, but there is not much infrastructure in place to handle this special case any different from a fully generic nonlinear model.

If the model you have shown above is the full extent of your system, I would consider MTK a bit overkill and instead use something more minimal, e.g.

  • OrdinaryDiffEq.jl directly
  • SeeToDee.jl
  • ControlSystems.jl

The last two options would be much easier to interface with ControlSystemIdentification.

Your model as you have shown it does not make any use of things like model components, connections, algebraic equations, and for such simple system I think MTK complicates things rather than simplifies. If your end goal is a much bigger model, MTK may of course still make sense.

Thanks, I’m trying to see if I can get structured_pem working. Is there any example or docs on how to setup the state-space model for constructor? I wasn’t able to find anything in the docs

Here’s an example