我编写了一个 SOR 算法来求解二维网格上的拉普拉斯方程。网格外侧固定为 0,中心方格固定为 10。
的某些值,我可以获得完全收敛的解,但不能获得其他值。在其他情况下,永远不会满足收敛条件,因此迭代到无穷大。我怀疑它与浮点/精度错误有关,但我不知道如何避免它。
条件如下:
其中是非固定点的数量,是一个小的有限值。基本上,当解中的平均逐点变化小于时,它应该收敛。
//Successive over-relaxation. argument b is the relaxation parameter.
unsigned int sor(double *v,double b) {
short i,j,t=1;
unsigned int s=0;
double l,r,n=((N-2)*(N-2)-1);
while (t) {//t is true when non-converged
r = 0.0;
for (i=1;i<N-1;i++) {
for (j=1;j<N-1;j++) {
if (i!=N/2 || j!=N/2) {
l = (*(v+N*(i+1)+j) + *(v+N*(i-1)+j) + *(v+N*i+j+1) + *(v+N*i+j-1))*0.25;
r += fabs(b*(l-*(v+N*i+j))); //add to residual
*(v+N*i+j) += b*(l-*(v+N*i+j)); //update new value
}
}
}
if (r/n<c) {t = 0;} //check convergence
s++;
if (s==USHRT_MAX) {t = 0;} //iteration limit is reached for some values of b. It will go higher than this, but USHRT_MAX is well beyond what is expected
}
return s;
}
网格是(在程序的其他地方定义)。理想情况下,. (Gauss-Seidel) 和其他一些值时,它收敛得很好,但不是普遍的。当变大时,它会更一致地收敛,但在某些区域仍然会失败。c=DBL_EPSILON
c
它有在附近爆发的趋势。对于较大的网格尺寸,这意味着找不到最佳参数,因为永远不会达到收敛。在附图中,是机器 epsilon。
更新:我怀疑对问题很重要。当数字变得非常小时,乘以任何大于 1.5 的值将导致数字显着向上取整。实际上,一个将开始表现得像一个,SOR 永远不会收敛......
问题是:我该如何避免这种情况?