混合形式泊松方程之FEniCS求解
混合形式泊松方程之FEniCS求解
bxplosion【本文仅是视频中Markdown文件内容,不包括同名视频中讲解】
如果你希望和我一样Win10上安装FEniCS,建议采用Win10 + WSL2 + Ubuntu。
FEniCS讲座系列
第1讲:有限元法求解偏微分方程之FEniCS入门讲解【上一讲】
第2讲要点
- 将高阶偏微分方程 变换成 1阶偏微分方程组
- 1阶偏微分方程组 变换成 1个变分方程
- 自然边界 和 基本边界
- 如何定义混合空间
- 如何自定义表达式
- FEniCS快捷可视化
混合形式的泊松方程
以泊松方程为例,这是一个二阶方程:
\[ -\Delta u = f \]
现在我们要将其改一阶方程组,引入一个叫热通量
(或简称 通量
)的辅助矢量\(\sigma = - \nabla u\),不难得到:
\[ \nabla \cdot \sigma = f \qquad \text{in } \Omega \\ \sigma + \nabla u = 0 \qquad \text{in } \Omega \]
这个通量
是有物理意义的,那就是所谓的傅里叶定律
:热通量
\(\sigma\)与温度 \(u\)的负梯度成比例。
\[ \sigma = - \kappa \nabla u \]
这里我们取\(\kappa=1\)而已。
而泊松方程实际就是傅里叶定律+能量守恒
的结果。如图:
稳态情况下,根据能量守恒,通过任意闭合曲面\(\partial\omega\)流出的能量(这里指热量) 必须等于 曲面内热源发出的能量:
\[ \textcolor{red}{\int_{\partial\omega} \sigma \cdot n ds} = \int_\omega f dx \]
进而
\[ \textcolor{red}{\int_{\omega} \nabla \cdot \sigma dx} = \int_\omega f dx \]
由于闭合区域\(\omega \subset \Omega\)的任意选择性,所以在整个\(\Omega\),下式成立
\[ \nabla \cdot \sigma = f \]
对应的边界条件则需要改成:
\[ u|_{\Gamma_D}=u_0 \qquad \text{ on } \Gamma_D\\ \left. \textcolor{red}{n\cdot\sigma}\right|_{\Gamma_N}=-g \qquad \text{ on } \Gamma_N \]
转换成变分形式
第一个方程是标量方程,选择标量测试函数\(v\);第二个方程是矢量方程,选择矢量测试函数\(\tau\)。
方程1× \(v\) + 方程2· \(\tau\),然后对全域\(\Omega\)积分,得到:
\[ \int_\Omega [\nabla \cdot \sigma v + \sigma\cdot\tau +\textcolor{red}{\nabla u \cdot \tau}] dx= \int_\Omega f v dx \]
\[ \nabla u \cdot \tau = \textcolor{red}{\nabla \cdot (u\tau)} - u \nabla\cdot\tau \]
\[ \int_\Omega [\nabla \cdot \sigma v + \sigma\cdot\tau - u \nabla\cdot\tau] dx = \int_\Omega f v dx - \textcolor{red}{\int_\Omega \nabla \cdot (u\tau)dx} \]
\[ \int_\Omega \nabla \cdot (u\tau)dx = \int_{\partial \Omega} u \textcolor{red}{\tau \cdot n} ds = \int_{\textcolor{red}{\Gamma_D}} \textcolor{red}{u_0} \tau \cdot n ds \]
参考这个关系,可以具体地定义测试函数和试探函数。
将所有测试函数元组
\((\tau,v)\)的集合记作\(\hat{V}\);类似地,将所有试探函数元组
\((\sigma,u)\)的集合记作\(V\):
\[ \hat{V} = \{(\tau,v) : v\in L^2(\Omega), \tau\in H(\mathrm{div},\Omega), \textcolor{red}{\tau\cdot n = 0} \text{ on } \Gamma_N\} \\ V = \{(\sigma,u) : u\in L^2(\Omega), \sigma\in H(\mathrm{div},\Omega), \textcolor{red}{\sigma\cdot n = -g} \text{ on } \Gamma_N\} \]
请注意,这里上一讲的不同之处在于, \(\Gamma_D\)上的第一类边界条件 \(u =
u_0\)进入了变分公式(现在是自然边界条件
),而第二类边界条件条件\(\sigma \cdot n = -g\)则在\(\Gamma_N\)上进入试探空间\(V\)的定义(现在是基本边界条件
)。
将上面的结果整理得到最终的变分方程: \[ \boxed{\int_\Omega [\nabla \cdot \sigma v + \sigma\cdot\tau - u \nabla\cdot\tau] dx = \int_\Omega f v dx - \int_{\Gamma_D} u_0 \tau \cdot n ds} \]
改成标准变分问题表述:寻求\((u,\sigma)\in V\),满足
\[ a(\sigma,u; \tau,v) = L(\tau,v) \qquad \forall (\tau,v)\in \hat{V} \\ \textcolor{red}{a(\sigma,u; \tau,v)}=\int_\Omega [\nabla \cdot \sigma v + \sigma\cdot\tau - u \nabla\cdot\tau] dx \\ \textcolor{red}{L(\tau,v)} = \int_\Omega f v dx - \int_{\Gamma_D} u_0 \tau \cdot n ds \]
求解这个混合形式泊松方程
- \(\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 * |
第二步:定义已提供的表达式
1 | # 第一类界值 |
第三步:创建和应用基本边界条件
1 | # 定义基本边界条件 |
第四步:定义变分问题
1 | # 定义试探函数和测试函数 |
第五步:求解并绘图
1 | # 求解 |
ParaView
可视化
1 | # 将解保存为VTK格式 |
FEniCS快捷可视化
1 | # 绘制矢量场图(如果是矢量场的话) |
END