xref: /petsc/src/mat/impls/aij/seq/lusol/lusol.c (revision d71ae5a4db6382e7f06317b8d368875286fe9008)
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 */
25*d71ae5a4SJacob Faibussowitsch PETSC_EXTERN void M1PAGE()
26*d71ae5a4SJacob Faibussowitsch {
274eb8e494SKris Buschelman   ;
284eb8e494SKris Buschelman }
29*d71ae5a4SJacob Faibussowitsch PETSC_EXTERN void M5SETX()
30*d71ae5a4SJacob Faibussowitsch {
314eb8e494SKris Buschelman   ;
324eb8e494SKris Buschelman }
334eb8e494SKris Buschelman 
34*d71ae5a4SJacob Faibussowitsch PETSC_EXTERN void M6RDEL()
35*d71ae5a4SJacob Faibussowitsch {
364eb8e494SKris Buschelman   ;
374eb8e494SKris Buschelman }
384eb8e494SKris Buschelman 
399371c9d4SSatish 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);
404eb8e494SKris Buschelman 
419371c9d4SSatish 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);
424eb8e494SKris Buschelman 
4309573ac7SBarry Smith extern PetscErrorCode MatDuplicate_LUSOL(Mat, MatDuplicateOption, Mat *);
44f0c56d0fSKris Buschelman 
45f0c56d0fSKris Buschelman typedef struct {
464eb8e494SKris Buschelman   double *data;
474eb8e494SKris Buschelman   int    *indc;
484eb8e494SKris Buschelman   int    *indr;
494eb8e494SKris Buschelman 
504eb8e494SKris Buschelman   int    *ip;
514eb8e494SKris Buschelman   int    *iq;
524eb8e494SKris Buschelman   int    *lenc;
534eb8e494SKris Buschelman   int    *lenr;
544eb8e494SKris Buschelman   int    *locc;
554eb8e494SKris Buschelman   int    *locr;
564eb8e494SKris Buschelman   int    *iploc;
574eb8e494SKris Buschelman   int    *iqloc;
584eb8e494SKris Buschelman   int    *ipinv;
594eb8e494SKris Buschelman   int    *iqinv;
604eb8e494SKris Buschelman   double *mnsw;
614eb8e494SKris Buschelman   double *mnsv;
624eb8e494SKris Buschelman 
634eb8e494SKris Buschelman   double elbowroom;
644eb8e494SKris Buschelman   double luroom;     /* Extra space allocated when factor fails   */
654eb8e494SKris Buschelman   double parmlu[30]; /* Input/output to LUSOL                     */
664eb8e494SKris Buschelman 
674eb8e494SKris Buschelman   int n;          /* Number of rows/columns in matrix          */
684eb8e494SKris Buschelman   int nz;         /* Number of nonzeros                        */
694eb8e494SKris Buschelman   int nnz;        /* Number of nonzeros allocated for factors  */
704eb8e494SKris Buschelman   int luparm[30]; /* Input/output to LUSOL                     */
714eb8e494SKris Buschelman 
72ace3abfcSBarry Smith   PetscBool CleanUpLUSOL;
734eb8e494SKris Buschelman 
74f0c56d0fSKris Buschelman } Mat_LUSOL;
754eb8e494SKris Buschelman 
764eb8e494SKris Buschelman /*  LUSOL input/Output Parameters (Description uses C-style indexes
774eb8e494SKris Buschelman  *
784eb8e494SKris Buschelman  *  Input parameters                                        Typical value
794eb8e494SKris Buschelman  *
804eb8e494SKris Buschelman  *  luparm(0) = nout     File number for printed messages.         6
814eb8e494SKris Buschelman  *  luparm(1) = lprint   Print level.                              0
824eb8e494SKris Buschelman  *                    < 0 suppresses output.
834eb8e494SKris Buschelman  *                    = 0 gives error messages.
844eb8e494SKris Buschelman  *                    = 1 gives debug output from some of the
854eb8e494SKris Buschelman  *                        other routines in LUSOL.
864eb8e494SKris Buschelman  *                   >= 2 gives the pivot row and column and the
874eb8e494SKris Buschelman  *                        no. of rows and columns involved at
884eb8e494SKris Buschelman  *                        each elimination step in lu1fac.
894eb8e494SKris Buschelman  *  luparm(2) = maxcol   lu1fac: maximum number of columns         5
904eb8e494SKris Buschelman  *                        searched allowed in a Markowitz-type
914eb8e494SKris Buschelman  *                        search for the next pivot element.
924eb8e494SKris Buschelman  *                        For some of the factorization, the
934eb8e494SKris Buschelman  *                        number of rows searched is
944eb8e494SKris Buschelman  *                        maxrow = maxcol - 1.
954eb8e494SKris Buschelman  *
964eb8e494SKris Buschelman  *
977a7aea1fSJed Brown  *  Output parameters:
984eb8e494SKris Buschelman  *
994eb8e494SKris Buschelman  *  luparm(9) = inform   Return code from last call to any LU routine.
1004eb8e494SKris Buschelman  *  luparm(10) = nsing    No. of singularities marked in the
1014eb8e494SKris Buschelman  *                        output array w(*).
1024eb8e494SKris Buschelman  *  luparm(11) = jsing    Column index of last singularity.
1034eb8e494SKris Buschelman  *  luparm(12) = minlen   Minimum recommended value for  lena.
1044eb8e494SKris Buschelman  *  luparm(13) = maxlen   ?
1054eb8e494SKris Buschelman  *  luparm(14) = nupdat   No. of updates performed by the lu8 routines.
1064eb8e494SKris Buschelman  *  luparm(15) = nrank    No. of nonempty rows of U.
1074eb8e494SKris Buschelman  *  luparm(16) = ndens1   No. of columns remaining when the density of
1084eb8e494SKris Buschelman  *                        the matrix being factorized reached dens1.
1094eb8e494SKris Buschelman  *  luparm(17) = ndens2   No. of columns remaining when the density of
1104eb8e494SKris Buschelman  *                        the matrix being factorized reached dens2.
1114eb8e494SKris Buschelman  *  luparm(18) = jumin    The column index associated with dumin.
1124eb8e494SKris Buschelman  *  luparm(19) = numl0    No. of columns in initial  L.
1134eb8e494SKris Buschelman  *  luparm(20) = lenl0    Size of initial  L  (no. of nonzeros).
1144eb8e494SKris Buschelman  *  luparm(21) = lenu0    Size of initial  U.
1154eb8e494SKris Buschelman  *  luparm(22) = lenl     Size of current  L.
1164eb8e494SKris Buschelman  *  luparm(23) = lenu     Size of current  U.
1174eb8e494SKris Buschelman  *  luparm(24) = lrow     Length of row file.
1184eb8e494SKris Buschelman  *  luparm(25) = ncp      No. of compressions of LU data structures.
1194eb8e494SKris Buschelman  *  luparm(26) = mersum   lu1fac: sum of Markowitz merit counts.
1204eb8e494SKris Buschelman  *  luparm(27) = nutri    lu1fac: triangular rows in U.
1214eb8e494SKris Buschelman  *  luparm(28) = nltri    lu1fac: triangular rows in L.
1224eb8e494SKris Buschelman  *  luparm(29) =
1234eb8e494SKris Buschelman  *
1244eb8e494SKris Buschelman  *
1254eb8e494SKris Buschelman  *  Input parameters                                        Typical value
1264eb8e494SKris Buschelman  *
1274eb8e494SKris Buschelman  *  parmlu(0) = elmax1   Max multiplier allowed in  L           10.0
1284eb8e494SKris Buschelman  *                        during factor.
1294eb8e494SKris Buschelman  *  parmlu(1) = elmax2   Max multiplier allowed in  L           10.0
1304eb8e494SKris Buschelman  *                        during updates.
1314eb8e494SKris Buschelman  *  parmlu(2) = small    Absolute tolerance for             eps**0.8
1324eb8e494SKris Buschelman  *                        treating reals as zero.     IBM double: 3.0d-13
1334eb8e494SKris Buschelman  *  parmlu(3) = utol1    Absolute tol for flagging          eps**0.66667
1344eb8e494SKris Buschelman  *                        small diagonals of U.       IBM double: 3.7d-11
1354eb8e494SKris Buschelman  *  parmlu(4) = utol2    Relative tol for flagging          eps**0.66667
1364eb8e494SKris Buschelman  *                        small diagonals of U.       IBM double: 3.7d-11
1374eb8e494SKris Buschelman  *  parmlu(5) = uspace   Factor limiting waste space in  U.      3.0
1384eb8e494SKris Buschelman  *                        In lu1fac, the row or column lists
1394eb8e494SKris Buschelman  *                        are compressed if their length
1404eb8e494SKris Buschelman  *                        exceeds uspace times the length of
1414eb8e494SKris Buschelman  *                        either file after the last compression.
1424eb8e494SKris Buschelman  *  parmlu(6) = dens1    The density at which the Markowitz      0.3
1434eb8e494SKris Buschelman  *                        strategy should search maxcol columns
1444eb8e494SKris Buschelman  *                        and no rows.
1454eb8e494SKris Buschelman  *  parmlu(7) = dens2    the density at which the Markowitz      0.6
1464eb8e494SKris Buschelman  *                        strategy should search only 1 column
1474eb8e494SKris Buschelman  *                        or (preferably) use a dense LU for
1484eb8e494SKris Buschelman  *                        all the remaining rows and columns.
1494eb8e494SKris Buschelman  *
1504eb8e494SKris Buschelman  *
1517a7aea1fSJed Brown  *  Output parameters:
1524eb8e494SKris Buschelman  *
1534eb8e494SKris Buschelman  *  parmlu(9) = amax     Maximum element in  A.
1544eb8e494SKris Buschelman  *  parmlu(10) = elmax    Maximum multiplier in current  L.
1554eb8e494SKris Buschelman  *  parmlu(11) = umax     Maximum element in current  U.
1564eb8e494SKris Buschelman  *  parmlu(12) = dumax    Maximum diagonal in  U.
1574eb8e494SKris Buschelman  *  parmlu(13) = dumin    Minimum diagonal in  U.
1584eb8e494SKris Buschelman  *  parmlu(14) =
1594eb8e494SKris Buschelman  *  parmlu(15) =
1604eb8e494SKris Buschelman  *  parmlu(16) =
1614eb8e494SKris Buschelman  *  parmlu(17) =
1624eb8e494SKris Buschelman  *  parmlu(18) =
1634eb8e494SKris Buschelman  *  parmlu(19) = resid    lu6sol: residual after solve with U or U'.
1644eb8e494SKris Buschelman  *  ...
1654eb8e494SKris Buschelman  *  parmlu(29) =
1664eb8e494SKris Buschelman  */
1674eb8e494SKris Buschelman 
1684eb8e494SKris Buschelman #define Factorization_Tolerance       1e-1
1694eb8e494SKris Buschelman #define Factorization_Pivot_Tolerance pow(2.2204460492503131E-16, 2.0 / 3.0)
1704eb8e494SKris Buschelman #define Factorization_Small_Tolerance 1e-15 /* pow(DBL_EPSILON, 0.8) */
1714eb8e494SKris Buschelman 
172*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_LUSOL(Mat A)
173*d71ae5a4SJacob Faibussowitsch {
174f0c56d0fSKris Buschelman   Mat_LUSOL *lusol = (Mat_LUSOL *)A->spptr;
1754eb8e494SKris Buschelman 
1764eb8e494SKris Buschelman   PetscFunctionBegin;
177bf0cc555SLisandro Dalcin   if (lusol && lusol->CleanUpLUSOL) {
1789566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->ip));
1799566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->iq));
1809566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->lenc));
1819566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->lenr));
1829566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->locc));
1839566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->locr));
1849566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->iploc));
1859566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->iqloc));
1869566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->ipinv));
1879566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->iqinv));
1889566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->mnsw));
1899566063dSJacob Faibussowitsch     PetscCall(PetscFree(lusol->mnsv));
1909566063dSJacob Faibussowitsch     PetscCall(PetscFree3(lusol->data, lusol->indc, lusol->indr));
1914eb8e494SKris Buschelman   }
1929566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->spptr));
1939566063dSJacob Faibussowitsch   PetscCall(MatDestroy_SeqAIJ(A));
1944eb8e494SKris Buschelman   PetscFunctionReturn(0);
1954eb8e494SKris Buschelman }
1964eb8e494SKris Buschelman 
197*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSolve_LUSOL(Mat A, Vec b, Vec x)
198*d71ae5a4SJacob Faibussowitsch {
199f0c56d0fSKris Buschelman   Mat_LUSOL    *lusol = (Mat_LUSOL *)A->spptr;
200d9ca1df4SBarry Smith   double       *xx;
201d9ca1df4SBarry Smith   const double *bb;
2024eb8e494SKris Buschelman   int           mode = 5;
2036849ba73SBarry Smith   int           i, m, n, nnz, status;
2044eb8e494SKris Buschelman 
2054eb8e494SKris Buschelman   PetscFunctionBegin;
2069566063dSJacob Faibussowitsch   PetscCall(VecGetArray(x, &xx));
2079566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(b, &bb));
2084eb8e494SKris Buschelman 
2094eb8e494SKris Buschelman   m = n = lusol->n;
2104eb8e494SKris Buschelman   nnz   = lusol->nnz;
2114eb8e494SKris Buschelman 
2122205254eSKarl Rupp   for (i = 0; i < m; i++) lusol->mnsv[i] = bb[i];
2134eb8e494SKris Buschelman 
2149371c9d4SSatish 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);
2154eb8e494SKris Buschelman 
21628b400f6SJacob Faibussowitsch   PetscCheck(!status, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "solve failed, error code %d", status);
2174eb8e494SKris Buschelman 
2189566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(x, &xx));
2199566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(b, &bb));
2204eb8e494SKris Buschelman   PetscFunctionReturn(0);
2214eb8e494SKris Buschelman }
2224eb8e494SKris Buschelman 
223*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLUFactorNumeric_LUSOL(Mat F, Mat A, const MatFactorInfo *info)
224*d71ae5a4SJacob Faibussowitsch {
2254eb8e494SKris Buschelman   Mat_SeqAIJ *a;
226719d5645SBarry Smith   Mat_LUSOL  *lusol = (Mat_LUSOL *)F->spptr;
2274eb8e494SKris Buschelman   int         m, n, nz, nnz, status;
2286849ba73SBarry Smith   int         i, rs, re;
2294eb8e494SKris Buschelman   int         factorizations;
2304eb8e494SKris Buschelman 
2314eb8e494SKris Buschelman   PetscFunctionBegin;
2329566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &m, &n));
2334eb8e494SKris Buschelman   a = (Mat_SeqAIJ *)A->data;
2344eb8e494SKris Buschelman 
23508401ef6SPierre Jolivet   PetscCheck(m == lusol->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "factorization struct inconsistent");
2364eb8e494SKris Buschelman 
2374eb8e494SKris Buschelman   factorizations = 0;
2382205254eSKarl Rupp   do {
2394eb8e494SKris Buschelman     /*******************************************************************/
2404eb8e494SKris Buschelman     /* Check the workspace allocation.                                 */
2414eb8e494SKris Buschelman     /*******************************************************************/
2424eb8e494SKris Buschelman 
2434eb8e494SKris Buschelman     nz  = a->nz;
2444eb8e494SKris Buschelman     nnz = PetscMax(lusol->nnz, (int)(lusol->elbowroom * nz));
2454eb8e494SKris Buschelman     nnz = PetscMax(nnz, 5 * n);
2464eb8e494SKris Buschelman 
2474eb8e494SKris Buschelman     if (nnz < lusol->luparm[12]) {
2484eb8e494SKris Buschelman       nnz = (int)(lusol->luroom * lusol->luparm[12]);
2494eb8e494SKris Buschelman     } else if ((factorizations > 0) && (lusol->luroom < 6)) {
2504eb8e494SKris Buschelman       lusol->luroom += 0.1;
2514eb8e494SKris Buschelman     }
2524eb8e494SKris Buschelman 
2534eb8e494SKris Buschelman     nnz = PetscMax(nnz, (int)(lusol->luroom * (lusol->luparm[22] + lusol->luparm[23])));
2544eb8e494SKris Buschelman 
2554eb8e494SKris Buschelman     if (nnz > lusol->nnz) {
2569566063dSJacob Faibussowitsch       PetscCall(PetscFree3(lusol->data, lusol->indc, lusol->indr));
2579566063dSJacob Faibussowitsch       PetscCall(PetscMalloc3(nnz, &lusol->data, nnz, &lusol->indc, nnz, &lusol->indr));
2584eb8e494SKris Buschelman       lusol->nnz = nnz;
2594eb8e494SKris Buschelman     }
2604eb8e494SKris Buschelman 
2614eb8e494SKris Buschelman     /*******************************************************************/
2624eb8e494SKris Buschelman     /* Fill in the data for the problem.      (1-based Fortran style)  */
2634eb8e494SKris Buschelman     /*******************************************************************/
2644eb8e494SKris Buschelman 
2654eb8e494SKris Buschelman     nz = 0;
2662205254eSKarl Rupp     for (i = 0; i < n; i++) {
2674eb8e494SKris Buschelman       rs = a->i[i];
2684eb8e494SKris Buschelman       re = a->i[i + 1];
2694eb8e494SKris Buschelman 
2702205254eSKarl Rupp       while (rs < re) {
2712205254eSKarl Rupp         if (a->a[rs] != 0.0) {
2724eb8e494SKris Buschelman           lusol->indc[nz] = i + 1;
2734eb8e494SKris Buschelman           lusol->indr[nz] = a->j[rs] + 1;
2744eb8e494SKris Buschelman           lusol->data[nz] = a->a[rs];
2754eb8e494SKris Buschelman           nz++;
2764eb8e494SKris Buschelman         }
2774eb8e494SKris Buschelman         rs++;
2784eb8e494SKris Buschelman       }
2794eb8e494SKris Buschelman     }
2804eb8e494SKris Buschelman 
2814eb8e494SKris Buschelman     /*******************************************************************/
2824eb8e494SKris Buschelman     /* Do the factorization.                                           */
2834eb8e494SKris Buschelman     /*******************************************************************/
2844eb8e494SKris Buschelman 
2859371c9d4SSatish 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);
2864eb8e494SKris Buschelman 
2872205254eSKarl Rupp     switch (status) {
288*d71ae5a4SJacob Faibussowitsch     case 0: /* factored */
289*d71ae5a4SJacob Faibussowitsch       break;
2904eb8e494SKris Buschelman 
291*d71ae5a4SJacob Faibussowitsch     case 7: /* insufficient memory */
292*d71ae5a4SJacob Faibussowitsch       break;
2934eb8e494SKris Buschelman 
2944eb8e494SKris Buschelman     case 1:
295*d71ae5a4SJacob Faibussowitsch     case -1: /* singular */
296*d71ae5a4SJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Singular matrix");
2974eb8e494SKris Buschelman 
2984eb8e494SKris Buschelman     case 3:
299*d71ae5a4SJacob Faibussowitsch     case 4: /* error conditions */
300*d71ae5a4SJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "matrix error");
3014eb8e494SKris Buschelman 
302*d71ae5a4SJacob Faibussowitsch     default: /* unknown condition */
303*d71ae5a4SJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "matrix unknown return code");
3044eb8e494SKris Buschelman     }
3054eb8e494SKris Buschelman 
3064eb8e494SKris Buschelman     factorizations++;
3074eb8e494SKris Buschelman   } while (status == 7);
308719d5645SBarry Smith   F->ops->solve   = MatSolve_LUSOL;
309719d5645SBarry Smith   F->assembled    = PETSC_TRUE;
310719d5645SBarry Smith   F->preallocated = PETSC_TRUE;
3114eb8e494SKris Buschelman   PetscFunctionReturn(0);
3124eb8e494SKris Buschelman }
3134eb8e494SKris Buschelman 
314*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLUFactorSymbolic_LUSOL(Mat F, Mat A, IS r, IS c, const MatFactorInfo *info)
315*d71ae5a4SJacob Faibussowitsch {
3164eb8e494SKris Buschelman   /************************************************************************/
3174eb8e494SKris Buschelman   /* Input                                                                */
3184eb8e494SKris Buschelman   /*     A  - matrix to factor                                            */
3194eb8e494SKris Buschelman   /*     r  - row permutation (ignored)                                   */
3204eb8e494SKris Buschelman   /*     c  - column permutation (ignored)                                */
3214eb8e494SKris Buschelman   /*                                                                      */
3224eb8e494SKris Buschelman   /* Output                                                               */
3234eb8e494SKris Buschelman   /*     F  - matrix storing the factorization;                           */
3244eb8e494SKris Buschelman   /************************************************************************/
325f0c56d0fSKris Buschelman   Mat_LUSOL *lusol;
326dfbe8321SBarry Smith   int        i, m, n, nz, nnz;
3274eb8e494SKris Buschelman 
3284eb8e494SKris Buschelman   PetscFunctionBegin;
3294eb8e494SKris Buschelman   /************************************************************************/
3304eb8e494SKris Buschelman   /* Check the arguments.                                                 */
3314eb8e494SKris Buschelman   /************************************************************************/
3324eb8e494SKris Buschelman 
3339566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &m, &n));
3344eb8e494SKris Buschelman   nz = ((Mat_SeqAIJ *)A->data)->nz;
3354eb8e494SKris Buschelman 
3364eb8e494SKris Buschelman   /************************************************************************/
3374eb8e494SKris Buschelman   /* Create the factorization.                                            */
3384eb8e494SKris Buschelman   /************************************************************************/
3394eb8e494SKris Buschelman 
34035bd34faSBarry Smith   F->ops->lufactornumeric = MatLUFactorNumeric_LUSOL;
34135bd34faSBarry Smith   lusol                   = (Mat_LUSOL *)(F->spptr);
3424eb8e494SKris Buschelman 
3434eb8e494SKris Buschelman   /************************************************************************/
3444eb8e494SKris Buschelman   /* Initialize parameters                                                */
3454eb8e494SKris Buschelman   /************************************************************************/
3464eb8e494SKris Buschelman 
3472205254eSKarl Rupp   for (i = 0; i < 30; i++) {
3484eb8e494SKris Buschelman     lusol->luparm[i] = 0;
3494eb8e494SKris Buschelman     lusol->parmlu[i] = 0;
3504eb8e494SKris Buschelman   }
3514eb8e494SKris Buschelman 
3524eb8e494SKris Buschelman   lusol->luparm[1] = -1;
3534eb8e494SKris Buschelman   lusol->luparm[2] = 5;
3544eb8e494SKris Buschelman   lusol->luparm[7] = 1;
3554eb8e494SKris Buschelman 
3564eb8e494SKris Buschelman   lusol->parmlu[0] = 1 / Factorization_Tolerance;
3574eb8e494SKris Buschelman   lusol->parmlu[1] = 1 / Factorization_Tolerance;
3584eb8e494SKris Buschelman   lusol->parmlu[2] = Factorization_Small_Tolerance;
3594eb8e494SKris Buschelman   lusol->parmlu[3] = Factorization_Pivot_Tolerance;
3604eb8e494SKris Buschelman   lusol->parmlu[4] = Factorization_Pivot_Tolerance;
3614eb8e494SKris Buschelman   lusol->parmlu[5] = 3.0;
3624eb8e494SKris Buschelman   lusol->parmlu[6] = 0.3;
3634eb8e494SKris Buschelman   lusol->parmlu[7] = 0.6;
3644eb8e494SKris Buschelman 
3654eb8e494SKris Buschelman   /************************************************************************/
3664eb8e494SKris Buschelman   /* Allocate the workspace needed by LUSOL.                              */
3674eb8e494SKris Buschelman   /************************************************************************/
3684eb8e494SKris Buschelman 
3694eb8e494SKris Buschelman   lusol->elbowroom = PetscMax(lusol->elbowroom, info->fill);
3704eb8e494SKris Buschelman   nnz              = PetscMax((int)(lusol->elbowroom * nz), 5 * n);
3714eb8e494SKris Buschelman 
3724eb8e494SKris Buschelman   lusol->n      = n;
3734eb8e494SKris Buschelman   lusol->nz     = nz;
3744eb8e494SKris Buschelman   lusol->nnz    = nnz;
3754eb8e494SKris Buschelman   lusol->luroom = 1.75;
3764eb8e494SKris Buschelman 
377d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(int) * n, &lusol->ip));
378d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(int) * n, &lusol->iq));
379d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(int) * n, &lusol->lenc));
380d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(int) * n, &lusol->lenr));
381d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(int) * n, &lusol->locc));
382d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(int) * n, &lusol->locr));
383d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(int) * n, &lusol->iploc));
384d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(int) * n, &lusol->iqloc));
385d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(int) * n, &lusol->ipinv));
386d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(int) * n, &lusol->iqinv));
387d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(double) * n, &lusol->mnsw));
388d0609cedSBarry Smith   PetscCall(PetscMalloc(sizeof(double) * n, &lusol->mnsv));
3899566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(nnz, &lusol->data, nnz, &lusol->indc, nnz, &lusol->indr));
3902205254eSKarl Rupp 
3914eb8e494SKris Buschelman   lusol->CleanUpLUSOL     = PETSC_TRUE;
39235bd34faSBarry Smith   F->ops->lufactornumeric = MatLUFactorNumeric_LUSOL;
3934eb8e494SKris Buschelman   PetscFunctionReturn(0);
3944eb8e494SKris Buschelman }
3954eb8e494SKris Buschelman 
396*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatFactorGetSolverType_seqaij_lusol(Mat A, MatSolverType *type)
397*d71ae5a4SJacob Faibussowitsch {
39835bd34faSBarry Smith   PetscFunctionBegin;
3992692d6eeSBarry Smith   *type = MATSOLVERLUSOL;
40035bd34faSBarry Smith   PetscFunctionReturn(0);
40135bd34faSBarry Smith }
40235bd34faSBarry Smith 
403*d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatGetFactor_seqaij_lusol(Mat A, MatFactorType ftype, Mat *F)
404*d71ae5a4SJacob Faibussowitsch {
405b24902e0SBarry Smith   Mat        B;
406f0c56d0fSKris Buschelman   Mat_LUSOL *lusol;
40735bd34faSBarry Smith   int        m, n;
4084eb8e494SKris Buschelman 
4094eb8e494SKris Buschelman   PetscFunctionBegin;
4109566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &m, &n));
4119566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
4129566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(B, PETSC_DECIDE, PETSC_DECIDE, m, n));
4139566063dSJacob Faibussowitsch   PetscCall(MatSetType(B, ((PetscObject)A)->type_name));
4149566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(B, 0, NULL));
4154eb8e494SKris Buschelman 
4164dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&lusol));
417b24902e0SBarry Smith   B->spptr = lusol;
4182f71e704SKris Buschelman 
41966e17bc3SBarry Smith   B->trivialsymbolic       = PETSC_TRUE;
420f0c56d0fSKris Buschelman   B->ops->lufactorsymbolic = MatLUFactorSymbolic_LUSOL;
421f0c56d0fSKris Buschelman   B->ops->destroy          = MatDestroy_LUSOL;
4222205254eSKarl Rupp 
4239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatFactorGetSolverType_C", MatFactorGetSolverType_seqaij_lusol));
4242205254eSKarl Rupp 
425d5f3da31SBarry Smith   B->factortype = MAT_FACTOR_LU;
4269566063dSJacob Faibussowitsch   PetscCall(PetscFree(B->solvertype));
4279566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERLUSOL, &B->solvertype));
42800c67f3bSHong Zhang 
429f0c56d0fSKris Buschelman   PetscFunctionReturn(0);
430f0c56d0fSKris Buschelman }
431f0c56d0fSKris Buschelman 
432*d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatSolverTypeRegister_Lusol(void)
433*d71ae5a4SJacob Faibussowitsch {
43442c9c57cSBarry Smith   PetscFunctionBegin;
4359566063dSJacob Faibussowitsch   PetscCall(MatSolverTypeRegister(MATSOLVERLUSOL, MATSEQAIJ, MAT_FACTOR_LU, MatGetFactor_seqaij_lusol));
43642c9c57cSBarry Smith   PetscFunctionReturn(0);
43742c9c57cSBarry Smith }
43842c9c57cSBarry Smith 
4392f71e704SKris Buschelman /*MC
44011a5261eSBarry Smith   MATSOLVERLUSOL - "lusol" - Provides direct solvers, LU, for sequential matrices
4412f71e704SKris Buschelman                          via the external package LUSOL.
4422f71e704SKris Buschelman 
4432f71e704SKris Buschelman   If LUSOL is installed (see the manual for
4442f71e704SKris Buschelman   instructions on how to declare the existence of external packages),
4452f71e704SKris Buschelman 
44611a5261eSBarry Smith   Works with `MATSEQAIJ` matrices
4472f71e704SKris Buschelman 
4482f71e704SKris Buschelman    Level: beginner
4492f71e704SKris Buschelman 
450db781477SPatrick Sanan .seealso: `PCLU`, `PCFactorSetMatSolverType()`, `MatSolverType`
4512f71e704SKris Buschelman M*/
452