I am using OpenModelica to model a complicated system and am facing an awkward error
the error is in the when
statement as you can see in the image
am using a when
statement to determine the mass flow rate in an expansion valve
to confirm that the error is in when
statement I deleted it and I put the mass flow rate equal to a formula that calculates the mass flow rate and it worked, that means that the problem is in when
statement
if anyone can help me, please
3 Answers
The usual solution to loops with when
is to introduce pre
on a discrete-valued variable. Unfortunately there is none so we have to introduce one.
So instead of
when level<min_level then
port.e_dbM=0.12;
end when;
it would be:
Boolean belowMin=level<min_level;
equation
when pre(belowMin) then
port.e_dbM=0.12;
end when;
(And similarly for elsewhen.)
This is a duplicate of the answer to, and error message in question in: Problems understanding a dymola error message - we might need a more generic question and answer as canonical for this.
From your description, I see that the variable dbM is a continuous variable. I think that using a when
-statement is not correct. Let us first fix that.
Reasoning: The condition within a when
-statement triggers an event only once at the time point when the condition indicator start to change its sign, i.e. the magnitude liquid_level_valve - min_value
becomes negative after being positive. The numerical solver usually succeeds to identify the time point where such change of the sign occurs. At this time point, say t_e, an event is triggered.
Once the event is triggered, the equation inside when
-statement is evaluated at time t_e. For the following simulation time steps, i.e. t > t_e, this equation is not evaluated anymore. Instead, the equation resulted from the connect
statement takes place as the default equation and not the equation within the when
-statement.
Therefore, try to express the boundary conditions with an if
statement instead of a when
-statement. The if
-statement is similar to what we know as branch functions in Calculus and this is the situation here.
I think the same situation addressed by the other answer could also occur with if
. You may need to follow a similar approach as described there.
If the errors are still there with the if
statement, then one may try the noEvent
operator, see description. This would not be precisely correct Numerics, but still a way to narrow the possible causes of such errors.
update: how to use if
instead of when
:
To illustrate the idea with simple use-case, say the main equation looks like this:
myMassFlowRate = port_e.dbM;
In order to express the boundary conditions, an auxiliary variable can be introduced:
if liquid_level_value < min_value then
tmp = 0.012;
elseif liquid_level_value > max_value then
tmp = 0;
else
tmp = port_e.dbM;
end if;
myMassFlowRate = tmp;
This works with such flat code with no connect
-statement. This way needs a bit of modification to work with ports communicating information across components, but the idea is the same, e.g. you can communicate discrete boolean values through ports if you need to. For example,
type LiquidLevel = enumeration(above,normal,below);
discrete LiqidLevel level(start = normal); // assumption
...
// using when is now correct
when(liquid_level_value < min_value) then
level = below;
elsewhen (liquid_level > max_value) then
level = above;
elsewhen (....)
level = normal;
end when;
the variable level can be communicated across an I/O port to set the flow rate:
if level == normal then
myMassFlowRate = port_e.dbM;
elseif level == below then
myMassFlowRate = 0;
else
myMassFlowRate = 0.012;
end if;
This is what corresponds to your description. Using when
directly to set a real variable is just a re-initialization.
after spending many days trying to solve the posted problem i found a solution to pervent the non-linearity error i used a Boolean inside WHEN statment , and that Boolean is going to control the mass flow rate using IF statment as following :
when liquid_level_valve < min_valve then
open_valve = true;
elsewhen liquid_level_valve > max_valve then
open_valve = false;
end when;
port_e.dbM = if open_tev then dbM_valve else 1 / 100000;
where the dbM is calculated using the equation corresponding to valve. and now my systeme works without any trouble
thanks for anyone how tried to help me