xref: /petsc/src/ksp/pc/impls/mat/pcmat.c (revision 4f572ea9526f19623f23a8c158f3503516190bbc)
14b9ad928SBarry Smith 
2af0996ceSBarry Smith #include <petsc/private/pcimpl.h> /*I "petscpc.h" I*/
34b9ad928SBarry Smith 
4345a4b08SToby Isaac typedef enum {
5345a4b08SToby Isaac   PCMATOP_MULT,
6345a4b08SToby Isaac   PCMATOP_MULT_TRANSPOSE,
7345a4b08SToby Isaac   PCMATOP_MULT_HERMITIAN_TRANSPOSE,
8345a4b08SToby Isaac   PCMATOP_SOLVE,
9345a4b08SToby Isaac   PCMATOP_SOLVE_TRANSPOSE,
10345a4b08SToby Isaac } PCMatOperation;
11345a4b08SToby Isaac 
12345a4b08SToby Isaac const char *const PCMatOpTypes[] = {"Mult", "MultTranspose", "MultHermitianTranspose", "Solve", "SolveTranspose", NULL};
13345a4b08SToby Isaac 
14345a4b08SToby Isaac typedef struct _PCMAT {
15345a4b08SToby Isaac   PCMatOperation apply;
16345a4b08SToby Isaac } PC_Mat;
17345a4b08SToby Isaac 
18d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_Mat(PC pc, Vec x, Vec y)
19d71ae5a4SJacob Faibussowitsch {
20345a4b08SToby Isaac   PC_Mat *pcmat = (PC_Mat *)pc->data;
21345a4b08SToby Isaac 
224b9ad928SBarry Smith   PetscFunctionBegin;
23345a4b08SToby Isaac   switch (pcmat->apply) {
24345a4b08SToby Isaac   case PCMATOP_MULT:
259566063dSJacob Faibussowitsch     PetscCall(MatMult(pc->pmat, x, y));
26345a4b08SToby Isaac     break;
27345a4b08SToby Isaac   case PCMATOP_MULT_TRANSPOSE:
28345a4b08SToby Isaac     PetscCall(MatMultTranspose(pc->pmat, x, y));
29345a4b08SToby Isaac     break;
30345a4b08SToby Isaac   case PCMATOP_SOLVE:
31345a4b08SToby Isaac     PetscCall(MatSolve(pc->pmat, x, y));
32345a4b08SToby Isaac     break;
33345a4b08SToby Isaac   case PCMATOP_SOLVE_TRANSPOSE:
34345a4b08SToby Isaac     PetscCall(MatSolveTranspose(pc->pmat, x, y));
35345a4b08SToby Isaac     break;
36345a4b08SToby Isaac   case PCMATOP_MULT_HERMITIAN_TRANSPOSE:
37345a4b08SToby Isaac     PetscCall(MatMultHermitianTranspose(pc->pmat, x, y));
38345a4b08SToby Isaac     break;
39345a4b08SToby Isaac   }
403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
414b9ad928SBarry Smith }
424b9ad928SBarry Smith 
43d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCMatApply_Mat(PC pc, Mat X, Mat Y)
44d71ae5a4SJacob Faibussowitsch {
45345a4b08SToby Isaac   PC_Mat *pcmat = (PC_Mat *)pc->data;
46345a4b08SToby Isaac 
477b6e2003SPierre Jolivet   PetscFunctionBegin;
48345a4b08SToby Isaac   switch (pcmat->apply) {
49345a4b08SToby Isaac   case PCMATOP_MULT:
509566063dSJacob Faibussowitsch     PetscCall(MatMatMult(pc->pmat, X, MAT_REUSE_MATRIX, PETSC_DEFAULT, &Y));
51345a4b08SToby Isaac     break;
52345a4b08SToby Isaac   case PCMATOP_MULT_TRANSPOSE:
53345a4b08SToby Isaac     PetscCall(MatTransposeMatMult(pc->pmat, X, MAT_REUSE_MATRIX, PETSC_DEFAULT, &Y));
54345a4b08SToby Isaac     break;
55345a4b08SToby Isaac   case PCMATOP_SOLVE:
56345a4b08SToby Isaac     PetscCall(MatMatSolve(pc->pmat, X, Y));
57345a4b08SToby Isaac     break;
58345a4b08SToby Isaac   case PCMATOP_SOLVE_TRANSPOSE:
59345a4b08SToby Isaac     PetscCall(MatMatSolveTranspose(pc->pmat, X, Y));
60345a4b08SToby Isaac     break;
61345a4b08SToby Isaac   case PCMATOP_MULT_HERMITIAN_TRANSPOSE: {
62345a4b08SToby Isaac     Mat W;
63345a4b08SToby Isaac 
64345a4b08SToby Isaac     PetscCall(MatDuplicate(X, MAT_COPY_VALUES, &W));
65345a4b08SToby Isaac     PetscCall(MatConjugate(W));
66345a4b08SToby Isaac     PetscCall(MatTransposeMatMult(pc->pmat, W, MAT_REUSE_MATRIX, PETSC_DEFAULT, &Y));
67345a4b08SToby Isaac     PetscCall(MatConjugate(Y));
68345a4b08SToby Isaac     PetscCall(MatDestroy(&W));
69345a4b08SToby Isaac     break;
70345a4b08SToby Isaac   }
71345a4b08SToby Isaac   }
723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
737b6e2003SPierre Jolivet }
747b6e2003SPierre Jolivet 
75d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_Mat(PC pc, Vec x, Vec y)
76d71ae5a4SJacob Faibussowitsch {
77345a4b08SToby Isaac   PC_Mat *pcmat = (PC_Mat *)pc->data;
78345a4b08SToby Isaac 
794b9ad928SBarry Smith   PetscFunctionBegin;
80345a4b08SToby Isaac   switch (pcmat->apply) {
81345a4b08SToby Isaac   case PCMATOP_MULT:
829566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pc->pmat, x, y));
83345a4b08SToby Isaac     break;
84345a4b08SToby Isaac   case PCMATOP_MULT_TRANSPOSE:
85345a4b08SToby Isaac     PetscCall(MatMult(pc->pmat, x, y));
86345a4b08SToby Isaac     break;
87345a4b08SToby Isaac   case PCMATOP_SOLVE:
88345a4b08SToby Isaac     PetscCall(MatSolveTranspose(pc->pmat, x, y));
89345a4b08SToby Isaac     break;
90345a4b08SToby Isaac   case PCMATOP_SOLVE_TRANSPOSE:
91345a4b08SToby Isaac     PetscCall(MatSolve(pc->pmat, x, y));
92345a4b08SToby Isaac     break;
93345a4b08SToby Isaac   case PCMATOP_MULT_HERMITIAN_TRANSPOSE: {
94345a4b08SToby Isaac     Vec w;
95345a4b08SToby Isaac 
96345a4b08SToby Isaac     PetscCall(VecDuplicate(x, &w));
97345a4b08SToby Isaac     PetscCall(VecCopy(x, w));
98345a4b08SToby Isaac     PetscCall(VecConjugate(w));
99345a4b08SToby Isaac     PetscCall(MatMult(pc->pmat, w, y));
100345a4b08SToby Isaac     PetscCall(VecConjugate(y));
101345a4b08SToby Isaac     PetscCall(VecDestroy(&w));
102345a4b08SToby Isaac     break;
103345a4b08SToby Isaac   }
104345a4b08SToby Isaac   }
1053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1064b9ad928SBarry Smith }
1074b9ad928SBarry Smith 
108d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_Mat(PC pc)
109d71ae5a4SJacob Faibussowitsch {
1104b9ad928SBarry Smith   PetscFunctionBegin;
111345a4b08SToby Isaac   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMatSetApplyOperation_C", NULL));
112345a4b08SToby Isaac   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMatGetApplyOperation_C", NULL));
113345a4b08SToby Isaac   PetscCall(PetscFree(pc->data));
114345a4b08SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
115345a4b08SToby Isaac }
116345a4b08SToby Isaac 
117345a4b08SToby Isaac /*@
118345a4b08SToby Isaac   PCMatSetApplyOperation - Set which matrix operation of the preconditioning matrix implements `PCApply()` for `PCMAT`.
119345a4b08SToby Isaac 
120345a4b08SToby Isaac   Logically collective
121345a4b08SToby Isaac 
122345a4b08SToby Isaac   Input Parameters:
123345a4b08SToby Isaac + pc    - An instance of `PCMAT`
124345a4b08SToby Isaac - matop - The selected `MatOperation`
125345a4b08SToby Isaac 
126345a4b08SToby Isaac   Level: intermediate
127345a4b08SToby Isaac 
128345a4b08SToby Isaac   Note:
129345a4b08SToby Isaac   If you have a matrix type that implements an exact inverse that isn't a factorization,
130345a4b08SToby Isaac   you can use `PCMatSetApplyOperation(pc, MATOP_SOLVE)`.
131345a4b08SToby Isaac 
132345a4b08SToby Isaac .seealso: `PCMAT`, `PCMatGetApplyOperation()`, `PCApply()`, `MatOperation`
133345a4b08SToby Isaac @*/
134345a4b08SToby Isaac PetscErrorCode PCMatSetApplyOperation(PC pc, MatOperation matop)
135345a4b08SToby Isaac {
136345a4b08SToby Isaac   PetscFunctionBegin;
137345a4b08SToby Isaac   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
138345a4b08SToby Isaac   PetscTryMethod((PetscObject)pc, "PCMatSetApplyOperation_C", (PC, MatOperation), (pc, matop));
139345a4b08SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
140345a4b08SToby Isaac }
141345a4b08SToby Isaac 
142345a4b08SToby Isaac /*@
143345a4b08SToby Isaac   PCMatGetApplyOperation - Get which matrix operation of the preconditioning matrix implements `PCApply()` for `PCMAT`.
144345a4b08SToby Isaac 
145345a4b08SToby Isaac   Logically collective
146345a4b08SToby Isaac 
147345a4b08SToby Isaac   Input Parameter:
148345a4b08SToby Isaac . pc - An instance of `PCMAT`
149345a4b08SToby Isaac 
150345a4b08SToby Isaac   Output Parameter:
151345a4b08SToby Isaac . matop - The `MatOperation`
152345a4b08SToby Isaac 
153345a4b08SToby Isaac   Level: intermediate
154345a4b08SToby Isaac 
155345a4b08SToby Isaac .seealso: `PCMAT`, `PCMatSetApplyOperation()`, `PCApply()`, `MatOperation`
156345a4b08SToby Isaac @*/
157345a4b08SToby Isaac PetscErrorCode PCMatGetApplyOperation(PC pc, MatOperation *matop)
158345a4b08SToby Isaac {
159345a4b08SToby Isaac   PetscFunctionBegin;
160345a4b08SToby Isaac   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
161*4f572ea9SToby Isaac   PetscAssertPointer(matop, 2);
162345a4b08SToby Isaac   PetscUseMethod((PetscObject)pc, "PCMatGetApplyOperation_C", (PC, MatOperation *), (pc, matop));
163345a4b08SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
164345a4b08SToby Isaac }
165345a4b08SToby Isaac 
166345a4b08SToby Isaac static PetscErrorCode PCMatSetApplyOperation_Mat(PC pc, MatOperation matop)
167345a4b08SToby Isaac {
168345a4b08SToby Isaac   PC_Mat        *pcmat = (PC_Mat *)pc->data;
169345a4b08SToby Isaac   PCMatOperation pcmatop;
170345a4b08SToby Isaac 
171345a4b08SToby Isaac   PetscFunctionBegin;
172345a4b08SToby Isaac 
173345a4b08SToby Isaac   // clang-format off
174345a4b08SToby Isaac #define MATOP_TO_PCMATOP_CASE(var, OP) case MATOP_##OP: (var) = PCMATOP_##OP; break
175345a4b08SToby Isaac   switch (matop) {
176345a4b08SToby Isaac   MATOP_TO_PCMATOP_CASE(pcmatop, MULT);
177345a4b08SToby Isaac   MATOP_TO_PCMATOP_CASE(pcmatop, MULT_TRANSPOSE);
178345a4b08SToby Isaac   MATOP_TO_PCMATOP_CASE(pcmatop, MULT_HERMITIAN_TRANSPOSE);
179345a4b08SToby Isaac   MATOP_TO_PCMATOP_CASE(pcmatop, SOLVE);
180345a4b08SToby Isaac   MATOP_TO_PCMATOP_CASE(pcmatop, SOLVE_TRANSPOSE);
181345a4b08SToby Isaac   default:
182345a4b08SToby Isaac     SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Unsupported MatOperation %d for PCMatSetApplyOperation()", (int)matop);
183345a4b08SToby Isaac   }
184345a4b08SToby Isaac #undef MATOP_TO_PCMATOP_CASE
185345a4b08SToby Isaac   // clang-format on
186345a4b08SToby Isaac 
187345a4b08SToby Isaac   pcmat->apply = pcmatop;
188345a4b08SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
189345a4b08SToby Isaac }
190345a4b08SToby Isaac 
191345a4b08SToby Isaac static PetscErrorCode PCMatGetApplyOperation_Mat(PC pc, MatOperation *matop_p)
192345a4b08SToby Isaac {
193345a4b08SToby Isaac   PC_Mat      *pcmat = (PC_Mat *)pc->data;
194345a4b08SToby Isaac   MatOperation matop = MATOP_MULT;
195345a4b08SToby Isaac 
196345a4b08SToby Isaac   PetscFunctionBegin;
197345a4b08SToby Isaac 
198345a4b08SToby Isaac   // clang-format off
199345a4b08SToby Isaac #define PCMATOP_TO_MATOP_CASE(var, OP) case PCMATOP_##OP: (var) = MATOP_##OP; break
200345a4b08SToby Isaac   switch (pcmat->apply) {
201345a4b08SToby Isaac   PCMATOP_TO_MATOP_CASE(matop, MULT);
202345a4b08SToby Isaac   PCMATOP_TO_MATOP_CASE(matop, MULT_TRANSPOSE);
203345a4b08SToby Isaac   PCMATOP_TO_MATOP_CASE(matop, MULT_HERMITIAN_TRANSPOSE);
204345a4b08SToby Isaac   PCMATOP_TO_MATOP_CASE(matop, SOLVE);
205345a4b08SToby Isaac   PCMATOP_TO_MATOP_CASE(matop, SOLVE_TRANSPOSE);
206345a4b08SToby Isaac   }
207345a4b08SToby Isaac #undef PCMATOP_TO_MATOP_CASE
208345a4b08SToby Isaac   // clang-format on
209345a4b08SToby Isaac 
210345a4b08SToby Isaac   *matop_p = matop;
211345a4b08SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
212345a4b08SToby Isaac }
213345a4b08SToby Isaac 
214345a4b08SToby Isaac static PetscErrorCode PCView_Mat(PC pc, PetscViewer viewer)
215345a4b08SToby Isaac {
216345a4b08SToby Isaac   PC_Mat   *pcmat = (PC_Mat *)pc->data;
217345a4b08SToby Isaac   PetscBool iascii;
218345a4b08SToby Isaac 
219345a4b08SToby Isaac   PetscFunctionBegin;
220345a4b08SToby Isaac   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
221345a4b08SToby Isaac   if (iascii) { PetscCall(PetscViewerASCIIPrintf(viewer, "PCApply() == Mat%s()\n", PCMatOpTypes[pcmat->apply])); }
2223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2234b9ad928SBarry Smith }
2244b9ad928SBarry Smith 
2254b9ad928SBarry Smith /*MC
226345a4b08SToby Isaac      PCMAT - A preconditioner obtained by applying an operation of the `pmat` provided in
227345a4b08SToby Isaac              in `PCSetOperators(pc,amat,pmat)` or `KSPSetOperators(ksp,amat,pmat)`.  By default, the operation is `MATOP_MULT`,
228345a4b08SToby Isaac              meaning that the `pmat` provides an approximate inverse of `amat`.
229345a4b08SToby Isaac              If some other operation of `pmat` implements the approximate inverse,
230345a4b08SToby Isaac              use `PCMatSetApplyOperation()` to select that operation.
2314b9ad928SBarry Smith 
2324b9ad928SBarry Smith    Level: intermediate
2334b9ad928SBarry Smith 
234345a4b08SToby Isaac .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCSHELL`, `MatOperation`, `PCMatSetApplyOperation()`, `PCMatGetApplyOperation()`
2354b9ad928SBarry Smith M*/
2364b9ad928SBarry Smith 
237d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_Mat(PC pc)
238d71ae5a4SJacob Faibussowitsch {
239345a4b08SToby Isaac   PC_Mat *data;
240345a4b08SToby Isaac 
2414b9ad928SBarry Smith   PetscFunctionBegin;
242345a4b08SToby Isaac   PetscCall(PetscNew(&data));
243345a4b08SToby Isaac   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMatSetApplyOperation_C", PCMatSetApplyOperation_Mat));
244345a4b08SToby Isaac   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMatGetApplyOperation_C", PCMatGetApplyOperation_Mat));
245345a4b08SToby Isaac   data->apply                  = PCMATOP_MULT;
246345a4b08SToby Isaac   pc->data                     = data;
2474b9ad928SBarry Smith   pc->ops->apply               = PCApply_Mat;
2487b6e2003SPierre Jolivet   pc->ops->matapply            = PCMatApply_Mat;
2494b9ad928SBarry Smith   pc->ops->applytranspose      = PCApplyTranspose_Mat;
2500a545947SLisandro Dalcin   pc->ops->setup               = NULL;
2514b9ad928SBarry Smith   pc->ops->destroy             = PCDestroy_Mat;
2520a545947SLisandro Dalcin   pc->ops->setfromoptions      = NULL;
253345a4b08SToby Isaac   pc->ops->view                = PCView_Mat;
2540a545947SLisandro Dalcin   pc->ops->applyrichardson     = NULL;
2550a545947SLisandro Dalcin   pc->ops->applysymmetricleft  = NULL;
2560a545947SLisandro Dalcin   pc->ops->applysymmetricright = NULL;
2573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2584b9ad928SBarry Smith }
259