14eb8e494SKris Buschelman /*$Id: lusol.c,v 1.11 2001/08/06 21:15:14 bsmith Exp $*/ 24eb8e494SKris Buschelman /* 34eb8e494SKris Buschelman Provides an interface to the LUSOL package of .... 44eb8e494SKris Buschelman 54eb8e494SKris Buschelman */ 64eb8e494SKris Buschelman #include "src/mat/impls/aij/seq/aij.h" 74eb8e494SKris Buschelman 84eb8e494SKris Buschelman #if defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 94eb8e494SKris Buschelman #define LU1FAC lu1fac_ 104eb8e494SKris Buschelman #define LU6SOL lu6sol_ 114eb8e494SKris Buschelman #define M1PAGE m1page_ 124eb8e494SKris Buschelman #define M5SETX m5setx_ 134eb8e494SKris Buschelman #define M6RDEL m6rdel_ 144eb8e494SKris Buschelman #elif !defined(PETSC_HAVE_FORTRAN_CAPS) 154eb8e494SKris Buschelman #define LU1FAC lu1fac 164eb8e494SKris Buschelman #define LU6SOL lu6sol 174eb8e494SKris Buschelman #define M1PAGE m1page 184eb8e494SKris Buschelman #define M5SETX m5setx 194eb8e494SKris Buschelman #define M6RDEL m6rdel 204eb8e494SKris Buschelman #endif 214eb8e494SKris Buschelman 224eb8e494SKris Buschelman EXTERN_C_BEGIN 234eb8e494SKris Buschelman /* 244eb8e494SKris Buschelman Dummy symbols that the MINOS files mi25bfac.f and mi15blas.f may require 254eb8e494SKris Buschelman */ 264eb8e494SKris Buschelman void PETSC_STDCALL M1PAGE() { 274eb8e494SKris Buschelman ; 284eb8e494SKris Buschelman } 294eb8e494SKris Buschelman void PETSC_STDCALL M5SETX() { 304eb8e494SKris Buschelman ; 314eb8e494SKris Buschelman } 324eb8e494SKris Buschelman 334eb8e494SKris Buschelman void PETSC_STDCALL M6RDEL() { 344eb8e494SKris Buschelman ; 354eb8e494SKris Buschelman } 364eb8e494SKris Buschelman 374eb8e494SKris Buschelman extern void PETSC_STDCALL LU1FAC (int *m, int *n, int *nnz, int *size, int *luparm, 384eb8e494SKris Buschelman double *parmlu, double *data, int *indc, int *indr, 394eb8e494SKris Buschelman int *rowperm, int *colperm, int *collen, int *rowlen, 404eb8e494SKris Buschelman int *colstart, int *rowstart, int *rploc, int *cploc, 414eb8e494SKris Buschelman int *rpinv, int *cpinv, double *w, int *inform); 424eb8e494SKris Buschelman 434eb8e494SKris Buschelman extern void PETSC_STDCALL LU6SOL (int *mode, int *m, int *n, double *rhs, double *x, 444eb8e494SKris Buschelman int *size, int *luparm, double *parmlu, double *data, 454eb8e494SKris Buschelman int *indc, int *indr, int *rowperm, int *colperm, 464eb8e494SKris Buschelman int *collen, int *rowlen, int *colstart, int *rowstart, 474eb8e494SKris Buschelman int *inform); 48*2f71e704SKris Buschelman EXTERN_C_END 494eb8e494SKris Buschelman 504eb8e494SKris Buschelman typedef struct 514eb8e494SKris Buschelman { 524eb8e494SKris Buschelman double *data; 534eb8e494SKris Buschelman int *indc; 544eb8e494SKris Buschelman int *indr; 554eb8e494SKris Buschelman 564eb8e494SKris Buschelman int *ip; 574eb8e494SKris Buschelman int *iq; 584eb8e494SKris Buschelman int *lenc; 594eb8e494SKris Buschelman int *lenr; 604eb8e494SKris Buschelman int *locc; 614eb8e494SKris Buschelman int *locr; 624eb8e494SKris Buschelman int *iploc; 634eb8e494SKris Buschelman int *iqloc; 644eb8e494SKris Buschelman int *ipinv; 654eb8e494SKris Buschelman int *iqinv; 664eb8e494SKris Buschelman double *mnsw; 674eb8e494SKris Buschelman double *mnsv; 684eb8e494SKris Buschelman 694eb8e494SKris Buschelman double elbowroom; 704eb8e494SKris Buschelman double luroom; /* Extra space allocated when factor fails */ 714eb8e494SKris Buschelman double parmlu[30]; /* Input/output to LUSOL */ 724eb8e494SKris Buschelman 734eb8e494SKris Buschelman int n; /* Number of rows/columns in matrix */ 744eb8e494SKris Buschelman int nz; /* Number of nonzeros */ 754eb8e494SKris Buschelman int nnz; /* Number of nonzeros allocated for factors */ 764eb8e494SKris Buschelman int luparm[30]; /* Input/output to LUSOL */ 774eb8e494SKris Buschelman 78*2f71e704SKris Buschelman int (*MatLUFactorSymbolic)(Mat,IS,IS,MatFactorInfo*,Mat*); 794eb8e494SKris Buschelman int (*MatDestroy)(Mat); 804eb8e494SKris Buschelman PetscTruth CleanUpLUSOL; 814eb8e494SKris Buschelman 824eb8e494SKris Buschelman } Mat_SeqAIJ_LUSOL; 834eb8e494SKris Buschelman 844eb8e494SKris Buschelman /* LUSOL input/Output Parameters (Description uses C-style indexes 854eb8e494SKris Buschelman * 864eb8e494SKris Buschelman * Input parameters Typical value 874eb8e494SKris Buschelman * 884eb8e494SKris Buschelman * luparm(0) = nout File number for printed messages. 6 894eb8e494SKris Buschelman * luparm(1) = lprint Print level. 0 904eb8e494SKris Buschelman * < 0 suppresses output. 914eb8e494SKris Buschelman * = 0 gives error messages. 924eb8e494SKris Buschelman * = 1 gives debug output from some of the 934eb8e494SKris Buschelman * other routines in LUSOL. 944eb8e494SKris Buschelman * >= 2 gives the pivot row and column and the 954eb8e494SKris Buschelman * no. of rows and columns involved at 964eb8e494SKris Buschelman * each elimination step in lu1fac. 974eb8e494SKris Buschelman * luparm(2) = maxcol lu1fac: maximum number of columns 5 984eb8e494SKris Buschelman * searched allowed in a Markowitz-type 994eb8e494SKris Buschelman * search for the next pivot element. 1004eb8e494SKris Buschelman * For some of the factorization, the 1014eb8e494SKris Buschelman * number of rows searched is 1024eb8e494SKris Buschelman * maxrow = maxcol - 1. 1034eb8e494SKris Buschelman * 1044eb8e494SKris Buschelman * 1054eb8e494SKris Buschelman * Output parameters 1064eb8e494SKris Buschelman * 1074eb8e494SKris Buschelman * luparm(9) = inform Return code from last call to any LU routine. 1084eb8e494SKris Buschelman * luparm(10) = nsing No. of singularities marked in the 1094eb8e494SKris Buschelman * output array w(*). 1104eb8e494SKris Buschelman * luparm(11) = jsing Column index of last singularity. 1114eb8e494SKris Buschelman * luparm(12) = minlen Minimum recommended value for lena. 1124eb8e494SKris Buschelman * luparm(13) = maxlen ? 1134eb8e494SKris Buschelman * luparm(14) = nupdat No. of updates performed by the lu8 routines. 1144eb8e494SKris Buschelman * luparm(15) = nrank No. of nonempty rows of U. 1154eb8e494SKris Buschelman * luparm(16) = ndens1 No. of columns remaining when the density of 1164eb8e494SKris Buschelman * the matrix being factorized reached dens1. 1174eb8e494SKris Buschelman * luparm(17) = ndens2 No. of columns remaining when the density of 1184eb8e494SKris Buschelman * the matrix being factorized reached dens2. 1194eb8e494SKris Buschelman * luparm(18) = jumin The column index associated with dumin. 1204eb8e494SKris Buschelman * luparm(19) = numl0 No. of columns in initial L. 1214eb8e494SKris Buschelman * luparm(20) = lenl0 Size of initial L (no. of nonzeros). 1224eb8e494SKris Buschelman * luparm(21) = lenu0 Size of initial U. 1234eb8e494SKris Buschelman * luparm(22) = lenl Size of current L. 1244eb8e494SKris Buschelman * luparm(23) = lenu Size of current U. 1254eb8e494SKris Buschelman * luparm(24) = lrow Length of row file. 1264eb8e494SKris Buschelman * luparm(25) = ncp No. of compressions of LU data structures. 1274eb8e494SKris Buschelman * luparm(26) = mersum lu1fac: sum of Markowitz merit counts. 1284eb8e494SKris Buschelman * luparm(27) = nutri lu1fac: triangular rows in U. 1294eb8e494SKris Buschelman * luparm(28) = nltri lu1fac: triangular rows in L. 1304eb8e494SKris Buschelman * luparm(29) = 1314eb8e494SKris Buschelman * 1324eb8e494SKris Buschelman * 1334eb8e494SKris Buschelman * Input parameters Typical value 1344eb8e494SKris Buschelman * 1354eb8e494SKris Buschelman * parmlu(0) = elmax1 Max multiplier allowed in L 10.0 1364eb8e494SKris Buschelman * during factor. 1374eb8e494SKris Buschelman * parmlu(1) = elmax2 Max multiplier allowed in L 10.0 1384eb8e494SKris Buschelman * during updates. 1394eb8e494SKris Buschelman * parmlu(2) = small Absolute tolerance for eps**0.8 1404eb8e494SKris Buschelman * treating reals as zero. IBM double: 3.0d-13 1414eb8e494SKris Buschelman * parmlu(3) = utol1 Absolute tol for flagging eps**0.66667 1424eb8e494SKris Buschelman * small diagonals of U. IBM double: 3.7d-11 1434eb8e494SKris Buschelman * parmlu(4) = utol2 Relative tol for flagging eps**0.66667 1444eb8e494SKris Buschelman * small diagonals of U. IBM double: 3.7d-11 1454eb8e494SKris Buschelman * parmlu(5) = uspace Factor limiting waste space in U. 3.0 1464eb8e494SKris Buschelman * In lu1fac, the row or column lists 1474eb8e494SKris Buschelman * are compressed if their length 1484eb8e494SKris Buschelman * exceeds uspace times the length of 1494eb8e494SKris Buschelman * either file after the last compression. 1504eb8e494SKris Buschelman * parmlu(6) = dens1 The density at which the Markowitz 0.3 1514eb8e494SKris Buschelman * strategy should search maxcol columns 1524eb8e494SKris Buschelman * and no rows. 1534eb8e494SKris Buschelman * parmlu(7) = dens2 the density at which the Markowitz 0.6 1544eb8e494SKris Buschelman * strategy should search only 1 column 1554eb8e494SKris Buschelman * or (preferably) use a dense LU for 1564eb8e494SKris Buschelman * all the remaining rows and columns. 1574eb8e494SKris Buschelman * 1584eb8e494SKris Buschelman * 1594eb8e494SKris Buschelman * Output parameters 1604eb8e494SKris Buschelman * 1614eb8e494SKris Buschelman * parmlu(9) = amax Maximum element in A. 1624eb8e494SKris Buschelman * parmlu(10) = elmax Maximum multiplier in current L. 1634eb8e494SKris Buschelman * parmlu(11) = umax Maximum element in current U. 1644eb8e494SKris Buschelman * parmlu(12) = dumax Maximum diagonal in U. 1654eb8e494SKris Buschelman * parmlu(13) = dumin Minimum diagonal in U. 1664eb8e494SKris Buschelman * parmlu(14) = 1674eb8e494SKris Buschelman * parmlu(15) = 1684eb8e494SKris Buschelman * parmlu(16) = 1694eb8e494SKris Buschelman * parmlu(17) = 1704eb8e494SKris Buschelman * parmlu(18) = 1714eb8e494SKris Buschelman * parmlu(19) = resid lu6sol: residual after solve with U or U'. 1724eb8e494SKris Buschelman * ... 1734eb8e494SKris Buschelman * parmlu(29) = 1744eb8e494SKris Buschelman */ 1754eb8e494SKris Buschelman 1764eb8e494SKris Buschelman #define Factorization_Tolerance 1e-1 1774eb8e494SKris Buschelman #define Factorization_Pivot_Tolerance pow(2.2204460492503131E-16, 2.0 / 3.0) 1784eb8e494SKris Buschelman #define Factorization_Small_Tolerance 1e-15 /* pow(DBL_EPSILON, 0.8) */ 1794eb8e494SKris Buschelman 180*2f71e704SKris Buschelman EXTERN_C_BEGIN 181*2f71e704SKris Buschelman #undef __FUNCT__ 182*2f71e704SKris Buschelman #define __FUNCT__ "MatConvert_LUSOL_SeqAIJ" 183*2f71e704SKris Buschelman int MatConvert_LUSOL_SeqAIJ(Mat A,MatType type,Mat *newmat) { 184*2f71e704SKris Buschelman /* This routine is only called to convert an unfactored PETSc-LUSOL matrix */ 185*2f71e704SKris Buschelman /* to its base PETSc type, so we will ignore 'MatType type'. */ 186*2f71e704SKris Buschelman int ierr; 187*2f71e704SKris Buschelman Mat B=*newmat; 188*2f71e704SKris Buschelman Mat_SeqAIJ_LUSOL *lusol=(Mat_SeqAIJ_LUSOL *)A->spptr; 189*2f71e704SKris Buschelman 190*2f71e704SKris Buschelman PetscFunctionBegin; 191*2f71e704SKris Buschelman if (B != A) { 192*2f71e704SKris Buschelman /* This routine was inherited from SeqAIJ. */ 193*2f71e704SKris Buschelman ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr); 194*2f71e704SKris Buschelman } else { 195*2f71e704SKris Buschelman B->ops->lufactorsymbolic = lusol->MatLUFactorSymbolic; 196*2f71e704SKris Buschelman B->ops->destroy = lusol->MatDestroy; 197*2f71e704SKris Buschelman 198*2f71e704SKris Buschelman ierr = PetscFree(lusol);CHKERRQ(ierr); 199*2f71e704SKris Buschelman ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr); 200*2f71e704SKris Buschelman } 201*2f71e704SKris Buschelman *newmat = B; 202*2f71e704SKris Buschelman PetscFunctionReturn(0); 203*2f71e704SKris Buschelman } 204*2f71e704SKris Buschelman EXTERN_C_END 2054eb8e494SKris Buschelman 2064eb8e494SKris Buschelman #undef __FUNCT__ 2074eb8e494SKris Buschelman #define __FUNCT__ "MatDestroy_SeqAIJ_LUSOL" 208*2f71e704SKris Buschelman int MatDestroy_SeqAIJ_LUSOL(Mat A) { 209*2f71e704SKris Buschelman int ierr; 210*2f71e704SKris Buschelman Mat_SeqAIJ_LUSOL *lusol=(Mat_SeqAIJ_LUSOL *)A->spptr; 2114eb8e494SKris Buschelman 2124eb8e494SKris Buschelman PetscFunctionBegin; 2134eb8e494SKris Buschelman if (lusol->CleanUpLUSOL) { 2144eb8e494SKris Buschelman ierr = PetscFree(lusol->ip);CHKERRQ(ierr); 2154eb8e494SKris Buschelman ierr = PetscFree(lusol->iq);CHKERRQ(ierr); 2164eb8e494SKris Buschelman ierr = PetscFree(lusol->lenc);CHKERRQ(ierr); 2174eb8e494SKris Buschelman ierr = PetscFree(lusol->lenr);CHKERRQ(ierr); 2184eb8e494SKris Buschelman ierr = PetscFree(lusol->locc);CHKERRQ(ierr); 2194eb8e494SKris Buschelman ierr = PetscFree(lusol->locr);CHKERRQ(ierr); 2204eb8e494SKris Buschelman ierr = PetscFree(lusol->iploc);CHKERRQ(ierr); 2214eb8e494SKris Buschelman ierr = PetscFree(lusol->iqloc);CHKERRQ(ierr); 2224eb8e494SKris Buschelman ierr = PetscFree(lusol->ipinv);CHKERRQ(ierr); 2234eb8e494SKris Buschelman ierr = PetscFree(lusol->iqinv);CHKERRQ(ierr); 2244eb8e494SKris Buschelman ierr = PetscFree(lusol->mnsw);CHKERRQ(ierr); 2254eb8e494SKris Buschelman ierr = PetscFree(lusol->mnsv);CHKERRQ(ierr); 2264eb8e494SKris Buschelman 2274eb8e494SKris Buschelman ierr = PetscFree(lusol->indc);CHKERRQ(ierr); 2284eb8e494SKris Buschelman } 2294eb8e494SKris Buschelman 230*2f71e704SKris Buschelman ierr = MatConvert_LUSOL_SeqAIJ(A,MATSEQAIJ,&A); 231*2f71e704SKris Buschelman ierr = (*A->ops->destroy)(A);CHKERRQ(ierr); 2324eb8e494SKris Buschelman PetscFunctionReturn(0); 2334eb8e494SKris Buschelman } 2344eb8e494SKris Buschelman 2354eb8e494SKris Buschelman #undef __FUNCT__ 2364eb8e494SKris Buschelman #define __FUNCT__ "MatSolve_SeqAIJ_LUSOL" 2374eb8e494SKris Buschelman int MatSolve_SeqAIJ_LUSOL(Mat A,Vec b,Vec x) 2384eb8e494SKris Buschelman { 2394eb8e494SKris Buschelman Mat_SeqAIJ_LUSOL *lusol = (Mat_SeqAIJ_LUSOL *)A->spptr; 2404eb8e494SKris Buschelman double *bb, *xx; 2414eb8e494SKris Buschelman int mode = 5; 2424eb8e494SKris Buschelman int i, m, n, nnz, status, ierr; 2434eb8e494SKris Buschelman 2444eb8e494SKris Buschelman PetscFunctionBegin; 2454eb8e494SKris Buschelman ierr = VecGetArray(x, &xx);CHKERRQ(ierr); 2464eb8e494SKris Buschelman ierr = VecGetArray(b, &bb);CHKERRQ(ierr); 2474eb8e494SKris Buschelman 2484eb8e494SKris Buschelman m = n = lusol->n; 2494eb8e494SKris Buschelman nnz = lusol->nnz; 2504eb8e494SKris Buschelman 2514eb8e494SKris Buschelman for (i = 0; i < m; i++) 2524eb8e494SKris Buschelman { 2534eb8e494SKris Buschelman lusol->mnsv[i] = bb[i]; 2544eb8e494SKris Buschelman } 2554eb8e494SKris Buschelman 2564eb8e494SKris Buschelman LU6SOL(&mode, &m, &n, lusol->mnsv, xx, &nnz, 2574eb8e494SKris Buschelman lusol->luparm, lusol->parmlu, lusol->data, 2584eb8e494SKris Buschelman lusol->indc, lusol->indr, lusol->ip, lusol->iq, 2594eb8e494SKris Buschelman lusol->lenc, lusol->lenr, lusol->locc, lusol->locr, &status); 2604eb8e494SKris Buschelman 2614eb8e494SKris Buschelman if (status != 0) 2624eb8e494SKris Buschelman { 2634eb8e494SKris Buschelman SETERRQ(PETSC_ERR_ARG_SIZ,"solve failed"); 2644eb8e494SKris Buschelman } 2654eb8e494SKris Buschelman 2664eb8e494SKris Buschelman ierr = VecRestoreArray(x, &xx);CHKERRQ(ierr); 2674eb8e494SKris Buschelman ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr); 2684eb8e494SKris Buschelman PetscFunctionReturn(0); 2694eb8e494SKris Buschelman } 2704eb8e494SKris Buschelman 2714eb8e494SKris Buschelman #undef __FUNCT__ 2724eb8e494SKris Buschelman #define __FUNCT__ "MatLUFactorNumeric_SeqAIJ_LUSOL" 2734eb8e494SKris Buschelman int MatLUFactorNumeric_SeqAIJ_LUSOL(Mat A, Mat *F) 2744eb8e494SKris Buschelman { 2754eb8e494SKris Buschelman Mat_SeqAIJ *a; 2764eb8e494SKris Buschelman Mat_SeqAIJ_LUSOL *lusol = (Mat_SeqAIJ_LUSOL *)(*F)->spptr; 2774eb8e494SKris Buschelman int m, n, nz, nnz, status; 2784eb8e494SKris Buschelman int i, rs, re,ierr; 2794eb8e494SKris Buschelman int factorizations; 2804eb8e494SKris Buschelman 2814eb8e494SKris Buschelman PetscFunctionBegin; 2824eb8e494SKris Buschelman ierr = MatGetSize(A,&m,&n);CHKERRQ(ierr);CHKERRQ(ierr); 2834eb8e494SKris Buschelman a = (Mat_SeqAIJ *)A->data; 2844eb8e494SKris Buschelman 2854eb8e494SKris Buschelman if (m != lusol->n) { 2864eb8e494SKris Buschelman SETERRQ(PETSC_ERR_ARG_SIZ,"factorization struct inconsistent"); 2874eb8e494SKris Buschelman } 2884eb8e494SKris Buschelman 2894eb8e494SKris Buschelman factorizations = 0; 2904eb8e494SKris Buschelman do 2914eb8e494SKris Buschelman { 2924eb8e494SKris Buschelman /*******************************************************************/ 2934eb8e494SKris Buschelman /* Check the workspace allocation. */ 2944eb8e494SKris Buschelman /*******************************************************************/ 2954eb8e494SKris Buschelman 2964eb8e494SKris Buschelman nz = a->nz; 2974eb8e494SKris Buschelman nnz = PetscMax(lusol->nnz, (int)(lusol->elbowroom*nz)); 2984eb8e494SKris Buschelman nnz = PetscMax(nnz, 5*n); 2994eb8e494SKris Buschelman 3004eb8e494SKris Buschelman if (nnz < lusol->luparm[12]){ 3014eb8e494SKris Buschelman nnz = (int)(lusol->luroom * lusol->luparm[12]); 3024eb8e494SKris Buschelman } else if ((factorizations > 0) && (lusol->luroom < 6)){ 3034eb8e494SKris Buschelman lusol->luroom += 0.1; 3044eb8e494SKris Buschelman } 3054eb8e494SKris Buschelman 3064eb8e494SKris Buschelman nnz = PetscMax(nnz, (int)(lusol->luroom*(lusol->luparm[22] + lusol->luparm[23]))); 3074eb8e494SKris Buschelman 3084eb8e494SKris Buschelman if (nnz > lusol->nnz){ 3094eb8e494SKris Buschelman ierr = PetscFree(lusol->indc);CHKERRQ(ierr); 3104eb8e494SKris Buschelman ierr = PetscMalloc((sizeof(double)+2*sizeof(int))*nnz,&lusol->indc);CHKERRQ(ierr); 3114eb8e494SKris Buschelman lusol->indr = lusol->indc + nnz; 3124eb8e494SKris Buschelman lusol->data = (double *)(lusol->indr + nnz); 3134eb8e494SKris Buschelman lusol->nnz = nnz; 3144eb8e494SKris Buschelman } 3154eb8e494SKris Buschelman 3164eb8e494SKris Buschelman /*******************************************************************/ 3174eb8e494SKris Buschelman /* Fill in the data for the problem. (1-based Fortran style) */ 3184eb8e494SKris Buschelman /*******************************************************************/ 3194eb8e494SKris Buschelman 3204eb8e494SKris Buschelman nz = 0; 3214eb8e494SKris Buschelman for (i = 0; i < n; i++) 3224eb8e494SKris Buschelman { 3234eb8e494SKris Buschelman rs = a->i[i]; 3244eb8e494SKris Buschelman re = a->i[i+1]; 3254eb8e494SKris Buschelman 3264eb8e494SKris Buschelman while (rs < re) 3274eb8e494SKris Buschelman { 3284eb8e494SKris Buschelman if (a->a[rs] != 0.0) 3294eb8e494SKris Buschelman { 3304eb8e494SKris Buschelman lusol->indc[nz] = i + 1; 3314eb8e494SKris Buschelman lusol->indr[nz] = a->j[rs] + 1; 3324eb8e494SKris Buschelman lusol->data[nz] = a->a[rs]; 3334eb8e494SKris Buschelman nz++; 3344eb8e494SKris Buschelman } 3354eb8e494SKris Buschelman rs++; 3364eb8e494SKris Buschelman } 3374eb8e494SKris Buschelman } 3384eb8e494SKris Buschelman 3394eb8e494SKris Buschelman /*******************************************************************/ 3404eb8e494SKris Buschelman /* Do the factorization. */ 3414eb8e494SKris Buschelman /*******************************************************************/ 3424eb8e494SKris Buschelman 3434eb8e494SKris Buschelman LU1FAC(&m, &n, &nz, &nnz, 3444eb8e494SKris Buschelman lusol->luparm, lusol->parmlu, lusol->data, 3454eb8e494SKris Buschelman lusol->indc, lusol->indr, lusol->ip, lusol->iq, 3464eb8e494SKris Buschelman lusol->lenc, lusol->lenr, lusol->locc, lusol->locr, 3474eb8e494SKris Buschelman lusol->iploc, lusol->iqloc, lusol->ipinv, 3484eb8e494SKris Buschelman lusol->iqinv, lusol->mnsw, &status); 3494eb8e494SKris Buschelman 3504eb8e494SKris Buschelman switch(status) 3514eb8e494SKris Buschelman { 3524eb8e494SKris Buschelman case 0: /* factored */ 3534eb8e494SKris Buschelman break; 3544eb8e494SKris Buschelman 3554eb8e494SKris Buschelman case 7: /* insufficient memory */ 3564eb8e494SKris Buschelman break; 3574eb8e494SKris Buschelman 3584eb8e494SKris Buschelman case 1: 3594eb8e494SKris Buschelman case -1: /* singular */ 3604eb8e494SKris Buschelman SETERRQ(1,"Singular matrix"); 3614eb8e494SKris Buschelman 3624eb8e494SKris Buschelman case 3: 3634eb8e494SKris Buschelman case 4: /* error conditions */ 3644eb8e494SKris Buschelman SETERRQ(1,"matrix error"); 3654eb8e494SKris Buschelman 3664eb8e494SKris Buschelman default: /* unknown condition */ 3674eb8e494SKris Buschelman SETERRQ(1,"matrix unknown return code"); 3684eb8e494SKris Buschelman } 3694eb8e494SKris Buschelman 3704eb8e494SKris Buschelman factorizations++; 3714eb8e494SKris Buschelman } while (status == 7); 372a8883a68SKris Buschelman (*F)->assembled = PETSC_TRUE; 3734eb8e494SKris Buschelman PetscFunctionReturn(0); 3744eb8e494SKris Buschelman } 3754eb8e494SKris Buschelman 3764eb8e494SKris Buschelman #undef __FUNCT__ 3774eb8e494SKris Buschelman #define __FUNCT__ "MatLUFactorSymbolic_SeqAIJ_LUSOL" 3784eb8e494SKris Buschelman int MatLUFactorSymbolic_SeqAIJ_LUSOL(Mat A, IS r, IS c,MatFactorInfo *info, Mat *F) 3794eb8e494SKris Buschelman { 3804eb8e494SKris Buschelman /************************************************************************/ 3814eb8e494SKris Buschelman /* Input */ 3824eb8e494SKris Buschelman /* A - matrix to factor */ 3834eb8e494SKris Buschelman /* r - row permutation (ignored) */ 3844eb8e494SKris Buschelman /* c - column permutation (ignored) */ 3854eb8e494SKris Buschelman /* */ 3864eb8e494SKris Buschelman /* Output */ 3874eb8e494SKris Buschelman /* F - matrix storing the factorization; */ 3884eb8e494SKris Buschelman /************************************************************************/ 3894eb8e494SKris Buschelman Mat B; 3904eb8e494SKris Buschelman Mat_SeqAIJ_LUSOL *lusol; 3914eb8e494SKris Buschelman int ierr,i, m, n, nz, nnz; 3924eb8e494SKris Buschelman 3934eb8e494SKris Buschelman PetscFunctionBegin; 3944eb8e494SKris Buschelman 3954eb8e494SKris Buschelman /************************************************************************/ 3964eb8e494SKris Buschelman /* Check the arguments. */ 3974eb8e494SKris Buschelman /************************************************************************/ 3984eb8e494SKris Buschelman 3994eb8e494SKris Buschelman ierr = MatGetSize(A, &m, &n);CHKERRQ(ierr); 4004eb8e494SKris Buschelman nz = ((Mat_SeqAIJ *)A->data)->nz; 4014eb8e494SKris Buschelman 4024eb8e494SKris Buschelman /************************************************************************/ 4034eb8e494SKris Buschelman /* Create the factorization. */ 4044eb8e494SKris Buschelman /************************************************************************/ 4054eb8e494SKris Buschelman 4064eb8e494SKris Buschelman ierr = MatCreate(A->comm,PETSC_DECIDE,PETSC_DECIDE,m,n,&B);CHKERRQ(ierr); 4074eb8e494SKris Buschelman ierr = MatSetType(B,MATLUSOL);CHKERRQ(ierr); 4084eb8e494SKris Buschelman ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr); 4094eb8e494SKris Buschelman 4104eb8e494SKris Buschelman B->ops->lufactornumeric = MatLUFactorNumeric_SeqAIJ_LUSOL; 4114eb8e494SKris Buschelman B->ops->solve = MatSolve_SeqAIJ_LUSOL; 4124eb8e494SKris Buschelman B->factor = FACTOR_LU; 4134eb8e494SKris Buschelman lusol = (Mat_SeqAIJ_LUSOL*)(B->spptr); 4144eb8e494SKris Buschelman 4154eb8e494SKris Buschelman /************************************************************************/ 4164eb8e494SKris Buschelman /* Initialize parameters */ 4174eb8e494SKris Buschelman /************************************************************************/ 4184eb8e494SKris Buschelman 4194eb8e494SKris Buschelman for (i = 0; i < 30; i++) 4204eb8e494SKris Buschelman { 4214eb8e494SKris Buschelman lusol->luparm[i] = 0; 4224eb8e494SKris Buschelman lusol->parmlu[i] = 0; 4234eb8e494SKris Buschelman } 4244eb8e494SKris Buschelman 4254eb8e494SKris Buschelman lusol->luparm[1] = -1; 4264eb8e494SKris Buschelman lusol->luparm[2] = 5; 4274eb8e494SKris Buschelman lusol->luparm[7] = 1; 4284eb8e494SKris Buschelman 4294eb8e494SKris Buschelman lusol->parmlu[0] = 1 / Factorization_Tolerance; 4304eb8e494SKris Buschelman lusol->parmlu[1] = 1 / Factorization_Tolerance; 4314eb8e494SKris Buschelman lusol->parmlu[2] = Factorization_Small_Tolerance; 4324eb8e494SKris Buschelman lusol->parmlu[3] = Factorization_Pivot_Tolerance; 4334eb8e494SKris Buschelman lusol->parmlu[4] = Factorization_Pivot_Tolerance; 4344eb8e494SKris Buschelman lusol->parmlu[5] = 3.0; 4354eb8e494SKris Buschelman lusol->parmlu[6] = 0.3; 4364eb8e494SKris Buschelman lusol->parmlu[7] = 0.6; 4374eb8e494SKris Buschelman 4384eb8e494SKris Buschelman /************************************************************************/ 4394eb8e494SKris Buschelman /* Allocate the workspace needed by LUSOL. */ 4404eb8e494SKris Buschelman /************************************************************************/ 4414eb8e494SKris Buschelman 4424eb8e494SKris Buschelman lusol->elbowroom = PetscMax(lusol->elbowroom, info->fill); 4434eb8e494SKris Buschelman nnz = PetscMax((int)(lusol->elbowroom*nz), 5*n); 4444eb8e494SKris Buschelman 4454eb8e494SKris Buschelman lusol->n = n; 4464eb8e494SKris Buschelman lusol->nz = nz; 4474eb8e494SKris Buschelman lusol->nnz = nnz; 4484eb8e494SKris Buschelman lusol->luroom = 1.75; 4494eb8e494SKris Buschelman 4504eb8e494SKris Buschelman ierr = PetscMalloc(sizeof(int)*n,&lusol->ip); 4514eb8e494SKris Buschelman ierr = PetscMalloc(sizeof(int)*n,&lusol->iq); 4524eb8e494SKris Buschelman ierr = PetscMalloc(sizeof(int)*n,&lusol->lenc); 4534eb8e494SKris Buschelman ierr = PetscMalloc(sizeof(int)*n,&lusol->lenr); 4544eb8e494SKris Buschelman ierr = PetscMalloc(sizeof(int)*n,&lusol->locc); 4554eb8e494SKris Buschelman ierr = PetscMalloc(sizeof(int)*n,&lusol->locr); 4564eb8e494SKris Buschelman ierr = PetscMalloc(sizeof(int)*n,&lusol->iploc); 4574eb8e494SKris Buschelman ierr = PetscMalloc(sizeof(int)*n,&lusol->iqloc); 4584eb8e494SKris Buschelman ierr = PetscMalloc(sizeof(int)*n,&lusol->ipinv); 4594eb8e494SKris Buschelman ierr = PetscMalloc(sizeof(int)*n,&lusol->iqinv); 4604eb8e494SKris Buschelman ierr = PetscMalloc(sizeof(double)*n,&lusol->mnsw); 4614eb8e494SKris Buschelman ierr = PetscMalloc(sizeof(double)*n,&lusol->mnsv); 4624eb8e494SKris Buschelman 4634eb8e494SKris Buschelman ierr = PetscMalloc((sizeof(double)+2*sizeof(int))*nnz,&lusol->indc); 4644eb8e494SKris Buschelman lusol->indr = lusol->indc + nnz; 4654eb8e494SKris Buschelman lusol->data = (double *)(lusol->indr + nnz); 4664eb8e494SKris Buschelman lusol->CleanUpLUSOL = PETSC_TRUE; 4674eb8e494SKris Buschelman *F = B; 4684eb8e494SKris Buschelman PetscFunctionReturn(0); 4694eb8e494SKris Buschelman } 4704eb8e494SKris Buschelman 471*2f71e704SKris Buschelman EXTERN_C_BEGIN 4724eb8e494SKris Buschelman #undef __FUNCT__ 473*2f71e704SKris Buschelman #define __FUNCT__ "MatConvert_SeqAIJ_LUSOL" 474*2f71e704SKris Buschelman int MatConvert_SeqAIJ_LUSOL(Mat A,MatType type,Mat *newmat) { 4754eb8e494SKris Buschelman int ierr, m, n; 476*2f71e704SKris Buschelman Mat_SeqAIJ_LUSOL *lusol; 477*2f71e704SKris Buschelman Mat B=*newmat; 4784eb8e494SKris Buschelman 4794eb8e494SKris Buschelman PetscFunctionBegin; 4804eb8e494SKris Buschelman ierr = MatGetSize(A, &m, &n);CHKERRQ(ierr); 4814eb8e494SKris Buschelman if (m != n) { 4824eb8e494SKris Buschelman SETERRQ(PETSC_ERR_ARG_SIZ,"matrix must be square"); 4834eb8e494SKris Buschelman } 484*2f71e704SKris Buschelman if (B != A) { 485*2f71e704SKris Buschelman ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr); 486*2f71e704SKris Buschelman } 4874eb8e494SKris Buschelman 488*2f71e704SKris Buschelman ierr = PetscNew(Mat_SeqAIJ_LUSOL,&lusol);CHKERRQ(ierr); 489*2f71e704SKris Buschelman lusol->MatLUFactorSymbolic = A->ops->lufactorsymbolic; 490*2f71e704SKris Buschelman lusol->MatDestroy = A->ops->destroy; 491*2f71e704SKris Buschelman lusol->CleanUpLUSOL = PETSC_FALSE; 492*2f71e704SKris Buschelman 493*2f71e704SKris Buschelman B->spptr = (void *)lusol; 494*2f71e704SKris Buschelman B->ops->lufactorsymbolic = MatLUFactorSymbolic_SeqAIJ_LUSOL; 495*2f71e704SKris Buschelman B->ops->destroy = MatDestroy_SeqAIJ_LUSOL; 496*2f71e704SKris Buschelman 4974eb8e494SKris Buschelman PetscLogInfo(0,"Using LUSOL for SeqAIJ LU factorization and solves."); 498*2f71e704SKris Buschelman ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_lusol_C", 499*2f71e704SKris Buschelman "MatConvert_SeqAIJ_LUSOL",MatConvert_SeqAIJ_LUSOL);CHKERRQ(ierr); 500*2f71e704SKris Buschelman ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_lusol_seqaij_C", 501*2f71e704SKris Buschelman "MatConvert_LUSOL_SeqAIJ",MatConvert_LUSOL_SeqAIJ);CHKERRQ(ierr); 502*2f71e704SKris Buschelman ierr = PetscObjectChangeTypeName((PetscObject)B,type);CHKERRQ(ierr); 503*2f71e704SKris Buschelman *newmat = B; 5044eb8e494SKris Buschelman PetscFunctionReturn(0); 5054eb8e494SKris Buschelman } 506*2f71e704SKris Buschelman EXTERN_C_END 507*2f71e704SKris Buschelman 508*2f71e704SKris Buschelman /*MC 509*2f71e704SKris Buschelman MATLUSOL - a matrix type providing direct solvers (LU) for sequential matrices 510*2f71e704SKris Buschelman via the external package LUSOL. 511*2f71e704SKris Buschelman 512*2f71e704SKris Buschelman If LUSOL is installed (see the manual for 513*2f71e704SKris Buschelman instructions on how to declare the existence of external packages), 514*2f71e704SKris Buschelman a matrix type can be constructed which invokes LUSOL solvers. 515*2f71e704SKris Buschelman After calling MatCreate(...,A), simply call MatSetType(A,MATLUSOL). 516*2f71e704SKris Buschelman This matrix type is only supported for double precision real. 517*2f71e704SKris Buschelman 518*2f71e704SKris Buschelman This matrix inherits from MATSEQAIJ. As a result, MatSeqAIJSetPreallocation is 519*2f71e704SKris Buschelman supported for this matrix type. 520*2f71e704SKris Buschelman 521*2f71e704SKris Buschelman Options Database Keys: 522*2f71e704SKris Buschelman . -mat_type lusol - sets the matrix type to lusol during a call to MatSetFromOptions() 523*2f71e704SKris Buschelman 524*2f71e704SKris Buschelman Level: beginner 525*2f71e704SKris Buschelman 526*2f71e704SKris Buschelman .seealso: PCLU 527*2f71e704SKris Buschelman M*/ 5284eb8e494SKris Buschelman 5294eb8e494SKris Buschelman EXTERN_C_BEGIN 5304eb8e494SKris Buschelman #undef __FUNCT__ 5314eb8e494SKris Buschelman #define __FUNCT__ "MatCreate_SeqAIJ_LUSOL" 5324eb8e494SKris Buschelman int MatCreate_SeqAIJ_LUSOL(Mat A) 5334eb8e494SKris Buschelman { 5344eb8e494SKris Buschelman int ierr; 5354eb8e494SKris Buschelman 5364eb8e494SKris Buschelman PetscFunctionBegin; 5374eb8e494SKris Buschelman ierr = MatSetType(A,MATSEQAIJ);CHKERRQ(ierr); 538*2f71e704SKris Buschelman ierr = MatConvert_SeqAIJ_LUSOL(A,MATLUSOL,&A);CHKERRQ(ierr); 5394eb8e494SKris Buschelman PetscFunctionReturn(0); 5404eb8e494SKris Buschelman } 5414eb8e494SKris Buschelman EXTERN_C_END 542