题
我正在尝试使用Lapack求解简单的线性方程系统。我使用针对带矩阵进行优化的DBSVG方法。我观察到了一种确实很奇怪的行为。当我以这种方式填充矩阵时:
for(i=0; i<DIM;i++) AB[0][i] = -1;
for(i=0; i<DIM;i++) AB[1][i] = 2;
for(i=0; i<DIM;i++) AB[2][i] = -1;
for(i=0; i<3; i++)
for(j=0;j<DIM;j++) {
AT[i*DIM+j]=AB[i][j];
}
并致电:
dgbsv_(&N, &KL, &KU, &NRHS, AT, &LDAB, myIpiv, x, &LDB, &INFO);
它可以很好地工作。但是,当我这样做时:
for(i=0; i<DIM;i++) AT[i] = -1;
for(i=0; i<DIM;i++) AT[DIM+i] = 2;
for(i=0; i<DIM;i++) AT[2*DIM+i] = -1;
它以填充NAN的向量产生。这是声明:
double AB[3][DIM], AT[3*DIM];
double x[DIM];
int myIpiv[DIM];
int N=DIM, KL=1, KU=1, NRHS=1, LDAB=DIM, LDB=DIM, INFO;
有任何想法吗?
解决方案
您没有正确布置乐队存储中的条目;这是在一次快乐事故之前工作。这 拉帕克文档 说:
On entry, the matrix A in band storage, in rows KL+1 to 2*KL+KU+1; rows 1 to KL of the array need not be set. The j-th column of A is stored in the j-th column of the array AB as follows: AB(KL+KU+1+i-j,j) = A(i,j) for max(1,j-KU)<=i<=min(N,j+KL) On exit, details of the factorization: U is stored as an upper triangular band matrix with KL+KU superdiagonals in rows 1 to KL+KU+1, and the multipliers used during the factorization are stored in rows KL+KU+2 to 2*KL+KU+1. See below for further details.
因此,如果您想要一个在对角线上的三角形矩阵,上下和下方的-1,则应该是:
* * * * * * * ... * * * *
* -1 -1 -1 -1 -1 -1 ... -1 -1 -1 -1
2 2 2 2 2 2 2 ... 2 2 2 2
-1 -1 -1 -1 -1 -1 -1 ... -1 -1 -1 *
在这种情况下,LDAB应为4。请记住,拉帕克(Lapack)使用列尺寸布局,因此在内存中应像这样的实际数组:
{ *, *, 2.0, -1.0, *, -1.0, 2.0, -1.0, *, -1.0, 2.0, -1.0, ... }
dgbsv
这两个相同的阵列给出了不同的结果,因为它正在读取您布置的阵列的末端。
其他提示
这是您使用的确切代码还是只是一个示例?我在这里运行了此代码(只需从您的帖子中剪切和粘贴,第二个循环中的AT到AT 2的更改:
const int DIM=10;
double AB[DIM][DIM], AT[3*DIM], AT2[3*DIM];
int i,j;
for(i=0; i<DIM;i++) AB[0][i] = -1;
for(i=0; i<DIM;i++) AB[1][i] = 2;
for(i=0; i<DIM;i++) AB[2][i] = -1;
for(i=0; i<3; i++)
for(j=0;j<DIM;j++) {
AT[i*DIM+j]=AB[i][j];
}
printf("AT:");
for (i=0;i<3*DIM;++i) printf("%lf ",AT[i]);
printf("\n\n");
for(i=0; i<DIM;i++) AT2[i] = -1;
for(i=0; i<DIM;i++) AT2[DIM+i] = 2;
for(i=0; i<DIM;i++) AT2[2*DIM+i] = -1;
printf("AT2:");
for (i=0;i<3*DIM;++i) printf("%lf ",AT2[i]);
printf("\n\n");
printf("Diff:");
for (i=0;i<3*DIM;++i) printf("%lf ",AT[i]-AT2[i]);
printf("\n\n");
并得到了这个输出
AT:-1.000000 -1.000000000000000000000000000000000000000000000000000000000000000000000000000000来入室-1.00000000000000000000000000000000000000000000来源-10000..8.8点视八点1.000000 -1.000000 -1.000000
AT2:-1.000000 -1.0000 -1.0000 -1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000来客-1.000000000000000000000000000000 000 000 000 000 -1.000000000000000000000000000000000000000000000000000000000000来-1.000000 -1.000000 -1.000000
差异:0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0000000000 0.0000 00000 0.000000000 0.000000 0.000000 0.000000 0.000000 0.00000000000000000000000000000000000000000000000000000000000000000000000000.0000000000000000000000000.0000000.0000000000000000000000000000000州0.00000000000000000000000000000000000000000000000000000000000000000.0000000.0000000000000000000000000000000州
显然在AT2和AT2是相同的。我期望的。