xref: /petsc/src/ksp/pc/impls/redundant/redundant.c (revision 753b7fb96d3b5d9fbe6e8fd943bba06cb168db41)
1dba47a55SKris Buschelman 
24b9ad928SBarry Smith /*
33f457be1SHong Zhang   This file defines a "solve the problem redundantly on each subgroup of processor" preconditioner.
44b9ad928SBarry Smith */
5af0996ceSBarry Smith #include <petsc/private/pcimpl.h>
6c6db04a5SJed Brown #include <petscksp.h>           /*I "petscksp.h" I*/
74b9ad928SBarry Smith 
84b9ad928SBarry Smith typedef struct {
93e065800SHong Zhang   KSP                ksp;
104b9ad928SBarry Smith   PC                 pc;                   /* actual preconditioner used on each processor */
11ce94432eSBarry Smith   Vec                xsub,ysub;            /* vectors of a subcommunicator to hold parallel vectors of PetscObjectComm((PetscObject)pc) */
123f457be1SHong Zhang   Vec                xdup,ydup;            /* parallel vector that congregates xsub or ysub facilitating vector scattering */
13b3804887SHong Zhang   Mat                pmats;                /* matrix and optional preconditioner matrix belong to a subcommunicator */
143f457be1SHong Zhang   VecScatter         scatterin,scatterout; /* scatter used to move all values to each processor group (subcommunicator) */
15ace3abfcSBarry Smith   PetscBool          useparallelmat;
16c540e29cSHong Zhang   PetscSubcomm       psubcomm;
171fbd8f88SHong Zhang   PetscInt           nsubcomm;             /* num of data structure PetscSubcomm */
18*753b7fb9SBarry Smith   PetscBool          shifttypeset;
19*753b7fb9SBarry Smith   MatFactorShiftType shifttype;
204b9ad928SBarry Smith } PC_Redundant;
214b9ad928SBarry Smith 
224b9ad928SBarry Smith #undef __FUNCT__
23*753b7fb9SBarry Smith #define __FUNCT__ "PCFactorSetShiftType_Redundant"
24*753b7fb9SBarry Smith PetscErrorCode  PCFactorSetShiftType_Redundant(PC pc,MatFactorShiftType shifttype)
25*753b7fb9SBarry Smith {
26*753b7fb9SBarry Smith   PC_Redundant   *red = (PC_Redundant*)pc->data;
27*753b7fb9SBarry Smith   PetscErrorCode ierr;
28*753b7fb9SBarry Smith 
29*753b7fb9SBarry Smith   PetscFunctionBegin;
30*753b7fb9SBarry Smith   if (red->ksp) {
31*753b7fb9SBarry Smith     PC pc;
32*753b7fb9SBarry Smith     ierr = KSPGetPC(red->ksp,&pc);CHKERRQ(ierr);
33*753b7fb9SBarry Smith     ierr = PCFactorSetShiftType(pc,shifttype);CHKERRQ(ierr);
34*753b7fb9SBarry Smith   } else {
35*753b7fb9SBarry Smith     red->shifttypeset = PETSC_TRUE;
36*753b7fb9SBarry Smith     red->shifttype    = shifttype;
37*753b7fb9SBarry Smith   }
38*753b7fb9SBarry Smith   PetscFunctionReturn(0);
39*753b7fb9SBarry Smith }
40*753b7fb9SBarry Smith 
41*753b7fb9SBarry Smith #undef __FUNCT__
424b9ad928SBarry Smith #define __FUNCT__ "PCView_Redundant"
436849ba73SBarry Smith static PetscErrorCode PCView_Redundant(PC pc,PetscViewer viewer)
444b9ad928SBarry Smith {
454b9ad928SBarry Smith   PC_Redundant   *red = (PC_Redundant*)pc->data;
46dfbe8321SBarry Smith   PetscErrorCode ierr;
47ace3abfcSBarry Smith   PetscBool      iascii,isstring;
4803ccd0b4SBarry Smith   PetscViewer    subviewer;
494b9ad928SBarry Smith 
504b9ad928SBarry Smith   PetscFunctionBegin;
51251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
52251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr);
5332077d6dSBarry Smith   if (iascii) {
5403ccd0b4SBarry Smith     if (!red->psubcomm) {
5503ccd0b4SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Redundant preconditioner: Not yet setup\n");CHKERRQ(ierr);
5603ccd0b4SBarry Smith     } else {
573e065800SHong Zhang       ierr = PetscViewerASCIIPrintf(viewer,"  Redundant preconditioner: First (color=0) of %D PCs follows\n",red->nsubcomm);CHKERRQ(ierr);
583f08860eSBarry Smith       ierr = PetscViewerGetSubViewer(viewer,((PetscObject)red->pc)->comm,&subviewer);CHKERRQ(ierr);
59f5dd71faSBarry Smith       if (!red->psubcomm->color) { /* only view first redundant pc */
601575c14dSBarry Smith         ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
613e065800SHong Zhang         ierr = KSPView(red->ksp,subviewer);CHKERRQ(ierr);
621575c14dSBarry Smith         ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
634b9ad928SBarry Smith       }
643f08860eSBarry Smith       ierr = PetscViewerRestoreSubViewer(viewer,((PetscObject)red->pc)->comm,&subviewer);CHKERRQ(ierr);
654b9ad928SBarry Smith     }
6603ccd0b4SBarry Smith   } else if (isstring) {
6703ccd0b4SBarry Smith     ierr = PetscViewerStringSPrintf(viewer," Redundant solver preconditioner");CHKERRQ(ierr);
684b9ad928SBarry Smith   }
694b9ad928SBarry Smith   PetscFunctionReturn(0);
704b9ad928SBarry Smith }
714b9ad928SBarry Smith 
724b9ad928SBarry Smith #undef __FUNCT__
734b9ad928SBarry Smith #define __FUNCT__ "PCSetUp_Redundant"
746849ba73SBarry Smith static PetscErrorCode PCSetUp_Redundant(PC pc)
754b9ad928SBarry Smith {
764b9ad928SBarry Smith   PC_Redundant   *red = (PC_Redundant*)pc->data;
77dfbe8321SBarry Smith   PetscErrorCode ierr;
781b81debcSHong Zhang   PetscInt       mstart,mend,mlocal,M;
7913f74950SBarry Smith   PetscMPIInt    size;
80ce94432eSBarry Smith   MPI_Comm       comm,subcomm;
81ddc54837SHong Zhang   Vec            x;
823f457be1SHong Zhang 
834b9ad928SBarry Smith   PetscFunctionBegin;
84ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
85ddc54837SHong Zhang 
86ddc54837SHong Zhang   /* if pmatrix set by user is sequential then we do not need to gather the parallel matrix */
87ddc54837SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
88ddc54837SHong Zhang   if (size == 1) red->useparallelmat = PETSC_FALSE;
891fbd8f88SHong Zhang 
904b9ad928SBarry Smith   if (!pc->setupcalled) {
911b81debcSHong Zhang     PetscInt mloc_sub;
9275024027SHong Zhang     if (!red->psubcomm) { /* create red->psubcomm, new ksp and pc over subcomm */
9375024027SHong Zhang       KSP ksp;
9475024027SHong Zhang       ierr = PCRedundantGetKSP(pc,&ksp);CHKERRQ(ierr);
951b81debcSHong Zhang     }
9675024027SHong Zhang     subcomm = PetscSubcommChild(red->psubcomm);
971fbd8f88SHong Zhang 
981b81debcSHong Zhang     if (red->useparallelmat) {
991b81debcSHong Zhang       /* grab the parallel matrix and put it into processors of a subcomminicator */
10053cd1579SHong Zhang       ierr = MatCreateRedundantMatrix(pc->pmat,red->psubcomm->n,subcomm,MAT_INITIAL_MATRIX,&red->pmats);CHKERRQ(ierr);
101b85f2e9bSHong Zhang 
102b85f2e9bSHong Zhang       ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
103b85f2e9bSHong Zhang       if (size > 1) {
104b85f2e9bSHong Zhang         PetscBool foundpack;
105b85f2e9bSHong Zhang         ierr = MatGetFactorAvailable(red->pmats,NULL,MAT_FACTOR_LU,&foundpack);CHKERRQ(ierr);
106b85f2e9bSHong Zhang         if (!foundpack) { /* reset default ksp and pc */
107b85f2e9bSHong Zhang           ierr = KSPSetType(red->ksp,KSPGMRES);CHKERRQ(ierr);
108b85f2e9bSHong Zhang           ierr = PCSetType(red->pc,PCBJACOBI);CHKERRQ(ierr);
109c1619fb6SBarry Smith         } else {
110c1619fb6SBarry Smith           ierr = PCFactorSetMatSolverPackage(red->pc,NULL);CHKERRQ(ierr);
111b85f2e9bSHong Zhang         }
112b85f2e9bSHong Zhang       }
113b85f2e9bSHong Zhang 
11423ee1639SBarry Smith       ierr = KSPSetOperators(red->ksp,red->pmats,red->pmats);CHKERRQ(ierr);
1154b9ad928SBarry Smith 
1161b81debcSHong Zhang       /* get working vectors xsub and ysub */
1172a7a6963SBarry Smith       ierr = MatCreateVecs(red->pmats,&red->xsub,&red->ysub);CHKERRQ(ierr);
1182fa5cd67SKarl Rupp 
1198b96b0d2SHong Zhang       /* create working vectors xdup and ydup.
1208b96b0d2SHong Zhang        xdup concatenates all xsub's contigously to form a mpi vector over dupcomm  (see PetscSubcommCreate_interlaced())
1218b96b0d2SHong Zhang        ydup concatenates all ysub and has empty local arrays because ysub's arrays will be place into it.
122ce94432eSBarry Smith        Note: we use communicator dupcomm, not PetscObjectComm((PetscObject)pc)! */
1231b81debcSHong Zhang       ierr = MatGetLocalSize(red->pmats,&mloc_sub,NULL);CHKERRQ(ierr);
12436be1a5eSBarry Smith       ierr = VecCreateMPI(PetscSubcommContiguousParent(red->psubcomm),mloc_sub,PETSC_DECIDE,&red->xdup);CHKERRQ(ierr);
12536be1a5eSBarry Smith       ierr = VecCreateMPIWithArray(PetscSubcommContiguousParent(red->psubcomm),1,mloc_sub,PETSC_DECIDE,NULL,&red->ydup);CHKERRQ(ierr);
1263f457be1SHong Zhang 
127f68be91cSHong Zhang       /* create vecscatters */
128f68be91cSHong Zhang       if (!red->scatterin) { /* efficiency of scatterin is independent from psubcomm_type! */
1293f457be1SHong Zhang         IS       is1,is2;
1303f457be1SHong Zhang         PetscInt *idx1,*idx2,i,j,k;
13145fc02eaSBarry Smith 
1322a7a6963SBarry Smith         ierr = MatCreateVecs(pc->pmat,&x,0);CHKERRQ(ierr);
1331b81debcSHong Zhang         ierr = VecGetSize(x,&M);CHKERRQ(ierr);
1341b81debcSHong Zhang         ierr = VecGetOwnershipRange(x,&mstart,&mend);CHKERRQ(ierr);
1351b81debcSHong Zhang         mlocal = mend - mstart;
136dcca6d9dSJed Brown         ierr = PetscMalloc2(red->psubcomm->n*mlocal,&idx1,red->psubcomm->n*mlocal,&idx2);CHKERRQ(ierr);
1373f457be1SHong Zhang         j    = 0;
1381fbd8f88SHong Zhang         for (k=0; k<red->psubcomm->n; k++) {
1393f457be1SHong Zhang           for (i=mstart; i<mend; i++) {
1403f457be1SHong Zhang             idx1[j]   = i;
141ddc54837SHong Zhang             idx2[j++] = i + M*k;
1423f457be1SHong Zhang           }
1433f457be1SHong Zhang         }
14470b3c8c7SBarry Smith         ierr = ISCreateGeneral(comm,red->psubcomm->n*mlocal,idx1,PETSC_COPY_VALUES,&is1);CHKERRQ(ierr);
14570b3c8c7SBarry Smith         ierr = ISCreateGeneral(comm,red->psubcomm->n*mlocal,idx2,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr);
146ddc54837SHong Zhang         ierr = VecScatterCreate(x,is1,red->xdup,is2,&red->scatterin);CHKERRQ(ierr);
147fcfd50ebSBarry Smith         ierr = ISDestroy(&is1);CHKERRQ(ierr);
148fcfd50ebSBarry Smith         ierr = ISDestroy(&is2);CHKERRQ(ierr);
1493f457be1SHong Zhang 
1506909748bSHong Zhang         /* Impl below is good for PETSC_SUBCOMM_INTERLACED (no inter-process communication) and PETSC_SUBCOMM_CONTIGUOUS (communication within subcomm) */
151ddc54837SHong Zhang         ierr = ISCreateStride(comm,mlocal,mstart+ red->psubcomm->color*M,1,&is1);CHKERRQ(ierr);
1523f457be1SHong Zhang         ierr = ISCreateStride(comm,mlocal,mstart,1,&is2);CHKERRQ(ierr);
153ddc54837SHong Zhang         ierr = VecScatterCreate(red->xdup,is1,x,is2,&red->scatterout);CHKERRQ(ierr);
154fcfd50ebSBarry Smith         ierr = ISDestroy(&is1);CHKERRQ(ierr);
155fcfd50ebSBarry Smith         ierr = ISDestroy(&is2);CHKERRQ(ierr);
1561d79065fSBarry Smith         ierr = PetscFree2(idx1,idx2);CHKERRQ(ierr);
157ddc54837SHong Zhang         ierr = VecDestroy(&x);CHKERRQ(ierr);
1581b81debcSHong Zhang       }
159ab661555SHong Zhang     } else { /* !red->useparallelmat */
16023ee1639SBarry Smith       ierr = KSPSetOperators(red->ksp,pc->mat,pc->pmat);CHKERRQ(ierr);
1611b81debcSHong Zhang     }
162ab661555SHong Zhang   } else { /* pc->setupcalled */
1634b9ad928SBarry Smith     if (red->useparallelmat) {
164ab661555SHong Zhang       MatReuse       reuse;
1651b81debcSHong Zhang       /* grab the parallel matrix and put it into processors of a subcomminicator */
1661b81debcSHong Zhang       /*--------------------------------------------------------------------------*/
167ab661555SHong Zhang       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
1684b9ad928SBarry Smith         /* destroy old matrices */
1696bf464f9SBarry Smith         ierr  = MatDestroy(&red->pmats);CHKERRQ(ierr);
170ab661555SHong Zhang         reuse = MAT_INITIAL_MATRIX;
1714b9ad928SBarry Smith       } else {
172ab661555SHong Zhang         reuse = MAT_REUSE_MATRIX;
173ab661555SHong Zhang       }
174306c2d5bSBarry Smith       ierr = MatCreateRedundantMatrix(pc->pmat,red->psubcomm->n,PetscSubcommChild(red->psubcomm),reuse,&red->pmats);CHKERRQ(ierr);
17523ee1639SBarry Smith       ierr = KSPSetOperators(red->ksp,red->pmats,red->pmats);CHKERRQ(ierr);
176ab661555SHong Zhang     } else { /* !red->useparallelmat */
17723ee1639SBarry Smith       ierr = KSPSetOperators(red->ksp,pc->mat,pc->pmat);CHKERRQ(ierr);
1784b9ad928SBarry Smith     }
179ab661555SHong Zhang   }
1801b81debcSHong Zhang 
1810c24e6a1SHong Zhang   if (pc->setfromoptionscalled) {
1823e065800SHong Zhang     ierr = KSPSetFromOptions(red->ksp);CHKERRQ(ierr);
1830c24e6a1SHong Zhang   }
1843e065800SHong Zhang   ierr = KSPSetUp(red->ksp);CHKERRQ(ierr);
1854b9ad928SBarry Smith   PetscFunctionReturn(0);
1864b9ad928SBarry Smith }
1874b9ad928SBarry Smith 
1884b9ad928SBarry Smith #undef __FUNCT__
1894b9ad928SBarry Smith #define __FUNCT__ "PCApply_Redundant"
1906849ba73SBarry Smith static PetscErrorCode PCApply_Redundant(PC pc,Vec x,Vec y)
1914b9ad928SBarry Smith {
1924b9ad928SBarry Smith   PC_Redundant   *red = (PC_Redundant*)pc->data;
193dfbe8321SBarry Smith   PetscErrorCode ierr;
1943f457be1SHong Zhang   PetscScalar    *array;
1954b9ad928SBarry Smith 
1964b9ad928SBarry Smith   PetscFunctionBegin;
197ddc54837SHong Zhang   if (!red->useparallelmat) {
198ddc54837SHong Zhang     ierr = KSPSolve(red->ksp,x,y);CHKERRQ(ierr);
199ddc54837SHong Zhang     PetscFunctionReturn(0);
200ddc54837SHong Zhang   }
201ddc54837SHong Zhang 
2023f457be1SHong Zhang   /* scatter x to xdup */
203ca9f406cSSatish Balay   ierr = VecScatterBegin(red->scatterin,x,red->xdup,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
204ca9f406cSSatish Balay   ierr = VecScatterEnd(red->scatterin,x,red->xdup,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2053f457be1SHong Zhang 
2063f457be1SHong Zhang   /* place xdup's local array into xsub */
2073f457be1SHong Zhang   ierr = VecGetArray(red->xdup,&array);CHKERRQ(ierr);
2083f457be1SHong Zhang   ierr = VecPlaceArray(red->xsub,(const PetscScalar*)array);CHKERRQ(ierr);
2094b9ad928SBarry Smith 
2104b9ad928SBarry Smith   /* apply preconditioner on each processor */
21183ab6a24SBarry Smith   ierr = KSPSolve(red->ksp,red->xsub,red->ysub);CHKERRQ(ierr);
2123f457be1SHong Zhang   ierr = VecResetArray(red->xsub);CHKERRQ(ierr);
2133f457be1SHong Zhang   ierr = VecRestoreArray(red->xdup,&array);CHKERRQ(ierr);
2144b9ad928SBarry Smith 
2153f457be1SHong Zhang   /* place ysub's local array into ydup */
2163f457be1SHong Zhang   ierr = VecGetArray(red->ysub,&array);CHKERRQ(ierr);
2173f457be1SHong Zhang   ierr = VecPlaceArray(red->ydup,(const PetscScalar*)array);CHKERRQ(ierr);
2183f457be1SHong Zhang 
2193f457be1SHong Zhang   /* scatter ydup to y */
220ca9f406cSSatish Balay   ierr = VecScatterBegin(red->scatterout,red->ydup,y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
221ca9f406cSSatish Balay   ierr = VecScatterEnd(red->scatterout,red->ydup,y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2223f457be1SHong Zhang   ierr = VecResetArray(red->ydup);CHKERRQ(ierr);
2233f457be1SHong Zhang   ierr = VecRestoreArray(red->ysub,&array);CHKERRQ(ierr);
2244b9ad928SBarry Smith   PetscFunctionReturn(0);
2254b9ad928SBarry Smith }
2264b9ad928SBarry Smith 
2274b9ad928SBarry Smith #undef __FUNCT__
228d88bfacbSStefano Zampini #define __FUNCT__ "PCApplyTranspose_Redundant"
229d88bfacbSStefano Zampini static PetscErrorCode PCApplyTranspose_Redundant(PC pc,Vec x,Vec y)
230d88bfacbSStefano Zampini {
231d88bfacbSStefano Zampini   PC_Redundant   *red = (PC_Redundant*)pc->data;
232d88bfacbSStefano Zampini   PetscErrorCode ierr;
233d88bfacbSStefano Zampini   PetscScalar    *array;
234d88bfacbSStefano Zampini 
235d88bfacbSStefano Zampini   PetscFunctionBegin;
236d88bfacbSStefano Zampini   if (!red->useparallelmat) {
237d88bfacbSStefano Zampini     ierr = KSPSolveTranspose(red->ksp,x,y);CHKERRQ(ierr);
238d88bfacbSStefano Zampini     PetscFunctionReturn(0);
239d88bfacbSStefano Zampini   }
240d88bfacbSStefano Zampini 
241d88bfacbSStefano Zampini   /* scatter x to xdup */
242d88bfacbSStefano Zampini   ierr = VecScatterBegin(red->scatterin,x,red->xdup,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
243d88bfacbSStefano Zampini   ierr = VecScatterEnd(red->scatterin,x,red->xdup,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
244d88bfacbSStefano Zampini 
245d88bfacbSStefano Zampini   /* place xdup's local array into xsub */
246d88bfacbSStefano Zampini   ierr = VecGetArray(red->xdup,&array);CHKERRQ(ierr);
247d88bfacbSStefano Zampini   ierr = VecPlaceArray(red->xsub,(const PetscScalar*)array);CHKERRQ(ierr);
248d88bfacbSStefano Zampini 
249d88bfacbSStefano Zampini   /* apply preconditioner on each processor */
250d88bfacbSStefano Zampini   ierr = KSPSolveTranspose(red->ksp,red->xsub,red->ysub);CHKERRQ(ierr);
251d88bfacbSStefano Zampini   ierr = VecResetArray(red->xsub);CHKERRQ(ierr);
252d88bfacbSStefano Zampini   ierr = VecRestoreArray(red->xdup,&array);CHKERRQ(ierr);
253d88bfacbSStefano Zampini 
254d88bfacbSStefano Zampini   /* place ysub's local array into ydup */
255d88bfacbSStefano Zampini   ierr = VecGetArray(red->ysub,&array);CHKERRQ(ierr);
256d88bfacbSStefano Zampini   ierr = VecPlaceArray(red->ydup,(const PetscScalar*)array);CHKERRQ(ierr);
257d88bfacbSStefano Zampini 
258d88bfacbSStefano Zampini   /* scatter ydup to y */
259d88bfacbSStefano Zampini   ierr = VecScatterBegin(red->scatterout,red->ydup,y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
260d88bfacbSStefano Zampini   ierr = VecScatterEnd(red->scatterout,red->ydup,y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
261d88bfacbSStefano Zampini   ierr = VecResetArray(red->ydup);CHKERRQ(ierr);
262d88bfacbSStefano Zampini   ierr = VecRestoreArray(red->ysub,&array);CHKERRQ(ierr);
263d88bfacbSStefano Zampini   PetscFunctionReturn(0);
264d88bfacbSStefano Zampini }
265d88bfacbSStefano Zampini 
266d88bfacbSStefano Zampini #undef __FUNCT__
2671ea5a559SBarry Smith #define __FUNCT__ "PCReset_Redundant"
2681ea5a559SBarry Smith static PetscErrorCode PCReset_Redundant(PC pc)
2694b9ad928SBarry Smith {
2704b9ad928SBarry Smith   PC_Redundant   *red = (PC_Redundant*)pc->data;
271dfbe8321SBarry Smith   PetscErrorCode ierr;
2724b9ad928SBarry Smith 
2734b9ad928SBarry Smith   PetscFunctionBegin;
2741b81debcSHong Zhang   if (red->useparallelmat) {
2756bf464f9SBarry Smith     ierr = VecScatterDestroy(&red->scatterin);CHKERRQ(ierr);
2766bf464f9SBarry Smith     ierr = VecScatterDestroy(&red->scatterout);CHKERRQ(ierr);
2776bf464f9SBarry Smith     ierr = VecDestroy(&red->ysub);CHKERRQ(ierr);
2786bf464f9SBarry Smith     ierr = VecDestroy(&red->xsub);CHKERRQ(ierr);
2796bf464f9SBarry Smith     ierr = VecDestroy(&red->xdup);CHKERRQ(ierr);
2806bf464f9SBarry Smith     ierr = VecDestroy(&red->ydup);CHKERRQ(ierr);
2811b81debcSHong Zhang   }
2826bf464f9SBarry Smith   ierr = MatDestroy(&red->pmats);CHKERRQ(ierr);
2831b81debcSHong Zhang   ierr = KSPReset(red->ksp);CHKERRQ(ierr);
2841ea5a559SBarry Smith   PetscFunctionReturn(0);
2851ea5a559SBarry Smith }
2861ea5a559SBarry Smith 
2871ea5a559SBarry Smith #undef __FUNCT__
2881ea5a559SBarry Smith #define __FUNCT__ "PCDestroy_Redundant"
2891ea5a559SBarry Smith static PetscErrorCode PCDestroy_Redundant(PC pc)
2901ea5a559SBarry Smith {
2911ea5a559SBarry Smith   PC_Redundant   *red = (PC_Redundant*)pc->data;
2921ea5a559SBarry Smith   PetscErrorCode ierr;
2931ea5a559SBarry Smith 
2941ea5a559SBarry Smith   PetscFunctionBegin;
2951ea5a559SBarry Smith   ierr = PCReset_Redundant(pc);CHKERRQ(ierr);
2966bf464f9SBarry Smith   ierr = KSPDestroy(&red->ksp);CHKERRQ(ierr);
2976bf464f9SBarry Smith   ierr = PetscSubcommDestroy(&red->psubcomm);CHKERRQ(ierr);
298c31cb41cSBarry Smith   ierr = PetscFree(pc->data);CHKERRQ(ierr);
2994b9ad928SBarry Smith   PetscFunctionReturn(0);
3004b9ad928SBarry Smith }
3014b9ad928SBarry Smith 
3024b9ad928SBarry Smith #undef __FUNCT__
3034b9ad928SBarry Smith #define __FUNCT__ "PCSetFromOptions_Redundant"
3044416b707SBarry Smith static PetscErrorCode PCSetFromOptions_Redundant(PetscOptionItems *PetscOptionsObject,PC pc)
3054b9ad928SBarry Smith {
306a98ce0f4SHong Zhang   PetscErrorCode ierr;
307a98ce0f4SHong Zhang   PC_Redundant   *red = (PC_Redundant*)pc->data;
308a98ce0f4SHong Zhang 
3094b9ad928SBarry Smith   PetscFunctionBegin;
310e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"Redundant options");CHKERRQ(ierr);
31109a6bc64SHong Zhang   ierr = PetscOptionsInt("-pc_redundant_number","Number of redundant pc","PCRedundantSetNumber",red->nsubcomm,&red->nsubcomm,0);CHKERRQ(ierr);
312a98ce0f4SHong Zhang   ierr = PetscOptionsTail();CHKERRQ(ierr);
3134b9ad928SBarry Smith   PetscFunctionReturn(0);
3144b9ad928SBarry Smith }
3154b9ad928SBarry Smith 
3164b9ad928SBarry Smith #undef __FUNCT__
31709a6bc64SHong Zhang #define __FUNCT__ "PCRedundantSetNumber_Redundant"
318f7a08781SBarry Smith static PetscErrorCode PCRedundantSetNumber_Redundant(PC pc,PetscInt nreds)
31909a6bc64SHong Zhang {
32009a6bc64SHong Zhang   PC_Redundant *red = (PC_Redundant*)pc->data;
32109a6bc64SHong Zhang 
32209a6bc64SHong Zhang   PetscFunctionBegin;
32309a6bc64SHong Zhang   red->nsubcomm = nreds;
32409a6bc64SHong Zhang   PetscFunctionReturn(0);
32509a6bc64SHong Zhang }
32609a6bc64SHong Zhang 
32709a6bc64SHong Zhang #undef __FUNCT__
32809a6bc64SHong Zhang #define __FUNCT__ "PCRedundantSetNumber"
32909a6bc64SHong Zhang /*@
33009a6bc64SHong Zhang    PCRedundantSetNumber - Sets the number of redundant preconditioner contexts.
33109a6bc64SHong Zhang 
3323f9fe445SBarry Smith    Logically Collective on PC
33309a6bc64SHong Zhang 
33409a6bc64SHong Zhang    Input Parameters:
33509a6bc64SHong Zhang +  pc - the preconditioner context
3369b21d695SBarry Smith -  nredundant - number of redundant preconditioner contexts; for example if you are using 64 MPI processes and
3379b21d695SBarry Smith                               use an nredundant of 4 there will be 4 parallel solves each on 16 = 64/4 processes.
33809a6bc64SHong Zhang 
33909a6bc64SHong Zhang    Level: advanced
34009a6bc64SHong Zhang 
34109a6bc64SHong Zhang .keywords: PC, redundant solve
34209a6bc64SHong Zhang @*/
3437087cfbeSBarry Smith PetscErrorCode PCRedundantSetNumber(PC pc,PetscInt nredundant)
34409a6bc64SHong Zhang {
3454ac538c5SBarry Smith   PetscErrorCode ierr;
34609a6bc64SHong Zhang 
34709a6bc64SHong Zhang   PetscFunctionBegin;
3480700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
349ce94432eSBarry Smith   if (nredundant <= 0) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG, "num of redundant pc %D must be positive",nredundant);
3504ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCRedundantSetNumber_C",(PC,PetscInt),(pc,nredundant));CHKERRQ(ierr);
35109a6bc64SHong Zhang   PetscFunctionReturn(0);
35209a6bc64SHong Zhang }
35309a6bc64SHong Zhang 
35409a6bc64SHong Zhang #undef __FUNCT__
3554b9ad928SBarry Smith #define __FUNCT__ "PCRedundantSetScatter_Redundant"
356f7a08781SBarry Smith static PetscErrorCode PCRedundantSetScatter_Redundant(PC pc,VecScatter in,VecScatter out)
3574b9ad928SBarry Smith {
3584b9ad928SBarry Smith   PC_Redundant   *red = (PC_Redundant*)pc->data;
359dfbe8321SBarry Smith   PetscErrorCode ierr;
3604b9ad928SBarry Smith 
3614b9ad928SBarry Smith   PetscFunctionBegin;
3624b9ad928SBarry Smith   ierr = PetscObjectReference((PetscObject)in);CHKERRQ(ierr);
3636bf464f9SBarry Smith   ierr = VecScatterDestroy(&red->scatterin);CHKERRQ(ierr);
3642fa5cd67SKarl Rupp 
365c3122656SLisandro Dalcin   red->scatterin  = in;
3662fa5cd67SKarl Rupp 
3674b9ad928SBarry Smith   ierr = PetscObjectReference((PetscObject)out);CHKERRQ(ierr);
3686bf464f9SBarry Smith   ierr = VecScatterDestroy(&red->scatterout);CHKERRQ(ierr);
369c3122656SLisandro Dalcin   red->scatterout = out;
3704b9ad928SBarry Smith   PetscFunctionReturn(0);
3714b9ad928SBarry Smith }
3724b9ad928SBarry Smith 
3734b9ad928SBarry Smith #undef __FUNCT__
3744b9ad928SBarry Smith #define __FUNCT__ "PCRedundantSetScatter"
3754b9ad928SBarry Smith /*@
3764b9ad928SBarry Smith    PCRedundantSetScatter - Sets the scatter used to copy values into the
3774b9ad928SBarry Smith      redundant local solve and the scatter to move them back into the global
3784b9ad928SBarry Smith      vector.
3794b9ad928SBarry Smith 
3803f9fe445SBarry Smith    Logically Collective on PC
3814b9ad928SBarry Smith 
3824b9ad928SBarry Smith    Input Parameters:
3834b9ad928SBarry Smith +  pc - the preconditioner context
3844b9ad928SBarry Smith .  in - the scatter to move the values in
3854b9ad928SBarry Smith -  out - the scatter to move them out
3864b9ad928SBarry Smith 
3874b9ad928SBarry Smith    Level: advanced
3884b9ad928SBarry Smith 
3894b9ad928SBarry Smith .keywords: PC, redundant solve
3904b9ad928SBarry Smith @*/
3917087cfbeSBarry Smith PetscErrorCode PCRedundantSetScatter(PC pc,VecScatter in,VecScatter out)
3924b9ad928SBarry Smith {
3934ac538c5SBarry Smith   PetscErrorCode ierr;
3944b9ad928SBarry Smith 
3954b9ad928SBarry Smith   PetscFunctionBegin;
3960700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
3970700a824SBarry Smith   PetscValidHeaderSpecific(in,VEC_SCATTER_CLASSID,2);
3980700a824SBarry Smith   PetscValidHeaderSpecific(out,VEC_SCATTER_CLASSID,3);
3994ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCRedundantSetScatter_C",(PC,VecScatter,VecScatter),(pc,in,out));CHKERRQ(ierr);
4004b9ad928SBarry Smith   PetscFunctionReturn(0);
4014b9ad928SBarry Smith }
4024b9ad928SBarry Smith 
4034b9ad928SBarry Smith #undef __FUNCT__
40483ab6a24SBarry Smith #define __FUNCT__ "PCRedundantGetKSP_Redundant"
405f7a08781SBarry Smith static PetscErrorCode PCRedundantGetKSP_Redundant(PC pc,KSP *innerksp)
4064b9ad928SBarry Smith {
4075f06b7aaSBarry Smith   PetscErrorCode ierr;
4084b9ad928SBarry Smith   PC_Redundant   *red = (PC_Redundant*)pc->data;
40975024027SHong Zhang   MPI_Comm       comm,subcomm;
41075024027SHong Zhang   const char     *prefix;
4114b9ad928SBarry Smith 
4124b9ad928SBarry Smith   PetscFunctionBegin;
41375024027SHong Zhang   if (!red->psubcomm) {
414e5acf8a4SHong Zhang     ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
415e5acf8a4SHong Zhang 
41675024027SHong Zhang     ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
41775024027SHong Zhang     ierr = PetscSubcommCreate(comm,&red->psubcomm);CHKERRQ(ierr);
41875024027SHong Zhang     ierr = PetscSubcommSetNumber(red->psubcomm,red->nsubcomm);CHKERRQ(ierr);
41975024027SHong Zhang     ierr = PetscSubcommSetType(red->psubcomm,PETSC_SUBCOMM_CONTIGUOUS);CHKERRQ(ierr);
420e5acf8a4SHong Zhang 
421e5acf8a4SHong Zhang     ierr = PetscSubcommSetOptionsPrefix(red->psubcomm,prefix);CHKERRQ(ierr);
422e5acf8a4SHong Zhang     ierr = PetscSubcommSetFromOptions(red->psubcomm);CHKERRQ(ierr);
42375024027SHong Zhang     ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(PetscSubcomm));CHKERRQ(ierr);
42475024027SHong Zhang 
42575024027SHong Zhang     /* create a new PC that processors in each subcomm have copy of */
42675024027SHong Zhang     subcomm = PetscSubcommChild(red->psubcomm);
42775024027SHong Zhang 
42875024027SHong Zhang     ierr = KSPCreate(subcomm,&red->ksp);CHKERRQ(ierr);
42975024027SHong Zhang     ierr = KSPSetErrorIfNotConverged(red->ksp,pc->erroriffailure);CHKERRQ(ierr);
43075024027SHong Zhang     ierr = PetscObjectIncrementTabLevel((PetscObject)red->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
43175024027SHong Zhang     ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)red->ksp);CHKERRQ(ierr);
43275024027SHong Zhang     ierr = KSPSetType(red->ksp,KSPPREONLY);CHKERRQ(ierr);
43375024027SHong Zhang     ierr = KSPGetPC(red->ksp,&red->pc);CHKERRQ(ierr);
43475024027SHong Zhang     ierr = PCSetType(red->pc,PCLU);CHKERRQ(ierr);
435*753b7fb9SBarry Smith     if (red->shifttypeset) {
436*753b7fb9SBarry Smith       ierr = PCFactorSetShiftType(red->pc,red->shifttype);CHKERRQ(ierr);
437*753b7fb9SBarry Smith       red->shifttypeset = PETSC_FALSE;
438*753b7fb9SBarry Smith     }
43975024027SHong Zhang     ierr = KSPSetOptionsPrefix(red->ksp,prefix);CHKERRQ(ierr);
44075024027SHong Zhang     ierr = KSPAppendOptionsPrefix(red->ksp,"redundant_");CHKERRQ(ierr);
44175024027SHong Zhang   }
44283ab6a24SBarry Smith   *innerksp = red->ksp;
4434b9ad928SBarry Smith   PetscFunctionReturn(0);
4444b9ad928SBarry Smith }
4454b9ad928SBarry Smith 
4464b9ad928SBarry Smith #undef __FUNCT__
44783ab6a24SBarry Smith #define __FUNCT__ "PCRedundantGetKSP"
4484b9ad928SBarry Smith /*@
44983ab6a24SBarry Smith    PCRedundantGetKSP - Gets the less parallel KSP created by the redundant PC.
4504b9ad928SBarry Smith 
4514b9ad928SBarry Smith    Not Collective
4524b9ad928SBarry Smith 
4534b9ad928SBarry Smith    Input Parameter:
4544b9ad928SBarry Smith .  pc - the preconditioner context
4554b9ad928SBarry Smith 
4564b9ad928SBarry Smith    Output Parameter:
45783ab6a24SBarry Smith .  innerksp - the KSP on the smaller set of processes
4584b9ad928SBarry Smith 
4594b9ad928SBarry Smith    Level: advanced
4604b9ad928SBarry Smith 
4614b9ad928SBarry Smith .keywords: PC, redundant solve
4624b9ad928SBarry Smith @*/
46383ab6a24SBarry Smith PetscErrorCode PCRedundantGetKSP(PC pc,KSP *innerksp)
4644b9ad928SBarry Smith {
4654ac538c5SBarry Smith   PetscErrorCode ierr;
4664b9ad928SBarry Smith 
4674b9ad928SBarry Smith   PetscFunctionBegin;
4680700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
46983ab6a24SBarry Smith   PetscValidPointer(innerksp,2);
470*753b7fb9SBarry Smith   ierr = PetscUseMethod(pc,"PCRedundantGetKSP_C",(PC,KSP*),(pc,innerksp));CHKERRQ(ierr);
4714b9ad928SBarry Smith   PetscFunctionReturn(0);
4724b9ad928SBarry Smith }
4734b9ad928SBarry Smith 
4744b9ad928SBarry Smith #undef __FUNCT__
4754b9ad928SBarry Smith #define __FUNCT__ "PCRedundantGetOperators_Redundant"
476f7a08781SBarry Smith static PetscErrorCode PCRedundantGetOperators_Redundant(PC pc,Mat *mat,Mat *pmat)
4774b9ad928SBarry Smith {
4784b9ad928SBarry Smith   PC_Redundant *red = (PC_Redundant*)pc->data;
4794b9ad928SBarry Smith 
4804b9ad928SBarry Smith   PetscFunctionBegin;
481b3804887SHong Zhang   if (mat)  *mat  = red->pmats;
482b3804887SHong Zhang   if (pmat) *pmat = red->pmats;
4834b9ad928SBarry Smith   PetscFunctionReturn(0);
4844b9ad928SBarry Smith }
4854b9ad928SBarry Smith 
4864b9ad928SBarry Smith #undef __FUNCT__
4874b9ad928SBarry Smith #define __FUNCT__ "PCRedundantGetOperators"
4884b9ad928SBarry Smith /*@
4894b9ad928SBarry Smith    PCRedundantGetOperators - gets the sequential matrix and preconditioner matrix
4904b9ad928SBarry Smith 
4914b9ad928SBarry Smith    Not Collective
4924b9ad928SBarry Smith 
4934b9ad928SBarry Smith    Input Parameter:
4944b9ad928SBarry Smith .  pc - the preconditioner context
4954b9ad928SBarry Smith 
4964b9ad928SBarry Smith    Output Parameters:
4974b9ad928SBarry Smith +  mat - the matrix
4984b9ad928SBarry Smith -  pmat - the (possibly different) preconditioner matrix
4994b9ad928SBarry Smith 
5004b9ad928SBarry Smith    Level: advanced
5014b9ad928SBarry Smith 
5024b9ad928SBarry Smith .keywords: PC, redundant solve
5034b9ad928SBarry Smith @*/
5047087cfbeSBarry Smith PetscErrorCode PCRedundantGetOperators(PC pc,Mat *mat,Mat *pmat)
5054b9ad928SBarry Smith {
5064ac538c5SBarry Smith   PetscErrorCode ierr;
5074b9ad928SBarry Smith 
5084b9ad928SBarry Smith   PetscFunctionBegin;
5090700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5104482741eSBarry Smith   if (mat)  PetscValidPointer(mat,2);
5114482741eSBarry Smith   if (pmat) PetscValidPointer(pmat,3);
5124ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCRedundantGetOperators_C",(PC,Mat*,Mat*),(pc,mat,pmat));CHKERRQ(ierr);
5134b9ad928SBarry Smith   PetscFunctionReturn(0);
5144b9ad928SBarry Smith }
5154b9ad928SBarry Smith 
5164b9ad928SBarry Smith /* -------------------------------------------------------------------------------------*/
51737a17b4dSBarry Smith /*MC
51883ab6a24SBarry Smith      PCREDUNDANT - Runs a KSP solver with preconditioner for the entire problem on subgroups of processors
51937a17b4dSBarry Smith 
52083ab6a24SBarry Smith      Options for the redundant preconditioners can be set with -redundant_pc_xxx for the redundant KSP with -redundant_ksp_xxx
52137a17b4dSBarry Smith 
52209391456SBarry Smith   Options Database:
5239b21d695SBarry Smith .  -pc_redundant_number <n> - number of redundant solves, for example if you are using 64 MPI processes and
5249b21d695SBarry Smith                               use an n of 4 there will be 4 parallel solves each on 16 = 64/4 processes.
52509391456SBarry Smith 
52637a17b4dSBarry Smith    Level: intermediate
52737a17b4dSBarry Smith 
52883ab6a24SBarry Smith    Notes: The default KSP is preonly and the default PC is LU.
52983ab6a24SBarry Smith 
530*753b7fb9SBarry Smith    PCFactorSetShiftType() applied to this PC will convey they shift type into the inner PC if it is factorization based.
531*753b7fb9SBarry Smith 
53283ab6a24SBarry Smith    Developer Notes: Note that PCSetInitialGuessNonzero()  is not used by this class but likely should be.
5339cfaa89bSBarry Smith 
53437a17b4dSBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PCRedundantSetScatter(),
53583ab6a24SBarry Smith            PCRedundantGetKSP(), PCRedundantGetOperators(), PCRedundantSetNumber()
53637a17b4dSBarry Smith M*/
53737a17b4dSBarry Smith 
5384b9ad928SBarry Smith #undef __FUNCT__
5394b9ad928SBarry Smith #define __FUNCT__ "PCCreate_Redundant"
5408cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_Redundant(PC pc)
5414b9ad928SBarry Smith {
542dfbe8321SBarry Smith   PetscErrorCode ierr;
5434b9ad928SBarry Smith   PC_Redundant   *red;
54469db28dcSHong Zhang   PetscMPIInt    size;
5453f457be1SHong Zhang 
5464b9ad928SBarry Smith   PetscFunctionBegin;
547b00a9115SJed Brown   ierr = PetscNewLog(pc,&red);CHKERRQ(ierr);
548ce94432eSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
5492fa5cd67SKarl Rupp 
55069db28dcSHong Zhang   red->nsubcomm       = size;
5514b9ad928SBarry Smith   red->useparallelmat = PETSC_TRUE;
5521fbd8f88SHong Zhang   pc->data            = (void*)red;
5534b9ad928SBarry Smith 
5544b9ad928SBarry Smith   pc->ops->apply          = PCApply_Redundant;
555d88bfacbSStefano Zampini   pc->ops->applytranspose = PCApplyTranspose_Redundant;
5564b9ad928SBarry Smith   pc->ops->setup          = PCSetUp_Redundant;
5574b9ad928SBarry Smith   pc->ops->destroy        = PCDestroy_Redundant;
5581ea5a559SBarry Smith   pc->ops->reset          = PCReset_Redundant;
5594b9ad928SBarry Smith   pc->ops->setfromoptions = PCSetFromOptions_Redundant;
5604b9ad928SBarry Smith   pc->ops->view           = PCView_Redundant;
5612fa5cd67SKarl Rupp 
562bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCRedundantSetScatter_C",PCRedundantSetScatter_Redundant);CHKERRQ(ierr);
563bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCRedundantSetNumber_C",PCRedundantSetNumber_Redundant);CHKERRQ(ierr);
564bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCRedundantGetKSP_C",PCRedundantGetKSP_Redundant);CHKERRQ(ierr);
565bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCRedundantGetOperators_C",PCRedundantGetOperators_Redundant);CHKERRQ(ierr);
566*753b7fb9SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetShiftType_C",PCFactorSetShiftType_Redundant);CHKERRQ(ierr);
5674b9ad928SBarry Smith   PetscFunctionReturn(0);
5684b9ad928SBarry Smith }
569b2573a8aSBarry Smith 
570