xref: /petsc/src/mat/tutorials/ex3.c (revision 609caa7c8c030312b00807b4f015fd827bb80932)
152030a5eSPierre Jolivet static char help[] = "Illustration of MatIS using a 1D Laplacian assembly\n\n";
2c4762a1bSJed Brown 
3c4762a1bSJed Brown /*
4c4762a1bSJed Brown   MatIS means that the matrix is not assembled. The easiest way to think of this (for me) is that processes do not have
5c4762a1bSJed Brown   to hold full matrix rows. One process can hold part of row i, and another processes can hold another part. However, there
6c4762a1bSJed Brown   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
7c4762a1bSJed Brown   overlap size, since that is a property only of MatIS. It is the size of the local piece of the vector you multiply in
8c4762a1bSJed Brown   MatMult(). This allows PETSc to understand the parallel layout of the Vec, and how it matches the Mat. If you only know
9c4762a1bSJed Brown   the overlap size when assembling, it is best to use PETSC_DECIDE for the local size in the creation routine, so that PETSc
10c4762a1bSJed Brown   automatically partitions the unknowns.
11c4762a1bSJed Brown 
12c4762a1bSJed Brown   Each P_1 element matrix for a cell will be
13c4762a1bSJed Brown 
14c4762a1bSJed Brown     /  1 -1 \
15c4762a1bSJed Brown     \ -1  1 /
16c4762a1bSJed Brown 
17c4762a1bSJed Brown   so that the assembled matrix has a tridiagonal [-1, 2, -1] pattern. We will use 1 cell per process for illustration,
18c4762a1bSJed Brown   and allow PETSc to decide the ownership.
19c4762a1bSJed Brown */
20c4762a1bSJed Brown 
21c4762a1bSJed Brown #include <petscmat.h>
22c4762a1bSJed Brown 
main(int argc,char ** argv)23d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv)
24d71ae5a4SJacob Faibussowitsch {
25c4762a1bSJed Brown   MPI_Comm               comm;
26c4762a1bSJed Brown   Mat                    A;
27c4762a1bSJed Brown   Vec                    x, y;
28c4762a1bSJed Brown   ISLocalToGlobalMapping map;
29c4762a1bSJed Brown   PetscScalar            elemMat[4] = {1.0, -1.0, -1.0, 1.0};
30c4762a1bSJed Brown   PetscReal              error;
31c4762a1bSJed Brown   PetscInt               overlapSize = 2, globalIdx[2];
32c4762a1bSJed Brown   PetscMPIInt            rank, size;
33c4762a1bSJed Brown 
34327415f7SBarry Smith   PetscFunctionBeginUser;
359566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
36c4762a1bSJed Brown   comm = PETSC_COMM_WORLD;
379566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
389566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
39c4762a1bSJed Brown   /* Create local-to-global map */
40c4762a1bSJed Brown   globalIdx[0] = rank;
41c4762a1bSJed Brown   globalIdx[1] = rank + 1;
429566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreate(comm, 1, overlapSize, globalIdx, PETSC_COPY_VALUES, &map));
43c4762a1bSJed Brown   /* Create matrix */
449566063dSJacob Faibussowitsch   PetscCall(MatCreateIS(comm, 1, PETSC_DECIDE, PETSC_DECIDE, size + 1, size + 1, map, map, &A));
459566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)A, "A"));
469566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&map));
479566063dSJacob Faibussowitsch   PetscCall(MatISSetPreallocation(A, overlapSize, NULL, overlapSize, NULL));
489566063dSJacob Faibussowitsch   PetscCall(MatSetValues(A, 2, globalIdx, 2, globalIdx, elemMat, ADD_VALUES));
499566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
509566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
51c4762a1bSJed Brown   /* Check that the constant vector is in the nullspace */
529566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(A, &x, &y));
539566063dSJacob Faibussowitsch   PetscCall(VecSet(x, 1.0));
549566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)x, "x"));
559566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(x, NULL, "-x_view"));
569566063dSJacob Faibussowitsch   PetscCall(MatMult(A, x, y));
579566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)y, "y"));
589566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(y, NULL, "-y_view"));
599566063dSJacob Faibussowitsch   PetscCall(VecNorm(y, NORM_2, &error));
60e00437b9SBarry Smith   PetscCheck(error <= PETSC_SMALL, comm, PETSC_ERR_ARG_WRONG, "Invalid output, x should be in the nullspace of A");
61c4762a1bSJed Brown   /* Check that an interior unit vector gets mapped to something of 1-norm 4 */
62c4762a1bSJed Brown   if (size > 1) {
639566063dSJacob Faibussowitsch     PetscCall(VecSet(x, 0.0));
649566063dSJacob Faibussowitsch     PetscCall(VecSetValue(x, 1, 1.0, INSERT_VALUES));
659566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(x));
669566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(x));
679566063dSJacob Faibussowitsch     PetscCall(MatMult(A, x, y));
689566063dSJacob Faibussowitsch     PetscCall(VecNorm(y, NORM_1, &error));
69e00437b9SBarry Smith     PetscCheck(PetscAbsReal(error - 4) <= PETSC_SMALL, comm, PETSC_ERR_ARG_WRONG, "Invalid output for matrix multiply");
70c4762a1bSJed Brown   }
71c4762a1bSJed Brown   /* Cleanup */
729566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A));
739566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
749566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y));
759566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
76b122ec5aSJacob Faibussowitsch   return 0;
77c4762a1bSJed Brown }
78c4762a1bSJed Brown 
79c4762a1bSJed Brown /*TEST
80c4762a1bSJed Brown 
81c4762a1bSJed Brown   test:
82c4762a1bSJed Brown     suffix: 0
83c4762a1bSJed Brown     requires:
84c4762a1bSJed Brown     args:
85*3886731fSPierre Jolivet     output_file: output/empty.out
86c4762a1bSJed Brown 
87c4762a1bSJed Brown   test:
88c4762a1bSJed Brown     suffix: 1
89c4762a1bSJed Brown     nsize: 3
90c4762a1bSJed Brown     args:
91*3886731fSPierre Jolivet     output_file: output/empty.out
92c4762a1bSJed Brown 
93c4762a1bSJed Brown   test:
94c4762a1bSJed Brown     suffix: 2
95c4762a1bSJed Brown     nsize: 7
96c4762a1bSJed Brown     args:
97*3886731fSPierre Jolivet     output_file: output/empty.out
98c4762a1bSJed Brown 
99c4762a1bSJed Brown TEST*/
100