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