当使用众所周知的ARPACK库来解决大型,稀疏的广义特征值问题(这里,我正在使用C ++接口)时,我注意到在尝试调用时非常奇怪的解决方案
nev = 10 // number of eigenvalues to calculate
ARluSymGenEig<double> eigenvalueProblem('C', nev, A, B, 5., "SM");
eigenvalueProblem.FindEigenvectors();
在数学上:使用线性元素在单位平方[0,1] ^ 2上的5x5网格上求解Cayley模式中的拉普拉斯 - 特征值问题。 'A'是相应的刚度 - 'B'是质量矩阵。没有输入Dirchlet边界条件,因此这就是Neumann问题。
我只对前10个最小的特征对感兴趣,因此“SM”(最小幅度); “5”。是一些转移参数。
我得到了这个输出:
~/LapEVSol$ ./main SquareGrid.txt meshoutput.vtk
Reading eigenvalue problem from file SquareGrid.txt...
** On entry to dgstrs, parameter number 6 had an illegal value
** On entry to dgstrs, parameter number 6 had an illegal value
** On entry to dgstrs, parameter number 6 had an illegal value
...
** On entry to dgstrs, parameter number 6 had an illegal value
** On entry to dgstrs, parameter number 6 had an illegal value
** On entry to dgstrs, parameter number 6 had an illegal value
Done!
Dimension of the system : 25
Number of 'requested' eigenvalues : 10
Number of 'converged' eigenvalues : 10
Number of Arnoldi vectors generated: 21
Number of iterations taken : 10
Eigenvalues:
lambda[1]: -90.5854
lambda[2]: -16.2358
lambda[3]: -11.0635
lambda[4]: -8.95837
lambda[5]: -5.78369
lambda[6]: 16.5812
lambda[7]: 16.9097
lambda[8]: 36.4766
lambda[9]: 62.1445
lambda[10]: 66.4824
||A*x(0) - lambda(0)*B*x(0)||: 0.252506
||A*x(1) - lambda(1)*B*x(1)||: 0.75909
||A*x(2) - lambda(2)*B*x(2)||: 0.911785
||A*x(3) - lambda(3)*B*x(3)||: 0.901433
||A*x(4) - lambda(4)*B*x(4)||: 1.20555
||A*x(5) - lambda(5)*B*x(5)||: 0.980946
||A*x(6) - lambda(6)*B*x(6)||: 0.985718
||A*x(7) - lambda(7)*B*x(7)||: 0.26326
||A*x(8) - lambda(8)*B*x(8)||: 0.204725
||A*x(9) - lambda(9)*B*x(9)||: 0.113176
当然这输出是完全错误的。特征值应该都是非负的,大概是0,10,10,22,47,47等。带有dgstrs()的错误消息导致假设,ARPACK调用SuperLU例程dgstrs()错误解决一些线性系统。在代码中,ARPACK试图调用
函数模板void ARluSymPencil :: MultInvAsBv(ARTYPE v,ARTYPE * w):*
Create_Dense_Matrix(&RHS, A->nrows(), 1, w, A->nrows(), SLU_DN, SLU_GE);
gstrs(trans, &L, &U, permc, permr, &RHS, &stat, &info);
superluc.h中的
inline void gstrs(trans_t trans, SuperMatrix *L, SuperMatrix *U,
int *perm_c, int *perm_r, SuperMatrix *B, SuperLUStat_t* stat, int *info)
{
if (L->Dtype == SLU_D) { // calling the double precision routine.
dgstrs(trans,L,U,perm_c,perm_r,B,stat,info);
}
...
}
inline void Create_Dense_Matrix(SuperMatrix* A, int m, int n, double* x,
int ldx, Stype_t S, Mtype_t M)
{
dCreate_Dense_Matrix(A,m,n,x,ldx,S,SLU_D,M);
} // Create_Dense_Matrix (double).
dgstrs()和dCreate_Dense_Matrix()是用Fortran编写的SuperLU例程,因此难以在调试中进一步跟踪。错误消息恰好发生在dgstrs()中,并且说第六个参数有问题,即SuperMatrix B. B在Create_Dense_Matrix()函数中创建,实际上看起来有点奇怪,因为参数“.. 。,A-> nrows(),1,...,A-> nrows()“,它基本上创建了一个密集的”m次1“矩阵,其前导维度为n(其中m是行数和n是输入矩阵A)的列数 - 我希望这是不同的。
即使在ARPACK ++给出的示例中,例如lsymgreg.cc(它基本上调用与我的问题完全相同的函数),输出也会给出错误的负特征值,并且具有相同的dgstrs() - 错误。并且所有测试的问题都具有非常小的尺寸(25x25矩阵),因此不存在任何稳定性问题并且对称特征值问题具有良好的条件。
是否曾经遇到过与ARPACK / ARPACK ++相同的问题,或者知道原因是什么?
编辑:以下是有关此问题的两个主要功能的更多信息:
首先在 argsym.h中找到FindArnoldiBasis():
template<class ARFLOAT, class ARFOP, class ARFB>
int ARSymGenEig<ARFLOAT, ARFOP, ARFB>::FindArnoldiBasis()
{
ARFLOAT* temp;
if (this->mode != 5) { // Using base function if not in Cayley mode.
return ARGenEig<ARFLOAT, ARFLOAT, ARFOP, ARFB>::FindArnoldiBasis();
}
else {
temp = new ARFLOAT[this->n+1];
if (!this->BasisOK) this->Restart();
// Changing to auto shift mode.
if (!this->AutoShift) {
ArpackError::Set(ArpackError::CHANGING_AUTOSHIFT, "FindArnoldiBasis");
this->AutoShift=true;
}
// ARPACK main loop.
while (!this->BasisOK) {
// Calling Aupp.
try { this->TakeStep(); }
catch (ArpackError) {
ArpackError(ArpackError::CANNOT_FIND_BASIS, "FindArnoldiBasis");
delete[] temp;
return 0;
}
switch (this->ido) {
case -1:
// Performing y <- B*x for the first time.
this->ipntr[3] = this->ipntr[2]+this->n; // not a clever idea, but...
(this->objB->*(this->MultBx))(&this->workd[this->ipntr[1]],&this->workd[this->ipntr[3]]);
case 1:
// Performing y <- OP*(A+sigma*B)*x, B*x is already available.
(this->objB->*MultAx)(&this->workd[this->ipntr[1]], temp);
axpy(this->n, this->sigmaR, &this->workd[this->ipntr[3]], 1, temp, 1);
(this->objOP->*(this->MultOPx))(temp, &this->workd[this->ipntr[2]]);
break;
case 2:
// Performing y <- B*x.
(this->objB->*(this->MultBx))(&this->workd[this->ipntr[1]],&this->workd[this->ipntr[2]]);
}
}
delete[] temp;
return this->nconv;
}
// FindArnoldiBasis.
此方法调用(在案例1中) MultOPx(),它调用 MultInvAsBv(),因此 gstrs():
template<class ARTYPE>
void ARluSymPencil<ARTYPE>::MultInvAsBv(ARTYPE* v, ARTYPE* w)
{
// Quitting the function if AsB was not factored.
if (!IsFactored()) {
throw ArpackError(ArpackError::NOT_FACTORED_MATRIX,
"ARluSymPencil::MultInvAsBv");
}
// Solving AsB.w = v.
int info;
SuperMatrix RHS;
copy(A->nrows(), v, 1, w, 1);
Create_Dense_Matrix(&RHS, A->nrows(), 1, w, A->nrows(), SLU_DN, SLU_GE);
// gstrs("N", &L, &U, permr, permc, &RHS, &info);
trans_t trans = NOTRANS;
StatInit(&stat);
gstrs(trans, &L, &U, permc, permr, &RHS, &stat, &info);
Destroy_SuperMatrix_Store(&RHS); // delete RHS.Store;
} // MultInvAsBv.
变量L,U,permc和permr位于类ARluSymPencil中,其中包含上述成员函数:
template<class ARTYPE>
class ARluSymPencil
{
protected:
bool factored;
int* permc;
int* permr;
char part;
char uplo;
ARluSymMatrix<ARTYPE>* A;
ARluSymMatrix<ARTYPE>* B;
SuperMatrix L;
SuperMatrix U;
SuperLUStat_t stat;
(SuperMatrix和其他一些类型在SuperLU库中定义)