1c4762a1bSJed Brown static char help[] = "Tests MatHYPRE\n";
2c4762a1bSJed Brown
3c4762a1bSJed Brown #include <petscmathypre.h>
4c4762a1bSJed Brown
main(int argc,char ** args)5d71ae5a4SJacob Faibussowitsch int main(int argc, char **args)
6d71ae5a4SJacob Faibussowitsch {
7c4762a1bSJed Brown Mat A, B, C, D;
840018c87Sstefanozampini Mat pAB, CD;
9c4762a1bSJed Brown hypre_ParCSRMatrix *parcsr;
10c4762a1bSJed Brown PetscReal err;
11c4762a1bSJed Brown PetscInt i, j, N = 6, M = 6;
12c4762a1bSJed Brown PetscBool flg, testptap = PETSC_TRUE, testmatmatmult = PETSC_TRUE;
13c4762a1bSJed Brown PetscReal norm;
14c4762a1bSJed Brown char file[256];
1540018c87Sstefanozampini MatType mtype = MATAIJ;
16c4762a1bSJed Brown
17327415f7SBarry Smith PetscFunctionBeginUser;
18*c8025a54SPierre Jolivet PetscCall(PetscInitialize(&argc, &args, NULL, help));
199566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL, NULL, "-f", file, sizeof(file), &flg));
20c4762a1bSJed Brown #if defined(PETSC_USE_COMPLEX)
21c4762a1bSJed Brown testptap = PETSC_FALSE;
22c4762a1bSJed Brown testmatmatmult = PETSC_FALSE;
239566063dSJacob Faibussowitsch PetscCall(PetscOptionsInsertString(NULL, "-options_left 0"));
24c4762a1bSJed Brown #endif
259566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-ptap", &testptap, NULL));
269566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-matmatmult", &testmatmatmult, NULL));
279566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, &A));
2840018c87Sstefanozampini #if PetscDefined(HAVE_HYPRE_DEVICE)
2940018c87Sstefanozampini #if PetscDefined(HAVE_HIP)
3040018c87Sstefanozampini mtype = MATAIJHIPSPARSE;
3140018c87Sstefanozampini #elif PetscDefined(HAVE_CUDA)
3240018c87Sstefanozampini mtype = MATAIJCUSPARSE;
3340018c87Sstefanozampini #endif
3440018c87Sstefanozampini #endif
3540018c87Sstefanozampini
36c4762a1bSJed Brown if (!flg) { /* Create a matrix and test MatSetValues */
37c4762a1bSJed Brown PetscMPIInt size;
38c4762a1bSJed Brown
399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
409566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, NULL, "-M", &M, NULL));
419566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, NULL, "-N", &N, NULL));
429566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A, PETSC_DECIDE, PETSC_DECIDE, M, N));
4340018c87Sstefanozampini PetscCall(MatSetType(A, mtype));
449566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(A, 9, NULL));
459566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(A, 9, NULL, 9, NULL));
469566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, &B));
479566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, PETSC_DECIDE, PETSC_DECIDE, M, N));
4840018c87Sstefanozampini #if PetscDefined(HAVE_HYPRE_DEVICE)
4940018c87Sstefanozampini PetscCall(MatSetType(B, mtype));
5040018c87Sstefanozampini #else
519566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATHYPRE));
5240018c87Sstefanozampini #endif
5340018c87Sstefanozampini PetscCall(MatSeqAIJSetPreallocation(B, 9, NULL));
5440018c87Sstefanozampini PetscCall(MatMPIAIJSetPreallocation(B, 9, NULL, 9, NULL));
55c4762a1bSJed Brown if (M == N) {
569566063dSJacob Faibussowitsch PetscCall(MatHYPRESetPreallocation(B, 9, NULL, 9, NULL));
57c4762a1bSJed Brown } else {
589566063dSJacob Faibussowitsch PetscCall(MatHYPRESetPreallocation(B, 6, NULL, 6, NULL));
59c4762a1bSJed Brown }
60c4762a1bSJed Brown if (M == N) {
61c4762a1bSJed Brown for (i = 0; i < M; i++) {
62c4762a1bSJed Brown PetscInt cols[] = {0, 1, 2, 3, 4, 5};
63c4762a1bSJed Brown PetscScalar vals[] = {0, 1. / size, 2. / size, 3. / size, 4. / size, 5. / size};
64c4762a1bSJed Brown for (j = i - 2; j < i + 1; j++) {
65c4762a1bSJed Brown if (j >= N) {
669566063dSJacob Faibussowitsch PetscCall(MatSetValue(A, i, N - 1, (1. * j * N + i) / (3. * N * size), ADD_VALUES));
679566063dSJacob Faibussowitsch PetscCall(MatSetValue(B, i, N - 1, (1. * j * N + i) / (3. * N * size), ADD_VALUES));
68c4762a1bSJed Brown } else if (i > j) {
699566063dSJacob Faibussowitsch PetscCall(MatSetValue(A, i, PetscMin(j, N - 1), (1. * j * N + i) / (2. * N * size), ADD_VALUES));
709566063dSJacob Faibussowitsch PetscCall(MatSetValue(B, i, PetscMin(j, N - 1), (1. * j * N + i) / (2. * N * size), ADD_VALUES));
71c4762a1bSJed Brown } else {
729566063dSJacob Faibussowitsch PetscCall(MatSetValue(A, i, PetscMin(j, N - 1), -1. - (1. * j * N + i) / (4. * N * size), ADD_VALUES));
739566063dSJacob Faibussowitsch PetscCall(MatSetValue(B, i, PetscMin(j, N - 1), -1. - (1. * j * N + i) / (4. * N * size), ADD_VALUES));
74c4762a1bSJed Brown }
75c4762a1bSJed Brown }
769566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &i, PetscMin(6, N), cols, vals, ADD_VALUES));
779566063dSJacob Faibussowitsch PetscCall(MatSetValues(B, 1, &i, PetscMin(6, N), cols, vals, ADD_VALUES));
78c4762a1bSJed Brown }
79c4762a1bSJed Brown } else {
80c4762a1bSJed Brown PetscInt rows[2];
81c4762a1bSJed Brown PetscBool test_offproc = PETSC_FALSE;
82c4762a1bSJed Brown
839566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_offproc", &test_offproc, NULL));
84c4762a1bSJed Brown if (test_offproc) {
85c4762a1bSJed Brown const PetscInt *ranges;
86c4762a1bSJed Brown PetscMPIInt rank;
87c4762a1bSJed Brown
889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
899566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRanges(A, &ranges));
90c4762a1bSJed Brown rows[0] = ranges[(rank + 1) % size];
91c4762a1bSJed Brown rows[1] = ranges[(rank + 1) % size + 1];
92c4762a1bSJed Brown } else {
939566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rows[0], &rows[1]));
94c4762a1bSJed Brown }
95c4762a1bSJed Brown for (i = rows[0]; i < rows[1]; i++) {
96c4762a1bSJed Brown PetscInt cols[] = {0, 1, 2, 3, 4, 5};
97c4762a1bSJed Brown PetscScalar vals[] = {-1, 1, -2, 2, -3, 3};
98c4762a1bSJed Brown
999566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &i, PetscMin(6, N), cols, vals, INSERT_VALUES));
1009566063dSJacob Faibussowitsch PetscCall(MatSetValues(B, 1, &i, PetscMin(6, N), cols, vals, INSERT_VALUES));
101c4762a1bSJed Brown }
102c4762a1bSJed Brown }
103c4762a1bSJed Brown /* MAT_FLUSH_ASSEMBLY currently not supported */
1049566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
1059566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
1069566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
1079566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
10840018c87Sstefanozampini #if PetscDefined(HAVE_HYPRE_DEVICE)
10940018c87Sstefanozampini PetscCall(MatConvert(B, MATHYPRE, MAT_INPLACE_MATRIX, &B));
11040018c87Sstefanozampini #endif
111c4762a1bSJed Brown
112c4762a1bSJed Brown #if defined(PETSC_USE_COMPLEX)
113c4762a1bSJed Brown /* make the matrix imaginary */
1149566063dSJacob Faibussowitsch PetscCall(MatScale(A, PETSC_i));
1159566063dSJacob Faibussowitsch PetscCall(MatScale(B, PETSC_i));
116c4762a1bSJed Brown #endif
117c4762a1bSJed Brown
11840018c87Sstefanozampini #if !PetscDefined(HAVE_HYPRE_DEVICE)
119c4762a1bSJed Brown /* MatAXPY further exercises MatSetValues_HYPRE */
1209566063dSJacob Faibussowitsch PetscCall(MatAXPY(B, -1., A, DIFFERENT_NONZERO_PATTERN));
1219566063dSJacob Faibussowitsch PetscCall(MatConvert(B, MATMPIAIJ, MAT_INITIAL_MATRIX, &C));
1229566063dSJacob Faibussowitsch PetscCall(MatNorm(C, NORM_INFINITY, &err));
12354c59aa7SJacob Faibussowitsch PetscCheck(err <= PETSC_SMALL, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatSetValues %g", err);
1249566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C));
12540018c87Sstefanozampini #endif
12640018c87Sstefanozampini PetscCall(MatDestroy(&B));
127c4762a1bSJed Brown } else {
128c4762a1bSJed Brown PetscViewer viewer;
129c4762a1bSJed Brown
1309566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, file, FILE_MODE_READ, &viewer));
1319566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(A));
1329566063dSJacob Faibussowitsch PetscCall(MatLoad(A, viewer));
13340018c87Sstefanozampini PetscCall(MatSetType(A, mtype));
1349566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer));
1359566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N));
136c4762a1bSJed Brown }
137c4762a1bSJed Brown
138c4762a1bSJed Brown /* check conversion routines */
139f9dc6c1fSStefano Zampini PetscCall(MatViewFromOptions(A, NULL, "-view_A"));
1409566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &B));
141f9dc6c1fSStefano Zampini PetscCall(MatViewFromOptions(B, NULL, "-view_convert"));
1429566063dSJacob Faibussowitsch PetscCall(MatMultEqual(B, A, 4, &flg));
143f9dc6c1fSStefano Zampini PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat HYPRE init");
144f9dc6c1fSStefano Zampini PetscCall(MatConvert(A, MATHYPRE, MAT_REUSE_MATRIX, &B));
145f9dc6c1fSStefano Zampini PetscCall(MatViewFromOptions(B, NULL, "-view_convert"));
146f9dc6c1fSStefano Zampini PetscCall(MatMultEqual(B, A, 4, &flg));
147f9dc6c1fSStefano Zampini PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat HYPRE reuse");
1489566063dSJacob Faibussowitsch PetscCall(MatConvert(B, MATIS, MAT_INITIAL_MATRIX, &D));
1499566063dSJacob Faibussowitsch PetscCall(MatConvert(B, MATIS, MAT_REUSE_MATRIX, &D));
1509566063dSJacob Faibussowitsch PetscCall(MatMultEqual(D, A, 4, &flg));
15154c59aa7SJacob Faibussowitsch PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat IS");
1529566063dSJacob Faibussowitsch PetscCall(MatConvert(B, MATAIJ, MAT_INITIAL_MATRIX, &C));
1539566063dSJacob Faibussowitsch PetscCall(MatConvert(B, MATAIJ, MAT_REUSE_MATRIX, &C));
1549566063dSJacob Faibussowitsch PetscCall(MatMultEqual(C, A, 4, &flg));
15554c59aa7SJacob Faibussowitsch PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat AIJ");
1569566063dSJacob Faibussowitsch PetscCall(MatAXPY(C, -1., A, SAME_NONZERO_PATTERN));
1579566063dSJacob Faibussowitsch PetscCall(MatNorm(C, NORM_INFINITY, &err));
15854c59aa7SJacob Faibussowitsch PetscCheck(err <= PETSC_SMALL, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat AIJ %g", err);
1599566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C));
1609566063dSJacob Faibussowitsch PetscCall(MatConvert(D, MATAIJ, MAT_INITIAL_MATRIX, &C));
1619566063dSJacob Faibussowitsch PetscCall(MatAXPY(C, -1., A, SAME_NONZERO_PATTERN));
1629566063dSJacob Faibussowitsch PetscCall(MatNorm(C, NORM_INFINITY, &err));
16354c59aa7SJacob Faibussowitsch PetscCheck(err <= PETSC_SMALL, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat IS %g", err);
1649566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C));
1659566063dSJacob Faibussowitsch PetscCall(MatDestroy(&D));
166c4762a1bSJed Brown
167c4762a1bSJed Brown /* check MatCreateFromParCSR */
1689566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(B, &parcsr));
1699566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(parcsr, MATAIJ, PETSC_COPY_VALUES, &D));
1709566063dSJacob Faibussowitsch PetscCall(MatDestroy(&D));
1719566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(parcsr, MATHYPRE, PETSC_USE_POINTER, &C));
172c4762a1bSJed Brown
173c4762a1bSJed Brown /* check MatMult operations */
1749566063dSJacob Faibussowitsch PetscCall(MatMultEqual(A, B, 4, &flg));
17554c59aa7SJacob Faibussowitsch PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMult B");
1769566063dSJacob Faibussowitsch PetscCall(MatMultEqual(A, C, 4, &flg));
17754c59aa7SJacob Faibussowitsch PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMult C");
1789566063dSJacob Faibussowitsch PetscCall(MatMultAddEqual(A, B, 4, &flg));
17954c59aa7SJacob Faibussowitsch PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultAdd B");
1809566063dSJacob Faibussowitsch PetscCall(MatMultAddEqual(A, C, 4, &flg));
18154c59aa7SJacob Faibussowitsch PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultAdd C");
1829566063dSJacob Faibussowitsch PetscCall(MatMultTransposeEqual(A, B, 4, &flg));
18354c59aa7SJacob Faibussowitsch PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultTranspose B");
1849566063dSJacob Faibussowitsch PetscCall(MatMultTransposeEqual(A, C, 4, &flg));
18554c59aa7SJacob Faibussowitsch PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultTranspose C");
1869566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAddEqual(A, B, 4, &flg));
18754c59aa7SJacob Faibussowitsch PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultTransposeAdd B");
1889566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAddEqual(A, C, 4, &flg));
18954c59aa7SJacob Faibussowitsch PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultTransposeAdd C");
190c4762a1bSJed Brown
191c4762a1bSJed Brown /* check PtAP */
192c4762a1bSJed Brown if (testptap && M == N) {
193c4762a1bSJed Brown Mat pP, hP;
194c4762a1bSJed Brown
195c4762a1bSJed Brown /* PETSc MatPtAP -> output is a MatAIJ
196c4762a1bSJed Brown It uses HYPRE functions when -matptap_via hypre is specified at command line */
197fb842aefSJose E. Roman PetscCall(MatPtAP(A, A, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &pP));
198fb842aefSJose E. Roman PetscCall(MatPtAP(A, A, MAT_REUSE_MATRIX, PETSC_DETERMINE, &pP));
1999566063dSJacob Faibussowitsch PetscCall(MatNorm(pP, NORM_INFINITY, &norm));
2009566063dSJacob Faibussowitsch PetscCall(MatPtAPMultEqual(A, A, pP, 10, &flg));
20154c59aa7SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatPtAP_MatAIJ");
202c4762a1bSJed Brown
203c4762a1bSJed Brown /* MatPtAP_HYPRE_HYPRE -> output is a MatHYPRE */
204fb842aefSJose E. Roman PetscCall(MatPtAP(C, B, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &hP));
205fb842aefSJose E. Roman PetscCall(MatPtAP(C, B, MAT_REUSE_MATRIX, PETSC_DETERMINE, &hP));
2069566063dSJacob Faibussowitsch PetscCall(MatPtAPMultEqual(C, B, hP, 10, &flg));
20754c59aa7SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatPtAP_HYPRE_HYPRE");
208c20d7725SJed Brown
209c20d7725SJed Brown /* Test MatAXPY_Basic() */
21040018c87Sstefanozampini #if !PetscDefined(HAVE_HYPRE_DEVICE)
2119566063dSJacob Faibussowitsch PetscCall(MatAXPY(hP, -1., pP, DIFFERENT_NONZERO_PATTERN));
2129566063dSJacob Faibussowitsch PetscCall(MatHasOperation(hP, MATOP_NORM, &flg));
213c4762a1bSJed Brown if (!flg) { /* TODO add MatNorm_HYPRE */
2149566063dSJacob Faibussowitsch PetscCall(MatConvert(hP, MATAIJ, MAT_INPLACE_MATRIX, &hP));
215c4762a1bSJed Brown }
2169566063dSJacob Faibussowitsch PetscCall(MatNorm(hP, NORM_INFINITY, &err));
217e00437b9SBarry Smith PetscCheck(err / norm <= PETSC_SMALL, PetscObjectComm((PetscObject)hP), PETSC_ERR_PLIB, "Error MatPtAP %g %g", err, norm);
21840018c87Sstefanozampini #endif
2199566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pP));
2209566063dSJacob Faibussowitsch PetscCall(MatDestroy(&hP));
221c4762a1bSJed Brown
222c4762a1bSJed Brown /* MatPtAP_AIJ_HYPRE -> output can be decided at runtime with -matptap_hypre_outtype */
22340018c87Sstefanozampini #if !PetscDefined(HAVE_HYPRE_DEVICE)
224fb842aefSJose E. Roman PetscCall(MatPtAP(A, B, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &hP));
225fb842aefSJose E. Roman PetscCall(MatPtAP(A, B, MAT_REUSE_MATRIX, PETSC_DETERMINE, &hP));
2269566063dSJacob Faibussowitsch PetscCall(MatPtAPMultEqual(A, B, hP, 10, &flg));
22754c59aa7SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatPtAP_AIJ_HYPRE");
2289566063dSJacob Faibussowitsch PetscCall(MatDestroy(&hP));
22940018c87Sstefanozampini #endif
230c4762a1bSJed Brown }
2319566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C));
2329566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B));
233c4762a1bSJed Brown
234c4762a1bSJed Brown /* check MatMatMult */
235c4762a1bSJed Brown if (testmatmatmult) {
2369566063dSJacob Faibussowitsch PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &B));
2379566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &C));
2389566063dSJacob Faibussowitsch PetscCall(MatConvert(B, MATHYPRE, MAT_INITIAL_MATRIX, &D));
239c4762a1bSJed Brown
240c4762a1bSJed Brown /* PETSc MatMatMult -> output is a MatAIJ
241c4762a1bSJed Brown It uses HYPRE functions when -matmatmult_via hypre is specified at command line */
242fb842aefSJose E. Roman PetscCall(MatMatMult(A, B, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &pAB));
243fb842aefSJose E. Roman PetscCall(MatMatMult(A, B, MAT_REUSE_MATRIX, PETSC_DETERMINE, &pAB));
2449566063dSJacob Faibussowitsch PetscCall(MatNorm(pAB, NORM_INFINITY, &norm));
2459566063dSJacob Faibussowitsch PetscCall(MatMatMultEqual(A, B, pAB, 10, &flg));
24654c59aa7SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatMatMult_AIJ_AIJ");
247c4762a1bSJed Brown
248c4762a1bSJed Brown /* MatMatMult_HYPRE_HYPRE -> output is a MatHYPRE */
249fb842aefSJose E. Roman PetscCall(MatMatMult(C, D, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &CD));
250fb842aefSJose E. Roman PetscCall(MatMatMult(C, D, MAT_REUSE_MATRIX, PETSC_DETERMINE, &CD));
2519566063dSJacob Faibussowitsch PetscCall(MatMatMultEqual(C, D, CD, 10, &flg));
25254c59aa7SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatMatMult_HYPRE_HYPRE");
253c20d7725SJed Brown
254c20d7725SJed Brown /* Test MatAXPY_Basic() */
25540018c87Sstefanozampini #if !PetscDefined(HAVE_HYPRE_DEVICE)
2569566063dSJacob Faibussowitsch PetscCall(MatAXPY(CD, -1., pAB, DIFFERENT_NONZERO_PATTERN));
257c20d7725SJed Brown
2589566063dSJacob Faibussowitsch PetscCall(MatHasOperation(CD, MATOP_NORM, &flg));
259c4762a1bSJed Brown if (!flg) { /* TODO add MatNorm_HYPRE */
2609566063dSJacob Faibussowitsch PetscCall(MatConvert(CD, MATAIJ, MAT_INPLACE_MATRIX, &CD));
261c4762a1bSJed Brown }
2629566063dSJacob Faibussowitsch PetscCall(MatNorm(CD, NORM_INFINITY, &err));
26354c59aa7SJacob Faibussowitsch PetscCheck((err / norm) <= PETSC_SMALL, PetscObjectComm((PetscObject)CD), PETSC_ERR_PLIB, "Error MatMatMult %g %g", err, norm);
26440018c87Sstefanozampini #endif
265c20d7725SJed Brown
2669566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C));
2679566063dSJacob Faibussowitsch PetscCall(MatDestroy(&D));
2689566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pAB));
2699566063dSJacob Faibussowitsch PetscCall(MatDestroy(&CD));
270c4762a1bSJed Brown
271c4762a1bSJed Brown /* When configured with HYPRE, MatMatMatMult is available for the triplet transpose(aij)-aij-aij */
27240018c87Sstefanozampini #if !PetscDefined(HAVE_HYPRE_DEVICE)
27340018c87Sstefanozampini Mat CAB;
2749566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(A, &C));
275fb842aefSJose E. Roman PetscCall(MatMatMatMult(C, A, B, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &CAB));
2769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C));
2779566063dSJacob Faibussowitsch PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &C));
278fb842aefSJose E. Roman PetscCall(MatMatMult(C, A, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &D));
2799566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C));
280fb842aefSJose E. Roman PetscCall(MatMatMult(D, B, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &C));
2819566063dSJacob Faibussowitsch PetscCall(MatNorm(C, NORM_INFINITY, &norm));
2829566063dSJacob Faibussowitsch PetscCall(MatAXPY(C, -1., CAB, DIFFERENT_NONZERO_PATTERN));
2839566063dSJacob Faibussowitsch PetscCall(MatNorm(C, NORM_INFINITY, &err));
28454c59aa7SJacob Faibussowitsch PetscCheck((err / norm) <= PETSC_SMALL, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMatMatMult %g %g", err, norm);
2859566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C));
2869566063dSJacob Faibussowitsch PetscCall(MatDestroy(&D));
2879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&CAB));
28840018c87Sstefanozampini #endif
2899566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B));
290c4762a1bSJed Brown }
291c4762a1bSJed Brown
292c4762a1bSJed Brown /* Check MatView */
2939566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &B));
2949566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(B, NULL, "-view_B"));
295c4762a1bSJed Brown
296c4762a1bSJed Brown /* Check MatDuplicate/MatCopy */
297c4762a1bSJed Brown for (j = 0; j < 3; j++) {
298c4762a1bSJed Brown MatDuplicateOption dop;
299c4762a1bSJed Brown
300c4762a1bSJed Brown dop = MAT_COPY_VALUES;
301c4762a1bSJed Brown if (j == 1) dop = MAT_DO_NOT_COPY_VALUES;
302c4762a1bSJed Brown if (j == 2) dop = MAT_SHARE_NONZERO_PATTERN;
303c4762a1bSJed Brown
304c4762a1bSJed Brown for (i = 0; i < 3; i++) {
305c4762a1bSJed Brown MatStructure str;
306c4762a1bSJed Brown
3079566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Dup/Copy tests: %" PetscInt_FMT " %" PetscInt_FMT "\n", j, i));
308c4762a1bSJed Brown
309c4762a1bSJed Brown str = DIFFERENT_NONZERO_PATTERN;
310c4762a1bSJed Brown if (i == 1) str = SAME_NONZERO_PATTERN;
311c4762a1bSJed Brown if (i == 2) str = SUBSET_NONZERO_PATTERN;
312c4762a1bSJed Brown
3139566063dSJacob Faibussowitsch PetscCall(MatDuplicate(A, dop, &C));
3149566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, dop, &D));
315c4762a1bSJed Brown if (dop != MAT_COPY_VALUES) {
3169566063dSJacob Faibussowitsch PetscCall(MatCopy(A, C, str));
3179566063dSJacob Faibussowitsch PetscCall(MatCopy(B, D, str));
318c4762a1bSJed Brown }
319c4762a1bSJed Brown /* AXPY with AIJ and HYPRE */
32040018c87Sstefanozampini #if !PetscDefined(HAVE_HYPRE_DEVICE)
3219566063dSJacob Faibussowitsch PetscCall(MatAXPY(C, -1.0, D, str));
3229566063dSJacob Faibussowitsch PetscCall(MatNorm(C, NORM_INFINITY, &err));
32340018c87Sstefanozampini #else
32440018c87Sstefanozampini err = 0.0;
32540018c87Sstefanozampini #endif
326c4762a1bSJed Brown if (err > PETSC_SMALL) {
3279566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(A, NULL, "-view_duplicate_diff"));
3289566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(B, NULL, "-view_duplicate_diff"));
3299566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(C, NULL, "-view_duplicate_diff"));
330f9dc6c1fSStefano Zampini PetscCall(MatViewFromOptions(D, NULL, "-view_duplicate_diff"));
33198921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error test 1 MatDuplicate/MatCopy %g (%" PetscInt_FMT ",%" PetscInt_FMT ")", err, j, i);
332c4762a1bSJed Brown }
333c4762a1bSJed Brown /* AXPY with HYPRE and HYPRE */
3349566063dSJacob Faibussowitsch PetscCall(MatAXPY(D, -1.0, B, str));
335c4762a1bSJed Brown if (err > PETSC_SMALL) {
3369566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(A, NULL, "-view_duplicate_diff"));
3379566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(B, NULL, "-view_duplicate_diff"));
3389566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(D, NULL, "-view_duplicate_diff"));
33998921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error test 2 MatDuplicate/MatCopy %g (%" PetscInt_FMT ",%" PetscInt_FMT ")", err, j, i);
340c4762a1bSJed Brown }
34140018c87Sstefanozampini #if !PetscDefined(HAVE_HYPRE_DEVICE)
342c4762a1bSJed Brown /* Copy from HYPRE to AIJ */
3439566063dSJacob Faibussowitsch PetscCall(MatCopy(B, C, str));
344c4762a1bSJed Brown /* Copy from AIJ to HYPRE */
3459566063dSJacob Faibussowitsch PetscCall(MatCopy(A, D, str));
346c4762a1bSJed Brown /* AXPY with HYPRE and AIJ */
3479566063dSJacob Faibussowitsch PetscCall(MatAXPY(D, -1.0, C, str));
3489566063dSJacob Faibussowitsch PetscCall(MatHasOperation(D, MATOP_NORM, &flg));
349c4762a1bSJed Brown if (!flg) { /* TODO add MatNorm_HYPRE */
3509566063dSJacob Faibussowitsch PetscCall(MatConvert(D, MATAIJ, MAT_INPLACE_MATRIX, &D));
351c4762a1bSJed Brown }
3529566063dSJacob Faibussowitsch PetscCall(MatNorm(D, NORM_INFINITY, &err));
353c4762a1bSJed Brown if (err > PETSC_SMALL) {
3549566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(A, NULL, "-view_duplicate_diff"));
3559566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(C, NULL, "-view_duplicate_diff"));
3569566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(D, NULL, "-view_duplicate_diff"));
35798921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error test 3 MatDuplicate/MatCopy %g (%" PetscInt_FMT ",%" PetscInt_FMT ")", err, j, i);
358c4762a1bSJed Brown }
35940018c87Sstefanozampini #endif
3609566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C));
3619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&D));
362c4762a1bSJed Brown }
363c4762a1bSJed Brown }
3649566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B));
365c4762a1bSJed Brown
3669566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(A, &flg));
367c4762a1bSJed Brown if (flg) {
368c4762a1bSJed Brown Vec y, y2;
369c4762a1bSJed Brown
3709566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &B));
3719566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, NULL, &y));
3729566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(B, NULL, &y2));
3739566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(A, y));
3749566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(B, y2));
3759566063dSJacob Faibussowitsch PetscCall(VecAXPY(y2, -1.0, y));
3769566063dSJacob Faibussowitsch PetscCall(VecNorm(y2, NORM_INFINITY, &err));
377c4762a1bSJed Brown if (err > PETSC_SMALL) {
3789566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(y, NULL, "-view_diagonal_diff"));
3799566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(y2, NULL, "-view_diagonal_diff"));
38098921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatGetDiagonal %g", err);
381c4762a1bSJed Brown }
3829566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B));
3839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&y));
3849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&y2));
385c4762a1bSJed Brown }
386c4762a1bSJed Brown
3879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A));
388c4762a1bSJed Brown
3899566063dSJacob Faibussowitsch PetscCall(PetscFinalize());
390b122ec5aSJacob Faibussowitsch return 0;
391c4762a1bSJed Brown }
392c4762a1bSJed Brown
393c4762a1bSJed Brown /*TEST
394c4762a1bSJed Brown
395c4762a1bSJed Brown build:
396c4762a1bSJed Brown requires: hypre
397c4762a1bSJed Brown
398c4762a1bSJed Brown test:
399c4762a1bSJed Brown suffix: 1
400c4762a1bSJed Brown args: -N 11 -M 11
401c4762a1bSJed Brown output_file: output/ex115_1.out
402c4762a1bSJed Brown
403c4762a1bSJed Brown test:
404c4762a1bSJed Brown suffix: 2
405c4762a1bSJed Brown nsize: 3
40640018c87Sstefanozampini args: -N 13 -M 13 -matmatmult_via hypre -options_left 0
407c4762a1bSJed Brown output_file: output/ex115_1.out
408c4762a1bSJed Brown
409c4762a1bSJed Brown test:
410c4762a1bSJed Brown suffix: 3
411c4762a1bSJed Brown nsize: 4
41240018c87Sstefanozampini args: -M 13 -N 7 -matmatmult_via hypre -options_left 0
413c4762a1bSJed Brown output_file: output/ex115_1.out
414c4762a1bSJed Brown
415c4762a1bSJed Brown test:
416c4762a1bSJed Brown suffix: 4
417c4762a1bSJed Brown nsize: 2
418c4762a1bSJed Brown args: -M 12 -N 19
419c4762a1bSJed Brown output_file: output/ex115_1.out
420c4762a1bSJed Brown
421c4762a1bSJed Brown test:
422c4762a1bSJed Brown suffix: 5
423c4762a1bSJed Brown nsize: 3
42440018c87Sstefanozampini args: -M 13 -N 13 -options_left 0 -matptap_via hypre -matptap_hypre_outtype hypre
425c4762a1bSJed Brown output_file: output/ex115_1.out
426c4762a1bSJed Brown
427c4762a1bSJed Brown test:
428263f2b91SStefano Zampini requires: !defined(PETSC_HAVE_HYPRE_DEVICE)
429c4762a1bSJed Brown suffix: 6
430c4762a1bSJed Brown nsize: 3
431c4762a1bSJed Brown args: -M 12 -N 19 -test_offproc
432c4762a1bSJed Brown output_file: output/ex115_1.out
433c4762a1bSJed Brown
434c4762a1bSJed Brown test:
435263f2b91SStefano Zampini requires: !defined(PETSC_HAVE_HYPRE_DEVICE)
436c4762a1bSJed Brown suffix: 7
437c4762a1bSJed Brown nsize: 3
438c4762a1bSJed Brown args: -M 19 -N 12 -test_offproc -view_B ::ascii_info_detail
439c4762a1bSJed Brown output_file: output/ex115_7.out
440c4762a1bSJed Brown
441c4762a1bSJed Brown test:
442263f2b91SStefano Zampini requires: !defined(PETSC_HAVE_HYPRE_DEVICE)
443c4762a1bSJed Brown suffix: 8
444c4762a1bSJed Brown nsize: 3
445c4762a1bSJed Brown args: -M 1 -N 12 -test_offproc
446c4762a1bSJed Brown output_file: output/ex115_1.out
447c4762a1bSJed Brown
448c4762a1bSJed Brown test:
449263f2b91SStefano Zampini requires: !defined(PETSC_HAVE_HYPRE_DEVICE)
450c4762a1bSJed Brown suffix: 9
451c4762a1bSJed Brown nsize: 3
452c4762a1bSJed Brown args: -M 1 -N 2 -test_offproc
453c4762a1bSJed Brown output_file: output/ex115_1.out
454c4762a1bSJed Brown
455c4762a1bSJed Brown TEST*/
456