一维绳波模拟中的探究:完全吸波性边界条件
完全吸波边界条件:
波动方程模拟在计算物理中占有重要的地位,具体应用有声学振动模拟、电磁波模拟、波函数模拟等。这些波动方程(除波函数外)都具有一个大致相同的形式:
其中\(u\)为某标量场,\(c\)为声速。
这类方程必定有行波解,在一维情况下,解可以表示为:
即解可以表示为两列相反传播的行波\(u_1\)、\(u_2\)的叠加。其中\(u_1\)、\(u_2\)为任意一元函数。
这种方程的求解除了与初始条件相关,还与边界有很大关系。边界处一般设置为固定或自由边界条件,两种边界在性质上有些许区别,但又有相似性,例如都能实现完全反射,从而形成驻波。
上面两张图为一维绳波的模拟(几个时刻的图形叠在一起)。每张图左端有一个波源,在做正弦振动,而左段为不同的边界条件,导致不同表现。左图为自由式边界条件,绳头可以自由摆动。右图为固定式边界条件,绳头强制固定在0处。
由于波源发出的能量无法被绳头耗散,两种情形下波都会被绳头反射,从而产生驻波。
于是,自然可以想象,会不会有一种边界条件,使右行波完全被吸收,从而不产生任何反射呢?答案是有的。可以想象,假如绳子绳头之外还有绳较长的延伸,从而做到在实验关心的时间之内,右行的波还没有碰到真正的边界,不存在反射,则右行的波就好像被“完全吸收”了。就是说,无限长绳等价于完全吸波条件。
但是电脑永远模拟不了无限,而只能用有限长的绳子近似“完全吸波条件”。因而实验时间不能太长,至少在反射波进入人们关心的区域之前,必须中止模拟,否则“完全吸波条件”失效,模拟会出现很大偏差。
并且即使这样,还是浪费了大量的计算资源在人们不关心的区域的波动方程计算上。这注定是一个糟糕的方法。
存不存在更好的方法?其实是有的。仔细观察模拟的机制,只要对绳头进行人为的操纵,让绳头的行为表现得和无限长绳情况下一模一样,就可以“骗过”左方的绳子,让绳子“以为”右行波还没有碰到边界,从而不会发生反射。
但是该如何认为移动绳头才能让绳头“蒙混过关”呢?天真的想法是利用该问题中只包含右行波的特点:
在该解中,绳子上每一个点的运动状态都滞后重复前面的点的运动状态,即:
那么绳头只需要简单地滞后重复某个相邻点的运动,即可完美地实现“完全吸波”。
然而数值模拟残酷地表明,这种方法完全行不通!具体原因和数值离散过程密切相关,笔者能力和精力有限,并没有进一步研究。
幸好,绳波系统有一个十分优异的特性——线性,将绳头视为一个系统,绳头的位移看成系统的输出端,而与绳头相连的倒数第二个节点的位移看成该系统的输入端,则该系统是一个线性时不变系统。该系统的含时响应完全线性取决与输入端的位移方程。
数学推导:
取绳头的位移为\(u_o(t)\)(输出),而绳头前一个节点的位移为\(u_i(t)\)(输入),则线性时不变系统有如下优良特性:
又由于:
式中,\(F(t)=\int^t_0f(t)dt\),因而最后一项为0。上式最终化简为:
我们把\(F(t)\)叫做绳头的“冲击响应函数”,因为如果输入函数具有以下形式:
其中\(\epsilon\)为一无限接近0的小量,则输出函数为:
冲击响应函数反映了当输入函数为阶跃函数时,输出端的变化情况。我们接下来的工作就是找到这个阶跃函数。
在数值模拟中,绳波系统可以离散为有多个节点的一条长链,相邻节点之间用弹簧连接,弹簧施加线性恢复力。对于第\(n\)个节点的位移\(u_n(t)\),运动学方程如下:
可以通过设置\(t'=t\)实现无量纲化:
绳波模型的离散化示意图:
由于该系统实际上具有无限多个节点力学分析将变得十分棘手。但是,有一种方法可以巧妙破解这一难题,从而实现物理系统的方程化:
考虑倒数第1、2个节点,设它们对左方的冲击响应函数分别为\(F_A(t)\)和\(F_B(t)\),由于系统右端为无限长序列,则应该有:
现在考虑运动方程:
联立方程有:
其中初值条件为:
这个方程是一个积分微分混合型方程,并且由于涉及到卷积,难以有效消除积分号,笔者能力有限难以给出解析解。不过该方程可以用皮卡迭代序列给出级数解。经过艰苦卓绝的求解(玄学找规律),笔者得到级数式为:
利用Python绘图显示图像:
可见当时间趋于无穷时,系统会逐渐稳定在1附近,这符合绳波冲击响应函数的特点。
注:由于泰勒级数收敛性较差,该级数用double精度计算会在\(x=20\)之后发散。为了正确计算,必须提高计算精度。高精度计算的方法在博文Java 高精度浮点数计算工具中有所介绍。
只要绳头的位移始终满足:
即能做到完全吸收向右传来的波,而避免反射波产生,即“完全吸波边界条件”。
但是,上式还有一个问题,即仍然需要无限大的储空间才能记录所有时刻的\(u_i(t)\),方法仍然没有可行性。为了解决这一问题,注意到:
可以设置截断距离\(L\),使积分近似为:
至此,数学推导部分已经全部完成,只剩下程序实现了。
程序模拟:
由于笔者使用java做科学计算的习惯(怪癖),程序由java实现。共编写两个类,一个类进行绳波模拟,另一个专注于计算绳头的冲击响应。以下是模拟结果。
固定式边界条件:
自由式边界条件:
完全吸波边界条件:
可以看出,完全吸收式边界条件较为出色地完成了任务,波包到达边界后几乎没有反弹,就好像边界为无穷大一样。
代码:
见我的github页面,测试代码也在里面。程序代码比较容易理解。
结束语:
通过本文的推导,我们得出了完全吸波边界的一种可行方法,该方法在计算机波动模拟中十分有用,尤其适用于包含无穷大场景,需要排除反射波的情况。不过笔者没有想出来如何在2维以上波动系统中实现类似边界条件。
* 本文为笔者课程学习闲暇时的一点思考,可能有naive的地方。公式推导基本是自己脑洞的,专业性欠缺,如果有误请各位高人指正。