为什么我的迭代线性求解器不收敛?

计算科学 线性代数 宠物 预处理 克雷洛夫法 迭代法
2021-11-30 20:30:23

使用KSPPETSc的线性求解器包)中的预条件 Krylov 方法求解稀疏线性系统(例如通过离散化和线性化偏微分方程获得的系统)时会出现什么问题?

我可以采取哪些步骤来确定我的问题出了什么问题?

我可以做哪些改变来成功有效地解决我的线性系统?

2个回答

初步建议

  • -ksp_converged_reason -ksp_monitor_true_residual当试图了解一个方法为什么不收敛时,总是运行 with 。
  • 使问题的大小和进程的数量尽可能小,以证明失败。您通常可以通过确定哪些小问题表现出导致您的方法失败并缩短周转时间的行为来获得洞察力。此外,还有一些调查技术只能用于小型系统。
  • 如果问题仅在大量时间步、延续步骤或非线性求解步骤之后出现,请考虑在发生故障时将模型状态写入,以便您可以快速进行试验。
  • 或者,特别是如果您的软件没有检查点功能,请使用-ksp_view_binaryMatView()保存线性系统,然后使用代码$PETSC_DIR/src/ksp/ksp/examples/tutorials/ex10.c读取矩阵并解决它(可能使用不同数量的进程)。这需要一个组装矩阵,因此它的用处可能会有所限制。
  • 有许多可能的求解器选择(例如,由于任意数量的组合级别,在 PETSc 的命令行中可用的数量无限),请参阅此问题以获取有关选择线性求解器的一般建议。

KSP 不收敛的常见原因

  • 方程是偶然的奇异的(例如忘记施加边界条件)。使用-pc_type svd -pc_svd_monitor. 还可以尝试使用直接求解器-pc_type lu(通过并行的第三方包,例如-pc_type lu -pc_factor_mat_solver_package superlu_dist)。
  • 这些方程是有意为奇异的(例如恒定的零空间),但没有告知 Krylov 方法,请参阅KSPSetNullSpace()
  • 这些方程是有意为奇异的KSPSetNullSpace()并被使用,但右手边并不一致。在调用之前,您可能需要先调用MatNullSpaceRemove()右侧KSPSolve()
  • 这些方程是不确定的,因此标准预调节器不起作用。通常你会从物理学中知道这一点,但你可以检查 -ksp_compute_eigenvalues -ksp_gmres_restart 1000 -pc_type none对于简单的鞍点问题,请尝试-pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_detect_saddle_point. 有关详细信息,请参阅用户手册PCFIELDSPLIT 手册页对于更困难的问题,请阅读文献以找到可靠的方法,并在此处(或petsc-users@mcs.anl.govpetsc-maint@mcs.anl.gov)询问您是否需要有关如何实施它们的建议。例如,请参阅此问题以了解高频亥姆霍兹。对于适度的问题规模,看看你是否可以只使用直接求解器。
  • 如果该方法收敛于预处理残差,但不收敛于真实残差,则预处理器可能是奇异的或几乎是奇异的。这对于鞍点问题(例如不可压缩流)或强非对称算子(例如具有大时间步长的低马赫双曲线问题)很常见。
  • 预处理器太弱或不稳定。看看是否-pc_type asm -sub_pc_type lu提高了收敛速度。如果 GMRES 在重启过程中丢失太多进度,请查看更长的重启时间是否有帮助-ksp_gmres_restart 300如果转置可用,请尝试-ksp_type bcgs其他不需要重新启动的方法。(请注意,与这些方法的收敛通常是不稳定的。)
  • 预处理矩阵可能不靠近(可能未组装的)运算符。尝试使用直接求解器进行求解,可以与-pc_type lu第三方软件包串联或并联(例如-pc_type lu -pc_factor_mat_solver_package superlu_dist,或mumps)。如果矩阵相同,则该方法应在一次迭代中收敛,否则在“少量”迭代中收敛。-snes_type test如果解决非线性问题,请尝试检查矩阵。
  • 预处理器是非线性的(例如嵌套迭代求解),请尝试-ksp_type fgmres or -ksp_type gcr
  • 您正在使用几何多重网格,但某些方程(通常是边界条件)在级别之间的缩放不兼容。如果要使用重新离散化的粗略级别,请尝试-pc_mg_galerkin以代数方式构造正确缩放的粗略算子,或者确保所有方程以相同的方式缩放。
  • 矩阵非常病态。使用此处描述的方法检查条件编号尝试通过选择组件/边界条件的相对缩放来改进它。试试-ksp_diagonal_scale -ksp_diagonal_scale_fix也许改变问题的公式以产生更友好的代数方程。如果您无法更正缩放比例,则可能需要使用直接求解器。
  • 矩阵是非线性的(例如,使用非线性函数的有限差分进行评估)。尝试不同的差分参数(例如-mat_mffd_type ds)。尝试使用更高的精度来使差分更准确,./configure --with-precision=__float128 --download-f2cblaslapack. 检查它是否以“更容易”的参数机制收敛。
  • 对称方法用于非对称问题。
  • 经典的 Gram-Schmidt 变得不稳定,尝试-ksp_gmres_modifiedgramschmidt或使用一种不同正交化的方法,例如-ksp_type gcr

我对学生的建议是在这些情况下尝试直接求解器。原因是求解器可能不收敛的原因有两类:(i) 矩阵错误,或 (ii) 求解器/预处理器有问题。直接求解器几乎总是产生可以与您期望的解决方案进行比较的东西,因此如果直接求解器的答案看起来正确,那么您就知道问题出在迭代求解器/前提条件上。另一方面,如果答案看起来错误,则问题在于组装矩阵和右手边。

我通常只使用 UMFPACK 作为直接求解器。我敢肯定用 PETSC 尝试类似的东西很简单。