ModelicaSpecification icon indicating copy to clipboard operation
ModelicaSpecification copied to clipboard

Using Conditional Components outside of connect() equations

Open d-model opened this issue 2 years ago • 8 comments

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

d-model avatar Jul 03 '23 16:07 d-model

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.

HansOlsson avatar Jul 03 '23 16:07 HansOlsson

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.

perost avatar Jul 03 '23 16:07 perost

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.

casella avatar Jul 03 '23 20:07 casella

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.

d-model avatar Jul 04 '23 19:07 d-model

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.

eshmoylova avatar Jul 05 '23 17:07 eshmoylova

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.

casella avatar Jul 05 '23 21:07 casella

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.

perost avatar Jul 05 '23 22:07 perost

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.)

HansOlsson avatar Jul 06 '23 07:07 HansOlsson

Now that #3489 has been finalized, can we also close this ticket?

casella avatar May 16 '25 11:05 casella

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.

HansOlsson avatar May 16 '25 11:05 HansOlsson