SuperLU 有两个驱动程序例程,即简单和专业,调用这些例程对一般非对称稀疏方程组求解的方式与 SPSOLVE 中的一次调用接口完全相同。可在单精度、双精度、复数和双精度复数数据类型中使用这些例程以及用户可调用的其他 SuperLU 例程。以下各表中列出了所有外部例程的单精度名称。这些例程都有可用的手册页(第 3P 部分)。有关在应用程序中使用的稀疏矩阵数据结构的说明,另请参见 SuperMatrix(3P) 手册页。
|
|
SuperLU 例程是用 C 编写的。因此,与列和行相关的索引必须从 0 开始。在以下示例中,将调用双精度简单驱动程序 dgssv() 来计算因子 L 和 U,并对解矩阵求解。
示例 6 SuperLU 简单驱动程序#include <stdio.h> #include <sunperf.h> #define M 5 #define N 5 int main(int argc, char *argv[]) { SuperMatrix A, L, U, B1, B2; int perm_r[M]; /* row permutations from partial pivoting */ int perm_c[N]; /* column permutation vector */ int info, i; superlu_options_t options; SuperLUStat_t stat; trans_t trans = NOTRANS; printf("Example code calling SuperLU simple driver to factor a \n"); printf("general unsymmetric matrix and solve two right-hand-side matrices\n"); /* the matrix in Harwell-Boeing format. */ int m = M; int n = M; int nnz = 12; double *dp; /* nonzeros of A, column-wise */ double a[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0}; /* row index of nonzeros */ int asub[] = {0, 1, 4, 1, 2, 4, 0, 2, 0, 3, 3, 4}; /* column pointers */ int xa[] = {0, 3, 6, 8, 10, 12}; /* Create Matrix A in the format expected by SuperLU */ dCreate_CompCol_Matrix(&A, m, n, nnz, a, asub, xa, SLU_NC, SLU_D, SLU_GE); int nrhs = 1; double rhs1[] = {17.0, 6.0, 13.0, 21.0, 21.0}; double rhs2[] = {17*.3, 6*.3, 13*.3, 21*.3, 21*.3}; /* right-hand side matrix B1, B2 */ dCreate_Dense_Matrix(&B1, m, nrhs, rhs1, m, SLU_DN, SLU_D, SLU_GE); dCreate_Dense_Matrix(&B2, m, nrhs, rhs2, m, SLU_DN, SLU_D, SLU_GE); /* set options that control behavior of solver to default parameters */ set_default_options(&options); options.ColPerm = NATURAL; /* Initialize the statistics variables. */ StatInit(&stat); /* factor input matrix and solve the first right-hand-side matrix */ dgssv(&options, &A, perm_c, perm_r, &L, &U, &B1, &stat, &info); printf("\nsolution matrix B1:\n"); dp = (double *) (((NCformat *)B1.Store)->nzval); printf(" i rhs[i] expected\n"); for (i=0; i<M; i++) printf("%5d %7.4lf %7.4lf\n", i, dp[i], 1.0); printf("Factor time = %8.2e sec\n", stat.utime[FACT]); printf("Solve time = %8.2e sec\n\n\n", stat.utime[SOLVE]); /* solve the second right-hand-side matrix */ dgstrs(trans, &L, &U, perm_c, perm_r, &B2, &stat, &info); printf("solution matrix B2:\n"); dp = (double *) (((NCformat *)B2.Store)->nzval); printf(" i rhs[i] expected\n"); for (i=0; i<M; i++) printf("%5d %7.4lf %7.4lf\n", i, dp[i], 0.3); printf("Solve time = %8.2e sec\n", stat.utime[SOLVE]); StatFree(&stat); Destroy_CompCol_Matrix(&A); Destroy_SuperMatrix_Store(&B1); Destroy_SuperMatrix_Store(&B2); Destroy_SuperNode_Matrix(&L); Destroy_CompCol_Matrix(&U); }
运行上例:
my_system% cc -xmemalign=8s simple.c -library=sunperf my_system% a.out Example code calling SuperLU simple driver to factor a general unsymmetric matrix and solve two right-hand-side matrices solution matrix B1: i rhs[i] expected 0 1.0000 1.0000 1 1.0000 1.0000 2 1.0000 1.0000 3 1.0000 1.0000 4 1.0000 1.0000 Factor time = 5.43e-02 sec Solve time = 6.76e-03 sec solution matrix B2: i rhs[i] expected 0 0.3000 0.3000 1 0.3000 0.3000 2 0.3000 0.3000 3 0.3000 0.3000 4 0.3000 0.3000 Solve time = 6.76e-03 sec示例 7 SuperLU 专业驱动程序
#include <stdio.h> #include <sunperf.h> #define M 5 #define N 5 #define NRHS 1 int main(int argc, char *argv[]) { SuperMatrix A, L, U, B, X; int perm_r[M]; /* row permutations from partial pivoting */ int perm_c[N]; /* column permutation vector */ int etree[N]; /* elimination tree */ double ferr[NRHS]; /* estimated forward error bound */ double berr[NRHS]; /* component-wise relative backward error */ double C[N], R[M]; /* column and row scale factors */ double rpg, rcond; char equed[1]; /* Specifies the form of equilibration that was done */ double *work, *dp; /* user-supplied workspace */ int lwork = 0; /* 0 for workspace to be allocated by system malloc */ int info, i; superlu_options_t options; SuperLUStat_t stat; mem_usage_t mem_usage; printf("Example code calling SuperLU expert driver\n\n"); /* the matrix in Harwell-Boeing format. */ int m = M; int n = M; int nnz = 12; /* nonzeros of A, column-wise */ double a[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0}; /* row index of nonzeros */ int asub[] = {0, 1, 4, 1, 2, 4, 0, 2, 0, 3, 3, 4}; /* column pointers */ int xa[] = {0, 3, 6, 8, 10, 12}; int nrhs = NRHS; double rhs[] = {17.0, 6.0, 13.0, 21.0, 21.0}; /* Create Matrix A in the format expected by SuperLU */ dCreate_CompCol_Matrix(&A, m, n, nnz, a, asub, xa, SLU_NC, SLU_D, SLU_GE); /* right-hand-side matrix B */ dCreate_Dense_Matrix(&B, m, nrhs, rhs, m, SLU_DN, SLU_D, SLU_GE); /* solution matrix X */ dCreate_Dense_Matrix(&X, m, nrhs, rhs, m, SLU_DN, SLU_D, SLU_GE); set_default_options(&options); options.ColPerm = NATURAL; /* Initialize the statistics variables. */ StatInit(&stat); dgssvx(&options, &A, perm_c, perm_r, etree, equed, R, C, &L, &U, work, lwork, &B, &X, &rpg, &rcond, ferr, berr, &mem_usage, &stat, &info); dp = (double *) (((NCformat *)X.Store)->nzval); printf(" i rhs[i] expected\n"); for (i=0; i<M; i++) printf("%5d %7.4lf %7.4lf\n", i, dp[i], 1.0); printf("Factor time = %8.2e sec\n", stat.utime[FACT]); printf("Solve time = %8.2e sec\n", stat.utime[SOLVE]); StatFree(&stat); Destroy_CompCol_Matrix(&A); Destroy_SuperMatrix_Store(&B); Destroy_SuperNode_Matrix(&L); Destroy_CompCol_Matrix(&U); }
运行上例:
my_system% cc -xmemalign=8s expert.c -library=sunperf my_system% a.out Example code calling SuperLU expert driver i rhs[i] expected 0 1.0000 1.0000 1 1.0000 1.0000 2 1.0000 1.0000 3 1.0000 1.0000 4 1.0000 1.0000 Factor time = 1.25e-03 sec Solve time = 1.70e-04 sec
从 Fortran 调用 SuperLU 的最简单方式是通过 SPSOLVE 接口。可选择 SuperLU,通过 SPSOLVE 中的初始化例程 DGSSIN() 的输入参数 MTXTYP 对非对称稀疏矩阵求解。一次调用接口例程 DGSSFS() 中也有相同的参数。
下表列出了 MTXTYP 的有效选项。要调用 SuperLU,可选择 's0' 或 'S0' 作为矩阵类型。由于 SPSOLVE 是基于 Fortran 的,因此与输入矩阵相关的所有列和行索引都必须从 1 开始。然而,如果通过 DGSSIN() 或 DGSSFS() 调用 SuperLU(通过设置 MTXTYP = 's0' 或 'S0'),则这些索引必须从 0 开始。
|
在调用例程 DGSSIN() 之后必须调用例程 DGSSOR(),以执行填充简化排序和符号因式分解。可使用一个字符参数 (ORDMTHD) 选择所需的排序方法。一次调用接口例程 DGSSFS() 中也存在此参数。下表列出了 SPSOLVE 和 SuperLU 的有效排序方法。也可以通过调用 DGSSUO() 而不是 DGSSOR() 来为求解器提供特定的排序方法。输入排列数组必须从 0 开始。
|
如上所示,一般嵌套分割方法在 SuperLU 中不可用。另一方面,基于 A'+A 的最小度排序和近似最小度列排序在 SPSOLVE 中不可用。
以下代码示例显示了如何通过标准接口和 SPSOLVE 的一次调用接口选择 SuperLU 来对一般非对称方程组进行因式分解和求解。
示例 8 通过 SPSOLVE 标准接口调用 SuperLUprogram SLU c This program is an example driver that calls the regular interface of SPSOLVE c to invoke SuperLU to factor and solve a general unsymmetric system. implicit none integer neqns, ier, msglvl, outunt, ldrhs, nrhs, i character mtxtyp*2, pivot*1, ordmthd*3 double precision handle(150) integer colstr(6), rowind(12) double precision values(12), rhs(5), xexpct(5) c Sparse matrix structure and value arrays. Coefficient matrix c is a general unsymmetric sparse matrix. c Ax = b, (solve for x) where: c 1.0 0.0 7.0 9.0 0.0 1.0 17.0 c 2.0 4.0 0.0 0.0 0.0 1.0 6.0 c A = 0.0 5.0 8.0 0.0 0.0 x = 1.0 b = 13.0 c 0.0 0.0 0.0 10.0 11.0 1.0 21.0 c 3.0 6.0 0.0 0.0 12.0 1.0 21.0 c Array indices must be zero-based for calling SuperLU data colstr / 0, 3, 6, 8, 10, 12 / data rowind / 0, 1, 4, 1, 2, 4, 0, 2, 0, 3, 3, 4 / data values / 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, $ 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 / data rhs / 17.0, 6.0, 13.0, 21.0, 21.0 / data xexpct / 1.0d0, 1.0d0, 1.0d0, 1.0d0, 1.0d0 / c initialize solver mtxtyp= 's0' pivot = 'n' neqns = 5 outunt = 6 msglvl = 0 c call regular interface call dgssin(mtxtyp, pivot, neqns , colstr, rowind,outunt, msglvl, & handle, ier) if ( ier .ne. 0 ) goto 110 c ordering and symbolic factorization ordmthd = 'mmd' call dgssor(ordmthd, handle, ier) if ( ier .ne. 0 ) goto 110 c numeric factorization call dgssfa ( neqns, colstr, rowind, values, handle, ier ) if ( ier .ne. 0 ) goto 110 c solution nrhs = 1 ldrhs = 5 call dgsssl ( nrhs, rhs, ldrhs, handle, ier ) if ( ier .ne. 0 ) goto 110 c deallocate sparse solver storage call dgssda ( handle, ier ) if ( ier .ne. 0 ) goto 110 c print values of sol write(6,200) 'i', 'rhs(i)', 'expected rhs(i)', 'error' do i = 1, neqns write(6,300) i, rhs(i), xexpct(i), (rhs(i)-xexpct(i)) enddo stop 110 continue c call to sparse solver returns an error write ( 6 , 400 ) & ' example: FAILED sparse solver error number = ', ier stop 200 format(4x,a1,3x,a6,3x,a15,4x,a6) 300 format(i5,3x,f5.2,7x,f5.2,8x,e10.2) ! i/sol/xexpct values 400 format(a60,i20) ! fail message, sparse solver error number end
运行上例:
my_system% f95 -dalign slu.f -library=sunperf my_system% a.out i rhs(i) expected rhs(i) error 1 1.00 1.00 0.00E+00 2 1.00 1.00 -0.33E-15 3 1.00 1.00 0.22E-15 4 1.00 1.00 -0.11E-15 5 1.00 1.00 0.22E-15示例 9 通过一次调用 SPSOLVE 接口调用 SuperLU
program SLU_SINGLE c This program is an example driver that calls the regular interface of SPSOLVE c to invoke SuperLU to factor and solve a general unsymmetric system. implicit none integer neqns, ier, msglvl, outunt, ldrhs, nrhs, i character mtxtyp*2, pivot*1, ordmthd*3 double precision handle(150) integer colstr(6), rowind(12) double precision values(12), rhs(5), xexpct(5) c Sparse matrix structure and value arrays. Coefficient matrix c is a general unsymmetric sparse matrix. c Ax = b, (solve for x) where: c 1.0 0.0 7.0 9.0 0.0 1.0 17.0 c 2.0 4.0 0.0 0.0 0.0 1.0 6.0 c A = 0.0 5.0 8.0 0.0 0.0 x = 1.0 b = 13.0 c 0.0 0.0 0.0 10.0 11.0 1.0 21.0 c 3.0 6.0 0.0 0.0 12.0 1.0 21.0 c Array indices must be zero-based for calling SuperLU data colstr / 0, 3, 6, 8, 10, 12 / data rowind / 0, 1, 4, 1, 2, 4, 0, 2, 0, 3, 3, 4 / data values / 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, $ 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 / data rhs / 17.0, 6.0, 13.0, 21.0, 21.0 / data xexpct / 1.0d0, 1.0d0, 1.0d0, 1.0d0, 1.0d0 / c initialize solver mtxtyp= 's0' pivot = 'n' neqns = 5 outunt = 6 msglvl = 0 ordmthd = 'mmd' nrhs = 1 ldrhs = 5 c One-call routine of SPSOLVE call dgssfs (mtxtyp, pivot, neqns , colstr, rowind, & values, nrhs , rhs, ldrhs , ordmthd, & outunt, msglvl, handle, ier) if ( ier .ne. 0 ) goto 110 c deallocate sparse solver storage call dgssda ( handle, ier ) if ( ier .ne. 0 ) goto 110 c print values of sol write(6,200) 'i', 'rhs(i)', 'expected rhs(i)', 'error' do i = 1, neqns write(6,300) i, rhs(i), xexpct(i), (rhs(i)-xexpct(i)) enddo stop 110 continue c call to sparse solver returns an error write ( 6 , 400 ) & ' example: FAILED sparse solver error number = ', ier stop 200 format(4x,a1,3x,a6,3x,a15,4x,a6) 300 format(i5,3x,f5.2,7x,f5.2,8x,e10.2) ! i/sol/xexpct values 400 format(a60,i20) ! fail message, sparse solver error number end
运行上例:
my_system% f95 -dalign slu_single.f -library=sunperf my_system% a.out i rhs(i) expected rhs(i) error 1 1.00 1.00 0.00E+00 2 1.00 1.00 -0.33E-15 3 1.00 1.00 0.22E-15 4 1.00 1.00 -0.11E-15 5 1.00 1.00 0.22E-15