Actual source code: ex8.c
1: static char help[] = "Shows how to add a new MatOperation to AIJ MatType\n\n";
3: #include <petscmat.h>
4: #include <petscblaslapack.h>
6: static PetscErrorCode MatScaleUserImpl_SeqAIJ(Mat inA, PetscScalar alpha)
7: {
8: PetscFunctionBegin;
9: PetscCall(MatScale(inA, alpha));
10: PetscFunctionReturn(PETSC_SUCCESS);
11: }
13: extern PetscErrorCode MatScaleUserImpl(Mat, PetscScalar);
15: static PetscErrorCode MatScaleUserImpl_MPIAIJ(Mat A, PetscScalar aa)
16: {
17: Mat AA, AB;
19: PetscFunctionBegin;
20: PetscCall(MatMPIAIJGetSeqAIJ(A, &AA, &AB, NULL));
21: PetscCall(MatScaleUserImpl(AA, aa));
22: PetscCall(MatScaleUserImpl(AB, aa));
23: PetscFunctionReturn(PETSC_SUCCESS);
24: }
26: /* This routine registers MatScaleUserImpl_SeqAIJ() and
27: MatScaleUserImpl_MPIAIJ() as methods providing MatScaleUserImpl()
28: functionality for SeqAIJ and MPIAIJ matrix-types */
29: PetscErrorCode RegisterMatScaleUserImpl(Mat mat)
30: {
31: PetscMPIInt size;
33: PetscFunctionBegin;
34: PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
35: if (size == 1) { /* SeqAIJ Matrix */
36: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatScaleUserImpl_C", MatScaleUserImpl_SeqAIJ));
37: } else { /* MPIAIJ Matrix */
38: Mat AA, AB;
39: PetscCall(MatMPIAIJGetSeqAIJ(mat, &AA, &AB, NULL));
40: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatScaleUserImpl_C", MatScaleUserImpl_MPIAIJ));
41: PetscCall(PetscObjectComposeFunction((PetscObject)AA, "MatScaleUserImpl_C", MatScaleUserImpl_SeqAIJ));
42: PetscCall(PetscObjectComposeFunction((PetscObject)AB, "MatScaleUserImpl_C", MatScaleUserImpl_SeqAIJ));
43: }
44: PetscFunctionReturn(PETSC_SUCCESS);
45: }
47: /* This routine deregisters MatScaleUserImpl_SeqAIJ() and
48: MatScaleUserImpl_MPIAIJ() as methods providing MatScaleUserImpl()
49: functionality for SeqAIJ and MPIAIJ matrix-types */
50: PetscErrorCode DeRegisterMatScaleUserImpl(Mat mat)
51: {
52: PetscMPIInt size;
54: PetscFunctionBegin;
55: PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
56: if (size == 1) { /* SeqAIJ Matrix */
57: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatScaleUserImpl_C", NULL));
58: } else { /* MPIAIJ Matrix */
59: Mat AA, AB;
60: PetscCall(MatMPIAIJGetSeqAIJ(mat, &AA, &AB, NULL));
61: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatScaleUserImpl_C", NULL));
62: PetscCall(PetscObjectComposeFunction((PetscObject)AA, "MatScaleUserImpl_C", NULL));
63: PetscCall(PetscObjectComposeFunction((PetscObject)AB, "MatScaleUserImpl_C", NULL));
64: }
65: PetscFunctionReturn(PETSC_SUCCESS);
66: }
68: /* this routines queries the already registered MatScaleUserImp_XXX
69: implementations for the given matrix, and calls the correct
70: routine. i.e if MatType is SeqAIJ, MatScaleUserImpl_SeqAIJ() gets
71: called, and if MatType is MPIAIJ, MatScaleUserImpl_MPIAIJ() gets
72: called */
73: PetscErrorCode MatScaleUserImpl(Mat mat, PetscScalar a)
74: {
75: PetscErrorCode (*f)(Mat, PetscScalar);
77: PetscFunctionBegin;
78: PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatScaleUserImpl_C", &f));
79: if (f) PetscCall((*f)(mat, a));
80: PetscFunctionReturn(PETSC_SUCCESS);
81: }
83: /* Main user code that uses MatScaleUserImpl() */
85: int main(int argc, char **args)
86: {
87: Mat mat;
88: PetscInt i, j, m = 2, n, Ii, J;
89: PetscScalar v, none = -1.0;
90: PetscMPIInt rank, size;
92: PetscFunctionBeginUser;
93: PetscCall(PetscInitialize(&argc, &args, (char *)0, help));
94: PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
95: PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
96: n = 2 * size;
98: /* create the matrix */
99: PetscCall(MatCreate(PETSC_COMM_WORLD, &mat));
100: PetscCall(MatSetSizes(mat, PETSC_DECIDE, PETSC_DECIDE, m * n, m * n));
101: PetscCall(MatSetType(mat, MATAIJ));
102: PetscCall(MatSetUp(mat));
104: /* register user defined MatScaleUser() operation for both SeqAIJ
105: and MPIAIJ types */
106: PetscCall(RegisterMatScaleUserImpl(mat));
108: /* assemble the matrix */
109: for (i = 0; i < m; i++) {
110: for (j = 2 * rank; j < 2 * rank + 2; j++) {
111: v = -1.0;
112: Ii = j + n * i;
113: if (i > 0) {
114: J = Ii - n;
115: PetscCall(MatSetValues(mat, 1, &Ii, 1, &J, &v, INSERT_VALUES));
116: }
117: if (i < m - 1) {
118: J = Ii + n;
119: PetscCall(MatSetValues(mat, 1, &Ii, 1, &J, &v, INSERT_VALUES));
120: }
121: if (j > 0) {
122: J = Ii - 1;
123: PetscCall(MatSetValues(mat, 1, &Ii, 1, &J, &v, INSERT_VALUES));
124: }
125: if (j < n - 1) {
126: J = Ii + 1;
127: PetscCall(MatSetValues(mat, 1, &Ii, 1, &J, &v, INSERT_VALUES));
128: }
129: v = 4.0;
130: PetscCall(MatSetValues(mat, 1, &Ii, 1, &Ii, &v, INSERT_VALUES));
131: }
132: }
133: PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
134: PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY));
136: /* check the matrix before and after scaling by -1.0 */
137: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Matrix _before_ MatScaleUserImpl() operation\n"));
138: PetscCall(MatView(mat, PETSC_VIEWER_STDOUT_WORLD));
139: PetscCall(MatScaleUserImpl(mat, none));
140: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Matrix _after_ MatScaleUserImpl() operation\n"));
141: PetscCall(MatView(mat, PETSC_VIEWER_STDOUT_WORLD));
143: /* deregister user defined MatScaleUser() operation for both SeqAIJ
144: and MPIAIJ types */
145: PetscCall(DeRegisterMatScaleUserImpl(mat));
146: PetscCall(MatDestroy(&mat));
147: PetscCall(PetscFinalize());
148: return 0;
149: }
151: /*TEST
153: test:
155: test:
156: suffix: 2
157: nsize: 2
159: TEST*/