Skip to content

Conversation

@cstjean
Copy link
Contributor

@cstjean cstjean commented Nov 21, 2025

This PR rewrites the @components parsing and model construction logic. Instead of parsing the RHS of each equation in the @components block, it evaluates it normally as plain julia code. Because the new code is a lot simpler, it was relatively easy to improve the flexibility of the model construction interface (see below) along the lines of #3791

There's still a lot of work to do, so I'd like to get some feedback before pushing forward (... or giving up). Is that a reasonable direction to take?

The good

  • Net reduction in model-parsing code {3FF2A5A2-A748-4C2F-B166-13A135C030A7}
  • Can now change structural parameters with __ syntax: @mtkcompile my_model = MyModel(sub_component__N=10)
  • Can now change subcomponents with __ syntax: @mtkcompile my_model = MyModel(sub_component__subsub_component=MyAlternativeComponent()). I believe this fixes Replacing subsystems #2038.
  • No parsing on the RHS of the components means that the RHS can be arbitrary Julia code, which is a lot more intuitive and general. For example,
    my_interpolation = LinearInterpolation(df.data, df.time)
    @mtkmodel MassSpringDamperSystem2 begin
        @components begin
            src = Interpolation(itp=my_interpolation)
    can now be
    @mtkmodel MassSpringDamperSystem2 begin
        @components begin
            src = Interpolation(LinearInterpolation, df.data, df.time)
  • This also supports heterogeneous arrays, as in resistors = [FixedResistor(), VariableResistor()].
  • Nested if blocks now work inside of @components

The bad

Model metadata for components @test A.structure[:components] == [[:cc, :C]] now yields [[:cc, :unimplemented]]. (But System metadata is fine). How bad is that? Where is that information used? Maybe Dyad?

Potential workaround: bring back #master's parsing code just for metadata parsing. Maybe if I strip that code of everything except the metadata part, it would be reasonably small, and we can give up on more complex cases (that aren't supported ATM anyway)?

The ugly

To support plant__component__subcomponent => AlternativeComponent(), I used ScopedValues to thread those parameters. I believe that it's broadly fine, but there might be edge cases I haven't thought about.

TODO

If this PR looks appealing, then the remaining items would be

  • Clean up, comment
  • Conform to the style guide
  • Validate kwarg names (at the moment misspelled constructor kwargs are ignored)
  • Squash, or redo the commit history
  • Figure out a solution for the commented out tests (from add test for passing params as structural params #3995)
  • Test against ModelingToolkitStandardLibrary
  • More tests

Let me know what you think! If this is too disruptive, I can tackle another direction. Most of these features can be implemented without getting rid of the RHS parsing code, but it's a lot more work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Replacing subsystems

1 participant