1dba47a55SKris Buschelman 24b9ad928SBarry Smith /* 34b9ad928SBarry Smith Defines a Eisenstat trick SSOR preconditioner. This uses about 44b9ad928SBarry Smith %50 of the usual amount of floating point ops used for SSOR + Krylov 54b9ad928SBarry Smith method. But it requires actually solving the preconditioned problem 64b9ad928SBarry Smith with both left and right preconditioning. 74b9ad928SBarry Smith */ 8af0996ceSBarry Smith #include <petsc/private/pcimpl.h> /*I "petscpc.h" I*/ 94b9ad928SBarry Smith 104b9ad928SBarry Smith typedef struct { 114b9ad928SBarry Smith Mat shell, A; 1278c391d7SBarry Smith Vec b[2], diag; /* temporary storage for true right hand side */ 134b9ad928SBarry Smith PetscReal omega; 14ace3abfcSBarry Smith PetscBool usediag; /* indicates preconditioner should include diagonal scaling*/ 154b9ad928SBarry Smith } PC_Eisenstat; 164b9ad928SBarry Smith 179371c9d4SSatish Balay static PetscErrorCode PCMult_Eisenstat(Mat mat, Vec b, Vec x) { 184b9ad928SBarry Smith PC pc; 194b9ad928SBarry Smith PC_Eisenstat *eis; 204b9ad928SBarry Smith 214b9ad928SBarry Smith PetscFunctionBegin; 229566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(mat, &pc)); 234b9ad928SBarry Smith eis = (PC_Eisenstat *)pc->data; 249566063dSJacob Faibussowitsch PetscCall(MatSOR(eis->A, b, eis->omega, SOR_EISENSTAT, 0.0, 1, 1, x)); 254b9ad928SBarry Smith PetscFunctionReturn(0); 264b9ad928SBarry Smith } 274b9ad928SBarry Smith 28*a9e2c90aSJose E. Roman static PetscErrorCode PCNorm_Eisenstat(Mat mat, NormType type, PetscReal *nrm) { 29*a9e2c90aSJose E. Roman PC pc; 30*a9e2c90aSJose E. Roman PC_Eisenstat *eis; 31*a9e2c90aSJose E. Roman 32*a9e2c90aSJose E. Roman PetscFunctionBegin; 33*a9e2c90aSJose E. Roman PetscCall(MatShellGetContext(mat, &pc)); 34*a9e2c90aSJose E. Roman eis = (PC_Eisenstat *)pc->data; 35*a9e2c90aSJose E. Roman PetscCall(MatNorm(eis->A, type, nrm)); 36*a9e2c90aSJose E. Roman PetscFunctionReturn(0); 37*a9e2c90aSJose E. Roman } 38*a9e2c90aSJose E. Roman 399371c9d4SSatish Balay static PetscErrorCode PCApply_Eisenstat(PC pc, Vec x, Vec y) { 404b9ad928SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 41ace3abfcSBarry Smith PetscBool hasop; 424b9ad928SBarry Smith 434b9ad928SBarry Smith PetscFunctionBegin; 4489c6957cSBarry Smith if (eis->usediag) { 459566063dSJacob Faibussowitsch PetscCall(MatHasOperation(pc->pmat, MATOP_MULT_DIAGONAL_BLOCK, &hasop)); 4689c6957cSBarry Smith if (hasop) { 479566063dSJacob Faibussowitsch PetscCall(MatMultDiagonalBlock(pc->pmat, x, y)); 4889c6957cSBarry Smith } else { 499566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(y, x, eis->diag)); 5089c6957cSBarry Smith } 519566063dSJacob Faibussowitsch } else PetscCall(VecCopy(x, y)); 524b9ad928SBarry Smith PetscFunctionReturn(0); 534b9ad928SBarry Smith } 544b9ad928SBarry Smith 559371c9d4SSatish Balay static PetscErrorCode PCPreSolve_Eisenstat(PC pc, KSP ksp, Vec b, Vec x) { 564b9ad928SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 57ace3abfcSBarry Smith PetscBool nonzero; 584b9ad928SBarry Smith 594b9ad928SBarry Smith PetscFunctionBegin; 6078c391d7SBarry Smith if (pc->presolvedone < 2) { 6108401ef6SPierre Jolivet PetscCheck(pc->mat == pc->pmat, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot have different mat and pmat"); 624b9ad928SBarry Smith /* swap shell matrix and true matrix */ 634b9ad928SBarry Smith eis->A = pc->mat; 644b9ad928SBarry Smith pc->mat = eis->shell; 654b9ad928SBarry Smith } 664b9ad928SBarry Smith 6778c391d7SBarry Smith if (!eis->b[pc->presolvedone - 1]) { 689566063dSJacob Faibussowitsch PetscCall(VecDuplicate(b, &eis->b[pc->presolvedone - 1])); 699566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)pc, (PetscObject)eis->b[pc->presolvedone - 1])); 7078c391d7SBarry Smith } 714b9ad928SBarry Smith 724b9ad928SBarry Smith /* if nonzero initial guess, modify x */ 739566063dSJacob Faibussowitsch PetscCall(KSPGetInitialGuessNonzero(ksp, &nonzero)); 744b9ad928SBarry Smith if (nonzero) { 759566063dSJacob Faibussowitsch PetscCall(VecCopy(x, eis->b[pc->presolvedone - 1])); 769566063dSJacob Faibussowitsch PetscCall(MatSOR(eis->A, eis->b[pc->presolvedone - 1], eis->omega, SOR_APPLY_UPPER, 0.0, 1, 1, x)); 774b9ad928SBarry Smith } 784b9ad928SBarry Smith 79121471adSBarry Smith /* save true b, other option is to swap pointers */ 809566063dSJacob Faibussowitsch PetscCall(VecCopy(b, eis->b[pc->presolvedone - 1])); 81121471adSBarry Smith 825c99c7daSBarry Smith /* modify b by (L + D/omega)^{-1} */ 839566063dSJacob Faibussowitsch PetscCall(MatSOR(eis->A, eis->b[pc->presolvedone - 1], eis->omega, (MatSORType)(SOR_ZERO_INITIAL_GUESS | SOR_LOCAL_FORWARD_SWEEP), 0.0, 1, 1, b)); 844b9ad928SBarry Smith PetscFunctionReturn(0); 854b9ad928SBarry Smith } 864b9ad928SBarry Smith 879371c9d4SSatish Balay static PetscErrorCode PCPostSolve_Eisenstat(PC pc, KSP ksp, Vec b, Vec x) { 884b9ad928SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 894b9ad928SBarry Smith 904b9ad928SBarry Smith PetscFunctionBegin; 914b9ad928SBarry Smith /* get back true b */ 929566063dSJacob Faibussowitsch PetscCall(VecCopy(eis->b[pc->presolvedone], b)); 93121471adSBarry Smith 94121471adSBarry Smith /* modify x by (U + D/omega)^{-1} */ 959566063dSJacob Faibussowitsch PetscCall(VecCopy(x, eis->b[pc->presolvedone])); 969566063dSJacob Faibussowitsch PetscCall(MatSOR(eis->A, eis->b[pc->presolvedone], eis->omega, (MatSORType)(SOR_ZERO_INITIAL_GUESS | SOR_LOCAL_BACKWARD_SWEEP), 0.0, 1, 1, x)); 972fa5cd67SKarl Rupp if (!pc->presolvedone) pc->mat = eis->A; 984b9ad928SBarry Smith PetscFunctionReturn(0); 994b9ad928SBarry Smith } 1004b9ad928SBarry Smith 1019371c9d4SSatish Balay static PetscErrorCode PCReset_Eisenstat(PC pc) { 1024b9ad928SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 1034b9ad928SBarry Smith 1044b9ad928SBarry Smith PetscFunctionBegin; 1059566063dSJacob Faibussowitsch PetscCall(VecDestroy(&eis->b[0])); 1069566063dSJacob Faibussowitsch PetscCall(VecDestroy(&eis->b[1])); 1079566063dSJacob Faibussowitsch PetscCall(MatDestroy(&eis->shell)); 1089566063dSJacob Faibussowitsch PetscCall(VecDestroy(&eis->diag)); 10969d2c0f9SBarry Smith PetscFunctionReturn(0); 11069d2c0f9SBarry Smith } 11169d2c0f9SBarry Smith 1129371c9d4SSatish Balay static PetscErrorCode PCDestroy_Eisenstat(PC pc) { 11369d2c0f9SBarry Smith PetscFunctionBegin; 1149566063dSJacob Faibussowitsch PetscCall(PCReset_Eisenstat(pc)); 1152e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCEisenstatSetOmega_C", NULL)); 1162e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCEisenstatSetNoDiagonalScaling_C", NULL)); 1172e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCEisenstatGetOmega_C", NULL)); 1182e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCEisenstatGetNoDiagonalScaling_C", NULL)); 1192e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", NULL)); 1209566063dSJacob Faibussowitsch PetscCall(PetscFree(pc->data)); 1214b9ad928SBarry Smith PetscFunctionReturn(0); 1224b9ad928SBarry Smith } 1234b9ad928SBarry Smith 1249371c9d4SSatish Balay static PetscErrorCode PCSetFromOptions_Eisenstat(PC pc, PetscOptionItems *PetscOptionsObject) { 1254b9ad928SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 1268afaa268SBarry Smith PetscBool set, flg; 1274b9ad928SBarry Smith 1284b9ad928SBarry Smith PetscFunctionBegin; 129d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "Eisenstat SSOR options"); 1309566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-pc_eisenstat_omega", "Relaxation factor 0 < omega < 2", "PCEisenstatSetOmega", eis->omega, &eis->omega, NULL)); 1319566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_eisenstat_no_diagonal_scaling", "Do not use standard diagonal scaling", "PCEisenstatSetNoDiagonalScaling", eis->usediag ? PETSC_FALSE : PETSC_TRUE, &flg, &set)); 1321baa6e33SBarry Smith if (set) PetscCall(PCEisenstatSetNoDiagonalScaling(pc, flg)); 133d0609cedSBarry Smith PetscOptionsHeadEnd(); 1344b9ad928SBarry Smith PetscFunctionReturn(0); 1354b9ad928SBarry Smith } 1364b9ad928SBarry Smith 1379371c9d4SSatish Balay static PetscErrorCode PCView_Eisenstat(PC pc, PetscViewer viewer) { 1384b9ad928SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 139ace3abfcSBarry Smith PetscBool iascii; 1404b9ad928SBarry Smith 1414b9ad928SBarry Smith PetscFunctionBegin; 1429566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 14332077d6dSBarry Smith if (iascii) { 1449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " omega = %g\n", (double)eis->omega)); 1454b9ad928SBarry Smith if (eis->usediag) { 1469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Using diagonal scaling (default)\n")); 1474b9ad928SBarry Smith } else { 1489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Not using diagonal scaling\n")); 1494b9ad928SBarry Smith } 1504b9ad928SBarry Smith } 1514b9ad928SBarry Smith PetscFunctionReturn(0); 1524b9ad928SBarry Smith } 1534b9ad928SBarry Smith 1549371c9d4SSatish Balay static PetscErrorCode PCSetUp_Eisenstat(PC pc) { 15513f74950SBarry Smith PetscInt M, N, m, n; 1564b9ad928SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 1574b9ad928SBarry Smith 1584b9ad928SBarry Smith PetscFunctionBegin; 1594b9ad928SBarry Smith if (!pc->setupcalled) { 1609566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->mat, &M, &N)); 1619566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pc->mat, &m, &n)); 1629566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &eis->shell)); 1639566063dSJacob Faibussowitsch PetscCall(MatSetSizes(eis->shell, m, n, M, N)); 1649566063dSJacob Faibussowitsch PetscCall(MatSetType(eis->shell, MATSHELL)); 1659566063dSJacob Faibussowitsch PetscCall(MatSetUp(eis->shell)); 1669566063dSJacob Faibussowitsch PetscCall(MatShellSetContext(eis->shell, pc)); 1679566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)pc, (PetscObject)eis->shell)); 1689566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(eis->shell, MATOP_MULT, (void (*)(void))PCMult_Eisenstat)); 169*a9e2c90aSJose E. Roman PetscCall(MatShellSetOperation(eis->shell, MATOP_NORM, (void (*)(void))PCNorm_Eisenstat)); 1704b9ad928SBarry Smith } 1714b9ad928SBarry Smith if (!eis->usediag) PetscFunctionReturn(0); 1724b9ad928SBarry Smith if (!pc->setupcalled) { 1739566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(pc->pmat, &eis->diag, NULL)); 1749566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)pc, (PetscObject)eis->diag)); 1754b9ad928SBarry Smith } 1769566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(pc->pmat, eis->diag)); 1774b9ad928SBarry Smith PetscFunctionReturn(0); 1784b9ad928SBarry Smith } 1794b9ad928SBarry Smith 1804b9ad928SBarry Smith /* --------------------------------------------------------------------*/ 1814b9ad928SBarry Smith 1829371c9d4SSatish Balay static PetscErrorCode PCEisenstatSetOmega_Eisenstat(PC pc, PetscReal omega) { 183c60c7ad4SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 1844b9ad928SBarry Smith 1854b9ad928SBarry Smith PetscFunctionBegin; 1862472a847SBarry Smith PetscCheck(omega > 0.0 && omega < 2.0, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Relaxation out of range"); 1874b9ad928SBarry Smith eis->omega = omega; 1884b9ad928SBarry Smith PetscFunctionReturn(0); 1894b9ad928SBarry Smith } 1904b9ad928SBarry Smith 1919371c9d4SSatish Balay static PetscErrorCode PCEisenstatSetNoDiagonalScaling_Eisenstat(PC pc, PetscBool flg) { 192c60c7ad4SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 1934b9ad928SBarry Smith 1944b9ad928SBarry Smith PetscFunctionBegin; 195c60c7ad4SBarry Smith eis->usediag = flg; 196c60c7ad4SBarry Smith PetscFunctionReturn(0); 197c60c7ad4SBarry Smith } 198c60c7ad4SBarry Smith 1999371c9d4SSatish Balay static PetscErrorCode PCEisenstatGetOmega_Eisenstat(PC pc, PetscReal *omega) { 200c60c7ad4SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 201c60c7ad4SBarry Smith 202c60c7ad4SBarry Smith PetscFunctionBegin; 203c60c7ad4SBarry Smith *omega = eis->omega; 204c60c7ad4SBarry Smith PetscFunctionReturn(0); 205c60c7ad4SBarry Smith } 206c60c7ad4SBarry Smith 2079371c9d4SSatish Balay static PetscErrorCode PCEisenstatGetNoDiagonalScaling_Eisenstat(PC pc, PetscBool *flg) { 208c60c7ad4SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 209c60c7ad4SBarry Smith 210c60c7ad4SBarry Smith PetscFunctionBegin; 211c60c7ad4SBarry Smith *flg = eis->usediag; 2124b9ad928SBarry Smith PetscFunctionReturn(0); 2134b9ad928SBarry Smith } 2144b9ad928SBarry Smith 2154b9ad928SBarry Smith /*@ 2164b9ad928SBarry Smith PCEisenstatSetOmega - Sets the SSOR relaxation coefficient, omega, 2174b9ad928SBarry Smith to use with Eisenstat's trick (where omega = 1.0 by default). 2184b9ad928SBarry Smith 219ad4df100SBarry Smith Logically Collective on PC 2204b9ad928SBarry Smith 2214b9ad928SBarry Smith Input Parameters: 2224b9ad928SBarry Smith + pc - the preconditioner context 2234b9ad928SBarry Smith - omega - relaxation coefficient (0 < omega < 2) 2244b9ad928SBarry Smith 2254b9ad928SBarry Smith Options Database Key: 2264b9ad928SBarry Smith . -pc_eisenstat_omega <omega> - Sets omega 2274b9ad928SBarry Smith 2284b9ad928SBarry Smith Notes: 2294b9ad928SBarry Smith The Eisenstat trick implementation of SSOR requires about 50% of the 2304b9ad928SBarry Smith usual amount of floating point operations used for SSOR + Krylov method; 2314b9ad928SBarry Smith however, the preconditioned problem must be solved with both left 2324b9ad928SBarry Smith and right preconditioning. 2334b9ad928SBarry Smith 2344b9ad928SBarry Smith To use SSOR without the Eisenstat trick, employ the PCSOR preconditioner, 2354b9ad928SBarry Smith which can be chosen with the database options 2364b9ad928SBarry Smith $ -pc_type sor -pc_sor_symmetric 2374b9ad928SBarry Smith 2384b9ad928SBarry Smith Level: intermediate 2394b9ad928SBarry Smith 240db781477SPatrick Sanan .seealso: `PCSORSetOmega()` 2414b9ad928SBarry Smith @*/ 2429371c9d4SSatish Balay PetscErrorCode PCEisenstatSetOmega(PC pc, PetscReal omega) { 2434b9ad928SBarry Smith PetscFunctionBegin; 2440700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 245c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(pc, omega, 2); 246cac4c232SBarry Smith PetscTryMethod(pc, "PCEisenstatSetOmega_C", (PC, PetscReal), (pc, omega)); 2474b9ad928SBarry Smith PetscFunctionReturn(0); 2484b9ad928SBarry Smith } 2494b9ad928SBarry Smith 2504b9ad928SBarry Smith /*@ 251c60c7ad4SBarry Smith PCEisenstatSetNoDiagonalScaling - Causes the Eisenstat preconditioner 2524b9ad928SBarry Smith not to do additional diagonal preconditioning. For matrices with a constant 2534b9ad928SBarry Smith along the diagonal, this may save a small amount of work. 2544b9ad928SBarry Smith 255ad4df100SBarry Smith Logically Collective on PC 2564b9ad928SBarry Smith 257c60c7ad4SBarry Smith Input Parameters: 258c60c7ad4SBarry Smith + pc - the preconditioner context 259c60c7ad4SBarry Smith - flg - PETSC_TRUE turns off diagonal scaling inside the algorithm 2604b9ad928SBarry Smith 2614b9ad928SBarry Smith Options Database Key: 262c60c7ad4SBarry Smith . -pc_eisenstat_no_diagonal_scaling - Activates PCEisenstatSetNoDiagonalScaling() 2634b9ad928SBarry Smith 2644b9ad928SBarry Smith Level: intermediate 2654b9ad928SBarry Smith 2664b9ad928SBarry Smith Note: 267f9ff08acSPierre Jolivet If you use the KSPSetDiagonalScaling() or -ksp_diagonal_scale option then you will 2686aad120cSJose E. Roman likely want to use this routine since it will save you some unneeded flops. 2694b9ad928SBarry Smith 270db781477SPatrick Sanan .seealso: `PCEisenstatSetOmega()` 2714b9ad928SBarry Smith @*/ 2729371c9d4SSatish Balay PetscErrorCode PCEisenstatSetNoDiagonalScaling(PC pc, PetscBool flg) { 2734b9ad928SBarry Smith PetscFunctionBegin; 2740700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 275cac4c232SBarry Smith PetscTryMethod(pc, "PCEisenstatSetNoDiagonalScaling_C", (PC, PetscBool), (pc, flg)); 276c60c7ad4SBarry Smith PetscFunctionReturn(0); 277c60c7ad4SBarry Smith } 278c60c7ad4SBarry Smith 279c60c7ad4SBarry Smith /*@ 280c60c7ad4SBarry Smith PCEisenstatGetOmega - Gets the SSOR relaxation coefficient, omega, 281c60c7ad4SBarry Smith to use with Eisenstat's trick (where omega = 1.0 by default). 282c60c7ad4SBarry Smith 283c60c7ad4SBarry Smith Logically Collective on PC 284c60c7ad4SBarry Smith 285c60c7ad4SBarry Smith Input Parameter: 286c60c7ad4SBarry Smith . pc - the preconditioner context 287c60c7ad4SBarry Smith 288c60c7ad4SBarry Smith Output Parameter: 289c60c7ad4SBarry Smith . omega - relaxation coefficient (0 < omega < 2) 290c60c7ad4SBarry Smith 291c60c7ad4SBarry Smith Options Database Key: 292c60c7ad4SBarry Smith . -pc_eisenstat_omega <omega> - Sets omega 293c60c7ad4SBarry Smith 294c60c7ad4SBarry Smith Notes: 295c60c7ad4SBarry Smith The Eisenstat trick implementation of SSOR requires about 50% of the 296c60c7ad4SBarry Smith usual amount of floating point operations used for SSOR + Krylov method; 297c60c7ad4SBarry Smith however, the preconditioned problem must be solved with both left 298c60c7ad4SBarry Smith and right preconditioning. 299c60c7ad4SBarry Smith 300c60c7ad4SBarry Smith To use SSOR without the Eisenstat trick, employ the PCSOR preconditioner, 301c60c7ad4SBarry Smith which can be chosen with the database options 302c60c7ad4SBarry Smith $ -pc_type sor -pc_sor_symmetric 303c60c7ad4SBarry Smith 304c60c7ad4SBarry Smith Level: intermediate 305c60c7ad4SBarry Smith 306db781477SPatrick Sanan .seealso: `PCSORGetOmega()`, `PCEisenstatSetOmega()` 307c60c7ad4SBarry Smith @*/ 3089371c9d4SSatish Balay PetscErrorCode PCEisenstatGetOmega(PC pc, PetscReal *omega) { 309c60c7ad4SBarry Smith PetscFunctionBegin; 310c60c7ad4SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 311cac4c232SBarry Smith PetscUseMethod(pc, "PCEisenstatGetOmega_C", (PC, PetscReal *), (pc, omega)); 312c60c7ad4SBarry Smith PetscFunctionReturn(0); 313c60c7ad4SBarry Smith } 314c60c7ad4SBarry Smith 315c60c7ad4SBarry Smith /*@ 316163d334eSBarry Smith PCEisenstatGetNoDiagonalScaling - Tells if the Eisenstat preconditioner 317c60c7ad4SBarry Smith not to do additional diagonal preconditioning. For matrices with a constant 318c60c7ad4SBarry Smith along the diagonal, this may save a small amount of work. 319c60c7ad4SBarry Smith 320c60c7ad4SBarry Smith Logically Collective on PC 321c60c7ad4SBarry Smith 322c60c7ad4SBarry Smith Input Parameter: 323c60c7ad4SBarry Smith . pc - the preconditioner context 324c60c7ad4SBarry Smith 325c60c7ad4SBarry Smith Output Parameter: 326c60c7ad4SBarry Smith . flg - PETSC_TRUE means there is no diagonal scaling applied 327c60c7ad4SBarry Smith 328c60c7ad4SBarry Smith Options Database Key: 329c60c7ad4SBarry Smith . -pc_eisenstat_no_diagonal_scaling - Activates PCEisenstatSetNoDiagonalScaling() 330c60c7ad4SBarry Smith 331c60c7ad4SBarry Smith Level: intermediate 332c60c7ad4SBarry Smith 333c60c7ad4SBarry Smith Note: 334f9ff08acSPierre Jolivet If you use the KSPSetDiagonalScaling() or -ksp_diagonal_scale option then you will 3356aad120cSJose E. Roman likely want to use this routine since it will save you some unneeded flops. 336c60c7ad4SBarry Smith 337db781477SPatrick Sanan .seealso: `PCEisenstatGetOmega()` 338c60c7ad4SBarry Smith @*/ 3399371c9d4SSatish Balay PetscErrorCode PCEisenstatGetNoDiagonalScaling(PC pc, PetscBool *flg) { 340c60c7ad4SBarry Smith PetscFunctionBegin; 341c60c7ad4SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 342cac4c232SBarry Smith PetscUseMethod(pc, "PCEisenstatGetNoDiagonalScaling_C", (PC, PetscBool *), (pc, flg)); 3434b9ad928SBarry Smith PetscFunctionReturn(0); 3444b9ad928SBarry Smith } 3454b9ad928SBarry Smith 3469371c9d4SSatish Balay static PetscErrorCode PCPreSolveChangeRHS_Eisenstat(PC pc, PetscBool *change) { 3478066bbecSBarry Smith PetscFunctionBegin; 3488066bbecSBarry Smith *change = PETSC_TRUE; 3498066bbecSBarry Smith PetscFunctionReturn(0); 3508066bbecSBarry Smith } 3518066bbecSBarry Smith 3524b9ad928SBarry Smith /* --------------------------------------------------------------------*/ 3534b9ad928SBarry Smith 3544b9ad928SBarry Smith /*MC 3554b9ad928SBarry Smith PCEISENSTAT - An implementation of SSOR (symmetric successive over relaxation, symmetric Gauss-Seidel) 3564b9ad928SBarry Smith preconditioning that incorporates Eisenstat's trick to reduce the amount of computation needed. 3574b9ad928SBarry Smith 3584b9ad928SBarry Smith Options Database Keys: 3594b9ad928SBarry Smith + -pc_eisenstat_omega <omega> - Sets omega 360c60c7ad4SBarry Smith - -pc_eisenstat_no_diagonal_scaling - Activates PCEisenstatSetNoDiagonalScaling() 3614b9ad928SBarry Smith 3624b9ad928SBarry Smith Level: beginner 3634b9ad928SBarry Smith 36495452b02SPatrick Sanan Notes: 36595452b02SPatrick Sanan Only implemented for the SeqAIJ matrix format. 3664b9ad928SBarry Smith Not a true parallel SOR, in parallel this implementation corresponds to block 3674b9ad928SBarry Smith Jacobi with SOR on each block. 3684b9ad928SBarry Smith 369db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, 370db781477SPatrick Sanan `PCEisenstatSetNoDiagonalScaling()`, `PCEisenstatSetOmega()`, `PCSOR` 3714b9ad928SBarry Smith M*/ 3724b9ad928SBarry Smith 3739371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_Eisenstat(PC pc) { 3744b9ad928SBarry Smith PC_Eisenstat *eis; 3754b9ad928SBarry Smith 3764b9ad928SBarry Smith PetscFunctionBegin; 3779566063dSJacob Faibussowitsch PetscCall(PetscNewLog(pc, &eis)); 3784b9ad928SBarry Smith 3794b9ad928SBarry Smith pc->ops->apply = PCApply_Eisenstat; 380dc231df0SBarry Smith pc->ops->presolve = PCPreSolve_Eisenstat; 381dc231df0SBarry Smith pc->ops->postsolve = PCPostSolve_Eisenstat; 3820a545947SLisandro Dalcin pc->ops->applyrichardson = NULL; 3834b9ad928SBarry Smith pc->ops->setfromoptions = PCSetFromOptions_Eisenstat; 3844b9ad928SBarry Smith pc->ops->destroy = PCDestroy_Eisenstat; 38569d2c0f9SBarry Smith pc->ops->reset = PCReset_Eisenstat; 3864b9ad928SBarry Smith pc->ops->view = PCView_Eisenstat; 3874b9ad928SBarry Smith pc->ops->setup = PCSetUp_Eisenstat; 3884b9ad928SBarry Smith 3893ec1f749SStefano Zampini pc->data = eis; 3904b9ad928SBarry Smith eis->omega = 1.0; 3910a545947SLisandro Dalcin eis->b[0] = NULL; 3920a545947SLisandro Dalcin eis->b[1] = NULL; 3930a545947SLisandro Dalcin eis->diag = NULL; 3944b9ad928SBarry Smith eis->usediag = PETSC_TRUE; 3954b9ad928SBarry Smith 3969566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCEisenstatSetOmega_C", PCEisenstatSetOmega_Eisenstat)); 3979566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCEisenstatSetNoDiagonalScaling_C", PCEisenstatSetNoDiagonalScaling_Eisenstat)); 3989566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCEisenstatGetOmega_C", PCEisenstatGetOmega_Eisenstat)); 3999566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCEisenstatGetNoDiagonalScaling_C", PCEisenstatGetNoDiagonalScaling_Eisenstat)); 4009566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", PCPreSolveChangeRHS_Eisenstat)); 4014b9ad928SBarry Smith PetscFunctionReturn(0); 4024b9ad928SBarry Smith } 403