【问题标题】:Avoid chattering in a block that finds the index of the highest value in a vector避免在找到向量中最大值的索引的块中喋喋不休
【发布时间】:2018-07-15 02:22:36
【问题描述】:

Modelica 新手尝试构建一个块来识别一组实数值(向量)中的最大值。

我尝试了两种版本 - 一种只给我最高值的索引,另一种会切换相应布尔向量的值。

两者都失败了。对于某些高输入值,模型(几乎)工作,但大多数时候我收到一条错误消息:“在时间 0.0277777777839..0.0277777778544 左右检测到抖动(连续 100 个状态事件,总时间增量小于步长 0.02 )。这可能是性能瓶颈。使用 -lv LOG_EVENTS 了解更多信息。过零是:indexMaxBool1.temp > indexMaxBool1.tempMax"

我在 Google 上搜索了涉及喋喋不休的错误消息,并找到了将 IF 语句替换为 WHEN 的答案。我只是害怕,后者不会根据需要频繁地提高计算(仅一次???需要重置吗?)。

如果能得到一些关于如何避免这种喋喋不休的提示,我将不胜感激。

到目前为止,这是我的模型:

阻止获取最高值的索引:

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 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;

测试模型:

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;

和:

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;

【问题讨论】:

    标签: modelica openmodelica


    【解决方案1】:

    我找到了一个解决方案 - 但我不知道它为什么有效。 我删除了中间变量 temp 并直接使用 v 值。瞧!

    如果 v[i]>maxTemp 则...

    我把这个问题留在这里,可能对某人有帮助。

    【讨论】:

    • 有一种可能的解释:关系 temp>tempMax 应该为 for 循环的每次迭代生成一个交叉函数。但是,如果 OpenModelica 中的交叉函数不是基于 for 循环迭代,而是基于关系中的变量,那么 for 循环的不同迭代将用不同的值覆盖相同的交叉函数,从而导致混乱。这就解释了为什么使用下标变量 v[I] 可以避免这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-16
    • 2016-06-11
    相关资源
    最近更新 更多