I have a function that does or does not have a derivative and inverse, depending on values of some parameters/coefficients. Can I make the annotations derivative and inverse conditional somehow?
Something like
function y_from_x
input Real x;
input Boolean hasInverse;
output Real y;
...
equation
...
annotation(inverse(x=x_from_y(y=y) if hasInverse));
end y_from_x;
There is no direct support for that in the Modelica specification.
What you could do is something like:
function y_from_x
input Real x;
input Boolean hasInverse;
output Real y;
...
algorithm
y:=if hasInverse then y_from_x1(x) else y_from_x2(x);
annotation(Inline=true);
end y_from_x;
function y_from_x1
input Real x;
output Real y;
...
algorithm
y:=y_from_x2(x);
annotation(inverse(x=x_from_y(y=y)));
end y_from_x1;
function y_from_x2
input Real x;
output Real y;
...
algorithm
...
end y_from_x2;
Related
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;
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.
I've a function that can calculate central difference of f(x) but I'm basic user of matlab and I can't define f(x) for function I've mentioned.
Can any body help me and define f(x) for this function?
INPUTS are a function f; a value
of h; a specific point a; the number of rows n. The input function f(x)
should be defined as an M-file.
My f(x) is : S(x) = 10*x-sin(x) with steps: 0.1
I want to get df(x) near the piont=pi/6
I wrote:
clc
syms x
derive(10*x-sin(x),0.1,pi/6,14)
but I've got this error :
Error using feval
Argument must contain a string or function_handle.
Error in derive (line 7)
D(1,1)=(feval(f,a+h)-feval(f,a-h))/(2*h);
Error in centre(line 2)
========================================
the function derive.m is here:
function derive(f,h,a,n)
% Approximate the derivative of a function at x = a.
disp(' Derivative table')
disp('______________________________________________')
disp(' i h Di,1 Di,2 Di,3 ... ')
disp('______________________________________________')
D(1,1)=(feval(f,a+h)-feval(f,a-h))/(2*h);
fprintf('%2.0f %8.4f %12.4f\n',1,h,D(1,1));
for i=1:n-1
h=h/2;
D(i+1,1)=(feval(f,a+h)-feval(f,a-h))/(2*h);
fprintf('%2.0f %8.4f %12.4f',i+1,h,D(i+1,1));
for k=1:i
D(i+1,k+1)=D(i+1,k)+(D(i+1,k)-D(i,k))/((4^k)-1);
fprintf('%12.4f',D(i+1,k+1));
end
fprintf('\n');
end
feval expects a function handle, that is a MatLab function handle. What you provided (10*x-sin(x)) is a symbolic expression.
You can define a function handle as follows:
f(x) = 10*x-sin(x);
Now f is a MatLab function handle, and you can use it as you wish:
derive(f,0.1,pi/6,14)
EDIT
You can also use an anonymous functions
derive((x)(10*x-sin(x)),0.1,pi/6,14)
END EDIT
Note, you do not need syms x, it defines x as a symbol, but in your function definition you use the parameter x defined in f(x).
EDIT
If you want to use a symbolic function, you can convert it to a MatLab function handle using matlabFunction
The following three questions are tied together so please forgive the length of the post.
Using Dymola 2016.
Using a replaceable function call within a model provides the opportunity for the user to have the drop down options. Example below:
model Test1
parameter Real x = 1;
Real y;
replaceable function a=b constrainedby d annotation(choicesAllMatching=true);
equation
y = a(x);
end Test1;
Doing the same replaceable function call within a function seems to not permit the same drop down functionality with the the function is called (i.e. right click call function in package browser. I assume this is intentional as a function is typically called within other functions/models. Example below:
function Test2
input Real x;
output Real y;
replaceable function a=b constrainedby d annotation(choicesAllMatching=true);
algorithm
y :=a(x);
end Test2;
Question #1. Is it possible to use a replaceable function call within a function in the same way you do a model? If so, what is the appropriate syntax? Alternative approach?
Alternatively, a different option would be to perform the replaceable function call in the model and then pass the result to another function that then makes the appropriate call. Example shown below:
model Test3mod
parameter Real x = 1;
Real y;
replaceable function a=b constrainedby d annotation(choicesAllMatching=true);
equation
y = Test3func(x,a);
end Test3mod;
Which passes parameter x and function handle a to:
function Test3func
input Real x;
input ???? a;
output Real y;
algorithm
y :=a(x);
end Test3func;
Question #2. Is this allowable in Modelica and if so, how? Alternative approach?
Question #3. Is it possible to define a string and turn that into a the name of a function. Example below:
model Test4
parameter String 'functionname';
parameter Real x = 1;
Real y;
equation
y = functionname(x);
end Test4;
Thank you in advance! I appreciate your feedback as I continue to explore the use of Modelica.
This should work fine:
model Test3mod
parameter Real x = 1;
Real y;
replaceable function a=b constrainedby d annotation(choicesAllMatching=true);
equation
y = Test3Func(x,a);
end blah;
function Test3func
input Real x;
input d f;
output Real y;
algorithm
y := f(x);
end Test3func;
I would like to use a class function/method in my Modelica model as follows:
optimization Moo(objective=-x(finalTime), startTime = 0, finalTime = 12)
parameter Real e = 0.05;
Real x(start=2, fixed=true, min=0, max=100);
input Real v (min=0, max=1);
function omega
input Real t;
output Real y;
algorithm
y := e;
end omega;
equation
der(x) = v*omega(time);
constraint
v<=1;
end Moo;
I would like the variable e in the function omega to be a variable so that I can easily change its value at a later point in time when I am doing a parameter sweep. Unfortunately, the function omega does not seem to know about the variable e and the JModelica compiler returns the error:
Cannot find class or component declaration for e
I would naïvely expect that since omega and e belong to the same class omega would be able to see e.
Is there a way to achieve this?
Member functions are not supported in Modelica, so a function declared inside a model acts like a standalone function without having access to the surrounding model variables.
Member functions are not allowed due to functions need to be pure, i.e. they are not allowed to have any side effect. This is a fundamental assumption in Modelica that makes it possible for a tool to apply symbolic transformation and rearrange calculations.
You can have something like a member function, if you explicitly pass the needed variables as additional input to the function. See this example:
package MemberFunction
model A
Real x=1;
function get_x = MemberFunction.get(u=x);
end A;
function get
input Real u;
output Real y;
algorithm
y := u;
end get;
model Test
A a;
Real x;
equation
x = a.get_x();
end Test;
end MemberFunction;
It seems that it is at least not encouraged to write Modelica functions with connectors as arguments. I get a warning if I try it.
Assume I have a connector
connector con
Real x;
Real y;
end con;
a record
record rec
Real x;
Real y;
end rec;
and a function
function f
input rec r[:];
output Real z;
algorithm
...
end f;
Given an array of connectors, i.e. con c[N], how can I convert it into an array of records rec?
One approach would be to use a function
function convert
input Integer N;
input Real x[N];
input Real y[N];
output rec z[N];
algorithm
z.x := x;
z.y := y;
end convert;
and call it via convert(size(c, 1), c.x, c.y).
Is there a simpler way?