I would like to ask a Modelica question about when function, and the following source code cannot be properly functioned. The variable Pstart_CONV is an initial condition for der(x_calc) in the if statement, and the Pstart_CONV value is given by x when the "when statement" becomes true. Because x is a step function, I want to assign an initial condition for der(x_calc) so x can be continued for the whole domain.
Thank you very much,
Source:
model Unnamed4
Real Pstart_CONV;
Real P_crit_ratio;
parameter Real P_crit_ratio_criteria = 2.00;
Real x;
Real x_calc(start=0);
equation
P_crit_ratio = 10-time;
when P_crit_ratio <= P_crit_ratio_criteria then
Pstart_CONV = x;
end when;
if P_crit_ratio >= P_crit_ratio_criteria then
x = time^2;
x_calc = 0;
else
der(x_calc) = time * 5;
x = x_calc + Pstart_CONV;
end if;
end Unnamed4;
There are two issues I see with this code. The main one has to do with the fact that this is what is called a "variable index" problem. I'll address that. But first, I want to point out that your if
and when
clauses are not properly synchronized. What I mean by that is that the change in behavior represented by your if
statement will not necessarily occur at the same instant that the when
clause is activated.
To address this, you can easily refactor your model to look like this:
model Model1
Real Pstart_CONV;
Real P_crit_ratio;
parameter Real P_crit_ratio_criteria=2.00;
Real x;
Real x_calc(start=0);
Boolean trigger(start=false);
equation
P_crit_ratio = 10-time;
when P_crit_ratio <= P_crit_ratio_criteria then
Pstart_CONV = x;
trigger = true;
end when;
if trigger then
der(x_calc) = time * 5;
x = x_calc + Pstart_CONV;
else
x_calc = 0;
x = time^2;
end if;
end Model1;
Now, both the if
and when
clauses are tied to the trigger
variable. Now we can address your main problem which is that on one side of your if
statement you have:
der(x_calc) = time * 5;
...and on the other side you have:
x_calc = 0;
In practice, what this means is that for part of the simulation you solve x_calc
using a differential equation while during the other part of the simulation you solve x_calc
using an algebraic equation. This leads to the "variable index" problem because the "index" of the DAE changes depending on whether the value of trigger
is true or false.
One approach to this is to modify the equations slightly. Instead of using the equation x_calc = 0
we specify an initial condition of 0
for x_calc
and then enforce a differential equation that says the value of x_calc
doesn't change, i.e., der(x_calc) = 0
. In other words, get the same behavior by removing an algebraic equation settings x_calc
to a constant and replacing it with an equation where we set the initial value of x_calc
to be the desired value and then add a differential equation that, in effect, simply says the value of x_calc
doesn't change.
Making such a change in your case leads to the following model:
model Model2
Real Pstart_CONV;
Real P_crit_ratio;
parameter Real P_crit_ratio_criteria=2.0;
Real x;
Real x_calc(start=0);
Boolean trigger(start=false);
initial equation
x_calc = 0;
equation
P_crit_ratio = 10-time;
when P_crit_ratio <= P_crit_ratio_criteria then
Pstart_CONV = x;
trigger = true;
end when;
if trigger then
der(x_calc) = time * 5;
x = x_calc + Pstart_CONV;
else
der(x_calc) = 0;
x = time^2;
end if;
end Model2;
I tested it, and this model ran using SystemModeler (although I don't know enough about your problem or the expected results to truly validate the results).
I hope that helps.