Search code examples
annotationsmodelicainversedymolaopenmodelica

Modelica annotation inverse of function is ignored


Problem: the inverse annotation of a function is ignored and the inverse is computed numerically.

According to Modelica Specifications it is possible to specify an inverse of a given function.

In order to test this functionallity I tried with a very trivial model with two functions:

  • the direct function y(x) = sin(x)
    function y_from_x
      input Real x;
      output Real y;
    algorithm
      y:=sin(x);
      annotation(inverse(x = x_from_y(y)));
    end y_from_x;
    
  • its inverse function x(y) = asin(y)
    function x_from_y
      input Real y;
      output Real x;
    algorithm
      x:=asin(y);
    end x_from_y;
    
  • a couple of releveant equations
    y = time;
    y = y_from_x(x);
    

As you may see, in order to retrieve the value of variable x, the function y_from_x should be inverted; consequently, since the inverse annotation explicitly tells how to invert the function, I expect x_from_y to be called.

No, that's not what happens. Even just at the flattening step the inverse function is discarded and the solution of y_from_x is computed numerically with an iteration loop. This happens with both OpenModelica v1.14 and Dymola 2018.

Is this the expected behaviour? How does this inverse annotation should be used? Is there a way to avoid such inefficient iterative solution?

Full code

model test_inverse

Real y, x;

function y_from_x
  input Real x;
  output Real y;
algorithm
  y:=sin(x);
  annotation(inverse(x = x_from_y(y)));
end y_from_x;

function x_from_y
  input Real y;
  output Real x;
algorithm
  x:=asin(y);
end x_from_y;


equation
  y = time;
  y = y_from_x(x);
end test_inverse;

Solution

  • The problem in Dymola (and likely also in OpenModelica) is that the function is inlined before the inverse is used, but your syntax is correct.

    The inlining can be avoided using:

    function y_from_x
      input Real x;
      output Real y;
    algorithm
      y:=sin(x);
      annotation(LateInline=true, inverse(x = x_from_y(y)));
    end y_from_x;
    

    However, note that Dymola does not numerically invert the sine function - instead it uses the built-in inverse for the sine-function; which is similar to asin.