如何防止 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;
只有当 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;