14b9ad928SBarry Smith /* 24b9ad928SBarry Smith The PC (preconditioner) interface routines, callable by users. 34b9ad928SBarry Smith */ 4af0996ceSBarry Smith #include <petsc/private/pcimpl.h> /*I "petscksp.h" I*/ 51e25c274SJed Brown #include <petscdm.h> 64b9ad928SBarry Smith 74b9ad928SBarry Smith /* Logging support */ 80700a824SBarry Smith PetscClassId PC_CLASSID; 9c677e75fSPierre Jolivet PetscLogEvent PC_SetUp, PC_SetUpOnBlocks, PC_Apply, PC_MatApply, PC_ApplyCoarse, PC_ApplyMultiple, PC_ApplySymmetricLeft; 10011ea8aeSBarry Smith PetscLogEvent PC_ApplySymmetricRight, PC_ModifySubMatrices, PC_ApplyOnBlocks, PC_ApplyTransposeOnBlocks; 11ab83eea4SMatthew G. Knepley PetscInt PetscMGLevelId; 120316ec64SBarry Smith PetscLogStage PCMPIStage; 134b9ad928SBarry Smith 14b4f8a55aSStefano Zampini PETSC_INTERN PetscErrorCode PCGetDefaultType_Private(PC pc, const char *type[]) 15d71ae5a4SJacob Faibussowitsch { 162e70eadcSBarry Smith PetscMPIInt size; 17b4f8a55aSStefano Zampini PetscBool hasopblock, hasopsolve, flg1, flg2, set, flg3, isnormal; 18566e8bf2SBarry Smith 19566e8bf2SBarry Smith PetscFunctionBegin; 209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size)); 21566e8bf2SBarry Smith if (pc->pmat) { 22b4f8a55aSStefano Zampini PetscCall(MatHasOperation(pc->pmat, MATOP_GET_DIAGONAL_BLOCK, &hasopblock)); 23b4f8a55aSStefano Zampini PetscCall(MatHasOperation(pc->pmat, MATOP_SOLVE, &hasopsolve)); 24566e8bf2SBarry Smith if (size == 1) { 259566063dSJacob Faibussowitsch PetscCall(MatGetFactorAvailable(pc->pmat, "petsc", MAT_FACTOR_ICC, &flg1)); 269566063dSJacob Faibussowitsch PetscCall(MatGetFactorAvailable(pc->pmat, "petsc", MAT_FACTOR_ILU, &flg2)); 279566063dSJacob Faibussowitsch PetscCall(MatIsSymmetricKnown(pc->pmat, &set, &flg3)); 28da74c943SJose E. Roman PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &isnormal, MATNORMAL, MATNORMALHERMITIAN, NULL)); 29ba8a7149SBarry Smith if (flg1 && (!flg2 || (set && flg3))) { 30566e8bf2SBarry Smith *type = PCICC; 31566e8bf2SBarry Smith } else if (flg2) { 32566e8bf2SBarry Smith *type = PCILU; 33da74c943SJose E. Roman } else if (isnormal) { 34da74c943SJose E. Roman *type = PCNONE; 35b4f8a55aSStefano Zampini } else if (hasopblock) { /* likely is a parallel matrix run on one processor */ 36566e8bf2SBarry Smith *type = PCBJACOBI; 37b4f8a55aSStefano Zampini } else if (hasopsolve) { 38b4f8a55aSStefano Zampini *type = PCMAT; 39566e8bf2SBarry Smith } else { 40566e8bf2SBarry Smith *type = PCNONE; 41566e8bf2SBarry Smith } 42566e8bf2SBarry Smith } else { 43b4f8a55aSStefano Zampini if (hasopblock) { 44566e8bf2SBarry Smith *type = PCBJACOBI; 45b4f8a55aSStefano Zampini } else if (hasopsolve) { 46b4f8a55aSStefano Zampini *type = PCMAT; 47566e8bf2SBarry Smith } else { 48566e8bf2SBarry Smith *type = PCNONE; 49566e8bf2SBarry Smith } 50566e8bf2SBarry Smith } 51b4f8a55aSStefano Zampini } else *type = NULL; 523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 53566e8bf2SBarry Smith } 544b9ad928SBarry Smith 55fe57bb1aSStefano Zampini /* do not log solves, setup and applications of preconditioners while constructing preconditioners; perhaps they should be logged separately from the regular solves */ 56fe57bb1aSStefano Zampini PETSC_EXTERN PetscLogEvent KSP_Solve, KSP_SetUp; 57fe57bb1aSStefano Zampini 58fe57bb1aSStefano Zampini static PetscErrorCode PCLogEventsDeactivatePush(void) 59fe57bb1aSStefano Zampini { 60fe57bb1aSStefano Zampini PetscFunctionBegin; 61fe57bb1aSStefano Zampini PetscCall(KSPInitializePackage()); 62fe57bb1aSStefano Zampini PetscCall(PetscLogEventDeactivatePush(KSP_Solve)); 63fe57bb1aSStefano Zampini PetscCall(PetscLogEventDeactivatePush(KSP_SetUp)); 64fe57bb1aSStefano Zampini PetscCall(PetscLogEventDeactivatePush(PC_Apply)); 65fe57bb1aSStefano Zampini PetscCall(PetscLogEventDeactivatePush(PC_SetUp)); 66fe57bb1aSStefano Zampini PetscCall(PetscLogEventDeactivatePush(PC_SetUpOnBlocks)); 67fe57bb1aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 68fe57bb1aSStefano Zampini } 69fe57bb1aSStefano Zampini 70fe57bb1aSStefano Zampini static PetscErrorCode PCLogEventsDeactivatePop(void) 71fe57bb1aSStefano Zampini { 72fe57bb1aSStefano Zampini PetscFunctionBegin; 73fe57bb1aSStefano Zampini PetscCall(KSPInitializePackage()); 74fe57bb1aSStefano Zampini PetscCall(PetscLogEventDeactivatePop(KSP_Solve)); 75fe57bb1aSStefano Zampini PetscCall(PetscLogEventDeactivatePop(KSP_SetUp)); 76fe57bb1aSStefano Zampini PetscCall(PetscLogEventDeactivatePop(PC_Apply)); 77fe57bb1aSStefano Zampini PetscCall(PetscLogEventDeactivatePop(PC_SetUp)); 78fe57bb1aSStefano Zampini PetscCall(PetscLogEventDeactivatePop(PC_SetUpOnBlocks)); 79fe57bb1aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 80fe57bb1aSStefano Zampini } 81fe57bb1aSStefano Zampini 8288584be7SBarry Smith /*@ 83562efe2eSBarry Smith PCReset - Resets a `PC` context to the pcsetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s 8488584be7SBarry Smith 85c3339decSBarry Smith Collective 8688584be7SBarry Smith 8788584be7SBarry Smith Input Parameter: 8888584be7SBarry Smith . pc - the preconditioner context 8988584be7SBarry Smith 9088584be7SBarry Smith Level: developer 9188584be7SBarry Smith 92f1580f4eSBarry Smith Note: 93562efe2eSBarry Smith This allows a `PC` to be reused for a different sized linear system but using the same options that have been previously set in `pc` 9488584be7SBarry Smith 95562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCSetUp()` 9688584be7SBarry Smith @*/ 97d71ae5a4SJacob Faibussowitsch PetscErrorCode PCReset(PC pc) 98d71ae5a4SJacob Faibussowitsch { 9988584be7SBarry Smith PetscFunctionBegin; 10088584be7SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 101dbbe0bcdSBarry Smith PetscTryTypeMethod(pc, reset); 1029566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pc->diagonalscaleright)); 1039566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pc->diagonalscaleleft)); 1049566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pc->pmat)); 1059566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pc->mat)); 1062fa5cd67SKarl Rupp 1070ce6c5a2SBarry Smith pc->setupcalled = 0; 1083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10988584be7SBarry Smith } 11088584be7SBarry Smith 1110764c050SBarry Smith /*@ 112f1580f4eSBarry Smith PCDestroy - Destroys `PC` context that was created with `PCCreate()`. 1134b9ad928SBarry Smith 114c3339decSBarry Smith Collective 1154b9ad928SBarry Smith 1164b9ad928SBarry Smith Input Parameter: 1174b9ad928SBarry Smith . pc - the preconditioner context 1184b9ad928SBarry Smith 1194b9ad928SBarry Smith Level: developer 1204b9ad928SBarry Smith 121562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCSetUp()` 1224b9ad928SBarry Smith @*/ 123d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy(PC *pc) 124d71ae5a4SJacob Faibussowitsch { 1254b9ad928SBarry Smith PetscFunctionBegin; 1263ba16761SJacob Faibussowitsch if (!*pc) PetscFunctionReturn(PETSC_SUCCESS); 127f4f49eeaSPierre Jolivet PetscValidHeaderSpecific(*pc, PC_CLASSID, 1); 128f4f49eeaSPierre Jolivet if (--((PetscObject)*pc)->refct > 0) { 1299371c9d4SSatish Balay *pc = NULL; 1303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1319371c9d4SSatish Balay } 1324b9ad928SBarry Smith 1339566063dSJacob Faibussowitsch PetscCall(PCReset(*pc)); 134241cb3abSLisandro Dalcin 135e04113cfSBarry Smith /* if memory was published with SAWs then destroy it */ 1369566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsViewOff((PetscObject)*pc)); 137f4f49eeaSPierre Jolivet PetscTryTypeMethod(*pc, destroy); 1389566063dSJacob Faibussowitsch PetscCall(DMDestroy(&(*pc)->dm)); 1399566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(pc)); 1403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1414b9ad928SBarry Smith } 1424b9ad928SBarry Smith 143cc4c1da9SBarry Smith /*@ 144c5eb9154SBarry Smith PCGetDiagonalScale - Indicates if the preconditioner applies an additional left and right 1454b9ad928SBarry Smith scaling as needed by certain time-stepping codes. 1464b9ad928SBarry Smith 147c3339decSBarry Smith Logically Collective 1484b9ad928SBarry Smith 1494b9ad928SBarry Smith Input Parameter: 1504b9ad928SBarry Smith . pc - the preconditioner context 1514b9ad928SBarry Smith 1524b9ad928SBarry Smith Output Parameter: 153f1580f4eSBarry Smith . flag - `PETSC_TRUE` if it applies the scaling 1544b9ad928SBarry Smith 1554b9ad928SBarry Smith Level: developer 1564b9ad928SBarry Smith 157f1580f4eSBarry Smith Note: 158562efe2eSBarry Smith If this returns `PETSC_TRUE` then the system solved via the Krylov method is, for left and right preconditioning, 1594b9ad928SBarry Smith 160562efe2eSBarry Smith $$ 161562efe2eSBarry Smith \begin{align*} 162562efe2eSBarry Smith D M A D^{-1} y = D M b \\ 163562efe2eSBarry Smith D A M D^{-1} z = D b. 164562efe2eSBarry Smith \end{align*} 165562efe2eSBarry Smith $$ 166562efe2eSBarry Smith 167562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCSetUp()`, `PCDiagonalScaleLeft()`, `PCDiagonalScaleRight()`, `PCSetDiagonalScale()` 1684b9ad928SBarry Smith @*/ 169d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGetDiagonalScale(PC pc, PetscBool *flag) 170d71ae5a4SJacob Faibussowitsch { 1714b9ad928SBarry Smith PetscFunctionBegin; 1720700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1734f572ea9SToby Isaac PetscAssertPointer(flag, 2); 1744b9ad928SBarry Smith *flag = pc->diagonalscale; 1753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1764b9ad928SBarry Smith } 1774b9ad928SBarry Smith 1784b9ad928SBarry Smith /*@ 179c5eb9154SBarry Smith PCSetDiagonalScale - Indicates the left scaling to use to apply an additional left and right 1804b9ad928SBarry Smith scaling as needed by certain time-stepping codes. 1814b9ad928SBarry Smith 182c3339decSBarry Smith Logically Collective 1834b9ad928SBarry Smith 1844b9ad928SBarry Smith Input Parameters: 1854b9ad928SBarry Smith + pc - the preconditioner context 1864b9ad928SBarry Smith - s - scaling vector 1874b9ad928SBarry Smith 1884b9ad928SBarry Smith Level: intermediate 1894b9ad928SBarry Smith 19095452b02SPatrick Sanan Notes: 191562efe2eSBarry Smith The system solved via the Krylov method is, for left and right preconditioning, 192562efe2eSBarry Smith $$ 193562efe2eSBarry Smith \begin{align*} 194562efe2eSBarry Smith D M A D^{-1} y = D M b \\ 195562efe2eSBarry Smith D A M D^{-1} z = D b. 196562efe2eSBarry Smith \end{align*} 197562efe2eSBarry Smith $$ 1984b9ad928SBarry Smith 199562efe2eSBarry Smith `PCDiagonalScaleLeft()` scales a vector by $D$. `PCDiagonalScaleRight()` scales a vector by $D^{-1}$. 2004b9ad928SBarry Smith 201562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCSetUp()`, `PCDiagonalScaleLeft()`, `PCDiagonalScaleRight()`, `PCGetDiagonalScale()` 2024b9ad928SBarry Smith @*/ 203d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetDiagonalScale(PC pc, Vec s) 204d71ae5a4SJacob Faibussowitsch { 2054b9ad928SBarry Smith PetscFunctionBegin; 2060700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 2070700a824SBarry Smith PetscValidHeaderSpecific(s, VEC_CLASSID, 2); 2084b9ad928SBarry Smith pc->diagonalscale = PETSC_TRUE; 2092fa5cd67SKarl Rupp 2109566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)s)); 2119566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pc->diagonalscaleleft)); 2122fa5cd67SKarl Rupp 2134b9ad928SBarry Smith pc->diagonalscaleleft = s; 2142fa5cd67SKarl Rupp 2159566063dSJacob Faibussowitsch PetscCall(VecDuplicate(s, &pc->diagonalscaleright)); 2169566063dSJacob Faibussowitsch PetscCall(VecCopy(s, pc->diagonalscaleright)); 2179566063dSJacob Faibussowitsch PetscCall(VecReciprocal(pc->diagonalscaleright)); 2183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2194b9ad928SBarry Smith } 2204b9ad928SBarry Smith 221bc08b0f1SBarry Smith /*@ 222c5eb9154SBarry Smith PCDiagonalScaleLeft - Scales a vector by the left scaling as needed by certain time-stepping codes. 2234b9ad928SBarry Smith 224c3339decSBarry Smith Logically Collective 2254b9ad928SBarry Smith 2264b9ad928SBarry Smith Input Parameters: 2274b9ad928SBarry Smith + pc - the preconditioner context 2284b9ad928SBarry Smith . in - input vector 229a2b725a8SWilliam Gropp - out - scaled vector (maybe the same as in) 2304b9ad928SBarry Smith 2314b9ad928SBarry Smith Level: intermediate 2324b9ad928SBarry Smith 23395452b02SPatrick Sanan Notes: 234562efe2eSBarry Smith The system solved via the Krylov method is, for left and right preconditioning, 2354b9ad928SBarry Smith 236562efe2eSBarry Smith $$ 237562efe2eSBarry Smith \begin{align*} 238562efe2eSBarry Smith D M A D^{-1} y = D M b \\ 239562efe2eSBarry Smith D A M D^{-1} z = D b. 240562efe2eSBarry Smith \end{align*} 241562efe2eSBarry Smith $$ 2424b9ad928SBarry Smith 243562efe2eSBarry Smith `PCDiagonalScaleLeft()` scales a vector by $D$. `PCDiagonalScaleRight()` scales a vector by $D^{-1}$. 2444b9ad928SBarry Smith 245562efe2eSBarry Smith If diagonal scaling is turned off and `in` is not `out` then `in` is copied to `out` 246562efe2eSBarry Smith 2470241b274SPierre Jolivet .seealso: [](ch_ksp), `PCCreate()`, `PCSetUp()`, `PCSetDiagonalScale()`, `PCDiagonalScaleRight()`, `MatDiagonalScale()` 2484b9ad928SBarry Smith @*/ 249d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDiagonalScaleLeft(PC pc, Vec in, Vec out) 250d71ae5a4SJacob Faibussowitsch { 2514b9ad928SBarry Smith PetscFunctionBegin; 2520700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 2530700a824SBarry Smith PetscValidHeaderSpecific(in, VEC_CLASSID, 2); 2540700a824SBarry Smith PetscValidHeaderSpecific(out, VEC_CLASSID, 3); 2554b9ad928SBarry Smith if (pc->diagonalscale) { 2569566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(out, pc->diagonalscaleleft, in)); 2574b9ad928SBarry Smith } else if (in != out) { 2589566063dSJacob Faibussowitsch PetscCall(VecCopy(in, out)); 2594b9ad928SBarry Smith } 2603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2614b9ad928SBarry Smith } 2624b9ad928SBarry Smith 263bc08b0f1SBarry Smith /*@ 2644b9ad928SBarry Smith PCDiagonalScaleRight - Scales a vector by the right scaling as needed by certain time-stepping codes. 2654b9ad928SBarry Smith 266c3339decSBarry Smith Logically Collective 2674b9ad928SBarry Smith 2684b9ad928SBarry Smith Input Parameters: 2694b9ad928SBarry Smith + pc - the preconditioner context 2704b9ad928SBarry Smith . in - input vector 271a2b725a8SWilliam Gropp - out - scaled vector (maybe the same as in) 2724b9ad928SBarry Smith 2734b9ad928SBarry Smith Level: intermediate 2744b9ad928SBarry Smith 27595452b02SPatrick Sanan Notes: 276562efe2eSBarry Smith The system solved via the Krylov method is, for left and right preconditioning, 2774b9ad928SBarry Smith 278562efe2eSBarry Smith $$ 279562efe2eSBarry Smith \begin{align*} 280562efe2eSBarry Smith D M A D^{-1} y = D M b \\ 281562efe2eSBarry Smith D A M D^{-1} z = D b. 282a3524536SPierre Jolivet \end{align*} 283562efe2eSBarry Smith $$ 2844b9ad928SBarry Smith 285562efe2eSBarry Smith `PCDiagonalScaleLeft()` scales a vector by $D$. `PCDiagonalScaleRight()` scales a vector by $D^{-1}$. 2864b9ad928SBarry Smith 287562efe2eSBarry Smith If diagonal scaling is turned off and `in` is not `out` then `in` is copied to `out` 288562efe2eSBarry Smith 2890241b274SPierre Jolivet .seealso: [](ch_ksp), `PCCreate()`, `PCSetUp()`, `PCDiagonalScaleLeft()`, `PCSetDiagonalScale()`, `MatDiagonalScale()` 2904b9ad928SBarry Smith @*/ 291d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDiagonalScaleRight(PC pc, Vec in, Vec out) 292d71ae5a4SJacob Faibussowitsch { 2934b9ad928SBarry Smith PetscFunctionBegin; 2940700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 2950700a824SBarry Smith PetscValidHeaderSpecific(in, VEC_CLASSID, 2); 2960700a824SBarry Smith PetscValidHeaderSpecific(out, VEC_CLASSID, 3); 2974b9ad928SBarry Smith if (pc->diagonalscale) { 2989566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(out, pc->diagonalscaleright, in)); 2994b9ad928SBarry Smith } else if (in != out) { 3009566063dSJacob Faibussowitsch PetscCall(VecCopy(in, out)); 3014b9ad928SBarry Smith } 3023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3034b9ad928SBarry Smith } 3044b9ad928SBarry Smith 30549517cdeSBarry Smith /*@ 30649517cdeSBarry Smith PCSetUseAmat - Sets a flag to indicate that when the preconditioner needs to apply (part of) the 307f1580f4eSBarry Smith operator during the preconditioning process it applies the Amat provided to `TSSetRHSJacobian()`, 308f1580f4eSBarry Smith `TSSetIJacobian()`, `SNESSetJacobian()`, `KSPSetOperators()` or `PCSetOperators()` not the Pmat. 30949517cdeSBarry Smith 310c3339decSBarry Smith Logically Collective 31149517cdeSBarry Smith 31249517cdeSBarry Smith Input Parameters: 31349517cdeSBarry Smith + pc - the preconditioner context 314f1580f4eSBarry Smith - flg - `PETSC_TRUE` to use the Amat, `PETSC_FALSE` to use the Pmat (default is false) 31549517cdeSBarry Smith 31649517cdeSBarry Smith Options Database Key: 317562efe2eSBarry Smith . -pc_use_amat <true,false> - use the amat argument to `KSPSetOperators()` or `PCSetOperators()` to apply the operator 31849517cdeSBarry Smith 31920f4b53cSBarry Smith Level: intermediate 32020f4b53cSBarry Smith 321f1580f4eSBarry Smith Note: 32249517cdeSBarry Smith For the common case in which the linear system matrix and the matrix used to construct the 323562efe2eSBarry Smith preconditioner are identical, this routine has no affect. 32449517cdeSBarry Smith 3250241b274SPierre Jolivet .seealso: [](ch_ksp), `PC`, `PCGetUseAmat()`, `PCBJACOBI`, `PCMG`, `PCFIELDSPLIT`, `PCCOMPOSITE`, 326562efe2eSBarry Smith `KSPSetOperators()`, `PCSetOperators()` 32749517cdeSBarry Smith @*/ 328d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUseAmat(PC pc, PetscBool flg) 329d71ae5a4SJacob Faibussowitsch { 33049517cdeSBarry Smith PetscFunctionBegin; 33149517cdeSBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 33249517cdeSBarry Smith pc->useAmat = flg; 3333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 33449517cdeSBarry Smith } 33549517cdeSBarry Smith 336422a814eSBarry Smith /*@ 337562efe2eSBarry Smith PCSetErrorIfFailure - Causes `PC` to generate an error if a floating point exception, for example a zero pivot, is detected. 338422a814eSBarry Smith 339c3339decSBarry Smith Logically Collective 340422a814eSBarry Smith 341422a814eSBarry Smith Input Parameters: 342562efe2eSBarry Smith + pc - iterative context obtained from `PCCreate()` 343f1580f4eSBarry Smith - flg - `PETSC_TRUE` indicates you want the error generated 344422a814eSBarry Smith 345422a814eSBarry Smith Level: advanced 346422a814eSBarry Smith 347422a814eSBarry Smith Notes: 348f1580f4eSBarry Smith Normally PETSc continues if a linear solver fails due to a failed setup of a preconditioner, you can call `KSPGetConvergedReason()` after a `KSPSolve()` 349422a814eSBarry Smith to determine if it has converged or failed. Or use -ksp_error_if_not_converged to cause the program to terminate as soon as lack of convergence is 350422a814eSBarry Smith detected. 351422a814eSBarry Smith 352562efe2eSBarry Smith This is propagated into `KSP`s used by this `PC`, which then propagate it into `PC`s used by those `KSP`s 353422a814eSBarry Smith 354562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `KSPSetErrorIfNotConverged()`, `PCGetInitialGuessNonzero()`, `PCSetInitialGuessKnoll()`, `PCGetInitialGuessKnoll()` 355422a814eSBarry Smith @*/ 356d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetErrorIfFailure(PC pc, PetscBool flg) 357d71ae5a4SJacob Faibussowitsch { 358422a814eSBarry Smith PetscFunctionBegin; 359422a814eSBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 360422a814eSBarry Smith PetscValidLogicalCollectiveBool(pc, flg, 2); 361422a814eSBarry Smith pc->erroriffailure = flg; 3623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 363422a814eSBarry Smith } 364422a814eSBarry Smith 36549517cdeSBarry Smith /*@ 36649517cdeSBarry Smith PCGetUseAmat - Gets a flag to indicate that when the preconditioner needs to apply (part of) the 367f1580f4eSBarry Smith operator during the preconditioning process it applies the Amat provided to `TSSetRHSJacobian()`, 368f1580f4eSBarry Smith `TSSetIJacobian()`, `SNESSetJacobian()`, `KSPSetOperators()` or `PCSetOperators()` not the Pmat. 36949517cdeSBarry Smith 370c3339decSBarry Smith Logically Collective 37149517cdeSBarry Smith 37249517cdeSBarry Smith Input Parameter: 37349517cdeSBarry Smith . pc - the preconditioner context 37449517cdeSBarry Smith 37549517cdeSBarry Smith Output Parameter: 376f1580f4eSBarry Smith . flg - `PETSC_TRUE` to use the Amat, `PETSC_FALSE` to use the Pmat (default is false) 37749517cdeSBarry Smith 37820f4b53cSBarry Smith Level: intermediate 37920f4b53cSBarry Smith 380f1580f4eSBarry Smith Note: 38149517cdeSBarry Smith For the common case in which the linear system matrix and the matrix used to construct the 38249517cdeSBarry Smith preconditioner are identical, this routine is does nothing. 38349517cdeSBarry Smith 3840241b274SPierre Jolivet .seealso: [](ch_ksp), `PC`, `PCSetUseAmat()`, `PCBJACOBI`, `PCMG`, `PCFIELDSPLIT`, `PCCOMPOSITE` 38549517cdeSBarry Smith @*/ 386d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGetUseAmat(PC pc, PetscBool *flg) 387d71ae5a4SJacob Faibussowitsch { 38849517cdeSBarry Smith PetscFunctionBegin; 38949517cdeSBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 39049517cdeSBarry Smith *flg = pc->useAmat; 3913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 39249517cdeSBarry Smith } 39349517cdeSBarry Smith 394f39d8e23SSatish Balay /*@ 3953821be0aSBarry Smith PCSetKSPNestLevel - sets the amount of nesting the `KSP` that contains this `PC` has 3963821be0aSBarry Smith 3973821be0aSBarry Smith Collective 3983821be0aSBarry Smith 3993821be0aSBarry Smith Input Parameters: 4003821be0aSBarry Smith + pc - the `PC` 4013821be0aSBarry Smith - level - the nest level 4023821be0aSBarry Smith 4033821be0aSBarry Smith Level: developer 4043821be0aSBarry Smith 4053821be0aSBarry Smith .seealso: [](ch_ksp), `KSPSetUp()`, `KSPSolve()`, `KSPDestroy()`, `KSP`, `KSPGMRES`, `KSPType`, `KSPGetNestLevel()`, `PCGetKSPNestLevel()`, `KSPSetNestLevel()` 4063821be0aSBarry Smith @*/ 4073821be0aSBarry Smith PetscErrorCode PCSetKSPNestLevel(PC pc, PetscInt level) 4083821be0aSBarry Smith { 4093821be0aSBarry Smith PetscFunctionBegin; 4107a99bfcaSBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 4117a99bfcaSBarry Smith PetscValidLogicalCollectiveInt(pc, level, 2); 4123821be0aSBarry Smith pc->kspnestlevel = level; 4133821be0aSBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 4143821be0aSBarry Smith } 4153821be0aSBarry Smith 4163821be0aSBarry Smith /*@ 4173821be0aSBarry Smith PCGetKSPNestLevel - gets the amount of nesting the `KSP` that contains this `PC` has 4183821be0aSBarry Smith 4197a99bfcaSBarry Smith Not Collective 4203821be0aSBarry Smith 4213821be0aSBarry Smith Input Parameter: 4223821be0aSBarry Smith . pc - the `PC` 4233821be0aSBarry Smith 4243821be0aSBarry Smith Output Parameter: 4253821be0aSBarry Smith . level - the nest level 4263821be0aSBarry Smith 4273821be0aSBarry Smith Level: developer 4283821be0aSBarry Smith 4293821be0aSBarry Smith .seealso: [](ch_ksp), `KSPSetUp()`, `KSPSolve()`, `KSPDestroy()`, `KSP`, `KSPGMRES`, `KSPType`, `KSPSetNestLevel()`, `PCSetKSPNestLevel()`, `KSPGetNestLevel()` 4303821be0aSBarry Smith @*/ 4313821be0aSBarry Smith PetscErrorCode PCGetKSPNestLevel(PC pc, PetscInt *level) 4323821be0aSBarry Smith { 4333821be0aSBarry Smith PetscFunctionBegin; 4347a99bfcaSBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 4357a99bfcaSBarry Smith PetscAssertPointer(level, 2); 4363821be0aSBarry Smith *level = pc->kspnestlevel; 4373821be0aSBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 4383821be0aSBarry Smith } 4393821be0aSBarry Smith 4403821be0aSBarry Smith /*@ 441f1580f4eSBarry Smith PCCreate - Creates a preconditioner context, `PC` 4424b9ad928SBarry Smith 443d083f849SBarry Smith Collective 4444b9ad928SBarry Smith 4454b9ad928SBarry Smith Input Parameter: 4464b9ad928SBarry Smith . comm - MPI communicator 4474b9ad928SBarry Smith 4484b9ad928SBarry Smith Output Parameter: 4497a99bfcaSBarry Smith . newpc - location to put the preconditioner context 4504b9ad928SBarry Smith 45120f4b53cSBarry Smith Level: developer 45220f4b53cSBarry Smith 453f1580f4eSBarry Smith Note: 454f1580f4eSBarry Smith The default preconditioner for sparse matrices is `PCILU` or `PCICC` with 0 fill on one process and block Jacobi (`PCBJACOBI`) with `PCILU` or `PCICC` 455f1580f4eSBarry Smith in parallel. For dense matrices it is always `PCNONE`. 4564b9ad928SBarry Smith 457562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCSetUp()`, `PCApply()`, `PCDestroy()` 4584b9ad928SBarry Smith @*/ 459d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCreate(MPI_Comm comm, PC *newpc) 460d71ae5a4SJacob Faibussowitsch { 4614b9ad928SBarry Smith PC pc; 4624b9ad928SBarry Smith 4634b9ad928SBarry Smith PetscFunctionBegin; 4644f572ea9SToby Isaac PetscAssertPointer(newpc, 2); 4659566063dSJacob Faibussowitsch PetscCall(PCInitializePackage()); 4664b9ad928SBarry Smith 4679566063dSJacob Faibussowitsch PetscCall(PetscHeaderCreate(pc, PC_CLASSID, "PC", "Preconditioner", "PC", comm, PCDestroy, PCView)); 4680a545947SLisandro Dalcin pc->mat = NULL; 4690a545947SLisandro Dalcin pc->pmat = NULL; 4704b9ad928SBarry Smith pc->setupcalled = 0; 4710c24e6a1SHong Zhang pc->setfromoptionscalled = 0; 4720a545947SLisandro Dalcin pc->data = NULL; 4734b9ad928SBarry Smith pc->diagonalscale = PETSC_FALSE; 4740a545947SLisandro Dalcin pc->diagonalscaleleft = NULL; 4750a545947SLisandro Dalcin pc->diagonalscaleright = NULL; 4764b9ad928SBarry Smith 4770a545947SLisandro Dalcin pc->modifysubmatrices = NULL; 4780a545947SLisandro Dalcin pc->modifysubmatricesP = NULL; 4792fa5cd67SKarl Rupp 480a7d21a52SLisandro Dalcin *newpc = pc; 4813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4824b9ad928SBarry Smith } 4834b9ad928SBarry Smith 4844b9ad928SBarry Smith /*@ 4854b9ad928SBarry Smith PCApply - Applies the preconditioner to a vector. 4864b9ad928SBarry Smith 487c3339decSBarry Smith Collective 4884b9ad928SBarry Smith 4894b9ad928SBarry Smith Input Parameters: 4904b9ad928SBarry Smith + pc - the preconditioner context 4914b9ad928SBarry Smith - x - input vector 4924b9ad928SBarry Smith 4934b9ad928SBarry Smith Output Parameter: 4944b9ad928SBarry Smith . y - output vector 4954b9ad928SBarry Smith 4964b9ad928SBarry Smith Level: developer 4974b9ad928SBarry Smith 498562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCApplyTranspose()`, `PCApplyBAorAB()` 4994b9ad928SBarry Smith @*/ 500d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply(PC pc, Vec x, Vec y) 501d71ae5a4SJacob Faibussowitsch { 502106e20bfSBarry Smith PetscInt m, n, mv, nv; 5034b9ad928SBarry Smith 5044b9ad928SBarry Smith PetscFunctionBegin; 5050700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 5060700a824SBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 5070700a824SBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 5087827d75bSBarry Smith PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors"); 509e0f629ddSJacob Faibussowitsch if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 510540bdfbdSVaclav Hapla /* use pmat to check vector sizes since for KSPLSQR the pmat may be of a different size than mat */ 5119566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pc->pmat, &m, &n)); 5129566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(x, &mv)); 5139566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(y, &nv)); 514540bdfbdSVaclav Hapla /* check pmat * y = x is feasible */ 51563a3b9bcSJacob Faibussowitsch PetscCheck(mv == m, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Preconditioner number of local rows %" PetscInt_FMT " does not equal input vector size %" PetscInt_FMT, m, mv); 51663a3b9bcSJacob Faibussowitsch PetscCheck(nv == n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Preconditioner number of local columns %" PetscInt_FMT " does not equal output vector size %" PetscInt_FMT, n, nv); 5179566063dSJacob Faibussowitsch PetscCall(VecSetErrorIfLocked(y, 3)); 518106e20bfSBarry Smith 5199566063dSJacob Faibussowitsch PetscCall(PCSetUp(pc)); 5209566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 5219566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_Apply, pc, x, y, 0)); 522dbbe0bcdSBarry Smith PetscUseTypeMethod(pc, apply, x, y); 5239566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Apply, pc, x, y, 0)); 524e0f629ddSJacob Faibussowitsch if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 5259566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 5263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5274b9ad928SBarry Smith } 5284b9ad928SBarry Smith 5294b9ad928SBarry Smith /*@ 530562efe2eSBarry Smith PCMatApply - Applies the preconditioner to multiple vectors stored as a `MATDENSE`. Like `PCApply()`, `Y` and `X` must be different matrices. 531c41ea70eSPierre Jolivet 532c3339decSBarry Smith Collective 533c677e75fSPierre Jolivet 534c677e75fSPierre Jolivet Input Parameters: 535c677e75fSPierre Jolivet + pc - the preconditioner context 536c677e75fSPierre Jolivet - X - block of input vectors 537c677e75fSPierre Jolivet 538c677e75fSPierre Jolivet Output Parameter: 539c677e75fSPierre Jolivet . Y - block of output vectors 540c677e75fSPierre Jolivet 541c677e75fSPierre Jolivet Level: developer 542c677e75fSPierre Jolivet 543562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCApply()`, `KSPMatSolve()` 544c677e75fSPierre Jolivet @*/ 545d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMatApply(PC pc, Mat X, Mat Y) 546d71ae5a4SJacob Faibussowitsch { 547c677e75fSPierre Jolivet Mat A; 548c677e75fSPierre Jolivet Vec cy, cx; 549bd82155bSPierre Jolivet PetscInt m1, M1, m2, M2, n1, N1, n2, N2, m3, M3, n3, N3; 550c677e75fSPierre Jolivet PetscBool match; 551c677e75fSPierre Jolivet 552c677e75fSPierre Jolivet PetscFunctionBegin; 553c677e75fSPierre Jolivet PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 554e2b200f6SPierre Jolivet PetscValidHeaderSpecific(X, MAT_CLASSID, 2); 555e2b200f6SPierre Jolivet PetscValidHeaderSpecific(Y, MAT_CLASSID, 3); 556e2b200f6SPierre Jolivet PetscCheckSameComm(pc, 1, X, 2); 557e2b200f6SPierre Jolivet PetscCheckSameComm(pc, 1, Y, 3); 5587827d75bSBarry Smith PetscCheck(Y != X, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "Y and X must be different matrices"); 5599566063dSJacob Faibussowitsch PetscCall(PCGetOperators(pc, NULL, &A)); 5609566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m3, &n3)); 5619566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(X, &m2, &n2)); 5629566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(Y, &m1, &n1)); 5639566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M3, &N3)); 5649566063dSJacob Faibussowitsch PetscCall(MatGetSize(X, &M2, &N2)); 5659566063dSJacob Faibussowitsch PetscCall(MatGetSize(Y, &M1, &N1)); 56663a3b9bcSJacob Faibussowitsch PetscCheck(n1 == n2 && N1 == N2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Incompatible number of columns between block of input vectors (n,N) = (%" PetscInt_FMT ",%" PetscInt_FMT ") and block of output vectors (n,N) = (%" PetscInt_FMT ",%" PetscInt_FMT ")", n2, N2, n1, N1); 56763a3b9bcSJacob Faibussowitsch PetscCheck(m2 == m3 && M2 == M3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Incompatible layout between block of input vectors (m,M) = (%" PetscInt_FMT ",%" PetscInt_FMT ") and Pmat (m,M)x(n,N) = (%" PetscInt_FMT ",%" PetscInt_FMT ")x(%" PetscInt_FMT ",%" PetscInt_FMT ")", m2, M2, m3, M3, n3, N3); 56863a3b9bcSJacob Faibussowitsch PetscCheck(m1 == n3 && M1 == N3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Incompatible layout between block of output vectors (m,M) = (%" PetscInt_FMT ",%" PetscInt_FMT ") and Pmat (m,M)x(n,N) = (%" PetscInt_FMT ",%" PetscInt_FMT ")x(%" PetscInt_FMT ",%" PetscInt_FMT ")", m1, M1, m3, M3, n3, N3); 5699566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)Y, &match, MATSEQDENSE, MATMPIDENSE, "")); 57028b400f6SJacob Faibussowitsch PetscCheck(match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Provided block of output vectors not stored in a dense Mat"); 5719566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)X, &match, MATSEQDENSE, MATMPIDENSE, "")); 57228b400f6SJacob Faibussowitsch PetscCheck(match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Provided block of input vectors not stored in a dense Mat"); 5739566063dSJacob Faibussowitsch PetscCall(PCSetUp(pc)); 574c677e75fSPierre Jolivet if (pc->ops->matapply) { 5759566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_MatApply, pc, X, Y, 0)); 576dbbe0bcdSBarry Smith PetscUseTypeMethod(pc, matapply, X, Y); 5779566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_MatApply, pc, X, Y, 0)); 578c677e75fSPierre Jolivet } else { 5799566063dSJacob Faibussowitsch PetscCall(PetscInfo(pc, "PC type %s applying column by column\n", ((PetscObject)pc)->type_name)); 580bd82155bSPierre Jolivet for (n1 = 0; n1 < N1; ++n1) { 5819566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVecRead(X, n1, &cx)); 5829566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVecWrite(Y, n1, &cy)); 5839566063dSJacob Faibussowitsch PetscCall(PCApply(pc, cx, cy)); 5849566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVecWrite(Y, n1, &cy)); 5859566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVecRead(X, n1, &cx)); 586c677e75fSPierre Jolivet } 587c677e75fSPierre Jolivet } 5883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 589c677e75fSPierre Jolivet } 590c677e75fSPierre Jolivet 591c677e75fSPierre Jolivet /*@ 5924b9ad928SBarry Smith PCApplySymmetricLeft - Applies the left part of a symmetric preconditioner to a vector. 5934b9ad928SBarry Smith 594c3339decSBarry Smith Collective 5954b9ad928SBarry Smith 5964b9ad928SBarry Smith Input Parameters: 5974b9ad928SBarry Smith + pc - the preconditioner context 5984b9ad928SBarry Smith - x - input vector 5994b9ad928SBarry Smith 6004b9ad928SBarry Smith Output Parameter: 6014b9ad928SBarry Smith . y - output vector 6024b9ad928SBarry Smith 60320f4b53cSBarry Smith Level: developer 60420f4b53cSBarry Smith 605f1580f4eSBarry Smith Note: 606f1580f4eSBarry Smith Currently, this routine is implemented only for `PCICC` and `PCJACOBI` preconditioners. 6074b9ad928SBarry Smith 608562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplySymmetricRight()` 6094b9ad928SBarry Smith @*/ 610d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApplySymmetricLeft(PC pc, Vec x, Vec y) 611d71ae5a4SJacob Faibussowitsch { 6124b9ad928SBarry Smith PetscFunctionBegin; 6130700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 6140700a824SBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 6150700a824SBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 6167827d75bSBarry Smith PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors"); 617e0f629ddSJacob Faibussowitsch if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 6189566063dSJacob Faibussowitsch PetscCall(PCSetUp(pc)); 6199566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 6209566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_ApplySymmetricLeft, pc, x, y, 0)); 621dbbe0bcdSBarry Smith PetscUseTypeMethod(pc, applysymmetricleft, x, y); 6229566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_ApplySymmetricLeft, pc, x, y, 0)); 6239566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 624e0f629ddSJacob Faibussowitsch if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 6253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6264b9ad928SBarry Smith } 6274b9ad928SBarry Smith 6284b9ad928SBarry Smith /*@ 6294b9ad928SBarry Smith PCApplySymmetricRight - Applies the right part of a symmetric preconditioner to a vector. 6304b9ad928SBarry Smith 631c3339decSBarry Smith Collective 6324b9ad928SBarry Smith 6334b9ad928SBarry Smith Input Parameters: 6344b9ad928SBarry Smith + pc - the preconditioner context 6354b9ad928SBarry Smith - x - input vector 6364b9ad928SBarry Smith 6374b9ad928SBarry Smith Output Parameter: 6384b9ad928SBarry Smith . y - output vector 6394b9ad928SBarry Smith 6404b9ad928SBarry Smith Level: developer 6414b9ad928SBarry Smith 642f1580f4eSBarry Smith Note: 643f1580f4eSBarry Smith Currently, this routine is implemented only for `PCICC` and `PCJACOBI` preconditioners. 6444b9ad928SBarry Smith 645562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplySymmetricLeft()` 6464b9ad928SBarry Smith @*/ 647d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApplySymmetricRight(PC pc, Vec x, Vec y) 648d71ae5a4SJacob Faibussowitsch { 6494b9ad928SBarry Smith PetscFunctionBegin; 6500700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 6510700a824SBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 6520700a824SBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 6537827d75bSBarry Smith PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors"); 654e0f629ddSJacob Faibussowitsch if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 6559566063dSJacob Faibussowitsch PetscCall(PCSetUp(pc)); 6569566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 6579566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_ApplySymmetricRight, pc, x, y, 0)); 658dbbe0bcdSBarry Smith PetscUseTypeMethod(pc, applysymmetricright, x, y); 6599566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_ApplySymmetricRight, pc, x, y, 0)); 6609566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 661e0f629ddSJacob Faibussowitsch if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 6623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6634b9ad928SBarry Smith } 6644b9ad928SBarry Smith 6654b9ad928SBarry Smith /*@ 6664b9ad928SBarry Smith PCApplyTranspose - Applies the transpose of preconditioner to a vector. 6674b9ad928SBarry Smith 668c3339decSBarry Smith Collective 6694b9ad928SBarry Smith 6704b9ad928SBarry Smith Input Parameters: 6714b9ad928SBarry Smith + pc - the preconditioner context 6724b9ad928SBarry Smith - x - input vector 6734b9ad928SBarry Smith 6744b9ad928SBarry Smith Output Parameter: 6754b9ad928SBarry Smith . y - output vector 6764b9ad928SBarry Smith 67720f4b53cSBarry Smith Level: developer 67820f4b53cSBarry Smith 679f1580f4eSBarry Smith Note: 68095452b02SPatrick Sanan For complex numbers this applies the non-Hermitian transpose. 6814c97465dSBarry Smith 682562efe2eSBarry Smith Developer Note: 683f1580f4eSBarry Smith We need to implement a `PCApplyHermitianTranspose()` 6844c97465dSBarry Smith 685562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplyBAorAB()`, `PCApplyBAorABTranspose()`, `PCApplyTransposeExists()` 6864b9ad928SBarry Smith @*/ 687d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApplyTranspose(PC pc, Vec x, Vec y) 688d71ae5a4SJacob Faibussowitsch { 6894b9ad928SBarry Smith PetscFunctionBegin; 6900700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 6910700a824SBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 6920700a824SBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 6937827d75bSBarry Smith PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors"); 694e0f629ddSJacob Faibussowitsch if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 6959566063dSJacob Faibussowitsch PetscCall(PCSetUp(pc)); 6969566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 6979566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_Apply, pc, x, y, 0)); 698dbbe0bcdSBarry Smith PetscUseTypeMethod(pc, applytranspose, x, y); 6999566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Apply, pc, x, y, 0)); 7009566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 701e0f629ddSJacob Faibussowitsch if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 7023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7034b9ad928SBarry Smith } 7044b9ad928SBarry Smith 7054b9ad928SBarry Smith /*@ 7069cc050e5SLisandro Dalcin PCApplyTransposeExists - Test whether the preconditioner has a transpose apply operation 7074b9ad928SBarry Smith 708c3339decSBarry Smith Collective 7094b9ad928SBarry Smith 710f1580f4eSBarry Smith Input Parameter: 7114b9ad928SBarry Smith . pc - the preconditioner context 7124b9ad928SBarry Smith 7134b9ad928SBarry Smith Output Parameter: 714f1580f4eSBarry Smith . flg - `PETSC_TRUE` if a transpose operation is defined 7154b9ad928SBarry Smith 7164b9ad928SBarry Smith Level: developer 7174b9ad928SBarry Smith 718562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCApplyTranspose()` 7194b9ad928SBarry Smith @*/ 720d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApplyTransposeExists(PC pc, PetscBool *flg) 721d71ae5a4SJacob Faibussowitsch { 7224b9ad928SBarry Smith PetscFunctionBegin; 7230700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 7244f572ea9SToby Isaac PetscAssertPointer(flg, 2); 7256ce5e81cSLisandro Dalcin if (pc->ops->applytranspose) *flg = PETSC_TRUE; 7266ce5e81cSLisandro Dalcin else *flg = PETSC_FALSE; 7273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7284b9ad928SBarry Smith } 7294b9ad928SBarry Smith 7304b9ad928SBarry Smith /*@ 731562efe2eSBarry Smith PCApplyBAorAB - Applies the preconditioner and operator to a vector. $y = B*A*x $ or $ y = A*B*x$. 7324b9ad928SBarry Smith 733c3339decSBarry Smith Collective 7344b9ad928SBarry Smith 7354b9ad928SBarry Smith Input Parameters: 7364b9ad928SBarry Smith + pc - the preconditioner context 737f1580f4eSBarry Smith . side - indicates the preconditioner side, one of `PC_LEFT`, `PC_RIGHT`, or `PC_SYMMETRIC` 7384b9ad928SBarry Smith . x - input vector 7394b9ad928SBarry Smith - work - work vector 7404b9ad928SBarry Smith 7414b9ad928SBarry Smith Output Parameter: 7424b9ad928SBarry Smith . y - output vector 7434b9ad928SBarry Smith 7444b9ad928SBarry Smith Level: developer 7454b9ad928SBarry Smith 746f1580f4eSBarry Smith Note: 747562efe2eSBarry Smith If the `PC` has had `PCSetDiagonalScale()` set then $ D M A D^{-1} $ for left preconditioning or $ D A M D^{-1} $ is actually applied. 748562efe2eSBarry Smith The specific `KSPSolve()` method must also be written to handle the post-solve "correction" for the diagonal scaling. 74913e0d083SBarry Smith 750562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplyTranspose()`, `PCApplyBAorABTranspose()` 7514b9ad928SBarry Smith @*/ 752d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApplyBAorAB(PC pc, PCSide side, Vec x, Vec y, Vec work) 753d71ae5a4SJacob Faibussowitsch { 7544b9ad928SBarry Smith PetscFunctionBegin; 7550700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 756a69c7061SStefano Zampini PetscValidLogicalCollectiveEnum(pc, side, 2); 7570700a824SBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7580700a824SBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 4); 7590700a824SBarry Smith PetscValidHeaderSpecific(work, VEC_CLASSID, 5); 760a69c7061SStefano Zampini PetscCheckSameComm(pc, 1, x, 3); 761a69c7061SStefano Zampini PetscCheckSameComm(pc, 1, y, 4); 762a69c7061SStefano Zampini PetscCheckSameComm(pc, 1, work, 5); 7637827d75bSBarry Smith PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors"); 7647827d75bSBarry Smith PetscCheck(side == PC_LEFT || side == PC_SYMMETRIC || side == PC_RIGHT, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Side must be right, left, or symmetric"); 7657827d75bSBarry Smith PetscCheck(!pc->diagonalscale || side != PC_SYMMETRIC, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot include diagonal scaling with symmetric preconditioner application"); 766e0f629ddSJacob Faibussowitsch if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 3, PETSC_TRUE)); 7674b9ad928SBarry Smith 7689566063dSJacob Faibussowitsch PetscCall(PCSetUp(pc)); 7694b9ad928SBarry Smith if (pc->diagonalscale) { 7704b9ad928SBarry Smith if (pc->ops->applyBA) { 7714b9ad928SBarry Smith Vec work2; /* this is expensive, but to fix requires a second work vector argument to PCApplyBAorAB() */ 7729566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x, &work2)); 7739566063dSJacob Faibussowitsch PetscCall(PCDiagonalScaleRight(pc, x, work2)); 774dbbe0bcdSBarry Smith PetscUseTypeMethod(pc, applyBA, side, work2, y, work); 7759566063dSJacob Faibussowitsch PetscCall(PCDiagonalScaleLeft(pc, y, y)); 7769566063dSJacob Faibussowitsch PetscCall(VecDestroy(&work2)); 7774b9ad928SBarry Smith } else if (side == PC_RIGHT) { 7789566063dSJacob Faibussowitsch PetscCall(PCDiagonalScaleRight(pc, x, y)); 7799566063dSJacob Faibussowitsch PetscCall(PCApply(pc, y, work)); 7809566063dSJacob Faibussowitsch PetscCall(MatMult(pc->mat, work, y)); 7819566063dSJacob Faibussowitsch PetscCall(PCDiagonalScaleLeft(pc, y, y)); 7824b9ad928SBarry Smith } else if (side == PC_LEFT) { 7839566063dSJacob Faibussowitsch PetscCall(PCDiagonalScaleRight(pc, x, y)); 7849566063dSJacob Faibussowitsch PetscCall(MatMult(pc->mat, y, work)); 7859566063dSJacob Faibussowitsch PetscCall(PCApply(pc, work, y)); 7869566063dSJacob Faibussowitsch PetscCall(PCDiagonalScaleLeft(pc, y, y)); 7877827d75bSBarry Smith } else PetscCheck(side != PC_SYMMETRIC, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot provide diagonal scaling with symmetric application of preconditioner"); 7884b9ad928SBarry Smith } else { 7894b9ad928SBarry Smith if (pc->ops->applyBA) { 790dbbe0bcdSBarry Smith PetscUseTypeMethod(pc, applyBA, side, x, y, work); 7914b9ad928SBarry Smith } else if (side == PC_RIGHT) { 7929566063dSJacob Faibussowitsch PetscCall(PCApply(pc, x, work)); 7939566063dSJacob Faibussowitsch PetscCall(MatMult(pc->mat, work, y)); 7944b9ad928SBarry Smith } else if (side == PC_LEFT) { 7959566063dSJacob Faibussowitsch PetscCall(MatMult(pc->mat, x, work)); 7969566063dSJacob Faibussowitsch PetscCall(PCApply(pc, work, y)); 7974b9ad928SBarry Smith } else if (side == PC_SYMMETRIC) { 7984b9ad928SBarry Smith /* There's an extra copy here; maybe should provide 2 work vectors instead? */ 7999566063dSJacob Faibussowitsch PetscCall(PCApplySymmetricRight(pc, x, work)); 8009566063dSJacob Faibussowitsch PetscCall(MatMult(pc->mat, work, y)); 8019566063dSJacob Faibussowitsch PetscCall(VecCopy(y, work)); 8029566063dSJacob Faibussowitsch PetscCall(PCApplySymmetricLeft(pc, work, y)); 8034b9ad928SBarry Smith } 8044b9ad928SBarry Smith } 805e0f629ddSJacob Faibussowitsch if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 4, PETSC_FALSE)); 8063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8074b9ad928SBarry Smith } 8084b9ad928SBarry Smith 8094b9ad928SBarry Smith /*@ 8104b9ad928SBarry Smith PCApplyBAorABTranspose - Applies the transpose of the preconditioner 811562efe2eSBarry Smith and operator to a vector. That is, applies $B^T * A^T$ with left preconditioning, 812562efe2eSBarry Smith NOT $(B*A)^T = A^T*B^T$. 8134b9ad928SBarry Smith 814c3339decSBarry Smith Collective 8154b9ad928SBarry Smith 8164b9ad928SBarry Smith Input Parameters: 8174b9ad928SBarry Smith + pc - the preconditioner context 818f1580f4eSBarry Smith . side - indicates the preconditioner side, one of `PC_LEFT`, `PC_RIGHT`, or `PC_SYMMETRIC` 8194b9ad928SBarry Smith . x - input vector 8204b9ad928SBarry Smith - work - work vector 8214b9ad928SBarry Smith 8224b9ad928SBarry Smith Output Parameter: 8234b9ad928SBarry Smith . y - output vector 8244b9ad928SBarry Smith 82520f4b53cSBarry Smith Level: developer 82620f4b53cSBarry Smith 827f1580f4eSBarry Smith Note: 828562efe2eSBarry Smith This routine is used internally so that the same Krylov code can be used to solve $A x = b$ and $A^T x = b$, with a preconditioner 829562efe2eSBarry Smith defined by $B^T$. This is why this has the funny form that it computes $B^T * A^T$ 8309b3038f0SBarry Smith 831562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplyTranspose()`, `PCApplyBAorAB()` 8324b9ad928SBarry Smith @*/ 833d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApplyBAorABTranspose(PC pc, PCSide side, Vec x, Vec y, Vec work) 834d71ae5a4SJacob Faibussowitsch { 8354b9ad928SBarry Smith PetscFunctionBegin; 8360700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 8370700a824SBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8380700a824SBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 4); 8390700a824SBarry Smith PetscValidHeaderSpecific(work, VEC_CLASSID, 5); 8407827d75bSBarry Smith PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors"); 841e0f629ddSJacob Faibussowitsch if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 3, PETSC_TRUE)); 8424b9ad928SBarry Smith if (pc->ops->applyBAtranspose) { 843dbbe0bcdSBarry Smith PetscUseTypeMethod(pc, applyBAtranspose, side, x, y, work); 844e0f629ddSJacob Faibussowitsch if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 4, PETSC_FALSE)); 8453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8464b9ad928SBarry Smith } 8477827d75bSBarry Smith PetscCheck(side == PC_LEFT || side == PC_RIGHT, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Side must be right or left"); 8484b9ad928SBarry Smith 8499566063dSJacob Faibussowitsch PetscCall(PCSetUp(pc)); 8504b9ad928SBarry Smith if (side == PC_RIGHT) { 8519566063dSJacob Faibussowitsch PetscCall(PCApplyTranspose(pc, x, work)); 8529566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pc->mat, work, y)); 8534b9ad928SBarry Smith } else if (side == PC_LEFT) { 8549566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pc->mat, x, work)); 8559566063dSJacob Faibussowitsch PetscCall(PCApplyTranspose(pc, work, y)); 8564b9ad928SBarry Smith } 8574b9ad928SBarry Smith /* add support for PC_SYMMETRIC */ 858e0f629ddSJacob Faibussowitsch if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 4, PETSC_FALSE)); 8593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8604b9ad928SBarry Smith } 8614b9ad928SBarry Smith 8624b9ad928SBarry Smith /*@ 8634b9ad928SBarry Smith PCApplyRichardsonExists - Determines whether a particular preconditioner has a 8644b9ad928SBarry Smith built-in fast application of Richardson's method. 8654b9ad928SBarry Smith 8664b9ad928SBarry Smith Not Collective 8674b9ad928SBarry Smith 8684b9ad928SBarry Smith Input Parameter: 8694b9ad928SBarry Smith . pc - the preconditioner 8704b9ad928SBarry Smith 8714b9ad928SBarry Smith Output Parameter: 872f1580f4eSBarry Smith . exists - `PETSC_TRUE` or `PETSC_FALSE` 8734b9ad928SBarry Smith 8744b9ad928SBarry Smith Level: developer 8754b9ad928SBarry Smith 87639b1ba1bSPierre Jolivet .seealso: [](ch_ksp), `PC`, `KSPRICHARDSON`, `PCApplyRichardson()` 8774b9ad928SBarry Smith @*/ 878d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApplyRichardsonExists(PC pc, PetscBool *exists) 879d71ae5a4SJacob Faibussowitsch { 8804b9ad928SBarry Smith PetscFunctionBegin; 8810700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 8824f572ea9SToby Isaac PetscAssertPointer(exists, 2); 8834b9ad928SBarry Smith if (pc->ops->applyrichardson) *exists = PETSC_TRUE; 8844b9ad928SBarry Smith else *exists = PETSC_FALSE; 8853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8864b9ad928SBarry Smith } 8874b9ad928SBarry Smith 8884b9ad928SBarry Smith /*@ 8894b9ad928SBarry Smith PCApplyRichardson - Applies several steps of Richardson iteration with 8904b9ad928SBarry Smith the particular preconditioner. This routine is usually used by the 8914b9ad928SBarry Smith Krylov solvers and not the application code directly. 8924b9ad928SBarry Smith 893c3339decSBarry Smith Collective 8944b9ad928SBarry Smith 8954b9ad928SBarry Smith Input Parameters: 8964b9ad928SBarry Smith + pc - the preconditioner context 897dd8e379bSPierre Jolivet . b - the right-hand side 8984b9ad928SBarry Smith . w - one work vector 8994b9ad928SBarry Smith . rtol - relative decrease in residual norm convergence criteria 90070441072SBarry Smith . abstol - absolute residual norm convergence criteria 9014b9ad928SBarry Smith . dtol - divergence residual norm increase criteria 9027319c654SBarry Smith . its - the number of iterations to apply. 9037319c654SBarry Smith - guesszero - if the input x contains nonzero initial guess 9044b9ad928SBarry Smith 905d8d19677SJose E. Roman Output Parameters: 9064d0a8057SBarry Smith + outits - number of iterations actually used (for SOR this always equals its) 9074d0a8057SBarry Smith . reason - the reason the apply terminated 908f1580f4eSBarry Smith - y - the solution (also contains initial guess if guesszero is `PETSC_FALSE` 9094b9ad928SBarry Smith 91020f4b53cSBarry Smith Level: developer 91120f4b53cSBarry Smith 9124b9ad928SBarry Smith Notes: 9134b9ad928SBarry Smith Most preconditioners do not support this function. Use the command 914f1580f4eSBarry Smith `PCApplyRichardsonExists()` to determine if one does. 9154b9ad928SBarry Smith 916f1580f4eSBarry Smith Except for the `PCMG` this routine ignores the convergence tolerances 9174b9ad928SBarry Smith and always runs for the number of iterations 9184b9ad928SBarry Smith 919562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCApplyRichardsonExists()` 9204b9ad928SBarry Smith @*/ 921d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApplyRichardson(PC pc, Vec b, Vec y, Vec w, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt its, PetscBool guesszero, PetscInt *outits, PCRichardsonConvergedReason *reason) 922d71ae5a4SJacob Faibussowitsch { 9234b9ad928SBarry Smith PetscFunctionBegin; 9240700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 9250700a824SBarry Smith PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 9260700a824SBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 9270700a824SBarry Smith PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 9287827d75bSBarry Smith PetscCheck(b != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "b and y must be different vectors"); 9299566063dSJacob Faibussowitsch PetscCall(PCSetUp(pc)); 930dbbe0bcdSBarry Smith PetscUseTypeMethod(pc, applyrichardson, b, y, w, rtol, abstol, dtol, its, guesszero, outits, reason); 9313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9324b9ad928SBarry Smith } 9334b9ad928SBarry Smith 934422a814eSBarry Smith /*@ 935f1580f4eSBarry Smith PCSetFailedReason - Sets the reason a `PCSetUp()` failed or `PC_NOERROR` if it did not fail 9361b2b9847SBarry Smith 937c3339decSBarry Smith Logically Collective 9381b2b9847SBarry Smith 939d8d19677SJose E. Roman Input Parameters: 9401b2b9847SBarry Smith + pc - the preconditioner context 9411b2b9847SBarry Smith - reason - the reason it failedx 9421b2b9847SBarry Smith 9431b2b9847SBarry Smith Level: advanced 9441b2b9847SBarry Smith 945562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCFailedReason` 9461b2b9847SBarry Smith @*/ 947d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFailedReason(PC pc, PCFailedReason reason) 948d71ae5a4SJacob Faibussowitsch { 9491b2b9847SBarry Smith PetscFunctionBegin; 9506479e835SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 9511b2b9847SBarry Smith pc->failedreason = reason; 9523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9531b2b9847SBarry Smith } 9541b2b9847SBarry Smith 9551b2b9847SBarry Smith /*@ 956f1580f4eSBarry Smith PCGetFailedReason - Gets the reason a `PCSetUp()` failed or `PC_NOERROR` if it did not fail 957422a814eSBarry Smith 958c3339decSBarry Smith Logically Collective 959422a814eSBarry Smith 960422a814eSBarry Smith Input Parameter: 961422a814eSBarry Smith . pc - the preconditioner context 962422a814eSBarry Smith 963422a814eSBarry Smith Output Parameter: 9641b2b9847SBarry Smith . reason - the reason it failed 965422a814eSBarry Smith 966422a814eSBarry Smith Level: advanced 967422a814eSBarry Smith 968f1580f4eSBarry Smith Note: 969f1580f4eSBarry Smith This is the maximum over reason over all ranks in the PC communicator. It is only valid after 9706479e835SStefano Zampini a call `KSPCheckDot()` or `KSPCheckNorm()` inside a `KSPSolve()` or `PCReduceFailedReason()`. 9716479e835SStefano Zampini It is not valid immediately after a `PCSetUp()` or `PCApply()`, then use `PCGetFailedReasonRank()` 9721b2b9847SBarry Smith 973a94f484eSPierre Jolivet .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCGetFailedReasonRank()`, `PCSetFailedReason()` 974422a814eSBarry Smith @*/ 975d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGetFailedReason(PC pc, PCFailedReason *reason) 976d71ae5a4SJacob Faibussowitsch { 977422a814eSBarry Smith PetscFunctionBegin; 9786479e835SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 9799754764cSHong Zhang if (pc->setupcalled < 0) *reason = (PCFailedReason)pc->setupcalled; 9800ae0b32dSHong Zhang else *reason = pc->failedreason; 9813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 982422a814eSBarry Smith } 983422a814eSBarry Smith 9841b2b9847SBarry Smith /*@ 985f1580f4eSBarry Smith PCGetFailedReasonRank - Gets the reason a `PCSetUp()` failed or `PC_NOERROR` if it did not fail on this MPI rank 9861b2b9847SBarry Smith 987f1580f4eSBarry Smith Not Collective 9881b2b9847SBarry Smith 9891b2b9847SBarry Smith Input Parameter: 9901b2b9847SBarry Smith . pc - the preconditioner context 9911b2b9847SBarry Smith 9921b2b9847SBarry Smith Output Parameter: 9931b2b9847SBarry Smith . reason - the reason it failed 9941b2b9847SBarry Smith 99520f4b53cSBarry Smith Level: advanced 99620f4b53cSBarry Smith 997f1580f4eSBarry Smith Note: 998562efe2eSBarry Smith Different processes may have different reasons or no reason, see `PCGetFailedReason()` 9991b2b9847SBarry Smith 1000562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCGetFailedReason()`, `PCSetFailedReason()`, `PCReduceFailedReason()` 10011b2b9847SBarry Smith @*/ 1002d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGetFailedReasonRank(PC pc, PCFailedReason *reason) 1003d71ae5a4SJacob Faibussowitsch { 10041b2b9847SBarry Smith PetscFunctionBegin; 10056479e835SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 10061b2b9847SBarry Smith if (pc->setupcalled < 0) *reason = (PCFailedReason)pc->setupcalled; 10071b2b9847SBarry Smith else *reason = pc->failedreason; 10083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10091b2b9847SBarry Smith } 1010422a814eSBarry Smith 10116479e835SStefano Zampini /*@ 10126479e835SStefano Zampini PCReduceFailedReason - Reduce the failed reason among the MPI processes that share the `PC` 10136479e835SStefano Zampini 10146479e835SStefano Zampini Collective 10156479e835SStefano Zampini 10166479e835SStefano Zampini Input Parameter: 10176479e835SStefano Zampini . pc - the preconditioner context 10186479e835SStefano Zampini 10196479e835SStefano Zampini Level: advanced 10206479e835SStefano Zampini 10216479e835SStefano Zampini Note: 1022562efe2eSBarry Smith Different MPI processes may have different reasons or no reason, see `PCGetFailedReason()`. This routine 10236479e835SStefano Zampini makes them have a common value (failure if any MPI process had a failure). 10246479e835SStefano Zampini 1025562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCGetFailedReason()`, `PCSetFailedReason()` 10266479e835SStefano Zampini @*/ 10276479e835SStefano Zampini PetscErrorCode PCReduceFailedReason(PC pc) 10286479e835SStefano Zampini { 10296479e835SStefano Zampini PetscInt buf; 10306479e835SStefano Zampini 10316479e835SStefano Zampini PetscFunctionBegin; 10326479e835SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 10336479e835SStefano Zampini buf = (PetscInt)pc->failedreason; 10346479e835SStefano Zampini PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &buf, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)pc))); 10356479e835SStefano Zampini pc->failedreason = (PCFailedReason)buf; 10366479e835SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 10376479e835SStefano Zampini } 10386479e835SStefano Zampini 10394b9ad928SBarry Smith /* 10404b9ad928SBarry Smith a setupcall of 0 indicates never setup, 104123ee1639SBarry Smith 1 indicates has been previously setup 1042422a814eSBarry Smith -1 indicates a PCSetUp() was attempted and failed 10434b9ad928SBarry Smith */ 10444b9ad928SBarry Smith /*@ 10454b9ad928SBarry Smith PCSetUp - Prepares for the use of a preconditioner. 10464b9ad928SBarry Smith 1047c3339decSBarry Smith Collective 10484b9ad928SBarry Smith 10494b9ad928SBarry Smith Input Parameter: 10504b9ad928SBarry Smith . pc - the preconditioner context 10514b9ad928SBarry Smith 10524b9ad928SBarry Smith Level: developer 10534b9ad928SBarry Smith 1054562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()` 10554b9ad928SBarry Smith @*/ 1056d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp(PC pc) 1057d71ae5a4SJacob Faibussowitsch { 1058566e8bf2SBarry Smith const char *def; 1059fc9b51d3SBarry Smith PetscObjectState matstate, matnonzerostate; 10604b9ad928SBarry Smith 10614b9ad928SBarry Smith PetscFunctionBegin; 10620700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 106328b400f6SJacob Faibussowitsch PetscCheck(pc->mat, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be set first"); 10646ce5e81cSLisandro Dalcin 106523ee1639SBarry Smith if (pc->setupcalled && pc->reusepreconditioner) { 10669566063dSJacob Faibussowitsch PetscCall(PetscInfo(pc, "Leaving PC with identical preconditioner since reuse preconditioner is set\n")); 10673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10684b9ad928SBarry Smith } 10694b9ad928SBarry Smith 10709566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)pc->pmat, &matstate)); 10719566063dSJacob Faibussowitsch PetscCall(MatGetNonzeroState(pc->pmat, &matnonzerostate)); 107223ee1639SBarry Smith if (!pc->setupcalled) { 10735e62d202SMark Adams //PetscCall(PetscInfo(pc, "Setting up PC for first time\n")); 107423ee1639SBarry Smith pc->flag = DIFFERENT_NONZERO_PATTERN; 10759df67409SStefano Zampini } else if (matstate == pc->matstate) PetscFunctionReturn(PETSC_SUCCESS); 10769df67409SStefano Zampini else { 10779df67409SStefano Zampini if (matnonzerostate != pc->matnonzerostate) { 10789566063dSJacob Faibussowitsch PetscCall(PetscInfo(pc, "Setting up PC with different nonzero pattern\n")); 107923ee1639SBarry Smith pc->flag = DIFFERENT_NONZERO_PATTERN; 108023ee1639SBarry Smith } else { 10815e62d202SMark Adams //PetscCall(PetscInfo(pc, "Setting up PC with same nonzero pattern\n")); 108223ee1639SBarry Smith pc->flag = SAME_NONZERO_PATTERN; 108323ee1639SBarry Smith } 108423ee1639SBarry Smith } 108523ee1639SBarry Smith pc->matstate = matstate; 1086fc9b51d3SBarry Smith pc->matnonzerostate = matnonzerostate; 108723ee1639SBarry Smith 10887adad957SLisandro Dalcin if (!((PetscObject)pc)->type_name) { 10899566063dSJacob Faibussowitsch PetscCall(PCGetDefaultType_Private(pc, &def)); 10909566063dSJacob Faibussowitsch PetscCall(PCSetType(pc, def)); 1091566e8bf2SBarry Smith } 10924b9ad928SBarry Smith 10939566063dSJacob Faibussowitsch PetscCall(MatSetErrorIfFailure(pc->pmat, pc->erroriffailure)); 10949566063dSJacob Faibussowitsch PetscCall(MatSetErrorIfFailure(pc->mat, pc->erroriffailure)); 10959566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_SetUp, pc, 0, 0, 0)); 10964b9ad928SBarry Smith if (pc->ops->setup) { 1097fe57bb1aSStefano Zampini PetscCall(PCLogEventsDeactivatePush()); 1098dbbe0bcdSBarry Smith PetscUseTypeMethod(pc, setup); 1099fe57bb1aSStefano Zampini PetscCall(PCLogEventsDeactivatePop()); 11004b9ad928SBarry Smith } 11019566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_SetUp, pc, 0, 0, 0)); 1102422a814eSBarry Smith if (!pc->setupcalled) pc->setupcalled = 1; 11033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11044b9ad928SBarry Smith } 11054b9ad928SBarry Smith 11064b9ad928SBarry Smith /*@ 11074b9ad928SBarry Smith PCSetUpOnBlocks - Sets up the preconditioner for each block in 1108*73716367SStefano Zampini the block Jacobi, overlapping Schwarz, and fieldsplit methods. 11094b9ad928SBarry Smith 1110c3339decSBarry Smith Collective 11114b9ad928SBarry Smith 1112f1580f4eSBarry Smith Input Parameter: 11134b9ad928SBarry Smith . pc - the preconditioner context 11144b9ad928SBarry Smith 11154b9ad928SBarry Smith Level: developer 11164b9ad928SBarry Smith 1117*73716367SStefano Zampini Notes: 1118*73716367SStefano Zampini For nested preconditioners such as `PCBJACOBI`, `PCSetUp()` is not called on each sub-`KSP` when `PCSetUp()` is 1119f1580f4eSBarry Smith called on the outer `PC`, this routine ensures it is called. 1120f1580f4eSBarry Smith 1121*73716367SStefano Zampini It calls `PCSetUp()` if not yet called. 1122*73716367SStefano Zampini 1123562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCSetUp()`, `PCCreate()`, `PCApply()`, `PCDestroy()` 11244b9ad928SBarry Smith @*/ 1125d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUpOnBlocks(PC pc) 1126d71ae5a4SJacob Faibussowitsch { 11274b9ad928SBarry Smith PetscFunctionBegin; 11280700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1129*73716367SStefano Zampini if (!pc->setupcalled) PetscCall(PCSetUp(pc)); /* "if" to prevent -info extra prints */ 11303ba16761SJacob Faibussowitsch if (!pc->ops->setuponblocks) PetscFunctionReturn(PETSC_SUCCESS); 11319566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_SetUpOnBlocks, pc, 0, 0, 0)); 1132fe57bb1aSStefano Zampini PetscCall(PCLogEventsDeactivatePush()); 1133dbbe0bcdSBarry Smith PetscUseTypeMethod(pc, setuponblocks); 1134fe57bb1aSStefano Zampini PetscCall(PCLogEventsDeactivatePop()); 11359566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_SetUpOnBlocks, pc, 0, 0, 0)); 11363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11374b9ad928SBarry Smith } 11384b9ad928SBarry Smith 11394b9ad928SBarry Smith /*@C 11404b9ad928SBarry Smith PCSetModifySubMatrices - Sets a user-defined routine for modifying the 114104c3f3b8SBarry Smith submatrices that arise within certain subdomain-based preconditioners such as `PCASM` 11424b9ad928SBarry Smith 1143c3339decSBarry Smith Logically Collective 11444b9ad928SBarry Smith 11454b9ad928SBarry Smith Input Parameters: 11464b9ad928SBarry Smith + pc - the preconditioner context 11474b9ad928SBarry Smith . func - routine for modifying the submatrices 114804c3f3b8SBarry Smith - ctx - optional user-defined context (may be `NULL`) 11494b9ad928SBarry Smith 115020f4b53cSBarry Smith Calling sequence of `func`: 115120f4b53cSBarry Smith + pc - the preconditioner context 115204c3f3b8SBarry Smith . nsub - number of index sets 115320f4b53cSBarry Smith . row - an array of index sets that contain the global row numbers 11544b9ad928SBarry Smith that comprise each local submatrix 11554b9ad928SBarry Smith . col - an array of index sets that contain the global column numbers 11564b9ad928SBarry Smith that comprise each local submatrix 11574b9ad928SBarry Smith . submat - array of local submatrices 11584b9ad928SBarry Smith - ctx - optional user-defined context for private data for the 115904c3f3b8SBarry Smith user-defined func routine (may be `NULL`) 11604b9ad928SBarry Smith 116120f4b53cSBarry Smith Level: advanced 116220f4b53cSBarry Smith 11634b9ad928SBarry Smith Notes: 116404c3f3b8SBarry Smith The basic submatrices are extracted from the preconditioner matrix as 116504c3f3b8SBarry Smith usual; the user can then alter these (for example, to set different boundary 116604c3f3b8SBarry Smith conditions for each submatrix) before they are used for the local solves. 116704c3f3b8SBarry Smith 1168f1580f4eSBarry Smith `PCSetModifySubMatrices()` MUST be called before `KSPSetUp()` and 1169f1580f4eSBarry Smith `KSPSolve()`. 11704b9ad928SBarry Smith 1171f1580f4eSBarry Smith A routine set by `PCSetModifySubMatrices()` is currently called within 1172f1580f4eSBarry Smith the block Jacobi (`PCBJACOBI`) and additive Schwarz (`PCASM`) 11734b9ad928SBarry Smith preconditioners. All other preconditioners ignore this routine. 11744b9ad928SBarry Smith 1175562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCBJACOBI`, `PCASM`, `PCModifySubMatrices()` 11764b9ad928SBarry Smith @*/ 117704c3f3b8SBarry Smith PetscErrorCode PCSetModifySubMatrices(PC pc, PetscErrorCode (*func)(PC pc, PetscInt nsub, const IS row[], const IS col[], Mat submat[], void *ctx), void *ctx) 1178d71ae5a4SJacob Faibussowitsch { 11794b9ad928SBarry Smith PetscFunctionBegin; 11800700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 11814b9ad928SBarry Smith pc->modifysubmatrices = func; 11824b9ad928SBarry Smith pc->modifysubmatricesP = ctx; 11833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11844b9ad928SBarry Smith } 11854b9ad928SBarry Smith 11864b9ad928SBarry Smith /*@C 11874b9ad928SBarry Smith PCModifySubMatrices - Calls an optional user-defined routine within 1188f1580f4eSBarry Smith certain preconditioners if one has been set with `PCSetModifySubMatrices()`. 11894b9ad928SBarry Smith 1190c3339decSBarry Smith Collective 11914b9ad928SBarry Smith 11924b9ad928SBarry Smith Input Parameters: 11934b9ad928SBarry Smith + pc - the preconditioner context 11944b9ad928SBarry Smith . nsub - the number of local submatrices 11954b9ad928SBarry Smith . row - an array of index sets that contain the global row numbers 11964b9ad928SBarry Smith that comprise each local submatrix 11974b9ad928SBarry Smith . col - an array of index sets that contain the global column numbers 11984b9ad928SBarry Smith that comprise each local submatrix 11994b9ad928SBarry Smith . submat - array of local submatrices 12004b9ad928SBarry Smith - ctx - optional user-defined context for private data for the 1201562efe2eSBarry Smith user-defined routine (may be `NULL`) 12024b9ad928SBarry Smith 12034b9ad928SBarry Smith Output Parameter: 12044b9ad928SBarry Smith . submat - array of local submatrices (the entries of which may 12054b9ad928SBarry Smith have been modified) 12064b9ad928SBarry Smith 120720f4b53cSBarry Smith Level: developer 120820f4b53cSBarry Smith 120904c3f3b8SBarry Smith Note: 12104b9ad928SBarry Smith The user should NOT generally call this routine, as it will 121104c3f3b8SBarry Smith automatically be called within certain preconditioners. 12124b9ad928SBarry Smith 1213562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCSetModifySubMatrices()` 12144b9ad928SBarry Smith @*/ 1215d71ae5a4SJacob Faibussowitsch PetscErrorCode PCModifySubMatrices(PC pc, PetscInt nsub, const IS row[], const IS col[], Mat submat[], void *ctx) 1216d71ae5a4SJacob Faibussowitsch { 12174b9ad928SBarry Smith PetscFunctionBegin; 12180700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 12193ba16761SJacob Faibussowitsch if (!pc->modifysubmatrices) PetscFunctionReturn(PETSC_SUCCESS); 12209566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_ModifySubMatrices, pc, 0, 0, 0)); 12219566063dSJacob Faibussowitsch PetscCall((*pc->modifysubmatrices)(pc, nsub, row, col, submat, ctx)); 12229566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_ModifySubMatrices, pc, 0, 0, 0)); 12233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12244b9ad928SBarry Smith } 12254b9ad928SBarry Smith 12264b9ad928SBarry Smith /*@ 12274b9ad928SBarry Smith PCSetOperators - Sets the matrix associated with the linear system and 12284b9ad928SBarry Smith a (possibly) different one associated with the preconditioner. 12294b9ad928SBarry Smith 1230c3339decSBarry Smith Logically Collective 12314b9ad928SBarry Smith 12324b9ad928SBarry Smith Input Parameters: 12334b9ad928SBarry Smith + pc - the preconditioner context 1234e5d3d808SBarry Smith . Amat - the matrix that defines the linear system 1235d1e9a80fSBarry Smith - Pmat - the matrix to be used in constructing the preconditioner, usually the same as Amat. 12364b9ad928SBarry Smith 123720f4b53cSBarry Smith Level: intermediate 1238189c0b8aSBarry Smith 123920f4b53cSBarry Smith Notes: 124020f4b53cSBarry Smith Passing a `NULL` for `Amat` or `Pmat` removes the matrix that is currently used. 124120f4b53cSBarry Smith 124220f4b53cSBarry Smith If you wish to replace either `Amat` or `Pmat` but leave the other one untouched then 1243f1580f4eSBarry Smith first call `KSPGetOperators()` to get the one you wish to keep, call `PetscObjectReference()` 1244f1580f4eSBarry Smith on it and then pass it back in in your call to `KSPSetOperators()`. 1245189c0b8aSBarry Smith 12464b9ad928SBarry Smith More Notes about Repeated Solution of Linear Systems: 124720f4b53cSBarry Smith PETSc does NOT reset the matrix entries of either `Amat` or `Pmat` 12484b9ad928SBarry Smith to zero after a linear solve; the user is completely responsible for 1249f1580f4eSBarry Smith matrix assembly. See the routine `MatZeroEntries()` if desiring to 12504b9ad928SBarry Smith zero all elements of a matrix. 12514b9ad928SBarry Smith 1252562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCGetOperators()`, `MatZeroEntries()` 12534b9ad928SBarry Smith @*/ 1254d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetOperators(PC pc, Mat Amat, Mat Pmat) 1255d71ae5a4SJacob Faibussowitsch { 12563b3f6333SBarry Smith PetscInt m1, n1, m2, n2; 12574b9ad928SBarry Smith 12584b9ad928SBarry Smith PetscFunctionBegin; 12590700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 12600700a824SBarry Smith if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 12610700a824SBarry Smith if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3); 12623fc8bf9cSBarry Smith if (Amat) PetscCheckSameComm(pc, 1, Amat, 2); 12633fc8bf9cSBarry Smith if (Pmat) PetscCheckSameComm(pc, 1, Pmat, 3); 126431641f1aSBarry Smith if (pc->setupcalled && pc->mat && pc->pmat && Amat && Pmat) { 12659566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(Amat, &m1, &n1)); 12669566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pc->mat, &m2, &n2)); 126763a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m2 && n1 == n2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Cannot change local size of Amat after use old sizes %" PetscInt_FMT " %" PetscInt_FMT " new sizes %" PetscInt_FMT " %" PetscInt_FMT, m2, n2, m1, n1); 12689566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(Pmat, &m1, &n1)); 12699566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pc->pmat, &m2, &n2)); 127063a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m2 && n1 == n2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Cannot change local size of Pmat after use old sizes %" PetscInt_FMT " %" PetscInt_FMT " new sizes %" PetscInt_FMT " %" PetscInt_FMT, m2, n2, m1, n1); 12713b3f6333SBarry Smith } 12724b9ad928SBarry Smith 127323ee1639SBarry Smith if (Pmat != pc->pmat) { 127423ee1639SBarry Smith /* changing the operator that defines the preconditioner thus reneed to clear current states so new preconditioner is built */ 127523ee1639SBarry Smith pc->matnonzerostate = -1; 127623ee1639SBarry Smith pc->matstate = -1; 127723ee1639SBarry Smith } 127823ee1639SBarry Smith 1279906ed7ccSBarry Smith /* reference first in case the matrices are the same */ 12809566063dSJacob Faibussowitsch if (Amat) PetscCall(PetscObjectReference((PetscObject)Amat)); 12819566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pc->mat)); 12829566063dSJacob Faibussowitsch if (Pmat) PetscCall(PetscObjectReference((PetscObject)Pmat)); 12839566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pc->pmat)); 12844b9ad928SBarry Smith pc->mat = Amat; 12854b9ad928SBarry Smith pc->pmat = Pmat; 12863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1287e56f5c9eSBarry Smith } 1288e56f5c9eSBarry Smith 128923ee1639SBarry Smith /*@ 129023ee1639SBarry Smith PCSetReusePreconditioner - reuse the current preconditioner even if the operator in the preconditioner has changed. 129123ee1639SBarry Smith 1292c3339decSBarry Smith Logically Collective 129323ee1639SBarry Smith 129423ee1639SBarry Smith Input Parameters: 129523ee1639SBarry Smith + pc - the preconditioner context 1296f1580f4eSBarry Smith - flag - `PETSC_TRUE` do not compute a new preconditioner, `PETSC_FALSE` do compute a new preconditioner 129723ee1639SBarry Smith 12982b26979fSBarry Smith Level: intermediate 12992b26979fSBarry Smith 1300f1580f4eSBarry Smith Note: 1301f1580f4eSBarry Smith Normally if a matrix inside a `PC` changes the `PC` automatically updates itself using information from the changed matrix. This option 1302f1580f4eSBarry Smith prevents this. 1303f1580f4eSBarry Smith 1304562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCGetOperators()`, `MatZeroEntries()`, `PCGetReusePreconditioner()`, `KSPSetReusePreconditioner()` 130523ee1639SBarry Smith @*/ 1306d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetReusePreconditioner(PC pc, PetscBool flag) 1307d71ae5a4SJacob Faibussowitsch { 130823ee1639SBarry Smith PetscFunctionBegin; 130923ee1639SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1310f9177522SStefano Zampini PetscValidLogicalCollectiveBool(pc, flag, 2); 131123ee1639SBarry Smith pc->reusepreconditioner = flag; 13123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13134b9ad928SBarry Smith } 13144b9ad928SBarry Smith 1315c60c7ad4SBarry Smith /*@ 1316f1580f4eSBarry Smith PCGetReusePreconditioner - Determines if the `PC` reuses the current preconditioner even if the operator in the preconditioner has changed. 1317c60c7ad4SBarry Smith 1318bba28a21SBarry Smith Not Collective 1319c60c7ad4SBarry Smith 1320c60c7ad4SBarry Smith Input Parameter: 1321c60c7ad4SBarry Smith . pc - the preconditioner context 1322c60c7ad4SBarry Smith 1323c60c7ad4SBarry Smith Output Parameter: 1324f1580f4eSBarry Smith . flag - `PETSC_TRUE` do not compute a new preconditioner, `PETSC_FALSE` do compute a new preconditioner 1325c60c7ad4SBarry Smith 1326d0418729SSatish Balay Level: intermediate 1327d0418729SSatish Balay 1328562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCGetOperators()`, `MatZeroEntries()`, `PCSetReusePreconditioner()` 1329c60c7ad4SBarry Smith @*/ 1330d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGetReusePreconditioner(PC pc, PetscBool *flag) 1331d71ae5a4SJacob Faibussowitsch { 1332c60c7ad4SBarry Smith PetscFunctionBegin; 1333c60c7ad4SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 13344f572ea9SToby Isaac PetscAssertPointer(flag, 2); 1335c60c7ad4SBarry Smith *flag = pc->reusepreconditioner; 13363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1337c60c7ad4SBarry Smith } 1338c60c7ad4SBarry Smith 1339487a658cSBarry Smith /*@ 13404b9ad928SBarry Smith PCGetOperators - Gets the matrix associated with the linear system and 13414b9ad928SBarry Smith possibly a different one associated with the preconditioner. 13424b9ad928SBarry Smith 1343562efe2eSBarry Smith Not Collective, though parallel `Mat`s are returned if `pc` is parallel 13444b9ad928SBarry Smith 13454b9ad928SBarry Smith Input Parameter: 13464b9ad928SBarry Smith . pc - the preconditioner context 13474b9ad928SBarry Smith 13484b9ad928SBarry Smith Output Parameters: 1349e5d3d808SBarry Smith + Amat - the matrix defining the linear system 135023ee1639SBarry Smith - Pmat - the matrix from which the preconditioner is constructed, usually the same as Amat. 13514b9ad928SBarry Smith 13524b9ad928SBarry Smith Level: intermediate 13534b9ad928SBarry Smith 1354f1580f4eSBarry Smith Note: 135595452b02SPatrick Sanan Does not increase the reference count of the matrices, so you should not destroy them 1356298cc208SBarry Smith 1357f1580f4eSBarry Smith Alternative usage: If the operators have NOT been set with `KSPSetOperators()`/`PCSetOperators()` then the operators 1358f1580f4eSBarry Smith are created in `PC` and returned to the user. In this case, if both operators 135973950996SBarry Smith mat and pmat are requested, two DIFFERENT operators will be returned. If 136073950996SBarry Smith only one is requested both operators in the PC will be the same (i.e. as 1361f1580f4eSBarry Smith if one had called `KSPSetOperators()`/`PCSetOperators()` with the same argument for both Mats). 136273950996SBarry Smith The user must set the sizes of the returned matrices and their type etc just 1363f1580f4eSBarry Smith as if the user created them with `MatCreate()`. For example, 136473950996SBarry Smith 1365f1580f4eSBarry Smith .vb 1366f1580f4eSBarry Smith KSP/PCGetOperators(ksp/pc,&Amat,NULL); is equivalent to 1367f1580f4eSBarry Smith set size, type, etc of Amat 136873950996SBarry Smith 1369f1580f4eSBarry Smith MatCreate(comm,&mat); 1370f1580f4eSBarry Smith KSP/PCSetOperators(ksp/pc,Amat,Amat); 1371f1580f4eSBarry Smith PetscObjectDereference((PetscObject)mat); 1372f1580f4eSBarry Smith set size, type, etc of Amat 1373f1580f4eSBarry Smith .ve 137473950996SBarry Smith 137573950996SBarry Smith and 137673950996SBarry Smith 1377f1580f4eSBarry Smith .vb 1378f1580f4eSBarry Smith KSP/PCGetOperators(ksp/pc,&Amat,&Pmat); is equivalent to 1379f1580f4eSBarry Smith set size, type, etc of Amat and Pmat 138073950996SBarry Smith 1381f1580f4eSBarry Smith MatCreate(comm,&Amat); 1382f1580f4eSBarry Smith MatCreate(comm,&Pmat); 1383f1580f4eSBarry Smith KSP/PCSetOperators(ksp/pc,Amat,Pmat); 1384f1580f4eSBarry Smith PetscObjectDereference((PetscObject)Amat); 1385f1580f4eSBarry Smith PetscObjectDereference((PetscObject)Pmat); 1386f1580f4eSBarry Smith set size, type, etc of Amat and Pmat 1387f1580f4eSBarry Smith .ve 138873950996SBarry Smith 1389f1580f4eSBarry Smith The rationale for this support is so that when creating a `TS`, `SNES`, or `KSP` the hierarchy 1390b8d709abSRichard Tran Mills of underlying objects (i.e. `SNES`, `KSP`, `PC`, `Mat`) and their lifespans can be completely 1391f1580f4eSBarry Smith managed by the top most level object (i.e. the `TS`, `SNES`, or `KSP`). Another way to look 1392f1580f4eSBarry Smith at this is when you create a `SNES` you do not NEED to create a `KSP` and attach it to 1393f1580f4eSBarry Smith the `SNES` object (the `SNES` object manages it for you). Similarly when you create a KSP 1394f1580f4eSBarry Smith you do not need to attach a `PC` to it (the `KSP` object manages the `PC` object for you). 1395f1580f4eSBarry Smith Thus, why should YOU have to create the `Mat` and attach it to the `SNES`/`KSP`/`PC`, when 139673950996SBarry Smith it can be created for you? 139773950996SBarry Smith 1398562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCSetOperators()`, `KSPGetOperators()`, `KSPSetOperators()`, `PCGetOperatorsSet()` 13994b9ad928SBarry Smith @*/ 1400d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGetOperators(PC pc, Mat *Amat, Mat *Pmat) 1401d71ae5a4SJacob Faibussowitsch { 14024b9ad928SBarry Smith PetscFunctionBegin; 14030700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1404e5d3d808SBarry Smith if (Amat) { 140573950996SBarry Smith if (!pc->mat) { 14069fca8c71SStefano Zampini if (pc->pmat && !Pmat) { /* Pmat has been set, but user did not request it, so use for Amat */ 14079a4708feSJed Brown pc->mat = pc->pmat; 14089566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pc->mat)); 1409e5d3d808SBarry Smith } else { /* both Amat and Pmat are empty */ 14109566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &pc->mat)); 1411e5d3d808SBarry Smith if (!Pmat) { /* user did NOT request Pmat, so make same as Amat */ 141273950996SBarry Smith pc->pmat = pc->mat; 14139566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pc->pmat)); 141473950996SBarry Smith } 141573950996SBarry Smith } 14169a4708feSJed Brown } 1417e5d3d808SBarry Smith *Amat = pc->mat; 141873950996SBarry Smith } 1419e5d3d808SBarry Smith if (Pmat) { 142073950996SBarry Smith if (!pc->pmat) { 1421e5d3d808SBarry Smith if (pc->mat && !Amat) { /* Amat has been set but was not requested, so use for pmat */ 14229a4708feSJed Brown pc->pmat = pc->mat; 14239566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pc->pmat)); 14249a4708feSJed Brown } else { 14259566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &pc->pmat)); 1426e5d3d808SBarry Smith if (!Amat) { /* user did NOT request Amat, so make same as Pmat */ 142773950996SBarry Smith pc->mat = pc->pmat; 14289566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pc->mat)); 142973950996SBarry Smith } 143073950996SBarry Smith } 14319a4708feSJed Brown } 1432e5d3d808SBarry Smith *Pmat = pc->pmat; 143373950996SBarry Smith } 14343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14354b9ad928SBarry Smith } 14364b9ad928SBarry Smith 14375d83a8b1SBarry Smith /*@ 1438906ed7ccSBarry Smith PCGetOperatorsSet - Determines if the matrix associated with the linear system and 1439f1580f4eSBarry Smith possibly a different one associated with the preconditioner have been set in the `PC`. 1440906ed7ccSBarry Smith 144120f4b53cSBarry Smith Not Collective, though the results on all processes should be the same 1442906ed7ccSBarry Smith 1443906ed7ccSBarry Smith Input Parameter: 1444906ed7ccSBarry Smith . pc - the preconditioner context 1445906ed7ccSBarry Smith 1446906ed7ccSBarry Smith Output Parameters: 1447906ed7ccSBarry Smith + mat - the matrix associated with the linear system was set 1448906ed7ccSBarry Smith - pmat - matrix associated with the preconditioner was set, usually the same 1449906ed7ccSBarry Smith 1450906ed7ccSBarry Smith Level: intermediate 1451906ed7ccSBarry Smith 1452562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCSetOperators()`, `KSPGetOperators()`, `KSPSetOperators()`, `PCGetOperators()` 1453906ed7ccSBarry Smith @*/ 1454d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGetOperatorsSet(PC pc, PetscBool *mat, PetscBool *pmat) 1455d71ae5a4SJacob Faibussowitsch { 1456906ed7ccSBarry Smith PetscFunctionBegin; 14570700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1458906ed7ccSBarry Smith if (mat) *mat = (pc->mat) ? PETSC_TRUE : PETSC_FALSE; 1459906ed7ccSBarry Smith if (pmat) *pmat = (pc->pmat) ? PETSC_TRUE : PETSC_FALSE; 14603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1461906ed7ccSBarry Smith } 1462906ed7ccSBarry Smith 1463f39d8e23SSatish Balay /*@ 1464a4fd02acSBarry Smith PCFactorGetMatrix - Gets the factored matrix from the 1465f1580f4eSBarry Smith preconditioner context. This routine is valid only for the `PCLU`, 1466f1580f4eSBarry Smith `PCILU`, `PCCHOLESKY`, and `PCICC` methods. 14674b9ad928SBarry Smith 1468562efe2eSBarry Smith Not Collective though `mat` is parallel if `pc` is parallel 14694b9ad928SBarry Smith 1470f1580f4eSBarry Smith Input Parameter: 14714b9ad928SBarry Smith . pc - the preconditioner context 14724b9ad928SBarry Smith 1473feefa0e1SJacob Faibussowitsch Output Parameters: 14744b9ad928SBarry Smith . mat - the factored matrix 14754b9ad928SBarry Smith 14764b9ad928SBarry Smith Level: advanced 14774b9ad928SBarry Smith 1478f1580f4eSBarry Smith Note: 1479562efe2eSBarry Smith Does not increase the reference count for `mat` so DO NOT destroy it 14809405f653SBarry Smith 1481562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 14824b9ad928SBarry Smith @*/ 1483d71ae5a4SJacob Faibussowitsch PetscErrorCode PCFactorGetMatrix(PC pc, Mat *mat) 1484d71ae5a4SJacob Faibussowitsch { 14854b9ad928SBarry Smith PetscFunctionBegin; 14860700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 14874f572ea9SToby Isaac PetscAssertPointer(mat, 2); 14887def7855SStefano Zampini PetscCall(PCFactorSetUpMatSolverType(pc)); 1489dbbe0bcdSBarry Smith PetscUseTypeMethod(pc, getfactoredmatrix, mat); 14903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14914b9ad928SBarry Smith } 14924b9ad928SBarry Smith 1493cc4c1da9SBarry Smith /*@ 14944b9ad928SBarry Smith PCSetOptionsPrefix - Sets the prefix used for searching for all 1495f1580f4eSBarry Smith `PC` options in the database. 14964b9ad928SBarry Smith 1497c3339decSBarry Smith Logically Collective 14984b9ad928SBarry Smith 14994b9ad928SBarry Smith Input Parameters: 15004b9ad928SBarry Smith + pc - the preconditioner context 1501f1580f4eSBarry Smith - prefix - the prefix string to prepend to all `PC` option requests 15024b9ad928SBarry Smith 1503f1580f4eSBarry Smith Note: 15044b9ad928SBarry Smith A hyphen (-) must NOT be given at the beginning of the prefix name. 15054b9ad928SBarry Smith The first character of all runtime options is AUTOMATICALLY the 15064b9ad928SBarry Smith hyphen. 15074b9ad928SBarry Smith 15084b9ad928SBarry Smith Level: advanced 15094b9ad928SBarry Smith 1510562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCSetFromOptions`, `PCAppendOptionsPrefix()`, `PCGetOptionsPrefix()` 15114b9ad928SBarry Smith @*/ 1512d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetOptionsPrefix(PC pc, const char prefix[]) 1513d71ae5a4SJacob Faibussowitsch { 15144b9ad928SBarry Smith PetscFunctionBegin; 15150700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 15169566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)pc, prefix)); 15173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15184b9ad928SBarry Smith } 15194b9ad928SBarry Smith 1520cc4c1da9SBarry Smith /*@ 15214b9ad928SBarry Smith PCAppendOptionsPrefix - Appends to the prefix used for searching for all 1522f1580f4eSBarry Smith `PC` options in the database. 15234b9ad928SBarry Smith 1524c3339decSBarry Smith Logically Collective 15254b9ad928SBarry Smith 15264b9ad928SBarry Smith Input Parameters: 15274b9ad928SBarry Smith + pc - the preconditioner context 1528f1580f4eSBarry Smith - prefix - the prefix string to prepend to all `PC` option requests 15294b9ad928SBarry Smith 1530f1580f4eSBarry Smith Note: 15314b9ad928SBarry Smith A hyphen (-) must NOT be given at the beginning of the prefix name. 15324b9ad928SBarry Smith The first character of all runtime options is AUTOMATICALLY the 15334b9ad928SBarry Smith hyphen. 15344b9ad928SBarry Smith 15354b9ad928SBarry Smith Level: advanced 15364b9ad928SBarry Smith 1537562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCSetFromOptions`, `PCSetOptionsPrefix()`, `PCGetOptionsPrefix()` 15384b9ad928SBarry Smith @*/ 1539d71ae5a4SJacob Faibussowitsch PetscErrorCode PCAppendOptionsPrefix(PC pc, const char prefix[]) 1540d71ae5a4SJacob Faibussowitsch { 15414b9ad928SBarry Smith PetscFunctionBegin; 15420700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 15439566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)pc, prefix)); 15443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15454b9ad928SBarry Smith } 15464b9ad928SBarry Smith 1547cc4c1da9SBarry Smith /*@ 15484b9ad928SBarry Smith PCGetOptionsPrefix - Gets the prefix used for searching for all 15494b9ad928SBarry Smith PC options in the database. 15504b9ad928SBarry Smith 15514b9ad928SBarry Smith Not Collective 15524b9ad928SBarry Smith 1553f1580f4eSBarry Smith Input Parameter: 15544b9ad928SBarry Smith . pc - the preconditioner context 15554b9ad928SBarry Smith 1556f1580f4eSBarry Smith Output Parameter: 15574b9ad928SBarry Smith . prefix - pointer to the prefix string used, is returned 15584b9ad928SBarry Smith 15594b9ad928SBarry Smith Level: advanced 15604b9ad928SBarry Smith 1561562efe2eSBarry Smith Fortran Note: 1562562efe2eSBarry Smith The user should pass in a string `prefix` of 1563562efe2eSBarry Smith sufficient length to hold the prefix. 1564562efe2eSBarry Smith 1565562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCSetFromOptions`, `PCSetOptionsPrefix()`, `PCAppendOptionsPrefix()` 15664b9ad928SBarry Smith @*/ 1567d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGetOptionsPrefix(PC pc, const char *prefix[]) 1568d71ae5a4SJacob Faibussowitsch { 15694b9ad928SBarry Smith PetscFunctionBegin; 15700700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 15714f572ea9SToby Isaac PetscAssertPointer(prefix, 2); 15729566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)pc, prefix)); 15733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15744b9ad928SBarry Smith } 15754b9ad928SBarry Smith 15768066bbecSBarry Smith /* 1577dd8e379bSPierre Jolivet Indicates the right-hand side will be changed by KSPSolve(), this occurs for a few 15788066bbecSBarry Smith preconditioners including BDDC and Eisentat that transform the equations before applying 15798066bbecSBarry Smith the Krylov methods 15808066bbecSBarry Smith */ 1581d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PCPreSolveChangeRHS(PC pc, PetscBool *change) 1582d71ae5a4SJacob Faibussowitsch { 1583a06fd7f2SStefano Zampini PetscFunctionBegin; 1584a06fd7f2SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 15854f572ea9SToby Isaac PetscAssertPointer(change, 2); 1586a06fd7f2SStefano Zampini *change = PETSC_FALSE; 1587cac4c232SBarry Smith PetscTryMethod(pc, "PCPreSolveChangeRHS_C", (PC, PetscBool *), (pc, change)); 15883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1589a06fd7f2SStefano Zampini } 1590a06fd7f2SStefano Zampini 15914b9ad928SBarry Smith /*@ 15924b9ad928SBarry Smith PCPreSolve - Optional pre-solve phase, intended for any 15934b9ad928SBarry Smith preconditioner-specific actions that must be performed before 15944b9ad928SBarry Smith the iterative solve itself. 15954b9ad928SBarry Smith 1596c3339decSBarry Smith Collective 15974b9ad928SBarry Smith 15984b9ad928SBarry Smith Input Parameters: 15994b9ad928SBarry Smith + pc - the preconditioner context 16004b9ad928SBarry Smith - ksp - the Krylov subspace context 16014b9ad928SBarry Smith 16024b9ad928SBarry Smith Level: developer 16034b9ad928SBarry Smith 1604feefa0e1SJacob Faibussowitsch Example Usage: 16054b9ad928SBarry Smith .vb 16064b9ad928SBarry Smith PCPreSolve(pc,ksp); 160723ce1328SBarry Smith KSPSolve(ksp,b,x); 16084b9ad928SBarry Smith PCPostSolve(pc,ksp); 16094b9ad928SBarry Smith .ve 16104b9ad928SBarry Smith 16114b9ad928SBarry Smith Notes: 1612f1580f4eSBarry Smith The pre-solve phase is distinct from the `PCSetUp()` phase. 16134b9ad928SBarry Smith 1614f1580f4eSBarry Smith `KSPSolve()` calls this directly, so is rarely called by the user. 16154b9ad928SBarry Smith 1616562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCPostSolve()` 16174b9ad928SBarry Smith @*/ 1618d71ae5a4SJacob Faibussowitsch PetscErrorCode PCPreSolve(PC pc, KSP ksp) 1619d71ae5a4SJacob Faibussowitsch { 16204b9ad928SBarry Smith Vec x, rhs; 16214b9ad928SBarry Smith 16224b9ad928SBarry Smith PetscFunctionBegin; 16230700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 16240700a824SBarry Smith PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2); 1625d9a03883SBarry Smith pc->presolvedone++; 16267827d75bSBarry Smith PetscCheck(pc->presolvedone <= 2, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot embed PCPreSolve() more than twice"); 16279566063dSJacob Faibussowitsch PetscCall(KSPGetSolution(ksp, &x)); 16289566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(ksp, &rhs)); 16294b9ad928SBarry Smith 1630dbbe0bcdSBarry Smith if (pc->ops->presolve) PetscUseTypeMethod(pc, presolve, ksp, rhs, x); 1631f4f49eeaSPierre Jolivet else if (pc->presolve) PetscCall(pc->presolve(pc, ksp)); 16323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16334b9ad928SBarry Smith } 16344b9ad928SBarry Smith 1635f560b561SHong Zhang /*@C 1636f1580f4eSBarry Smith PCSetPreSolve - Sets function used by `PCPreSolve()` which is intended for any 1637f560b561SHong Zhang preconditioner-specific actions that must be performed before 1638f560b561SHong Zhang the iterative solve itself. 1639f560b561SHong Zhang 1640c3339decSBarry Smith Logically Collective 1641f560b561SHong Zhang 1642f560b561SHong Zhang Input Parameters: 1643f560b561SHong Zhang + pc - the preconditioner object 1644f560b561SHong Zhang - presolve - the function to call before the solve 1645f560b561SHong Zhang 164620f4b53cSBarry Smith Calling sequence of `presolve`: 164720f4b53cSBarry Smith + pc - the `PC` context 164820f4b53cSBarry Smith - ksp - the `KSP` context 1649f560b561SHong Zhang 1650f560b561SHong Zhang Level: developer 1651f560b561SHong Zhang 1652562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCSetUp()`, `PCPreSolve()` 1653f560b561SHong Zhang @*/ 165404c3f3b8SBarry Smith PetscErrorCode PCSetPreSolve(PC pc, PetscErrorCode (*presolve)(PC pc, KSP ksp)) 1655d71ae5a4SJacob Faibussowitsch { 1656f560b561SHong Zhang PetscFunctionBegin; 1657f560b561SHong Zhang PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1658f560b561SHong Zhang pc->presolve = presolve; 16593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1660f560b561SHong Zhang } 1661f560b561SHong Zhang 16624b9ad928SBarry Smith /*@ 16634b9ad928SBarry Smith PCPostSolve - Optional post-solve phase, intended for any 16644b9ad928SBarry Smith preconditioner-specific actions that must be performed after 16654b9ad928SBarry Smith the iterative solve itself. 16664b9ad928SBarry Smith 1667c3339decSBarry Smith Collective 16684b9ad928SBarry Smith 16694b9ad928SBarry Smith Input Parameters: 16704b9ad928SBarry Smith + pc - the preconditioner context 16714b9ad928SBarry Smith - ksp - the Krylov subspace context 16724b9ad928SBarry Smith 1673feefa0e1SJacob Faibussowitsch Example Usage: 16744b9ad928SBarry Smith .vb 16754b9ad928SBarry Smith PCPreSolve(pc,ksp); 167623ce1328SBarry Smith KSPSolve(ksp,b,x); 16774b9ad928SBarry Smith PCPostSolve(pc,ksp); 16784b9ad928SBarry Smith .ve 16794b9ad928SBarry Smith 1680562efe2eSBarry Smith Level: developer 1681562efe2eSBarry Smith 16824b9ad928SBarry Smith Note: 1683f1580f4eSBarry Smith `KSPSolve()` calls this routine directly, so it is rarely called by the user. 16844b9ad928SBarry Smith 1685562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCSetPostSolve()`, `PCSetPresolve()`, `PCPreSolve()`, `KSPSolve()` 16864b9ad928SBarry Smith @*/ 1687d71ae5a4SJacob Faibussowitsch PetscErrorCode PCPostSolve(PC pc, KSP ksp) 1688d71ae5a4SJacob Faibussowitsch { 16894b9ad928SBarry Smith Vec x, rhs; 16904b9ad928SBarry Smith 16914b9ad928SBarry Smith PetscFunctionBegin; 16920700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 16930700a824SBarry Smith PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2); 1694d9a03883SBarry Smith pc->presolvedone--; 16959566063dSJacob Faibussowitsch PetscCall(KSPGetSolution(ksp, &x)); 16969566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(ksp, &rhs)); 1697dbbe0bcdSBarry Smith PetscTryTypeMethod(pc, postsolve, ksp, rhs, x); 16983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16994b9ad928SBarry Smith } 17004b9ad928SBarry Smith 1701ffeef943SBarry Smith /*@ 1702f1580f4eSBarry Smith PCLoad - Loads a `PC` that has been stored in binary with `PCView()`. 170355849f57SBarry Smith 1704c3339decSBarry Smith Collective 170555849f57SBarry Smith 170655849f57SBarry Smith Input Parameters: 1707f1580f4eSBarry Smith + newdm - the newly loaded `PC`, this needs to have been created with `PCCreate()` or 1708f1580f4eSBarry Smith some related function before a call to `PCLoad()`. 1709f1580f4eSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()` 171055849f57SBarry Smith 171155849f57SBarry Smith Level: intermediate 171255849f57SBarry Smith 1713f1580f4eSBarry Smith Note: 1714562efe2eSBarry Smith The type is determined by the data in the file, any `PCType` set into the `PC` before this call is ignored. 171555849f57SBarry Smith 1716562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PetscViewerBinaryOpen()`, `PCView()`, `MatLoad()`, `VecLoad()` 171755849f57SBarry Smith @*/ 1718d71ae5a4SJacob Faibussowitsch PetscErrorCode PCLoad(PC newdm, PetscViewer viewer) 1719d71ae5a4SJacob Faibussowitsch { 172055849f57SBarry Smith PetscBool isbinary; 1721060da220SMatthew G. Knepley PetscInt classid; 172255849f57SBarry Smith char type[256]; 172355849f57SBarry Smith 172455849f57SBarry Smith PetscFunctionBegin; 172555849f57SBarry Smith PetscValidHeaderSpecific(newdm, PC_CLASSID, 1); 172655849f57SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 17279566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 172828b400f6SJacob Faibussowitsch PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()"); 172955849f57SBarry Smith 17309566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT)); 17317827d75bSBarry Smith PetscCheck(classid == PC_FILE_CLASSID, PetscObjectComm((PetscObject)newdm), PETSC_ERR_ARG_WRONG, "Not PC next in file"); 17329566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR)); 17339566063dSJacob Faibussowitsch PetscCall(PCSetType(newdm, type)); 1734dbbe0bcdSBarry Smith PetscTryTypeMethod(newdm, load, viewer); 17353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 173655849f57SBarry Smith } 173755849f57SBarry Smith 17389804daf3SBarry Smith #include <petscdraw.h> 1739e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 1740e04113cfSBarry Smith #include <petscviewersaws.h> 17410acecf5bSBarry Smith #endif 1742fe2efc57SMark 1743ffeef943SBarry Smith /*@ 1744562efe2eSBarry Smith PCViewFromOptions - View from the `PC` based on options in the options database 1745fe2efc57SMark 1746c3339decSBarry Smith Collective 1747fe2efc57SMark 1748fe2efc57SMark Input Parameters: 174920f4b53cSBarry Smith + A - the `PC` context 1750f1580f4eSBarry Smith . obj - Optional object that provides the options prefix 1751736c3998SJose E. Roman - name - command line option 1752fe2efc57SMark 1753fe2efc57SMark Level: intermediate 1754f1580f4eSBarry Smith 1755562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCView`, `PetscObjectViewFromOptions()`, `PCCreate()` 1756fe2efc57SMark @*/ 1757d71ae5a4SJacob Faibussowitsch PetscErrorCode PCViewFromOptions(PC A, PetscObject obj, const char name[]) 1758d71ae5a4SJacob Faibussowitsch { 1759fe2efc57SMark PetscFunctionBegin; 1760fe2efc57SMark PetscValidHeaderSpecific(A, PC_CLASSID, 1); 17619566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 17623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1763fe2efc57SMark } 1764fe2efc57SMark 1765ffeef943SBarry Smith /*@ 1766f1580f4eSBarry Smith PCView - Prints information about the `PC` 17674b9ad928SBarry Smith 1768c3339decSBarry Smith Collective 17694b9ad928SBarry Smith 17704b9ad928SBarry Smith Input Parameters: 1771feefa0e1SJacob Faibussowitsch + pc - the `PC` context 17724b9ad928SBarry Smith - viewer - optional visualization context 17734b9ad928SBarry Smith 177420f4b53cSBarry Smith Level: developer 177520f4b53cSBarry Smith 1776f1580f4eSBarry Smith Notes: 17774b9ad928SBarry Smith The available visualization contexts include 1778f1580f4eSBarry Smith + `PETSC_VIEWER_STDOUT_SELF` - standard output (default) 1779f1580f4eSBarry Smith - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard 17804b9ad928SBarry Smith output where only the first processor opens 17814b9ad928SBarry Smith the file. All other processors send their 17824b9ad928SBarry Smith data to the first processor to print. 17834b9ad928SBarry Smith 17844b9ad928SBarry Smith The user can open an alternative visualization contexts with 1785f1580f4eSBarry Smith `PetscViewerASCIIOpen()` (output to a specified file). 17864b9ad928SBarry Smith 1787562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PetscViewer`, `KSPView()`, `PetscViewerASCIIOpen()` 17884b9ad928SBarry Smith @*/ 1789d71ae5a4SJacob Faibussowitsch PetscErrorCode PCView(PC pc, PetscViewer viewer) 1790d71ae5a4SJacob Faibussowitsch { 179119fd82e9SBarry Smith PCType cstr; 17926cd81132SPierre Jolivet PetscViewerFormat format; 17936cd81132SPierre Jolivet PetscBool iascii, isstring, isbinary, isdraw, pop = PETSC_FALSE; 1794e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 1795536b137fSBarry Smith PetscBool issaws; 17960acecf5bSBarry Smith #endif 17974b9ad928SBarry Smith 17984b9ad928SBarry Smith PetscFunctionBegin; 17990700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 180048a46eb9SPierre Jolivet if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc), &viewer)); 18010700a824SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1802c9780b6fSBarry Smith PetscCheckSameComm(pc, 1, viewer, 2); 18034b9ad928SBarry Smith 18049566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 18059566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 18069566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 18079566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 1808e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 18099566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 18100acecf5bSBarry Smith #endif 1811219b1045SBarry Smith 181232077d6dSBarry Smith if (iascii) { 18139566063dSJacob Faibussowitsch PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)pc, viewer)); 181448a46eb9SPierre Jolivet if (!pc->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, " PC has not been set up so information may be incomplete\n")); 18159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 1816dbbe0bcdSBarry Smith PetscTryTypeMethod(pc, view, viewer); 18179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 1818834dbeb0SBarry Smith if (pc->mat) { 18196cd81132SPierre Jolivet PetscCall(PetscViewerGetFormat(viewer, &format)); 18206cd81132SPierre Jolivet if (format != PETSC_VIEWER_ASCII_INFO_DETAIL) { 18219566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_INFO)); 18226cd81132SPierre Jolivet pop = PETSC_TRUE; 18236cd81132SPierre Jolivet } 18244b9ad928SBarry Smith if (pc->pmat == pc->mat) { 18259566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " linear system matrix = precond matrix:\n")); 18269566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 18279566063dSJacob Faibussowitsch PetscCall(MatView(pc->mat, viewer)); 18289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 18294b9ad928SBarry Smith } else { 1830834dbeb0SBarry Smith if (pc->pmat) { 18319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " linear system matrix followed by preconditioner matrix:\n")); 18324b9ad928SBarry Smith } else { 18339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " linear system matrix:\n")); 18344b9ad928SBarry Smith } 18359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 18369566063dSJacob Faibussowitsch PetscCall(MatView(pc->mat, viewer)); 18379566063dSJacob Faibussowitsch if (pc->pmat) PetscCall(MatView(pc->pmat, viewer)); 18389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 18394b9ad928SBarry Smith } 18406cd81132SPierre Jolivet if (pop) PetscCall(PetscViewerPopFormat(viewer)); 18414b9ad928SBarry Smith } 18424b9ad928SBarry Smith } else if (isstring) { 18439566063dSJacob Faibussowitsch PetscCall(PCGetType(pc, &cstr)); 18449566063dSJacob Faibussowitsch PetscCall(PetscViewerStringSPrintf(viewer, " PCType: %-7.7s", cstr)); 1845dbbe0bcdSBarry Smith PetscTryTypeMethod(pc, view, viewer); 18469566063dSJacob Faibussowitsch if (pc->mat) PetscCall(MatView(pc->mat, viewer)); 18479566063dSJacob Faibussowitsch if (pc->pmat && pc->pmat != pc->mat) PetscCall(MatView(pc->pmat, viewer)); 18485b0b0462SBarry Smith } else if (isbinary) { 184955849f57SBarry Smith PetscInt classid = PC_FILE_CLASSID; 185055849f57SBarry Smith MPI_Comm comm; 185155849f57SBarry Smith PetscMPIInt rank; 185255849f57SBarry Smith char type[256]; 185355849f57SBarry Smith 18549566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)pc, &comm)); 18559566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1856dd400576SPatrick Sanan if (rank == 0) { 18579566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT)); 18589566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(type, ((PetscObject)pc)->type_name, 256)); 18599566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, type, 256, PETSC_CHAR)); 186055849f57SBarry Smith } 1861dbbe0bcdSBarry Smith PetscTryTypeMethod(pc, view, viewer); 1862219b1045SBarry Smith } else if (isdraw) { 1863219b1045SBarry Smith PetscDraw draw; 1864d9884438SBarry Smith char str[25]; 186589fd9fafSBarry Smith PetscReal x, y, bottom, h; 1866d9884438SBarry Smith PetscInt n; 1867219b1045SBarry Smith 18689566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 18699566063dSJacob Faibussowitsch PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y)); 18701d840656SPeter Brune if (pc->mat) { 18719566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->mat, &n, NULL)); 187263a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(str, 25, "PC: %s (%" PetscInt_FMT ")", ((PetscObject)pc)->type_name, n)); 18731d840656SPeter Brune } else { 18749566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(str, 25, "PC: %s", ((PetscObject)pc)->type_name)); 18751d840656SPeter Brune } 18769566063dSJacob Faibussowitsch PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_RED, PETSC_DRAW_BLACK, str, NULL, &h)); 187789fd9fafSBarry Smith bottom = y - h; 18789566063dSJacob Faibussowitsch PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom)); 1879dbbe0bcdSBarry Smith PetscTryTypeMethod(pc, view, viewer); 18809566063dSJacob Faibussowitsch PetscCall(PetscDrawPopCurrentPoint(draw)); 1881e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 1882536b137fSBarry Smith } else if (issaws) { 1883d45a07a7SBarry Smith PetscMPIInt rank; 1884d45a07a7SBarry Smith 18859566063dSJacob Faibussowitsch PetscCall(PetscObjectName((PetscObject)pc)); 18869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 188748a46eb9SPierre Jolivet if (!((PetscObject)pc)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)pc, viewer)); 18889566063dSJacob Faibussowitsch if (pc->mat) PetscCall(MatView(pc->mat, viewer)); 18899566063dSJacob Faibussowitsch if (pc->pmat && pc->pmat != pc->mat) PetscCall(MatView(pc->pmat, viewer)); 18900acecf5bSBarry Smith #endif 18914b9ad928SBarry Smith } 18923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18934b9ad928SBarry Smith } 18944b9ad928SBarry Smith 18954b9ad928SBarry Smith /*@C 1896562efe2eSBarry Smith PCRegister - Adds a method (`PCType`) to the preconditioner package. 18971c84c290SBarry Smith 1898cc4c1da9SBarry Smith Not collective. No Fortran Support 18991c84c290SBarry Smith 19001c84c290SBarry Smith Input Parameters: 190120f4b53cSBarry Smith + sname - name of a new user-defined solver 190220f4b53cSBarry Smith - function - routine to create method context 19031c84c290SBarry Smith 1904feefa0e1SJacob Faibussowitsch Example Usage: 19051c84c290SBarry Smith .vb 1906bdf89e91SBarry Smith PCRegister("my_solver", MySolverCreate); 19071c84c290SBarry Smith .ve 19081c84c290SBarry Smith 19091c84c290SBarry Smith Then, your solver can be chosen with the procedural interface via 19101c84c290SBarry Smith $ PCSetType(pc, "my_solver") 19111c84c290SBarry Smith or at runtime via the option 19121c84c290SBarry Smith $ -pc_type my_solver 19134b9ad928SBarry Smith 19144b9ad928SBarry Smith Level: advanced 19151c84c290SBarry Smith 191620f4b53cSBarry Smith Note: 191720f4b53cSBarry Smith `PCRegister()` may be called multiple times to add several user-defined preconditioners. 191820f4b53cSBarry Smith 1919562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCType`, `PCRegisterAll()` 19204b9ad928SBarry Smith @*/ 1921d71ae5a4SJacob Faibussowitsch PetscErrorCode PCRegister(const char sname[], PetscErrorCode (*function)(PC)) 1922d71ae5a4SJacob Faibussowitsch { 19234b9ad928SBarry Smith PetscFunctionBegin; 19249566063dSJacob Faibussowitsch PetscCall(PCInitializePackage()); 19259566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&PCList, sname, function)); 19263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19274b9ad928SBarry Smith } 19284b9ad928SBarry Smith 1929d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_PC(Mat A, Vec X, Vec Y) 1930d71ae5a4SJacob Faibussowitsch { 1931186a3e20SStefano Zampini PC pc; 1932186a3e20SStefano Zampini 1933186a3e20SStefano Zampini PetscFunctionBegin; 19349566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(A, &pc)); 19359566063dSJacob Faibussowitsch PetscCall(PCApply(pc, X, Y)); 19363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1937186a3e20SStefano Zampini } 1938186a3e20SStefano Zampini 19395d83a8b1SBarry Smith /*@ 19400bacdadaSStefano Zampini PCComputeOperator - Computes the explicit preconditioned operator. 19414b9ad928SBarry Smith 1942c3339decSBarry Smith Collective 19434b9ad928SBarry Smith 1944d8d19677SJose E. Roman Input Parameters: 1945186a3e20SStefano Zampini + pc - the preconditioner object 1946562efe2eSBarry Smith - mattype - the `MatType` to be used for the operator 19474b9ad928SBarry Smith 19484b9ad928SBarry Smith Output Parameter: 1949a5b23f4aSJose E. Roman . mat - the explicit preconditioned operator 19504b9ad928SBarry Smith 195120f4b53cSBarry Smith Level: advanced 195220f4b53cSBarry Smith 1953f1580f4eSBarry Smith Note: 1954186a3e20SStefano Zampini This computation is done by applying the operators to columns of the identity matrix. 1955186a3e20SStefano Zampini This routine is costly in general, and is recommended for use only with relatively small systems. 1956562efe2eSBarry Smith Currently, this routine uses a dense matrix format when `mattype` == `NULL` 19574b9ad928SBarry Smith 1958562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `KSPComputeOperator()`, `MatType` 19594b9ad928SBarry Smith @*/ 1960d71ae5a4SJacob Faibussowitsch PetscErrorCode PCComputeOperator(PC pc, MatType mattype, Mat *mat) 1961d71ae5a4SJacob Faibussowitsch { 1962186a3e20SStefano Zampini PetscInt N, M, m, n; 1963186a3e20SStefano Zampini Mat A, Apc; 19644b9ad928SBarry Smith 19654b9ad928SBarry Smith PetscFunctionBegin; 19660700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 19674f572ea9SToby Isaac PetscAssertPointer(mat, 3); 19689566063dSJacob Faibussowitsch PetscCall(PCGetOperators(pc, &A, NULL)); 19699566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m, &n)); 19709566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 19719566063dSJacob Faibussowitsch PetscCall(MatCreateShell(PetscObjectComm((PetscObject)pc), m, n, M, N, pc, &Apc)); 19729566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(Apc, MATOP_MULT, (void (*)(void))MatMult_PC)); 19739566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(Apc, mattype, mat)); 19749566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Apc)); 19753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19764b9ad928SBarry Smith } 19774b9ad928SBarry Smith 19786c237d78SBarry Smith /*@ 19796c237d78SBarry Smith PCSetCoordinates - sets the coordinates of all the nodes on the local process 19806c237d78SBarry Smith 1981c3339decSBarry Smith Collective 19826c237d78SBarry Smith 19836c237d78SBarry Smith Input Parameters: 19846c237d78SBarry Smith + pc - the solver context 19856c237d78SBarry Smith . dim - the dimension of the coordinates 1, 2, or 3 198614893cbeSStefano Zampini . nloc - the blocked size of the coordinates array 198714893cbeSStefano Zampini - coords - the coordinates array 19886c237d78SBarry Smith 19896c237d78SBarry Smith Level: intermediate 19906c237d78SBarry Smith 1991f1580f4eSBarry Smith Note: 199220f4b53cSBarry Smith `coords` is an array of the dim coordinates for the nodes on 199320f4b53cSBarry Smith the local processor, of size `dim`*`nloc`. 199414893cbeSStefano Zampini If there are 108 equation on a processor 19956c237d78SBarry Smith for a displacement finite element discretization of elasticity (so 199614893cbeSStefano Zampini that there are nloc = 36 = 108/3 nodes) then the array must have 108 19976c237d78SBarry Smith double precision values (ie, 3 * 36). These x y z coordinates 19986c237d78SBarry Smith should be ordered for nodes 0 to N-1 like so: [ 0.x, 0.y, 0.z, 1.x, 19996c237d78SBarry Smith ... , N-1.z ]. 20006c237d78SBarry Smith 2001562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `MatSetNearNullSpace()` 20026c237d78SBarry Smith @*/ 2003d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetCoordinates(PC pc, PetscInt dim, PetscInt nloc, PetscReal coords[]) 2004d71ae5a4SJacob Faibussowitsch { 20056c237d78SBarry Smith PetscFunctionBegin; 200632954da3SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 200732954da3SStefano Zampini PetscValidLogicalCollectiveInt(pc, dim, 2); 200822794d57SStefano Zampini PetscTryMethod(pc, "PCSetCoordinates_C", (PC, PetscInt, PetscInt, PetscReal[]), (pc, dim, nloc, coords)); 20093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20106c237d78SBarry Smith } 2011fd2dd295SFande Kong 2012fd2dd295SFande Kong /*@ 2013fd2dd295SFande Kong PCGetInterpolations - Gets interpolation matrices for all levels (except level 0) 2014fd2dd295SFande Kong 2015c3339decSBarry Smith Logically Collective 2016fd2dd295SFande Kong 2017d8d19677SJose E. Roman Input Parameter: 2018d8d19677SJose E. Roman . pc - the precondition context 2019fd2dd295SFande Kong 2020d8d19677SJose E. Roman Output Parameters: 2021d8d19677SJose E. Roman + num_levels - the number of levels 2022562efe2eSBarry Smith - interpolations - the interpolation matrices (size of `num_levels`-1) 2023fd2dd295SFande Kong 2024fd2dd295SFande Kong Level: advanced 2025fd2dd295SFande Kong 2026562efe2eSBarry Smith Developer Note: 2027f1580f4eSBarry Smith Why is this here instead of in `PCMG` etc? 2028fd2dd295SFande Kong 2029562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCMG`, `PCMGGetRestriction()`, `PCMGSetInterpolation()`, `PCMGGetInterpolation()`, `PCGetCoarseOperators()` 2030fd2dd295SFande Kong @*/ 2031d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGetInterpolations(PC pc, PetscInt *num_levels, Mat *interpolations[]) 2032d71ae5a4SJacob Faibussowitsch { 2033fd2dd295SFande Kong PetscFunctionBegin; 2034fd2dd295SFande Kong PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 20354f572ea9SToby Isaac PetscAssertPointer(num_levels, 2); 20364f572ea9SToby Isaac PetscAssertPointer(interpolations, 3); 2037cac4c232SBarry Smith PetscUseMethod(pc, "PCGetInterpolations_C", (PC, PetscInt *, Mat *[]), (pc, num_levels, interpolations)); 20383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2039fd2dd295SFande Kong } 2040fd2dd295SFande Kong 2041fd2dd295SFande Kong /*@ 2042fd2dd295SFande Kong PCGetCoarseOperators - Gets coarse operator matrices for all levels (except the finest level) 2043fd2dd295SFande Kong 2044c3339decSBarry Smith Logically Collective 2045fd2dd295SFande Kong 2046d8d19677SJose E. Roman Input Parameter: 2047d8d19677SJose E. Roman . pc - the precondition context 2048fd2dd295SFande Kong 2049d8d19677SJose E. Roman Output Parameters: 2050d8d19677SJose E. Roman + num_levels - the number of levels 2051562efe2eSBarry Smith - coarseOperators - the coarse operator matrices (size of `num_levels`-1) 2052fd2dd295SFande Kong 2053fd2dd295SFande Kong Level: advanced 2054fd2dd295SFande Kong 2055562efe2eSBarry Smith Developer Note: 2056f1580f4eSBarry Smith Why is this here instead of in `PCMG` etc? 2057fd2dd295SFande Kong 2058562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCMG`, `PCMGGetRestriction()`, `PCMGSetInterpolation()`, `PCMGGetRScale()`, `PCMGGetInterpolation()`, `PCGetInterpolations()` 2059fd2dd295SFande Kong @*/ 2060d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGetCoarseOperators(PC pc, PetscInt *num_levels, Mat *coarseOperators[]) 2061d71ae5a4SJacob Faibussowitsch { 2062fd2dd295SFande Kong PetscFunctionBegin; 2063fd2dd295SFande Kong PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 20644f572ea9SToby Isaac PetscAssertPointer(num_levels, 2); 20654f572ea9SToby Isaac PetscAssertPointer(coarseOperators, 3); 2066cac4c232SBarry Smith PetscUseMethod(pc, "PCGetCoarseOperators_C", (PC, PetscInt *, Mat *[]), (pc, num_levels, coarseOperators)); 20673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2068fd2dd295SFande Kong } 2069