Actual source code: ex88.c

  1: static char help[] = "Tests MatShift(), MatScale(), and MatDiagonalScale() for SHELL and NEST matrices\n\n";

  3: #include <petscmat.h>

  5: typedef struct _n_User *User;
  6: struct _n_User {
  7:   Mat B;
  8: };

 10: static PetscErrorCode MatView_User(Mat A, PetscViewer viewer)
 11: {
 12:   User user;

 14:   PetscFunctionBegin;
 15:   PetscCall(MatShellGetContext(A, &user));
 16:   PetscCall(MatView(user->B, viewer));
 17:   PetscFunctionReturn(PETSC_SUCCESS);
 18: }

 20: static PetscErrorCode MatMult_User(Mat A, Vec X, Vec Y)
 21: {
 22:   User user;

 24:   PetscFunctionBegin;
 25:   PetscCall(MatShellGetContext(A, &user));
 26:   PetscCall(MatMult(user->B, X, Y));
 27:   PetscFunctionReturn(PETSC_SUCCESS);
 28: }

 30: static PetscErrorCode MatMultTranspose_User(Mat A, Vec X, Vec Y)
 31: {
 32:   User user;

 34:   PetscFunctionBegin;
 35:   PetscCall(MatShellGetContext(A, &user));
 36:   PetscCall(MatMultTranspose(user->B, X, Y));
 37:   PetscFunctionReturn(PETSC_SUCCESS);
 38: }

 40: static PetscErrorCode MatGetDiagonal_User(Mat A, Vec X)
 41: {
 42:   User user;

 44:   PetscFunctionBegin;
 45:   PetscCall(MatShellGetContext(A, &user));
 46:   PetscCall(MatGetDiagonal(user->B, X));
 47:   PetscFunctionReturn(PETSC_SUCCESS);
 48: }

 50: static PetscErrorCode TestMatrix(Mat A, Vec X, Vec Y, Vec Z)
 51: {
 52:   Vec         W1, W2, W3, diff;
 53:   Mat         E;
 54:   const char *mattypename;
 55:   PetscViewer viewer = PETSC_VIEWER_STDOUT_WORLD;
 56:   PetscReal   nrm;
 57: #if PetscDefined(USE_COMPLEX)
 58:   const PetscScalar diag[2]     = {PetscCMPLX(-6.2902938000000000e+07, 4.5741953400000000e+08), PetscCMPLX(1.0828994620000000e+09, 1.2955916360000000e+09)};
 59:   const PetscScalar multadd[2]  = {PetscCMPLX(1.4926230300000000e+08, -1.2811063360000000e+09), PetscCMPLX(-1.2985220710000000e+09, -2.1029893020000000e+09)};
 60:   const PetscScalar multtadd[2] = {PetscCMPLX(-1.5271967100000000e+08, -1.2648172000000000e+09), PetscCMPLX(-9.9654009700000000e+08, -2.1192784380000000e+09)};
 61: #else
 62:   const PetscScalar diag[2]     = {2.9678190300000000e+08, 1.4173141580000000e+09};
 63:   const PetscScalar multadd[2]  = {-6.8966198500000000e+08, -2.0310609940000000e+09};
 64:   const PetscScalar multtadd[2] = {-9.1052873900000000e+08, -1.8101942400000000e+09};
 65: #endif

 67:   PetscFunctionBegin;
 68:   PetscCall(PetscObjectGetType((PetscObject)A, &mattypename));
 69:   PetscCall(PetscViewerASCIIPrintf(viewer, "\nMatrix of type: %s\n", mattypename));
 70:   PetscCall(VecDuplicate(X, &W1));
 71:   PetscCall(VecDuplicate(X, &W2));
 72:   PetscCall(VecDuplicate(X, &W3));
 73:   PetscCall(MatScale(A, 31));
 74:   PetscCall(MatShift(A, 37));
 75:   PetscCall(MatDiagonalScale(A, X, Y));
 76:   PetscCall(MatScale(A, 41));
 77:   PetscCall(MatDiagonalScale(A, Y, Z));
 78:   PetscCall(MatComputeOperator(A, MATDENSE, &E));

 80:   PetscCall(MatView(E, viewer));
 81:   PetscCall(PetscViewerASCIIPrintf(viewer, "Testing MatMult + MatMultTranspose\n"));
 82:   PetscCall(MatMult(A, Z, W1));
 83:   PetscCall(MatMultTranspose(A, W1, W2));
 84:   PetscCall(VecView(W2, viewer));
 85:   PetscCall(PetscViewerASCIIPrintf(viewer, "Testing MatMultHermitianTranspose\n"));
 86:   PetscCall(VecConjugate(W1));
 87:   PetscCall(MatMultHermitianTranspose(A, W1, W2));
 88:   PetscCall(VecConjugate(W2));
 89:   PetscCall(VecView(W2, viewer));

 91:   PetscCall(PetscViewerASCIIPrintf(viewer, "Testing MatMultAdd\n"));
 92:   PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF, 1, 2, multadd, &diff));
 93:   PetscCall(VecSet(W1, -1.0));
 94:   PetscCall(MatMultAdd(A, W1, W1, W2));
 95:   PetscCall(VecView(W2, viewer));
 96:   PetscCall(VecAXPY(W2, -1.0, diff));
 97:   PetscCall(VecNorm(W2, NORM_2, &nrm));
 98:   PetscCheck(!(PetscDefined(USE_REAL_DOUBLE) || PetscDefined(USE_REAL___FLOAT128)) || nrm <= PETSC_SMALL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatMultAdd(A,x,x,y) produces incorrect result");

100:   PetscCall(VecSet(W2, -1.0));
101:   PetscCall(MatMultAdd(A, W1, W2, W2));
102:   PetscCall(VecView(W2, viewer));
103:   PetscCall(VecAXPY(W2, -1.0, diff));
104:   PetscCall(VecNorm(W2, NORM_2, &nrm));
105:   PetscCheck(!(PetscDefined(USE_REAL_DOUBLE) || PetscDefined(USE_REAL___FLOAT128)) || nrm <= PETSC_SMALL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatMultAdd(A,x,y,y) produces incorrect result");
106:   PetscCall(VecDestroy(&diff));

108:   PetscCall(PetscViewerASCIIPrintf(viewer, "Testing MatMultTransposeAdd\n"));
109:   PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF, 1, 2, multtadd, &diff));

111:   PetscCall(VecSet(W1, -1.0));
112:   PetscCall(MatMultTransposeAdd(A, W1, W1, W2));
113:   PetscCall(VecView(W2, viewer));
114:   PetscCall(VecAXPY(W2, -1.0, diff));
115:   PetscCall(VecNorm(W2, NORM_2, &nrm));
116:   PetscCheck(!(PetscDefined(USE_REAL_DOUBLE) || PetscDefined(USE_REAL___FLOAT128)) || nrm <= PETSC_SMALL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatMultTransposeAdd(A,x,x,y) produces incorrect result");

118:   PetscCall(VecSet(W2, -1.0));
119:   PetscCall(MatMultTransposeAdd(A, W1, W2, W2));
120:   PetscCall(VecView(W2, viewer));
121:   PetscCall(VecAXPY(W2, -1.0, diff));
122:   PetscCall(VecNorm(W2, NORM_2, &nrm));
123:   PetscCheck(!(PetscDefined(USE_REAL_DOUBLE) || PetscDefined(USE_REAL___FLOAT128)) || nrm <= PETSC_SMALL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatMultTransposeAdd(A,x,y,y) produces incorrect result");
124:   PetscCall(VecDestroy(&diff));

126:   PetscCall(PetscViewerASCIIPrintf(viewer, "Testing MatMultHermitianTransposeAdd\n"));
127:   PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF, 1, 2, multtadd, &diff));

129:   PetscCall(VecSet(W1, -1.0));
130:   PetscCall(MatMultHermitianTransposeAdd(A, W1, W1, W3));
131:   PetscCall(VecConjugate(W3));
132:   PetscCall(VecView(W3, viewer));
133:   PetscCall(VecAXPY(W3, -1.0, diff));
134:   PetscCall(VecNorm(W3, NORM_2, &nrm));
135:   PetscCheck(!(PetscDefined(USE_REAL_DOUBLE) || PetscDefined(USE_REAL___FLOAT128)) || nrm <= PETSC_SMALL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatMultHermitianTransposeAdd(A,x,x,y) produces incorrect result");

137:   PetscCall(VecSet(W3, -1.0));
138:   PetscCall(MatMultHermitianTransposeAdd(A, W1, W3, W3));
139:   PetscCall(VecConjugate(W3));
140:   PetscCall(VecView(W3, viewer));
141:   PetscCall(VecAXPY(W3, -1.0, diff));
142:   PetscCall(VecNorm(W3, NORM_2, &nrm));
143:   PetscCheck(!(PetscDefined(USE_REAL_DOUBLE) || PetscDefined(USE_REAL___FLOAT128)) || nrm <= PETSC_SMALL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatMultHermitianTransposeAdd(A,x,y,y) produces incorrect result");
144:   PetscCall(VecDestroy(&diff));

146:   PetscCall(PetscViewerASCIIPrintf(viewer, "Testing MatGetDiagonal\n"));
147:   PetscCall(MatGetDiagonal(A, W2));
148:   PetscCall(VecView(W2, viewer));
149:   PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF, 1, 2, diag, &diff));
150:   PetscCall(VecAXPY(diff, -1.0, W2));
151:   PetscCall(VecNorm(diff, NORM_2, &nrm));
152:   PetscCheck(!(PetscDefined(USE_REAL_DOUBLE) || PetscDefined(USE_REAL___FLOAT128)) || nrm <= PETSC_SMALL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatGetDiagonal() produces incorrect result");
153:   PetscCall(VecDestroy(&diff));

155:   /* MATSHELL does not support MatDiagonalSet after MatScale */
156:   if (strncmp(mattypename, "shell", 5)) {
157:     PetscCall(MatDiagonalSet(A, X, INSERT_VALUES));
158:     PetscCall(MatGetDiagonal(A, W1));
159:     PetscCall(VecView(W1, viewer));
160:   } else {
161:     PetscCall(PetscViewerASCIIPrintf(viewer, "MatDiagonalSet not tested on MATSHELL\n"));
162:   }

164:   PetscCall(MatDestroy(&E));
165:   PetscCall(VecDestroy(&W1));
166:   PetscCall(VecDestroy(&W2));
167:   PetscCall(VecDestroy(&W3));
168:   PetscFunctionReturn(PETSC_SUCCESS);
169: }

171: int main(int argc, char **args)
172: {
173:   const PetscInt inds[] = {0, 1};
174: #if PetscDefined(USE_COMPLEX)
175:   const PetscScalar xvals[] = {PetscCMPLX(11, 4), PetscCMPLX(13, 2)}, yvals[] = {PetscCMPLX(17, 3), PetscCMPLX(19, 1)}, zvals[] = {PetscCMPLX(23, 6), PetscCMPLX(29, 2)};
176:   PetscScalar       avals[] = {PetscCMPLX(2, 3), PetscCMPLX(3, 5), PetscCMPLX(5, 4), PetscCMPLX(7, 5)};
177: #else
178:   const PetscScalar xvals[] = {11, 13}, yvals[] = {17, 19}, zvals[] = {23, 29};
179:   PetscScalar       avals[] = {2, 3, 5, 7};
180: #endif
181:   Mat  A, S, D[4], N;
182:   Vec  X, Y, Z;
183:   User user;

185:   PetscFunctionBeginUser;
186:   PetscCall(PetscInitialize(&argc, &args, NULL, help));
187:   PetscCall(MatCreateSeqAIJ(PETSC_COMM_WORLD, 2, 2, 2, NULL, &A));
188:   PetscCall(MatSetUp(A));
189:   PetscCall(VecCreateSeq(PETSC_COMM_WORLD, 2, &X));
190:   PetscCall(VecDuplicate(X, &Y));
191:   PetscCall(VecDuplicate(X, &Z));
192:   PetscCall(MatSetValues(A, 2, inds, 2, inds, avals, INSERT_VALUES));
193:   PetscCall(VecSetValues(X, 2, inds, xvals, INSERT_VALUES));
194:   PetscCall(VecSetValues(Y, 2, inds, yvals, INSERT_VALUES));
195:   PetscCall(VecSetValues(Z, 2, inds, zvals, INSERT_VALUES));
196:   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
197:   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
198:   PetscCall(VecAssemblyBegin(X));
199:   PetscCall(VecAssemblyBegin(Y));
200:   PetscCall(VecAssemblyBegin(Z));
201:   PetscCall(VecAssemblyEnd(X));
202:   PetscCall(VecAssemblyEnd(Y));
203:   PetscCall(VecAssemblyEnd(Z));

205:   PetscCall(PetscNew(&user));
206:   user->B = A;

208:   PetscCall(MatCreateShell(PETSC_COMM_WORLD, 2, 2, 2, 2, user, &S));
209:   PetscCall(MatSetUp(S));
210:   PetscCall(MatShellSetOperation(S, MATOP_VIEW, (PetscErrorCodeFn *)MatView_User));
211:   PetscCall(MatShellSetOperation(S, MATOP_MULT, (PetscErrorCodeFn *)MatMult_User));
212:   PetscCall(MatShellSetOperation(S, MATOP_MULT_TRANSPOSE, (PetscErrorCodeFn *)MatMultTranspose_User));
213:   PetscCall(MatShellSetOperation(S, MATOP_GET_DIAGONAL, (PetscErrorCodeFn *)MatGetDiagonal_User));

215:   for (PetscInt i = 0; i < 4; i++) PetscCall(MatCreateSeqDense(PETSC_COMM_WORLD, 1, 1, &avals[i], &D[i]));
216:   PetscCall(MatCreateNest(PETSC_COMM_WORLD, 2, NULL, 2, NULL, D, &N));
217:   PetscCall(MatSetUp(N));

219:   PetscCall(TestMatrix(S, X, Y, Z));
220:   PetscCall(TestMatrix(A, X, Y, Z));
221:   PetscCall(TestMatrix(N, X, Y, Z));

223:   for (PetscInt i = 0; i < 4; i++) PetscCall(MatDestroy(&D[i]));
224:   PetscCall(MatDestroy(&A));
225:   PetscCall(MatDestroy(&S));
226:   PetscCall(MatDestroy(&N));
227:   PetscCall(VecDestroy(&X));
228:   PetscCall(VecDestroy(&Y));
229:   PetscCall(VecDestroy(&Z));
230:   PetscCall(PetscFree(user));
231:   PetscCall(PetscFinalize());
232:   return 0;
233: }

235: /*TEST

237:    testset:
238:      test:
239:        suffix: 1
240:        requires:!complex
241:      test:
242:        suffix: 2
243:        requires: complex

245: TEST*/