Reputation: 433
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?
Upvotes: 3
Views: 354
Reputation: 6655
If the time constant T
is constant, a parameter, or maybe a (discrete) variable depends on what you want to do.
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.
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.
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})
Upvotes: 3