FESTUNG 模型介绍 - 2. 对流问题隐式求解
1. 控制方程
对流问题的控制方程为
\[\partial_t C + \partial_x u^1 C + \partial_y u^2 C = 0, \\
\begin{array}{cl}
C = C_D & \mathrm{on} \; \partial \Omega_D, \\
- \nabla C \cdot \mathbf{v} = g_N & \mathrm{on} \; \partial \Omega_N.
\end{array}
\]
在边界处包含 Dirichlet 和 Neumann 两种边界条件。
2. 数值离散
2.1. 空间离散
采用间断有限元方法对控制方程进行离散,包括采用一次分部积分并利用 Green-Gauss 公式将方程转化为
\[\underbrace{ \int_{\mathcal{T}_k} \varphi_{ki} \sum_{j=1}^N \partial_t C_{kj} \varphi_{kj} }_{I}
- \underbrace{ \int_{\mathcal{T}_k} \partial_x \varphi_{ki} \sum_{j=1}^N C_{kj} \varphi_{kj} \sum_{j=1}^N u^1_{kl} \varphi_{kl}
- \int_{\mathcal{T}_k} \partial_y \varphi_{ki} \sum_{j=1}^N C_{kj} \varphi_{kj} \sum_{j=1}^N u^1_{kl} \varphi_{kl} }_{II} \\
+ \underbrace{ \left \{
\begin{array}{c}
\sum_{n=1}^3 \int_{\partial \mathcal{T}_k} v_{kn}^1 u^1_{kn} \varphi_{ki} \sum_{j=1}^N C_{kj}^* \varphi_{kj}
+ \sum_{n=1}^3 \int_{\partial \mathcal{T}_k} v_{kn}^2 u^2_{kn} \varphi_{ki} \sum_{j=1}^N C_{kj}^* \varphi_{kj} \quad \mathrm{on} \; \mathcal{E}_{\Omega} \\
\sum_{n=1}^3 \int_{\partial \mathcal{T}_k} v_{kn}^1 u^1_{kn} \varphi_{ki} \sum_{j=1}^N C_D^* \varphi_{kj}
+ \sum_{n=1}^3 \int_{\partial \mathcal{T}_k} v_{kn}^2 u^2_{kn} \varphi_{ki} \sum_{j=1}^N C_D^* \varphi_{kj} \quad \mathrm{on} \; \mathcal{E}_{D}
\end{array} \right \}
}_{III} = 0.
\]
代入质量矩阵 \(\mathcal{M}\) 等,可将半离散方程化为矩阵形式
\[\mathcal{M} \partial_t C + \left( \mathcal{G}^1 + \mathcal{G}^2 + \mathcal{R} \right) C = \mathcal{K}_D + \mathcal{K}_N
\]
其中 \(\mathcal{K}_D\) 和 \(\mathcal{K}_N\) 为边界条件产生的常数向量。最终得到关于时间的常微分方程组
\[\partial_t C = \mathcal{S}( C, t ), \quad \mathcal{S}( C, t ) = \mathcal{M}^{-1} \left[ \mathcal{K}_D + \mathcal{K}_N - \left( \mathcal{G}^1 + \mathcal{G}^2 + \mathcal{R} \right) C \right]
\]
2.2. 时间离散
在获得关于时间的半离散方程后,可采用 s 步对角隐式 Runge-Kutta 方法(DIRK)计算,其计算流程为
\[\begin{array}{ll}
\mathbf{C}^{(i)} :=\mathbf{C}^{n}+\Delta t^{n} \sum_{j=1}^{i} a_{i j} \mathcal{S}\left(\mathbf{C}^{(j)}, t^{(j)}\right), & \text { for } \quad i=1, \ldots, s \\
\mathbf{C}^{n+1} :=\mathbf{C}^{n}+\Delta t^{n} \sum_{i=1}^{s} b_{i} \mathcal{S}\left(\mathbf{C}^{(i)}, t^{(i)}\right)
\end{array}
\]
在 DIRK 方法中,\(b_j = a_{sj}\),因此计算时不必进行最后一步 \(\mathbf{C}^{n+1}\) 的计算,而只需把 \(\mathbf{C}^{(s)}\) 值赋给 \(\mathbf{C}^{n+1}\) 即可。
将空间算子表达式代入,可得每一步 \(\mathbf{C}^{(i)}\) 的具体计算公式为
\[\mathbf{C}^{(i)} =\mathbf{C}^{n}+\Delta t^{n} \sum_{j=1}^{i} a_{i j} \mathcal{M}^{-1} \left[ \mathcal{K}_D + \mathcal{K}_N - \left( \mathcal{G}^1 + \mathcal{G}^2 + \mathcal{R} \right) C^{(j)} \right]
\]
将与 \(\mathbf{C}^{(i)}\) 相关的项移到等号左侧可得
\[\left( 1 + \Delta t^n a_{ii} \mathcal{M}^{-1} \mathcal{A} \right) \mathbf{C}^{(i)} = \mathbf{C}^{n} + \Delta t^n a_{ii} \mathcal{M}^{-1} \mathcal{V} + \sum_{j=1}^{i-1} a_{i j} \mathcal{M}^{-1}( \mathcal{V} - \mathcal{A} \mathbf{C}^{(j)} )
\]
其中 \(\mathcal{A} = \mathcal{G}^1 + \mathcal{G}^2 + \mathcal{R}\), \(\mathcal{V} = \mathcal{K}_D + \mathcal{K}_N\)。将 \(\mathcal{M}\) 同时乘以等号两侧,可得
\[\left( \mathcal{M} + \Delta t^n a_{ii} \mathcal{A} \right) \mathbf{C}^{(i)} =
\mathcal{M} \mathbf{C}^{n} + \Delta t^n a_{ii} \mathcal{V} + \sum_{j=1}^{i-1} a_{i j} ( \mathcal{V} - \mathcal{A} \mathbf{C}^{(j)} )
\]
两侧同乘以 \(\left( \mathcal{M} + \Delta t^n a_{ii} \mathcal{A} \right)^{-1}\),即可获得 \(\mathbf{C}^{(i)}\) 的数值解。
3. 模型实现
在 FESTUNG 中,solveSubStep.m
实现了 DIRK 方法中每步 \(\mathbf{C}^{(i)}\) 的计算过程。
首先,组装系数矩阵 sysA 与 sysV,分别代表 \(\mathcal{A}\) 与 \(\mathcal{V}\)。当求解恒定问题时,由于此时半离散方程不包含时间变化项,因此
\[C = \mathcal{A}^{-1} \mathcal{V}
\]
当求解问题为非恒定时,首先计算方程组的右端项 sysR = \(\mathcal{M} \mathbf{C}^{n} + \Delta t^n a_{ii} \mathcal{V} + \sum_{j=1}^{i-1} a_{i j} ( \mathcal{V} - \mathcal{A} \mathbf{C}^{(j)} )\) ,其代码为
% Computing the rhs
sysR = (problemData.tau * problemData.A(nSubStep, nSubStep)) * sysV + problemData.globM * problemData.cDiscRK{1};
for j = 1 : nSubStep - 1
sysR = sysR + (problemData.tau * problemData.A(nSubStep, j)) * problemData.rhsRK{j};
end % for
随后,将系数矩阵的逆左乘至右端项 sysR 上,即可获得 \(\mathbf{C}^{(i)}\) 的数值解
% Compute the next step
problemData.cDiscRK{nSubStep + 1} = (problemData.globM + (problemData.tau * problemData.A(nSubStep, nSubStep)) * sysA) \ sysR;