有限元法求解偏微分方程之FEniCS入门讲解
有限元法求解偏微分方程之FEniCS入门讲解
bxplosionFEniCS入门讲解(求解泊松方程)
FEniCS
是一个有限元法求解偏微分方程的开源计算平台。
- 泊松方程
- 将泊松方程转化成(弱)变分形式
- 求解微分方程边值问题(1维泊松方程)
- 求解2维泊松方程
ParaView
中查看解
泊松方程
第一个例子自然是求解著名的泊松方程。
\[ -\Delta u=f \qquad \text{ in } \Omega \\ u|_{\Gamma_D}=u_0 \qquad \text{ on } \Gamma_D\\ \left.\frac{\partial u}{\partial n}\right|_{\Gamma_N}=g \qquad \text{ on } \Gamma_N = \partial \Omega - \Gamma_D \]
将泊松方程转化成(弱)变分形式
首先:对泊松方程两边都乘上测试函数\(v\),然后对全域\(\Omega\)积分。
\[ -\int_\Omega \textcolor{red}{\Delta u v} dx=\int_\Omega f v dx \]
这里需要说明一下试探函数
和测试函数
的概念。
测试函数,定义为: \[ \hat{V} = \{v\in H^1(\Omega): \textcolor{red}{v=0} \text{ on } \Gamma_D\} \]
试探函数,定义为: \[ V = \{u\in H^1(\Omega): \textcolor{red}{u=u_0} \text{ on } \Gamma_D\} \]
然后,对上面这个变分方程进行变换
\[ \textcolor{red}{\Delta u v} = \left(\frac{\partial}{\partial x_i}\frac{\partial}{\partial x_i}u\right) v = \frac{\partial}{\partial x_i}\left(\frac{\partial u}{\partial x_i} v\right) - \frac{\partial u}{\partial x_i} \frac{\partial u}{\partial x_i} = \textcolor{red}{\nabla \cdot (\nabla u v) -\nabla u \cdot \nabla v} \]
\[ \int_\Omega \nabla u \cdot \nabla v dx=\int_\Omega f v dx + \textcolor{red}{\int_\Omega \nabla \cdot (\nabla u v) dx} \]
\[ \int_\Omega \nabla \cdot (\nabla u v) dx = \int_{\partial \Omega} n \cdot \nabla u v ds = \int_{\partial \Omega} \frac{\partial u}{\partial n} v ds = \textcolor{red}{\int_{\Gamma_N} g v ds} \]
\[ \boxed{\int_\Omega \nabla u \cdot \nabla v dx = \int_\Omega f v dx + \int_{\Gamma_N} g v ds} \]
左边是双线性形式\(a(u,v)\),右边是线性形式\(L(v)\):
\[ a(u,v) = \int_\Omega \nabla u \cdot \nabla v dx \\ L(v) = \int_\Omega f v dx + \int_{\Gamma_N} g v ds \]
于是得到标准的变分问题:寻求\(u\in V\),满足
\[ a(u,v) = L(v) \qquad \forall v \in \hat{V} \]
这就是和前面的泊松问题等价的变分问题。
求解微分方程边值问题(1维泊松方程)
\[ -u''=f \\ u(0)=0,\ u'(1)=g \]
有了前面的准备,现在可以写代码求解了。
第一步:为求解域创建网格,并定义函数空间
1 | from dolfin import * |
第二步:定义已提供的表达式
1 | u0 = Constant(0) |
第三步:创建和应用Dirichlet
边界条件
1 | # 定义Dirichlet边界(x = 0) |
第四步:定义变分问题
1 | u = TrialFunction(V) |
第五步:求解并绘图
1 | # 求解 |
求解2维泊松方程
- \(\Omega=[0,1]×[0,1]\) (一个单位矩阵)
- \(\Gamma_D=\{(0,y)\cup(1,y)\subset\partial \Omega\}\)(Dirichlet边界)
- \(\Gamma_N=\{(x,0)\cup(x,1)\subset\partial \Omega\}\) (Neumann边界)
- \(g=\sin(5x)\) (法向导数)
- \(f=10\exp\left\{−\dfrac{(x−0.5)^2+(y−0.5)^2}{0.02}\right\}\) (源项)
类似地,也分五步求解
1 | from dolfin import * |
ParaView
中查看解
1 | # 将解保存为VTK格式 |
【结束】