具有零时间常数的一阶 Modelica 模型
First order Modelica model with null time constant
我想弄清楚在 Modelica 中是否有可能(并且在语义上合法)模拟一阶传递函数的模型,时间常数等于零(下面的 T
)。我使用的是 OpenModelica 1.15.0~dev-48-g3656b95,但我是在一般的 Modelica 上下文中提问的。
我的背景是在 Modelica 模型上试验模型降阶,这让我尝试使用 Modelica.Blocks.Continuous.FirstOrder
和 有时为空 时间常数。但是,为了使讨论更简单,这是我正在研究的平面模型(标准 FirstOrder
块的简化和改编):
model FirstOrderZero
import Modelica.SIunits;
Real u "input";
Real y "output";
parameter Real k(unit="1")=1 "Gain";
constant SIunits.Time T=0 "Time Constant";
equation
u = 1;
der(y) = (k*u - y)/T;
end FirstOrderZero;
我理解 Modelica 工具运行符号方程分析的方式,时间常数 T
应该是 constant
而不是 parameter
。实际上,对于 T=0
,微分方程退化为代数方程 y = k*u
。除非 Modelica 仿真工具可以为 T
的不同值生成不同的代码路径(我认为没有 Modelica 工具可以做到这一点,除了未来的 Modia 之外?),T
是否为 null 的事实应该在方程分析开始时决定。
我不明白的是为什么上面的模型无法模拟("division by zero at time 0 [...] where divisor expression is 0.0" 使用 OM 1.15 dev)而 它有效 当最后一个方程被重写为:
T*der(y) = (k*u - y);
我假设符号方程分析应该自动重新制定方程? (我可以通过 OM Transformational Debugger 看到等式变为 der(y) = (k - y)/0.0
,当然,在模拟时会中断)。
或者,用空常量除法编写 Modelica 方程在语法上是非法的吗?
T 的可变性
如果时间常数 T
是常量,则参数或(离散)变量取决于您要执行的操作。
- 常量的值在翻译过程中得到修复
- 翻译后可以更改参数(因此在模拟开始之前),但不能在模拟期间更改
- 离散变量可以在模拟过程中改变它们的值,但只能在事件实例中改变
- 连续变量可以在模拟过程中改变它们的值
有关详细信息,请参阅 Modelica 规范 3.4 中的 4.4.4 Component Variability Prefixes discrete, parameter, constant。
对于一阶元素,您通常使用在模拟过程中不会改变的传递函数,但用户应该能够设置 T
的值。因此 parameter
将是自然的选择。
为什么你的模拟失败了
通过为 T
使用常量,与使用参数相比,Modelica 工具可以更优化您的方程式。根据您编写方程式的方式,您最终会得到不同的优化方程式。
对于 constant T=0
,您的原始模型减少到
model FirstOrderZero
Real u, y;
parameter Real k=1;
equation
u = 1;
der(y) = (k*u - y)/0;
end FirstOrderZero;
要求解 y
需要其导数 der(y)
- 但无法计算,因为总是会被零除。
在第二种情况下 T*der(y) = (k*u - y);
你的模型减少到
model FirstOrderZero
Real u, y;
parameter Real k=1;
equation
u = 1;
0 * der(y) = (k*u - y);
end FirstOrderZero;
等式 0 * der(y) = (k*u - y)
结果 0 = (k*u - y)
,因此 y = k*u
。没有被零除,可以模拟模型
你看,尽管 Modelica 是一种非因果语言,但如何编写方程式可能很重要。
你能做什么
T=0的一阶元件不再是一阶元件,只是比例增益。要对其建模,请使用块 Modelica.Blocks.Continuous.TransferFunction
.
如果 T
不为零,参数化如下:
Modelica.Blocks.Continuous.TransferFunction transferFunction(b={k}, a={T,1})
如果它的零使用
Modelica.Blocks.Continuous.TransferFunction transferFunction(b={k}, a={1})
我想弄清楚在 Modelica 中是否有可能(并且在语义上合法)模拟一阶传递函数的模型,时间常数等于零(下面的 T
)。我使用的是 OpenModelica 1.15.0~dev-48-g3656b95,但我是在一般的 Modelica 上下文中提问的。
我的背景是在 Modelica 模型上试验模型降阶,这让我尝试使用 Modelica.Blocks.Continuous.FirstOrder
和 有时为空 时间常数。但是,为了使讨论更简单,这是我正在研究的平面模型(标准 FirstOrder
块的简化和改编):
model FirstOrderZero
import Modelica.SIunits;
Real u "input";
Real y "output";
parameter Real k(unit="1")=1 "Gain";
constant SIunits.Time T=0 "Time Constant";
equation
u = 1;
der(y) = (k*u - y)/T;
end FirstOrderZero;
我理解 Modelica 工具运行符号方程分析的方式,时间常数 T
应该是 constant
而不是 parameter
。实际上,对于 T=0
,微分方程退化为代数方程 y = k*u
。除非 Modelica 仿真工具可以为 T
的不同值生成不同的代码路径(我认为没有 Modelica 工具可以做到这一点,除了未来的 Modia 之外?),T
是否为 null 的事实应该在方程分析开始时决定。
我不明白的是为什么上面的模型无法模拟("division by zero at time 0 [...] where divisor expression is 0.0" 使用 OM 1.15 dev)而 它有效 当最后一个方程被重写为:
T*der(y) = (k*u - y);
我假设符号方程分析应该自动重新制定方程? (我可以通过 OM Transformational Debugger 看到等式变为 der(y) = (k - y)/0.0
,当然,在模拟时会中断)。
或者,用空常量除法编写 Modelica 方程在语法上是非法的吗?
T 的可变性
如果时间常数 T
是常量,则参数或(离散)变量取决于您要执行的操作。
- 常量的值在翻译过程中得到修复
- 翻译后可以更改参数(因此在模拟开始之前),但不能在模拟期间更改
- 离散变量可以在模拟过程中改变它们的值,但只能在事件实例中改变
- 连续变量可以在模拟过程中改变它们的值
有关详细信息,请参阅 Modelica 规范 3.4 中的 4.4.4 Component Variability Prefixes discrete, parameter, constant。
对于一阶元素,您通常使用在模拟过程中不会改变的传递函数,但用户应该能够设置 T
的值。因此 parameter
将是自然的选择。
为什么你的模拟失败了
通过为 T
使用常量,与使用参数相比,Modelica 工具可以更优化您的方程式。根据您编写方程式的方式,您最终会得到不同的优化方程式。
对于 constant T=0
,您的原始模型减少到
model FirstOrderZero
Real u, y;
parameter Real k=1;
equation
u = 1;
der(y) = (k*u - y)/0;
end FirstOrderZero;
要求解 y
需要其导数 der(y)
- 但无法计算,因为总是会被零除。
在第二种情况下 T*der(y) = (k*u - y);
你的模型减少到
model FirstOrderZero
Real u, y;
parameter Real k=1;
equation
u = 1;
0 * der(y) = (k*u - y);
end FirstOrderZero;
等式 0 * der(y) = (k*u - y)
结果 0 = (k*u - y)
,因此 y = k*u
。没有被零除,可以模拟模型
你看,尽管 Modelica 是一种非因果语言,但如何编写方程式可能很重要。
你能做什么
T=0的一阶元件不再是一阶元件,只是比例增益。要对其建模,请使用块 Modelica.Blocks.Continuous.TransferFunction
.
如果 T
不为零,参数化如下:
Modelica.Blocks.Continuous.TransferFunction transferFunction(b={k}, a={T,1})
如果它的零使用
Modelica.Blocks.Continuous.TransferFunction transferFunction(b={k}, a={1})