xref: /petsc/src/mat/tests/ex62.c (revision 66af8762ec03dbef0e079729eb2a1734a35ed7ff)
1 static char help[] = "Test Matrix products for AIJ matrices\n\
2 Input arguments are:\n\
3   -fA <input_file> -fB <input_file> -fC <input_file>: file to load\n\n";
4 /* Example of usage:
5    ./ex62 -fA <A_binary> -fB <B_binary>
6    mpiexec -n 3 ./ex62 -fA medium -fB medium
7 */
8 
9 #include <petscmat.h>
10 
11 /*
12      B = A - B
13      norm = norm(B)
14 */
15 PetscErrorCode MatNormDifference(Mat A, Mat B, PetscReal *norm)
16 {
17   PetscFunctionBegin;
18   PetscCall(MatAXPY(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
19   PetscCall(MatNorm(B, NORM_FROBENIUS, norm));
20   PetscFunctionReturn(PETSC_SUCCESS);
21 }
22 
23 int main(int argc, char **args)
24 {
25   Mat          A, A_save, B, C, P, C1, R;
26   PetscViewer  viewer;
27   PetscMPIInt  size, rank;
28   PetscInt     i, j, *idxn, PM, PN = PETSC_DECIDE, rstart, rend;
29   PetscReal    norm;
30   PetscRandom  rdm;
31   char         file[2][PETSC_MAX_PATH_LEN] = {"", ""};
32   PetscScalar *a, rval, alpha;
33   PetscBool    Test_MatMatMult = PETSC_TRUE, Test_MatTrMat = PETSC_TRUE, Test_MatMatTr = PETSC_TRUE;
34   PetscBool    Test_MatPtAP = PETSC_TRUE, Test_MatRARt = PETSC_TRUE, flg, seqaij, flgA, flgB;
35   MatInfo      info;
36   PetscInt     nzp = 5; /* num of nonzeros in each row of P */
37   MatType      mattype;
38   const char  *deft = MATAIJ;
39   char         A_mattype[256], B_mattype[256];
40   PetscInt     mcheck = 10;
41 
42   PetscFunctionBeginUser;
43   PetscCall(PetscInitialize(&argc, &args, (char *)0, help));
44   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
45   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
46 
47   /*  Load the matrices A_save and B */
48   PetscOptionsBegin(PETSC_COMM_WORLD, "", "", "");
49   PetscCall(PetscOptionsBool("-test_rart", "Test MatRARt", "", Test_MatRARt, &Test_MatRARt, NULL));
50   PetscCall(PetscOptionsInt("-PN", "Number of columns of P", "", PN, &PN, NULL));
51   PetscCall(PetscOptionsInt("-mcheck", "Number of matmult checks", "", mcheck, &mcheck, NULL));
52   PetscCall(PetscOptionsString("-fA", "Path for matrix A", "", file[0], file[0], sizeof(file[0]), &flg));
53   PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_USER_INPUT, "Must indicate a file name for matrix A with the -fA option.");
54   PetscCall(PetscOptionsString("-fB", "Path for matrix B", "", file[1], file[1], sizeof(file[1]), &flg));
55   PetscCall(PetscOptionsFList("-A_mat_type", "Matrix type", "MatSetType", MatList, deft, A_mattype, 256, &flgA));
56   PetscCall(PetscOptionsFList("-B_mat_type", "Matrix type", "MatSetType", MatList, deft, B_mattype, 256, &flgB));
57   PetscOptionsEnd();
58 
59   PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, file[0], FILE_MODE_READ, &viewer));
60   PetscCall(MatCreate(PETSC_COMM_WORLD, &A_save));
61   PetscCall(MatLoad(A_save, viewer));
62   PetscCall(PetscViewerDestroy(&viewer));
63 
64   if (flg) {
65     PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, file[1], FILE_MODE_READ, &viewer));
66     PetscCall(MatCreate(PETSC_COMM_WORLD, &B));
67     PetscCall(MatLoad(B, viewer));
68     PetscCall(PetscViewerDestroy(&viewer));
69   } else {
70     PetscCall(PetscObjectReference((PetscObject)A_save));
71     B = A_save;
72   }
73 
74   if (flgA) PetscCall(MatConvert(A_save, A_mattype, MAT_INPLACE_MATRIX, &A_save));
75   if (flgB) PetscCall(MatConvert(B, B_mattype, MAT_INPLACE_MATRIX, &B));
76   PetscCall(MatSetFromOptions(A_save));
77   PetscCall(MatSetFromOptions(B));
78 
79   PetscCall(MatGetType(B, &mattype));
80 
81   PetscCall(PetscMalloc(nzp * (sizeof(PetscInt) + sizeof(PetscScalar)), &idxn));
82   a = (PetscScalar *)(idxn + nzp);
83 
84   PetscCall(PetscRandomCreate(PETSC_COMM_WORLD, &rdm));
85   PetscCall(PetscRandomSetFromOptions(rdm));
86 
87   /* 1) MatMatMult() */
88   /* ----------------*/
89   if (Test_MatMatMult) {
90     PetscCall(MatDuplicate(A_save, MAT_COPY_VALUES, &A));
91 
92     /* (1.1) Test developer API */
93     PetscCall(MatProductCreate(A, B, NULL, &C));
94     PetscCall(MatSetOptionsPrefix(C, "AB_"));
95     PetscCall(MatProductSetType(C, MATPRODUCT_AB));
96     PetscCall(MatProductSetAlgorithm(C, MATPRODUCTALGORITHMDEFAULT));
97     PetscCall(MatProductSetFill(C, PETSC_DEFAULT));
98     PetscCall(MatProductSetFromOptions(C));
99     /* we can inquire about MATOP_PRODUCTSYMBOLIC even if the destination matrix type has not been set yet */
100     PetscCall(MatHasOperation(C, MATOP_PRODUCTSYMBOLIC, &flg));
101     PetscCall(MatProductSymbolic(C));
102     PetscCall(MatProductNumeric(C));
103     PetscCall(MatMatMultEqual(A, B, C, mcheck, &flg));
104     PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Error in C=A*B");
105 
106     /* Test reuse symbolic C */
107     alpha = 0.9;
108     PetscCall(MatScale(A, alpha));
109     PetscCall(MatProductNumeric(C));
110 
111     PetscCall(MatMatMultEqual(A, B, C, mcheck, &flg));
112     PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Error in C=A*B");
113     PetscCall(MatDestroy(&C));
114 
115     /* (1.2) Test user driver */
116     PetscCall(MatMatMult(A, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &C));
117 
118     /* Test MAT_REUSE_MATRIX - reuse symbolic C */
119     alpha = 1.0;
120     for (i = 0; i < 2; i++) {
121       alpha -= 0.1;
122       PetscCall(MatScale(A, alpha));
123       PetscCall(MatMatMult(A, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &C));
124     }
125     PetscCall(MatMatMultEqual(A, B, C, mcheck, &flg));
126     PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Error: MatMatMult()");
127     PetscCall(MatDestroy(&A));
128 
129     /* Test MatProductClear() */
130     PetscCall(MatProductClear(C));
131     PetscCall(MatDestroy(&C));
132 
133     /* Test MatMatMult() for dense and aij matrices */
134     PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &flg, MATSEQAIJ, MATMPIAIJ, ""));
135     if (flg) {
136       PetscCall(MatConvert(A_save, MATDENSE, MAT_INITIAL_MATRIX, &A));
137       PetscCall(MatMatMult(A, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &C));
138       PetscCall(MatDestroy(&C));
139       PetscCall(MatDestroy(&A));
140     }
141   }
142 
143   /* Create P and R = P^T  */
144   /* --------------------- */
145   PetscCall(MatGetSize(B, &PM, NULL));
146   if (PN < 0) PN = PM / 2;
147   PetscCall(MatCreate(PETSC_COMM_WORLD, &P));
148   PetscCall(MatSetSizes(P, PETSC_DECIDE, PETSC_DECIDE, PM, PN));
149   PetscCall(MatSetType(P, MATAIJ));
150   PetscCall(MatSeqAIJSetPreallocation(P, nzp, NULL));
151   PetscCall(MatMPIAIJSetPreallocation(P, nzp, NULL, nzp, NULL));
152   PetscCall(MatGetOwnershipRange(P, &rstart, &rend));
153   for (i = 0; i < nzp; i++) PetscCall(PetscRandomGetValue(rdm, &a[i]));
154   for (i = rstart; i < rend; i++) {
155     for (j = 0; j < nzp; j++) {
156       PetscCall(PetscRandomGetValue(rdm, &rval));
157       idxn[j] = (PetscInt)(PetscRealPart(rval) * PN);
158     }
159     PetscCall(MatSetValues(P, 1, &i, nzp, idxn, a, ADD_VALUES));
160   }
161   PetscCall(MatAssemblyBegin(P, MAT_FINAL_ASSEMBLY));
162   PetscCall(MatAssemblyEnd(P, MAT_FINAL_ASSEMBLY));
163 
164   PetscCall(MatTranspose(P, MAT_INITIAL_MATRIX, &R));
165   PetscCall(MatConvert(P, mattype, MAT_INPLACE_MATRIX, &P));
166   PetscCall(MatConvert(R, mattype, MAT_INPLACE_MATRIX, &R));
167   PetscCall(MatSetFromOptions(P));
168   PetscCall(MatSetFromOptions(R));
169 
170   /* 2) MatTransposeMatMult() */
171   /* ------------------------ */
172   if (Test_MatTrMat) {
173     /* (2.1) Test developer driver C = P^T*B */
174     PetscCall(MatProductCreate(P, B, NULL, &C));
175     PetscCall(MatSetOptionsPrefix(C, "AtB_"));
176     PetscCall(MatProductSetType(C, MATPRODUCT_AtB));
177     PetscCall(MatProductSetAlgorithm(C, MATPRODUCTALGORITHMDEFAULT));
178     PetscCall(MatProductSetFill(C, PETSC_DEFAULT));
179     PetscCall(MatProductSetFromOptions(C));
180     PetscCall(MatHasOperation(C, MATOP_PRODUCTSYMBOLIC, &flg));
181     if (flg) {                                                 /* run tests if supported */
182       PetscCall(MatProductSymbolic(C));                        /* equivalent to MatSetUp() */
183       PetscCall(MatSetOption(C, MAT_USE_INODES, PETSC_FALSE)); /* illustrate how to call MatSetOption() */
184       PetscCall(MatProductNumeric(C));
185       PetscCall(MatProductNumeric(C)); /* test reuse symbolic C */
186 
187       PetscCall(MatTransposeMatMultEqual(P, B, C, mcheck, &flg));
188       PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error: developer driver C = P^T*B");
189       PetscCall(MatDestroy(&C));
190 
191       /* (2.2) Test user driver C = P^T*B */
192       PetscCall(MatTransposeMatMult(P, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &C));
193       PetscCall(MatTransposeMatMult(P, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &C));
194       PetscCall(MatGetInfo(C, MAT_GLOBAL_SUM, &info));
195       PetscCall(MatProductClear(C));
196 
197       /* Compare P^T*B and R*B */
198       PetscCall(MatMatMult(R, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &C1));
199       PetscCall(MatNormDifference(C, C1, &norm));
200       PetscCheck(norm <= PETSC_SMALL, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatTransposeMatMult(): %g", (double)norm);
201       PetscCall(MatDestroy(&C1));
202 
203       /* Test MatDuplicate() of C=P^T*B */
204       PetscCall(MatDuplicate(C, MAT_COPY_VALUES, &C1));
205       PetscCall(MatDestroy(&C1));
206     } else {
207       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "MatTransposeMatMult not supported\n"));
208     }
209     PetscCall(MatDestroy(&C));
210   }
211 
212   /* 3) MatMatTransposeMult() */
213   /* ------------------------ */
214   if (Test_MatMatTr) {
215     /* C = B*R^T */
216     PetscCall(PetscObjectBaseTypeCompare((PetscObject)B, MATSEQAIJ, &seqaij));
217     if (seqaij) {
218       PetscCall(MatMatTransposeMult(B, R, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &C));
219       PetscCall(MatSetOptionsPrefix(C, "ABt_")); /* enable '-ABt_' for matrix C */
220       PetscCall(MatGetInfo(C, MAT_GLOBAL_SUM, &info));
221 
222       /* Test MAT_REUSE_MATRIX - reuse symbolic C */
223       PetscCall(MatMatTransposeMult(B, R, MAT_REUSE_MATRIX, PETSC_DEFAULT, &C));
224 
225       /* Check */
226       PetscCall(MatMatMult(B, P, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &C1));
227       PetscCall(MatNormDifference(C, C1, &norm));
228       PetscCheck(norm <= PETSC_SMALL, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatMatTransposeMult() %g", (double)norm);
229       PetscCall(MatDestroy(&C1));
230       PetscCall(MatDestroy(&C));
231     }
232   }
233 
234   /* 4) Test MatPtAP() */
235   /*-------------------*/
236   if (Test_MatPtAP) {
237     PetscCall(MatDuplicate(A_save, MAT_COPY_VALUES, &A));
238 
239     /* (4.1) Test developer API */
240     PetscCall(MatProductCreate(A, P, NULL, &C));
241     PetscCall(MatSetOptionsPrefix(C, "PtAP_"));
242     PetscCall(MatProductSetType(C, MATPRODUCT_PtAP));
243     PetscCall(MatProductSetAlgorithm(C, MATPRODUCTALGORITHMDEFAULT));
244     PetscCall(MatProductSetFill(C, PETSC_DEFAULT));
245     PetscCall(MatProductSetFromOptions(C));
246     PetscCall(MatProductSymbolic(C));
247     PetscCall(MatProductNumeric(C));
248     PetscCall(MatPtAPMultEqual(A, P, C, mcheck, &flg));
249     PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatProduct_PtAP");
250     PetscCall(MatProductNumeric(C)); /* reuse symbolic C */
251 
252     PetscCall(MatPtAPMultEqual(A, P, C, mcheck, &flg));
253     PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatProduct_PtAP");
254     PetscCall(MatDestroy(&C));
255 
256     /* (4.2) Test user driver */
257     PetscCall(MatPtAP(A, P, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &C));
258 
259     /* Test MAT_REUSE_MATRIX - reuse symbolic C */
260     alpha = 1.0;
261     for (i = 0; i < 2; i++) {
262       alpha -= 0.1;
263       PetscCall(MatScale(A, alpha));
264       PetscCall(MatPtAP(A, P, MAT_REUSE_MATRIX, PETSC_DEFAULT, &C));
265     }
266     PetscCall(MatPtAPMultEqual(A, P, C, mcheck, &flg));
267     PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatPtAP");
268 
269     /* 5) Test MatRARt() */
270     /* ----------------- */
271     if (Test_MatRARt) {
272       Mat RARt;
273 
274       /* (5.1) Test developer driver RARt = R*A*Rt */
275       PetscCall(MatProductCreate(A, R, NULL, &RARt));
276       PetscCall(MatSetOptionsPrefix(RARt, "RARt_"));
277       PetscCall(MatProductSetType(RARt, MATPRODUCT_RARt));
278       PetscCall(MatProductSetAlgorithm(RARt, MATPRODUCTALGORITHMDEFAULT));
279       PetscCall(MatProductSetFill(RARt, PETSC_DEFAULT));
280       PetscCall(MatProductSetFromOptions(RARt));
281       PetscCall(MatHasOperation(RARt, MATOP_PRODUCTSYMBOLIC, &flg));
282       if (flg) {
283         PetscCall(MatProductSymbolic(RARt));                        /* equivalent to MatSetUp() */
284         PetscCall(MatSetOption(RARt, MAT_USE_INODES, PETSC_FALSE)); /* illustrate how to call MatSetOption() */
285         PetscCall(MatProductNumeric(RARt));
286         PetscCall(MatProductNumeric(RARt)); /* test reuse symbolic RARt */
287         PetscCall(MatDestroy(&RARt));
288 
289         /* (2.2) Test user driver RARt = R*A*Rt */
290         PetscCall(MatRARt(A, R, MAT_INITIAL_MATRIX, 2.0, &RARt));
291         PetscCall(MatRARt(A, R, MAT_REUSE_MATRIX, 2.0, &RARt));
292 
293         PetscCall(MatNormDifference(C, RARt, &norm));
294         PetscCheck(norm <= PETSC_SMALL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "|PtAP - RARt| = %g", (double)norm);
295       } else {
296         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "MatRARt not supported\n"));
297       }
298       PetscCall(MatDestroy(&RARt));
299     }
300 
301     PetscCall(MatDestroy(&A));
302     PetscCall(MatDestroy(&C));
303   }
304 
305   /* Destroy objects */
306   PetscCall(PetscRandomDestroy(&rdm));
307   PetscCall(PetscFree(idxn));
308 
309   PetscCall(MatDestroy(&A_save));
310   PetscCall(MatDestroy(&B));
311   PetscCall(MatDestroy(&P));
312   PetscCall(MatDestroy(&R));
313 
314   PetscCall(PetscFinalize());
315   return 0;
316 }
317 
318 /*TEST
319    test:
320      suffix: 1
321      requires: datafilespath !complex double !defined(PETSC_USE_64BIT_INDICES)
322      args: -fA ${DATAFILESPATH}/matrices/medium -fB ${DATAFILESPATH}/matrices/medium
323      output_file: output/ex62_1.out
324 
325    test:
326      suffix: 2_ab_scalable
327      requires: datafilespath !complex double !defined(PETSC_USE_64BIT_INDICES)
328      args: -fA ${DATAFILESPATH}/matrices/medium -fB ${DATAFILESPATH}/matrices/medium -AB_mat_product_algorithm scalable -matmatmult_via scalable -AtB_mat_product_algorithm outerproduct -mattransposematmult_via outerproduct
329      output_file: output/ex62_1.out
330 
331    test:
332      suffix: 3_ab_scalable_fast
333      requires: datafilespath !complex double !defined(PETSC_USE_64BIT_INDICES)
334      args: -fA ${DATAFILESPATH}/matrices/medium -fB ${DATAFILESPATH}/matrices/medium -AB_mat_product_algorithm scalable_fast -matmatmult_via scalable_fast -matmattransmult_via color
335      output_file: output/ex62_1.out
336 
337    test:
338      suffix: 4_ab_heap
339      requires: datafilespath !complex double !defined(PETSC_USE_64BIT_INDICES)
340      args: -fA ${DATAFILESPATH}/matrices/medium -fB ${DATAFILESPATH}/matrices/medium -AB_mat_product_algorithm heap -matmatmult_via heap -PtAP_mat_product_algorithm rap -matptap_via rap
341      output_file: output/ex62_1.out
342 
343    test:
344      suffix: 5_ab_btheap
345      requires: datafilespath !complex double !defined(PETSC_USE_64BIT_INDICES)
346      args: -fA ${DATAFILESPATH}/matrices/medium -fB ${DATAFILESPATH}/matrices/medium -AB_mat_product_algorithm btheap -matmatmult_via btheap -matrart_via r*art
347      output_file: output/ex62_1.out
348 
349    test:
350      suffix: 6_ab_llcondensed
351      requires: datafilespath !complex double !defined(PETSC_USE_64BIT_INDICES)
352      args: -fA ${DATAFILESPATH}/matrices/medium -fB ${DATAFILESPATH}/matrices/medium -AB_mat_product_algorithm llcondensed -matmatmult_via llcondensed -matrart_via coloring_rart
353      output_file: output/ex62_1.out
354 
355    test:
356      suffix: 7_ab_rowmerge
357      requires: datafilespath !complex double !defined(PETSC_USE_64BIT_INDICES)
358      args: -fA ${DATAFILESPATH}/matrices/medium -fB ${DATAFILESPATH}/matrices/medium -AB_mat_product_algorithm rowmerge -matmatmult_via rowmerge
359      output_file: output/ex62_1.out
360 
361    test:
362      suffix: 8_ab_hypre
363      requires: hypre datafilespath !complex double !defined(PETSC_USE_64BIT_INDICES)
364      args: -fA ${DATAFILESPATH}/matrices/medium -fB ${DATAFILESPATH}/matrices/medium -AB_mat_product_algorithm hypre -matmatmult_via hypre -PtAP_mat_product_algorithm hypre -matptap_via hypre
365      output_file: output/ex62_1.out
366 
367    test:
368      suffix: hypre_medium
369      nsize: {{1 3}}
370      requires: hypre datafilespath !complex double !defined(PETSC_USE_64BIT_INDICES)
371      args: -fA ${DATAFILESPATH}/matrices/medium -fB ${DATAFILESPATH}/matrices/medium -A_mat_type hypre -B_mat_type hypre -test_rart 0
372      output_file: output/ex62_hypre.out
373 
374    test:
375      suffix: hypre_tiny
376      nsize: {{1 3}}
377      requires: hypre !complex double !defined(PETSC_USE_64BIT_INDICES)
378      args: -fA ${wPETSC_DIR}/share/petsc/datafiles/matrices/tiny_system -fB ${wPETSC_DIR}/share/petsc/datafiles/matrices/tiny_system -A_mat_type hypre -B_mat_type hypre -test_rart 0
379      output_file: output/ex62_hypre.out
380 
381    test:
382      suffix: 9_mkl
383      TODO: broken MatScale?
384      requires: mkl_sparse datafilespath !complex double !defined(PETSC_USE_64BIT_INDICES)
385      args: -fA ${DATAFILESPATH}/matrices/medium -fB ${DATAFILESPATH}/matrices/medium -A_mat_type aijmkl -B_mat_type aijmkl
386      output_file: output/ex62_1.out
387 
388    test:
389      suffix: 10
390      requires: datafilespath !complex double !defined(PETSC_USE_64BIT_INDICES)
391      nsize: 3
392      args: -fA ${DATAFILESPATH}/matrices/medium -fB ${DATAFILESPATH}/matrices/medium
393      output_file: output/ex62_1.out
394 
395    test:
396      suffix: 10_backend
397      requires: datafilespath !complex double !defined(PETSC_USE_64BIT_INDICES)
398      nsize: 3
399      args: -fA ${DATAFILESPATH}/matrices/medium -AB_mat_product_algorithm backend -matmatmult_via backend -AtB_mat_product_algorithm backend -mattransposematmult_via backend -PtAP_mat_product_algorithm backend -matptap_via backend
400      output_file: output/ex62_1.out
401 
402    test:
403      suffix: 11_ab_scalable
404      requires: datafilespath !complex double !defined(PETSC_USE_64BIT_INDICES)
405      nsize: 3
406      args: -fA ${DATAFILESPATH}/matrices/medium -fB ${DATAFILESPATH}/matrices/medium -AB_mat_product_algorithm scalable -matmatmult_via scalable -AtB_mat_product_algorithm scalable -mattransposematmult_via scalable
407      output_file: output/ex62_1.out
408 
409    test:
410      suffix: 12_ab_seqmpi
411      requires: datafilespath !complex double !defined(PETSC_USE_64BIT_INDICES)
412      nsize: 3
413      args: -fA ${DATAFILESPATH}/matrices/medium -fB ${DATAFILESPATH}/matrices/medium -AB_mat_product_algorithm seqmpi -matmatmult_via seqmpi -AtB_mat_product_algorithm at*b -mattransposematmult_via at*b
414      output_file: output/ex62_1.out
415 
416    test:
417      suffix: 13_ab_hypre
418      requires: hypre datafilespath !complex double !defined(PETSC_USE_64BIT_INDICES)
419      nsize: 3
420      args: -fA ${DATAFILESPATH}/matrices/medium -fB ${DATAFILESPATH}/matrices/medium -AB_mat_product_algorithm hypre -matmatmult_via hypre -PtAP_mat_product_algorithm hypre -matptap_via hypre
421      output_file: output/ex62_1.out
422 
423    test:
424      suffix: 14_seqaij
425      requires: !complex double !defined(PETSC_USE_64BIT_INDICES)
426      args: -fA ${wPETSC_DIR}/share/petsc/datafiles/matrices/tiny_system -fB ${wPETSC_DIR}/share/petsc/datafiles/matrices/tiny_system
427      output_file: output/ex62_1.out
428 
429    test:
430      suffix: 14_seqaijcusparse
431      requires: cuda !complex double !defined(PETSC_USE_64BIT_INDICES)
432      args: -A_mat_type aijcusparse -B_mat_type aijcusparse -mat_form_explicit_transpose -fA ${wPETSC_DIR}/share/petsc/datafiles/matrices/tiny_system -fB ${wPETSC_DIR}/share/petsc/datafiles/matrices/tiny_system
433      output_file: output/ex62_1.out
434 
435    test:
436      suffix: 14_seqaijcusparse_cpu
437      requires: cuda !complex double !defined(PETSC_USE_64BIT_INDICES)
438      args: -A_mat_type aijcusparse -B_mat_type aijcusparse -mat_form_explicit_transpose -fA ${wPETSC_DIR}/share/petsc/datafiles/matrices/tiny_system -fB ${wPETSC_DIR}/share/petsc/datafiles/matrices/tiny_system -AB_mat_product_algorithm_backend_cpu -matmatmult_backend_cpu -PtAP_mat_product_algorithm_backend_cpu -matptap_backend_cpu -RARt_mat_product_algorithm_backend_cpu -matrart_backend_cpu
439      output_file: output/ex62_1.out
440 
441    test:
442      suffix: 14_mpiaijcusparse_seq
443      nsize: 1
444      requires: cuda !complex double !defined(PETSC_USE_64BIT_INDICES)
445      args: -A_mat_type mpiaijcusparse -B_mat_type mpiaijcusparse -mat_form_explicit_transpose -fA ${wPETSC_DIR}/share/petsc/datafiles/matrices/tiny_system -fB ${wPETSC_DIR}/share/petsc/datafiles/matrices/tiny_system
446      output_file: output/ex62_1.out
447 
448    test:
449      suffix: 14_mpiaijcusparse_seq_cpu
450      nsize: 1
451      requires: cuda !complex double !defined(PETSC_USE_64BIT_INDICES)
452      args: -A_mat_type mpiaijcusparse -B_mat_type mpiaijcusparse -mat_form_explicit_transpose -fA ${wPETSC_DIR}/share/petsc/datafiles/matrices/tiny_system -fB ${wPETSC_DIR}/share/petsc/datafiles/matrices/tiny_system -AB_mat_product_algorithm_backend_cpu -matmatmult_backend_cpu -PtAP_mat_product_algorithm_backend_cpu -matptap_backend_cpu -test_rart 0
453      output_file: output/ex62_1.out
454 
455    test:
456      suffix: 14_mpiaijcusparse
457      nsize: 3
458      requires: cuda !complex double !defined(PETSC_USE_64BIT_INDICES)
459      args: -A_mat_type mpiaijcusparse -B_mat_type mpiaijcusparse -mat_form_explicit_transpose -fA ${wPETSC_DIR}/share/petsc/datafiles/matrices/tiny_system -fB ${wPETSC_DIR}/share/petsc/datafiles/matrices/tiny_system
460      output_file: output/ex62_1.out
461 
462    test:
463      suffix: 14_mpiaijcusparse_cpu
464      nsize: 3
465      requires: cuda !complex double !defined(PETSC_USE_64BIT_INDICES)
466      args: -A_mat_type mpiaijcusparse -B_mat_type mpiaijcusparse -mat_form_explicit_transpose -fA ${wPETSC_DIR}/share/petsc/datafiles/matrices/tiny_system -fB ${wPETSC_DIR}/share/petsc/datafiles/matrices/tiny_system -AB_mat_product_algorithm_backend_cpu -matmatmult_backend_cpu -PtAP_mat_product_algorithm_backend_cpu -matptap_backend_cpu -test_rart 0
467      output_file: output/ex62_1.out
468 
469    test:
470      nsize: {{1 3}}
471      suffix: 14_aijkokkos
472      requires: kokkos_kernels !complex double !defined(PETSC_USE_64BIT_INDICES)
473      args: -A_mat_type aijkokkos -B_mat_type aijkokkos -fA ${wPETSC_DIR}/share/petsc/datafiles/matrices/tiny_system -fB ${wPETSC_DIR}/share/petsc/datafiles/matrices/tiny_system
474      output_file: output/ex62_1.out
475 
476    # these tests use matrices with many zero rows
477    test:
478      suffix: 15_seqaijcusparse
479      requires: cuda !complex double !defined(PETSC_USE_64BIT_INDICES) datafilespath
480      args: -A_mat_type aijcusparse -mat_form_explicit_transpose -fA ${DATAFILESPATH}/matrices/matmatmult/A4.BGriffith
481      output_file: output/ex62_1.out
482 
483    test:
484      suffix: 15_mpiaijcusparse_seq
485      nsize: 1
486      requires: cuda !complex double !defined(PETSC_USE_64BIT_INDICES) datafilespath
487      args: -A_mat_type mpiaijcusparse -mat_form_explicit_transpose -fA ${DATAFILESPATH}/matrices/matmatmult/A4.BGriffith
488      output_file: output/ex62_1.out
489 
490    test:
491      nsize: 3
492      suffix: 15_mpiaijcusparse
493      requires: cuda !complex double !defined(PETSC_USE_64BIT_INDICES) datafilespath
494      args: -A_mat_type mpiaijcusparse -mat_form_explicit_transpose -fA ${DATAFILESPATH}/matrices/matmatmult/A4.BGriffith
495      output_file: output/ex62_1.out
496 
497 TEST*/
498