model try
Real x(start = 1);
algorithm
when x >= 7 then
reinit(x, 5);
end when;
equation
der(x) = 1 ;
end try;
The when statement should be triggered whenever the guard condition is changed from false to true.
But it is not the case in OpenModelica. The example try in OpenModelica showes that when is triggered only once. I was wondering whether it is the bug of OpenModelica or some misunderstanding from my side.
You are correct. I am pretty sure this would be a bug in OpenModelica. The model works as you would expect in Dymola 2013.
My guess is that it is related to the fact that your when condition involves x and the statements inside end up changing x (the same variable). It may be that it somehow fails to notice the reinit in the monitor function used to determine the point at which the when clause should trigger.
Related
I'm making the PI controller using the Dymola Platform and i met the error message like below
And here's some of my code that consist of valve which calculate the disp and PI controller which control the amount of the disp.
They are communicating each other using the flag
//PI controller///
if flag_input==1 then //flag_input==1 : Stop control / flag_input==0 : Restart control//
control:=0;
else
control:=(P_term+I_term)/unit;
end if;
if error<0 then // error<0 : flag to Valve to restart calculating the disp//
flag_output:=1;
else
flag_output:=0;
end if;
//Valve//
if (26/5)*(thetta/(2*pi))*0.001>0.026 and flag_input==0 then
//restart calculating the disp when received flag==1 from the PI controller//
disp:=0.026;
flag:=1;
elseif (26/5)*(thetta/(2*pi))*0.001<0 and flag_input==0 then
disp:=0;
flag:=1;
else
disp:=(26/5)*(thetta/(2*pi))*0.001;
flag:=0;
end if;
Can someone tell me what is the meaning of algebraic loop error and figure out the problem?
From your code snippet it's hard to tell where exactly the problem is.
Dymola tells you that you created a large algebraic loop over all the variables listed at the top under Unknowns and the equations listed below in the section Equations.
This can happen easily when you create if statements with variables which depend on each other. Often you just have to use pre() at the right place to break the loop.
Let`s use another small example to explain the problem.
For some reason we try to count the full milliseconds, which have passed in the current simulation and stop, once we reach 100.
model count_ms
Integer y(start=0);
equation
if y >= 100 then
y = 100;
else
y = integer(1000*time);
end if;
end count_ms;
This code will produce a similar error as yours:
An algebraic loop involving Integers or Booleans has been detected.
Unknowns: y
Equations: y = (if y >= 100 then 100 else integer(1000*time));
From the error message we see that y can not be solved, due to the equation resulting from the if statement. The equation is not solvable, as y depends on itself. To solve such problems pre was introduced, which gives you access to the value of a variable had when the event was triggered.
To fix the code above, we simply have to use pre when we check for y
if pre(y) >= 100 then
and the model simulates as expected.
I try a simple code on modelica using if:
model thermostat1
parameter Real T0=10;
Real T(start=T0);
equation
if T<73 then
der(T)=-T+80;
else
der(T)=-T+50;
end if;
end thermostat1;
the simulation stops at the moment T reaches 73.
Why can't the simulation continue with the new equation ( der(T)=-T+50 )?
And how can i fix it?
Thank you.
What happens in your model is called chattering. This means, that there are very frequent events happening.
In you case specifically this is caused by the condition T<73 combined with the definitions of the derivatives. Let me try to explain what happens with the model you have provided:
The temperature rises until it reaches 73
Then the temperature starts to fall because the condition in the if-statement turns fall
This causes the if-statement to immediately change to true again, making the temperature rise
This causes the if-statement to change to false again, making the temperature fall
goto 3.
This causes the condition T<73 to change at a very high frequency, in turn creating many events, which have to be handled by the solver. This makes the progress in time very little (what you refer to as "the simulation stops").
There are multiple ways to solve this problem. One is to add a hysteresis to the model. I did that in code below. To describe the hysteresis part I used the code from Modelica.Blocks.Logical.Hysteresis. This will make the boolean variable upperLimit (which replaces your T<73) change only if temperature gets higher than T_highand lower than T_low. I chose this solution as it seems reasonable for a thermostat.
model thermostat1
parameter Real T0=10;
parameter Real T_High=74;
parameter Real T_Low=72;
Boolean upperLimit "Output of hysteresis block";
Real T(start=T0);
equation
upperLimit =not pre(upperLimit) and T > T_High or pre(upperLimit) and T >= T_Low;
if upperLimit then
der(T)=-T+50;
else
der(T)=-T+80;
end if;
end thermostat1;
The result of the simulation then looks like:
More general information can be found e.g. at http://book.xogeny.com/behavior/discrete/decay/
I need to detect whenever there is a change in a RealInput value X. I habe tried to check
if X == pre(X), but only receive an error and a warning that Real cannot be compared for equality. I also thought about using the derivative of X, but there is no explicit expression for this.
Other thoughts of mine have been to try to sample the continuous input into discrete variables that I can compare. Could this work in some way?
Try the change() operator. It is described in $3.7.3.1 of the Modelica Specification. According to the specification, it will be expanded to X<>pre(X), so that might work as well.
The change() operator is only practically useful for non-Real signals. The reason is that <> is not defined for Real types. Instead, you'll need to create a model that checks to see whether the signal deviates from the last recorded value by more than a given "epsilon". I haven't tested it, but the code would look something like this:
model DetectChange
parameter Real eps;
input Real signal;
output Boolean change;
protected
Real last_value;
initial algorithm
last_value = signal;
algorithm
when pre(change) then
last_value := signal;
end when;
change := abs(signal-last_value)>=eps;
end DetectChange;
Again, I haven't tested this. But it gives you some idea.
I have a selection of variables in my Modelica simulation (using Dymola) which is running good. Now I want to plot the behaviour of certain of these variables, which are numbered (with indices). I do not wish to plot the variables versus time, but versus their index. I'm planning to use the plotArray function, but that's not really what I'm curious about in this post. The problem is, all variables are zero when I call them, which indeed is their initial value, but I want to attain their value when steady state has set in, let's say when time = 5000. Hence I need to evaluate the variables at this specific time.
How do I evaluate a variable at a specific time from the simulation, or at the end of the simulation for that matter?
Edit: After extensive googling I've come over a function called val(), which seems to do what I want, but I can't get it to work with my Dymola software.
Edit 2: I've managed to evaluate my variables as desired, but the approach I used was (in my opinion) beyond tedious. I extracted the .mat-file from the simulation into MATLAB, where I eventually managed to identify the variables of my desire, and then plotted them at the desired time. What really surprised me, however, was the apparent chaos with respect to the variables in the .mat-file. On first glance, there was little agreement between how my variables are ordered in the Modelica model and how they are ordered in the .mat-file, and there was no naming of the variables, leaving me to search for variables solely based on comparing their value with the Dymola simulation. Am I simply completely mistaken here, or is there some easier way to extract variables from the .mat-file?
Maybe I'm misunderstanding your question, but I suspect there is a simple answer here. It sounds like you have an array and you want to populate that array with the values of a specific variable at a specific time and then plot the array. So, for example, let's say you had a variable x and you want to record the time that x crossed certain threshholds. A simple model like this would suffice:
model RecordVariables
Real x;
Real times[10];
initial equation
x = 11;
equation
der(x) = -x;
when x<=10.0 then
times[1] = time;
end when;
when x<=9.0 then
times[2] = time;
end when;
when x<=8.0 then
times[3] = time;
end when;
when x<=7.0 then
times[4] = time;
end when;
when x<=6.0 then
times[5] = time;
end when;
when x<=5.0 then
times[6] = time;
end when;
when x<=4.0 then
times[7] = time;
end when;
when x<=3.0 then
times[8] = time;
end when;
when x<=2.0 then
times[9] = time;
end when;
when x<=1.0 then
times[10] = time;
end when;
end RecordVariables;
Of course, writing out all those when clauses is pretty tedious. So we can actually create a more compact version like this:
model RecordVariables2
Real x;
Real times[5];
Integer i;
Real next_level;
initial equation
next_level = 10.0;
x = 11;
i = 1;
algorithm
der(x) :=-x;
when x<=pre(next_level) then
times[i] :=time;
if i<size(times,1) then
i :=pre(i) + 1;
next_level :=next_level - 1.0;
end if;
end when;
end RecordVariables2;
A few comments about this approach. First, note the use of the pre operator. This is necessary to distinguish between the values of the variables i and next_level both before and after the events generated by the when clause. Second, you will note the if statement within the when clause that prevents the index i from getting large enough to "overflow" the times buffer. This allows you to set times to have whatever size you want and never risk such an overflow. Note, however, that it is entirely possible in this model to make times so large that some values will never be filled in.
I hope this helps.
You can use DymBrowse.m to load variables from the resultfile to Matlab. It should be available in \Program Files\Dymola xx\Mfiles\dymtools.
Add the directory \Mfiles... to your matlab paths.
Just few questions, i hope someone will find time to answer :).
What if we have COUPLED model example: system of n indepedent variables X and n nonlinear partial differential equations PDEf(X,PDEf(X)) with respect to TIME that depends of X,PDEf(X)(partial differential equation depending of variables X ). Can you give some advice? Here is one example:
Let’s say that c is output, or desired variable. Let’s say that r is independent variable.Partial differential equation looks like:
∂c/∂t=D*1/r+∂c/∂r+2(D* (∂^2 c)/(∂r^2 ))
D=constant
r=0:0.1:Rp- Matlab syntaxis, how to represent same in Modelica (I use integrator,but didn't work)?
Here is a code (does not work):
model PDEtest
/* Boundary conditions
1. delta(c)/delta(r)=0 for r=0
2. delta(c)/delta(r)=-j*d for r=Rp*/
parameter Real Rp=88*1e-3; // length
parameter Real initialConc=1000;
parameter Real Dp=1e-14;
parameter Integer np=10; // num. of points
Real cp[np](start=fill(initialConc,np));
Modelica.Blocks.Continuous.Integrator r(k=1); // independent x1
Real j;
protected
parameter Real dr=Rp/np;
parameter Real ts= 0.01; // for using when loop (sample(0,ts) )
algorithm
j:=sin(time); // this should be indepedent variable like x2
r.u:=dr;
while r.y<=Rp loop
for i in 2:np-1 loop
der(cp[i]):=2*Dp/r.y+(cp[i]-cp[i-1])/dr+2*(Dp*(cp[i+1]-2*cp[i]+cp[i-1])/dr^2);
end for;
if r.y==Rp then
cp[np]:=-j*Dp;
end if;
cp[1]:=if time >=0 then initialConc else initialConc;
end while;
annotation (uses(Modelica(version="3.2")));
end PDEtest;
Here are more questions:
This code don’t work in OpenModelica 1.8.1, also don’t work in Dymola 2013demo. How can we have continuos function of variable c, not array of functions ?
Can we place values of array cp in combiTable? And how?
If instead “algorithm” stay “equation” code can’t be succesfull checked.Why? In OpenModelica, error is :could not flattening model :S.
Is there any simplified way to use a set of equation (PDE’s) that are coupled? I know for PDEs library in Modelica, but I think they are complicated. I want to write a function for solving PDE and call these function in “main model”, so that output of function be continuos function of “c”.I don’t know what for doing with array of functions.
Can you give me advice how to understand Modelica language, if we “speak” like in Matlab? For example: Values of independent variable r,we can specife in Matlab, like r=0:TimeStep:Rp…How to do same in Modelica? And please explain me how section “equation” works, is there similarity with Matlab, and is there necessary sequancial approach?
Cheers :)
It's hard to answer your question, since you assuming that Modelica ~ Matlab, but that's not the case. So I won't comment your code, since it's really wrong. Let me give you an example model to the burger equation. Maybe you could use it as starting point.
model burgereqn
Real u[N+2](start=u0);
parameter Real h = 1/(N+1);
parameter Integer N = 10;
parameter Real v = 234;
parameter Real Pi = 3.14159265358979;
parameter Real u0[N+2]={((sin(2*Pi*x[i]))+0.5*sin(Pi*x[i])) for i in 1:N+2};
parameter Real x[N+2] = { h*i for i in 1:N+2};
equation
der(u[1]) = 0;
for i in 2:N+1 loop
der(u[i]) = - ((u[i+1]^2-u[i-1]^2)/(4*(x[i+1]-x[i-1])))
+ (v/(x[i+1]-x[i-1])^2)*(u[i+1]-2*u[i]+u[i+1]);
end for;
der(u[N+2]) = 0;
end burgereqn;
Your further questions:
cp is an continuous variable and the array is representing
every discretization point.
Why you should want to do that, as far as I understand cp is
your desired solution variable.
You should try to use almost always equation section
algorithm sections are usually used in functions. I'm pretty
sure you can represent your desire behaviour with equations.
I don't know that library, but the hard thing on a pde is the
discretization and the solving it self. You may run into issues
while solving the pde with a modelica tool, since usually
a Modelica tool has no specialized solving algorithm for pdes.
Please consider for that question further references. You could
start with Modelica.org.