Actual source code: ex88.c
petsc-3.9.2 2018-05-20
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 TestMatrix(Mat A,Vec X,Vec Y,Vec Z)
56: {
58: Vec W1,W2,diff;
59: Mat E;
60: const char *mattypename;
61: PetscViewer viewer = PETSC_VIEWER_STDOUT_WORLD;
62: PetscScalar diag[2] = {2.9678190300000000e+08,1.4173141580000000e+09};
63: PetscReal nrm;
64:
67: VecDuplicate(X,&W1);
68: VecDuplicate(X,&W2);
69: MatScale(A,31);
70: MatShift(A,37);
71: MatDiagonalScale(A,X,Y);
72: MatScale(A,41);
73: MatDiagonalScale(A,Y,Z);
74: MatComputeExplicitOperator(A,&E);
76: PetscObjectGetType((PetscObject)A,&mattypename);
77: PetscViewerASCIIPrintf(viewer,"Matrix of type: %s\n",mattypename);
78: MatView(E,viewer);
79: MatMult(A,Z,W1);
80: MatMultTranspose(A,W1,W2);
81: VecView(W2,viewer);
82: MatGetDiagonal(A,W2);
83: VecCreateSeqWithArray(PETSC_COMM_SELF,1,2,diag,&diff);
84: VecAXPY(diff,-1.0,W2);
85: VecNorm(diff,NORM_2,&nrm);
86: if (nrm > PETSC_SMALL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"MatGetDiagonal() produces incorrect result");
87: VecDestroy(&diff);
88: VecView(W2,viewer);
90: /* MATSHELL does not support MatDiagonalSet after MatScale */
91: if (strncmp(mattypename, "shell", 5)) {
92: MatDiagonalSet(A,X,INSERT_VALUES);
93: MatGetDiagonal(A,W1);
94: VecView(W1,viewer);
95: } else {
96: PetscViewerASCIIPrintf(viewer,"MatDiagonalSet not tested on MATSHELL\n");
97: }
98: MatDestroy(&E);
99: VecDestroy(&W1);
100: VecDestroy(&W2);
101: return(0);
102: }
104: int main(int argc,char **args)
105: {
106: const PetscScalar xvals[] = {11,13},yvals[] = {17,19},zvals[] = {23,29};
107: const PetscInt inds[] = {0,1};
108: PetscScalar avals[] = {2,3,5,7};
109: Mat A,S,D[4],N;
110: Vec X,Y,Z;
111: User user;
112: PetscInt i;
113: PetscErrorCode ierr;
115: PetscInitialize(&argc,&args,(char*)0,help);if (ierr) return ierr;
116: MatCreateSeqAIJ(PETSC_COMM_WORLD,2,2,2,NULL,&A);
117: MatSetUp(A);
118: MatSetValues(A,2,inds,2,inds,avals,INSERT_VALUES);
119: VecCreateSeq(PETSC_COMM_WORLD,2,&X);
120: VecDuplicate(X,&Y);
121: VecDuplicate(X,&Z);
122: VecSetValues(X,2,inds,xvals,INSERT_VALUES);
123: VecSetValues(Y,2,inds,yvals,INSERT_VALUES);
124: VecSetValues(Z,2,inds,zvals,INSERT_VALUES);
125: MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
126: MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
127: VecAssemblyBegin(X);
128: VecAssemblyBegin(Y);
129: VecAssemblyBegin(Z);
130: VecAssemblyEnd(X);
131: VecAssemblyEnd(Y);
132: VecAssemblyEnd(Z);
134: PetscNew(&user);
135: user->B = A;
137: MatCreateShell(PETSC_COMM_WORLD,2,2,2,2,user,&S);
138: MatSetUp(S);
139: MatShellSetOperation(S,MATOP_VIEW,(void (*)(void))MatView_User);
140: MatShellSetOperation(S,MATOP_MULT,(void (*)(void))MatMult_User);
141: MatShellSetOperation(S,MATOP_MULT_TRANSPOSE,(void (*)(void))MatMultTranspose_User);
142: MatShellSetOperation(S,MATOP_GET_DIAGONAL,(void (*)(void))MatGetDiagonal_User);
144: for (i=0; i<4; i++) {
145: MatCreateSeqDense(PETSC_COMM_WORLD,1,1,&avals[i],&D[i]);
146: }
147: MatCreateNest(PETSC_COMM_WORLD,2,NULL,2,NULL,D,&N);
148: MatSetUp(N);
150: TestMatrix(S,X,Y,Z);
151: TestMatrix(A,X,Y,Z);
152: TestMatrix(N,X,Y,Z);
154: for (i=0; i<4; i++) {MatDestroy(&D[i]);}
155: MatDestroy(&A);
156: MatDestroy(&S);
157: MatDestroy(&N);
158: VecDestroy(&X);
159: VecDestroy(&Y);
160: VecDestroy(&Z);
161: PetscFree(user);
162: PetscFinalize();
163: return ierr;
164: }
167: /*TEST
169: test:
171: TEST*/