1 static char help[] = "Illustration of MatIS using a 1D Laplacian assembly\n\n"; 2 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. 11 12 Each P_1 element matrix for a cell will be 13 14 / 1 -1 \ 15 \ -1 1 / 16 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 */ 20 21 #include <petscmat.h> 22 23 int main(int argc, char **argv) { 24 MPI_Comm comm; 25 Mat A; 26 Vec x, y; 27 ISLocalToGlobalMapping map; 28 PetscScalar elemMat[4] = {1.0, -1.0, -1.0, 1.0}; 29 PetscReal error; 30 PetscInt overlapSize = 2, globalIdx[2]; 31 PetscMPIInt rank, size; 32 33 PetscFunctionBeginUser; 34 PetscCall(PetscInitialize(&argc, &argv, NULL, help)); 35 comm = PETSC_COMM_WORLD; 36 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 37 PetscCallMPI(MPI_Comm_size(comm, &size)); 38 /* Create local-to-global map */ 39 globalIdx[0] = rank; 40 globalIdx[1] = rank+1; 41 PetscCall(ISLocalToGlobalMappingCreate(comm, 1, overlapSize, globalIdx, PETSC_COPY_VALUES, &map)); 42 /* Create matrix */ 43 PetscCall(MatCreateIS(comm, 1, PETSC_DECIDE, PETSC_DECIDE, size+1, size+1, map, map, &A)); 44 PetscCall(PetscObjectSetName((PetscObject) A, "A")); 45 PetscCall(ISLocalToGlobalMappingDestroy(&map)); 46 PetscCall(MatISSetPreallocation(A, overlapSize, NULL, overlapSize, NULL)); 47 PetscCall(MatSetValues(A, 2, globalIdx, 2, globalIdx, elemMat, ADD_VALUES)); 48 PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 49 PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 50 /* Check that the constant vector is in the nullspace */ 51 PetscCall(MatCreateVecs(A, &x, &y)); 52 PetscCall(VecSet(x, 1.0)); 53 PetscCall(PetscObjectSetName((PetscObject) x, "x")); 54 PetscCall(VecViewFromOptions(x, NULL, "-x_view")); 55 PetscCall(MatMult(A, x, y)); 56 PetscCall(PetscObjectSetName((PetscObject) y, "y")); 57 PetscCall(VecViewFromOptions(y, NULL, "-y_view")); 58 PetscCall(VecNorm(y, NORM_2, &error)); 59 PetscCheck(error <= PETSC_SMALL,comm, PETSC_ERR_ARG_WRONG, "Invalid output, x should be in the nullspace of A"); 60 /* Check that an interior unit vector gets mapped to something of 1-norm 4 */ 61 if (size > 1) { 62 PetscCall(VecSet(x, 0.0)); 63 PetscCall(VecSetValue(x, 1, 1.0, INSERT_VALUES)); 64 PetscCall(VecAssemblyBegin(x)); 65 PetscCall(VecAssemblyEnd(x)); 66 PetscCall(MatMult(A, x, y)); 67 PetscCall(VecNorm(y, NORM_1, &error)); 68 PetscCheck(PetscAbsReal(error - 4) <= PETSC_SMALL,comm, PETSC_ERR_ARG_WRONG, "Invalid output for matrix multiply"); 69 } 70 /* Cleanup */ 71 PetscCall(MatDestroy(&A)); 72 PetscCall(VecDestroy(&x)); 73 PetscCall(VecDestroy(&y)); 74 PetscCall(PetscFinalize()); 75 return 0; 76 } 77 78 /*TEST 79 80 test: 81 suffix: 0 82 requires: 83 args: 84 85 test: 86 suffix: 1 87 nsize: 3 88 args: 89 90 test: 91 suffix: 2 92 nsize: 7 93 args: 94 95 TEST*/ 96