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;