1

Modelica Newbie trying to build a block that identifies the highest value of a set of real values (vector).

I tried two versions - one which would just give me the index of the highest value and one which would switch the value of a corresponding boolean vector.

Both failed. For certain high input values the model worked (almost), but most of the time I get an error saying: "Chattering detected around time 0.0277777777839..0.0277777778544 (100 state events in a row with a total time delta less than the step size 0.02). This can be a performance bottleneck. Use -lv LOG_EVENTS for more information. The zero-crossing was: indexMaxBool1.temp > indexMaxBool1.tempMax"

I googled error messages involving chattering and found answers telling to replace the IF-statement by WHEN. I only am affraid, that the latter won't raise the calculation as often as needed (only once??? Does it need a reset?).

I would appreciate getting some hints on how to avoid that chattering.

Here are my models so far:

Block to get the index of the highest value:

block IndexMax
  extends Modelica.Blocks.Icons.Block;
  parameter Integer nin=1 "Number of inputs";
  Modelica.Blocks.Interfaces.RealInput v[nin];
  Modelica.Blocks.Interfaces.IntegerOutput index;

    protected
      Real tempMax;
      Real temp;

algorithm
   if size(v,1)>1 then
     tempMax := v[1];
     index := 1;

     for i in 2:size(v,1) loop
       temp := v[i];
       if temp > tempMax then
        tempMax := temp;
        index := i;
       end if;
     end for;
  else
    index :=0;
  end if;

end IndexMax;

Block to get a vector of boolean values, with one switched on at the index of the highest input:

block IndexMaxBool
  extends Modelica.Blocks.Icons.Block;
  parameter Integer nin = 1 "Number of inputs";
  Modelica.Blocks.Interfaces.RealInput v[nin];
  Modelica.Blocks.Interfaces.BooleanOutput bool[nin];
protected
  Real tempMax;
  Real temp;
  Integer index;
algorithm
  if size(v, 1) > 1 then
    for i in 1:size(v,1) loop
      bool[i] := false;
    end for;
    tempMax := v[1];
    index := 1;

    for i in 2:size(v, 1) loop
      temp := v[i];
      if temp > tempMax then
        tempMax := temp;
        index := i;
      end if;
    end for;
  else
    index := 0;
  end if;
  if index > 0 then
    bool[index]:=true;
  end if;
end IndexMaxBool;

The test Models:

model testMax2
    Modelica.Blocks.Sources.RealExpression realExpression1(y = 1);
    FlowsAndStreams.BDSCalc.IndexMaxBool indexMaxBool1(nin = 3);
    Modelica.Blocks.Interfaces.BooleanOutput y;
    Modelica.Blocks.Interfaces.BooleanOutput y1;
    Modelica.Blocks.Interfaces.BooleanOutput y2;
    Modelica.Blocks.Sources.Sine sine1(amplitude = 2, freqHz = 1, phase = 0.785398);
    Modelica.Blocks.Sources.Sine sine2(amplitude = 2, freqHz = 3);
    equation
      connect(sine1.y, indexMaxBool1.v[2]);
      connect(sine2.y, indexMaxBool1.v[3]);
      connect(indexMaxBool1.bool[3], y2);
      connect(indexMaxBool1.bool[1], y);
      connect(indexMaxBool1.bool[2], y1);
      connect(realExpression1.y, indexMaxBool1.v[1]);
end testMax2;

and:

model testMax
    FlowsAndStreams.BDSCalc.IndexMax indexMax1(nin = 3);
    Modelica.Blocks.Sources.RealExpression realExpression1(y = 1);
    Modelica.Blocks.Sources.RealExpression realExpression2(y = 10);
    Modelica.Blocks.Sources.RealExpression realExpression3(y = 3);
    Modelica.Blocks.Interfaces.IntegerOutput y;
    equation
      connect(realExpression3.y, indexMax1.v[3]) annotation(
        Line(points = {{-69, -40}, {-8, -40}, {-8, 0}}, color = {0, 0, 127}));
      connect(realExpression2.y, indexMax1.v[2]) annotation(
        Line(points = {{-69, 0}, {-8, 0}}, color = {0, 0, 127}));
      connect(realExpression1.y, indexMax1.v[1]) annotation(
        Line(points = {{-69, 30}, {-10, 30}, {-10, 0}, {-8, 0}}, color = {0, 0, 127}));
      connect(indexMax1.index, y) annotation(
        Line(points = {{10, 0}, {50, 0}}, color = {255, 127, 0}));
end testMax;

1 Answer 1

1

I found a solution - but I don't know why it works. I removed the intermediate variable temp and work instead directly with the v values. Voila!

If v[i]>maxTemp then...

I leave this question here, may it help someone.

Sign up to request clarification or add additional context in comments.

1 Comment

There is one possible explanation: The relation temp>tempMax should generate one crossing function for each iteration of the for-loop. However, if the crossing functions in OpenModelica instead of being based on the for-loop iterations are based on the variables in the relation the different iterations of the for-loop will then overwrite the same crossing-function with different values causing a mess. That explains why using subscripted variables v[I] avoids the problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.