xref: /petsc/src/mat/tests/ex115.c (revision 40018c87c17b6c242a12cd0fdaf8119b9c68bd57)
1c4762a1bSJed Brown 
2c4762a1bSJed Brown static char help[] = "Tests MatHYPRE\n";
3c4762a1bSJed Brown 
4c4762a1bSJed Brown #include <petscmathypre.h>
5c4762a1bSJed Brown 
6d71ae5a4SJacob Faibussowitsch int main(int argc, char **args)
7d71ae5a4SJacob Faibussowitsch {
8c4762a1bSJed Brown   Mat                 A, B, C, D;
9*40018c87Sstefanozampini   Mat                 pAB, CD;
10c4762a1bSJed Brown   hypre_ParCSRMatrix *parcsr;
11c4762a1bSJed Brown   PetscReal           err;
12c4762a1bSJed Brown   PetscInt            i, j, N = 6, M = 6;
13c4762a1bSJed Brown   PetscBool           flg, testptap = PETSC_TRUE, testmatmatmult = PETSC_TRUE;
14c4762a1bSJed Brown   PetscReal           norm;
15c4762a1bSJed Brown   char                file[256];
16*40018c87Sstefanozampini   MatType             mtype = MATAIJ;
17c4762a1bSJed Brown 
18327415f7SBarry Smith   PetscFunctionBeginUser;
199566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &args, (char *)0, help));
209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetString(NULL, NULL, "-f", file, sizeof(file), &flg));
21c4762a1bSJed Brown #if defined(PETSC_USE_COMPLEX)
22c4762a1bSJed Brown   testptap       = PETSC_FALSE;
23c4762a1bSJed Brown   testmatmatmult = PETSC_FALSE;
249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInsertString(NULL, "-options_left 0"));
25c4762a1bSJed Brown #endif
269566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-ptap", &testptap, NULL));
279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-matmatmult", &testmatmatmult, NULL));
289566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_WORLD, &A));
29*40018c87Sstefanozampini #if PetscDefined(HAVE_HYPRE_DEVICE)
30*40018c87Sstefanozampini   #if PetscDefined(HAVE_HIP)
31*40018c87Sstefanozampini   mtype = MATAIJHIPSPARSE;
32*40018c87Sstefanozampini   #elif PetscDefined(HAVE_CUDA)
33*40018c87Sstefanozampini   mtype = MATAIJCUSPARSE;
34*40018c87Sstefanozampini   #endif
35*40018c87Sstefanozampini #endif
36*40018c87Sstefanozampini 
37c4762a1bSJed Brown   if (!flg) { /* Create a matrix and test MatSetValues */
38c4762a1bSJed Brown     PetscMPIInt size;
39c4762a1bSJed Brown 
409566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
419566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetInt(NULL, NULL, "-M", &M, NULL));
429566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetInt(NULL, NULL, "-N", &N, NULL));
439566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(A, PETSC_DECIDE, PETSC_DECIDE, M, N));
44*40018c87Sstefanozampini     PetscCall(MatSetType(A, mtype));
459566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(A, 9, NULL));
469566063dSJacob Faibussowitsch     PetscCall(MatMPIAIJSetPreallocation(A, 9, NULL, 9, NULL));
479566063dSJacob Faibussowitsch     PetscCall(MatCreate(PETSC_COMM_WORLD, &B));
489566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, PETSC_DECIDE, PETSC_DECIDE, M, N));
49*40018c87Sstefanozampini #if PetscDefined(HAVE_HYPRE_DEVICE)
50*40018c87Sstefanozampini     PetscCall(MatSetType(B, mtype));
51*40018c87Sstefanozampini #else
529566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATHYPRE));
53*40018c87Sstefanozampini #endif
54*40018c87Sstefanozampini     PetscCall(MatSeqAIJSetPreallocation(B, 9, NULL));
55*40018c87Sstefanozampini     PetscCall(MatMPIAIJSetPreallocation(B, 9, NULL, 9, NULL));
56c4762a1bSJed Brown     if (M == N) {
579566063dSJacob Faibussowitsch       PetscCall(MatHYPRESetPreallocation(B, 9, NULL, 9, NULL));
58c4762a1bSJed Brown     } else {
599566063dSJacob Faibussowitsch       PetscCall(MatHYPRESetPreallocation(B, 6, NULL, 6, NULL));
60c4762a1bSJed Brown     }
61c4762a1bSJed Brown     if (M == N) {
62c4762a1bSJed Brown       for (i = 0; i < M; i++) {
63c4762a1bSJed Brown         PetscInt    cols[] = {0, 1, 2, 3, 4, 5};
64c4762a1bSJed Brown         PetscScalar vals[] = {0, 1. / size, 2. / size, 3. / size, 4. / size, 5. / size};
65c4762a1bSJed Brown         for (j = i - 2; j < i + 1; j++) {
66c4762a1bSJed Brown           if (j >= N) {
679566063dSJacob Faibussowitsch             PetscCall(MatSetValue(A, i, N - 1, (1. * j * N + i) / (3. * N * size), ADD_VALUES));
689566063dSJacob Faibussowitsch             PetscCall(MatSetValue(B, i, N - 1, (1. * j * N + i) / (3. * N * size), ADD_VALUES));
69c4762a1bSJed Brown           } else if (i > j) {
709566063dSJacob Faibussowitsch             PetscCall(MatSetValue(A, i, PetscMin(j, N - 1), (1. * j * N + i) / (2. * N * size), ADD_VALUES));
719566063dSJacob Faibussowitsch             PetscCall(MatSetValue(B, i, PetscMin(j, N - 1), (1. * j * N + i) / (2. * N * size), ADD_VALUES));
72c4762a1bSJed Brown           } else {
739566063dSJacob Faibussowitsch             PetscCall(MatSetValue(A, i, PetscMin(j, N - 1), -1. - (1. * j * N + i) / (4. * N * size), ADD_VALUES));
749566063dSJacob Faibussowitsch             PetscCall(MatSetValue(B, i, PetscMin(j, N - 1), -1. - (1. * j * N + i) / (4. * N * size), ADD_VALUES));
75c4762a1bSJed Brown           }
76c4762a1bSJed Brown         }
779566063dSJacob Faibussowitsch         PetscCall(MatSetValues(A, 1, &i, PetscMin(6, N), cols, vals, ADD_VALUES));
789566063dSJacob Faibussowitsch         PetscCall(MatSetValues(B, 1, &i, PetscMin(6, N), cols, vals, ADD_VALUES));
79c4762a1bSJed Brown       }
80c4762a1bSJed Brown     } else {
81c4762a1bSJed Brown       PetscInt  rows[2];
82c4762a1bSJed Brown       PetscBool test_offproc = PETSC_FALSE;
83c4762a1bSJed Brown 
849566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_offproc", &test_offproc, NULL));
85c4762a1bSJed Brown       if (test_offproc) {
86c4762a1bSJed Brown         const PetscInt *ranges;
87c4762a1bSJed Brown         PetscMPIInt     rank;
88c4762a1bSJed Brown 
899566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
909566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRanges(A, &ranges));
91c4762a1bSJed Brown         rows[0] = ranges[(rank + 1) % size];
92c4762a1bSJed Brown         rows[1] = ranges[(rank + 1) % size + 1];
93c4762a1bSJed Brown       } else {
949566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRange(A, &rows[0], &rows[1]));
95c4762a1bSJed Brown       }
96c4762a1bSJed Brown       for (i = rows[0]; i < rows[1]; i++) {
97c4762a1bSJed Brown         PetscInt    cols[] = {0, 1, 2, 3, 4, 5};
98c4762a1bSJed Brown         PetscScalar vals[] = {-1, 1, -2, 2, -3, 3};
99c4762a1bSJed Brown 
1009566063dSJacob Faibussowitsch         PetscCall(MatSetValues(A, 1, &i, PetscMin(6, N), cols, vals, INSERT_VALUES));
1019566063dSJacob Faibussowitsch         PetscCall(MatSetValues(B, 1, &i, PetscMin(6, N), cols, vals, INSERT_VALUES));
102c4762a1bSJed Brown       }
103c4762a1bSJed Brown     }
104c4762a1bSJed Brown     /* MAT_FLUSH_ASSEMBLY currently not supported */
1059566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
1069566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
1079566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
1089566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
109*40018c87Sstefanozampini #if PetscDefined(HAVE_HYPRE_DEVICE)
110*40018c87Sstefanozampini     PetscCall(MatConvert(B, MATHYPRE, MAT_INPLACE_MATRIX, &B));
111*40018c87Sstefanozampini #endif
112c4762a1bSJed Brown 
113c4762a1bSJed Brown #if defined(PETSC_USE_COMPLEX)
114c4762a1bSJed Brown     /* make the matrix imaginary */
1159566063dSJacob Faibussowitsch     PetscCall(MatScale(A, PETSC_i));
1169566063dSJacob Faibussowitsch     PetscCall(MatScale(B, PETSC_i));
117c4762a1bSJed Brown #endif
118c4762a1bSJed Brown 
119*40018c87Sstefanozampini #if !PetscDefined(HAVE_HYPRE_DEVICE)
120c4762a1bSJed Brown     /* MatAXPY further exercises MatSetValues_HYPRE */
1219566063dSJacob Faibussowitsch     PetscCall(MatAXPY(B, -1., A, DIFFERENT_NONZERO_PATTERN));
1229566063dSJacob Faibussowitsch     PetscCall(MatConvert(B, MATMPIAIJ, MAT_INITIAL_MATRIX, &C));
1239566063dSJacob Faibussowitsch     PetscCall(MatNorm(C, NORM_INFINITY, &err));
12454c59aa7SJacob Faibussowitsch     PetscCheck(err <= PETSC_SMALL, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatSetValues %g", err);
1259566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&C));
126*40018c87Sstefanozampini #endif
127*40018c87Sstefanozampini     PetscCall(MatDestroy(&B));
128c4762a1bSJed Brown   } else {
129c4762a1bSJed Brown     PetscViewer viewer;
130c4762a1bSJed Brown 
1319566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, file, FILE_MODE_READ, &viewer));
1329566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(A));
1339566063dSJacob Faibussowitsch     PetscCall(MatLoad(A, viewer));
134*40018c87Sstefanozampini     PetscCall(MatSetType(A, mtype));
1359566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
1369566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A, &M, &N));
137c4762a1bSJed Brown   }
138c4762a1bSJed Brown 
139c4762a1bSJed Brown   /* check conversion routines */
140f9dc6c1fSStefano Zampini   PetscCall(MatViewFromOptions(A, NULL, "-view_A"));
1419566063dSJacob Faibussowitsch   PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &B));
142f9dc6c1fSStefano Zampini   PetscCall(MatViewFromOptions(B, NULL, "-view_convert"));
1439566063dSJacob Faibussowitsch   PetscCall(MatMultEqual(B, A, 4, &flg));
144f9dc6c1fSStefano Zampini   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat HYPRE init");
145f9dc6c1fSStefano Zampini   PetscCall(MatConvert(A, MATHYPRE, MAT_REUSE_MATRIX, &B));
146f9dc6c1fSStefano Zampini   PetscCall(MatViewFromOptions(B, NULL, "-view_convert"));
147f9dc6c1fSStefano Zampini   PetscCall(MatMultEqual(B, A, 4, &flg));
148f9dc6c1fSStefano Zampini   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat HYPRE reuse");
1499566063dSJacob Faibussowitsch   PetscCall(MatConvert(B, MATIS, MAT_INITIAL_MATRIX, &D));
1509566063dSJacob Faibussowitsch   PetscCall(MatConvert(B, MATIS, MAT_REUSE_MATRIX, &D));
1519566063dSJacob Faibussowitsch   PetscCall(MatMultEqual(D, A, 4, &flg));
15254c59aa7SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat IS");
1539566063dSJacob Faibussowitsch   PetscCall(MatConvert(B, MATAIJ, MAT_INITIAL_MATRIX, &C));
1549566063dSJacob Faibussowitsch   PetscCall(MatConvert(B, MATAIJ, MAT_REUSE_MATRIX, &C));
1559566063dSJacob Faibussowitsch   PetscCall(MatMultEqual(C, A, 4, &flg));
15654c59aa7SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat AIJ");
1579566063dSJacob Faibussowitsch   PetscCall(MatAXPY(C, -1., A, SAME_NONZERO_PATTERN));
1589566063dSJacob Faibussowitsch   PetscCall(MatNorm(C, NORM_INFINITY, &err));
15954c59aa7SJacob Faibussowitsch   PetscCheck(err <= PETSC_SMALL, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat AIJ %g", err);
1609566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&C));
1619566063dSJacob Faibussowitsch   PetscCall(MatConvert(D, MATAIJ, MAT_INITIAL_MATRIX, &C));
1629566063dSJacob Faibussowitsch   PetscCall(MatAXPY(C, -1., A, SAME_NONZERO_PATTERN));
1639566063dSJacob Faibussowitsch   PetscCall(MatNorm(C, NORM_INFINITY, &err));
16454c59aa7SJacob Faibussowitsch   PetscCheck(err <= PETSC_SMALL, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat IS %g", err);
1659566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&C));
1669566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&D));
167c4762a1bSJed Brown 
168c4762a1bSJed Brown   /* check MatCreateFromParCSR */
1699566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR(B, &parcsr));
1709566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(parcsr, MATAIJ, PETSC_COPY_VALUES, &D));
1719566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&D));
1729566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(parcsr, MATHYPRE, PETSC_USE_POINTER, &C));
173c4762a1bSJed Brown 
174c4762a1bSJed Brown   /* check MatMult operations */
1759566063dSJacob Faibussowitsch   PetscCall(MatMultEqual(A, B, 4, &flg));
17654c59aa7SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMult B");
1779566063dSJacob Faibussowitsch   PetscCall(MatMultEqual(A, C, 4, &flg));
17854c59aa7SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMult C");
1799566063dSJacob Faibussowitsch   PetscCall(MatMultAddEqual(A, B, 4, &flg));
18054c59aa7SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultAdd B");
1819566063dSJacob Faibussowitsch   PetscCall(MatMultAddEqual(A, C, 4, &flg));
18254c59aa7SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultAdd C");
1839566063dSJacob Faibussowitsch   PetscCall(MatMultTransposeEqual(A, B, 4, &flg));
18454c59aa7SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultTranspose B");
1859566063dSJacob Faibussowitsch   PetscCall(MatMultTransposeEqual(A, C, 4, &flg));
18654c59aa7SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultTranspose C");
1879566063dSJacob Faibussowitsch   PetscCall(MatMultTransposeAddEqual(A, B, 4, &flg));
18854c59aa7SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultTransposeAdd B");
1899566063dSJacob Faibussowitsch   PetscCall(MatMultTransposeAddEqual(A, C, 4, &flg));
19054c59aa7SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultTransposeAdd C");
191c4762a1bSJed Brown 
192c4762a1bSJed Brown   /* check PtAP */
193c4762a1bSJed Brown   if (testptap && M == N) {
194c4762a1bSJed Brown     Mat pP, hP;
195c4762a1bSJed Brown 
196c4762a1bSJed Brown     /* PETSc MatPtAP -> output is a MatAIJ
197c4762a1bSJed Brown        It uses HYPRE functions when -matptap_via hypre is specified at command line */
1989566063dSJacob Faibussowitsch     PetscCall(MatPtAP(A, A, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &pP));
1999566063dSJacob Faibussowitsch     PetscCall(MatPtAP(A, A, MAT_REUSE_MATRIX, PETSC_DEFAULT, &pP));
2009566063dSJacob Faibussowitsch     PetscCall(MatNorm(pP, NORM_INFINITY, &norm));
2019566063dSJacob Faibussowitsch     PetscCall(MatPtAPMultEqual(A, A, pP, 10, &flg));
20254c59aa7SJacob Faibussowitsch     PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatPtAP_MatAIJ");
203c4762a1bSJed Brown 
204c4762a1bSJed Brown     /* MatPtAP_HYPRE_HYPRE -> output is a MatHYPRE */
2059566063dSJacob Faibussowitsch     PetscCall(MatPtAP(C, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &hP));
2069566063dSJacob Faibussowitsch     PetscCall(MatPtAP(C, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &hP));
2079566063dSJacob Faibussowitsch     PetscCall(MatPtAPMultEqual(C, B, hP, 10, &flg));
20854c59aa7SJacob Faibussowitsch     PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatPtAP_HYPRE_HYPRE");
209c20d7725SJed Brown 
210c20d7725SJed Brown     /* Test MatAXPY_Basic() */
211*40018c87Sstefanozampini #if !PetscDefined(HAVE_HYPRE_DEVICE)
2129566063dSJacob Faibussowitsch     PetscCall(MatAXPY(hP, -1., pP, DIFFERENT_NONZERO_PATTERN));
2139566063dSJacob Faibussowitsch     PetscCall(MatHasOperation(hP, MATOP_NORM, &flg));
214c4762a1bSJed Brown     if (!flg) { /* TODO add MatNorm_HYPRE */
2159566063dSJacob Faibussowitsch       PetscCall(MatConvert(hP, MATAIJ, MAT_INPLACE_MATRIX, &hP));
216c4762a1bSJed Brown     }
2179566063dSJacob Faibussowitsch     PetscCall(MatNorm(hP, NORM_INFINITY, &err));
218e00437b9SBarry Smith     PetscCheck(err / norm <= PETSC_SMALL, PetscObjectComm((PetscObject)hP), PETSC_ERR_PLIB, "Error MatPtAP %g %g", err, norm);
219*40018c87Sstefanozampini #endif
2209566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pP));
2219566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&hP));
222c4762a1bSJed Brown 
223c4762a1bSJed Brown     /* MatPtAP_AIJ_HYPRE -> output can be decided at runtime with -matptap_hypre_outtype */
224*40018c87Sstefanozampini #if !PetscDefined(HAVE_HYPRE_DEVICE)
2259566063dSJacob Faibussowitsch     PetscCall(MatPtAP(A, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &hP));
2269566063dSJacob Faibussowitsch     PetscCall(MatPtAP(A, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &hP));
2279566063dSJacob Faibussowitsch     PetscCall(MatPtAPMultEqual(A, B, hP, 10, &flg));
22854c59aa7SJacob Faibussowitsch     PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatPtAP_AIJ_HYPRE");
2299566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&hP));
230*40018c87Sstefanozampini #endif
231c4762a1bSJed Brown   }
2329566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&C));
2339566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&B));
234c4762a1bSJed Brown 
235c4762a1bSJed Brown   /* check MatMatMult */
236c4762a1bSJed Brown   if (testmatmatmult) {
2379566063dSJacob Faibussowitsch     PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &B));
2389566063dSJacob Faibussowitsch     PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &C));
2399566063dSJacob Faibussowitsch     PetscCall(MatConvert(B, MATHYPRE, MAT_INITIAL_MATRIX, &D));
240c4762a1bSJed Brown 
241c4762a1bSJed Brown     /* PETSc MatMatMult -> output is a MatAIJ
242c4762a1bSJed Brown        It uses HYPRE functions when -matmatmult_via hypre is specified at command line */
2439566063dSJacob Faibussowitsch     PetscCall(MatMatMult(A, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &pAB));
2449566063dSJacob Faibussowitsch     PetscCall(MatMatMult(A, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &pAB));
2459566063dSJacob Faibussowitsch     PetscCall(MatNorm(pAB, NORM_INFINITY, &norm));
2469566063dSJacob Faibussowitsch     PetscCall(MatMatMultEqual(A, B, pAB, 10, &flg));
24754c59aa7SJacob Faibussowitsch     PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatMatMult_AIJ_AIJ");
248c4762a1bSJed Brown 
249c4762a1bSJed Brown     /* MatMatMult_HYPRE_HYPRE -> output is a MatHYPRE */
2509566063dSJacob Faibussowitsch     PetscCall(MatMatMult(C, D, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &CD));
2519566063dSJacob Faibussowitsch     PetscCall(MatMatMult(C, D, MAT_REUSE_MATRIX, PETSC_DEFAULT, &CD));
2529566063dSJacob Faibussowitsch     PetscCall(MatMatMultEqual(C, D, CD, 10, &flg));
25354c59aa7SJacob Faibussowitsch     PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatMatMult_HYPRE_HYPRE");
254c20d7725SJed Brown 
255c20d7725SJed Brown     /* Test MatAXPY_Basic() */
256*40018c87Sstefanozampini #if !PetscDefined(HAVE_HYPRE_DEVICE)
2579566063dSJacob Faibussowitsch     PetscCall(MatAXPY(CD, -1., pAB, DIFFERENT_NONZERO_PATTERN));
258c20d7725SJed Brown 
2599566063dSJacob Faibussowitsch     PetscCall(MatHasOperation(CD, MATOP_NORM, &flg));
260c4762a1bSJed Brown     if (!flg) { /* TODO add MatNorm_HYPRE */
2619566063dSJacob Faibussowitsch       PetscCall(MatConvert(CD, MATAIJ, MAT_INPLACE_MATRIX, &CD));
262c4762a1bSJed Brown     }
2639566063dSJacob Faibussowitsch     PetscCall(MatNorm(CD, NORM_INFINITY, &err));
26454c59aa7SJacob Faibussowitsch     PetscCheck((err / norm) <= PETSC_SMALL, PetscObjectComm((PetscObject)CD), PETSC_ERR_PLIB, "Error MatMatMult %g %g", err, norm);
265*40018c87Sstefanozampini #endif
266c20d7725SJed Brown 
2679566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&C));
2689566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
2699566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pAB));
2709566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&CD));
271c4762a1bSJed Brown 
272c4762a1bSJed Brown     /* When configured with HYPRE, MatMatMatMult is available for the triplet transpose(aij)-aij-aij */
273*40018c87Sstefanozampini #if !PetscDefined(HAVE_HYPRE_DEVICE)
274*40018c87Sstefanozampini     Mat CAB;
2759566063dSJacob Faibussowitsch     PetscCall(MatCreateTranspose(A, &C));
2769566063dSJacob Faibussowitsch     PetscCall(MatMatMatMult(C, A, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &CAB));
2779566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&C));
2789566063dSJacob Faibussowitsch     PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &C));
2799566063dSJacob Faibussowitsch     PetscCall(MatMatMult(C, A, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &D));
2809566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&C));
2819566063dSJacob Faibussowitsch     PetscCall(MatMatMult(D, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &C));
2829566063dSJacob Faibussowitsch     PetscCall(MatNorm(C, NORM_INFINITY, &norm));
2839566063dSJacob Faibussowitsch     PetscCall(MatAXPY(C, -1., CAB, DIFFERENT_NONZERO_PATTERN));
2849566063dSJacob Faibussowitsch     PetscCall(MatNorm(C, NORM_INFINITY, &err));
28554c59aa7SJacob Faibussowitsch     PetscCheck((err / norm) <= PETSC_SMALL, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMatMatMult %g %g", err, norm);
2869566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&C));
2879566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
2889566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&CAB));
289*40018c87Sstefanozampini #endif
2909566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
291c4762a1bSJed Brown   }
292c4762a1bSJed Brown 
293c4762a1bSJed Brown   /* Check MatView */
2949566063dSJacob Faibussowitsch   PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &B));
2959566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(B, NULL, "-view_B"));
296c4762a1bSJed Brown 
297c4762a1bSJed Brown   /* Check MatDuplicate/MatCopy */
298c4762a1bSJed Brown   for (j = 0; j < 3; j++) {
299c4762a1bSJed Brown     MatDuplicateOption dop;
300c4762a1bSJed Brown 
301c4762a1bSJed Brown     dop = MAT_COPY_VALUES;
302c4762a1bSJed Brown     if (j == 1) dop = MAT_DO_NOT_COPY_VALUES;
303c4762a1bSJed Brown     if (j == 2) dop = MAT_SHARE_NONZERO_PATTERN;
304c4762a1bSJed Brown 
305c4762a1bSJed Brown     for (i = 0; i < 3; i++) {
306c4762a1bSJed Brown       MatStructure str;
307c4762a1bSJed Brown 
3089566063dSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Dup/Copy tests: %" PetscInt_FMT " %" PetscInt_FMT "\n", j, i));
309c4762a1bSJed Brown 
310c4762a1bSJed Brown       str = DIFFERENT_NONZERO_PATTERN;
311c4762a1bSJed Brown       if (i == 1) str = SAME_NONZERO_PATTERN;
312c4762a1bSJed Brown       if (i == 2) str = SUBSET_NONZERO_PATTERN;
313c4762a1bSJed Brown 
3149566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(A, dop, &C));
3159566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, dop, &D));
316c4762a1bSJed Brown       if (dop != MAT_COPY_VALUES) {
3179566063dSJacob Faibussowitsch         PetscCall(MatCopy(A, C, str));
3189566063dSJacob Faibussowitsch         PetscCall(MatCopy(B, D, str));
319c4762a1bSJed Brown       }
320c4762a1bSJed Brown       /* AXPY with AIJ and HYPRE */
321*40018c87Sstefanozampini #if !PetscDefined(HAVE_HYPRE_DEVICE)
3229566063dSJacob Faibussowitsch       PetscCall(MatAXPY(C, -1.0, D, str));
3239566063dSJacob Faibussowitsch       PetscCall(MatNorm(C, NORM_INFINITY, &err));
324*40018c87Sstefanozampini #else
325*40018c87Sstefanozampini       err = 0.0;
326*40018c87Sstefanozampini #endif
327c4762a1bSJed Brown       if (err > PETSC_SMALL) {
3289566063dSJacob Faibussowitsch         PetscCall(MatViewFromOptions(A, NULL, "-view_duplicate_diff"));
3299566063dSJacob Faibussowitsch         PetscCall(MatViewFromOptions(B, NULL, "-view_duplicate_diff"));
3309566063dSJacob Faibussowitsch         PetscCall(MatViewFromOptions(C, NULL, "-view_duplicate_diff"));
331f9dc6c1fSStefano Zampini         PetscCall(MatViewFromOptions(D, NULL, "-view_duplicate_diff"));
33298921bdaSJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error test 1 MatDuplicate/MatCopy %g (%" PetscInt_FMT ",%" PetscInt_FMT ")", err, j, i);
333c4762a1bSJed Brown       }
334c4762a1bSJed Brown       /* AXPY with HYPRE and HYPRE */
3359566063dSJacob Faibussowitsch       PetscCall(MatAXPY(D, -1.0, B, str));
336c4762a1bSJed Brown       if (err > PETSC_SMALL) {
3379566063dSJacob Faibussowitsch         PetscCall(MatViewFromOptions(A, NULL, "-view_duplicate_diff"));
3389566063dSJacob Faibussowitsch         PetscCall(MatViewFromOptions(B, NULL, "-view_duplicate_diff"));
3399566063dSJacob Faibussowitsch         PetscCall(MatViewFromOptions(D, NULL, "-view_duplicate_diff"));
34098921bdaSJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error test 2 MatDuplicate/MatCopy %g (%" PetscInt_FMT ",%" PetscInt_FMT ")", err, j, i);
341c4762a1bSJed Brown       }
342*40018c87Sstefanozampini #if !PetscDefined(HAVE_HYPRE_DEVICE)
343c4762a1bSJed Brown       /* Copy from HYPRE to AIJ */
3449566063dSJacob Faibussowitsch       PetscCall(MatCopy(B, C, str));
345c4762a1bSJed Brown       /* Copy from AIJ to HYPRE */
3469566063dSJacob Faibussowitsch       PetscCall(MatCopy(A, D, str));
347c4762a1bSJed Brown       /* AXPY with HYPRE and AIJ */
3489566063dSJacob Faibussowitsch       PetscCall(MatAXPY(D, -1.0, C, str));
3499566063dSJacob Faibussowitsch       PetscCall(MatHasOperation(D, MATOP_NORM, &flg));
350c4762a1bSJed Brown       if (!flg) { /* TODO add MatNorm_HYPRE */
3519566063dSJacob Faibussowitsch         PetscCall(MatConvert(D, MATAIJ, MAT_INPLACE_MATRIX, &D));
352c4762a1bSJed Brown       }
3539566063dSJacob Faibussowitsch       PetscCall(MatNorm(D, NORM_INFINITY, &err));
354c4762a1bSJed Brown       if (err > PETSC_SMALL) {
3559566063dSJacob Faibussowitsch         PetscCall(MatViewFromOptions(A, NULL, "-view_duplicate_diff"));
3569566063dSJacob Faibussowitsch         PetscCall(MatViewFromOptions(C, NULL, "-view_duplicate_diff"));
3579566063dSJacob Faibussowitsch         PetscCall(MatViewFromOptions(D, NULL, "-view_duplicate_diff"));
35898921bdaSJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error test 3 MatDuplicate/MatCopy %g (%" PetscInt_FMT ",%" PetscInt_FMT ")", err, j, i);
359c4762a1bSJed Brown       }
360*40018c87Sstefanozampini #endif
3619566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
3629566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&D));
363c4762a1bSJed Brown     }
364c4762a1bSJed Brown   }
3659566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&B));
366c4762a1bSJed Brown 
3679566063dSJacob Faibussowitsch   PetscCall(MatHasCongruentLayouts(A, &flg));
368c4762a1bSJed Brown   if (flg) {
369c4762a1bSJed Brown     Vec y, y2;
370c4762a1bSJed Brown 
3719566063dSJacob Faibussowitsch     PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &B));
3729566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(A, NULL, &y));
3739566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(B, NULL, &y2));
3749566063dSJacob Faibussowitsch     PetscCall(MatGetDiagonal(A, y));
3759566063dSJacob Faibussowitsch     PetscCall(MatGetDiagonal(B, y2));
3769566063dSJacob Faibussowitsch     PetscCall(VecAXPY(y2, -1.0, y));
3779566063dSJacob Faibussowitsch     PetscCall(VecNorm(y2, NORM_INFINITY, &err));
378c4762a1bSJed Brown     if (err > PETSC_SMALL) {
3799566063dSJacob Faibussowitsch       PetscCall(VecViewFromOptions(y, NULL, "-view_diagonal_diff"));
3809566063dSJacob Faibussowitsch       PetscCall(VecViewFromOptions(y2, NULL, "-view_diagonal_diff"));
38198921bdaSJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatGetDiagonal %g", err);
382c4762a1bSJed Brown     }
3839566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
3849566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&y));
3859566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&y2));
386c4762a1bSJed Brown   }
387c4762a1bSJed Brown 
3889566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A));
389c4762a1bSJed Brown 
3909566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
391b122ec5aSJacob Faibussowitsch   return 0;
392c4762a1bSJed Brown }
393c4762a1bSJed Brown 
394c4762a1bSJed Brown /*TEST
395c4762a1bSJed Brown 
396c4762a1bSJed Brown    build:
397c4762a1bSJed Brown       requires: hypre
398c4762a1bSJed Brown 
399c4762a1bSJed Brown    test:
400c4762a1bSJed Brown       suffix: 1
401c4762a1bSJed Brown       args: -N 11 -M 11
402c4762a1bSJed Brown       output_file: output/ex115_1.out
403c4762a1bSJed Brown 
404c4762a1bSJed Brown    test:
405c4762a1bSJed Brown       suffix: 2
406c4762a1bSJed Brown       nsize: 3
407*40018c87Sstefanozampini       args: -N 13 -M 13 -matmatmult_via hypre -options_left 0
408c4762a1bSJed Brown       output_file: output/ex115_1.out
409c4762a1bSJed Brown 
410c4762a1bSJed Brown    test:
411c4762a1bSJed Brown       suffix: 3
412c4762a1bSJed Brown       nsize: 4
413*40018c87Sstefanozampini       args: -M 13 -N 7 -matmatmult_via hypre -options_left 0
414c4762a1bSJed Brown       output_file: output/ex115_1.out
415c4762a1bSJed Brown 
416c4762a1bSJed Brown    test:
417c4762a1bSJed Brown       suffix: 4
418c4762a1bSJed Brown       nsize: 2
419c4762a1bSJed Brown       args: -M 12 -N 19
420c4762a1bSJed Brown       output_file: output/ex115_1.out
421c4762a1bSJed Brown 
422c4762a1bSJed Brown    test:
423c4762a1bSJed Brown       suffix: 5
424c4762a1bSJed Brown       nsize: 3
425*40018c87Sstefanozampini       args: -M 13 -N 13 -options_left 0 -matptap_via hypre -matptap_hypre_outtype hypre
426c4762a1bSJed Brown       output_file: output/ex115_1.out
427c4762a1bSJed Brown 
428c4762a1bSJed Brown    test:
429263f2b91SStefano Zampini       requires: !defined(PETSC_HAVE_HYPRE_DEVICE)
430c4762a1bSJed Brown       suffix: 6
431c4762a1bSJed Brown       nsize: 3
432c4762a1bSJed Brown       args: -M 12 -N 19 -test_offproc
433c4762a1bSJed Brown       output_file: output/ex115_1.out
434c4762a1bSJed Brown 
435c4762a1bSJed Brown    test:
436263f2b91SStefano Zampini       requires: !defined(PETSC_HAVE_HYPRE_DEVICE)
437c4762a1bSJed Brown       suffix: 7
438c4762a1bSJed Brown       nsize: 3
439c4762a1bSJed Brown       args: -M 19 -N 12 -test_offproc -view_B ::ascii_info_detail
440c4762a1bSJed Brown       output_file: output/ex115_7.out
441c4762a1bSJed Brown 
442c4762a1bSJed Brown    test:
443263f2b91SStefano Zampini       requires: !defined(PETSC_HAVE_HYPRE_DEVICE)
444c4762a1bSJed Brown       suffix: 8
445c4762a1bSJed Brown       nsize: 3
446c4762a1bSJed Brown       args: -M 1 -N 12 -test_offproc
447c4762a1bSJed Brown       output_file: output/ex115_1.out
448c4762a1bSJed Brown 
449c4762a1bSJed Brown    test:
450263f2b91SStefano Zampini       requires: !defined(PETSC_HAVE_HYPRE_DEVICE)
451c4762a1bSJed Brown       suffix: 9
452c4762a1bSJed Brown       nsize: 3
453c4762a1bSJed Brown       args: -M 1 -N 2 -test_offproc
454c4762a1bSJed Brown       output_file: output/ex115_1.out
455c4762a1bSJed Brown 
456c4762a1bSJed Brown TEST*/
457