我正在尝试通过编译的 FMU 或导出的 Dymola 源代码找到一种方法来访问 dymola 中模型的 jacobian。
最终目标是使用相同的程序来访问更复杂的多体车辆模型(205 个状态)的雅可比。
使用fmi2GetDirectionalDerivative()
FMI 标准似乎很有希望,所以我制作了一个简单的线性车辆模型来测试它。
model Vehicle "Single-track Linear bicycle vehicle model"
extends Modelica.Blocks.Icons.Block;
import SI = Modelica.SIunits;
import MB = Modelica.Mechanics.MultiBody;
// model parameters
parameter SI.Velocity u = 10 "forward velocity";
parameter SI.Inertia Iz = 2000 "yaw moment of inertia";
parameter SI.Length L = 3 "wheel base";
parameter SI.Mass Mf = 900 "front axle mass";
parameter SI.Mass Mr = 600 "rear axle mass";
parameter Real Cf(unit="N/rad") = 300000 "front axle cornering stiffness";
parameter Real Cr(unit="N/rad") = 200000 "rear axle cornering stiffness";
// calculated parameters
final parameter SI.Mass M = Mf + Mr "mass";
final parameter SI.Length a = Mr/Mf*L "CG position front";
final parameter SI.Length b = L - a "CG position front";
input SI.Angle delta "steering angle" annotation(Dialog(group="Inputs"));
public
SI.Velocity v "lateral velocity";
output SI.Acceleration ay "lateral acceleration";
SI.AngularVelocity r "yaw rate";
equation
ay = der(v) + u*r;
M*(der(v) + u*r) = Cf*(delta-(v+a*r)/u) + Cr*(-(v-b*r)/u);
Iz*der(r) = a*Cf*(delta-(v+a*r)/u) - b*Cr*(-(v-b*r)/u);
end Vehicle;
该模型具有:
- 州 -
v
和r
- 输入 -
delta
- 输出 -
ay
对于本次测试,
delta=amp*sin(2*Modelica.Constants.pi*freq*time)
和amp = 1*Modelica.Constants.pi/180
freq = 0.5
版本:Dymola 2020x
- 求解器:RKFIX2
- 时间步长:0.01s
- 协同仿真 FMU
由于这是一个线性模型,所以雅可比在整个模拟过程中应该是一个恒定值。对于这个模型,当我设置 flag 时Advanced.GenerateAnalyticJacobian = true
,我会得到以下模型 jacobian 的值,这些值是根据已知fmi2GetDirectionalDerivative()
和未知的所有组合计算得出的。在所有情况下,dvKnown = 1
对于功能。
根据状态空间方程,这些值是正确的:
+--------------+----------+
| Derivative | Value |
+--------------+----------+
| der(v)/delta | 200 |
+--------------+----------+
| ay/delta | 200 |
+--------------+----------+
| der(r)/delta | 300 |
+--------------+----------+
| der(v)/v | -33.3333 |
+--------------+----------+
| ay/v | -33.3333 |
+--------------+----------+
| der(r)/v | -20 |
+--------------+----------+
| der(v)/r | -36.6667 |
+--------------+----------+
| ay/r | -26.6667 |
+--------------+----------+
| der(r)/r | -70 |
+--------------+----------+
但是,如果我设置 flag Advanced.GenerateAnalyticJacobian = false
,我会得到以下完全垃圾值:
+--------------+-----------+
| Derivative | Value |
+--------------+-----------+
| der(v)/delta | -1.57E+11 |
+--------------+-----------+
| ay/delta | -1.57E+11 |
+--------------+-----------+
| der(r)/delta | 1.52942 |
+--------------+-----------+
| der(v)/v | -9.12E+08 |
+--------------+-----------+
| ay/v | -9.12E+08 |
+--------------+-----------+
| der(r)/v | 14999.8 |
+--------------+-----------+
| der(v)/r | 5.47E+11 |
+--------------+-----------+
| ay/r | 5.47E+11 |
+--------------+-----------+
| der(r)/r | -2.25E+07 |
+--------------+-----------+
我希望该值与分析值不同,因为它是数值计算的,但我不明白为什么它完全错误。
我尝试启用其他一些标志(Advanced.AllowNumericDifferentiation
, Advanced.AutomaticDifferentiation
)并将求解器更改为 CVODE、DASSL 等,但值仍然不正确。
不幸的是,Dymola 无法为大型模型计算分析雅可比,因此我无法使用该选项。我读过的所有文献都指向fmi2GetDirectionalDerivative()
.
我将不胜感激有关如何将模型 jacobian 从 FMU 中取出的任何意见。
如果有其他方法可以通过 Dymola 使用,那也可以,因为我们有源代码导出许可证。