如何防止 Modelica 中不必要的事件检测?

How to prevent unnecessary event detection in Modelica?

只有当 S2 为真时,我如何才能在 S1=... 语句中实现 y>1 的事件检测,否则阻止它,因为它只会减慢一般情况下的模拟速度?

model zeroCrossingTest
// BOOLEAN VARIABLE DECLARATIONS 
Boolean S1(start=true, fixed=true);
Boolean S2(start=false, fixed=true);
Boolean S3(start=false, fixed=true);
Real y;
equation
der(y) = -y + 2;

// ================= 
// TRANSITIONS START 
S1 = if pre(S2) then (y>1) else 
        if pre(S1) then not ( (y>0.2)  )
 else false;

S2 = if pre(S1) then (y>0.2) else 
        if pre(S2) then not ( (y>0.5)  or  (y>1)  )
 else false;

S3 = if pre(S2) then (y>0.5) else 
        pre(S3);
end zeroCrossingTest; 

来自 S1 的零交叉 = if pre(S2) then (y>1).. 仍在 OpenModelica 中计算(时间为 0.69 的状态事件),尽管 pre(S2) 为假

UPDATE1:不会产生不必要事件的替代实现..谢谢@marco

model zeroCrossingTest_OriginalImplementation
  // BOOLEAN VARIABLE DECLARATIONS
  Boolean S1(start = true, fixed = true);
  Boolean S2(start = false, fixed = true);
  Boolean S3(start = false, fixed = true);
  Real y;
equation
  der(y) = -y + 2;
// =================
// TRANSITIONS START 
S1 = pre(S2) and y>1 or 
        pre(S1) and not y>0.2;
 
S2 = pre(S1) and y>0.2 or 
        pre(S2) and not ( y>0.5  or  y>1  );
 
S3 = pre(S2) and y>0.5 or 
        pre(S3);
end zeroCrossingTest_OriginalImplementation;

UPDATE2:一个更复杂的模型,它给出相同行为的布尔变量生成不必要的状态事件(对于 y>0.7,y>0.8):

model zeroCrossingTest_OriginalImplementation
Boolean S1(start=true, fixed=true);
Boolean S2(start=false, fixed=true);
Boolean S3(start=false, fixed=true);
Boolean S4(start=false, fixed=true);
Boolean S5(start=false, fixed=true);
Boolean S6(start=false, fixed=true);
  Real y;
equation
  der(y) = -y + 2;
// ================= 
// TRANSITIONS START 
S1 = pre(S2) and (y>1) or 
        pre(S6) and (y>0.8) or 
        pre(S1) and not ( (y>0.2)  );
 
S2 = pre(S1) and (y>0.2) or 
        pre(S2) and not ( (y>0.5)  or  (y>1)  or  (y>0.6)  );
 
S3 = pre(S2) and (y>0.5) or 
        pre(S3);

S4 = pre(S2) and (y>0.6) or 
        pre(S4) and not ( (y>0.65)  );
 
S5 = pre(S4) and (y>0.65) or 
        pre(S5) and not ( (y>0.7)  );
 
S6 = pre(S5) and (y>0.7) or 
        pre(S6) and not ( (y>0.8)  );
end zeroCrossingTest_OriginalImplementation;

更新 3:此实现仅生成必要的事件(总共 2 个事件)。有什么理由反对这种方法吗?

model zeroCrossingTest_OriginalImplementation
Boolean S1(start=true, fixed=true);
Boolean S2(start=false, fixed=true);
Boolean S3(start=false, fixed=true);
Boolean S4(start=false, fixed=true);
Boolean S5(start=false, fixed=true);
Boolean S6(start=false, fixed=true);

Real inS1;
Real inS2;
Real inS3;
Real inS4;
Real inS5;
Real inS6;

  Real y;
equation
  der(y) = -y + 2;
  
// ===================== 
// inState Variables 
inS1= if pre(S1) then 1 else 0;
inS2= if pre(S2) then 1 else 0;
inS3= if pre(S3) then 1 else 0;
inS4= if pre(S4) then 1 else 0;
inS5= if pre(S5) then 1 else 0;
inS6= if pre(S6) then 1 else 0;
  
// ================= 
// TRANSITIONS START 
S1 = pre(S2) and (inS2*y>1) or 
        pre(S6) and (inS6*y>0.8) or 
        pre(S1) and not ( (inS1*y>0.2)  );
 
S2 = pre(S1) and (inS1*y>0.2) or 
        pre(S2) and not ( (inS2*y>0.5)  or  (inS2*y>1)  or  (inS2*y>0.6)  );
 
S3 = pre(S2) and (inS2*y>0.5) or 
        pre(S3);

S4 = pre(S2) and (inS2*y>0.6) or 
        pre(S4) and not ( (inS4*y>0.65)  );
 
S5 = pre(S4) and (inS4*y>0.65) or 
        pre(S5) and not ( (inS5*y>0.7)  );
 
S6 = pre(S5) and (inS5*y>0.7) or 
        pre(S6) and not ( (inS6*y>0.8)  );
end zeroCrossingTest_OriginalImplementation;

我不是 OpenModelica 专家,我不知道为什么 S1 在 OpenModelica 中以 0.69 秒生成和事件(但在 Dymola 中不是,正如 Markus A. 已经指出的那样)。

但在这种情况下,可以通过将 y > 1 比较移动到 if 条件中来防止不必要的事件:

  S1 = if pre(S2) and y > 1 then true 
       else if pre(S1) and not y > 0.2 then true 
       else false;

请注意,考虑到 precedence of operators.

,我删除了大部分大括号

你也可以删除 else if 分支:

  S1 = if pre(S2) and y > 1 or 
          pre(S1) and not y > 0.2 
       then true 
       else false;

因为比较已经 returns 真或假,我们可以删除 if 并简单地写:

  S1 = pre(S2) and y > 1 or 
       pre(S1) and not y > 0.2;