有限元方法软件scikit-fem的两个例子
最近在使用有限元方法。有限元软件有很多,最出名的应该是fenics,它功能非常多,功能包装得也很好,使用方便。唯一的缺点是太大了,如果只是写个小软件去安装它就显得非常臃肿。想象一下,你使用外部库比你自身的程序大的多,而这个外部库还是不常用的。fenics在wsl上还不太好安装。因为windows下认为两个名字相同但大小写不同的文件是同一文件,但安装fenics时需要安装一个和已有库同名的软件包,所以就安装不上。后来找来找去找到一个名为scikit-fem的包。它很小,看它官网上帮助文档发现也能解很多问题。但缺点是这帮助文档写的太简略了!有好多代码和函数需要猜它什么意思。这了记录两个典型例子,可能会对使用scikit-fem的人有所帮助。
一维波动方程
该例子是ex44.py中的例子。对于方程,它需要转化成一个一阶方程组求解。所以这个例子对于求解方程组也很有帮助。
使用Crank-Nicolson差分格式
把其中第二个方程转化成变分形式(第一个方程不用转化,因为没有导数项),并整理得到
现在看如下代码块
可以看到矩阵A和B的形式分别为
分别对应上面推导公式的右端和左端。时间t^k时刻的u乘以B,得到Bu^k,然后求解Au^{k+1} = Bu^k,得到u^{k+1}。
2. 非线性方程
非线性方程转化成变分形式会得到非线性泛函。此时把用基组展开的试探函数带入到变分形式中将得到关于展开系数的非线性方程。此时用牛顿迭代法去求解即可。在使用scikit-fem时,我们需要把变分形式线性化交给程序求解。一个泛函泛函导数的定义为
引入参数t是为了能和普通函数求导一样求出泛函导数,其实是不必要的。这里选用的例子是ex10.py。对于极小曲面问题(帮助文档里写错了,掉了根号)
它的变分形式为
为了求解泛函导数,把如下泛函在t = 0处展开到一阶(为了方便省略积分号)
注意这里使用了
当t趋于0时
看ex10.py中的代码块
这里w = p['prev']就是前一步的解,即公式中的u。代码中的u则是上式中的,
。可以看到Jacobian恰好是和推导得到的泛函导数相对应。