我正在尝试创建一个模型,其中一个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 =时间;是任意的,因此模型编译)
放大:
以某种方式在下一步楼层功能出现意外行为之前0.005秒,并成为以下一个值结束的线性函数。
然后我尝试了ceil()函数。一切似乎都是正确的,直到我意识到ceil()函数在其他值(例如x = 13)
时会发生同样的问题如果可以,我将不胜感激:
P.S。我正在使用这个“波函数”模拟两个锯齿状物体之间的相互作用“
答案 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
the
答案 2 :(得分:2)
我猜这个问题是由于浮点表示和事件没有在确切的时间发生。
在时间= 0.99时考虑x-floor(x)
和1-(x-floor(x))
,它们是0.99
和0.01
;在时间= 1.00时,它们是0.0
和1.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)
之间失去同步;结果不明。
请注意,现在修改了所有三个示例以生成看起来类似的输出。