ModelicaSpecification icon indicating copy to clipboard operation
ModelicaSpecification copied to clipboard

Can der apply to a discrete Real variable

Open TongYuan-MC opened this issue 1 year ago • 4 comments

model DiscreteRealDerTest
  Real xd;
  Real x;
  Real y;
  // Real yd = der(xd); // This is not allowed according to MLS3.6 P44
equation
  when sample(0, 0.1) then
    xd = sin(time);
  end when;
  x = if time < 0.5 then sin(time) else xd;
  y = der(x); // Should this be supported? Should a warning message given if supported?
end DiscreteRealDerTest;

In the above model, Real yd = der(xd) should not allowed according to MLS3.6 P44 since xd is discrete-time Real variable, see bottom. x is continue-time Real variable, so it could be derivatived, however der(x) = if time < 0.5 then cos(time) else der(xd); involed in der(xd) which is not allowed.

In OpenModelica lastest release v1.22.3,

  1. DiscreteRealDerTest can be simulated, and y = if time < 0.5 then cos(time) else 0;
  2. Real yd = der(xd); will get a compile error.

DiscreteRealDerTest is a simplify model of Modelica.Electrical.Spice3.Examples.Nor and Modelica.Electrical.Spice3.Examples.Spice3BenchmarkFourBitBinaryAdder in Modelica Standard Library 4.0, this two standard models both use Modelica.Electrical.Spice3.Sources.V_pulse which resulted in derivative a discrete variable.

image

TongYuan-MC avatar Apr 19 '24 03:04 TongYuan-MC

model DiscreteRealDerTest
  Real xd;
  Real x;
  Real y;
  // Real yd = der(xd); // This is not allowed according to MLS3.6 P44
equation
  when sample(0, 0.1) then
    xd = sin(time);
  end when;
  x = if time < 0.5 then sin(time) else xd;
  y = der(x); // Should this be supported? Should a warning message given if supported?
end DiscreteRealDerTest;

In the above model, Real yd = der(xd) should not allowed according to MLS3.6 P44 since xd is discrete-time Real variable, see bottom. x is continue-time Real variable, so it could be derivatived, however der(x) = if time < 0.5 then cos(time) else der(xd); involed in der(xd) which is not allowed.

In OpenModelica lastest release v1.22.3,

  1. DiscreteRealDerTest can be simulated, and y = if time < 0.5 then cos(time) else 0;
  2. Real yd = der(xd); will get a compile error.

The DiscreteRealDerTest requires more analysis, see the end. Clearly the yd should be an error.

DiscreteRealDerTest is a simplify model of Modelica.Electrical.Spice3.Examples.Nor and Modelica.Electrical.Spice3.Examples.Spice3BenchmarkFourBitBinaryAdder in Modelica Standard Library 4.0, this two standard models both use Modelica.Electrical.Spice3.Sources.V_pulse which resulted in derivative a discrete variable.

I don't see that those models in MSL have the same issue. The reason is that if you write an equation involving discrete variables the new variable isn't discrete, especially not when involving other variables. So in Modelica.Electrical.Spice3.Sources.V_pulse the variable T0 is discrete but v isn't, and we differentiate something related to v, and the model is designed to ensure that v is continuous.

--

Regarding: DiscreteRealDerTest: Dymola as default will stop when simulating it, since it involves differentiating an expression that jumps, and thus the derivative will be infinite at some points.

Just ignoring infinite derivatives will generate bad result, and should simply not be done.

However, if you set Advanced.Translation.ImpulseWhenDifferentiatingDiscontinuity = true; then Dymola 2024x (and later) will differentiate it generating impulses such that if you add the following to the model:

public
  Real z;
initial equation
  z=x;
equation
  der(z)=2*y;

You will see that z is two times x and that z jumps (similarly as x), even though its derivative is plotted to be zero after 0.5s. However, that is not standard Modelica yet - as a description of impulses will require more.

I don't know whether OpenModelica handles the impulse by default (as when setting the flag in Dymola), or just produces the wrong result.

HansOlsson avatar Apr 19 '24 07:04 HansOlsson

Or to clarify further:

  • Differentiating an expression indirectly involving a discrete variable may be ok, as long as the expression itself is continuous. (This is the case in MSL.)
    • For the future we might consider impulses if not continuous.
  • If it is just the discrete variable it clearly cannot be continuous.

HansOlsson avatar Apr 19 '24 07:04 HansOlsson

In Dymola 2024x, 2023-10-16, trival version

  • Advanced.Translation.ImpulseWhenDifferentiatingDiscontinuity = true is not supported
  • DiscreteRealDerTest terminates at 0.6s consistent with your comment @HansOlsson
  • The following model will cause "Translation aborted" with reason "Failed to reduce the DAE index"
model DiscreteRealDerTest2
  Real xd(start = 0);
  Real x;
  Real y;
equation 
  when sample(0, 0.1) then
    xd = 0;
  end when;
  x = 2 * xd + 1; 
  y = der(x);
end DiscreteRealDerTest2;

TongYuan-MC avatar Apr 20 '24 01:04 TongYuan-MC

My conclusions:

  • As far as I understand there is no issue in the specification. I don't know if OpenModelica uses impulses, or generates incorrect results.
  • Allowing impulse-handling would be interesting, but it should likely be an MCP, and I think we need to check the interest for it.

HansOlsson avatar May 16 '24 14:05 HansOlsson

@HansOlsson I haven't tried the advanced impulse dymola setting yet, but it seems to me like there may be a connection to my other issue raised here: https://github.com/modelica/ModelicaSpecification/issues/3298

I want to do something like the following in a way that handles discrete jumps in input variable u:

block ContinuousEdge
  input Real u;
  output Boolean y;
equation
  y=der(u)>0;
end ContinuousEdge;

I'll give it a try later. Nonetheless, I would very much be in favor of an MCP here if it allows what I'm after.

Edit: Ok, I gave this a try. The model no longer fails to simulate at the discontinuity, but it doesn't produce the desired result as detailed in the comparison with simulink.

mestinso avatar Aug 09 '24 02:08 mestinso

@HansOlsson I haven't tried the advanced impulse dymola setting yet, but it seems to me like there may be a connection to my other issue raised here: #3298

I want to do something like the following in a way that handles discrete jumps in input variable u:

block ContinuousEdge
  input Real u;
  output Boolean y;
equation
  y=der(u)>0;
end ContinuousEdge;

The idea of checking the sign of the derivative without explicitly computing the derivate is something we could consider (and somewhat separate from this issue - if we continue that it should likely be in #3298; even if there might also be an exception for discrete Real variables). However, I don't know exactly how to do it - does anyone else have suggestions?

HansOlsson avatar Aug 30 '24 11:08 HansOlsson