Actual source code: ex308.c
1: static char help[] = "Tests MatGetMultPetscSF() for the parallel AIJ, BAIJ, SBAIJ, dense, and SELL matrix types.\n\n";
3: #include <petscmat.h>
4: #include <petscsf.h>
6: int main(int argc, char **argv)
7: {
8: Mat A;
9: Vec x, y;
10: PetscSF sf;
11: PetscBool isdense;
12: PetscInt N = 12, rstart, rend, cstart, cend, nroots, nleaves, i, ok = 1;
13: PetscInt *rootdata = NULL, *leafdata = NULL;
15: PetscFunctionBeginUser;
16: PetscCall(PetscInitialize(&argc, &argv, NULL, help));
17: PetscCall(PetscOptionsGetInt(NULL, NULL, "-n", &N, NULL));
19: /* Build a symmetric tridiagonal matrix; the type is selected with -mat_type. */
20: PetscCall(MatCreate(PETSC_COMM_WORLD, &A));
21: PetscCall(MatSetSizes(A, PETSC_DECIDE, PETSC_DECIDE, N, N));
22: PetscCall(MatSetType(A, MATMPIAIJ));
23: PetscCall(MatSetFromOptions(A));
24: PetscCall(MatSetUp(A));
25: PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
26: for (i = rstart; i < rend; i++) {
27: PetscScalar diag = 2.0, offd = -1.0;
29: PetscCall(MatSetValue(A, i, i, diag, INSERT_VALUES));
30: if (i + 1 < N) PetscCall(MatSetValue(A, i, i + 1, offd, INSERT_VALUES));
31: if (i - 1 >= 0) PetscCall(MatSetValue(A, i, i - 1, offd, INSERT_VALUES));
32: }
33: PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
34: PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
36: PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMPIDENSE, &isdense));
37: if (isdense) {
38: /* Dense builds its matrix-multiply PetscSF lazily on the first MatMult(), so trigger it first.
39: The SF is an allgather: every rank gathers all N global columns. */
40: PetscCall(MatCreateVecs(A, &x, &y));
41: PetscCall(VecSet(x, 1.0));
42: PetscCall(MatMult(A, x, y));
43: PetscCall(MatGetMultPetscSF(A, &sf));
44: PetscCheck(sf, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "MatGetMultPetscSF() returned NULL on a parallel dense matrix after MatMult()");
45: PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL));
46: if (nleaves != N) ok = 0;
47: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &ok, 1, MPIU_INT, MPI_LAND, PETSC_COMM_WORLD));
48: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "MatGetMultPetscSF() OK (PetscSF valid, allgather sees all columns: %s)\n", ok ? "yes" : "no"));
49: PetscCall(VecDestroy(&x));
50: PetscCall(VecDestroy(&y));
51: } else {
52: PetscCall(MatGetMultPetscSF(A, &sf));
53: PetscCheck(sf, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "MatGetMultPetscSF() returned NULL on a parallel matrix");
55: /* Broadcast each owned global column index to the off-process columns that couple
56: to local rows; every gathered value must lie outside the local column ownership range. */
57: PetscCall(MatGetOwnershipRangeColumn(A, &cstart, &cend));
58: PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL));
59: PetscCall(PetscMalloc2(nroots, &rootdata, nleaves, &leafdata));
60: for (i = 0; i < nroots; i++) rootdata[i] = cstart + i;
61: PetscCall(PetscSFBcastBegin(sf, MPIU_INT, rootdata, leafdata, MPI_REPLACE));
62: PetscCall(PetscSFBcastEnd(sf, MPIU_INT, rootdata, leafdata, MPI_REPLACE));
63: for (i = 0; i < nleaves; i++)
64: if (leafdata[i] < 0 || leafdata[i] >= N || (leafdata[i] >= cstart && leafdata[i] < cend)) ok = 0;
65: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &ok, 1, MPIU_INT, MPI_LAND, PETSC_COMM_WORLD));
66: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "MatGetMultPetscSF() OK (PetscSF valid, all gathered columns off-process: %s)\n", ok ? "yes" : "no"));
67: PetscCall(PetscFree2(rootdata, leafdata));
68: }
69: PetscCall(MatDestroy(&A));
70: PetscCall(PetscFinalize());
71: return 0;
72: }
74: /*TEST
76: test:
77: suffix: aij
78: nsize: {{2 3}}
79: args: -mat_type mpiaij
80: output_file: output/ex308.out
82: test:
83: suffix: baij
84: nsize: {{2 3}}
85: args: -mat_type mpibaij
86: output_file: output/ex308.out
88: test:
89: suffix: sbaij
90: nsize: {{2 3}}
91: args: -mat_type mpisbaij
92: output_file: output/ex308.out
94: test:
95: suffix: kokkos
96: requires: kokkos_kernels
97: nsize: {{2 3}}
98: args: -mat_type mpiaijkokkos
99: output_file: output/ex308.out
101: test:
102: suffix: dense
103: nsize: {{2 3}}
104: args: -mat_type mpidense
105: output_file: output/ex308_dense.out
107: test:
108: suffix: sell
109: nsize: {{2 3}}
110: args: -mat_type mpisell
111: output_file: output/ex308.out
113: TEST*/