如何使用 Dymola 为特定变量设置收敛公差?
How to set a convergence tolerance to an specific variable using Dymola?
所以,我有一个带有压力损失的管道模型,其中未知量是质量流量。通常,在这个问题的大多数模型上,守恒方程用于计算质量流量,但是这样的模型有很多收敛问题(因为管末端的阻塞流导致无穷大的压力导数在结束)。请参见下图,左侧是问题的表示,右侧是显示无限压力导数的图表。
因此,我使用的是一个更稳健的模型,尽管它输出的不是质量流量而是管长,这是已知的。因此需要一个迭代循环来确定质量流量。好吧,我编写了一个函数 length
,在给定管道几何形状、质量流量和边界条件的情况下,它输出计算出的管道长度,并使方程式如下:
parameter Real L;
Real m_flow;
...
equation
L = length(geometry, boundary, m_flow)
它模拟得很好,但它需要很长时间......而且它不应该因为质量流量对管长度相当不敏感,例如。 if L=3
如果 length 的输出在 L ± 0.1
以内,我可以说 m_flow
已经收敛。另一方面,Dymola 中 DASSL 的默认收敛容差是 0.0001
,这对所有其他变量都很好,但我的模型在这里是一个重大挫折...
话虽如此,我想知道是否有设置特定公差 L
(来自 annotations
或其他)的(hacky)方法。我无法在网上或 Dymola 的用户手册中找到任何解决方案......到目前为止,我通过制作第二个函数来管理解决方法,该函数使用 Newton-Raphson 方法来确定质量流量,例如:
function massflowrate
input geometry, boundary, m_flow_start, tolerance;
output m_flow;
protected
Real error, L, dL, dLdm_flow, Delta_m_flow;
algorithm
error = geometry.L;
m_flow = m_flow_start;
while error>tolerance loop
L = length(geometry, boundary, m_flow);
error = abs(boundary.L - L);
dL = length(geometry, boundary, m_flow*1.001);
dLdm_flow = dL/(0.001*m_flow);
Delta_m_flow = (geometry.L - L)/dLdm_flow;
m_flow = m_flow + Delta_m_flow;
end while;
end massflowrate;
然后我在方程式部分使用它:
parameter Real L;
Real m_flow;
...
equation
m_flow = massflowrate(geometry, boundary, delay(m_flow,10), tolerance)
然而,这个解决方案并非没有问题,真正的方程是 非常 非线性的,并且取决于边界条件,求解器会达到一个永无止境的循环... =/
PS:对于冗长的 post 和缺少 MWE,我深表歉意,真正的方程式非常长,并且包含大量的热力学,我认为这没有任何帮助, 不过有需要的话我可以提供实物模型
长度函数是否平滑?对我来说,它不平滑似乎是问题的可能原因,@Phil 的建议也可能是个好主意。
不过,也应该可以按如下方式做你想做的事:
Real m_flow(nominal=1e9);
解释:方程通常求解到 unknowns 中的某个公差 - 在这种情况下 m_flow.
每个变量的公差是一个relative/absolute公差,考虑到标称值,Dymola不允许您为不同的变量设置不同的公差。
因此,计算 m_flow 不太准确的简单方法是为它设置一个较高的标称值,因为误差容限将是 tol*(abs(m_flow)+abs(nominal(m_flow)))
或类似的东西。
缺点是它可能太不准确,例如导致其他事件,或者错误是如此随机以至于求解器仍然变慢。
所以,我有一个带有压力损失的管道模型,其中未知量是质量流量。通常,在这个问题的大多数模型上,守恒方程用于计算质量流量,但是这样的模型有很多收敛问题(因为管末端的阻塞流导致无穷大的压力导数在结束)。请参见下图,左侧是问题的表示,右侧是显示无限压力导数的图表。
因此,我使用的是一个更稳健的模型,尽管它输出的不是质量流量而是管长,这是已知的。因此需要一个迭代循环来确定质量流量。好吧,我编写了一个函数 length
,在给定管道几何形状、质量流量和边界条件的情况下,它输出计算出的管道长度,并使方程式如下:
parameter Real L;
Real m_flow;
...
equation
L = length(geometry, boundary, m_flow)
它模拟得很好,但它需要很长时间......而且它不应该因为质量流量对管长度相当不敏感,例如。 if L=3
如果 length 的输出在 L ± 0.1
以内,我可以说 m_flow
已经收敛。另一方面,Dymola 中 DASSL 的默认收敛容差是 0.0001
,这对所有其他变量都很好,但我的模型在这里是一个重大挫折...
话虽如此,我想知道是否有设置特定公差 L
(来自 annotations
或其他)的(hacky)方法。我无法在网上或 Dymola 的用户手册中找到任何解决方案......到目前为止,我通过制作第二个函数来管理解决方法,该函数使用 Newton-Raphson 方法来确定质量流量,例如:
function massflowrate
input geometry, boundary, m_flow_start, tolerance;
output m_flow;
protected
Real error, L, dL, dLdm_flow, Delta_m_flow;
algorithm
error = geometry.L;
m_flow = m_flow_start;
while error>tolerance loop
L = length(geometry, boundary, m_flow);
error = abs(boundary.L - L);
dL = length(geometry, boundary, m_flow*1.001);
dLdm_flow = dL/(0.001*m_flow);
Delta_m_flow = (geometry.L - L)/dLdm_flow;
m_flow = m_flow + Delta_m_flow;
end while;
end massflowrate;
然后我在方程式部分使用它:
parameter Real L;
Real m_flow;
...
equation
m_flow = massflowrate(geometry, boundary, delay(m_flow,10), tolerance)
然而,这个解决方案并非没有问题,真正的方程是 非常 非线性的,并且取决于边界条件,求解器会达到一个永无止境的循环... =/
PS:对于冗长的 post 和缺少 MWE,我深表歉意,真正的方程式非常长,并且包含大量的热力学,我认为这没有任何帮助, 不过有需要的话我可以提供实物模型
长度函数是否平滑?对我来说,它不平滑似乎是问题的可能原因,@Phil 的建议也可能是个好主意。
不过,也应该可以按如下方式做你想做的事:
Real m_flow(nominal=1e9);
解释:方程通常求解到 unknowns 中的某个公差 - 在这种情况下 m_flow.
每个变量的公差是一个relative/absolute公差,考虑到标称值,Dymola不允许您为不同的变量设置不同的公差。
因此,计算 m_flow 不太准确的简单方法是为它设置一个较高的标称值,因为误差容限将是 tol*(abs(m_flow)+abs(nominal(m_flow)))
或类似的东西。
缺点是它可能太不准确,例如导致其他事件,或者错误是如此随机以至于求解器仍然变慢。