xref: /petsc/src/mat/tests/ex30.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
1c4762a1bSJed Brown 
2c4762a1bSJed Brown static char help[] = "Tests ILU and ICC factorization with and without matrix ordering on seqaij format, and illustrates drawing of matrix sparsity structure with MatView().\n\
3c4762a1bSJed Brown   Input parameters are:\n\
4c4762a1bSJed Brown   -lf <level> : level of fill for ILU (default is 0)\n\
5c4762a1bSJed Brown   -lu : use full LU or Cholesky factorization\n\
6c4762a1bSJed Brown   -m <value>,-n <value> : grid dimensions\n\
7c4762a1bSJed Brown Note that most users should employ the KSP interface to the\n\
8c4762a1bSJed Brown linear solvers instead of using the factorization routines\n\
9c4762a1bSJed Brown directly.\n\n";
10c4762a1bSJed Brown 
11c4762a1bSJed Brown #include <petscmat.h>
12c4762a1bSJed Brown 
139371c9d4SSatish Balay int main(int argc, char **args) {
14c4762a1bSJed Brown   Mat           C, A;
15c4762a1bSJed Brown   PetscInt      i, j, m = 5, n = 5, Ii, J, lf = 0;
16c4762a1bSJed Brown   PetscBool     LU = PETSC_FALSE, CHOLESKY, TRIANGULAR = PETSC_FALSE, MATDSPL = PETSC_FALSE, flg, matordering;
17c4762a1bSJed Brown   PetscScalar   v;
18c4762a1bSJed Brown   IS            row, col;
19c4762a1bSJed Brown   PetscViewer   viewer1, viewer2;
20c4762a1bSJed Brown   MatFactorInfo info;
21c4762a1bSJed Brown   Vec           x, y, b, ytmp;
22c4762a1bSJed Brown   PetscReal     norm2, norm2_inplace, tol = 100. * PETSC_MACHINE_EPSILON;
23c4762a1bSJed Brown   PetscRandom   rdm;
24c4762a1bSJed Brown   PetscMPIInt   size;
25c4762a1bSJed Brown 
26327415f7SBarry Smith   PetscFunctionBeginUser;
279566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &args, (char *)0, help));
289566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
29be096a46SBarry Smith   PetscCheck(size == 1, PETSC_COMM_WORLD, PETSC_ERR_WRONG_MPI_SIZE, "This is a uniprocessor example only!");
309566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-m", &m, NULL));
319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-n", &n, NULL));
329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-lf", &lf, NULL));
33c4762a1bSJed Brown 
349566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawOpen(PETSC_COMM_SELF, 0, 0, 0, 0, 400, 400, &viewer1));
359566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawOpen(PETSC_COMM_SELF, 0, 0, 400, 0, 400, 400, &viewer2));
36c4762a1bSJed Brown 
379566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, &C));
389566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m * n, m * n, m * n, m * n));
399566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(C));
409566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
41c4762a1bSJed Brown 
42c4762a1bSJed Brown   /* Create matrix C in seqaij format and sC in seqsbaij. (This is five-point stencil with some extra elements) */
43c4762a1bSJed Brown   for (i = 0; i < m; i++) {
44c4762a1bSJed Brown     for (j = 0; j < n; j++) {
459371c9d4SSatish Balay       v  = -1.0;
469371c9d4SSatish Balay       Ii = j + n * i;
479371c9d4SSatish Balay       J  = Ii - n;
489371c9d4SSatish Balay       if (J >= 0) PetscCall(MatSetValues(C, 1, &Ii, 1, &J, &v, INSERT_VALUES));
499371c9d4SSatish Balay       J = Ii + n;
509371c9d4SSatish Balay       if (J < m * n) PetscCall(MatSetValues(C, 1, &Ii, 1, &J, &v, INSERT_VALUES));
519371c9d4SSatish Balay       J = Ii - 1;
529371c9d4SSatish Balay       if (J >= 0) PetscCall(MatSetValues(C, 1, &Ii, 1, &J, &v, INSERT_VALUES));
539371c9d4SSatish Balay       J = Ii + 1;
549371c9d4SSatish Balay       if (J < m * n) PetscCall(MatSetValues(C, 1, &Ii, 1, &J, &v, INSERT_VALUES));
559371c9d4SSatish Balay       v = 4.0;
569371c9d4SSatish Balay       PetscCall(MatSetValues(C, 1, &Ii, 1, &Ii, &v, INSERT_VALUES));
57c4762a1bSJed Brown     }
58c4762a1bSJed Brown   }
599566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
609566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
61c4762a1bSJed Brown 
629566063dSJacob Faibussowitsch   PetscCall(MatIsSymmetric(C, 0.0, &flg));
6328b400f6SJacob Faibussowitsch   PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "C is non-symmetric");
64c4762a1bSJed Brown 
65c4762a1bSJed Brown   /* Create vectors for error checking */
669566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(C, &x, &b));
679566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &y));
689566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &ytmp));
699566063dSJacob Faibussowitsch   PetscCall(PetscRandomCreate(PETSC_COMM_SELF, &rdm));
709566063dSJacob Faibussowitsch   PetscCall(PetscRandomSetFromOptions(rdm));
719566063dSJacob Faibussowitsch   PetscCall(VecSetRandom(x, rdm));
729566063dSJacob Faibussowitsch   PetscCall(MatMult(C, x, b));
73c4762a1bSJed Brown 
749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, "-mat_ordering", &matordering));
75c4762a1bSJed Brown   if (matordering) {
769566063dSJacob Faibussowitsch     PetscCall(MatGetOrdering(C, MATORDERINGRCM, &row, &col));
77c4762a1bSJed Brown   } else {
789566063dSJacob Faibussowitsch     PetscCall(MatGetOrdering(C, MATORDERINGNATURAL, &row, &col));
79c4762a1bSJed Brown   }
80c4762a1bSJed Brown 
819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, "-display_matrices", &MATDSPL));
82c4762a1bSJed Brown   if (MATDSPL) {
83c4762a1bSJed Brown     printf("original matrix:\n");
849566063dSJacob Faibussowitsch     PetscCall(PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_ASCII_INFO));
859566063dSJacob Faibussowitsch     PetscCall(MatView(C, PETSC_VIEWER_STDOUT_SELF));
869566063dSJacob Faibussowitsch     PetscCall(PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF));
879566063dSJacob Faibussowitsch     PetscCall(MatView(C, PETSC_VIEWER_STDOUT_SELF));
889566063dSJacob Faibussowitsch     PetscCall(MatView(C, viewer1));
89c4762a1bSJed Brown   }
90c4762a1bSJed Brown 
91c4762a1bSJed Brown   /* Compute LU or ILU factor A */
929566063dSJacob Faibussowitsch   PetscCall(MatFactorInfoInitialize(&info));
93c4762a1bSJed Brown 
94c4762a1bSJed Brown   info.fill          = 1.0;
95c4762a1bSJed Brown   info.diagonal_fill = 0;
96c4762a1bSJed Brown   info.zeropivot     = 0.0;
97c4762a1bSJed Brown 
989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, "-lu", &LU));
99c4762a1bSJed Brown   if (LU) {
100c4762a1bSJed Brown     printf("Test LU...\n");
1019566063dSJacob Faibussowitsch     PetscCall(MatGetFactor(C, MATSOLVERPETSC, MAT_FACTOR_LU, &A));
1029566063dSJacob Faibussowitsch     PetscCall(MatLUFactorSymbolic(A, C, row, col, &info));
103c4762a1bSJed Brown   } else {
104c4762a1bSJed Brown     printf("Test ILU...\n");
105c4762a1bSJed Brown     info.levels = lf;
106c4762a1bSJed Brown 
1079566063dSJacob Faibussowitsch     PetscCall(MatGetFactor(C, MATSOLVERPETSC, MAT_FACTOR_ILU, &A));
1089566063dSJacob Faibussowitsch     PetscCall(MatILUFactorSymbolic(A, C, row, col, &info));
109c4762a1bSJed Brown   }
1109566063dSJacob Faibussowitsch   PetscCall(MatLUFactorNumeric(A, C, &info));
111c4762a1bSJed Brown 
112c4762a1bSJed Brown   /* Solve A*y = b, then check the error */
1139566063dSJacob Faibussowitsch   PetscCall(MatSolve(A, b, y));
1149566063dSJacob Faibussowitsch   PetscCall(VecAXPY(y, -1.0, x));
1159566063dSJacob Faibussowitsch   PetscCall(VecNorm(y, NORM_2, &norm2));
1169566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A));
117c4762a1bSJed Brown 
118c4762a1bSJed Brown   /* Test in-place ILU(0) and compare it with the out-place ILU(0) */
119c4762a1bSJed Brown   if (!LU && lf == 0) {
1209566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(C, MAT_COPY_VALUES, &A));
1219566063dSJacob Faibussowitsch     PetscCall(MatILUFactor(A, row, col, &info));
122c4762a1bSJed Brown     /*
123c4762a1bSJed Brown     printf("In-place factored matrix:\n");
1249566063dSJacob Faibussowitsch     PetscCall(MatView(C,PETSC_VIEWER_STDOUT_SELF));
125c4762a1bSJed Brown     */
1269566063dSJacob Faibussowitsch     PetscCall(MatSolve(A, b, y));
1279566063dSJacob Faibussowitsch     PetscCall(VecAXPY(y, -1.0, x));
1289566063dSJacob Faibussowitsch     PetscCall(VecNorm(y, NORM_2, &norm2_inplace));
12908401ef6SPierre Jolivet     PetscCheck(PetscAbs(norm2 - norm2_inplace) <= tol, PETSC_COMM_SELF, PETSC_ERR_PLIB, "ILU(0) %g and in-place ILU(0) %g give different residuals", (double)norm2, (double)norm2_inplace);
1309566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
131c4762a1bSJed Brown   }
132c4762a1bSJed Brown 
133c4762a1bSJed Brown   /* Test Cholesky and ICC on seqaij matrix with matrix reordering on aij matrix C */
134c4762a1bSJed Brown   CHOLESKY = LU;
135c4762a1bSJed Brown   if (CHOLESKY) {
136c4762a1bSJed Brown     printf("Test Cholesky...\n");
137c4762a1bSJed Brown     lf = -1;
1389566063dSJacob Faibussowitsch     PetscCall(MatGetFactor(C, MATSOLVERPETSC, MAT_FACTOR_CHOLESKY, &A));
1399566063dSJacob Faibussowitsch     PetscCall(MatCholeskyFactorSymbolic(A, C, row, &info));
140c4762a1bSJed Brown   } else {
141c4762a1bSJed Brown     printf("Test ICC...\n");
142c4762a1bSJed Brown     info.levels        = lf;
143c4762a1bSJed Brown     info.fill          = 1.0;
144c4762a1bSJed Brown     info.diagonal_fill = 0;
145c4762a1bSJed Brown     info.zeropivot     = 0.0;
146c4762a1bSJed Brown 
1479566063dSJacob Faibussowitsch     PetscCall(MatGetFactor(C, MATSOLVERPETSC, MAT_FACTOR_ICC, &A));
1489566063dSJacob Faibussowitsch     PetscCall(MatICCFactorSymbolic(A, C, row, &info));
149c4762a1bSJed Brown   }
1509566063dSJacob Faibussowitsch   PetscCall(MatCholeskyFactorNumeric(A, C, &info));
151c4762a1bSJed Brown 
152c4762a1bSJed Brown   /* test MatForwardSolve() and MatBackwardSolve() with matrix reordering on aij matrix C */
153c4762a1bSJed Brown   if (lf == -1) {
1549566063dSJacob Faibussowitsch     PetscCall(PetscOptionsHasName(NULL, NULL, "-triangular_solve", &TRIANGULAR));
155c4762a1bSJed Brown     if (TRIANGULAR) {
156c4762a1bSJed Brown       printf("Test MatForwardSolve...\n");
1579566063dSJacob Faibussowitsch       PetscCall(MatForwardSolve(A, b, ytmp));
158c4762a1bSJed Brown       printf("Test MatBackwardSolve...\n");
1599566063dSJacob Faibussowitsch       PetscCall(MatBackwardSolve(A, ytmp, y));
1609566063dSJacob Faibussowitsch       PetscCall(VecAXPY(y, -1.0, x));
1619566063dSJacob Faibussowitsch       PetscCall(VecNorm(y, NORM_2, &norm2));
162*48a46eb9SPierre Jolivet       if (norm2 > tol) PetscCall(PetscPrintf(PETSC_COMM_SELF, "MatForwardSolve and BackwardSolve: Norm of error=%g\n", (double)norm2));
163c4762a1bSJed Brown     }
164c4762a1bSJed Brown   }
165c4762a1bSJed Brown 
1669566063dSJacob Faibussowitsch   PetscCall(MatSolve(A, b, y));
1679566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A));
1689566063dSJacob Faibussowitsch   PetscCall(VecAXPY(y, -1.0, x));
1699566063dSJacob Faibussowitsch   PetscCall(VecNorm(y, NORM_2, &norm2));
170*48a46eb9SPierre Jolivet   if (lf == -1 && norm2 > tol) PetscCall(PetscPrintf(PETSC_COMM_SELF, " reordered SEQAIJ:   Cholesky/ICC levels %" PetscInt_FMT ", residual %g\n", lf, (double)norm2));
171c4762a1bSJed Brown 
172c4762a1bSJed Brown   /* Test in-place ICC(0) and compare it with the out-place ICC(0) */
173c4762a1bSJed Brown   if (!CHOLESKY && lf == 0 && !matordering) {
1749566063dSJacob Faibussowitsch     PetscCall(MatConvert(C, MATSBAIJ, MAT_INITIAL_MATRIX, &A));
1759566063dSJacob Faibussowitsch     PetscCall(MatICCFactor(A, row, &info));
176c4762a1bSJed Brown     /*
177c4762a1bSJed Brown     printf("In-place factored matrix:\n");
1789566063dSJacob Faibussowitsch     PetscCall(MatView(A,PETSC_VIEWER_STDOUT_SELF));
179c4762a1bSJed Brown     */
1809566063dSJacob Faibussowitsch     PetscCall(MatSolve(A, b, y));
1819566063dSJacob Faibussowitsch     PetscCall(VecAXPY(y, -1.0, x));
1829566063dSJacob Faibussowitsch     PetscCall(VecNorm(y, NORM_2, &norm2_inplace));
18308401ef6SPierre Jolivet     PetscCheck(PetscAbs(norm2 - norm2_inplace) <= tol, PETSC_COMM_SELF, PETSC_ERR_PLIB, "ICC(0) %g and in-place ICC(0) %g give different residuals", (double)norm2, (double)norm2_inplace);
1849566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
185c4762a1bSJed Brown   }
186c4762a1bSJed Brown 
187c4762a1bSJed Brown   /* Free data structures */
1889566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&row));
1899566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&col));
1909566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&C));
1919566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&viewer1));
1929566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&viewer2));
1939566063dSJacob Faibussowitsch   PetscCall(PetscRandomDestroy(&rdm));
1949566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
1959566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y));
1969566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ytmp));
1979566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&b));
1989566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
199b122ec5aSJacob Faibussowitsch   return 0;
200c4762a1bSJed Brown }
201c4762a1bSJed Brown 
202c4762a1bSJed Brown /*TEST
203c4762a1bSJed Brown 
204c4762a1bSJed Brown    test:
205c4762a1bSJed Brown       args: -mat_ordering -display_matrices -nox
2068cc725e6SPierre Jolivet       filter: grep -v " MPI process"
207c4762a1bSJed Brown 
208c4762a1bSJed Brown    test:
209c4762a1bSJed Brown       suffix: 2
210c4762a1bSJed Brown       args: -mat_ordering -display_matrices -nox -lu
211c4762a1bSJed Brown 
212c4762a1bSJed Brown    test:
213c4762a1bSJed Brown       suffix: 3
214c4762a1bSJed Brown       args: -mat_ordering -lu -triangular_solve
215c4762a1bSJed Brown 
216c4762a1bSJed Brown    test:
217c4762a1bSJed Brown       suffix: 4
218c4762a1bSJed Brown 
219c4762a1bSJed Brown    test:
220c4762a1bSJed Brown       suffix: 5
221c4762a1bSJed Brown       args: -lu
222c4762a1bSJed Brown 
223c4762a1bSJed Brown    test:
224c4762a1bSJed Brown       suffix: 6
225c4762a1bSJed Brown       args: -lu -triangular_solve
226c4762a1bSJed Brown       output_file: output/ex30_3.out
227c4762a1bSJed Brown 
228c4762a1bSJed Brown TEST*/
229