当 StopTime 在 OpenModelica 中太高时,FFT 的模拟结果错误或没有



我正在使用带有OpenModelica的realFFT库来分析PWM信号中的频率。 当我分析低于 10 kHz 的频率时,一切正常。 但是,一旦我将最大频率设置为10 kHz以上,我的模拟要么计算错误的结果,要么崩溃,要么说它模拟但没有显示结果。

到目前为止,我发现了什么: 我有一个samplePeriod=8.3us,样本数量ns=6000,最大频率为f_max=12kHz,分辨率为f_res=20Hz,导致停止时间>=(6000-1)*8.3us -->停止时间>=0.05s(根据图书馆)。 所以我用这个 stopTime 模拟并且它有效,但是当我设置 stopTime=0.1s 时,它没有显示任何结果,但说它模拟得很好。当我进一步将停止时间增加到 0.2 秒时,它计算出错误的结果。

这对我来说没有意义,为什么它会随着停止时间的增加而失败? 这可能是另一个OpenModelica问题,并且可以在Dymola上运行良好吗?

这是我的模型:

model TestRealFFT
Modelica.Blocks.Sources.Pulse pulse1(amplitude = 1, offset = 0, period = 100e-6, width = 40) annotation(
Placement(visible = true, transformation(origin = {-168, 16}, extent = {{-60, -60}, {60, 60}}, rotation = 0)));
FFTmath fFTmath1(f_max = 12000, f_res = 20) annotation(
Placement(visible = true, transformation(origin = {176, 8}, extent = {{-80, -80}, {80, 80}}, rotation = 0)));
equation
connect(pulse1.y, fFTmath1.u) annotation(
Line(points = {{-102, 16}, {68, 16}, {68, 8}, {80, 8}}, color = {0, 0, 127}));
annotation(
stopTime = 2,
Diagram(coordinateSystem(extent = {{-300, -250}, {300, 250}})),
Icon(coordinateSystem(extent = {{-300, -250}, {300, 250}})),
__OpenModelica_commandLineOptions = "",
experiment(StartTime = 0, StopTime = 0.2, Tolerance = 1e-06, Interval = 8e-06));
end TestRealFFT;

model FFTmath
import Modelica.Constants.{pi};
import Modelica.Math.FastFourierTransform.*;
import Modelica.SIunits.*;
Modelica.Blocks.Interfaces.RealInput u annotation(
Placement(visible = true, transformation(origin = {-120, 0}, extent = {{-20, -20}, {20, 20}}, rotation = 0), iconTransformation(origin = {-120, 0}, extent = {{-20, -20}, {20, 20}}, rotation = 0)));
parameter Frequency f_max = 12000 "Maximum frequency of interest";
parameter Frequency f_res = 20 "Frequency resolution";
final parameter Integer ns = realFFTsamplePoints(f_max, f_res, f_max_factor = 5) "Number of samples";
final parameter Integer nf = div(ns, 2) + 1 "Number of frequency points";
final parameter Integer nfi = max(1, min(integer(ceil(f_max / f_res)) + 1, nf));
final parameter Frequency f_i[nfi](each fixed = false) "FFT frequencies of interested frequency points";
parameter Time samplePeriod = 1 / (2 * f_res * div(ns, 2));
output Integer info(start = 0, fixed = true) "Information flag from FFT computation";
Integer iTick(start = 0, fixed = true);
discrete Real Buf[ns](start = zeros(ns), each fixed = true) "Input buffer";
Real A_i[nfi](start = zeros(nfi), each fixed = true) "FFT amplitudes";
Real Phi_i[nfi](start = zeros(nfi), each fixed = true) "FFT phases";
Real y(start = 0, fixed = true);
// "Signal from which FFT is computed";
initial equation
for i in 1:nfi loop
f_i[i] = (i - 1) * f_res;
end for;
equation
algorithm
when sample(0, samplePeriod) then
iTick := iTick + 1;
y := u;
if iTick <= ns then
Buf[iTick] := y;
end if;
if iTick == ns then
(info, A_i, Phi_i) := realFFT(Buf, nfi);
end if;
end when;
//3 * sin(2  * pi * f1 * time) + sin(2 * pi * f2 * time);
annotation(
Documentation(Icon(graphics = {Text(origin = {-42, 62}, extent = {{110, -78}, {-30, 18}}, textString = "FFT"), Rectangle(origin = {0, -79}, fillPattern = FillPattern.Solid, extent = {{-80, -1}, {80, 1}}), Rectangle(origin = {-79, -49}, fillPattern = FillPattern.Solid, extent = {{-1, -29}, {1, 29}}), Polygon(origin = {-79, -15}, fillPattern = FillPattern.Solid, points = {{0, -5}, {-6, -5}, {0, 5}, {6, -5}, {6, -5}, {0, -5}}), Polygon(origin = {85, -79}, rotation = -90, fillPattern = FillPattern.Solid, points = {{0, -5}, {-6, -5}, {0, 5}, {6, -5}, {6, -5}, {0, -5}}), Rectangle(origin = {-59, -65}, fillPattern = FillPattern.Solid, extent = {{-1, 23}, {1, -15}}), Ellipse(origin = {-59, -39}, fillPattern = FillPattern.Solid, extent = {{-3, 3}, {3, -3}}, endAngle = 360), Ellipse(origin = {-49, -61}, fillPattern = FillPattern.Solid, extent = {{-3, 3}, {3, -3}}, endAngle = 360), Ellipse(origin = {-19, -53}, fillPattern = FillPattern.Solid, extent = {{-3, 3}, {3, -3}}, endAngle = 360), Ellipse(origin = {25, -67}, fillPattern = FillPattern.Solid, extent = {{-3, 3}, {3, -3}}, endAngle = 360), Ellipse(origin = {31, -49}, fillPattern = FillPattern.Solid, extent = {{-3, 3}, {3, -3}}, endAngle = 360), Rectangle(origin = {-49, -65}, fillPattern = FillPattern.Solid, extent = {{-1, 1}, {1, -15}}), Rectangle(origin = {31, -65}, fillPattern = FillPattern.Solid, extent = {{-1, 15}, {1, -15}}), Rectangle(origin = {-19, -63}, fillPattern = FillPattern.Solid, extent = {{-1, 7}, {1, -15}}), Rectangle(origin = {25, -63}, fillPattern = FillPattern.Solid, extent = {{-1, -5}, {1, -15}}), Ellipse(origin = {-67, -61}, fillPattern = FillPattern.Solid, extent = {{-3, 3}, {3, -3}}, endAngle = 360), Rectangle(origin = {-67, -63}, fillPattern = FillPattern.Solid, extent = {{-1, 1}, {1, -15}}), Rectangle(origin = {37, -63}, fillPattern = FillPattern.Solid, extent = {{-1, -5}, {1, -15}}), Ellipse(origin = {37, -67}, fillPattern = FillPattern.Solid, extent = {{-3, 3}, {3, -3}}, endAngle = 360), Line(points = {{-100, 100}, {100, 100}, {100, -100}, {-100, -100}, {-100, 100}, {-100, 100}}, thickness = 0.5)}),
Diagram,
__OpenModelica_commandLineOptions = "");
end FFTmath;

我非常感谢任何帮助!

看起来像OpenModelica中的一个错误。请在 trac.openmodelica.org 上打开有关它的票证。

问题 1巨大的结果文件中断
使用 OpenModelica (v1.14.0-dev-26633-gd9901afc5b) 进行 0.05 秒模拟时,结果 mat 文件已经为 1.06 GB。在 0.1 秒内,您会得到大约 2.1 GB 和一个损坏的标头。

问题 2错误的结果
当您模拟区间 [0, 0.2] 时,解决方案是完全错误的。y的值在 1.4e+31 左右,time上升到 5e+218。可能是因为结果文件损坏。
但是,即使您降低容差和间隔,它也无法正确模拟,这可能是因为事件数量巨大。

适用于 Dymola 2019,但需要大量时间才能打开结果文件。

最新更新