xref: /petsc/src/ksp/pc/impls/kaczmarz/kaczmarz.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
1af0996ceSBarry Smith #include <petsc/private/pcimpl.h> /*I "petscpc.h" I*/
23f93e5bdSPeter Brune 
33f93e5bdSPeter Brune typedef struct {
43f93e5bdSPeter Brune   PetscReal lambda;    /* damping parameter */
569b97631SPeter Brune   PetscBool symmetric; /* apply the projections symmetrically */
63f93e5bdSPeter Brune } PC_Kaczmarz;
73f93e5bdSPeter Brune 
89371c9d4SSatish Balay static PetscErrorCode PCDestroy_Kaczmarz(PC pc) {
93f93e5bdSPeter Brune   PetscFunctionBegin;
109566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
113f93e5bdSPeter Brune   PetscFunctionReturn(0);
123f93e5bdSPeter Brune }
133f93e5bdSPeter Brune 
149371c9d4SSatish Balay static PetscErrorCode PCApply_Kaczmarz(PC pc, Vec x, Vec y) {
153f93e5bdSPeter Brune   PC_Kaczmarz       *jac = (PC_Kaczmarz *)pc->data;
163f93e5bdSPeter Brune   PetscInt           xs, xe, ys, ye, ncols, i, j;
173f93e5bdSPeter Brune   const PetscInt    *cols;
18e298bee8SBarry Smith   const PetscScalar *vals, *xarray;
193f93e5bdSPeter Brune   PetscScalar        r;
203f93e5bdSPeter Brune   PetscReal          anrm;
21e298bee8SBarry Smith   PetscScalar       *yarray;
223f93e5bdSPeter Brune   PetscReal          lambda = jac->lambda;
233f93e5bdSPeter Brune 
243f93e5bdSPeter Brune   PetscFunctionBegin;
259566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(pc->pmat, &xs, &xe));
269566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRangeColumn(pc->pmat, &ys, &ye));
279566063dSJacob Faibussowitsch   PetscCall(VecSet(y, 0.));
289566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xarray));
299566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yarray));
303f93e5bdSPeter Brune   for (i = xs; i < xe; i++) {
313f93e5bdSPeter Brune     /* get the maximum row width and row norms */
329566063dSJacob Faibussowitsch     PetscCall(MatGetRow(pc->pmat, i, &ncols, &cols, &vals));
333f93e5bdSPeter Brune     r    = xarray[i - xs];
343f93e5bdSPeter Brune     anrm = 0.;
353f93e5bdSPeter Brune     for (j = 0; j < ncols; j++) {
369371c9d4SSatish Balay       if (cols[j] >= ys && cols[j] < ye) { r -= yarray[cols[j] - ys] * vals[j]; }
3769b97631SPeter Brune       anrm += PetscRealPart(PetscSqr(vals[j]));
383f93e5bdSPeter Brune     }
3969b97631SPeter Brune     if (anrm > 0.) {
403f93e5bdSPeter Brune       for (j = 0; j < ncols; j++) {
419371c9d4SSatish Balay         if (cols[j] >= ys && cols[j] < ye) { yarray[cols[j] - ys] += vals[j] * lambda * r / anrm; }
423f93e5bdSPeter Brune       }
433f93e5bdSPeter Brune     }
449566063dSJacob Faibussowitsch     PetscCall(MatRestoreRow(pc->pmat, i, &ncols, &cols, &vals));
453f93e5bdSPeter Brune   }
4669b97631SPeter Brune   if (jac->symmetric) {
4769b97631SPeter Brune     for (i = xe - 1; i >= xs; i--) {
489566063dSJacob Faibussowitsch       PetscCall(MatGetRow(pc->pmat, i, &ncols, &cols, &vals));
4969b97631SPeter Brune       r    = xarray[i - xs];
5069b97631SPeter Brune       anrm = 0.;
5169b97631SPeter Brune       for (j = 0; j < ncols; j++) {
529371c9d4SSatish Balay         if (cols[j] >= ys && cols[j] < ye) { r -= yarray[cols[j] - ys] * vals[j]; }
5369b97631SPeter Brune         anrm += PetscRealPart(PetscSqr(vals[j]));
5469b97631SPeter Brune       }
5569b97631SPeter Brune       if (anrm > 0.) {
5669b97631SPeter Brune         for (j = 0; j < ncols; j++) {
579371c9d4SSatish Balay           if (cols[j] >= ys && cols[j] < ye) { yarray[cols[j] - ys] += vals[j] * lambda * r / anrm; }
5869b97631SPeter Brune         }
5969b97631SPeter Brune       }
609566063dSJacob Faibussowitsch       PetscCall(MatRestoreRow(pc->pmat, i, &ncols, &cols, &vals));
6169b97631SPeter Brune     }
6269b97631SPeter Brune   }
639566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yarray));
649566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xarray));
653f93e5bdSPeter Brune   PetscFunctionReturn(0);
663f93e5bdSPeter Brune }
673f93e5bdSPeter Brune 
689371c9d4SSatish Balay PetscErrorCode PCSetFromOptions_Kaczmarz(PC pc, PetscOptionItems *PetscOptionsObject) {
693f93e5bdSPeter Brune   PC_Kaczmarz *jac = (PC_Kaczmarz *)pc->data;
703f93e5bdSPeter Brune 
713f93e5bdSPeter Brune   PetscFunctionBegin;
72d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "Kaczmarz options");
739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_kaczmarz_lambda", "relaxation factor (0 < lambda)", "", jac->lambda, &jac->lambda, NULL));
749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_kaczmarz_symmetric", "apply row projections symmetrically", "", jac->symmetric, &jac->symmetric, NULL));
75d0609cedSBarry Smith   PetscOptionsHeadEnd();
763f93e5bdSPeter Brune   PetscFunctionReturn(0);
773f93e5bdSPeter Brune }
783f93e5bdSPeter Brune 
799371c9d4SSatish Balay PetscErrorCode PCView_Kaczmarz(PC pc, PetscViewer viewer) {
803f93e5bdSPeter Brune   PC_Kaczmarz *jac = (PC_Kaczmarz *)pc->data;
813f93e5bdSPeter Brune   PetscBool    iascii;
823f93e5bdSPeter Brune 
833f93e5bdSPeter Brune   PetscFunctionBegin;
849566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
85*48a46eb9SPierre Jolivet   if (iascii) PetscCall(PetscViewerASCIIPrintf(viewer, "  lambda = %g\n", (double)jac->lambda));
863f93e5bdSPeter Brune   PetscFunctionReturn(0);
873f93e5bdSPeter Brune }
883f93e5bdSPeter Brune 
893f93e5bdSPeter Brune /*MC
903f93e5bdSPeter Brune      PCKaczmarz - Kaczmarz iteration
913f93e5bdSPeter Brune 
923f93e5bdSPeter Brune    Options Database Keys:
933f93e5bdSPeter Brune .  -pc_sor_lambda <1.0> - Sets damping parameter lambda
943f93e5bdSPeter Brune 
953f93e5bdSPeter Brune    Level: beginner
963f93e5bdSPeter Brune 
9795452b02SPatrick Sanan    Notes:
9895452b02SPatrick Sanan     In parallel this is block-Jacobi with Kaczmarz inner solve.
9969b97631SPeter Brune 
10069b97631SPeter Brune    References:
101606c0280SSatish Balay .  * - S. Kaczmarz, "Angenaherte Auflosing von Systemen Linearer Gleichungen",
10296a0c994SBarry Smith    Bull. Internat. Acad. Polon. Sci. C1. A, 1937.
1033f93e5bdSPeter Brune 
104db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`
1053f93e5bdSPeter Brune 
1063f93e5bdSPeter Brune M*/
1073f93e5bdSPeter Brune 
1089371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_Kaczmarz(PC pc) {
1093f93e5bdSPeter Brune   PC_Kaczmarz *jac;
1103f93e5bdSPeter Brune 
1113f93e5bdSPeter Brune   PetscFunctionBegin;
1129566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(pc, &jac));
1133f93e5bdSPeter Brune 
1143f93e5bdSPeter Brune   pc->ops->apply          = PCApply_Kaczmarz;
1153f93e5bdSPeter Brune   pc->ops->setfromoptions = PCSetFromOptions_Kaczmarz;
1160a545947SLisandro Dalcin   pc->ops->setup          = NULL;
1173f93e5bdSPeter Brune   pc->ops->view           = PCView_Kaczmarz;
1183f93e5bdSPeter Brune   pc->ops->destroy        = PCDestroy_Kaczmarz;
1193f93e5bdSPeter Brune   pc->data                = (void *)jac;
1203f93e5bdSPeter Brune   jac->lambda             = 1.0;
12169b97631SPeter Brune   jac->symmetric          = PETSC_FALSE;
1223f93e5bdSPeter Brune   PetscFunctionReturn(0);
1233f93e5bdSPeter Brune }
124