代码之家  ›  专栏  ›  技术社区  ›  ThatsRightJack

LAPACKE的带状矩阵格式

  •  2
  • ThatsRightJack  · 技术社区  · 9 年前

    我正在尝试使用英特尔MKL中称为LAPACKE的LAPACK的C接口来求解一个通用带状矩阵。我试图调用的函数是 *gbsv ,其中 * 表示格式。不幸的是,我找到了 非常 很难找到关于如何使用C接口格式化带状矩阵的工作示例。如果有人能为所有C用户提供一个工作示例,我向您保证,这将是有帮助的。

    以fortran布局为例 here ,但我不确定如何将其格式化为LAPACKE的输入。我还应该注意,在我的问题中,我必须快速构建带状矩阵。所以我有5个系数,A,B,C,D,E,每个I节点,它们必须被放入带状矩阵形式,然后传递给LAPACKE。

    1 回复  |  直到 9 年前
        1
  •  2
  •   francis    9 年前

    函数的原型 LAPACKE_dgbsv() 如下所示:

    lapack_int LAPACKE_dgbsv( int matrix_layout, lapack_int n, lapack_int kl,
                          lapack_int ku, lapack_int nrhs, double* ab,
                          lapack_int ldab, lapack_int* ipiv, double* b,
                          lapack_int ldb )
    

    功能的主要区别 dgbsv() Lapack的观点 matrix_layout ,可以是 LAPACK_ROW_MAJOR (C订购)或 LAPACK_COL_MAJOR (Fortran排序)。如果 LAPACK_ROW_MAJOR , LAPACKE_dgbsv 将转置矩阵,调用 dgbsv() 然后将矩阵转置回C排序。

    其他参数的含义与函数相同 dgbsv() 如果 LAPACK_ROW_MAJOR 则使用正确的 ldab 对于 dgbsv() 将由以下公式计算 LAPACKE_dgbsv() 和论点 低密度脂蛋白抗体 可以设置为 n 然而,就像 dgbsv() ,必须为矩阵分配额外的空间 ab 以存储分解的详细信息。

    以下示例使用 LAPACKE_dgbsv() 用中心有限差分法求解一维稳态扩散。考虑零温度边界条件,并将其中一个正弦波用作源项以检查正确性。以下程序由编译 gcc main3.c -o main3 -llapacke -llapack -lblas -Wall :

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    #include <time.h>
    
    #include <lapacke.h>
    
    int main(void){
    
        srand (time(NULL));
    
        //size of the matrix
        int n=10;
        // number of right-hand size
        int nrhs=4;
    
        int ku=2;
        int kl=2;
        // ldab is larger than the number of bands, 
        // to store the details of factorization
        int ldab = 2*kl+ku+1;
    
        //memory initialization
        double *a=malloc(n*ldab*sizeof(double));
        if(a==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
    
        double *b=malloc(n*nrhs*sizeof(double));
        if(b==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
    
        int *ipiv=malloc(n*sizeof(int));
        if(ipiv==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
    
        int i,j;
    
        double fact=1*((n+1.)*(n+1.));
        //matrix initialization : the different bands
        // are stored in rows kl <= j< 2kl+ku+1
        for(i=0;i<n;i++){
            a[(0+kl)*n+i]=0;
            a[(1+kl)*n+i]=-1*fact;
            a[(2+kl)*n+i]=2*fact;
            a[(3+kl)*n+i]=-1*fact;
            a[(4+kl)*n+i]=0;
    
            //initialize source terms 
            for(j=0;j<nrhs;j++){
                b[i*nrhs+j]=sin(M_PI*(i+1)/(n+1.));
            }
        }
        printf("end ini \n");
    
        int ierr;
    
    
        // ROW_MAJOR is C order, Lapacke will compute ldab by himself.
        ierr=LAPACKE_dgbsv(LAPACK_ROW_MAJOR, n, kl,ku,nrhs, a,n, ipiv,  b,nrhs );
    
    
        if(ierr<0){LAPACKE_xerbla( "LAPACKE_dgbsv", ierr );}
    
        printf("output of LAPACKE_dgbsv\n");
        for(i=0;i<n;i++){
            for(j=0;j<nrhs;j++){
                printf("%g ",b[i*nrhs+j]);
            }
            printf("\n");
        }
    
        //checking correctness
        double norm=0;
        double diffnorm=0;
        for(i=0;i<n;i++){
            for(j=0;j<nrhs;j++){
                norm+=b[i*nrhs+j]*b[i*nrhs+j];
                diffnorm+=(b[i*nrhs+j]-1./(M_PI*M_PI)*sin(M_PI*(i+1)/(n+1.)))*(b[i*nrhs+j]-1./(M_PI*M_PI)*sin(M_PI*(i+1)/(n+1.)));
            }
        }
        printf("analical solution is 1/(PI*PI)*sin(x)\n");
        printf("relative difference is %g\n",sqrt(diffnorm/norm));
    
    
        free(a);
        free(b);
        free(ipiv);
    
        return 0;
    }