xref: /petsc/src/ksp/pc/impls/pbjacobi/pbjacobi.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
1dba47a55SKris Buschelman 
24b9ad928SBarry Smith /*
34b9ad928SBarry Smith    Include files needed for the PBJacobi preconditioner:
44b9ad928SBarry Smith      pcimpl.h - private include file intended for use by all preconditioners
54b9ad928SBarry Smith */
64b9ad928SBarry Smith 
7af0996ceSBarry Smith #include <petsc/private/pcimpl.h> /*I "petscpc.h" I*/
84b9ad928SBarry Smith 
94b9ad928SBarry Smith /*
104b9ad928SBarry Smith    Private context (data structure) for the PBJacobi preconditioner.
114b9ad928SBarry Smith */
124b9ad928SBarry Smith typedef struct {
13713ccfa9SJed Brown   const MatScalar *diag;
14c1ac3661SBarry Smith   PetscInt         bs, mbs;
154b9ad928SBarry Smith } PC_PBJacobi;
164b9ad928SBarry Smith 
179371c9d4SSatish Balay static PetscErrorCode PCApply_PBJacobi_1(PC pc, Vec x, Vec y) {
18bbead8a2SBarry Smith   PC_PBJacobi       *jac = (PC_PBJacobi *)pc->data;
19bbead8a2SBarry Smith   PetscInt           i, m = jac->mbs;
20bbead8a2SBarry Smith   const MatScalar   *diag = jac->diag;
21bbead8a2SBarry Smith   const PetscScalar *xx;
22bbead8a2SBarry Smith   PetscScalar       *yy;
23bbead8a2SBarry Smith 
24bbead8a2SBarry Smith   PetscFunctionBegin;
259566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
269566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
272fa5cd67SKarl Rupp   for (i = 0; i < m; i++) yy[i] = diag[i] * xx[i];
289566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
299566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
309566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(m));
31bbead8a2SBarry Smith   PetscFunctionReturn(0);
32bbead8a2SBarry Smith }
33bbead8a2SBarry Smith 
349371c9d4SSatish Balay static PetscErrorCode PCApply_PBJacobi_2(PC pc, Vec x, Vec y) {
354b9ad928SBarry Smith   PC_PBJacobi       *jac = (PC_PBJacobi *)pc->data;
36c1ac3661SBarry Smith   PetscInt           i, m = jac->mbs;
3785f4f44aSBarry Smith   const MatScalar   *diag = jac->diag;
380e666e78SToby Isaac   PetscScalar        x0, x1, *yy;
390e666e78SToby Isaac   const PetscScalar *xx;
404b9ad928SBarry Smith 
414b9ad928SBarry Smith   PetscFunctionBegin;
429566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
439566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
444b9ad928SBarry Smith   for (i = 0; i < m; i++) {
459371c9d4SSatish Balay     x0            = xx[2 * i];
469371c9d4SSatish Balay     x1            = xx[2 * i + 1];
474b9ad928SBarry Smith     yy[2 * i]     = diag[0] * x0 + diag[2] * x1;
484b9ad928SBarry Smith     yy[2 * i + 1] = diag[1] * x0 + diag[3] * x1;
494b9ad928SBarry Smith     diag += 4;
504b9ad928SBarry Smith   }
519566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
529566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
539566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(6.0 * m));
544b9ad928SBarry Smith   PetscFunctionReturn(0);
554b9ad928SBarry Smith }
569371c9d4SSatish Balay static PetscErrorCode PCApply_PBJacobi_3(PC pc, Vec x, Vec y) {
574b9ad928SBarry Smith   PC_PBJacobi       *jac = (PC_PBJacobi *)pc->data;
58c1ac3661SBarry Smith   PetscInt           i, m = jac->mbs;
5985f4f44aSBarry Smith   const MatScalar   *diag = jac->diag;
600e666e78SToby Isaac   PetscScalar        x0, x1, x2, *yy;
610e666e78SToby Isaac   const PetscScalar *xx;
624b9ad928SBarry Smith 
634b9ad928SBarry Smith   PetscFunctionBegin;
649566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
659566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
664b9ad928SBarry Smith   for (i = 0; i < m; i++) {
679371c9d4SSatish Balay     x0 = xx[3 * i];
689371c9d4SSatish Balay     x1 = xx[3 * i + 1];
699371c9d4SSatish Balay     x2 = xx[3 * i + 2];
702fa5cd67SKarl Rupp 
714b9ad928SBarry Smith     yy[3 * i]     = diag[0] * x0 + diag[3] * x1 + diag[6] * x2;
724b9ad928SBarry Smith     yy[3 * i + 1] = diag[1] * x0 + diag[4] * x1 + diag[7] * x2;
734b9ad928SBarry Smith     yy[3 * i + 2] = diag[2] * x0 + diag[5] * x1 + diag[8] * x2;
744b9ad928SBarry Smith     diag += 9;
754b9ad928SBarry Smith   }
769566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
779566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
789566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(15.0 * m));
794b9ad928SBarry Smith   PetscFunctionReturn(0);
804b9ad928SBarry Smith }
819371c9d4SSatish Balay static PetscErrorCode PCApply_PBJacobi_4(PC pc, Vec x, Vec y) {
824b9ad928SBarry Smith   PC_PBJacobi       *jac = (PC_PBJacobi *)pc->data;
83c1ac3661SBarry Smith   PetscInt           i, m = jac->mbs;
8485f4f44aSBarry Smith   const MatScalar   *diag = jac->diag;
850e666e78SToby Isaac   PetscScalar        x0, x1, x2, x3, *yy;
860e666e78SToby Isaac   const PetscScalar *xx;
874b9ad928SBarry Smith 
884b9ad928SBarry Smith   PetscFunctionBegin;
899566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
909566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
914b9ad928SBarry Smith   for (i = 0; i < m; i++) {
929371c9d4SSatish Balay     x0 = xx[4 * i];
939371c9d4SSatish Balay     x1 = xx[4 * i + 1];
949371c9d4SSatish Balay     x2 = xx[4 * i + 2];
959371c9d4SSatish Balay     x3 = xx[4 * i + 3];
962fa5cd67SKarl Rupp 
974b9ad928SBarry Smith     yy[4 * i]     = diag[0] * x0 + diag[4] * x1 + diag[8] * x2 + diag[12] * x3;
984b9ad928SBarry Smith     yy[4 * i + 1] = diag[1] * x0 + diag[5] * x1 + diag[9] * x2 + diag[13] * x3;
994b9ad928SBarry Smith     yy[4 * i + 2] = diag[2] * x0 + diag[6] * x1 + diag[10] * x2 + diag[14] * x3;
1004b9ad928SBarry Smith     yy[4 * i + 3] = diag[3] * x0 + diag[7] * x1 + diag[11] * x2 + diag[15] * x3;
1014b9ad928SBarry Smith     diag += 16;
1024b9ad928SBarry Smith   }
1039566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
1049566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
1059566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(28.0 * m));
1064b9ad928SBarry Smith   PetscFunctionReturn(0);
1074b9ad928SBarry Smith }
1089371c9d4SSatish Balay static PetscErrorCode PCApply_PBJacobi_5(PC pc, Vec x, Vec y) {
1094b9ad928SBarry Smith   PC_PBJacobi       *jac = (PC_PBJacobi *)pc->data;
110c1ac3661SBarry Smith   PetscInt           i, m = jac->mbs;
11185f4f44aSBarry Smith   const MatScalar   *diag = jac->diag;
1120e666e78SToby Isaac   PetscScalar        x0, x1, x2, x3, x4, *yy;
1130e666e78SToby Isaac   const PetscScalar *xx;
1144b9ad928SBarry Smith 
1154b9ad928SBarry Smith   PetscFunctionBegin;
1169566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
1179566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
1184b9ad928SBarry Smith   for (i = 0; i < m; i++) {
1199371c9d4SSatish Balay     x0 = xx[5 * i];
1209371c9d4SSatish Balay     x1 = xx[5 * i + 1];
1219371c9d4SSatish Balay     x2 = xx[5 * i + 2];
1229371c9d4SSatish Balay     x3 = xx[5 * i + 3];
1239371c9d4SSatish Balay     x4 = xx[5 * i + 4];
1242fa5cd67SKarl Rupp 
1254b9ad928SBarry Smith     yy[5 * i]     = diag[0] * x0 + diag[5] * x1 + diag[10] * x2 + diag[15] * x3 + diag[20] * x4;
1264b9ad928SBarry Smith     yy[5 * i + 1] = diag[1] * x0 + diag[6] * x1 + diag[11] * x2 + diag[16] * x3 + diag[21] * x4;
1274b9ad928SBarry Smith     yy[5 * i + 2] = diag[2] * x0 + diag[7] * x1 + diag[12] * x2 + diag[17] * x3 + diag[22] * x4;
1284b9ad928SBarry Smith     yy[5 * i + 3] = diag[3] * x0 + diag[8] * x1 + diag[13] * x2 + diag[18] * x3 + diag[23] * x4;
1294b9ad928SBarry Smith     yy[5 * i + 4] = diag[4] * x0 + diag[9] * x1 + diag[14] * x2 + diag[19] * x3 + diag[24] * x4;
1304b9ad928SBarry Smith     diag += 25;
1314b9ad928SBarry Smith   }
1329566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
1339566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
1349566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(45.0 * m));
1354b9ad928SBarry Smith   PetscFunctionReturn(0);
1364b9ad928SBarry Smith }
1379371c9d4SSatish Balay static PetscErrorCode PCApply_PBJacobi_6(PC pc, Vec x, Vec y) {
1380e1b4bd6SMark F. Adams   PC_PBJacobi       *jac = (PC_PBJacobi *)pc->data;
1390e1b4bd6SMark F. Adams   PetscInt           i, m = jac->mbs;
1400e1b4bd6SMark F. Adams   const MatScalar   *diag = jac->diag;
1410e666e78SToby Isaac   PetscScalar        x0, x1, x2, x3, x4, x5, *yy;
1420e666e78SToby Isaac   const PetscScalar *xx;
1430e1b4bd6SMark F. Adams 
1440e1b4bd6SMark F. Adams   PetscFunctionBegin;
1459566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
1469566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
1470e1b4bd6SMark F. Adams   for (i = 0; i < m; i++) {
1489371c9d4SSatish Balay     x0 = xx[6 * i];
1499371c9d4SSatish Balay     x1 = xx[6 * i + 1];
1509371c9d4SSatish Balay     x2 = xx[6 * i + 2];
1519371c9d4SSatish Balay     x3 = xx[6 * i + 3];
1529371c9d4SSatish Balay     x4 = xx[6 * i + 4];
1539371c9d4SSatish Balay     x5 = xx[6 * i + 5];
1542fa5cd67SKarl Rupp 
1550e1b4bd6SMark F. Adams     yy[6 * i]     = diag[0] * x0 + diag[6] * x1 + diag[12] * x2 + diag[18] * x3 + diag[24] * x4 + diag[30] * x5;
1560e1b4bd6SMark F. Adams     yy[6 * i + 1] = diag[1] * x0 + diag[7] * x1 + diag[13] * x2 + diag[19] * x3 + diag[25] * x4 + diag[31] * x5;
1570e1b4bd6SMark F. Adams     yy[6 * i + 2] = diag[2] * x0 + diag[8] * x1 + diag[14] * x2 + diag[20] * x3 + diag[26] * x4 + diag[32] * x5;
1580e1b4bd6SMark F. Adams     yy[6 * i + 3] = diag[3] * x0 + diag[9] * x1 + diag[15] * x2 + diag[21] * x3 + diag[27] * x4 + diag[33] * x5;
1590e1b4bd6SMark F. Adams     yy[6 * i + 4] = diag[4] * x0 + diag[10] * x1 + diag[16] * x2 + diag[22] * x3 + diag[28] * x4 + diag[34] * x5;
1600e1b4bd6SMark F. Adams     yy[6 * i + 5] = diag[5] * x0 + diag[11] * x1 + diag[17] * x2 + diag[23] * x3 + diag[29] * x4 + diag[35] * x5;
1610e1b4bd6SMark F. Adams     diag += 36;
1620e1b4bd6SMark F. Adams   }
1639566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
1649566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
1659566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(66.0 * m));
1660e1b4bd6SMark F. Adams   PetscFunctionReturn(0);
1670e1b4bd6SMark F. Adams }
1689371c9d4SSatish Balay static PetscErrorCode PCApply_PBJacobi_7(PC pc, Vec x, Vec y) {
1690a4ca348SMatthew G Knepley   PC_PBJacobi       *jac = (PC_PBJacobi *)pc->data;
1700a4ca348SMatthew G Knepley   PetscInt           i, m = jac->mbs;
1710a4ca348SMatthew G Knepley   const MatScalar   *diag = jac->diag;
1720e666e78SToby Isaac   PetscScalar        x0, x1, x2, x3, x4, x5, x6, *yy;
1730e666e78SToby Isaac   const PetscScalar *xx;
1740a4ca348SMatthew G Knepley 
1750a4ca348SMatthew G Knepley   PetscFunctionBegin;
1769566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
1779566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
1780a4ca348SMatthew G Knepley   for (i = 0; i < m; i++) {
1799371c9d4SSatish Balay     x0 = xx[7 * i];
1809371c9d4SSatish Balay     x1 = xx[7 * i + 1];
1819371c9d4SSatish Balay     x2 = xx[7 * i + 2];
1829371c9d4SSatish Balay     x3 = xx[7 * i + 3];
1839371c9d4SSatish Balay     x4 = xx[7 * i + 4];
1849371c9d4SSatish Balay     x5 = xx[7 * i + 5];
1859371c9d4SSatish Balay     x6 = xx[7 * i + 6];
1862fa5cd67SKarl Rupp 
1870a4ca348SMatthew G Knepley     yy[7 * i]     = diag[0] * x0 + diag[7] * x1 + diag[14] * x2 + diag[21] * x3 + diag[28] * x4 + diag[35] * x5 + diag[42] * x6;
1880a4ca348SMatthew G Knepley     yy[7 * i + 1] = diag[1] * x0 + diag[8] * x1 + diag[15] * x2 + diag[22] * x3 + diag[29] * x4 + diag[36] * x5 + diag[43] * x6;
1890a4ca348SMatthew G Knepley     yy[7 * i + 2] = diag[2] * x0 + diag[9] * x1 + diag[16] * x2 + diag[23] * x3 + diag[30] * x4 + diag[37] * x5 + diag[44] * x6;
1900a4ca348SMatthew G Knepley     yy[7 * i + 3] = diag[3] * x0 + diag[10] * x1 + diag[17] * x2 + diag[24] * x3 + diag[31] * x4 + diag[38] * x5 + diag[45] * x6;
1910a4ca348SMatthew G Knepley     yy[7 * i + 4] = diag[4] * x0 + diag[11] * x1 + diag[18] * x2 + diag[25] * x3 + diag[32] * x4 + diag[39] * x5 + diag[46] * x6;
1920a4ca348SMatthew G Knepley     yy[7 * i + 5] = diag[5] * x0 + diag[12] * x1 + diag[19] * x2 + diag[26] * x3 + diag[33] * x4 + diag[40] * x5 + diag[47] * x6;
1930a4ca348SMatthew G Knepley     yy[7 * i + 6] = diag[6] * x0 + diag[13] * x1 + diag[20] * x2 + diag[27] * x3 + diag[34] * x4 + diag[41] * x5 + diag[48] * x6;
1940a4ca348SMatthew G Knepley     diag += 49;
1950a4ca348SMatthew G Knepley   }
1969566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
1979566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
1989566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(91.0 * m)); /* 2*bs2 - bs */
1990a4ca348SMatthew G Knepley   PetscFunctionReturn(0);
2000a4ca348SMatthew G Knepley }
2019371c9d4SSatish Balay static PetscErrorCode PCApply_PBJacobi_N(PC pc, Vec x, Vec y) {
202f79daf70SMark Lohry   PC_PBJacobi       *jac = (PC_PBJacobi *)pc->data;
203f79daf70SMark Lohry   PetscInt           i, ib, jb;
204f79daf70SMark Lohry   const PetscInt     m    = jac->mbs;
205f79daf70SMark Lohry   const PetscInt     bs   = jac->bs;
206f79daf70SMark Lohry   const MatScalar   *diag = jac->diag;
207f79daf70SMark Lohry   PetscScalar       *yy;
208f79daf70SMark Lohry   const PetscScalar *xx;
209f79daf70SMark Lohry 
210f79daf70SMark Lohry   PetscFunctionBegin;
2119566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
2129566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
213f79daf70SMark Lohry   for (i = 0; i < m; i++) {
214f79daf70SMark Lohry     for (ib = 0; ib < bs; ib++) {
215f79daf70SMark Lohry       PetscScalar rowsum = 0;
2169371c9d4SSatish Balay       for (jb = 0; jb < bs; jb++) { rowsum += diag[ib + jb * bs] * xx[bs * i + jb]; }
217f79daf70SMark Lohry       yy[bs * i + ib] = rowsum;
218f79daf70SMark Lohry     }
219f79daf70SMark Lohry     diag += bs * bs;
220f79daf70SMark Lohry   }
2219566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
2229566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
2239566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops((2.0 * bs * bs - bs) * m)); /* 2*bs2 - bs */
224f79daf70SMark Lohry   PetscFunctionReturn(0);
225f79daf70SMark Lohry }
226faff7d23SJed Brown 
2279371c9d4SSatish Balay static PetscErrorCode PCApplyTranspose_PBJacobi_N(PC pc, Vec x, Vec y) {
2288cd12025SJed Brown   PC_PBJacobi       *jac = (PC_PBJacobi *)pc->data;
2298cd12025SJed Brown   PetscInt           i, j, k, m = jac->mbs, bs = jac->bs;
2308cd12025SJed Brown   const MatScalar   *diag = jac->diag;
2318cd12025SJed Brown   const PetscScalar *xx;
2328cd12025SJed Brown   PetscScalar       *yy;
2338cd12025SJed Brown 
2348cd12025SJed Brown   PetscFunctionBegin;
2359566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
2369566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
2378cd12025SJed Brown   for (i = 0; i < m; i++) {
2388cd12025SJed Brown     for (j = 0; j < bs; j++) yy[i * bs + j] = 0.;
2398cd12025SJed Brown     for (j = 0; j < bs; j++) {
2409371c9d4SSatish Balay       for (k = 0; k < bs; k++) { yy[i * bs + k] += diag[k * bs + j] * xx[i * bs + j]; }
2418cd12025SJed Brown     }
2428cd12025SJed Brown     diag += bs * bs;
2438cd12025SJed Brown   }
2449566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
2459566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
2469566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(m * bs * (2 * bs - 1)));
2478cd12025SJed Brown   PetscFunctionReturn(0);
2488cd12025SJed Brown }
2498cd12025SJed Brown 
2504b9ad928SBarry Smith /* -------------------------------------------------------------------------- */
2519371c9d4SSatish Balay static PetscErrorCode PCSetUp_PBJacobi(PC pc) {
2524b9ad928SBarry Smith   PC_PBJacobi   *jac = (PC_PBJacobi *)pc->data;
2534b9ad928SBarry Smith   Mat            A   = pc->pmat;
25400e125f8SBarry Smith   MatFactorError err;
255539c167fSBarry Smith   PetscInt       nlocal;
2564b9ad928SBarry Smith 
2574b9ad928SBarry Smith   PetscFunctionBegin;
2589566063dSJacob Faibussowitsch   PetscCall(MatInvertBlockDiagonal(A, &jac->diag));
2599566063dSJacob Faibussowitsch   PetscCall(MatFactorGetError(A, &err));
26000e125f8SBarry Smith   if (err) pc->failedreason = (PCFailedReason)err;
261d7806518SHong Zhang 
2629566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A, &jac->bs));
2639566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &nlocal, NULL));
264539c167fSBarry Smith   jac->mbs = nlocal / jac->bs;
265521d7252SBarry Smith   switch (jac->bs) {
2669371c9d4SSatish Balay   case 1: pc->ops->apply = PCApply_PBJacobi_1; break;
2679371c9d4SSatish Balay   case 2: pc->ops->apply = PCApply_PBJacobi_2; break;
2689371c9d4SSatish Balay   case 3: pc->ops->apply = PCApply_PBJacobi_3; break;
2699371c9d4SSatish Balay   case 4: pc->ops->apply = PCApply_PBJacobi_4; break;
2709371c9d4SSatish Balay   case 5: pc->ops->apply = PCApply_PBJacobi_5; break;
2719371c9d4SSatish Balay   case 6: pc->ops->apply = PCApply_PBJacobi_6; break;
2729371c9d4SSatish Balay   case 7: pc->ops->apply = PCApply_PBJacobi_7; break;
2739371c9d4SSatish Balay   default: pc->ops->apply = PCApply_PBJacobi_N; break;
2744b9ad928SBarry Smith   }
2758cd12025SJed Brown   pc->ops->applytranspose = PCApplyTranspose_PBJacobi_N;
2764b9ad928SBarry Smith   PetscFunctionReturn(0);
2774b9ad928SBarry Smith }
2784b9ad928SBarry Smith /* -------------------------------------------------------------------------- */
2799371c9d4SSatish Balay static PetscErrorCode PCDestroy_PBJacobi(PC pc) {
2804b9ad928SBarry Smith   PetscFunctionBegin;
2814b9ad928SBarry Smith   /*
2824b9ad928SBarry Smith       Free the private data structure that was hanging off the PC
2834b9ad928SBarry Smith   */
2849566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
2854b9ad928SBarry Smith   PetscFunctionReturn(0);
2864b9ad928SBarry Smith }
287fa939db7SJed Brown 
2889371c9d4SSatish Balay static PetscErrorCode PCView_PBJacobi(PC pc, PetscViewer viewer) {
289fa939db7SJed Brown   PC_PBJacobi *jac = (PC_PBJacobi *)pc->data;
290fa939db7SJed Brown   PetscBool    iascii;
291fa939db7SJed Brown 
292fa939db7SJed Brown   PetscFunctionBegin;
2939566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
294*48a46eb9SPierre Jolivet   if (iascii) PetscCall(PetscViewerASCIIPrintf(viewer, "  point-block size %" PetscInt_FMT "\n", jac->bs));
295fa939db7SJed Brown   PetscFunctionReturn(0);
296fa939db7SJed Brown }
297fa939db7SJed Brown 
2984b9ad928SBarry Smith /* -------------------------------------------------------------------------- */
29937a17b4dSBarry Smith /*MC
300422a814eSBarry Smith      PCPBJACOBI - Point block Jacobi preconditioner
301422a814eSBarry Smith 
30295452b02SPatrick Sanan    Notes:
303468ae2e8SBarry Smith     See PCJACOBI for diagonal Jacobi, PCVPBJACOBI for variable-size point block, and PCBJACOBI for large size blocks
304422a814eSBarry Smith 
305422a814eSBarry Smith    This works for AIJ and BAIJ matrices and uses the blocksize provided to the matrix
306422a814eSBarry Smith 
307422a814eSBarry Smith    Uses dense LU factorization with partial pivoting to invert the blocks; if a zero pivot
308422a814eSBarry Smith    is detected a PETSc error is generated.
309422a814eSBarry Smith 
31095452b02SPatrick Sanan    Developer Notes:
31195452b02SPatrick Sanan      This should support the PCSetErrorIfFailure() flag set to PETSC_TRUE to allow
312422a814eSBarry Smith      the factorization to continue even after a zero pivot is found resulting in a Nan and hence
313422a814eSBarry Smith      terminating KSP with a KSP_DIVERGED_NANORIF allowing
314422a814eSBarry Smith      a nonlinear solver/ODE integrator to recover without stopping the program as currently happens.
315422a814eSBarry Smith 
31690dfcc32SBarry Smith      Perhaps should provide an option that allows generation of a valid preconditioner
317422a814eSBarry Smith      even if a block is singular as the PCJACOBI does.
31837a17b4dSBarry Smith 
31937a17b4dSBarry Smith    Level: beginner
32037a17b4dSBarry Smith 
321db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCJACOBI`, `PCVPBJACOBI`, `PCBJACOBI`
32237a17b4dSBarry Smith 
32337a17b4dSBarry Smith M*/
32437a17b4dSBarry Smith 
3259371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_PBJacobi(PC pc) {
3264b9ad928SBarry Smith   PC_PBJacobi *jac;
3274b9ad928SBarry Smith 
3284b9ad928SBarry Smith   PetscFunctionBegin;
3294b9ad928SBarry Smith   /*
3304b9ad928SBarry Smith      Creates the private data structure for this preconditioner and
3314b9ad928SBarry Smith      attach it to the PC object.
3324b9ad928SBarry Smith   */
3339566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(pc, &jac));
3344b9ad928SBarry Smith   pc->data = (void *)jac;
3354b9ad928SBarry Smith 
3364b9ad928SBarry Smith   /*
3374b9ad928SBarry Smith      Initialize the pointers to vectors to ZERO; these will be used to store
3384b9ad928SBarry Smith      diagonal entries of the matrix for fast preconditioner application.
3394b9ad928SBarry Smith   */
3400a545947SLisandro Dalcin   jac->diag = NULL;
3414b9ad928SBarry Smith 
3424b9ad928SBarry Smith   /*
3434b9ad928SBarry Smith       Set the pointers for the functions that are provided above.
3444b9ad928SBarry Smith       Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
3454b9ad928SBarry Smith       are called, they will automatically call these functions.  Note we
3464b9ad928SBarry Smith       choose not to provide a couple of these functions since they are
3474b9ad928SBarry Smith       not needed.
3484b9ad928SBarry Smith   */
3490a545947SLisandro Dalcin   pc->ops->apply               = NULL; /*set depending on the block size */
3500a545947SLisandro Dalcin   pc->ops->applytranspose      = NULL;
3514b9ad928SBarry Smith   pc->ops->setup               = PCSetUp_PBJacobi;
3524b9ad928SBarry Smith   pc->ops->destroy             = PCDestroy_PBJacobi;
3530a545947SLisandro Dalcin   pc->ops->setfromoptions      = NULL;
354fa939db7SJed Brown   pc->ops->view                = PCView_PBJacobi;
3550a545947SLisandro Dalcin   pc->ops->applyrichardson     = NULL;
3560a545947SLisandro Dalcin   pc->ops->applysymmetricleft  = NULL;
3570a545947SLisandro Dalcin   pc->ops->applysymmetricright = NULL;
3584b9ad928SBarry Smith   PetscFunctionReturn(0);
3594b9ad928SBarry Smith }
360