1
votes

I am using OpenModelica to model a complicated system and am facing an awkward error enter image description here the error is in the when statement as you can see in the image enter image description here 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
How did you declare port_e.dbM? Is it declared as a discrete variable or a continuous variable? Is it involved in other equations outside "when"?Atiyah Elsheikh
I used a stream connector i name it connecter so its :. Connecter port_e , port_s;Dahmani Merzaka
How about the variable dbM. My impression it is a continuous variable and not a discrete variable, i.e. it is declared as Real dbM and not as discrete Real dbM?. In this case, I suspect that you need to use an "if"-statement instead of "when"-statement.Atiyah Elsheikh
THis is how dbM is declared connector connector_A replaceable package Medium = Modelica.Media.Interfaces.PartialMedium; flow Medium.MassFlowRate dbM; Medium.AbsolutePressure p ; stream Medium.SpecificEnthalpy h; end connector_A;Dahmani Merzaka

3 Answers

3
votes

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.

1
votes

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.

1
votes

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