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