Modelica中三角波函数生成问题
我试图创建一个模型,其中一个Modelica变量是另一个变量的三角波。首先,我尝试了floor()函数,如下所示:Modelica中三角波函数生成问题,modelica,openmodelica,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
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)时也会出现同样的问题之前,一切似乎都是正确的
如果您能:
顺便说一句,我用这个“波函数”来模拟两个锯齿状物体之间的相互作用“我无法解释你的模拟中出现的小故障 然而,我会对锯齿函数采取另一种方法:我把它看作是一个积分器,向上和向下积分+1和-1。积分时间决定了锯齿函数的振幅和周期 下图显示了一个使用MSL块的实现和一个使用代码的实现 致以最良好的祝愿, 雷内·贾斯尼尔森 框图: 代码:
model test3
parameter Real a=2 "amplitude";
parameter Real b=3 "period";
Real u, y;
initial equation
u = 1;
y = 0;
equation
4*a/b*u = der(y);
when y > a then
u = -1;
elsewhen y < -a then
u = 1;
end when;
end test3;
模型测试3
参数实a=2“振幅”;
参数实b=3“周期”;
真u,y;
初始方程
u=1;
y=0;
方程式
4*a/b*u=der(y);
当y>a时
u=-1;
否则当y<-a那么
u=1;
结束时;
结束试验3;
模拟结果:
我想问题是由于浮点表示和事件没有在准确的时间发生 考虑
x层(x)
和1-(x层(x))
在时间=0.99时,它们是0.99
和0.01
;在时间=1.00时它们是0.0
和1.0
,这会导致您的问题
对于a=b=1,可以使用以下公式计算p:
<代码> p= min(mod(x,2),2-mod(x,2));。甚至可以将<代码> Novivs/COD>添加到它,并且可以考虑信号连续(但不可微)。< /P>
如果允许您使用Modelica标准库,您可以使用CombitMetable块,通过线性插值和周期外推,建立参数化、基于时间的锯齿形信号。例如
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;
我的第一个建议是删除sign函数,因为与
foo>=0
相比,执行sign(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函数稍微不同步,但是如果使用sin(x*pi/b)>=0
,这在根查找ε内,不会发生奇怪的事情
当您使用符号(sin(x*pi/b))>=0时,这不再可能,而不是使用小于零的ε,它现在是-1,而不是大于零的ε,它是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;
模型测试2“正常工作”
参数实数b=1;
参数实数a=1;
实x,p,u;
实相=mod(x,b*2);
方程式
如果阶段性问题很多,请考虑我对整个MODEICA世界非常陌生,所以我先道歉,如果我的问题看起来很愚蠢:首先我尝试了你的代码,它确实编译成功,但是唯一可能绘制的两个参数是常量A和B。你可以把其他变量添加到你的代码中,比如X和Y,它们可以是D。rawn?来自C背景,我不熟悉整个块的概念,否则我会自己添加它。第二点是Modelica标准库中也有一个梯形块。为什么不使用它呢?我更新了Test4
模型,使其具有所需的输出变量y
。x=time
对于Comb是隐式的iTimeTable,因此除了时间之外,没有其他输入的可能性。是的,您也可以使用梯形信号,但只能在时间上移动,另请参见Test4
。我认为mod()函数值得一试。您介意将代码添加到您的答案中吗?如果可以,我也将不胜感激:1.让我了解更多关于noEvent()的信息用简单的话来说函数。我试着去读它,但没有完全理解。2.让我知道为什么一些理论上不可微的信号在Modelica中是可以的,而其他的则不行?例如floor()函数不应该是可微的,但OpenModelica编译时不会出现任何错误noEvent
使其成为可微函数,因此解算器不会在运行时尝试查找过零。基本上,您不知道是否在事件发生后才获得时间。有时,如果if表达式中的条件发生错误,则可能会出现意外情况e是不存在的。关于可微函数:它们仅在执行索引缩减时(或者如果工具依赖于雅可比矩阵)才是必需的。有些函数是分段可微的,并且可能也可以工作(如果函数给出事件,因为在事件期间不使用导数,并且呈现在左侧和右侧)。首先,非常感谢您的回答。您的第二个代码是本页中生成包含信号的第一个解决方案。第二,在您的第二个代码中,b似乎是半周期。您能修复它吗?第三,您的第一个代码不能解决问题。我在OpenModelica和Wolfram SystemModeler中都尝试过。最后,您完全正确关于删除sign()函数,我真是太蠢了,添加了:),尽管删除它并不能解决我的问题。还有Modelica.Constants.pi
的pi
。我还有一个iss
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;