The conditional declaration of the component and the following if the equation

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

Code like the one below 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 get around this?

+6
source share
3 answers

If you want to use state components, there are some limitations that you need to know about. This is clearly seen in section 4.4.5 of the Modelica 3.3 specification. It says: "If the condition is false, the component, its modifiers and any communication equations associated with the component are deleted." I will show you how to use this to solve your problem in just a second, but first I want to explain why your solution does not work.

The problem is with model validation. In your case, it is obvious that the equation component.x and component component either exist or do not exist. This is because you bound them to the same boolean variable. But what if you did not have 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 see that this is logically identical to your case. For component.x there is no way to exist when component missing. But can we prove such things at all ? No.

So, when conditional components were introduced, conservative semantics were implemented, which could always guarantee that sets of variables and equations would never be “out of sync”.

Let's go back to the fact that the specification says: "If the condition is false, the component, its modifiers, and any connection equations involving the component, are deleted"

In your case, the solution can be quite simple. Depending on how you declare "x", you can simply add the 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 applies only to the component , and if component not, then the modification (equation) is absent. Thus, the variable x and the associated equation are “synchronous”. But this does not work for all cases (IIRC, x must have an input qualifier for this to work ... maybe this is possible in your case?).

There are two alternatives. First put the component.x equation inside component . Secondly, you need to enter a connector on component , which, if connected, will generate the required equation. As with the modification (this is not a coincidence), you can associate x with some input connector, and then do this:

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

Now I could imagine that after considering all three cases (modifying, internalizing the equation and using connect ), you come to the conclusion that none of them will work. If so, then I would humbly suggest that you have a problem with how you developed the component. The reason these limitations arise is due to the need to test the components yourself for correctness. This requires the component to be complete (“balanced” in the specification terminology).

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

+8
source

I think the reason this will not work is because the parser will look for the declaration of the variable "component.x", which, if the component is inactive, does not exist. It does not work even if you insert "Evaluate = true" into the annotation. In my opinion, the cleanest solution is to work at the equation level and to include different sets of equations in one block. You can create a wrapper model with the correct connectors and parasites, and then, if it is a causal model, for example, you can use plug-in classes to parameterize models as functions, or in case of acausal models put equations inside if statements. Another possible workaround is to place two different models inside the same block, so you can use their variables in the equations section, and then create conditional connections that will allow you to use the block with the selected behavior. In other words, you can create a “transfer model” with two blocks inside, and then put the connection equations in the connectors of the wrapper model inside the if statements. Remember to create the model so that there is a consistent system of quotes even for blocks that are not used. But this is not the best solution, because if the blocks are large, you will have to wait more time to compile, since everything will be compiled.

Hope this helps,

Marco

+1
source

You can also create a dummy component that does not appear at the graphic level:

 connector DummyHeatPort "Dummy heatport to facilitate optional heatport. Use this with a conditional heatport by connecting it to the heatport. Then use the -DummyHeatPort.Q_flow in the thermal energy balance." Modelica.SIunits.Temperature T "Port temperature"; flow Modelica.SIunits.HeatFlowRate Q_flow "Heat flow rate (positive if flowing from outside into the component)"; end DummyHeatPort; 

Then when it is used in the dual port model

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatport if use_heat_port; DummyHeatPort dummy_heatport; 

...

  equation flowport_a.H_flow + flowport_b.H_flow - dummy_heatport.Q_flow = storage "thermal energy balance"; connect(dummy_heatport, heatport); 

Thus, Heatport is used if it is present but does not cause an error.

0
source

All Articles