Contents

A.Ch49-数值模拟

数值模拟是基于理论与实践的数值求解过程,仿真并与现实相接近,用于复现、诠释物理现象,是目前热门的研究领域。

49.1 ParaView

用于后处理器的 ParaView 以其开源、兼容性高等特点,适用于网格、粒子后处理,受到科学家与工程师的青睐。

我常用的有 h5part、VTK ASCII 格式,分别对应粒子和网格后处理,常用过滤器有 SPH、Clip 等。

49.2 自由面条件

\( \eta \) 是自由面方程,\( \phi \) 是速度势,\( P_c \) 是气垫压强。

49.2.1 运动学条件

\[ \frac{\partial \phi}{\partial y} = \frac{\partial \eta }{\partial t} + \frac{\partial \phi}{\partial x} \frac{\partial \eta}{\partial x} + \frac{\partial \phi}{\partial z}\frac{\partial \eta}{\partial z} \]

49.2.2 动力学条件

\[ \frac{\partial \phi}{\partial t} + \frac{|\Delta\phi|^2}{2} + g\eta=0 \]

如果是气垫船,表面压强不为大气压,则气室下方:

\[ \frac{\partial \phi}{\partial t} + \frac{|\Delta\phi|^2}{2} + \frac{P_c}{\rho} + g\eta=0 \]

49.2.3 线性化自由面条件

微幅波假设:当波面起伏是小量时,波面流体质点运动速度也是小量,\(\frac{A}{\lambda} \ll 1 \)。

  1. 运动学条件:\( \frac{\partial \phi}{\partial y} = \frac{\partial \eta }{\partial t} \);
  2. 动力学条件:\( \frac{\partial \phi}{\partial t} + g\eta=0 \)。

可以得到:

\[ g\frac{\partial \phi}{\partial y} + \frac{ \partial ^2\phi}{\partial t^2}=0 \]

49.3 SPH

SPH 光滑粒子流体动力学。

49.3.1 SPH 验证集

《Geo-disaster Modeling and Analysis: An SPH-based Approach》中存在一些很好的验证集。

49.4 气垫船理论研究

49.4.1 流量系数

流量系数的理论公式推导基于伯努利方程(能量方程),流量系数 \(C_d\) 蕴含了局部能量的损耗,取值范围为 \(0 \leq C_d \leq 1\):

\[ Q = C_d A \sqrt{\frac{2\Delta P}{\rho_a}} \]

49.5 HPC 高性能计算

我能用到的高性能计算/辅助工具有:

  • GCC Fortran 编译器;
  • Meson 构建工具;
  • OpenMP 并行编程;
  • OpenBLAS 矩阵库;
  • PETSc 线性代数库;
  • HDF5 文件格式;
  • Fortran_stdlib 标准库;
  • Python 绘图脚本;
  • Octave 科学工具箱;
  • PowerShell 脚本;
  • MSC.Patran 建模和网格划分工具;
  • ParaView 后处理器。

49.6 CSR 稀疏矩阵格式

CSR(Compressed Sparse Row)稀疏矩阵存储格式是一种常用的稀疏矩阵存储方法,它能够高效地存储稀疏矩阵中的非零元素。CSR 格式主要包括三个组成部分:indices(列索引)、indptr(行指针)以及 data(非零元素值)。下面我将详细介绍 indptr(行指针)的作用。

49.6.1 CSR 格式简介

CSR 格式的主要优点在于能够快速访问矩阵的行,这对于许多基于行的操作来说是非常重要的。CSR 格式由以下三部分组成:

  1. data - 存储所有非零元素的值,按行优先顺序排列。
  2. indices - 存储每个非零元素对应的列索引。
  3. indptr - 存储每行第一个非零元素在 data 数组中的位置。对于最后一行,indptr 包含的是所有非零元素的总数加一。

49.6.2 行指针 (indptr) 的作用

indptr 数组是一个整数数组,它的长度等于矩阵的行数加一。indptr 的每个元素表示对应行的第一个非零元素在 dataindices 数组中的起始位置。具体来说:

  • indptr[0] 总是 0,表示第一行非零元素的起始位置。
  • indptr[row] 表示第 row 行(从 0 开始计数)的第一个非零元素的位置。
  • indptr[row+1] - indptr[row] 表示第 row 行中的非零元素数量。

举个例子,假设有一个 4x4 的稀疏矩阵如下所示:

1
2
3
4
0 2 0 1
0 0 3 0
4 0 0 0
0 0 0 0

该矩阵的 CSR 格式表示为:

  • data: [2, 1, 3, 4] (非零元素值)
  • indices: [1, 3, 2, 0] (列索引)
  • indptr: [0, 2, 3, 4, 4] (行指针)

这里 indptr 的解释如下:

  • indptr[0] = 0:第一行的第一个非零元素在 data 中的位置。
  • indptr[1] = 2:第二行的第一个非零元素在 data 中的位置。
  • indptr[2] = 3:第三行的第一个非零元素在 data 中的位置。
  • indptr[3] = 4:第四行的第一个非零元素在 data 中的位置。
  • indptr[4] = 4:最后一行(第 4 行)没有非零元素,因此 indptr[4] 表示所有非零元素的总数加一。

通过这种方式,我们可以快速访问每一行的非零元素及其对应的列索引。例如,要获取第一行的非零元素,我们可以通过 indptr[0]indptr[1] 访问 dataindices 数组:

  • 第一行非零元素的值:data[indptr[0]:indptr[1]] = [2, 1]
  • 第一行非零元素的列索引:indices[indptr[0]:indptr[1]] = [1, 3]

49.6.3 总结

indptr 数组是 CSR 格式的一个关键组成部分,它帮助我们快速定位每行的第一个非零元素在 dataindices 数组中的位置。这使得在处理稀疏矩阵时能够高效地遍历每一行的非零元素。

CSR 格式不仅在内存使用上节省空间,在许多矩阵操作中也能提供时间上的优势,特别是在处理大型稀疏矩阵时。对于需要频繁访问行或基于行的操作,CSR 格式可以提供高效的性能。 然而,对于需要频繁访问列或基于列的操作,可能需要考虑使用 CSC(Compressed Sparse Column)格式,因为它在这些场景下表现更好。

C 语言的行优先的存储格式适合 CSR,Fortran 语言的列优先的存储格式适合 CSC。

49.7 BLAS 简单指南

当程序运行的很慢时,一定会有至少一个大循环,并且可能存在多个 \( O(n^2) \) 及以上的算法。做科学计算的时候,难免遇到浮点型的矩阵运算,矩阵运算往往满足了前述的 2 种情况, 采用优化的 BLAS/LAPACK 库是一种绝佳选择,直接法可能不是最完美的,但一般是发挥最稳定的。我们常用到以下三种求解例程:

  • ?gemm:矩阵乘法;
  • ?getrf/?getrs:矩阵求逆;
  • ?getrf/?getrs:线性方程组求解。

它们的时间复杂度一般都在 \( O(n^2) ~ O(n^3) \) 范围内,比如 OpenBLAS/oneMKL 这类被优化和并行的线性代数库,在中小型矩阵中十分有效。 额外地,使用 Intel VTune Profiler 工具查看程序并行情况,尝试为所有耗时部分的 \( O(n^2) \) 及以上的算法代码至少实施 OpenMP。 只要是线性的时间复杂度的必要功能,则不会影响代码运行效率。

参考链接

  1. 上海交通大学-水波基础理论
  2. 上海交通大学-船舶流体力学