Actual source code: ex3.c
1: static char help[] = "Illustration of MatIS using a 1D Laplacian assembly\n\n";
3: /*
4: MatIS means that the matrix is not assembled. The easiest way to think of this (for me) is that processes do not have
5: to hold full matrix rows. One process can hold part of row i, and another processes can hold another part. However, there
6: are still the same number of global rows. The local size here is not the size of the local IS block, which we call the
7: overlap size, since that is a property only of MatIS. It is the size of the local piece of the vector you multiply in
8: MatMult(). This allows PETSc to understand the parallel layout of the Vec, and how it matches the Mat. If you only know
9: the overlap size when assembling, it is best to use PETSC_DECIDE for the local size in the creation routine, so that PETSc
10: automatically partitions the unknowns.
12: Each P_1 element matrix for a cell will be
14: / 1 -1 \
15: \ -1 1 /
17: so that the assembled matrix has a tridiagonal [-1, 2, -1] pattern. We will use 1 cell per process for illustration,
18: and allow PETSc to decide the ownership.
19: */
21: #include <petscmat.h>
23: int main(int argc, char **argv)
24: {
25: MPI_Comm comm;
26: Mat A;
27: Vec x, y;
28: ISLocalToGlobalMapping map;
29: PetscScalar elemMat[4] = {1.0, -1.0, -1.0, 1.0};
30: PetscReal error;
31: PetscInt overlapSize = 2, globalIdx[2];
32: PetscMPIInt rank, size;
35: PetscInitialize(&argc, &argv, NULL, help);
36: comm = PETSC_COMM_WORLD;
37: MPI_Comm_rank(comm, &rank);
38: MPI_Comm_size(comm, &size);
39: /* Create local-to-global map */
40: globalIdx[0] = rank;
41: globalIdx[1] = rank + 1;
42: ISLocalToGlobalMappingCreate(comm, 1, overlapSize, globalIdx, PETSC_COPY_VALUES, &map);
43: /* Create matrix */
44: MatCreateIS(comm, 1, PETSC_DECIDE, PETSC_DECIDE, size + 1, size + 1, map, map, &A);
45: PetscObjectSetName((PetscObject)A, "A");
46: ISLocalToGlobalMappingDestroy(&map);
47: MatISSetPreallocation(A, overlapSize, NULL, overlapSize, NULL);
48: MatSetValues(A, 2, globalIdx, 2, globalIdx, elemMat, ADD_VALUES);
49: MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);
50: MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);
51: /* Check that the constant vector is in the nullspace */
52: MatCreateVecs(A, &x, &y);
53: VecSet(x, 1.0);
54: PetscObjectSetName((PetscObject)x, "x");
55: VecViewFromOptions(x, NULL, "-x_view");
56: MatMult(A, x, y);
57: PetscObjectSetName((PetscObject)y, "y");
58: VecViewFromOptions(y, NULL, "-y_view");
59: VecNorm(y, NORM_2, &error);
61: /* Check that an interior unit vector gets mapped to something of 1-norm 4 */
62: if (size > 1) {
63: VecSet(x, 0.0);
64: VecSetValue(x, 1, 1.0, INSERT_VALUES);
65: VecAssemblyBegin(x);
66: VecAssemblyEnd(x);
67: MatMult(A, x, y);
68: VecNorm(y, NORM_1, &error);
70: }
71: /* Cleanup */
72: MatDestroy(&A);
73: VecDestroy(&x);
74: VecDestroy(&y);
75: PetscFinalize();
76: return 0;
77: }
79: /*TEST
81: test:
82: suffix: 0
83: requires:
84: args:
86: test:
87: suffix: 1
88: nsize: 3
89: args:
91: test:
92: suffix: 2
93: nsize: 7
94: args:
96: TEST*/