在Modelica

时间:2017-02-09 13:59:23

标签: modelica openmodelica

我正在尝试创建一个模型,其中一个Modelica变量是另一个变量的三角波。首先我尝试了floor()函数,如下所示:

model test1
  final constant Real pi=2*Modelica.Math.asin(1.0);
  parameter Real b = 1;
  parameter Real a = 1;
  Real x,p,u;
equation
  if sign(sin(x*pi/b))>=0 then 
    p=a*(x-b*floor(x/b));
  else 
    p=a*(b-(x-b*floor(x/b)));
  end if;
  x=time;
  u = floor(x/b);
end test1

(x =时间;是任意的,因此模型编译)

但结果很奇怪,如下所示 enter image description here

放大:

enter image description here

以某种方式在下一步楼层功能出现意外行为之前0.005秒,并成为以下一个值结束的线性函数。

enter image description here

然后我尝试了ceil()函数。一切似乎都是正确的,直到我意识到ceil()函数在其他值(例如x = 13)

时会发生同样的问题

如果可以,我将不胜感激:

  1. 帮助我理解为什么会发生这种“故障”,如果是故意设计还是错误?
  2. 我该如何解决这个问题?
  3. 有没有其他方法可以创建三角波函数?
  4. P.S。我正在使用这个“波函数”模拟两个锯齿状物体之间的相互作用“

4 个答案:

答案 0 :(得分:4)

如果允许使用Modelica标准库,则可以使用CombiTimeTable块建立参数化的基于时间的Z字形信号,该块具有线性插值和周期性外推。例如,

model Test4
  parameter Real a=2 "Amplitude";
  parameter Real b=3 "Period";
  Real y=zigzag.y[1] "Zigzag";
  Modelica.Blocks.Sources.CombiTimeTable zigzag(
    table=[0,0;b/4,a;b/4,a;b/2,0;b/2,0;3*b/4,-a;3*b/4,-a;b,0],
    extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic)
    annotation(Placement(transformation(extent={{-80,60},{-60,80}})));
  Modelica.Blocks.Sources.Trapezoid trapezoid(
    amplitude=2*a,
    rising=b/2,
    width=0,
    falling=b/2,
    period=b,
    offset=-a)
    annotation(Placement(transformation(extent={{-80,25},{-60,45}})));
  annotation(uses(Modelica(version="3.2.2")));
end Test4;

答案 1 :(得分:2)

我对模拟中的故障没有解释。

但是,我会采用另一种方法来处理锯齿函数:我将其视为向上和向下积分+1和-1的积分器。积分时间决定了锯齿函数的幅度和周期。

下面的图片显示了使用MSL块的实现和使用代码的实现。以下模拟结果对于两种实现都是相同的。

祝你好运, Rene Just Nielsen

方框图: Block diagram implementation代码:

the

模拟结果: enter image description here

答案 2 :(得分:2)

我猜这个问题是由于浮点表示和事件没有在确切的时间发生。

在时间= 0.99时考虑x-floor(x)1-(x-floor(x)),它们是0.990.01;在时间= 1.00时,它们是0.01.0,这会导致您的问题。

对于a = b = 1,您可以对p使用以下等式: p=min(mod(x,2),2-mod(x,2));。你甚至可以添加noEvent,你可以认为信号是连续的(但不是可区分的)。

model test
  parameter Real b = 1;
  parameter Real a = 3;
  Real x, p;
equation
  p = 2*a*min(1 / b * mod(x, b ),1 - 1/b * mod(x, b));
  x = time;
end test;

答案 3 :(得分:2)

我的第一个建议是删除sign-function,因为与sign(foo)>=0相比,foo>=0没有任何好处。

足够有趣似乎可以解决Dymola中的问题 - 我也假设在OpenModelica中:

model test1 "almost original"
  final constant Real pi=2*Modelica.Math.asin(1.0);
  parameter Real b = 1;
  parameter Real a = 1;
  Real x,p,u;
equation
  if sin(x*pi/b)>=0 then 
    p=a*(x-b*floor(x/b));
  else 
    p=a*(b-(x-b*floor(x/b)));
  end if;
  x=time;
  u = floor(x/b);
end test1;

现在我只需要解释一下 - 原因是sin(x*pi/b)与floor-function略有不同步,但是如果你使用sin(x*pi/b)>=0在寻根者epsilon中,没什么奇怪的。

当您使用不再可能的sign(sin(x*pi/b))>=0时,不是让sin(x*pi/b) epsilon低于零,而是现在为-1,而不是epsilon高于零,则为1。

因此,真正的解决方案稍微复杂一些:

model test2 "working"
  parameter Real b = 1;
  parameter Real a = 1;
  Real x,p,u;
  Real phase=mod(x,b*2);
equation 
  if phase<b then
    p=a/b*phase;
  else
    p=a-a/b*(phase-b);
  end if;
  x=time;
  u = floor(x/b);
end test2;

根据建议的解决方案进行了改进:

model test3 "almost working"
  parameter Real b = 1;
  parameter Real a = 1;
  Real x,p,u;
equation
  if mod(x,2*b)<b then 
    p=a/b*mod(x,b);
  else 
    p=a-a/b*mod(x,b);
  end if;
  x=time;
  u = floor(x/b);
end test3;

此解决方案test2的关键点是,只有一个有问题的事件生成表达式mod(x,2*b) - 并且<不会与此不同步。

在实践中,test3几乎肯定也会起作用,但在不太可能的情况下,事件生成可能会在mod(x,2*b)mod(x,b)之间失去同步;结果不明。

请注意,现在修改了所有三个示例以生成看起来类似的输出。