xref: /petsc/src/ksp/pc/impls/mat/tests/ex1.c (revision 32e037510874440daa9fa8248b5cfeac7662c93e)
1345a4b08SToby Isaac const char help[] = "Test PCMatSetApplyOperation() and PCMatGetApplyOperation()";
2345a4b08SToby Isaac 
3345a4b08SToby Isaac #include <petscpc.h>
4345a4b08SToby Isaac 
TestVecEquality(Vec x,Vec y)5345a4b08SToby Isaac static PetscErrorCode TestVecEquality(Vec x, Vec y)
6345a4b08SToby Isaac {
7345a4b08SToby Isaac   Vec       diff;
8345a4b08SToby Isaac   PetscReal err, scale;
9345a4b08SToby Isaac 
10345a4b08SToby Isaac   PetscFunctionBegin;
11345a4b08SToby Isaac   PetscCall(VecDuplicate(x, &diff));
12345a4b08SToby Isaac   PetscCall(VecCopy(x, diff));
13345a4b08SToby Isaac   PetscCall(VecAXPY(diff, -1.0, y));
14345a4b08SToby Isaac   PetscCall(VecNorm(diff, NORM_INFINITY, &err));
15345a4b08SToby Isaac   PetscCall(VecNorm(x, NORM_INFINITY, &scale));
16345a4b08SToby Isaac   PetscCheck(err <= PETSC_SMALL * scale, PetscObjectComm((PetscObject)x), PETSC_ERR_PLIB, "PC operation does not match Mat operation");
17345a4b08SToby Isaac   PetscCall(VecDestroy(&diff));
18345a4b08SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
19345a4b08SToby Isaac }
20345a4b08SToby Isaac 
TestMatEquality(Mat x,Mat y)21345a4b08SToby Isaac static PetscErrorCode TestMatEquality(Mat x, Mat y)
22345a4b08SToby Isaac {
23345a4b08SToby Isaac   Mat       diff;
24345a4b08SToby Isaac   PetscReal err, scale;
25345a4b08SToby Isaac   PetscInt  m, n;
26345a4b08SToby Isaac 
27345a4b08SToby Isaac   PetscFunctionBegin;
28345a4b08SToby Isaac   PetscCall(MatGetSize(x, &m, &n));
29345a4b08SToby Isaac   PetscCall(MatDuplicate(x, MAT_COPY_VALUES, &diff));
30345a4b08SToby Isaac   PetscCall(MatAXPY(diff, -1.0, y, SAME_NONZERO_PATTERN));
31345a4b08SToby Isaac   PetscCall(MatNorm(diff, NORM_FROBENIUS, &err));
32345a4b08SToby Isaac   PetscCall(MatNorm(x, NORM_FROBENIUS, &scale));
33345a4b08SToby Isaac   PetscCheck(err < PETSC_SMALL * m * n * scale, PetscObjectComm((PetscObject)x), PETSC_ERR_PLIB, "PC operation does not match Mat operation");
34345a4b08SToby Isaac   PetscCall(MatDestroy(&diff));
35345a4b08SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
36345a4b08SToby Isaac }
37345a4b08SToby Isaac 
38345a4b08SToby Isaac // Test PCMat with a given operation versus a Matrix that encode the same operation relative to the original matrix
TestPCMatVersusMat(PC pc,Mat A,PetscRandom rand,MatOperation op)39345a4b08SToby Isaac static PetscErrorCode TestPCMatVersusMat(PC pc, Mat A, PetscRandom rand, MatOperation op)
40345a4b08SToby Isaac {
41345a4b08SToby Isaac   Vec          b, x, x2;
42345a4b08SToby Isaac   Mat          B, X, X2;
43345a4b08SToby Isaac   MatOperation op2;
44345a4b08SToby Isaac 
45345a4b08SToby Isaac   PetscFunctionBegin;
46345a4b08SToby Isaac   PetscCall(PCMatSetApplyOperation(pc, op));
47345a4b08SToby Isaac   PetscCall(PCView(pc, PETSC_VIEWER_STDOUT_SELF));
48345a4b08SToby Isaac   PetscCall(PCMatGetApplyOperation(pc, &op2));
49345a4b08SToby Isaac   PetscCheck(op == op2, PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "Input and output MatOperation differ");
50345a4b08SToby Isaac 
51345a4b08SToby Isaac   PetscCall(MatCreateVecs(A, &b, &x));
52345a4b08SToby Isaac   PetscCall(VecDuplicate(x, &x2));
53345a4b08SToby Isaac   PetscCall(VecSetRandom(b, rand));
54345a4b08SToby Isaac 
55345a4b08SToby Isaac   PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &B));
56345a4b08SToby Isaac   PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &X2));
57345a4b08SToby Isaac   PetscCall(MatSetRandom(B, rand));
58345a4b08SToby Isaac 
59345a4b08SToby Isaac   PetscCall(MatMult(A, b, x));
60345a4b08SToby Isaac   PetscCall(PCApply(pc, b, x2));
61345a4b08SToby Isaac   PetscCall(TestVecEquality(x, x2));
62345a4b08SToby Isaac 
63345a4b08SToby Isaac   PetscCall(MatMultTranspose(A, b, x));
64345a4b08SToby Isaac   PetscCall(PCApplyTranspose(pc, b, x2));
65345a4b08SToby Isaac   PetscCall(TestVecEquality(x, x2));
66345a4b08SToby Isaac 
67*fb842aefSJose E. Roman   PetscCall(MatMatMult(A, B, MAT_INITIAL_MATRIX, PETSC_CURRENT, &X));
68345a4b08SToby Isaac   PetscCall(PCMatApply(pc, B, X2));
69345a4b08SToby Isaac   PetscCall(TestMatEquality(X, X2));
70345a4b08SToby Isaac 
71345a4b08SToby Isaac   PetscCall(MatDestroy(&X2));
72345a4b08SToby Isaac   PetscCall(MatDestroy(&X));
73345a4b08SToby Isaac   PetscCall(MatDestroy(&B));
74345a4b08SToby Isaac   PetscCall(VecDestroy(&x2));
75345a4b08SToby Isaac   PetscCall(VecDestroy(&x));
76345a4b08SToby Isaac   PetscCall(VecDestroy(&b));
77345a4b08SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
78345a4b08SToby Isaac }
79345a4b08SToby Isaac 
main(int argc,char ** argv)80345a4b08SToby Isaac int main(int argc, char **argv)
81345a4b08SToby Isaac {
82345a4b08SToby Isaac   PetscInt    n = 10;
83345a4b08SToby Isaac   Mat         A, AT, AH, II, Ainv, AinvT;
84345a4b08SToby Isaac   MPI_Comm    comm;
85345a4b08SToby Isaac   PC          pc;
86345a4b08SToby Isaac   PetscRandom rand;
87345a4b08SToby Isaac 
88345a4b08SToby Isaac   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
89345a4b08SToby Isaac   comm = PETSC_COMM_SELF;
90345a4b08SToby Isaac 
91345a4b08SToby Isaac   PetscCall(PetscRandomCreate(comm, &rand));
92345a4b08SToby Isaac   if (PetscDefined(USE_COMPLEX)) {
93345a4b08SToby Isaac     PetscScalar i = PetscSqrtScalar(-1.0);
94345a4b08SToby Isaac     PetscCall(PetscRandomSetInterval(rand, -1.0 - i, 1.0 + i));
95345a4b08SToby Isaac   } else {
96345a4b08SToby Isaac     PetscCall(PetscRandomSetInterval(rand, -1.0, 1.0));
97345a4b08SToby Isaac   }
98345a4b08SToby Isaac 
99345a4b08SToby Isaac   PetscCall(MatCreateSeqDense(comm, n, n, NULL, &A));
100345a4b08SToby Isaac   PetscCall(MatSetRandom(A, rand));
101345a4b08SToby Isaac 
102345a4b08SToby Isaac   PetscCall(PCCreate(comm, &pc));
103345a4b08SToby Isaac   PetscCall(PCSetType(pc, PCMAT));
104345a4b08SToby Isaac   PetscCall(PCSetOperators(pc, A, A));
105345a4b08SToby Isaac   PetscCall(PCSetUp(pc));
106345a4b08SToby Isaac 
107345a4b08SToby Isaac   MatOperation default_op;
108345a4b08SToby Isaac   PetscCall(PCMatGetApplyOperation(pc, &default_op));
109345a4b08SToby Isaac   PetscCheck(default_op == MATOP_MULT, comm, PETSC_ERR_PLIB, "Default operation has changed");
110345a4b08SToby Isaac 
111345a4b08SToby Isaac   // Test setting an invalid operation
112345a4b08SToby Isaac   PetscCall(PetscPushErrorHandler(PetscReturnErrorHandler, NULL));
113345a4b08SToby Isaac   PetscErrorCode ierr = PCMatSetApplyOperation(pc, MATOP_SET_VALUES);
114345a4b08SToby Isaac   PetscCall(PetscPopErrorHandler());
115345a4b08SToby Isaac   PetscCheck(ierr == PETSC_ERR_ARG_INCOMP, comm, PETSC_ERR_PLIB, "Wrong error message for unsupported MatOperation");
116345a4b08SToby Isaac 
117345a4b08SToby Isaac   PetscCall(TestPCMatVersusMat(pc, A, rand, MATOP_MULT));
118345a4b08SToby Isaac 
119345a4b08SToby Isaac   PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &AT));
120345a4b08SToby Isaac   PetscCall(TestPCMatVersusMat(pc, AT, rand, MATOP_MULT_TRANSPOSE));
121345a4b08SToby Isaac 
122345a4b08SToby Isaac   PetscCall(MatHermitianTranspose(A, MAT_INITIAL_MATRIX, &AH));
123345a4b08SToby Isaac   PetscCall(TestPCMatVersusMat(pc, AH, rand, MATOP_MULT_HERMITIAN_TRANSPOSE));
124345a4b08SToby Isaac 
125345a4b08SToby Isaac   PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &II));
126345a4b08SToby Isaac   PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &Ainv));
127345a4b08SToby Isaac   PetscCall(MatZeroEntries(II));
128345a4b08SToby Isaac   PetscCall(MatShift(II, 1.0));
129345a4b08SToby Isaac   PetscCall(MatLUFactor(A, NULL, NULL, NULL));
130345a4b08SToby Isaac   PetscCall(MatMatSolve(A, II, Ainv));
131345a4b08SToby Isaac   PetscCall(PCSetOperators(pc, A, A));
132345a4b08SToby Isaac   PetscCall(TestPCMatVersusMat(pc, Ainv, rand, MATOP_SOLVE));
133345a4b08SToby Isaac 
134345a4b08SToby Isaac   PetscCall(MatTranspose(Ainv, MAT_INITIAL_MATRIX, &AinvT));
135345a4b08SToby Isaac   PetscCall(TestPCMatVersusMat(pc, AinvT, rand, MATOP_SOLVE_TRANSPOSE));
136345a4b08SToby Isaac 
137345a4b08SToby Isaac   PetscCall(PCDestroy(&pc));
138345a4b08SToby Isaac   PetscCall(MatDestroy(&AinvT));
139345a4b08SToby Isaac   PetscCall(MatDestroy(&Ainv));
140345a4b08SToby Isaac   PetscCall(MatDestroy(&II));
141345a4b08SToby Isaac   PetscCall(MatDestroy(&AH));
142345a4b08SToby Isaac   PetscCall(MatDestroy(&AT));
143345a4b08SToby Isaac   PetscCall(MatDestroy(&A));
144345a4b08SToby Isaac   PetscCall(PetscRandomDestroy(&rand));
145345a4b08SToby Isaac   PetscCall(PetscFinalize());
146345a4b08SToby Isaac   return 0;
147345a4b08SToby Isaac }
148345a4b08SToby Isaac 
149345a4b08SToby Isaac /*TEST
150345a4b08SToby Isaac 
151345a4b08SToby Isaac   test:
152345a4b08SToby Isaac     suffix: 0
153345a4b08SToby Isaac 
154345a4b08SToby Isaac TEST*/
155