Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calling functions as block #3601

Open
HansOlsson opened this issue Nov 6, 2024 · 3 comments
Open

Calling functions as block #3601

HansOlsson opened this issue Nov 6, 2024 · 3 comments
Milestone

Comments

@HansOlsson
Copy link
Collaborator

HansOlsson commented Nov 6, 2024

Replying to:

Regarding blocks that can operate both in discrete-time and non-discrete-time, my claim is that the missing feature in Modelica is the ability to use a function as a block. This would both fill the gap of not having a way to express that a block in Modelica does not contain stateful dynamics, and allow us to take advantage of the variability rules for function calls when making block-oriented models.

Originally posted by @henrikt-ma in #3527 (comment)

I agree that would be useful - regardless of variability rules.

So, to get started:

The idea (to me) would be to use any function as a graphical block - without minimal or preferably no additional coding. Thus avoiding the duplication between Modelica.Blocks.Math and Modelica.Math (and similarly between Modelica.ComplexBlocks.ComplexMath and Modelica.ComplexMath). (The additional Modelica.Blocks.Sources duplication is a separate story.)

It is likely that we should turn it into an MCP; note that it is not related to MCP-0012 (but we should make sure that they don't clash too much).

First the basics:

  • A component of a (pure) function in a block or model will behave the same as a block calling that function.
  • Connections to the inputs give values for the arguments.
  • Connections to the output(s) correspond to the result(s).

Then the complicated parts:

  • Should the inputs/outputs just be normal variables, to help re-use (will need special rules to allow connections)? Or would it be better if they were connector variables (will need a rule change)?
  • Only pure functions, and no special cases for only calling at certain time-points, right? (At least at first.)
  • No mixing of the styles, right? This means that we don't allow modifiers setting inputs for these function components.
  • Note: An alternative to connecting to the inputs would be to require modifiers for inputs, but allow connections to outputs. I don't think that would be good, but just wanted to list the alternative. The benefit would be that we could easily handle more complicated expressions as inputs.
  • How do we handle arrays?

For array variables I think we can (at first) ignore connecting to specific array elements. (There's Modelica.Blocks.Routing.Multiplex for handling that).

To be concrete consider:

  function double
    input Real x[:];
    output Real y[size(x,1)];
  algorithm 
    y:=2*x;
  end double;
  double doub, doub2;
equation
  connect(src.y, doub.x);
  connect(doub.y, doub2.x);
  connect(doub2.y, mimo.u);

So,

  • How do we instantiate this when translating?
    • One alternative would be to view the function-component as syntactic sugar:
      • One variant would be to replace the connections by mimo.u=double(double(src.y));
      • A variant alternative would be to only generate code like: Real doub.y[:]=double(src.y);Real doub2.y[:]=double(doub.y);
    • Another alternative would be to have some form of size-modifier: double doub(size_x=size(src.y,1)), double doub2(size_x=size(doub.y,1)); Possibly just stored as annotation, or synthesized when instantiating. Requiring an actual size_x modifier in the function would be odd to me, both because it would be counter to just using functions and also because you would need to set a modifier - so style-mixing.
  • Is this important in the GUI? That is do we need to know the number of elements of doub2.y in the GUI?
@HansOlsson HansOlsson added this to the 2024-November milestone Nov 6, 2024
@HansOlsson
Copy link
Collaborator Author

Interested @HansOlsson @henrikt-ma @casella (in principle)
Benefits: avoid repetition and clarity
Gerd:

  • Might be impureConstant?
  • Call the function-component directly (without connections)?
  • How to handle functions such as spline/NN (large constant data+small variable).

@henrikt-ma
Copy link
Collaborator

  • Should the inputs/outputs just be normal variables, to help re-use (will need special rules to allow connections)? Or would it be better if they were connector variables (will need a rule change)?

I think requiring connector variables would be really bad for functions in general. When defining a function, I don't think one should have to think much about whether the function might be used as a block or not, so if a connector variable would be required to make the function usable as a block, it would mean that functions should always use connector variables.

At most, I think that the author of a function should have to think about placement of the inputs and outputs in the icon, but for backward compatibility we could even consider providing default placements to make all existing functions usable as blocks from start.

@henrikt-ma
Copy link
Collaborator

  • No mixing of the styles, right? This means that we don't allow modifiers setting inputs for these function components.

I don't find this obvious, as partial application could come in very handy here. Perhaps one could at least make an exception for passing constant arguments through a modifier?

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

No branches or pull requests

2 participants