Actual source code: ex62.c


  2: static char help[] = "Test Matrix products for AIJ matrices\n\
  3: Input arguments are:\n\
  4:   -fA <input_file> -fB <input_file> -fC <input_file>: file to load\n\n";
  5: /* Example of usage:
  6:    ./ex62 -fA <A_binary> -fB <B_binary>
  7:    mpiexec -n 3 ./ex62 -fA medium -fB medium
  8: */

 10: #include <petscmat.h>

 12: /*
 13:      B = A - B
 14:      norm = norm(B)
 15: */
 16: PetscErrorCode MatNormDifference(Mat A, Mat B, PetscReal *norm)
 17: {
 18:   PetscFunctionBegin;
 19:   PetscCall(MatAXPY(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
 20:   PetscCall(MatNorm(B, NORM_FROBENIUS, norm));
 21:   PetscFunctionReturn(PETSC_SUCCESS);
 22: }

 24: int main(int argc, char **args)
 25: {
 26:   Mat          A, A_save, B, C, P, C1, R;
 27:   PetscViewer  viewer;
 28:   PetscMPIInt  size, rank;
 29:   PetscInt     i, j, *idxn, PM, PN = PETSC_DECIDE, rstart, rend;
 30:   PetscReal    norm;
 31:   PetscRandom  rdm;
 32:   char         file[2][PETSC_MAX_PATH_LEN] = {"", ""};
 33:   PetscScalar *a, rval, alpha;
 34:   PetscBool    Test_MatMatMult = PETSC_TRUE, Test_MatTrMat = PETSC_TRUE, Test_MatMatTr = PETSC_TRUE;
 35:   PetscBool    Test_MatPtAP = PETSC_TRUE, Test_MatRARt = PETSC_TRUE, flg, seqaij, flgA, flgB;
 36:   MatInfo      info;
 37:   PetscInt     nzp = 5; /* num of nonzeros in each row of P */
 38:   MatType      mattype;
 39:   const char  *deft = MATAIJ;
 40:   char         A_mattype[256], B_mattype[256];
 41:   PetscInt     mcheck = 10;

 43:   PetscFunctionBeginUser;
 44:   PetscCall(PetscInitialize(&argc, &args, (char *)0, help));
 45:   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
 46:   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));

 48:   /*  Load the matrices A_save and B */
 49:   PetscOptionsBegin(PETSC_COMM_WORLD, "", "", "");
 50:   PetscCall(PetscOptionsBool("-test_rart", "Test MatRARt", "", Test_MatRARt, &Test_MatRARt, NULL));
 51:   PetscCall(PetscOptionsInt("-PN", "Number of columns of P", "", PN, &PN, NULL));
 52:   PetscCall(PetscOptionsInt("-mcheck", "Number of matmult checks", "", mcheck, &mcheck, NULL));
 53:   PetscCall(PetscOptionsString("-fA", "Path for matrix A", "", file[0], file[0], sizeof(file[0]), &flg));
 54:   PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_USER_INPUT, "Must indicate a file name for matrix A with the -fA option.");
 55:   PetscCall(PetscOptionsString("-fB", "Path for matrix B", "", file[1], file[1], sizeof(file[1]), &flg));
 56:   PetscCall(PetscOptionsFList("-A_mat_type", "Matrix type", "MatSetType", MatList, deft, A_mattype, 256, &flgA));
 57:   PetscCall(PetscOptionsFList("-B_mat_type", "Matrix type", "MatSetType", MatList, deft, B_mattype, 256, &flgB));
 58:   PetscOptionsEnd();

 60:   PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, file[0], FILE_MODE_READ, &viewer));
 61:   PetscCall(MatCreate(PETSC_COMM_WORLD, &A_save));
 62:   PetscCall(MatLoad(A_save, viewer));
 63:   PetscCall(PetscViewerDestroy(&viewer));

 65:   if (flg) {
 66:     PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, file[1], FILE_MODE_READ, &viewer));
 67:     PetscCall(MatCreate(PETSC_COMM_WORLD, &B));
 68:     PetscCall(MatLoad(B, viewer));
 69:     PetscCall(PetscViewerDestroy(&viewer));
 70:   } else {
 71:     PetscCall(PetscObjectReference((PetscObject)A_save));
 72:     B = A_save;
 73:   }

 75:   if (flgA) PetscCall(MatConvert(A_save, A_mattype, MAT_INPLACE_MATRIX, &A_save));
 76:   if (flgB) PetscCall(MatConvert(B, B_mattype, MAT_INPLACE_MATRIX, &B));
 77:   PetscCall(MatSetFromOptions(A_save));
 78:   PetscCall(MatSetFromOptions(B));

 80:   PetscCall(MatGetType(B, &mattype));

 82:   PetscCall(PetscMalloc(nzp * (sizeof(PetscInt) + sizeof(PetscScalar)), &idxn));
 83:   a = (PetscScalar *)(idxn + nzp);

 85:   PetscCall(PetscRandomCreate(PETSC_COMM_WORLD, &rdm));
 86:   PetscCall(PetscRandomSetFromOptions(rdm));

 88:   /* 1) MatMatMult() */
 89:   /* ----------------*/
 90:   if (Test_MatMatMult) {
 91:     PetscCall(MatDuplicate(A_save, MAT_COPY_VALUES, &A));

 93:     /* (1.1) Test developer API */
 94:     PetscCall(MatProductCreate(A, B, NULL, &C));
 95:     PetscCall(MatSetOptionsPrefix(C, "AB_"));
 96:     PetscCall(MatProductSetType(C, MATPRODUCT_AB));
 97:     PetscCall(MatProductSetAlgorithm(C, MATPRODUCTALGORITHMDEFAULT));
 98:     PetscCall(MatProductSetFill(C, PETSC_DEFAULT));
 99:     PetscCall(MatProductSetFromOptions(C));
100:     /* we can inquire about MATOP_PRODUCTSYMBOLIC even if the destination matrix type has not been set yet */
101:     PetscCall(MatHasOperation(C, MATOP_PRODUCTSYMBOLIC, &flg));
102:     PetscCall(MatProductSymbolic(C));
103:     PetscCall(MatProductNumeric(C));
104:     PetscCall(MatMatMultEqual(A, B, C, mcheck, &flg));
105:     PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Error in C=A*B");

107:     /* Test reuse symbolic C */
108:     alpha = 0.9;
109:     PetscCall(MatScale(A, alpha));
110:     PetscCall(MatProductNumeric(C));

112:     PetscCall(MatMatMultEqual(A, B, C, mcheck, &flg));
113:     PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Error in C=A*B");
114:     PetscCall(MatDestroy(&C));

116:     /* (1.2) Test user driver */
117:     PetscCall(MatMatMult(A, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &C));

119:     /* Test MAT_REUSE_MATRIX - reuse symbolic C */
120:     alpha = 1.0;
121:     for (i = 0; i < 2; i++) {
122:       alpha -= 0.1;
123:       PetscCall(MatScale(A, alpha));
124:       PetscCall(MatMatMult(A, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &C));
125:     }
126:     PetscCall(MatMatMultEqual(A, B, C, mcheck, &flg));
127:     PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Error: MatMatMult()");
128:     PetscCall(MatDestroy(&A));

130:     /* Test MatProductClear() */
131:     PetscCall(MatProductClear(C));
132:     PetscCall(MatDestroy(&C));

134:     /* Test MatMatMult() for dense and aij matrices */
135:     PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &flg, MATSEQAIJ, MATMPIAIJ, ""));
136:     if (flg) {
137:       PetscCall(MatConvert(A_save, MATDENSE, MAT_INITIAL_MATRIX, &A));
138:       PetscCall(MatMatMult(A, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &C));
139:       PetscCall(MatDestroy(&C));
140:       PetscCall(MatDestroy(&A));
141:     }
142:   }

144:   /* Create P and R = P^T  */
145:   /* --------------------- */
146:   PetscCall(MatGetSize(B, &PM, NULL));
147:   if (PN < 0) PN = PM / 2;
148:   PetscCall(MatCreate(PETSC_COMM_WORLD, &P));
149:   PetscCall(MatSetSizes(P, PETSC_DECIDE, PETSC_DECIDE, PM, PN));
150:   PetscCall(MatSetType(P, MATAIJ));
151:   PetscCall(MatSeqAIJSetPreallocation(P, nzp, NULL));
152:   PetscCall(MatMPIAIJSetPreallocation(P, nzp, NULL, nzp, NULL));
153:   PetscCall(MatGetOwnershipRange(P, &rstart, &rend));
154:   for (i = 0; i < nzp; i++) PetscCall(PetscRandomGetValue(rdm, &a[i]));
155:   for (i = rstart; i < rend; i++) {
156:     for (j = 0; j < nzp; j++) {
157:       PetscCall(PetscRandomGetValue(rdm, &rval));
158:       idxn[j] = (PetscInt)(PetscRealPart(rval) * PN);
159:     }
160:     PetscCall(MatSetValues(P, 1, &i, nzp, idxn, a, ADD_VALUES));
161:   }
162:   PetscCall(MatAssemblyBegin(P, MAT_FINAL_ASSEMBLY));
163:   PetscCall(MatAssemblyEnd(P, MAT_FINAL_ASSEMBLY));

165:   PetscCall(MatTranspose(P, MAT_INITIAL_MATRIX, &R));
166:   PetscCall(MatConvert(P, mattype, MAT_INPLACE_MATRIX, &P));
167:   PetscCall(MatConvert(R, mattype, MAT_INPLACE_MATRIX, &R));
168:   PetscCall(MatSetFromOptions(P));
169:   PetscCall(MatSetFromOptions(R));

171:   /* 2) MatTransposeMatMult() */
172:   /* ------------------------ */
173:   if (Test_MatTrMat) {
174:     /* (2.1) Test developer driver C = P^T*B */
175:     PetscCall(MatProductCreate(P, B, NULL, &C));
176:     PetscCall(MatSetOptionsPrefix(C, "AtB_"));
177:     PetscCall(MatProductSetType(C, MATPRODUCT_AtB));
178:     PetscCall(MatProductSetAlgorithm(C, MATPRODUCTALGORITHMDEFAULT));
179:     PetscCall(MatProductSetFill(C, PETSC_DEFAULT));
180:     PetscCall(MatProductSetFromOptions(C));
181:     PetscCall(MatHasOperation(C, MATOP_PRODUCTSYMBOLIC, &flg));
182:     if (flg) {                                                 /* run tests if supported */
183:       PetscCall(MatProductSymbolic(C));                        /* equivalent to MatSetUp() */
184:       PetscCall(MatSetOption(C, MAT_USE_INODES, PETSC_FALSE)); /* illustrate how to call MatSetOption() */
185:       PetscCall(MatProductNumeric(C));
186:       PetscCall(MatProductNumeric(C)); /* test reuse symbolic C */

188:       PetscCall(MatTransposeMatMultEqual(P, B, C, mcheck, &flg));
189:       PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error: developer driver C = P^T*B");
190:       PetscCall(MatDestroy(&C));

192:       /* (2.2) Test user driver C = P^T*B */
193:       PetscCall(MatTransposeMatMult(P, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &C));
194:       PetscCall(MatTransposeMatMult(P, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &C));
195:       PetscCall(MatGetInfo(C, MAT_GLOBAL_SUM, &info));
196:       PetscCall(MatProductClear(C));

198:       /* Compare P^T*B and R*B */
199:       PetscCall(MatMatMult(R, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &C1));
200:       PetscCall(MatNormDifference(C, C1, &norm));
201:       PetscCheck(norm <= PETSC_SMALL, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatTransposeMatMult(): %g", (double)norm);
202:       PetscCall(MatDestroy(&C1));

204:       /* Test MatDuplicate() of C=P^T*B */
205:       PetscCall(MatDuplicate(C, MAT_COPY_VALUES, &C1));
206:       PetscCall(MatDestroy(&C1));
207:     } else {
208:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "MatTransposeMatMult not supported\n"));
209:     }
210:     PetscCall(MatDestroy(&C));
211:   }

213:   /* 3) MatMatTransposeMult() */
214:   /* ------------------------ */
215:   if (Test_MatMatTr) {
216:     /* C = B*R^T */
217:     PetscCall(PetscObjectBaseTypeCompare((PetscObject)B, MATSEQAIJ, &seqaij));
218:     if (seqaij) {
219:       PetscCall(MatMatTransposeMult(B, R, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &C));
220:       PetscCall(MatSetOptionsPrefix(C, "ABt_")); /* enable '-ABt_' for matrix C */
221:       PetscCall(MatGetInfo(C, MAT_GLOBAL_SUM, &info));

223:       /* Test MAT_REUSE_MATRIX - reuse symbolic C */
224:       PetscCall(MatMatTransposeMult(B, R, MAT_REUSE_MATRIX, PETSC_DEFAULT, &C));

226:       /* Check */
227:       PetscCall(MatMatMult(B, P, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &C1));
228:       PetscCall(MatNormDifference(C, C1, &norm));
229:       PetscCheck(norm <= PETSC_SMALL, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatMatTransposeMult() %g", (double)norm);
230:       PetscCall(MatDestroy(&C1));
231:       PetscCall(MatDestroy(&C));
232:     }
233:   }

235:   /* 4) Test MatPtAP() */
236:   /*-------------------*/
237:   if (Test_MatPtAP) {
238:     PetscCall(MatDuplicate(A_save, MAT_COPY_VALUES, &A));

240:     /* (4.1) Test developer API */
241:     PetscCall(MatProductCreate(A, P, NULL, &C));
242:     PetscCall(MatSetOptionsPrefix(C, "PtAP_"));
243:     PetscCall(MatProductSetType(C, MATPRODUCT_PtAP));
244:     PetscCall(MatProductSetAlgorithm(C, MATPRODUCTALGORITHMDEFAULT));
245:     PetscCall(MatProductSetFill(C, PETSC_DEFAULT));
246:     PetscCall(MatProductSetFromOptions(C));
247:     PetscCall(MatProductSymbolic(C));
248:     PetscCall(MatProductNumeric(C));
249:     PetscCall(MatPtAPMultEqual(A, P, C, mcheck, &flg));
250:     PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatProduct_PtAP");
251:     PetscCall(MatProductNumeric(C)); /* reuse symbolic C */

253:     PetscCall(MatPtAPMultEqual(A, P, C, mcheck, &flg));
254:     PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatProduct_PtAP");
255:     PetscCall(MatDestroy(&C));

257:     /* (4.2) Test user driver */
258:     PetscCall(MatPtAP(A, P, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &C));

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_DEFAULT, &C));
266:     }
267:     PetscCall(MatPtAPMultEqual(A, P, C, mcheck, &flg));
268:     PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatPtAP");

270:     /* 5) Test MatRARt() */
271:     /* ----------------- */
272:     if (Test_MatRARt) {
273:       Mat RARt;

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_DEFAULT));
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));

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));

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:     }

302:     PetscCall(MatDestroy(&A));
303:     PetscCall(MatDestroy(&C));
304:   }

306:   /* Destroy objects */
307:   PetscCall(PetscRandomDestroy(&rdm));
308:   PetscCall(PetscFree(idxn));

310:   PetscCall(MatDestroy(&A_save));
311:   PetscCall(MatDestroy(&B));
312:   PetscCall(MatDestroy(&P));
313:   PetscCall(MatDestroy(&R));

315:   PetscCall(PetscFinalize());
316:   return 0;
317: }

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/ex62_1.out

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/ex62_1.out

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/ex62_1.out

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/ex62_1.out

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/ex62_1.out

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/ex62_1.out

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/ex62_1.out

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/ex62_1.out

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

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

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/ex62_1.out

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/ex62_1.out

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/ex62_1.out

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/ex62_1.out

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/ex62_1.out

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/ex62_1.out

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/ex62_1.out

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/ex62_1.out

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/ex62_1.out

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/ex62_1.out

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/ex62_1.out

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/ex62_1.out

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/ex62_1.out

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/ex62_1.out

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/ex62_1.out

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/ex62_1.out

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/ex62_1.out

498: TEST*/