提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
问题一 :PETSc 的make不成功
PETSc在./configure之后,运行make PETSC_DIR=安装路径/petsc-v3.19.0 PETSC_ARCH=arch-linux-c-debug all 后报错。
解决办法
直接简单粗暴地删除安装路径/petsc-v3.19.0/下的arch-linux-c-debug文件,然后重新./configure,即可解决。
./configure
意味着重新编译PETSc包里的各个文件,类似于初始化。
问题二:ex19在子域上设置ksp迭代终止的绝对误差和相对误差失败
命令行参数
``
mpiexec -n 4 ./ex19 -lidvelocity 100 -prandtl 0.72 -grashof 10000 -da_grid_x 64 -da_grid_y 64
-snes_type newtonls -ksp_type gmres -pc_type fieldsplit -pc_fieldsplit_type symmetric_multiplicative
-pc_fieldsplit_block_size 4 -pc_fieldsplit_0_fields 0,1,2 -pc_fieldsplit_1_fields 3
-fieldsplit_0_pc_type asm -fieldsplit_0_pc_asm_type restrict -fieldsplit_0_pc_asm_overlap 5
-fieldsplit_0_sub_pc_type lu -fieldsplit_1_pc_type asm -fieldsplit_1_pc_asm_type restrict
-fieldsplit_1_pc_asm_overlap 5 -fieldsplit_1_sub_pc_type lu -snes_monitor -snes_converged_reason
-fieldsplit_0_ksp_atol 1e-10 -fieldsplit_1_ksp_atol 1e-10 -fieldsplit_0_ksp_rtol 1e-6
-fieldsplit_1_ksp_rtol 1e-6
原因
:这里给出PETSc官方的回信内容。
The snes options are not relevant since the parts of a PCFIELDSPLIT are always linear problems.
By default PCFIELDSPLIT uses a KSP type of preonly on each split (that is it applies the preconditioner exactly once inside the PCApply_FieldSplit() hence the -fieldsplit_*_ksp_ options are not relevent. You can use -fieldsplit_ksp_type gmres for example to have it use gmres on each of the splits, but note that then you should use -ksp_type fgmres since using gmres inside a preconditioner results in a nonlinear preconditioner.
You can always run with -ksp_view to see the solver being used and the prefixes that currently make sense.
我理解的意思大概就是由于ksp线性求解器自身有默认的type——preonly,如果不在字块上单独定义他的type,那就不能修改其atol和rtol。同时snes不能在字块上设置,因为字块上通常是线性问题,所以这里我修改了代码如下:
mpiexec -n 4 ./ex19 -lidvelocity 100 -prandtl 0.72 -grashof 10000 -da_grid_x 64 -da_grid_y 64
-snes_type newtonls -pc_type fieldsplit -pc_fieldsplit_type symmetric_multiplicative
-pc_fieldsplit_block_size 4 -pc_fieldsplit_0_fields 0,1,2 -pc_fieldsplit_1_fields 3
-fieldsplit_0_pc_type asm -fieldsplit_0_pc_asm_type restrict -fieldsplit_0_pc_asm_overlap 5
-fieldsplit_0_sub_pc_type lu -fieldsplit_1_pc_type asm -fieldsplit_1_pc_asm_type restrict
-fieldsplit_1_pc_asm_overlap 5 -fieldsplit_1_sub_pc_type lu -snes_monitor -snes_converged_reason
-fieldsplit_ksp_type gmres
-fieldsplit_0_ksp_atol 1e-10 -fieldsplit_1_ksp_atol 1e-10
-fieldsplit_0_ksp_rtol 1e-8 -fieldsplit_1_ksp_rtol 1e-8
这样就能跑出来(因为之前在子域上设置ksp的atol和rtol时显示未使用该命令行,这次并没有报这样的信息)。同时,为了验证我们已经修改了子块上ksp的atol和rtol,我们在命令行后添加
-fieldsplit_0_ksp_view -fieldsplit_1_ksp_view
或者
-ksp_view
在输出的ksp信息中,可以看到
KSP Object: (fieldsplit_0_) 4 MPI processes
type: gmres
restart=30, using Classical (unmodified) Gram-Schmidt Orthogonalization with no iterative refinement
happy breakdown tolerance 1e-30
maximum iterations=10000, initial guess is zero
tolerances: relative=1e-08, absolute=1e-10, divergence=10000.
left preconditioning
using PRECONDITIONED norm type for convergence test
以及
KSP Object: (fieldsplit_1_) 4 MPI processes
type: gmres
restart=30, using Classical (unmodified) Gram-Schmidt Orthogonalization with no iterative refinement
happy breakdown tolerance 1e-30
maximum iterations=10000, initial guess is zero
tolerances: relative=1e-08, absolute=1e-10, divergence=10000.
left preconditioning
using PRECONDITIONED norm type for convergence test
说明字块上的迭代终止误差限修改成功。
此外,在未设置字块的KSP参数时,通过-ksp_view
,可以发现在字块上默认的KSP求解器type是preonly。而当KSPType为preonly
时,由于这不涉及迭代,因此迭代结束误差限和迭代计数等基本KSP参数不再适用。
KSP Object: (fieldsplit_0_) 4 MPI processes
type: preonly
maximum iterations=10000, initial guess is zero
tolerances: relative=1e-05, absolute=1e-50, divergence=10000.
left preconditioning
using NONE norm type for convergence test
KSP Object: (fieldsplit_1_) 4 MPI processes
type: preonly
maximum iterations=10000, initial guess is zero
tolerances: relative=1e-05, absolute=1e-50, divergence=10000.
left preconditioning
using NONE norm type for convergence test
PETSc官网上关于KSPPREONLY的解释中有这样的一句话:
==This implements a method that applies ONLY the preconditioner exactly once. ==
结合后面的理解,这里要说明的是,KSPPREONLY仅做预处理,而不做迭代求解。
PETSc关于KSPPREONLY的链接: link
注
1.在解决这个问题的过程中,意外发现在命令行中输入-snes_view
,不仅可以知道SNES求解器的一些配置,还可以直接得到总的线性迭代次数。(非常nice)
问题三 tsirm.c文件的学习
1.命令行无法修改某些参数
Number of residuals for minimization ( -ksp_tsirm_size_ls)、
Maximum number of iterations for the minimization step(-ksp_tsirm_max_it_ls)、
Method used for the minimization step(-ksp_tsirm_cgls)、
Tolerance threshold for the minimization step(-ksp_tsirm_tol_ls).
一开始我觉得:
原因是在源文件在KSPSetUp_TSIRM函数中初始化这些变量后,无法再通过命令行修改这些变量的值,一方面可能是函数调用顺序有问题,在调用命令行设置参数函数(KSPSetFromOptions_TSIRM)之后,又调用了KSPSetUp_TSIRM函数。另一方面,由于KSPSetUp_TSIRM函数的返回值被声明为static,所以这个函数是静态函数,静态函数只是在声明他的文件当中可见,不能被其他文件所用。但这跟其内部的值不能从外部更改没有关系,于是有了下面这段代码的思考
#include <stdio.h>
static int max(int *a,int *b)
{
*a=1,*b=2;
return (*a>*b)?*a:*b;
}
static int max1(int a,int b)
{
a=1,b=2;
return (a>b)?a:b;
}
int main()
{
/* 基本事实:函数变量为指针时,在函数内部修改变量所指向的值,那么外部值会跟着改变;
而当函数变量是具体的数时,在函数内部修改变量的值,外部的值不会更改 */
int a=3,b=1;
int c=3,d=1;
printf("max=%d\n",max1(c,d));
printf("c=%d,d=%d\n",c,d);
printf("max=%d\n",max(&a,&b));
printf("a=%d,b=%d\n",a,b);
return 0;
}
/*输出结果
max=2
c=3,d=1
max=2
a=1,b=2
*/
原因还是没有找到,这里静态与否无关紧要。
解决办法
将那几个在KSPSetUp_TSIRM函数中初始化的变量放到KSPSetFromOptions_TSIRM函数中即可。或者说只要他们不出现在KSPSetUp_TSIRM函数中就可以,具体原因有待考究,反正不是static的问题。