2016-03-31 22 views
1

私はインテルのMKLでLAPACKと呼ばれるLAPACKへのCインタフェースを使って一般的なバンド行列を解こうとしています。呼び出す関数は*gbsvです。*はその形式を示しています。残念ながら、私はVERYのCインタフェースを使用して帯状行列をどのようにフォーマットするかについての実例を見つけるのは難しいと考えています。誰かがそこにいるすべてのCユーザーのための実用的な例を提供できるなら、私はそれが役に立つと確信しています。LAPACKEのバンド行列のフォーマット

fortranレイアウトは例としてhereとして与えられていますが、私はLAPACKEへの入力のためにこれをどのようにフォーマットするのかは正確には分かりません。私はまた、私の問題では、バンド飛行行列をオンザフライで構築しなければならないことに注意する必要があります。だから、各iノードのための5つの係数A、B、C、D、Eがあります。これらはLAPACKEに渡されます。

+0

私のインストールのMKLのルートフォルダでは、私が使用しているルーチンのすべての実装例を使用してファイルをtarでまとめている「例」サブフォルダがあるが示された(たとえば、 LAPACKE_dgesv、cblas_dgemm、mkl_dimatcopy)。そこを見ましたか? – PZwan

+0

私は見ましたが、バンドマトリックスソルバ* gbsvの例はありません。私が間違っているなら私を訂正してください。私はダブルチェックします。 – ThatsRightJack

+0

あなたは正しいです。私はlapacke examplesフォルダのgbsvをgrepして何も見つけられませんでした。申し訳ありませんが、私は手伝っていませんでした。 – PZwan

答えて

1

機能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) 

関数LAPACKのdgbsv()との主な違いは、LAPACK_ROW_MAJOR(C順序)またはLAPACK_COL_MAJOR(Fortranの順序)とすることができる引数matrix_layout、です。 LAPACK_ROW_MAJORの場合、LAPACKE_dgbsvは行列を転置します。dgbsv()を呼び出し、行列をC順序に転置します。

他の引数の意味は、関数dgbsv()と同じです。 LAPACK_ROW_MAJORが使用されている場合、dgbsv()の正しいldabLAPACKE_dgbsv()で、ldabの引数はnに設定できます。しかし、dgbsv()のように、因数分解の詳細を格納するために行列abに追加のスペースを割り当てる必要があります。

次の例では、LAPACKE_dgbsv()を使用して、センタリングされた有限差分による1D定常拡散を解きます。 Null温度境界条件が考慮され、正弦波の1つが正しさをチェックするためのソース項として使用されます。次のプログラムは、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; 
} 
関連する問題