Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

conditional component declaration and a following if equation

I am trying to build a model that will have slightly different equations based on whether or not certain components exist (in my case, fluid ports).

A code like the following will not work:

parameter Boolean use_component=false;
Component component if use_component;
equation
if use_component then
  component.x = 0;
end if;

How can I work around this?

like image 453
Yigal Avatar asked Feb 03 '13 01:02

Yigal


2 Answers

If you want to use condition components, there are some restrictions you need to be aware of. Section 4.4.5 of the Modelica 3.3 specification sums it up nicely. It says "If the condition is false, the component, its modifiers, and any connect equations involving the component, are removed". I'll show you how to use this to solve your problem in just a second, but first I want to explain why your solution doesn't work.

The issue has to do with checking the model. In your case, it is obvious that the equation component.x and the component component either both exist or neither exist. That is because you have tied them to the same Boolean variable. But what if you had don't this:

parameter Real some_number;
Component component if some_number*some_number>4.0;
equation
if some_number>=-2 and some_number<=2 then
  component.x = 0;
end if;

We can see that this logically identical to your case. There is no chance for component.x to exist when component is absent. But can we prove such things in general? No.

So, when conditional components were introduced, conservative semantics were implemented which can always trivially ensure that the sets of variables and equations involved never get "out of sync".

Let us to return to what the specification says: "If the condition is false, the component, its modifiers, and any connect equations involving the component, are removed"

For your case, the solution could potentially be quite simple. Depending on how you declare "x", you could just add a modification to component, i.e.

parameter Boolean use_component=false;
Component component(x=0) if use_component;

The elegance of this is that the modification only applies to component and if component isn't present, neither is the modification (equation). So the variable x and its associated equation are "in sync". But this doesn't work for all cases (IIRC, x has to have an input qualifier for this to work...maybe that is possible in your case?).

There are two remaining alternatives. First, put the equation component.x inside component. The second is to introduce a connector on component that, if connected, will generate the equation you want. As with the modification case (this is not a coincidence), you could associate x with an input connector of some kind and then do this:

parameter Boolean use_component;
Component component if use_component;
Constant zero(k=0);
equation
connect(k.y, component.x);

Now, I could imagine that after considering all three cases (modification, internalize equation and use connect), you come to the conclusion that none of them will work. If this is the case, then I would humbly suggest that you have an issue with how you have designed the component. The reason these restrictions arise is related to the necessity to check components by themselves for correctness. This requires that the component be complete ("balanced" in the terminology of the specification).

If you cannot solve the problem with approaches I mentioned above, then I suspect you really have a balancing issue and that you probably need to redefine the boundaries of your component somehow. If this is the case, I would suggest you open another question here with details of what you are trying to do.

like image 65
Michael Tiller Avatar answered Sep 24 '22 09:09

Michael Tiller


I think that the reason why this will not work is that the parser will look for the declaration of the variable "component.x" that, if the component is not active, does not exist. It does not work even if you insert the "Evaluate=true" in the annotation. The cleanest solution in my opinion is to work at equation level and enable different sets of equations in the same block. You can create a wrapper model with the correct connectors and paramenters, and then if it is a causal model for example you can use replaceable classes in order to parameterize the models as functions, or else, in case of acausal models, put the equations inside if statements. Another possible workaround is to place two different models inside one block, so you can use their variables into the equation section, and then build up conditional connections that will enable the usage of the block with the choosen behaviour. In other words you can build up a "wrap model" with two blocks inside, and then place the connection equations to the connectors of the wrap model inside if statements. Remember to build up the model so that there will be a consistent system of quations even for the blocks that are not used. But this is not the best solution, because if the blocks are big you will have to wait longer time for compilation since everything will be compiled.

I hope this will help,

Marco

like image 27
Marco Romanoni Avatar answered Sep 25 '22 09:09

Marco Romanoni