Using Conditional Components outside of connect() equations
I have recently been looking at conditional components and noticed that the specification says (section 4.4.5):
A component declared with a condition-attribute can only be modified and/or used in connections.
However, any tool I have tried so far has been happy to accept code that uses conditional components in normal equations or algorithm sections (clocked or continuous time). I have also found some previous discussions on this topic (mainly https://github.com/modelica/ModelicaSpecification/issues/104), but they don't seem to have had any clear resolutions.
With this my question is whether the tools' behaviour is now some kind of de-facto standard or whether there are any intentions to update the standard to reflect the commonly implemented behaviour.
As conditional components in equations or algorithms are quite useful, I would welcome seeing them supported officially by the standard.
Best regards
Pedantic check in Dymola does detect such uses. I guess the diagnostics should now be enabled also for non-pedantic check; it wasn't originally since there were a number of issues in MSL: https://github.com/modelica/ModelicaStandardLibrary/issues/1223
The basic problem with using conditional components in normal equations and/or algorithms is that the conditional component is potentially removed - and removing it would break the equations and/or algorithms.
Having some semantics for it would be possible, but it would require more thought. In particular algorithms are problematic. It might also be possible to have some special case when the condition is known to be true, but specifying that would be complicated.
Newer versions of OpenModelica also doesn't allow this.
Edit: Actually, that's not entirely correct. By default we only issue a warning, it's only in strict mode that we don't allow it at all.
One trick which is perfectly legal is to put the equations in modifiers of the conditional component declaration. For example:
parameter Boolean active;
SomeModel m(x = a + b) if active
Real z = a - b if active;
is OK, while
parameter Boolean active;
SomeModel m if active
equation
if active then
m.x = a + b;
z = a - b;
end if;
is not.
When just considering input or output connectors I believe it should always be possible to rewrite the code in a standard-conforming way: For example
model test2
parameter Boolean active = true;
Modelica.Blocks.Interfaces.RealInput inp if active;
Modelica.Blocks.Interfaces.RealOutput out;
algorithm
if active then
out := inp;
else
out := 1.;
end if;
end test2;
could be turned into:
model test2
parameter Boolean active = true;
Modelica.Blocks.Interfaces.RealInput inp if active;
Modelica.Blocks.Interfaces.RealOutput local_inp;
Modelica.Blocks.Interfaces.RealOutput out;
equation
if active then
connect(inp, local_inp);
else
local_inp = 0.;
end if;
algorithm
if active then
out := local_inp;
else
out := 1.;
end if;
end test2;
The transformation should even be possible to do automatically, by adding the extra connector, the equations for that connector and replacing other uses of the conditional component by the new component.
This is also the approach taken by some (many?) Standard Library models (e.g. Modelica.Blocks.Continuous.Integrator), but when I'm writing code myself, I would much rather write the first example instead of having to include this workaround everywhere.
Note, the suggestion of an exists() function from the original discussion (see #104) seems to me like a good approach in order to make this kind of model checkable.
One design pattern that I have seen in libraries (and support in MapleSim) is to have conditional outer for quick modification setting:
public
parameter Boolean useDefault = true;
parameter SomeType Material = DefaultOuterMaterial1 annotation(Dialog(enable=not useDefaultMaterial));
protected
outer parameter SomeType DefaultOuterMaterial1 if useDefaultMaterial;
and SomeType has the appropriate defaultComponentPrefixes and defaultComponentName so that the correct inner is created the moment it is dropped on the canvas.
If DefaultOuterMaterial1 is not conditional and it is not used (no inner is defined), there will be a missing inner warning and a useless inner would be created for it.
I believe there are some good uses where conditional should be allowed outside of connect equations if the code accounts for eliminating them from the equations when they become disabled like in both of @casella's examples. The compiler should be responsible only for eliminating disabled connect equations but it should be user's responsibility to ensure that the model would be valid if the condition becomes false for any other uses of the component. My suggestion is to change the specification to say:
If the Boolean expression is false the component (including its modifier) is removed from the flattened DAE, and connections to/from the component are removed by the tool. It is an error if the disabled component appears in any other active equation or modification.
If the Boolean expression is false the component (including its modifier) is removed from the flattened DAE, and connections to/from the component are removed by the tool. It is an error if the disabled component appears in any other active equation or modification.
From a model developer's perspective this proposal makes a lot of sense to me, I find the current restrictions a bit awkward. I'm not sure the implementation of such a revised rule could be challenging, maybe in some corner cases.
I'd like to hear @perost's opinon on that.
If the Boolean expression is false the component (including its modifier) is removed from the flattened DAE, and connections to/from the component are removed by the tool. It is an error if the disabled component appears in any other active equation or modification.
From a model developer's perspective this proposal makes a lot of sense to me, I find the current restrictions a bit awkward. I'm not sure the implementation of such a revised rule could be challenging, maybe in some corner cases.
I'd like to hear @perost's opinon on that.
I think the biggest issue would be to specify what an active equation or modification is, the specification doesn't say anything about whether if-equations can or should be evaluated when producing the flat DAE for example. So different tools might interpret such a restriction differently.
I think the biggest issue would be to specify what an active equation or modification is, the specification doesn't say anything about whether if-equations can or should be evaluated when producing the flat DAE for example. So different tools might interpret such a restriction differently.
Exactly. Note that C++20 introduced consteval to handle a similar issue. Such constructs may be needed, but they also make the language messier.
(For C++ an additional issue is that there's const, constexpr, and consteval. Additionally they also imply other semantic changes which may be a subtle plan by Sutter to redesign the language.)
Now that #3489 has been finalized, can we also close this ticket?
Now that #3489 has been finalized, can we also close this ticket?
Yes, assuming we skip the part for allowing use of the disabled components in non-active.