当 OpenModelica 中的 StopTime 太高时,FFT 的仿真结果错误或没有仿真结果

Wrong or no simulation results of FFT when StopTime ist too high in OpenModelica

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

到目前为止我发现了什么: 我有一个 samplePeriod=8.3us,样本数 ns=6000,最大频率为 f_max=12kHz,分辨率为 f_res=20Hz,这导致 stopTime>=(6000-1 )*8.3us --> stopTime>=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-file 已经是 1.06 GB。在 0.1 秒内,您得到大约 2.1 GB 和损坏的 header.

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

在 Dymola 2019 中工作,但需要很长时间才能打开结果文件。