xref: /petsc/src/mat/impls/aij/seq/lusol/lusol.c (revision 4dfa11a44d5adf2389f1d3acbc8f3c1116dc6c3a)
1be1d678aSKris Buschelman 
24eb8e494SKris Buschelman /*
34eb8e494SKris Buschelman         Provides an interface to the LUSOL package of ....
44eb8e494SKris Buschelman 
54eb8e494SKris Buschelman */
6c6db04a5SJed Brown #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 /*
234eb8e494SKris Buschelman     Dummy symbols that the MINOS files mi25bfac.f and mi15blas.f may require
244eb8e494SKris Buschelman */
259371c9d4SSatish Balay PETSC_EXTERN void M1PAGE() {
264eb8e494SKris Buschelman   ;
274eb8e494SKris Buschelman }
289371c9d4SSatish Balay PETSC_EXTERN void M5SETX() {
294eb8e494SKris Buschelman   ;
304eb8e494SKris Buschelman }
314eb8e494SKris Buschelman 
329371c9d4SSatish Balay PETSC_EXTERN void M6RDEL() {
334eb8e494SKris Buschelman   ;
344eb8e494SKris Buschelman }
354eb8e494SKris Buschelman 
369371c9d4SSatish Balay PETSC_EXTERN void LU1FAC(int *m, int *n, int *nnz, int *size, int *luparm, double *parmlu, double *data, int *indc, int *indr, int *rowperm, int *colperm, int *collen, int *rowlen, int *colstart, int *rowstart, int *rploc, int *cploc, int *rpinv, int *cpinv, double *w, int *inform);
374eb8e494SKris Buschelman 
389371c9d4SSatish Balay PETSC_EXTERN void LU6SOL(int *mode, int *m, int *n, double *rhs, double *x, int *size, int *luparm, double *parmlu, double *data, int *indc, int *indr, int *rowperm, int *colperm, int *collen, int *rowlen, int *colstart, int *rowstart, int *inform);
394eb8e494SKris Buschelman 
4009573ac7SBarry Smith extern PetscErrorCode MatDuplicate_LUSOL(Mat, MatDuplicateOption, Mat *);
41f0c56d0fSKris Buschelman 
42f0c56d0fSKris Buschelman typedef struct {
434eb8e494SKris Buschelman   double *data;
444eb8e494SKris Buschelman   int    *indc;
454eb8e494SKris Buschelman   int    *indr;
464eb8e494SKris Buschelman 
474eb8e494SKris Buschelman   int    *ip;
484eb8e494SKris Buschelman   int    *iq;
494eb8e494SKris Buschelman   int    *lenc;
504eb8e494SKris Buschelman   int    *lenr;
514eb8e494SKris Buschelman   int    *locc;
524eb8e494SKris Buschelman   int    *locr;
534eb8e494SKris Buschelman   int    *iploc;
544eb8e494SKris Buschelman   int    *iqloc;
554eb8e494SKris Buschelman   int    *ipinv;
564eb8e494SKris Buschelman   int    *iqinv;
574eb8e494SKris Buschelman   double *mnsw;
584eb8e494SKris Buschelman   double *mnsv;
594eb8e494SKris Buschelman 
604eb8e494SKris Buschelman   double elbowroom;
614eb8e494SKris Buschelman   double luroom;     /* Extra space allocated when factor fails   */
624eb8e494SKris Buschelman   double parmlu[30]; /* Input/output to LUSOL                     */
634eb8e494SKris Buschelman 
644eb8e494SKris Buschelman   int n;          /* Number of rows/columns in matrix          */
654eb8e494SKris Buschelman   int nz;         /* Number of nonzeros                        */
664eb8e494SKris Buschelman   int nnz;        /* Number of nonzeros allocated for factors  */
674eb8e494SKris Buschelman   int luparm[30]; /* Input/output to LUSOL                     */
684eb8e494SKris Buschelman 
69ace3abfcSBarry Smith   PetscBool CleanUpLUSOL;
704eb8e494SKris Buschelman 
71f0c56d0fSKris Buschelman } Mat_LUSOL;
724eb8e494SKris Buschelman 
734eb8e494SKris Buschelman /*  LUSOL input/Output Parameters (Description uses C-style indexes
744eb8e494SKris Buschelman  *
754eb8e494SKris Buschelman  *  Input parameters                                        Typical value
764eb8e494SKris Buschelman  *
774eb8e494SKris Buschelman  *  luparm(0) = nout     File number for printed messages.         6
784eb8e494SKris Buschelman  *  luparm(1) = lprint   Print level.                              0
794eb8e494SKris Buschelman  *                    < 0 suppresses output.
804eb8e494SKris Buschelman  *                    = 0 gives error messages.
814eb8e494SKris Buschelman  *                    = 1 gives debug output from some of the
824eb8e494SKris Buschelman  *                        other routines in LUSOL.
834eb8e494SKris Buschelman  *                   >= 2 gives the pivot row and column and the
844eb8e494SKris Buschelman  *                        no. of rows and columns involved at
854eb8e494SKris Buschelman  *                        each elimination step in lu1fac.
864eb8e494SKris Buschelman  *  luparm(2) = maxcol   lu1fac: maximum number of columns         5
874eb8e494SKris Buschelman  *                        searched allowed in a Markowitz-type
884eb8e494SKris Buschelman  *                        search for the next pivot element.
894eb8e494SKris Buschelman  *                        For some of the factorization, the
904eb8e494SKris Buschelman  *                        number of rows searched is
914eb8e494SKris Buschelman  *                        maxrow = maxcol - 1.
924eb8e494SKris Buschelman  *
934eb8e494SKris Buschelman  *
947a7aea1fSJed Brown  *  Output parameters:
954eb8e494SKris Buschelman  *
964eb8e494SKris Buschelman  *  luparm(9) = inform   Return code from last call to any LU routine.
974eb8e494SKris Buschelman  *  luparm(10) = nsing    No. of singularities marked in the
984eb8e494SKris Buschelman  *                        output array w(*).
994eb8e494SKris Buschelman  *  luparm(11) = jsing    Column index of last singularity.
1004eb8e494SKris Buschelman  *  luparm(12) = minlen   Minimum recommended value for  lena.
1014eb8e494SKris Buschelman  *  luparm(13) = maxlen   ?
1024eb8e494SKris Buschelman  *  luparm(14) = nupdat   No. of updates performed by the lu8 routines.
1034eb8e494SKris Buschelman  *  luparm(15) = nrank    No. of nonempty rows of U.
1044eb8e494SKris Buschelman  *  luparm(16) = ndens1   No. of columns remaining when the density of
1054eb8e494SKris Buschelman  *                        the matrix being factorized reached dens1.
1064eb8e494SKris Buschelman  *  luparm(17) = ndens2   No. of columns remaining when the density of
1074eb8e494SKris Buschelman  *                        the matrix being factorized reached dens2.
1084eb8e494SKris Buschelman  *  luparm(18) = jumin    The column index associated with dumin.
1094eb8e494SKris Buschelman  *  luparm(19) = numl0    No. of columns in initial  L.
1104eb8e494SKris Buschelman  *  luparm(20) = lenl0    Size of initial  L  (no. of nonzeros).
1114eb8e494SKris Buschelman  *  luparm(21) = lenu0    Size of initial  U.
1124eb8e494SKris Buschelman  *  luparm(22) = lenl     Size of current  L.
1134eb8e494SKris Buschelman  *  luparm(23) = lenu     Size of current  U.
1144eb8e494SKris Buschelman  *  luparm(24) = lrow     Length of row file.
1154eb8e494SKris Buschelman  *  luparm(25) = ncp      No. of compressions of LU data structures.
1164eb8e494SKris Buschelman  *  luparm(26) = mersum   lu1fac: sum of Markowitz merit counts.
1174eb8e494SKris Buschelman  *  luparm(27) = nutri    lu1fac: triangular rows in U.
1184eb8e494SKris Buschelman  *  luparm(28) = nltri    lu1fac: triangular rows in L.
1194eb8e494SKris Buschelman  *  luparm(29) =
1204eb8e494SKris Buschelman  *
1214eb8e494SKris Buschelman  *
1224eb8e494SKris Buschelman  *  Input parameters                                        Typical value
1234eb8e494SKris Buschelman  *
1244eb8e494SKris Buschelman  *  parmlu(0) = elmax1   Max multiplier allowed in  L           10.0
1254eb8e494SKris Buschelman  *                        during factor.
1264eb8e494SKris Buschelman  *  parmlu(1) = elmax2   Max multiplier allowed in  L           10.0
1274eb8e494SKris Buschelman  *                        during updates.
1284eb8e494SKris Buschelman  *  parmlu(2) = small    Absolute tolerance for             eps**0.8
1294eb8e494SKris Buschelman  *                        treating reals as zero.     IBM double: 3.0d-13
1304eb8e494SKris Buschelman  *  parmlu(3) = utol1    Absolute tol for flagging          eps**0.66667
1314eb8e494SKris Buschelman  *                        small diagonals of U.       IBM double: 3.7d-11
1324eb8e494SKris Buschelman  *  parmlu(4) = utol2    Relative tol for flagging          eps**0.66667
1334eb8e494SKris Buschelman  *                        small diagonals of U.       IBM double: 3.7d-11
1344eb8e494SKris Buschelman  *  parmlu(5) = uspace   Factor limiting waste space in  U.      3.0
1354eb8e494SKris Buschelman  *                        In lu1fac, the row or column lists
1364eb8e494SKris Buschelman  *                        are compressed if their length
1374eb8e494SKris Buschelman  *                        exceeds uspace times the length of
1384eb8e494SKris Buschelman  *                        either file after the last compression.
1394eb8e494SKris Buschelman  *  parmlu(6) = dens1    The density at which the Markowitz      0.3
1404eb8e494SKris Buschelman  *                        strategy should search maxcol columns
1414eb8e494SKris Buschelman  *                        and no rows.
1424eb8e494SKris Buschelman  *  parmlu(7) = dens2    the density at which the Markowitz      0.6
1434eb8e494SKris Buschelman  *                        strategy should search only 1 column
1444eb8e494SKris Buschelman  *                        or (preferably) use a dense LU for
1454eb8e494SKris Buschelman  *                        all the remaining rows and columns.
1464eb8e494SKris Buschelman  *
1474eb8e494SKris Buschelman  *
1487a7aea1fSJed Brown  *  Output parameters:
1494eb8e494SKris Buschelman  *
1504eb8e494SKris Buschelman  *  parmlu(9) = amax     Maximum element in  A.
1514eb8e494SKris Buschelman  *  parmlu(10) = elmax    Maximum multiplier in current  L.
1524eb8e494SKris Buschelman  *  parmlu(11) = umax     Maximum element in current  U.
1534eb8e494SKris Buschelman  *  parmlu(12) = dumax    Maximum diagonal in  U.
1544eb8e494SKris Buschelman  *  parmlu(13) = dumin    Minimum diagonal in  U.
1554eb8e494SKris Buschelman  *  parmlu(14) =
1564eb8e494SKris Buschelman  *  parmlu(15) =
1574eb8e494SKris Buschelman  *  parmlu(16) =
1584eb8e494SKris Buschelman  *  parmlu(17) =
1594eb8e494SKris Buschelman  *  parmlu(18) =
1604eb8e494SKris Buschelman  *  parmlu(19) = resid    lu6sol: residual after solve with U or U'.
1614eb8e494SKris Buschelman  *  ...
1624eb8e494SKris Buschelman  *  parmlu(29) =
1634eb8e494SKris Buschelman  */
1644eb8e494SKris Buschelman 
1654eb8e494SKris Buschelman #define Factorization_Tolerance       1e-1
1664eb8e494SKris Buschelman #define Factorization_Pivot_Tolerance pow(2.2204460492503131E-16, 2.0 / 3.0)
1674eb8e494SKris Buschelman #define Factorization_Small_Tolerance 1e-15 /* pow(DBL_EPSILON, 0.8) */
1684eb8e494SKris Buschelman 
1699371c9d4SSatish Balay PetscErrorCode MatDestroy_LUSOL(Mat A) {
170f0c56d0fSKris Buschelman   Mat_LUSOL *lusol = (Mat_LUSOL *)A->spptr;
1714eb8e494SKris Buschelman 
1724eb8e494SKris Buschelman   PetscFunctionBegin;
173bf0cc555SLisandro Dalcin   if (lusol && lusol->CleanUpLUSOL) {
1749566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->ip));
1759566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->iq));
1769566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->lenc));
1779566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->lenr));
1789566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->locc));
1799566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->locr));
1809566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->iploc));
1819566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->iqloc));
1829566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->ipinv));
1839566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->iqinv));
1849566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->mnsw));
1859566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->mnsv));
1869566063dSJacob Faibussowitsch     PetscCall(PetscFree3(lusol->data, lusol->indc, lusol->indr));
1874eb8e494SKris Buschelman   }
1889566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->spptr));
1899566063dSJacob Faibussowitsch   PetscCall(MatDestroy_SeqAIJ(A));
1904eb8e494SKris Buschelman   PetscFunctionReturn(0);
1914eb8e494SKris Buschelman }
1924eb8e494SKris Buschelman 
1939371c9d4SSatish Balay PetscErrorCode MatSolve_LUSOL(Mat A, Vec b, Vec x) {
194f0c56d0fSKris Buschelman   Mat_LUSOL    *lusol = (Mat_LUSOL *)A->spptr;
195d9ca1df4SBarry Smith   double       *xx;
196d9ca1df4SBarry Smith   const double *bb;
1974eb8e494SKris Buschelman   int           mode = 5;
1986849ba73SBarry Smith   int           i, m, n, nnz, status;
1994eb8e494SKris Buschelman 
2004eb8e494SKris Buschelman   PetscFunctionBegin;
2019566063dSJacob Faibussowitsch   PetscCall(VecGetArray(x, &xx));
2029566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(b, &bb));
2034eb8e494SKris Buschelman 
2044eb8e494SKris Buschelman   m = n = lusol->n;
2054eb8e494SKris Buschelman   nnz   = lusol->nnz;
2064eb8e494SKris Buschelman 
2072205254eSKarl Rupp   for (i = 0; i < m; i++) lusol->mnsv[i] = bb[i];
2084eb8e494SKris Buschelman 
2099371c9d4SSatish Balay   LU6SOL(&mode, &m, &n, lusol->mnsv, xx, &nnz, lusol->luparm, lusol->parmlu, lusol->data, lusol->indc, lusol->indr, lusol->ip, lusol->iq, lusol->lenc, lusol->lenr, lusol->locc, lusol->locr, &status);
2104eb8e494SKris Buschelman 
21128b400f6SJacob Faibussowitsch   PetscCheck(!status, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "solve failed, error code %d", status);
2124eb8e494SKris Buschelman 
2139566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(x, &xx));
2149566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(b, &bb));
2154eb8e494SKris Buschelman   PetscFunctionReturn(0);
2164eb8e494SKris Buschelman }
2174eb8e494SKris Buschelman 
2189371c9d4SSatish Balay PetscErrorCode MatLUFactorNumeric_LUSOL(Mat F, Mat A, const MatFactorInfo *info) {
2194eb8e494SKris Buschelman   Mat_SeqAIJ *a;
220719d5645SBarry Smith   Mat_LUSOL  *lusol = (Mat_LUSOL *)F->spptr;
2214eb8e494SKris Buschelman   int         m, n, nz, nnz, status;
2226849ba73SBarry Smith   int         i, rs, re;
2234eb8e494SKris Buschelman   int         factorizations;
2244eb8e494SKris Buschelman 
2254eb8e494SKris Buschelman   PetscFunctionBegin;
2269566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &m, &n));
2274eb8e494SKris Buschelman   a = (Mat_SeqAIJ *)A->data;
2284eb8e494SKris Buschelman 
22908401ef6SPierre Jolivet   PetscCheck(m == lusol->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "factorization struct inconsistent");
2304eb8e494SKris Buschelman 
2314eb8e494SKris Buschelman   factorizations = 0;
2322205254eSKarl Rupp   do {
2334eb8e494SKris Buschelman     /*******************************************************************/
2344eb8e494SKris Buschelman     /* Check the workspace allocation.                                 */
2354eb8e494SKris Buschelman     /*******************************************************************/
2364eb8e494SKris Buschelman 
2374eb8e494SKris Buschelman     nz  = a->nz;
2384eb8e494SKris Buschelman     nnz = PetscMax(lusol->nnz, (int)(lusol->elbowroom * nz));
2394eb8e494SKris Buschelman     nnz = PetscMax(nnz, 5 * n);
2404eb8e494SKris Buschelman 
2414eb8e494SKris Buschelman     if (nnz < lusol->luparm[12]) {
2424eb8e494SKris Buschelman       nnz = (int)(lusol->luroom * lusol->luparm[12]);
2434eb8e494SKris Buschelman     } else if ((factorizations > 0) && (lusol->luroom < 6)) {
2444eb8e494SKris Buschelman       lusol->luroom += 0.1;
2454eb8e494SKris Buschelman     }
2464eb8e494SKris Buschelman 
2474eb8e494SKris Buschelman     nnz = PetscMax(nnz, (int)(lusol->luroom * (lusol->luparm[22] + lusol->luparm[23])));
2484eb8e494SKris Buschelman 
2494eb8e494SKris Buschelman     if (nnz > lusol->nnz) {
2509566063dSJacob Faibussowitsch       PetscCall(PetscFree3(lusol->data, lusol->indc, lusol->indr));
2519566063dSJacob Faibussowitsch       PetscCall(PetscMalloc3(nnz, &lusol->data, nnz, &lusol->indc, nnz, &lusol->indr));
2524eb8e494SKris Buschelman       lusol->nnz = nnz;
2534eb8e494SKris Buschelman     }
2544eb8e494SKris Buschelman 
2554eb8e494SKris Buschelman     /*******************************************************************/
2564eb8e494SKris Buschelman     /* Fill in the data for the problem.      (1-based Fortran style)  */
2574eb8e494SKris Buschelman     /*******************************************************************/
2584eb8e494SKris Buschelman 
2594eb8e494SKris Buschelman     nz = 0;
2602205254eSKarl Rupp     for (i = 0; i < n; i++) {
2614eb8e494SKris Buschelman       rs = a->i[i];
2624eb8e494SKris Buschelman       re = a->i[i + 1];
2634eb8e494SKris Buschelman 
2642205254eSKarl Rupp       while (rs < re) {
2652205254eSKarl Rupp         if (a->a[rs] != 0.0) {
2664eb8e494SKris Buschelman           lusol->indc[nz] = i + 1;
2674eb8e494SKris Buschelman           lusol->indr[nz] = a->j[rs] + 1;
2684eb8e494SKris Buschelman           lusol->data[nz] = a->a[rs];
2694eb8e494SKris Buschelman           nz++;
2704eb8e494SKris Buschelman         }
2714eb8e494SKris Buschelman         rs++;
2724eb8e494SKris Buschelman       }
2734eb8e494SKris Buschelman     }
2744eb8e494SKris Buschelman 
2754eb8e494SKris Buschelman     /*******************************************************************/
2764eb8e494SKris Buschelman     /* Do the factorization.                                           */
2774eb8e494SKris Buschelman     /*******************************************************************/
2784eb8e494SKris Buschelman 
2799371c9d4SSatish Balay     LU1FAC(&m, &n, &nz, &nnz, lusol->luparm, lusol->parmlu, lusol->data, lusol->indc, lusol->indr, lusol->ip, lusol->iq, lusol->lenc, lusol->lenr, lusol->locc, lusol->locr, lusol->iploc, lusol->iqloc, lusol->ipinv, lusol->iqinv, lusol->mnsw, &status);
2804eb8e494SKris Buschelman 
2812205254eSKarl Rupp     switch (status) {
2829371c9d4SSatish Balay     case 0: /* factored */ break;
2834eb8e494SKris Buschelman 
2849371c9d4SSatish Balay     case 7: /* insufficient memory */ break;
2854eb8e494SKris Buschelman 
2864eb8e494SKris Buschelman     case 1:
2879371c9d4SSatish Balay     case -1: /* singular */ SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Singular matrix");
2884eb8e494SKris Buschelman 
2894eb8e494SKris Buschelman     case 3:
2909371c9d4SSatish Balay     case 4: /* error conditions */ SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "matrix error");
2914eb8e494SKris Buschelman 
2929371c9d4SSatish Balay     default: /* unknown condition */ SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "matrix unknown return code");
2934eb8e494SKris Buschelman     }
2944eb8e494SKris Buschelman 
2954eb8e494SKris Buschelman     factorizations++;
2964eb8e494SKris Buschelman   } while (status == 7);
297719d5645SBarry Smith   F->ops->solve   = MatSolve_LUSOL;
298719d5645SBarry Smith   F->assembled    = PETSC_TRUE;
299719d5645SBarry Smith   F->preallocated = PETSC_TRUE;
3004eb8e494SKris Buschelman   PetscFunctionReturn(0);
3014eb8e494SKris Buschelman }
3024eb8e494SKris Buschelman 
3039371c9d4SSatish Balay PetscErrorCode MatLUFactorSymbolic_LUSOL(Mat F, Mat A, IS r, IS c, const MatFactorInfo *info) {
3044eb8e494SKris Buschelman   /************************************************************************/
3054eb8e494SKris Buschelman   /* Input                                                                */
3064eb8e494SKris Buschelman   /*     A  - matrix to factor                                            */
3074eb8e494SKris Buschelman   /*     r  - row permutation (ignored)                                   */
3084eb8e494SKris Buschelman   /*     c  - column permutation (ignored)                                */
3094eb8e494SKris Buschelman   /*                                                                      */
3104eb8e494SKris Buschelman   /* Output                                                               */
3114eb8e494SKris Buschelman   /*     F  - matrix storing the factorization;                           */
3124eb8e494SKris Buschelman   /************************************************************************/
313f0c56d0fSKris Buschelman   Mat_LUSOL *lusol;
314dfbe8321SBarry Smith   int        i, m, n, nz, nnz;
3154eb8e494SKris Buschelman 
3164eb8e494SKris Buschelman   PetscFunctionBegin;
3174eb8e494SKris Buschelman   /************************************************************************/
3184eb8e494SKris Buschelman   /* Check the arguments.                                                 */
3194eb8e494SKris Buschelman   /************************************************************************/
3204eb8e494SKris Buschelman 
3219566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &m, &n));
3224eb8e494SKris Buschelman   nz = ((Mat_SeqAIJ *)A->data)->nz;
3234eb8e494SKris Buschelman 
3244eb8e494SKris Buschelman   /************************************************************************/
3254eb8e494SKris Buschelman   /* Create the factorization.                                            */
3264eb8e494SKris Buschelman   /************************************************************************/
3274eb8e494SKris Buschelman 
32835bd34faSBarry Smith   F->ops->lufactornumeric = MatLUFactorNumeric_LUSOL;
32935bd34faSBarry Smith   lusol                   = (Mat_LUSOL *)(F->spptr);
3304eb8e494SKris Buschelman 
3314eb8e494SKris Buschelman   /************************************************************************/
3324eb8e494SKris Buschelman   /* Initialize parameters                                                */
3334eb8e494SKris Buschelman   /************************************************************************/
3344eb8e494SKris Buschelman 
3352205254eSKarl Rupp   for (i = 0; i < 30; i++) {
3364eb8e494SKris Buschelman     lusol->luparm[i] = 0;
3374eb8e494SKris Buschelman     lusol->parmlu[i] = 0;
3384eb8e494SKris Buschelman   }
3394eb8e494SKris Buschelman 
3404eb8e494SKris Buschelman   lusol->luparm[1] = -1;
3414eb8e494SKris Buschelman   lusol->luparm[2] = 5;
3424eb8e494SKris Buschelman   lusol->luparm[7] = 1;
3434eb8e494SKris Buschelman 
3444eb8e494SKris Buschelman   lusol->parmlu[0] = 1 / Factorization_Tolerance;
3454eb8e494SKris Buschelman   lusol->parmlu[1] = 1 / Factorization_Tolerance;
3464eb8e494SKris Buschelman   lusol->parmlu[2] = Factorization_Small_Tolerance;
3474eb8e494SKris Buschelman   lusol->parmlu[3] = Factorization_Pivot_Tolerance;
3484eb8e494SKris Buschelman   lusol->parmlu[4] = Factorization_Pivot_Tolerance;
3494eb8e494SKris Buschelman   lusol->parmlu[5] = 3.0;
3504eb8e494SKris Buschelman   lusol->parmlu[6] = 0.3;
3514eb8e494SKris Buschelman   lusol->parmlu[7] = 0.6;
3524eb8e494SKris Buschelman 
3534eb8e494SKris Buschelman   /************************************************************************/
3544eb8e494SKris Buschelman   /* Allocate the workspace needed by LUSOL.                              */
3554eb8e494SKris Buschelman   /************************************************************************/
3564eb8e494SKris Buschelman 
3574eb8e494SKris Buschelman   lusol->elbowroom = PetscMax(lusol->elbowroom, info->fill);
3584eb8e494SKris Buschelman   nnz              = PetscMax((int)(lusol->elbowroom * nz), 5 * n);
3594eb8e494SKris Buschelman 
3604eb8e494SKris Buschelman   lusol->n      = n;
3614eb8e494SKris Buschelman   lusol->nz     = nz;
3624eb8e494SKris Buschelman   lusol->nnz    = nnz;
3634eb8e494SKris Buschelman   lusol->luroom = 1.75;
3644eb8e494SKris Buschelman 
365d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(int) * n, &lusol->ip));
366d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(int) * n, &lusol->iq));
367d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(int) * n, &lusol->lenc));
368d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(int) * n, &lusol->lenr));
369d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(int) * n, &lusol->locc));
370d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(int) * n, &lusol->locr));
371d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(int) * n, &lusol->iploc));
372d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(int) * n, &lusol->iqloc));
373d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(int) * n, &lusol->ipinv));
374d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(int) * n, &lusol->iqinv));
375d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(double) * n, &lusol->mnsw));
376d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(double) * n, &lusol->mnsv));
3779566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(nnz, &lusol->data, nnz, &lusol->indc, nnz, &lusol->indr));
3782205254eSKarl Rupp 
3794eb8e494SKris Buschelman   lusol->CleanUpLUSOL     = PETSC_TRUE;
38035bd34faSBarry Smith   F->ops->lufactornumeric = MatLUFactorNumeric_LUSOL;
3814eb8e494SKris Buschelman   PetscFunctionReturn(0);
3824eb8e494SKris Buschelman }
3834eb8e494SKris Buschelman 
3849371c9d4SSatish Balay PetscErrorCode MatFactorGetSolverType_seqaij_lusol(Mat A, MatSolverType *type) {
38535bd34faSBarry Smith   PetscFunctionBegin;
3862692d6eeSBarry Smith   *type = MATSOLVERLUSOL;
38735bd34faSBarry Smith   PetscFunctionReturn(0);
38835bd34faSBarry Smith }
38935bd34faSBarry Smith 
3909371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatGetFactor_seqaij_lusol(Mat A, MatFactorType ftype, Mat *F) {
391b24902e0SBarry Smith   Mat        B;
392f0c56d0fSKris Buschelman   Mat_LUSOL *lusol;
39335bd34faSBarry Smith   int        m, n;
3944eb8e494SKris Buschelman 
3954eb8e494SKris Buschelman   PetscFunctionBegin;
3969566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &m, &n));
3979566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
3989566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(B, PETSC_DECIDE, PETSC_DECIDE, m, n));
3999566063dSJacob Faibussowitsch   PetscCall(MatSetType(B, ((PetscObject)A)->type_name));
4009566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(B, 0, NULL));
4014eb8e494SKris Buschelman 
402*4dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&lusol));
403b24902e0SBarry Smith   B->spptr = lusol;
4042f71e704SKris Buschelman 
40566e17bc3SBarry Smith   B->trivialsymbolic       = PETSC_TRUE;
406f0c56d0fSKris Buschelman   B->ops->lufactorsymbolic = MatLUFactorSymbolic_LUSOL;
407f0c56d0fSKris Buschelman   B->ops->destroy          = MatDestroy_LUSOL;
4082205254eSKarl Rupp 
4099566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatFactorGetSolverType_C", MatFactorGetSolverType_seqaij_lusol));
4102205254eSKarl Rupp 
411d5f3da31SBarry Smith   B->factortype = MAT_FACTOR_LU;
4129566063dSJacob Faibussowitsch   PetscCall(PetscFree(B->solvertype));
4139566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERLUSOL, &B->solvertype));
41400c67f3bSHong Zhang 
415f0c56d0fSKris Buschelman   PetscFunctionReturn(0);
416f0c56d0fSKris Buschelman }
417f0c56d0fSKris Buschelman 
4189371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatSolverTypeRegister_Lusol(void) {
41942c9c57cSBarry Smith   PetscFunctionBegin;
4209566063dSJacob Faibussowitsch   PetscCall(MatSolverTypeRegister(MATSOLVERLUSOL, MATSEQAIJ, MAT_FACTOR_LU, MatGetFactor_seqaij_lusol));
42142c9c57cSBarry Smith   PetscFunctionReturn(0);
42242c9c57cSBarry Smith }
42342c9c57cSBarry Smith 
4242f71e704SKris Buschelman /*MC
42511a5261eSBarry Smith   MATSOLVERLUSOL - "lusol" - Provides direct solvers, LU, for sequential matrices
4262f71e704SKris Buschelman                          via the external package LUSOL.
4272f71e704SKris Buschelman 
4282f71e704SKris Buschelman   If LUSOL is installed (see the manual for
4292f71e704SKris Buschelman   instructions on how to declare the existence of external packages),
4302f71e704SKris Buschelman 
43111a5261eSBarry Smith   Works with `MATSEQAIJ` matrices
4322f71e704SKris Buschelman 
4332f71e704SKris Buschelman    Level: beginner
4342f71e704SKris Buschelman 
435db781477SPatrick Sanan .seealso: `PCLU`, `PCFactorSetMatSolverType()`, `MatSolverType`
4362f71e704SKris Buschelman M*/
437