Opened 7 years ago

Closed 6 years ago

#4868 closed defect (fixed)

Issue with Integer-Real conversions in min/max functions with the NF

Reported by: Francesco Casella Owned by: Per Östlund
Priority: high Milestone: 2.0.0
Component: New Instantiation Version:
Keywords: Cc:

Description

Please check the simulation results of Modelica.Electrical.Analog.Examples.OpAmps.Comparator. The output of the comparator remains constant instead of being a square wave.

The root cause of the problem is that instead of having Rn = Rp = 500 we get Rp = 1000, Rn = 0.

The equations in the source code are

Rp = R*(1 + alpha*(T_heatPort - T_ref))*(1 - min(1, max(0, rInt)));
Rn = R*(1 + alpha*(T_heatPort - T_ref))*min(1, max(0, rInt));

The corresponding flattened equations with the NF are

potentiometer.Rp = potentiometer.R * (1.0 + potentiometer.alpha * (potentiometer.T_heatPort - potentiometer.T_ref)) *
  /*Real*/(1 - min(1, max(0, potentiometer.rInt)));
potentiometer.Rn = potentiometer.R * (1.0 + potentiometer.alpha * (potentiometer.T_heatPort - potentiometer.T_ref)) *
  /*Real*/(min(1, max(0, potentiometer.rInt)));

while the old FE gives:

potentiometer.Rp = potentiometer.R * (1.0 + potentiometer.alpha * (potentiometer.T_heatPort - potentiometer.T_ref)) *
  (1.0 - min(1.0, max(0.0, potentiometer.rInt)));
potentiometer.Rn = potentiometer.R * (1.0 + potentiometer.alpha * (potentiometer.T_heatPort - potentiometer.T_ref)) *
  min(1.0, max(0.0, potentiometer.rInt));

Apparently, the NF casts the Real argument of min and max to Integer rather casting the Integer argument to Real, and later casts the result back to Real, leading to a completely wrong result.

According to the specification 10.3.4, "min(x,y) returns the least element of the scalars x and y; as defined by <", so I guess when comparing a Real and an Integer, the latter should be cast to the former, and not the other way round.

Change History (3)

comment:1 by Francesco Casella, 7 years ago

With this this commit the output changed to a runtime error because of division by zero Rn.

Version 0, edited 7 years ago by Francesco Casella (next)

comment:2 by Martin Sjölund, 7 years ago

Current code:

  function typeMinMaxCall
    input Call call;
    input ExpOrigin.Type origin;
    input SourceInfo info;
    output Expression callExp;
    output Type ty;
    output Variability var;
  protected
    Call argtycall;
    Function fn;
    list<TypedArg> args;
    TypedArg start,interval;
  algorithm
    argtycall as ARG_TYPED_CALL(_, args, _) := typeNormalCall(call, origin, info);
    argtycall := matchTypedNormalCall(argtycall, origin, info);
    callExp := Expression.CALL(unboxArgs(argtycall));
    ty := Type.arrayElementType(Util.tuple32(listHead(args)));
    var := variability(argtycall);
    // TODO: check basic type in two argument overload.
    // check arrays of simple types in one argument overload.
    // fix return type.
  end typeMinMaxCall;

comment:3 by Per Östlund, 6 years ago

Resolution: fixed
Status: newclosed

Fixed in fa177e77. The model also simulates and the comparator seems to be correct too as far as I can determine.

Note: See TracTickets for help on using tickets.