3

I'd like to figure out whether it's possible (and semantically legal) in Modelica to simulate a model of a first-order transfer function, with a time constant equal to zero (T below). I'm using OpenModelica 1.15.0~dev-48-g3656b95, but I'm asking the question in a general Modelica context.

My context is experimenting Model Order Reduction on Modelica models, which brings me to try to use the Modelica.Blocks.Continuous.FirstOrder with a sometimes null time constant. However, to make the discussion simpler, here is the flat model I'm working on (a simplification and adaptation of the standard FirstOrder block):

model FirstOrderZero
  import Modelica.SIunits;

  Real u "input";
  Real y "output";

  parameter Real k(unit="1")=1 "Gain";
  constant SIunits.Time T=0 "Time Constant";

equation
  u = 1;
  der(y) = (k*u - y)/T;

end FirstOrderZero;

I understand that the way Modelica tools operate a symbolic equation analysis, the time constant T should be constant rather than a parameter. Indeed, for T=0, the differential equation gets degenerated into an algebraic equation y = k*u. Unless the Modelica simulation tool can generate different code pathways for different values of T (which I think no Modelica tool does, except maybe Modia in the future?), the fact that T is null or not should be decided at the beginning of the equation analysis.

What I don't understand is why the above model fails to simulate ("division by zero at time 0 [...] where divisor expression is 0.0" with OM 1.15 dev) whereas it works when the last equation is rewritten as:

 T*der(y) = (k*u - y);

I would assume that the symbolic equation analysis should reformulate the equation automatically? (I can see with OM Transformational Debugger that the equation becomes der(y) = (k - y)/0.0 which, of course, breaks at simulation).

Or perhaps, is it syntactically illegal to write Modelica equations with a division by a null constant?

Pierre H.
  • 388
  • 1
  • 11

1 Answers1

3

Variability of T

If the time constant T is constant, a parameter, or maybe a (discrete) variable depends on what you want to do.

  • the value of constants gets fixed during translation
  • parameters can be changed after translation (so before a simulation is started), but not during simulation
  • discrete variables can change their value during simulation, but only at event instances
  • continuous variables can change their value during simulation

See 4.4.4 Component Variability Prefixes discrete, parameter, constant in the Modelica Specification 3.4 for details.

For first order elements you usually use a transfer function that will not change during simulation, but the user should be able to set the value of T. Therefore parameter would be the natural choice.

Why your simulation fails

By using a constant for T, the Modelica tool can optimize your equations more than it can when you use a parameter. And depending on how you write your equations, you will end up with a different optimized equation.

For constant T=0 your original model reduces to

model FirstOrderZero
  Real u, y;
  parameter Real k=1;
equation 
  u = 1;
  der(y) = (k*u - y)/0;
end FirstOrderZero;

To solve y its derivative der(y) is needed - but it can not be computed, as a division by zero always occurs.

In the second case with T*der(y) = (k*u - y); your model reduces to

model FirstOrderZero
  Real u, y;
  parameter Real k=1;
equation 
  u = 1;
  0 * der(y) = (k*u - y);
end FirstOrderZero;

The equation 0 * der(y) = (k*u - y) results in 0 = (k*u - y) and therefore y = k*u. There is no division by zero and the model can be simulated.

You see, even though Modelica is an acausal language, it can matter how you write your equations.

What you can do

A first order element with T=0 is not a first order element anymore, but only a proportional gain. To model that, use the block Modelica.Blocks.Continuous.TransferFunction.

If T is not zero, parametrize it like this:

Modelica.Blocks.Continuous.TransferFunction transferFunction(b={k}, a={T,1})

and if its zero use

Modelica.Blocks.Continuous.TransferFunction transferFunction(b={k}, a={1})
marco
  • 5,944
  • 10
  • 22
  • To make my question more precise (and maybe it is a silly one): I'm looking for a reference (for example the Modelica spec) which states that equations with a division by 0 are incorrect. Otherwise, why the symbolic equation analyzer could not cancel it? Agreed, this would involve multiplying the equation by 0, which indeed doesn't an equivalent equation. – Pierre H. Apr 22 '20 at 13:03
  • I just checked that `Modelica.Blocks.Continuous.TransferFunction transferFunction(b={k}, a={T,1})` with `T` being a constant equal to zero fails similarly (division by 0 at time 0). This is coherent. – Pierre H. Apr 22 '20 at 13:09
  • Well, divisions by zero are illegal. If you have a division by zero in your translated model you have a problem. In the example above we saw that the same equation could result in a division by zero or not, depending on how you write it. – marco Apr 22 '20 at 13:11
  • Regarding your second comment: Of course. That's why you have to use `a={1}` in that case. – marco Apr 22 '20 at 13:12
  • Multiplying an equation divided by 0 is not allowed. You would end up with `0/0` which is not defined. – marco Apr 22 '20 at 13:18
  • 2
    Thanks @marco for your feedback. So I may summarize the reasoning like this: 1) it *mathematically* illegal to "simplify" a zero at the denominator of an equation so no Modelica engine would do this. 2) OpenModelica doesn't detect that the equation is broken by containing `.../0` so it generates a corresponding C code 3) The compiled model crashes with a classical "division by zero" error. So all seems perfectly logical now, except maybe at step 2), where OM could raise an error, isn't it? – Pierre H. Apr 22 '20 at 13:27
  • 2
    Exactly, good summary. If the tool should throw an error at step 2 is questionable. The code can be generated, so the the translation process is fine. Note that Dymola also translates the model, but it gives the warning `Evaluation caused division by zero (T=0), in (k*u-y)/T`. – marco Apr 22 '20 at 13:58