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)); 25*54e23b33SJose E. Roman PetscCall(MatFactorGetError(eis->A, (MatFactorError *)&pc->failedreason)); 264b9ad928SBarry Smith PetscFunctionReturn(0); 274b9ad928SBarry Smith } 284b9ad928SBarry Smith 29a9e2c90aSJose E. Roman static PetscErrorCode PCNorm_Eisenstat(Mat mat, NormType type, PetscReal *nrm) { 30a9e2c90aSJose E. Roman PC pc; 31a9e2c90aSJose E. Roman PC_Eisenstat *eis; 32a9e2c90aSJose E. Roman 33a9e2c90aSJose E. Roman PetscFunctionBegin; 34a9e2c90aSJose E. Roman PetscCall(MatShellGetContext(mat, &pc)); 35a9e2c90aSJose E. Roman eis = (PC_Eisenstat *)pc->data; 36a9e2c90aSJose E. Roman PetscCall(MatNorm(eis->A, type, nrm)); 37a9e2c90aSJose E. Roman PetscFunctionReturn(0); 38a9e2c90aSJose E. Roman } 39a9e2c90aSJose E. Roman 409371c9d4SSatish Balay static PetscErrorCode PCApply_Eisenstat(PC pc, Vec x, Vec y) { 414b9ad928SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 42ace3abfcSBarry Smith PetscBool hasop; 434b9ad928SBarry Smith 444b9ad928SBarry Smith PetscFunctionBegin; 4589c6957cSBarry Smith if (eis->usediag) { 469566063dSJacob Faibussowitsch PetscCall(MatHasOperation(pc->pmat, MATOP_MULT_DIAGONAL_BLOCK, &hasop)); 4789c6957cSBarry Smith if (hasop) { 489566063dSJacob Faibussowitsch PetscCall(MatMultDiagonalBlock(pc->pmat, x, y)); 4989c6957cSBarry Smith } else { 509566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(y, x, eis->diag)); 5189c6957cSBarry Smith } 529566063dSJacob Faibussowitsch } else PetscCall(VecCopy(x, y)); 534b9ad928SBarry Smith PetscFunctionReturn(0); 544b9ad928SBarry Smith } 554b9ad928SBarry Smith 569371c9d4SSatish Balay static PetscErrorCode PCPreSolve_Eisenstat(PC pc, KSP ksp, Vec b, Vec x) { 574b9ad928SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 58ace3abfcSBarry Smith PetscBool nonzero; 594b9ad928SBarry Smith 604b9ad928SBarry Smith PetscFunctionBegin; 6178c391d7SBarry Smith if (pc->presolvedone < 2) { 6208401ef6SPierre Jolivet PetscCheck(pc->mat == pc->pmat, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot have different mat and pmat"); 634b9ad928SBarry Smith /* swap shell matrix and true matrix */ 644b9ad928SBarry Smith eis->A = pc->mat; 654b9ad928SBarry Smith pc->mat = eis->shell; 664b9ad928SBarry Smith } 674b9ad928SBarry Smith 6878c391d7SBarry Smith if (!eis->b[pc->presolvedone - 1]) { 699566063dSJacob Faibussowitsch PetscCall(VecDuplicate(b, &eis->b[pc->presolvedone - 1])); 709566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)pc, (PetscObject)eis->b[pc->presolvedone - 1])); 7178c391d7SBarry Smith } 724b9ad928SBarry Smith 734b9ad928SBarry Smith /* if nonzero initial guess, modify x */ 749566063dSJacob Faibussowitsch PetscCall(KSPGetInitialGuessNonzero(ksp, &nonzero)); 754b9ad928SBarry Smith if (nonzero) { 769566063dSJacob Faibussowitsch PetscCall(VecCopy(x, eis->b[pc->presolvedone - 1])); 779566063dSJacob Faibussowitsch PetscCall(MatSOR(eis->A, eis->b[pc->presolvedone - 1], eis->omega, SOR_APPLY_UPPER, 0.0, 1, 1, x)); 78*54e23b33SJose E. Roman PetscCall(MatFactorGetError(eis->A, (MatFactorError *)&pc->failedreason)); 794b9ad928SBarry Smith } 804b9ad928SBarry Smith 81121471adSBarry Smith /* save true b, other option is to swap pointers */ 829566063dSJacob Faibussowitsch PetscCall(VecCopy(b, eis->b[pc->presolvedone - 1])); 83121471adSBarry Smith 845c99c7daSBarry Smith /* modify b by (L + D/omega)^{-1} */ 859566063dSJacob 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)); 86*54e23b33SJose E. Roman PetscCall(MatFactorGetError(eis->A, (MatFactorError *)&pc->failedreason)); 874b9ad928SBarry Smith PetscFunctionReturn(0); 884b9ad928SBarry Smith } 894b9ad928SBarry Smith 909371c9d4SSatish Balay static PetscErrorCode PCPostSolve_Eisenstat(PC pc, KSP ksp, Vec b, Vec x) { 914b9ad928SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 924b9ad928SBarry Smith 934b9ad928SBarry Smith PetscFunctionBegin; 944b9ad928SBarry Smith /* get back true b */ 959566063dSJacob Faibussowitsch PetscCall(VecCopy(eis->b[pc->presolvedone], b)); 96121471adSBarry Smith 97121471adSBarry Smith /* modify x by (U + D/omega)^{-1} */ 989566063dSJacob Faibussowitsch PetscCall(VecCopy(x, eis->b[pc->presolvedone])); 999566063dSJacob 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)); 100*54e23b33SJose E. Roman PetscCall(MatFactorGetError(eis->A, (MatFactorError *)&pc->failedreason)); 1012fa5cd67SKarl Rupp if (!pc->presolvedone) pc->mat = eis->A; 1024b9ad928SBarry Smith PetscFunctionReturn(0); 1034b9ad928SBarry Smith } 1044b9ad928SBarry Smith 1059371c9d4SSatish Balay static PetscErrorCode PCReset_Eisenstat(PC pc) { 1064b9ad928SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 1074b9ad928SBarry Smith 1084b9ad928SBarry Smith PetscFunctionBegin; 1099566063dSJacob Faibussowitsch PetscCall(VecDestroy(&eis->b[0])); 1109566063dSJacob Faibussowitsch PetscCall(VecDestroy(&eis->b[1])); 1119566063dSJacob Faibussowitsch PetscCall(MatDestroy(&eis->shell)); 1129566063dSJacob Faibussowitsch PetscCall(VecDestroy(&eis->diag)); 11369d2c0f9SBarry Smith PetscFunctionReturn(0); 11469d2c0f9SBarry Smith } 11569d2c0f9SBarry Smith 1169371c9d4SSatish Balay static PetscErrorCode PCDestroy_Eisenstat(PC pc) { 11769d2c0f9SBarry Smith PetscFunctionBegin; 1189566063dSJacob Faibussowitsch PetscCall(PCReset_Eisenstat(pc)); 1192e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCEisenstatSetOmega_C", NULL)); 1202e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCEisenstatSetNoDiagonalScaling_C", NULL)); 1212e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCEisenstatGetOmega_C", NULL)); 1222e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCEisenstatGetNoDiagonalScaling_C", NULL)); 1232e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", NULL)); 1249566063dSJacob Faibussowitsch PetscCall(PetscFree(pc->data)); 1254b9ad928SBarry Smith PetscFunctionReturn(0); 1264b9ad928SBarry Smith } 1274b9ad928SBarry Smith 1289371c9d4SSatish Balay static PetscErrorCode PCSetFromOptions_Eisenstat(PC pc, PetscOptionItems *PetscOptionsObject) { 1294b9ad928SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 1308afaa268SBarry Smith PetscBool set, flg; 1314b9ad928SBarry Smith 1324b9ad928SBarry Smith PetscFunctionBegin; 133d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "Eisenstat SSOR options"); 1349566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-pc_eisenstat_omega", "Relaxation factor 0 < omega < 2", "PCEisenstatSetOmega", eis->omega, &eis->omega, NULL)); 1359566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_eisenstat_no_diagonal_scaling", "Do not use standard diagonal scaling", "PCEisenstatSetNoDiagonalScaling", eis->usediag ? PETSC_FALSE : PETSC_TRUE, &flg, &set)); 1361baa6e33SBarry Smith if (set) PetscCall(PCEisenstatSetNoDiagonalScaling(pc, flg)); 137d0609cedSBarry Smith PetscOptionsHeadEnd(); 1384b9ad928SBarry Smith PetscFunctionReturn(0); 1394b9ad928SBarry Smith } 1404b9ad928SBarry Smith 1419371c9d4SSatish Balay static PetscErrorCode PCView_Eisenstat(PC pc, PetscViewer viewer) { 1424b9ad928SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 143ace3abfcSBarry Smith PetscBool iascii; 1444b9ad928SBarry Smith 1454b9ad928SBarry Smith PetscFunctionBegin; 1469566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 14732077d6dSBarry Smith if (iascii) { 1489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " omega = %g\n", (double)eis->omega)); 1494b9ad928SBarry Smith if (eis->usediag) { 1509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Using diagonal scaling (default)\n")); 1514b9ad928SBarry Smith } else { 1529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Not using diagonal scaling\n")); 1534b9ad928SBarry Smith } 1544b9ad928SBarry Smith } 1554b9ad928SBarry Smith PetscFunctionReturn(0); 1564b9ad928SBarry Smith } 1574b9ad928SBarry Smith 1589371c9d4SSatish Balay static PetscErrorCode PCSetUp_Eisenstat(PC pc) { 15913f74950SBarry Smith PetscInt M, N, m, n; 1604b9ad928SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 1614b9ad928SBarry Smith 1624b9ad928SBarry Smith PetscFunctionBegin; 1634b9ad928SBarry Smith if (!pc->setupcalled) { 1649566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->mat, &M, &N)); 1659566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pc->mat, &m, &n)); 1669566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &eis->shell)); 1679566063dSJacob Faibussowitsch PetscCall(MatSetSizes(eis->shell, m, n, M, N)); 1689566063dSJacob Faibussowitsch PetscCall(MatSetType(eis->shell, MATSHELL)); 1699566063dSJacob Faibussowitsch PetscCall(MatSetUp(eis->shell)); 1709566063dSJacob Faibussowitsch PetscCall(MatShellSetContext(eis->shell, pc)); 1719566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)pc, (PetscObject)eis->shell)); 1729566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(eis->shell, MATOP_MULT, (void (*)(void))PCMult_Eisenstat)); 173a9e2c90aSJose E. Roman PetscCall(MatShellSetOperation(eis->shell, MATOP_NORM, (void (*)(void))PCNorm_Eisenstat)); 1744b9ad928SBarry Smith } 1754b9ad928SBarry Smith if (!eis->usediag) PetscFunctionReturn(0); 1764b9ad928SBarry Smith if (!pc->setupcalled) { 1779566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(pc->pmat, &eis->diag, NULL)); 1789566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)pc, (PetscObject)eis->diag)); 1794b9ad928SBarry Smith } 1809566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(pc->pmat, eis->diag)); 1814b9ad928SBarry Smith PetscFunctionReturn(0); 1824b9ad928SBarry Smith } 1834b9ad928SBarry Smith 1844b9ad928SBarry Smith /* --------------------------------------------------------------------*/ 1854b9ad928SBarry Smith 1869371c9d4SSatish Balay static PetscErrorCode PCEisenstatSetOmega_Eisenstat(PC pc, PetscReal omega) { 187c60c7ad4SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 1884b9ad928SBarry Smith 1894b9ad928SBarry Smith PetscFunctionBegin; 1902472a847SBarry Smith PetscCheck(omega > 0.0 && omega < 2.0, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Relaxation out of range"); 1914b9ad928SBarry Smith eis->omega = omega; 1924b9ad928SBarry Smith PetscFunctionReturn(0); 1934b9ad928SBarry Smith } 1944b9ad928SBarry Smith 1959371c9d4SSatish Balay static PetscErrorCode PCEisenstatSetNoDiagonalScaling_Eisenstat(PC pc, PetscBool flg) { 196c60c7ad4SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 1974b9ad928SBarry Smith 1984b9ad928SBarry Smith PetscFunctionBegin; 199c60c7ad4SBarry Smith eis->usediag = flg; 200c60c7ad4SBarry Smith PetscFunctionReturn(0); 201c60c7ad4SBarry Smith } 202c60c7ad4SBarry Smith 2039371c9d4SSatish Balay static PetscErrorCode PCEisenstatGetOmega_Eisenstat(PC pc, PetscReal *omega) { 204c60c7ad4SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 205c60c7ad4SBarry Smith 206c60c7ad4SBarry Smith PetscFunctionBegin; 207c60c7ad4SBarry Smith *omega = eis->omega; 208c60c7ad4SBarry Smith PetscFunctionReturn(0); 209c60c7ad4SBarry Smith } 210c60c7ad4SBarry Smith 2119371c9d4SSatish Balay static PetscErrorCode PCEisenstatGetNoDiagonalScaling_Eisenstat(PC pc, PetscBool *flg) { 212c60c7ad4SBarry Smith PC_Eisenstat *eis = (PC_Eisenstat *)pc->data; 213c60c7ad4SBarry Smith 214c60c7ad4SBarry Smith PetscFunctionBegin; 215c60c7ad4SBarry Smith *flg = eis->usediag; 2164b9ad928SBarry Smith PetscFunctionReturn(0); 2174b9ad928SBarry Smith } 2184b9ad928SBarry Smith 2194b9ad928SBarry Smith /*@ 2204b9ad928SBarry Smith PCEisenstatSetOmega - Sets the SSOR relaxation coefficient, omega, 2214b9ad928SBarry Smith to use with Eisenstat's trick (where omega = 1.0 by default). 2224b9ad928SBarry Smith 223ad4df100SBarry Smith Logically Collective on PC 2244b9ad928SBarry Smith 2254b9ad928SBarry Smith Input Parameters: 2264b9ad928SBarry Smith + pc - the preconditioner context 2274b9ad928SBarry Smith - omega - relaxation coefficient (0 < omega < 2) 2284b9ad928SBarry Smith 2294b9ad928SBarry Smith Options Database Key: 2304b9ad928SBarry Smith . -pc_eisenstat_omega <omega> - Sets omega 2314b9ad928SBarry Smith 2324b9ad928SBarry Smith Notes: 2334b9ad928SBarry Smith The Eisenstat trick implementation of SSOR requires about 50% of the 2344b9ad928SBarry Smith usual amount of floating point operations used for SSOR + Krylov method; 2354b9ad928SBarry Smith however, the preconditioned problem must be solved with both left 2364b9ad928SBarry Smith and right preconditioning. 2374b9ad928SBarry Smith 2384b9ad928SBarry Smith To use SSOR without the Eisenstat trick, employ the PCSOR preconditioner, 2394b9ad928SBarry Smith which can be chosen with the database options 2404b9ad928SBarry Smith $ -pc_type sor -pc_sor_symmetric 2414b9ad928SBarry Smith 2424b9ad928SBarry Smith Level: intermediate 2434b9ad928SBarry Smith 244db781477SPatrick Sanan .seealso: `PCSORSetOmega()` 2454b9ad928SBarry Smith @*/ 2469371c9d4SSatish Balay PetscErrorCode PCEisenstatSetOmega(PC pc, PetscReal omega) { 2474b9ad928SBarry Smith PetscFunctionBegin; 2480700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 249c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(pc, omega, 2); 250cac4c232SBarry Smith PetscTryMethod(pc, "PCEisenstatSetOmega_C", (PC, PetscReal), (pc, omega)); 2514b9ad928SBarry Smith PetscFunctionReturn(0); 2524b9ad928SBarry Smith } 2534b9ad928SBarry Smith 2544b9ad928SBarry Smith /*@ 255c60c7ad4SBarry Smith PCEisenstatSetNoDiagonalScaling - Causes the Eisenstat preconditioner 2564b9ad928SBarry Smith not to do additional diagonal preconditioning. For matrices with a constant 2574b9ad928SBarry Smith along the diagonal, this may save a small amount of work. 2584b9ad928SBarry Smith 259ad4df100SBarry Smith Logically Collective on PC 2604b9ad928SBarry Smith 261c60c7ad4SBarry Smith Input Parameters: 262c60c7ad4SBarry Smith + pc - the preconditioner context 263c60c7ad4SBarry Smith - flg - PETSC_TRUE turns off diagonal scaling inside the algorithm 2644b9ad928SBarry Smith 2654b9ad928SBarry Smith Options Database Key: 266c60c7ad4SBarry Smith . -pc_eisenstat_no_diagonal_scaling - Activates PCEisenstatSetNoDiagonalScaling() 2674b9ad928SBarry Smith 2684b9ad928SBarry Smith Level: intermediate 2694b9ad928SBarry Smith 2704b9ad928SBarry Smith Note: 271f9ff08acSPierre Jolivet If you use the KSPSetDiagonalScaling() or -ksp_diagonal_scale option then you will 2726aad120cSJose E. Roman likely want to use this routine since it will save you some unneeded flops. 2734b9ad928SBarry Smith 274db781477SPatrick Sanan .seealso: `PCEisenstatSetOmega()` 2754b9ad928SBarry Smith @*/ 2769371c9d4SSatish Balay PetscErrorCode PCEisenstatSetNoDiagonalScaling(PC pc, PetscBool flg) { 2774b9ad928SBarry Smith PetscFunctionBegin; 2780700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 279cac4c232SBarry Smith PetscTryMethod(pc, "PCEisenstatSetNoDiagonalScaling_C", (PC, PetscBool), (pc, flg)); 280c60c7ad4SBarry Smith PetscFunctionReturn(0); 281c60c7ad4SBarry Smith } 282c60c7ad4SBarry Smith 283c60c7ad4SBarry Smith /*@ 284c60c7ad4SBarry Smith PCEisenstatGetOmega - Gets the SSOR relaxation coefficient, omega, 285c60c7ad4SBarry Smith to use with Eisenstat's trick (where omega = 1.0 by default). 286c60c7ad4SBarry Smith 287c60c7ad4SBarry Smith Logically Collective on PC 288c60c7ad4SBarry Smith 289c60c7ad4SBarry Smith Input Parameter: 290c60c7ad4SBarry Smith . pc - the preconditioner context 291c60c7ad4SBarry Smith 292c60c7ad4SBarry Smith Output Parameter: 293c60c7ad4SBarry Smith . omega - relaxation coefficient (0 < omega < 2) 294c60c7ad4SBarry Smith 295c60c7ad4SBarry Smith Options Database Key: 296c60c7ad4SBarry Smith . -pc_eisenstat_omega <omega> - Sets omega 297c60c7ad4SBarry Smith 298c60c7ad4SBarry Smith Notes: 299c60c7ad4SBarry Smith The Eisenstat trick implementation of SSOR requires about 50% of the 300c60c7ad4SBarry Smith usual amount of floating point operations used for SSOR + Krylov method; 301c60c7ad4SBarry Smith however, the preconditioned problem must be solved with both left 302c60c7ad4SBarry Smith and right preconditioning. 303c60c7ad4SBarry Smith 304c60c7ad4SBarry Smith To use SSOR without the Eisenstat trick, employ the PCSOR preconditioner, 305c60c7ad4SBarry Smith which can be chosen with the database options 306c60c7ad4SBarry Smith $ -pc_type sor -pc_sor_symmetric 307c60c7ad4SBarry Smith 308c60c7ad4SBarry Smith Level: intermediate 309c60c7ad4SBarry Smith 310db781477SPatrick Sanan .seealso: `PCSORGetOmega()`, `PCEisenstatSetOmega()` 311c60c7ad4SBarry Smith @*/ 3129371c9d4SSatish Balay PetscErrorCode PCEisenstatGetOmega(PC pc, PetscReal *omega) { 313c60c7ad4SBarry Smith PetscFunctionBegin; 314c60c7ad4SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 315cac4c232SBarry Smith PetscUseMethod(pc, "PCEisenstatGetOmega_C", (PC, PetscReal *), (pc, omega)); 316c60c7ad4SBarry Smith PetscFunctionReturn(0); 317c60c7ad4SBarry Smith } 318c60c7ad4SBarry Smith 319c60c7ad4SBarry Smith /*@ 320163d334eSBarry Smith PCEisenstatGetNoDiagonalScaling - Tells if the Eisenstat preconditioner 321c60c7ad4SBarry Smith not to do additional diagonal preconditioning. For matrices with a constant 322c60c7ad4SBarry Smith along the diagonal, this may save a small amount of work. 323c60c7ad4SBarry Smith 324c60c7ad4SBarry Smith Logically Collective on PC 325c60c7ad4SBarry Smith 326c60c7ad4SBarry Smith Input Parameter: 327c60c7ad4SBarry Smith . pc - the preconditioner context 328c60c7ad4SBarry Smith 329c60c7ad4SBarry Smith Output Parameter: 330c60c7ad4SBarry Smith . flg - PETSC_TRUE means there is no diagonal scaling applied 331c60c7ad4SBarry Smith 332c60c7ad4SBarry Smith Options Database Key: 333c60c7ad4SBarry Smith . -pc_eisenstat_no_diagonal_scaling - Activates PCEisenstatSetNoDiagonalScaling() 334c60c7ad4SBarry Smith 335c60c7ad4SBarry Smith Level: intermediate 336c60c7ad4SBarry Smith 337c60c7ad4SBarry Smith Note: 338f9ff08acSPierre Jolivet If you use the KSPSetDiagonalScaling() or -ksp_diagonal_scale option then you will 3396aad120cSJose E. Roman likely want to use this routine since it will save you some unneeded flops. 340c60c7ad4SBarry Smith 341db781477SPatrick Sanan .seealso: `PCEisenstatGetOmega()` 342c60c7ad4SBarry Smith @*/ 3439371c9d4SSatish Balay PetscErrorCode PCEisenstatGetNoDiagonalScaling(PC pc, PetscBool *flg) { 344c60c7ad4SBarry Smith PetscFunctionBegin; 345c60c7ad4SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 346cac4c232SBarry Smith PetscUseMethod(pc, "PCEisenstatGetNoDiagonalScaling_C", (PC, PetscBool *), (pc, flg)); 3474b9ad928SBarry Smith PetscFunctionReturn(0); 3484b9ad928SBarry Smith } 3494b9ad928SBarry Smith 3509371c9d4SSatish Balay static PetscErrorCode PCPreSolveChangeRHS_Eisenstat(PC pc, PetscBool *change) { 3518066bbecSBarry Smith PetscFunctionBegin; 3528066bbecSBarry Smith *change = PETSC_TRUE; 3538066bbecSBarry Smith PetscFunctionReturn(0); 3548066bbecSBarry Smith } 3558066bbecSBarry Smith 3564b9ad928SBarry Smith /* --------------------------------------------------------------------*/ 3574b9ad928SBarry Smith 3584b9ad928SBarry Smith /*MC 3594b9ad928SBarry Smith PCEISENSTAT - An implementation of SSOR (symmetric successive over relaxation, symmetric Gauss-Seidel) 3604b9ad928SBarry Smith preconditioning that incorporates Eisenstat's trick to reduce the amount of computation needed. 3614b9ad928SBarry Smith 3624b9ad928SBarry Smith Options Database Keys: 3634b9ad928SBarry Smith + -pc_eisenstat_omega <omega> - Sets omega 364c60c7ad4SBarry Smith - -pc_eisenstat_no_diagonal_scaling - Activates PCEisenstatSetNoDiagonalScaling() 3654b9ad928SBarry Smith 3664b9ad928SBarry Smith Level: beginner 3674b9ad928SBarry Smith 36895452b02SPatrick Sanan Notes: 36995452b02SPatrick Sanan Only implemented for the SeqAIJ matrix format. 3704b9ad928SBarry Smith Not a true parallel SOR, in parallel this implementation corresponds to block 3714b9ad928SBarry Smith Jacobi with SOR on each block. 3724b9ad928SBarry Smith 373db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, 374db781477SPatrick Sanan `PCEisenstatSetNoDiagonalScaling()`, `PCEisenstatSetOmega()`, `PCSOR` 3754b9ad928SBarry Smith M*/ 3764b9ad928SBarry Smith 3779371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_Eisenstat(PC pc) { 3784b9ad928SBarry Smith PC_Eisenstat *eis; 3794b9ad928SBarry Smith 3804b9ad928SBarry Smith PetscFunctionBegin; 3819566063dSJacob Faibussowitsch PetscCall(PetscNewLog(pc, &eis)); 3824b9ad928SBarry Smith 3834b9ad928SBarry Smith pc->ops->apply = PCApply_Eisenstat; 384dc231df0SBarry Smith pc->ops->presolve = PCPreSolve_Eisenstat; 385dc231df0SBarry Smith pc->ops->postsolve = PCPostSolve_Eisenstat; 3860a545947SLisandro Dalcin pc->ops->applyrichardson = NULL; 3874b9ad928SBarry Smith pc->ops->setfromoptions = PCSetFromOptions_Eisenstat; 3884b9ad928SBarry Smith pc->ops->destroy = PCDestroy_Eisenstat; 38969d2c0f9SBarry Smith pc->ops->reset = PCReset_Eisenstat; 3904b9ad928SBarry Smith pc->ops->view = PCView_Eisenstat; 3914b9ad928SBarry Smith pc->ops->setup = PCSetUp_Eisenstat; 3924b9ad928SBarry Smith 3933ec1f749SStefano Zampini pc->data = eis; 3944b9ad928SBarry Smith eis->omega = 1.0; 3950a545947SLisandro Dalcin eis->b[0] = NULL; 3960a545947SLisandro Dalcin eis->b[1] = NULL; 3970a545947SLisandro Dalcin eis->diag = NULL; 3984b9ad928SBarry Smith eis->usediag = PETSC_TRUE; 3994b9ad928SBarry Smith 4009566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCEisenstatSetOmega_C", PCEisenstatSetOmega_Eisenstat)); 4019566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCEisenstatSetNoDiagonalScaling_C", PCEisenstatSetNoDiagonalScaling_Eisenstat)); 4029566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCEisenstatGetOmega_C", PCEisenstatGetOmega_Eisenstat)); 4039566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCEisenstatGetNoDiagonalScaling_C", PCEisenstatGetNoDiagonalScaling_Eisenstat)); 4049566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", PCPreSolveChangeRHS_Eisenstat)); 4054b9ad928SBarry Smith PetscFunctionReturn(0); 4064b9ad928SBarry Smith } 407