transition false-true at initialisation OpenModelica - modelica

I have been facing some problem with Modelica initialisation. I want to simulate the initial step of a finite state machine and I would like the initial state to start from false and instantly turns to true at the beginning of the simulation.
equation
OUTPUT=active;
algorithm
when change(INPUT) then X:= not X; reinit(t,0); end when;
initial algorithm
active:=true;
Here is the code.
Variable INPUT, OUTPUT and X are all Boolean type. INPUT is a variable that makes the state changes ( from true to false and vice versa).
What the code does is to set variable active to true at the initialisation. What I would like to get is that it starts from false and it gets to true at time t=0; basically I would like to see the transition from false to true at the first instant of the simulation. Is it possible?

EDIT 2:
Looking at this issue, using initial() for the when clause solves the problem.
model Test
Boolean x(start=false) "state";
Boolean u;
Modelica.Blocks.Interfaces.BooleanOutput y;
equation
u=true;
when initial() then
x = not pre(x);
elsewhen edge(u) then
x = not pre(x);
end when;
y=x;
end Test;
Looking at the debugger of OpenModelica, first x gets the start-value false assigned, then it jumps into the when clause and sets it to true.

Related

How can I generate complex events in modelica for when statement?

I tryed to use this code:
Real x,y;
Boolean trigger(start = true)
when x < y and trigger then
trigger = false;
end when;
I want to generate event for "when" only once. But my code doesn't work.
How can I generate complex events in modelica for when statement?
In Dymola you get the following error message:
The computational causality analysis requires the variables trigger
to be solved from the equation: when x < y and trigger then trigger =
false; end when;
however, the when condition also depends on the unknowns.
You may be able to cut the loop by putting 'pre' around these
references in the when condition.
Thus the solution would be:
Real x,y;
Boolean trigger(start = true) ;
equation
when x < y and pre(trigger) then
trigger = false;
end when;
As you see this is quite simple (and simulates in Dymola), but I haven't checked it in OpenModelica.
The problem you seem to be hitting is the first error message Internal error BackendDAETransform.analyseStrongComponentBlock failed (Sorry - Support for Discrete Equation Systems is not yet implemented). This seems to be https://trac.openmodelica.org/OpenModelica/ticket/1232, and I think it is caused by redefining part of your condition variable within the when statement.
You can work around this with reinit. See also the Bouncing ball example and the reference. It needs to act on a state variable, that's why I put the der(trigger) in there.
model test_when
Real trigger(start = 1.0, fixed = true);
equation
der(trigger) = 0;
when trigger > 0.5 and time > 5 then
reinit(trigger, 0);
end when;
annotation(
experiment(StartTime = 0, StopTime = 10, Tolerance = 1e-06, Interval = 0.02));
end test_when;
Probably there is a nicer way to achieve this. Anybody else got input on this?
You can check the compilation log (Statistics - events) to confirm that only one event was fired.

Too many equations for discrete state machine variables in when statements in Modelica

I have a contrived Modelica model in which a have a state machine variable manipulated by multiple when statements:
model WhenExample
type State = enumeration(first, second, third);
State state;
initial equation
state = State.first;
equation
when sample(0, 1) then
state = State.second;
end when;
when sample(0, 3) then
state = State.third;
end when;
end WhenExample;
When compiling under OpenModelica OMC, I get the following error:
[1] 16:46:39 Symbolic Error
Too many equations, over-determined system. The model has 2 equation(s) and 1 variable(s).
This kinda makes sense as I do have two equations for my single state variable. However, those equations only apply at discrete points in time, right?
Do I need to make sure all "manipulations" of a particular variable happen only in a single when statement?
See Modelica Spec, section 8.5 Events and Synchronization:
https://www.modelica.org/documents/ModelicaSpec33Revision1.pdf
Just before section 8.6 there is an example that should help you.
Some code based on that is given below:
model WhenExample
parameter Integer multiplySample = 3;
Boolean fastSample, slowSample;
Integer ticks(start=0);
type State = enumeration(first, second, third);
State state(start = State.first);
equation
fastSample = sample(0,1);
algorithm
when fastSample then
ticks := if pre(ticks) < multiplySample then pre(ticks)+1 else 0;
slowSample := pre(ticks) == 0;
state := State.second;
end when;
when slowSample then
state := State.third;
end when;
end WhenExample;

issue generating triangular wave function in Modelica

I'm trying to create a model where one Modelica variable is a triangular wave of another variable. First I tried the floor() function as below:
model test1
final constant Real pi=2*Modelica.Math.asin(1.0);
parameter Real b = 1;
parameter Real a = 1;
Real x,p,u;
equation
if sign(sin(x*pi/b))>=0 then
p=a*(x-b*floor(x/b));
else
p=a*(b-(x-b*floor(x/b)));
end if;
x=time;
u = floor(x/b);
end test1
(x=time; is arbitrary so the model compiles)
but the result is weird, as you can see below
zoom in:
somehow 0.005 seconds before the next step floor function behaves unexpectedly and becomes a linear function ending by the next value.
then I tried the ceil() function. everything seemed right till I realised the same problem happens with ceil() function at other values (e.g. x=13)
I would appreciate if you could:
help me understand why this "glitch" happens and if it is intentional by design or a bug?
how I can fix this?
are there any alternatives to create a triangular wave function?
P.S. I am using this "wave function" to model the interaction between two jagged bodies"
If you are allowed to utilize the Modelica Standard Library, you can build up a parametrized, time-based zigzag signal using the CombiTimeTable block with linear interpolation and periodic extrapolation. For example,
model Test4
parameter Real a=2 "Amplitude";
parameter Real b=3 "Period";
Real y=zigzag.y[1] "Zigzag";
Modelica.Blocks.Sources.CombiTimeTable zigzag(
table=[0,0;b/4,a;b/4,a;b/2,0;b/2,0;3*b/4,-a;3*b/4,-a;b,0],
extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic)
annotation(Placement(transformation(extent={{-80,60},{-60,80}})));
Modelica.Blocks.Sources.Trapezoid trapezoid(
amplitude=2*a,
rising=b/2,
width=0,
falling=b/2,
period=b,
offset=-a)
annotation(Placement(transformation(extent={{-80,25},{-60,45}})));
annotation(uses(Modelica(version="3.2.2")));
end Test4;
I don't have an explanation for the glitches in your simulation.
However, I would take another approach to the sawtooth function: I see it as an integrator integrating +1 and -1 upwards and downwards. The integration time determines the amplitude and period of the sawtooth function.
The pictures below show an implementation using MSL blocks and one using code. The simulation results below are the same for both implementations.
Best regards,
Rene Just Nielsen
Block diagram:
Code:
model test3
parameter Real a=2 "amplitude";
parameter Real b=3 "period";
Real u, y;
initial equation
u = 1;
y = 0;
equation
4*a/b*u = der(y);
when y > a then
u = -1;
elsewhen y < -a then
u = 1;
end when;
end test3;
Simulation result:
The problem I guess is due to floating point representation and events not occurring at exact times.
Consider x-floor(x) and 1-(x-floor(x)) at time=0.99, they are 0.99 and 0.01; at time=1.00 they are 0.0 and 1.0, which causes your problems.
For a=b=1, you can use the following equation for p:
p=min(mod(x,2),2-mod(x,2));. You can even add noEvent to it, and you can consider the signal continuous (but not differentiable).
model test
parameter Real b = 1;
parameter Real a = 3;
Real x, p;
equation
p = 2*a*min(1 / b * mod(x, b ),1 - 1/b * mod(x, b));
x = time;
end test;
My first advise would be to remove the sign-function, since there is no benefit of doing sign(foo)>=0 compared to foo>=0.
Interesting enough that seems to fix the problem in Dymola - and I assume also in OpenModelica:
model test1 "almost original"
final constant Real pi=2*Modelica.Math.asin(1.0);
parameter Real b = 1;
parameter Real a = 1;
Real x,p,u;
equation
if sin(x*pi/b)>=0 then
p=a*(x-b*floor(x/b));
else
p=a*(b-(x-b*floor(x/b)));
end if;
x=time;
u = floor(x/b);
end test1;
Now I only have to explain that - and the reason is that sin(x*pi/b) is slightly out of sync with the floor-function, but if you use sin(x*pi/b)>=0 that is within the root-finding epsilon and nothing strange happen.
When you use sign(sin(x*pi/b))>=0 that is no longer possible, instead of having sin(x*pi/b) an epsilon below zero it is now -1, and instead of epsilon above zero it is 1.
The real solution is thus slightly more complicated:
model test2 "working"
parameter Real b = 1;
parameter Real a = 1;
Real x,p,u;
Real phase=mod(x,b*2);
equation
if phase<b then
p=a/b*phase;
else
p=a-a/b*(phase-b);
end if;
x=time;
u = floor(x/b);
end test2;
which was improved based on a suggested solution:
model test3 "almost working"
parameter Real b = 1;
parameter Real a = 1;
Real x,p,u;
equation
if mod(x,2*b)<b then
p=a/b*mod(x,b);
else
p=a-a/b*mod(x,b);
end if;
x=time;
u = floor(x/b);
end test3;
The key point in this solution, test2, is that there is only one problematic event generating expression mod(x,2*b) - and the < will not get out of sync with this.
In practice test3 will almost certainly also work, but in unlikely cases the event generation might get out of sync between mod(x,2*b) and mod(x,b); with unknown consequences.
Note that all three examples are now modified to generate output that looks similar.

Dynamically switching connect in Modelica

Assume I have a large connector involving all kinds of base types (Real, Integer, String, Boolean). How can I switch connections based on state events?
I would like to do something like this:
model switch
input ComplicatedConnector icon[2];
output ComplicatedConnector ocon;
input Real x;
equation
if x >= 0 then
connect(ocon, icon[1]);
else
connect(ocon, icon[2]);
end if;
end switch;
This does not work. How can it be properly expressed in Modelica?
Answer based on comment by Adrian Pop.
model switch
input ComplicatedConnector icon[2];
output ComplicatedConnector ocon;
input Real x;
ComplicatedConnector con;
initial equation
con = icon[1];
equation
connect(ocon, con);
when x >= 0 then
con := icon[1];
end when;
when x < 0 then
con := icon[2];
end when;
end switch;
Update: The model above is wrong because ocon outputs the initial value of icon[1] forever if no event occurs which is not what you would expect from a switch. Note that this is not due to a wrong answer but due to my false interpretation of the answer. The following model is based on the answer by Michael Tiller.
model switch
input ComplicatedConnector icon[2];
output ComplicatedConnector ocon;
input Real x;
Integer k;
initial equation
k = 1;
equation
ocon = icon[k];
when x >= 0 then
k := 1;
elsewhen x < 0 then
k := 2;
end when;
end switch;
Is not possible. You can only switch them based on a parameter known at compile time (also known as structural parameter). The condition in the if equation containing connects needs to be a parameter expression.
Note that connect statements are equations. You can expand them out yourself. They exist mainly to avoid "bookkeeping" errors for generating boilerplate equations. So what I suggest you do is simply take your switch model and expand each connect into equations. The it should work.

Sample function doesn't work on Dymola

I try to compile the following code with Dymola:
class abc
import Modelica.SIunits;
parameter SIunits.Time delta_t=0.5;
constant Real a[:]={4,2,6,-1,3,5,7,4,-3,-6};
Real x;
Integer j(start=1);
Integer k=size(a, 1);
algorithm
when {(sample(0, delta_t) and j < k),j == 1} then
x := a[j];
j := j + 1;
end when;
end abc;
and for time = 0 the variable j starts with 2. But it should start with j = 1.
Does anybody have an idea for this problem?
Keep in mind that sample(x,y) means that sample is true at x+i*y where i starts at zero. Which is to say that sample(0, ...) becomes true at time=0.
Since j starts at 1 and k is presumably more than 1, it doesn't seem unexpected to me that sample(0, delta_t) and j<k should become true at the start of the simulation.
I suspect what you want is:
class abc
import Modelica.SIunits;
parameter SIunits.Time delta_t=0.5;
constant Real a[:]={4,2,6,-1,3,5,7,4,-3,-6};
Real x;
Integer j(start=1);
Integer k=size(a, 1);
algorithm
when {(sample(delta_t, delta_t) and j < k),j == 1} then
x := a[pre(j)];
j := pre(j) + 1;
end when;
end abc;
I don't really see the point of the j==1 condition. It is true at the outset which means it doesn't "become" true then. And since j is never decremented, I don't see why it should ever return to the value 1 once it increments for the first time.
Note that I added a pre around the right-hand side values for j. If this were in an
equation section, I'm pretty sure the pre would be required. Since it is an algorithm section, it is mainly to document the intent of the code. It also makes the code robust to switching from equation to algorithm section.
Of course, there is an event at time = 0 triggered by the expression sample(0, delta_t) and j<k which becomes true.
But in older versions of Dymola there is an bug with the initialization of discrete variables. For instance even if you remove sample(0.0, delta_t) and j<k in dymola74, j will become 2 at time=0. The issue was that the pre values of when clauses, where not initialized correct. As far as I know this is corrected at least in the version FD1 2013.