Actual source code: ex88.c
petsc-3.8.4 2018-03-24
2: static char help[] = "Tests MatShift(), MatScale(), and MatDiagonalScale() for SHELL and NEST matrices\n\n";
4: #include <petscmat.h>
6: typedef struct _n_User *User;
7: struct _n_User {
8: Mat B;
9: };
11: static PetscErrorCode MatView_User(Mat A,PetscViewer viewer)
12: {
13: User user;
17: MatShellGetContext(A,&user);
18: MatView(user->B,viewer);
19: return(0);
20: }
22: static PetscErrorCode MatMult_User(Mat A,Vec X,Vec Y)
23: {
24: User user;
28: MatShellGetContext(A,&user);
29: MatMult(user->B,X,Y);
30: return(0);
31: }
33: static PetscErrorCode MatMultTranspose_User(Mat A,Vec X,Vec Y)
34: {
35: User user;
39: MatShellGetContext(A,&user);
40: MatMultTranspose(user->B,X,Y);
41: return(0);
42: }
44: static PetscErrorCode MatGetDiagonal_User(Mat A,Vec X)
45: {
46: User user;
50: MatShellGetContext(A,&user);
51: MatGetDiagonal(user->B,X);
52: return(0);
53: }
55: static PetscErrorCode MatDiagonalSet_User(Mat A,Vec D,InsertMode is)
56: {
57: User user;
61: MatShellGetContext(A,&user);
62: MatDiagonalSet(user->B,D,is);
63: return(0);
64: }
67: static PetscErrorCode TestMatrix(Mat A,Vec X,Vec Y,Vec Z)
68: {
70: Vec W1,W2;
71: Mat E;
72: const char *mattypename;
73: PetscViewer viewer = PETSC_VIEWER_STDOUT_WORLD;
76: VecDuplicate(X,&W1);
77: VecDuplicate(X,&W2);
78: MatScale(A,31);
79: MatShift(A,37);
80: MatDiagonalScale(A,X,Y);
81: MatScale(A,41);
82: MatDiagonalScale(A,Y,Z);
83: MatComputeExplicitOperator(A,&E);
85: PetscObjectGetType((PetscObject)A,&mattypename);
86: PetscViewerASCIIPrintf(viewer,"Matrix of type: %s\n",mattypename);
87: MatView(E,viewer);
88: MatMult(A,Z,W1);
89: MatMultTranspose(A,W1,W2);
90: VecView(W2,viewer);
91: MatGetDiagonal(A,W2);
92: VecView(W2,viewer);
93: /* MATSHELL does not support MatDiagonalSet after MatScale */
94: if (strncmp(mattypename, "shell", 5)) {
95: MatDiagonalSet(A,X,INSERT_VALUES);
96: MatGetDiagonal(A,W1);
97: VecView(W1,viewer);
98: } else {
99: PetscViewerASCIIPrintf(viewer,"MatDiagonalSet not tested on MATSHELL\n");
100: }
101: MatDestroy(&E);
102: VecDestroy(&W1);
103: VecDestroy(&W2);
104: return(0);
105: }
107: int main(int argc,char **args)
108: {
109: const PetscScalar xvals[] = {11,13},yvals[] = {17,19},zvals[] = {23,29};
110: const PetscInt inds[] = {0,1};
111: PetscScalar avals[] = {2,3,5,7};
112: Mat A,S,D[4],N;
113: Vec X,Y,Z;
114: User user;
115: PetscInt i;
116: PetscErrorCode ierr;
118: PetscInitialize(&argc,&args,(char*)0,help);if (ierr) return ierr;
119: MatCreateSeqAIJ(PETSC_COMM_WORLD,2,2,2,NULL,&A);
120: MatSetUp(A);
121: MatSetValues(A,2,inds,2,inds,avals,INSERT_VALUES);
122: VecCreateSeq(PETSC_COMM_WORLD,2,&X);
123: VecDuplicate(X,&Y);
124: VecDuplicate(X,&Z);
125: VecSetValues(X,2,inds,xvals,INSERT_VALUES);
126: VecSetValues(Y,2,inds,yvals,INSERT_VALUES);
127: VecSetValues(Z,2,inds,zvals,INSERT_VALUES);
128: MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
129: MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
130: VecAssemblyBegin(X);
131: VecAssemblyBegin(Y);
132: VecAssemblyBegin(Z);
133: VecAssemblyEnd(X);
134: VecAssemblyEnd(Y);
135: VecAssemblyEnd(Z);
137: PetscNew(&user);
138: user->B = A;
140: MatCreateShell(PETSC_COMM_WORLD,2,2,2,2,user,&S);
141: MatSetUp(S);
142: MatShellSetOperation(S,MATOP_VIEW,(void (*)(void))MatView_User);
143: MatShellSetOperation(S,MATOP_MULT,(void (*)(void))MatMult_User);
144: MatShellSetOperation(S,MATOP_MULT_TRANSPOSE,(void (*)(void))MatMultTranspose_User);
145: MatShellSetOperation(S,MATOP_GET_DIAGONAL,(void (*)(void))MatGetDiagonal_User);
146: MatShellSetOperation(S,MATOP_DIAGONAL_SET,(void (*)(void))MatDiagonalSet_User);
148: for (i=0; i<4; i++) {
149: MatCreateSeqDense(PETSC_COMM_WORLD,1,1,&avals[i],&D[i]);
150: }
151: MatCreateNest(PETSC_COMM_WORLD,2,NULL,2,NULL,D,&N);
152: MatSetUp(N);
154: TestMatrix(S,X,Y,Z);
155: TestMatrix(A,X,Y,Z);
156: TestMatrix(N,X,Y,Z);
158: for (i=0; i<4; i++) {MatDestroy(&D[i]);}
159: MatDestroy(&A);
160: MatDestroy(&S);
161: MatDestroy(&N);
162: VecDestroy(&X);
163: VecDestroy(&Y);
164: VecDestroy(&Z);
165: PetscFree(user);
166: PetscFinalize();
167: return ierr;
168: }