xref: /petsc/src/mat/impls/aij/seq/klu/klu.c (revision 3ba1676111f5c958fe6c2729b46ca4d523958bb3)
169e15a41SShri Abhyankar 
269e15a41SShri Abhyankar /*
369e15a41SShri Abhyankar    Provides an interface to the KLUv1.2 sparse solver
469e15a41SShri Abhyankar 
569e15a41SShri Abhyankar    When build with PETSC_USE_64BIT_INDICES this will use SuiteSparse_long as the
669e15a41SShri Abhyankar    integer type in KLU, otherwise it will use int. This means
769e15a41SShri Abhyankar    all integers in this file are simply declared as PetscInt. Also it means
869e15a41SShri Abhyankar    that KLU SuiteSparse_long version MUST be built with 64 bit integers when used.
969e15a41SShri Abhyankar 
1069e15a41SShri Abhyankar */
1169e15a41SShri Abhyankar #include <../src/mat/impls/aij/seq/aij.h>
1269e15a41SShri Abhyankar 
1369e15a41SShri Abhyankar #if defined(PETSC_USE_64BIT_INDICES)
1469e15a41SShri Abhyankar   #define klu_K_defaults                        klu_l_defaults
1530704e1fSBarry Smith   #define klu_K_analyze(a, b, c, d)             klu_l_analyze((SuiteSparse_long)a, (SuiteSparse_long *)b, (SuiteSparse_long *)c, d)
1630704e1fSBarry Smith   #define klu_K_analyze_given(a, b, c, d, e, f) klu_l_analyze_given((SuiteSparse_long)a, (SuiteSparse_long *)b, (SuiteSparse_long *)c, (SuiteSparse_long *)d, (SuiteSparse_long *)e, f)
1769e15a41SShri Abhyankar   #define klu_K_free_symbolic                   klu_l_free_symbolic
1869e15a41SShri Abhyankar   #define klu_K_free_numeric                    klu_l_free_numeric
1969e15a41SShri Abhyankar   #define klu_K_common                          klu_l_common
2069e15a41SShri Abhyankar   #define klu_K_symbolic                        klu_l_symbolic
2169e15a41SShri Abhyankar   #define klu_K_numeric                         klu_l_numeric
2269e15a41SShri Abhyankar   #if defined(PETSC_USE_COMPLEX)
2330704e1fSBarry Smith     #define klu_K_factor(a, b, c, d, e) klu_zl_factor((SuiteSparse_long *)a, (SuiteSparse_long *)b, c, d, e);
2469e15a41SShri Abhyankar     #define klu_K_solve                 klu_zl_solve
2569e15a41SShri Abhyankar     #define klu_K_tsolve                klu_zl_tsolve
2669e15a41SShri Abhyankar     #define klu_K_refactor              klu_zl_refactor
2769e15a41SShri Abhyankar     #define klu_K_sort                  klu_zl_sort
2869e15a41SShri Abhyankar     #define klu_K_flops                 klu_zl_flops
2969e15a41SShri Abhyankar     #define klu_K_rgrowth               klu_zl_rgrowth
3069e15a41SShri Abhyankar     #define klu_K_condest               klu_zl_condest
3169e15a41SShri Abhyankar     #define klu_K_rcond                 klu_zl_rcond
3269e15a41SShri Abhyankar     #define klu_K_scale                 klu_zl_scale
3369e15a41SShri Abhyankar   #else
3430704e1fSBarry Smith     #define klu_K_factor(a, b, c, d, e) klu_l_factor((SuiteSparse_long *)a, (SuiteSparse_long *)b, c, d, e);
3569e15a41SShri Abhyankar     #define klu_K_solve                 klu_l_solve
3669e15a41SShri Abhyankar     #define klu_K_tsolve                klu_l_tsolve
3769e15a41SShri Abhyankar     #define klu_K_refactor              klu_l_refactor
3869e15a41SShri Abhyankar     #define klu_K_sort                  klu_l_sort
3969e15a41SShri Abhyankar     #define klu_K_flops                 klu_l_flops
4069e15a41SShri Abhyankar     #define klu_K_rgrowth               klu_l_rgrowth
4169e15a41SShri Abhyankar     #define klu_K_condest               klu_l_condest
4269e15a41SShri Abhyankar     #define klu_K_rcond                 klu_l_rcond
4369e15a41SShri Abhyankar     #define klu_K_scale                 klu_l_scale
4469e15a41SShri Abhyankar   #endif
4569e15a41SShri Abhyankar #else
4669e15a41SShri Abhyankar   #define klu_K_defaults      klu_defaults
4769e15a41SShri Abhyankar   #define klu_K_analyze       klu_analyze
4869e15a41SShri Abhyankar   #define klu_K_analyze_given klu_analyze_given
4969e15a41SShri Abhyankar   #define klu_K_free_symbolic klu_free_symbolic
5069e15a41SShri Abhyankar   #define klu_K_free_numeric  klu_free_numeric
5169e15a41SShri Abhyankar   #define klu_K_common        klu_common
5269e15a41SShri Abhyankar   #define klu_K_symbolic      klu_symbolic
5369e15a41SShri Abhyankar   #define klu_K_numeric       klu_numeric
5469e15a41SShri Abhyankar   #if defined(PETSC_USE_COMPLEX)
5569e15a41SShri Abhyankar     #define klu_K_factor   klu_z_factor
5669e15a41SShri Abhyankar     #define klu_K_solve    klu_z_solve
5769e15a41SShri Abhyankar     #define klu_K_tsolve   klu_z_tsolve
5869e15a41SShri Abhyankar     #define klu_K_refactor klu_z_refactor
5969e15a41SShri Abhyankar     #define klu_K_sort     klu_z_sort
6069e15a41SShri Abhyankar     #define klu_K_flops    klu_z_flops
6169e15a41SShri Abhyankar     #define klu_K_rgrowth  klu_z_rgrowth
6269e15a41SShri Abhyankar     #define klu_K_condest  klu_z_condest
6369e15a41SShri Abhyankar     #define klu_K_rcond    klu_z_rcond
6469e15a41SShri Abhyankar     #define klu_K_scale    klu_z_scale
6569e15a41SShri Abhyankar   #else
6669e15a41SShri Abhyankar     #define klu_K_factor   klu_factor
6769e15a41SShri Abhyankar     #define klu_K_solve    klu_solve
6869e15a41SShri Abhyankar     #define klu_K_tsolve   klu_tsolve
6969e15a41SShri Abhyankar     #define klu_K_refactor klu_refactor
7069e15a41SShri Abhyankar     #define klu_K_sort     klu_sort
7169e15a41SShri Abhyankar     #define klu_K_flops    klu_flops
7269e15a41SShri Abhyankar     #define klu_K_rgrowth  klu_rgrowth
7369e15a41SShri Abhyankar     #define klu_K_condest  klu_condest
7469e15a41SShri Abhyankar     #define klu_K_rcond    klu_rcond
7569e15a41SShri Abhyankar     #define klu_K_scale    klu_scale
7669e15a41SShri Abhyankar   #endif
7769e15a41SShri Abhyankar #endif
7869e15a41SShri Abhyankar 
7969e15a41SShri Abhyankar EXTERN_C_BEGIN
8069e15a41SShri Abhyankar #include <klu.h>
8169e15a41SShri Abhyankar EXTERN_C_END
8269e15a41SShri Abhyankar 
834ac6704cSBarry Smith static const char *KluOrderingTypes[] = {"AMD", "COLAMD"};
8469e15a41SShri Abhyankar static const char *scale[]            = {"NONE", "SUM", "MAX"};
8569e15a41SShri Abhyankar 
8669e15a41SShri Abhyankar typedef struct {
8769e15a41SShri Abhyankar   klu_K_common    Common;
8869e15a41SShri Abhyankar   klu_K_symbolic *Symbolic;
8969e15a41SShri Abhyankar   klu_K_numeric  *Numeric;
9069e15a41SShri Abhyankar   PetscInt       *perm_c, *perm_r;
9169e15a41SShri Abhyankar   MatStructure    flg;
9269e15a41SShri Abhyankar   PetscBool       PetscMatOrdering;
9369e15a41SShri Abhyankar   PetscBool       CleanUpKLU;
9469e15a41SShri Abhyankar } Mat_KLU;
9569e15a41SShri Abhyankar 
96d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_KLU(Mat A)
97d71ae5a4SJacob Faibussowitsch {
98569c4379SBarry Smith   Mat_KLU *lu = (Mat_KLU *)A->data;
9969e15a41SShri Abhyankar 
10069e15a41SShri Abhyankar   PetscFunctionBegin;
101569c4379SBarry Smith   if (lu->CleanUpKLU) {
10269e15a41SShri Abhyankar     klu_K_free_symbolic(&lu->Symbolic, &lu->Common);
10369e15a41SShri Abhyankar     klu_K_free_numeric(&lu->Numeric, &lu->Common);
1049566063dSJacob Faibussowitsch     PetscCall(PetscFree2(lu->perm_r, lu->perm_c));
10569e15a41SShri Abhyankar   }
1062e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatFactorGetSolverType_C", NULL));
1079566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
108*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10969e15a41SShri Abhyankar }
11069e15a41SShri Abhyankar 
111d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_KLU(Mat A, Vec b, Vec x)
112d71ae5a4SJacob Faibussowitsch {
113569c4379SBarry Smith   Mat_KLU     *lu = (Mat_KLU *)A->data;
11469e15a41SShri Abhyankar   PetscScalar *xa;
11569e15a41SShri Abhyankar   PetscInt     status;
11669e15a41SShri Abhyankar 
11769e15a41SShri Abhyankar   PetscFunctionBegin;
11869e15a41SShri Abhyankar   /* KLU uses a column major format, solve Ax = b by klu_*_solve */
11969e15a41SShri Abhyankar   /* ----------------------------------*/
1209566063dSJacob Faibussowitsch   PetscCall(VecCopy(b, x)); /* klu_solve stores the solution in rhs */
1219566063dSJacob Faibussowitsch   PetscCall(VecGetArray(x, &xa));
12269e15a41SShri Abhyankar   status = klu_K_solve(lu->Symbolic, lu->Numeric, A->rmap->n, 1, (PetscReal *)xa, &lu->Common);
1235f80ce2aSJacob Faibussowitsch   PetscCheck(status == 1, PETSC_COMM_SELF, PETSC_ERR_LIB, "KLU Solve failed");
1249566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(x, &xa));
125*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12669e15a41SShri Abhyankar }
12769e15a41SShri Abhyankar 
128d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_KLU(Mat A, Vec b, Vec x)
129d71ae5a4SJacob Faibussowitsch {
130569c4379SBarry Smith   Mat_KLU     *lu = (Mat_KLU *)A->data;
13169e15a41SShri Abhyankar   PetscScalar *xa;
13269e15a41SShri Abhyankar   PetscInt     status;
13369e15a41SShri Abhyankar 
13469e15a41SShri Abhyankar   PetscFunctionBegin;
13569e15a41SShri Abhyankar   /* KLU uses a column major format, solve A^Tx = b by klu_*_tsolve */
13669e15a41SShri Abhyankar   /* ----------------------------------*/
1379566063dSJacob Faibussowitsch   PetscCall(VecCopy(b, x)); /* klu_solve stores the solution in rhs */
1389566063dSJacob Faibussowitsch   PetscCall(VecGetArray(x, &xa));
13969e15a41SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
14069e15a41SShri Abhyankar   PetscInt conj_solve = 1;
14169e15a41SShri Abhyankar   status              = klu_K_tsolve(lu->Symbolic, lu->Numeric, A->rmap->n, 1, (PetscReal *)xa, conj_solve, &lu->Common); /* conjugate solve */
14269e15a41SShri Abhyankar #else
14369e15a41SShri Abhyankar   status = klu_K_tsolve(lu->Symbolic, lu->Numeric, A->rmap->n, 1, xa, &lu->Common);
14469e15a41SShri Abhyankar #endif
1455f80ce2aSJacob Faibussowitsch   PetscCheck(status == 1, PETSC_COMM_SELF, PETSC_ERR_LIB, "KLU Solve failed");
1469566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(x, &xa));
147*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14869e15a41SShri Abhyankar }
14969e15a41SShri Abhyankar 
150d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatLUFactorNumeric_KLU(Mat F, Mat A, const MatFactorInfo *info)
151d71ae5a4SJacob Faibussowitsch {
152569c4379SBarry Smith   Mat_KLU     *lu = (Mat_KLU *)(F)->data;
15369e15a41SShri Abhyankar   Mat_SeqAIJ  *a  = (Mat_SeqAIJ *)A->data;
15469e15a41SShri Abhyankar   PetscInt    *ai = a->i, *aj = a->j;
15569e15a41SShri Abhyankar   PetscScalar *av = a->a;
15669e15a41SShri Abhyankar 
15769e15a41SShri Abhyankar   PetscFunctionBegin;
15869e15a41SShri Abhyankar   /* numeric factorization of A' */
15969e15a41SShri Abhyankar   /* ----------------------------*/
16069e15a41SShri Abhyankar 
161ad540459SPierre Jolivet   if (lu->flg == SAME_NONZERO_PATTERN && lu->Numeric) klu_K_free_numeric(&lu->Numeric, &lu->Common);
16269e15a41SShri Abhyankar   lu->Numeric = klu_K_factor(ai, aj, (PetscReal *)av, lu->Symbolic, &lu->Common);
1635f80ce2aSJacob Faibussowitsch   PetscCheck(lu->Numeric, PETSC_COMM_SELF, PETSC_ERR_LIB, "KLU Numeric factorization failed");
16469e15a41SShri Abhyankar 
16569e15a41SShri Abhyankar   lu->flg                = SAME_NONZERO_PATTERN;
16669e15a41SShri Abhyankar   lu->CleanUpKLU         = PETSC_TRUE;
16769e15a41SShri Abhyankar   F->ops->solve          = MatSolve_KLU;
16869e15a41SShri Abhyankar   F->ops->solvetranspose = MatSolveTranspose_KLU;
169*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17069e15a41SShri Abhyankar }
17169e15a41SShri Abhyankar 
172d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatLUFactorSymbolic_KLU(Mat F, Mat A, IS r, IS c, const MatFactorInfo *info)
173d71ae5a4SJacob Faibussowitsch {
17469e15a41SShri Abhyankar   Mat_SeqAIJ     *a  = (Mat_SeqAIJ *)A->data;
175569c4379SBarry Smith   Mat_KLU        *lu = (Mat_KLU *)(F->data);
17669e15a41SShri Abhyankar   PetscInt        i, *ai = a->i, *aj = a->j, m = A->rmap->n, n = A->cmap->n;
17769e15a41SShri Abhyankar   const PetscInt *ra, *ca;
17869e15a41SShri Abhyankar 
17969e15a41SShri Abhyankar   PetscFunctionBegin;
18069e15a41SShri Abhyankar   if (lu->PetscMatOrdering) {
1819566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(r, &ra));
1829566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(c, &ca));
1839566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(m, &lu->perm_r, n, &lu->perm_c));
18469e15a41SShri Abhyankar     /* we cannot simply memcpy on 64 bit archs */
18569e15a41SShri Abhyankar     for (i = 0; i < m; i++) lu->perm_r[i] = ra[i];
18669e15a41SShri Abhyankar     for (i = 0; i < n; i++) lu->perm_c[i] = ca[i];
1879566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(r, &ra));
1889566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(c, &ca));
18969e15a41SShri Abhyankar   }
19069e15a41SShri Abhyankar 
19169e15a41SShri Abhyankar   /* symbolic factorization of A' */
19269e15a41SShri Abhyankar   /* ---------------------------------------------------------------------- */
1934ac6704cSBarry Smith   if (r) {
1944ac6704cSBarry Smith     lu->PetscMatOrdering = PETSC_TRUE;
19569e15a41SShri Abhyankar     lu->Symbolic         = klu_K_analyze_given(n, ai, aj, lu->perm_c, lu->perm_r, &lu->Common);
19669e15a41SShri Abhyankar   } else { /* use klu internal ordering */
19769e15a41SShri Abhyankar     lu->Symbolic = klu_K_analyze(n, ai, aj, &lu->Common);
19869e15a41SShri Abhyankar   }
1995f80ce2aSJacob Faibussowitsch   PetscCheck(lu->Symbolic, PETSC_COMM_SELF, PETSC_ERR_LIB, "KLU Symbolic Factorization failed");
20069e15a41SShri Abhyankar 
20169e15a41SShri Abhyankar   lu->flg                   = DIFFERENT_NONZERO_PATTERN;
20269e15a41SShri Abhyankar   lu->CleanUpKLU            = PETSC_TRUE;
20369e15a41SShri Abhyankar   (F)->ops->lufactornumeric = MatLUFactorNumeric_KLU;
204*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20569e15a41SShri Abhyankar }
20669e15a41SShri Abhyankar 
207d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_Info_KLU(Mat A, PetscViewer viewer)
208d71ae5a4SJacob Faibussowitsch {
209569c4379SBarry Smith   Mat_KLU       *lu      = (Mat_KLU *)A->data;
21069e15a41SShri Abhyankar   klu_K_numeric *Numeric = (klu_K_numeric *)lu->Numeric;
21169e15a41SShri Abhyankar 
21269e15a41SShri Abhyankar   PetscFunctionBegin;
2139566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "KLU stats:\n"));
2149566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of diagonal blocks: %" PetscInt_FMT "\n", (PetscInt)(Numeric->nblocks)));
2159566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  Total nonzeros=%" PetscInt_FMT "\n", (PetscInt)(Numeric->lnz + Numeric->unz)));
2169566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "KLU runtime parameters:\n"));
21769e15a41SShri Abhyankar   /* Control parameters used by numeric factorization */
2189566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  Partial pivoting tolerance: %g\n", lu->Common.tol));
21969e15a41SShri Abhyankar   /* BTF preordering */
2209566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  BTF preordering enabled: %" PetscInt_FMT "\n", (PetscInt)(lu->Common.btf)));
22169e15a41SShri Abhyankar   /* mat ordering */
22248a46eb9SPierre Jolivet   if (!lu->PetscMatOrdering) PetscCall(PetscViewerASCIIPrintf(viewer, "  Ordering: %s (not using the PETSc ordering)\n", KluOrderingTypes[(int)lu->Common.ordering]));
22369e15a41SShri Abhyankar   /* matrix row scaling */
2249566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  Matrix row scaling: %s\n", scale[(int)lu->Common.scale]));
225*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22669e15a41SShri Abhyankar }
22769e15a41SShri Abhyankar 
228d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_KLU(Mat A, PetscViewer viewer)
229d71ae5a4SJacob Faibussowitsch {
23069e15a41SShri Abhyankar   PetscBool         iascii;
23169e15a41SShri Abhyankar   PetscViewerFormat format;
23269e15a41SShri Abhyankar 
23369e15a41SShri Abhyankar   PetscFunctionBegin;
2349566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
23569e15a41SShri Abhyankar   if (iascii) {
2369566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
23748a46eb9SPierre Jolivet     if (format == PETSC_VIEWER_ASCII_INFO) PetscCall(MatView_Info_KLU(A, viewer));
23869e15a41SShri Abhyankar   }
239*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24069e15a41SShri Abhyankar }
24169e15a41SShri Abhyankar 
242d71ae5a4SJacob Faibussowitsch PetscErrorCode MatFactorGetSolverType_seqaij_klu(Mat A, MatSolverType *type)
243d71ae5a4SJacob Faibussowitsch {
24469e15a41SShri Abhyankar   PetscFunctionBegin;
24569e15a41SShri Abhyankar   *type = MATSOLVERKLU;
246*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24769e15a41SShri Abhyankar }
24869e15a41SShri Abhyankar 
24969e15a41SShri Abhyankar /*MC
25011a5261eSBarry Smith   MATSOLVERKLU = "klu" - A matrix type providing direct solvers, LU, for sequential matrices
25169e15a41SShri Abhyankar   via the external package KLU.
25269e15a41SShri Abhyankar 
253057b0833SShri Abhyankar   ./configure --download-suitesparse to install PETSc to use KLU
25469e15a41SShri Abhyankar 
2553ca39a21SBarry Smith   Use -pc_type lu -pc_factor_mat_solver_type klu to use this direct solver
256c2b89b5dSBarry Smith 
25769e15a41SShri Abhyankar   Consult KLU documentation for more information on the options database keys below.
25869e15a41SShri Abhyankar 
25969e15a41SShri Abhyankar   Options Database Keys:
26069e15a41SShri Abhyankar + -mat_klu_pivot_tol <0.001>                  - Partial pivoting tolerance
26169e15a41SShri Abhyankar . -mat_klu_use_btf <1>                        - Use BTF preordering
26269e15a41SShri Abhyankar . -mat_klu_ordering <AMD>                     - KLU reordering scheme to reduce fill-in (choose one of) AMD COLAMD PETSC
26369e15a41SShri Abhyankar - -mat_klu_row_scale <NONE>                   - Matrix row scaling (choose one of) NONE SUM MAX
26469e15a41SShri Abhyankar 
265a364b7d2SBarry Smith    Note: KLU is part of SuiteSparse http://faculty.cse.tamu.edu/davis/suitesparse.html
266a364b7d2SBarry Smith 
26769e15a41SShri Abhyankar    Level: beginner
26869e15a41SShri Abhyankar 
269db781477SPatrick Sanan .seealso: `PCLU`, `MATSOLVERUMFPACK`, `MATSOLVERCHOLMOD`, `PCFactorSetMatSolverType()`, `MatSolverType`
27069e15a41SShri Abhyankar M*/
27169e15a41SShri Abhyankar 
272d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetFactor_seqaij_klu(Mat A, MatFactorType ftype, Mat *F)
273d71ae5a4SJacob Faibussowitsch {
27469e15a41SShri Abhyankar   Mat       B;
27569e15a41SShri Abhyankar   Mat_KLU  *lu;
2764ac6704cSBarry Smith   PetscInt  m = A->rmap->n, n = A->cmap->n, idx = 0, status;
27769e15a41SShri Abhyankar   PetscBool flg;
27869e15a41SShri Abhyankar 
27969e15a41SShri Abhyankar   PetscFunctionBegin;
28069e15a41SShri Abhyankar   /* Create the factorization matrix F */
2819566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
2829566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(B, PETSC_DECIDE, PETSC_DECIDE, m, n));
2839566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy("klu", &((PetscObject)B)->type_name));
2849566063dSJacob Faibussowitsch   PetscCall(MatSetUp(B));
285569c4379SBarry Smith 
2864dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&lu));
28769e15a41SShri Abhyankar 
288569c4379SBarry Smith   B->data                  = lu;
289569c4379SBarry Smith   B->ops->getinfo          = MatGetInfo_External;
29069e15a41SShri Abhyankar   B->ops->lufactorsymbolic = MatLUFactorSymbolic_KLU;
29169e15a41SShri Abhyankar   B->ops->destroy          = MatDestroy_KLU;
29269e15a41SShri Abhyankar   B->ops->view             = MatView_KLU;
29369e15a41SShri Abhyankar 
2949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatFactorGetSolverType_C", MatFactorGetSolverType_seqaij_klu));
29569e15a41SShri Abhyankar 
29669e15a41SShri Abhyankar   B->factortype   = MAT_FACTOR_LU;
29769e15a41SShri Abhyankar   B->assembled    = PETSC_TRUE; /* required by -ksp_view */
29869e15a41SShri Abhyankar   B->preallocated = PETSC_TRUE;
29969e15a41SShri Abhyankar 
3009566063dSJacob Faibussowitsch   PetscCall(PetscFree(B->solvertype));
3019566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERKLU, &B->solvertype));
302f73b0415SBarry Smith   B->canuseordering = PETSC_TRUE;
3039566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&B->preferredordering[MAT_FACTOR_LU]));
30400c67f3bSHong Zhang 
30569e15a41SShri Abhyankar   /* initializations */
30669e15a41SShri Abhyankar   /* ------------------------------------------------*/
30769e15a41SShri Abhyankar   /* get the default control parameters */
30869e15a41SShri Abhyankar   status = klu_K_defaults(&lu->Common);
3095f80ce2aSJacob Faibussowitsch   PetscCheck(status > 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "KLU Initialization failed");
3106c4ed002SBarry Smith 
31169e15a41SShri Abhyankar   lu->Common.scale = 0; /* No row scaling */
31269e15a41SShri Abhyankar 
31326cc229bSBarry Smith   PetscOptionsBegin(PetscObjectComm((PetscObject)B), ((PetscObject)B)->prefix, "KLU Options", "Mat");
31469e15a41SShri Abhyankar   /* Partial pivoting tolerance */
3159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-mat_klu_pivot_tol", "Partial pivoting tolerance", "None", lu->Common.tol, &lu->Common.tol, NULL));
31669e15a41SShri Abhyankar   /* BTF pre-ordering */
3179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-mat_klu_use_btf", "Enable BTF preordering", "None", (PetscInt)lu->Common.btf, (PetscInt *)&lu->Common.btf, NULL));
31869e15a41SShri Abhyankar   /* Matrix reordering */
319dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-mat_klu_ordering", "Internal ordering method", "None", KluOrderingTypes, PETSC_STATIC_ARRAY_LENGTH(KluOrderingTypes), KluOrderingTypes[0], &idx, &flg));
3204ac6704cSBarry Smith   lu->Common.ordering = (int)idx;
32169e15a41SShri Abhyankar   /* Matrix row scaling */
3229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-mat_klu_row_scale", "Matrix row scaling", "None", scale, 3, scale[0], &idx, &flg));
323d0609cedSBarry Smith   PetscOptionsEnd();
32469e15a41SShri Abhyankar   *F = B;
325*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32669e15a41SShri Abhyankar }
327